]> andersk Git - moira.git/blame - clients/moira/menu.c
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / clients / moira / menu.c
CommitLineData
07c56447 1/*
2aaf83c2 2 * Copyright 1987 by the Massachusetts Institute of Technology.
3 * For copying and distribution information, see the file
4 * "mit-copyright.h".
5 *
6 * $Source$
7 * $Author$
8 * $Header$
2aaf83c2 9 *
07c56447 10 * Generic menu system module.
11 *
12 * Basically, we define an enormous tree structure which represents the
13 * menu. Some extra pieces (ml_command, ma_doc) get thrown in so we can
14 * also use the structure for a command-based system.
15 *
16 * By making the menu descriptions so general, we can ease porting to just
17 * about anything.
18 */
19
2aaf83c2 20#ifndef lint
21static char rcsid_menu_c[] = "$Header$";
e9db439c 22
2aaf83c2 23#endif lint
24
babbc197 25#include <mit-copyright.h>
34f47457 26#include <sys/types.h>
07c56447 27#include <stdio.h>
cde7e985 28#include <string.h>
967b7c08 29#include <signal.h>
07c56447 30#include <curses.h>
6df34521 31#ifdef POSIX
cde7e985 32#include <unistd.h>
68ec9052 33#include <termios.h>
6df34521 34#endif /* POSIX */
2aaf83c2 35#include <ctype.h>
90e30045 36#ifndef sun
93b28238 37#include <varargs.h>
90e30045 38#endif
6298c97d 39#include <com_err.h>
cde7e985 40#include <moira.h>
07c56447 41#include "menu.h"
42
c13d1215 43#ifndef __STDC__
44#define const
45#endif
46
967b7c08 47#define MAX(A,B) ((A) > (B) ? (A) : (B))
48#define MIN(A,B) ((A) < (B) ? (A) : (B))
49#define CTL(ch) ((ch) & 037)
07c56447 50
51#define MIN_INPUT 2 /* Minimum number of lines for input window */
52
facd6784 53extern int interrupt; /* will be set if ^C is received */
859891c0 54extern FILE *fdopen();
593574d6 55#ifndef sgi
859891c0 56extern int getpid();
593574d6 57#endif
34f47457 58extern char *calloc();
859891c0 59extern char *whoami;
60
61FILE *log_file = (FILE *) NULL; /* file stream of log file */
e9db439c 62int more_flg = 1;
2aaf83c2 63
cde7e985 64#ifdef POSIX
65extern char *malloc();
66#endif
67
07c56447 68/* Structure for holding current displayed menu */
69struct menu_screen {
70 WINDOW *ms_screen; /* Window for this menu */
71 WINDOW *ms_title; /* Title subwindow */
72 WINDOW *ms_menu; /* Menu subwindow */
73 WINDOW *ms_input; /* Input subwindow */
74 int ms_input_y; /* Input subwindow reference coordinate */
e9db439c 75} *cur_ms;
07c56447 76
2aaf83c2 77#define NULLMS ((struct menu_screen *) 0)
78
79Menu *top_menu; /* Root for command search */
11317e48 80int parsed_argc; /* used by extern routines to get additional */
81char **parsed_argv; /* comand line input */
2aaf83c2 82
6298c97d 83/*
84 * Hook function to cause error messages to be printed through
22da5e41 85 * curses instead of around it. Takes at most 5 args to the
86 * printf string (crock...)
6298c97d 87 */
88
c13d1215 89void
22da5e41 90menu_com_err_hook(who, code, fmt, arg1, arg2, arg3, arg4, arg5)
c13d1215 91 const char *who;
92 long code;
93 const char *fmt;
22da5e41 94 caddr_t arg1, arg2, arg3, arg4, arg5;
6298c97d 95{
96 char buf[BUFSIZ], *cp;
97
6298c97d 98 (void) strcpy(buf, who);
99 for (cp = buf; *cp; cp++);
100 *cp++ = ':';
101 *cp++ = ' ';
102 if (code) {
103 (void) strcpy(cp, error_message(code));
104 while (*cp)
105 cp++;
106 }
22da5e41 107 sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5);
6298c97d 108 Put_message(buf);
109}
110
07c56447 111/*
112 * Start_menu takes a menu as an argument. It initializes curses u.s.w.,
113 * and a quit in any submenu should unwind back to here. (it might not,
114 * if user functions which run their own menus don't cooperate.)
115 * Start_menu should only be called once, at the start of the program.
116 */
117Start_menu(m)
e9db439c 118 Menu *m;
07c56447 119{
2aaf83c2 120 struct menu_screen *make_ms();
c13d1215 121#ifdef __STDC__
122 register void (*old_hook)(const char *, long, const char *, va_list) = set_com_err_hook(menu_com_err_hook);
123#else
124 register void (*old_hook)() = set_com_err_hook(menu_com_err_hook);
125#endif
6298c97d 126
24582af9 127 if (initscr() == (WINDOW *)ERR) {
07c56447 128 fputs("Can't initialize curses!\n", stderr);
2aaf83c2 129 Start_no_menu(m);
6298c97d 130 } else {
131 (void) raw(); /* We parse & print everything ourselves */
132 (void) noecho();
133 cur_ms = make_ms(0); /* So we always have some current */
73b2adba 134 /* menu_screen */
6298c97d 135 /* Run the menu */
136 (void) Do_menu(m, -1, (char **) NULL);
07c56447 137 }
6298c97d 138 (void) set_com_err_hook(old_hook);
967b7c08 139 Cleanup_menu();
140}
141
142Cleanup_menu()
143{
144 if (cur_ms) {
34f47457 145 (void) wclear(cur_ms->ms_screen);
146 (void) wrefresh(cur_ms->ms_screen);
967b7c08 147 }
07c56447 148 endwin();
149}
967b7c08 150
07c56447 151
2aaf83c2 152/* Like Start_menu, except it doesn't print menus and doesn't use curses */
153Start_no_menu(m)
e9db439c 154 Menu *m;
2aaf83c2 155{
156 cur_ms = NULLMS;
33a56ee9 157 COLS = 80;
74e7b641 158 /* Run the menu */
967b7c08 159 (void) Do_menu(m, -1, (char **) NULL);
2aaf83c2 160}
161
07c56447 162/*
163 * Create a new menu screen template with the specified menu length
164 * and return it.
165 */
e9db439c 166struct menu_screen *
167make_ms(length)
168 int length;
07c56447 169{
170 struct menu_screen *ms;
07c56447 171
e9db439c 172 if (MAX_TITLE + length + MIN_INPUT > LINES) {
07c56447 173 fputs("Menu too big!\n", stderr);
174 exit(2);
175 }
176
177 ms = (struct menu_screen *) malloc(sizeof(struct menu_screen));
178
179 ms->ms_screen = newwin(0, 0, 0, 0);
180 ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0);
181 ms->ms_menu = subwin(ms->ms_screen,
182 length, 0, MAX_TITLE, 0);
183 ms->ms_input = subwin(ms->ms_screen, 0, 0,
184 ms->ms_input_y = MAX_TITLE + length,
185 0);
186
187 scrollok(ms->ms_input, TRUE);
2aaf83c2 188 (void) wmove(ms->ms_input, 0, 0);
189 (void) wclear(ms->ms_screen);
07c56447 190
e9db439c 191 return (ms);
07c56447 192}
193
194/*
195 * This routine destroys a menu_screen.
196 */
197destroy_ms(ms)
e9db439c 198 struct menu_screen *ms;
07c56447 199{
200 delwin(ms->ms_title);
201 delwin(ms->ms_menu);
202 delwin(ms->ms_input);
203 delwin(ms->ms_screen);
e9db439c 204 free((char *) ms);
07c56447 205}
206
207/*
208 * This guy actually puts up the menu
967b7c08 209 * Note: if margc < 0, no 'r' option will be displayed (i.e., on the
210 * top level menu)
07c56447 211 */
e9db439c 212int
74e7b641 213Do_menu(m, margc, margv)
e9db439c 214 Menu *m;
74e7b641 215 int margc;
216 char *margv[];
07c56447 217{
c13d1215 218 struct menu_screen *my_ms = NULLMS, *old_cur_ms = NULLMS;
07c56447 219 char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */
2aaf83c2 220 char buf[MAX_ARGC * MAX_ARGLEN];
07c56447 221 char *argv[MAX_ARGC];
222 int line;
2aaf83c2 223 int i;
224 struct menu_line *command, *Find_command();
07c56447 225 int argc;
967b7c08 226 int quitflag, is_topmenu = (margc < 0);
859891c0 227 int toggle_logging();
967b7c08 228
07c56447 229 /* Entry function gets called with old menu_screen still current */
11317e48 230 if (m->m_entry != NULLFUNC) {
74e7b641 231 if (m->m_entry(m, margc, margv) == DM_QUIT)
232 return DM_NORMAL;
11317e48 233 if (parsed_argc > 0) {
234 margc = parsed_argc + 1;
235 margv = --parsed_argv;
b5b88538 236 } else {
237 margc--;
238 margv++;
11317e48 239 }
240 }
241
242 parsed_argc = 0;
07c56447 243
2aaf83c2 244 /* The following get run only in curses mode */
e9db439c 245 if (cur_ms != NULLMS) {
2aaf83c2 246 /* Get a menu_screen */
247 old_cur_ms = cur_ms;
859891c0 248 /* 2 is for the 2 obligatory lines; quit and toggle */
249 cur_ms = my_ms = make_ms(m->m_length + 2 + (is_topmenu ? 0 : 1));
07c56447 250
2aaf83c2 251 /* Now print the title and the menu */
e9db439c 252 (void) wclear(my_ms->ms_menu);
253 (void) wmove(my_ms->ms_title, 0, MAX(0, (COLS -
254 strlen(m->m_title)) >> 1));
2aaf83c2 255 (void) wstandout(my_ms->ms_title);
256 (void) waddstr(my_ms->ms_title, m->m_title);
257 (void) wstandend(my_ms->ms_title);
258
e9db439c 259 for (line = 0; line < m->m_length; line++) {
6298c97d 260 int len = strlen(m->m_lines[line].ml_command);
261 if (len > 12) len=12;
262
2aaf83c2 263 (void) wmove(my_ms->ms_menu, line, 0);
6298c97d 264
265 (void) wprintw(my_ms->ms_menu, "%2d. (%s)%*s %s.", line + 1,
e9db439c 266 m->m_lines[line].ml_command,
6298c97d 267 12-len, "",
e9db439c 268 m->m_lines[line].ml_doc);
2aaf83c2 269 }
270 (void) wmove(my_ms->ms_menu, line++, 0);
967b7c08 271 if (!is_topmenu) {
272 (void) waddstr(my_ms->ms_menu,
6298c97d 273 " r. (return) Return to previous menu.");
859891c0 274 (void) wmove(my_ms->ms_menu, line++, 0);
967b7c08 275 }
859891c0 276 (void) waddstr(my_ms->ms_menu,
277 " t. (toggle) Toggle logging on and off.");
278 (void) wmove(my_ms->ms_menu, line, 0);
6298c97d 279 (void) waddstr(my_ms->ms_menu, " q. (quit) Quit.");
33a56ee9 280 } else {
281 Put_message(m->m_title);
282 for (line = 0; line < m->m_length; line++) {
283 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
284 m->m_lines[line].ml_command,
285 12 - strlen(m->m_lines[line].ml_command), "",
286 m->m_lines[line].ml_doc);
287 Put_message(buf);
288 }
289 if (!is_topmenu)
290 Put_message(" r. (return) Return to previous menu.");
291 Put_message(" t. (toggle) Toggle logging on and off.");
292 Put_message(" q. (quit) Quit.");
293 Put_message(" ?. Print this information.");
07c56447 294 }
07c56447 295
e9db439c 296 for (;;) {
07c56447 297 /* This will be set by a return val from func or submenu */
298 quitflag = DM_NORMAL;
2aaf83c2 299 /* This is here because we may be coming from another menu */
e9db439c 300 if (cur_ms != NULL)
301 touchwin(my_ms->ms_screen);
11317e48 302 if (margc > 1) {
303 /* Initialize argv */
304 for (argc = 0; argc < MAX_ARGC; argc++)
305 argv[argc] = argvals[argc];
306 argc = margc - 1;
307 for (i = 1; i < margc; i++)
308 strcpy(argvals[i - 1], margv[i]);
309 margc = 0;
310 } else {
311 /* Get a command */
312 if (!Prompt_input("Command: ", buf, sizeof(buf))) {
313 if (cur_ms == NULLMS &&
314 feof(stdin))
315 sprintf(buf, "quit");
316 else
317 continue;
318 }
319 /* Parse it into the argument list */
320 /* If there's nothing there, try again */
321 /* Initialize argv */
322 for (argc = 0; argc < MAX_ARGC; argc++)
323 argv[argc] = argvals[argc];
324
325 if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
e85f474d 326 continue;
327 }
e9db439c 328 if ((line = atoi(argv[0])) > 0 && line <= m->m_length) {
329 command = &m->m_lines[line - 1];
330 }
967b7c08 331 else if ((!is_topmenu &&
859891c0 332 (!strcmp(argv[0], "r") || !strcmp(argv[0], "return")))
333 || !strcmp(argv[0], "q") || !strcmp(argv[0], "quit")) {
334
07c56447 335 /* here if it's either return or quit */
e9db439c 336 if (cur_ms != NULLMS) {
2aaf83c2 337 cur_ms = old_cur_ms;
338 destroy_ms(my_ms);
339 }
e9db439c 340 if (m->m_exit != NULLFUNC)
341 m->m_exit(m);
342 return (*argv[0] == 'r' ? DM_NORMAL : DM_QUIT);
e9db439c 343 }
33a56ee9 344 else if (argv[0][0] == '?') {
345 for (line = 0; line < m->m_length; line++) {
346 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
347 m->m_lines[line].ml_command,
348 12 - strlen(m->m_lines[line].ml_command), "",
349 m->m_lines[line].ml_doc);
350 Put_message(buf);
351 }
352 if (!is_topmenu)
353 Put_message(" r. (return) Return to previous menu.");
354 Put_message(" t. (toggle) Toggle logging on and off.");
355 Put_message(" q. (quit) Quit.");
356 continue;
357 }
859891c0 358 else if (!strcmp(argv[0], "t") || !strcmp(argv[0], "toggle")) {
359 toggle_logging(argc, argv);
360 continue;
361 }
362 /* finally, try to find it using Find_command */
73b2adba 363 else if ((command = Find_command(m, argvals[0])) ==
e9db439c 364 (struct menu_line *) 0) {
b5b88538 365 sprintf(buf, "Command not recognized: %s\n", argvals[0]);
366 Put_message(buf);
e9db439c 367 continue;
368 }
2aaf83c2 369 /* If we got to here, command is a valid menu_line */
370 /* Send the offical command name into the argv */
371 (void) strcpy(argvals[0], command->ml_command);
372 /* Show that we're working on it */
373 Put_message(command->ml_doc);
374 /* Print args that we've already got */
e9db439c 375 for (i = 1; i < argc; i++) {
376 if (command->ml_args[i].ma_prompt == NULL)
377 break;
2aaf83c2 378 (void) sprintf(buf, "%s%s", command->ml_args[i].ma_prompt,
379 argv[i]);
380 Put_message(buf);
381 }
382 /* Get remaining arguments, if any */
e9db439c 383 for (; argc < command->ml_argc; argc++) {
967b7c08 384 if (!Prompt_input(command->ml_args[argc].ma_prompt,
385 argvals[argc], sizeof(argvals[argc])))
386 goto punt_command;
2aaf83c2 387 }
11317e48 388 parsed_argc = argc - command->ml_argc;
389 parsed_argv = &(argv[command->ml_argc]);
e9db439c 390 if (command->ml_function != NULLFUNC) {
2aaf83c2 391 /* If it's got a function, call it */
392 quitflag = command->ml_function(argc, argv);
e9db439c 393 }
394 else if (command->ml_submenu != NULLMENU) {
2aaf83c2 395 /* Else see if it is a submenu */
74e7b641 396 quitflag = Do_menu(command->ml_submenu, argc, argv);
e9db439c 397 }
398 else {
2aaf83c2 399 /* If it's got neither, something is wrong */
400 Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
07c56447 401 }
e9db439c 402 if (quitflag == DM_QUIT) {
403 if (cur_ms != NULLMS) {
2aaf83c2 404 cur_ms = old_cur_ms;
405 destroy_ms(my_ms);
406 }
e9db439c 407 if (m->m_exit != NULLFUNC)
408 m->m_exit(m);
11317e48 409 parsed_argc = 0;
e9db439c 410 return (DM_QUIT);
07c56447 411 }
967b7c08 412 punt_command:
11317e48 413 parsed_argc = 0;
07c56447 414 }
415}
416
142e9b37 417refresh_screen()
418{
419 if (cur_ms != NULLMS) {
420 touchwin(cur_ms->ms_screen);
421 refresh_ms(cur_ms);
422 }
423}
424
425
07c56447 426/* Prompt the user for input in the input window of cur_ms */
967b7c08 427int Prompt_input(prompt, buf, buflen)
e9db439c 428 char *prompt;
429 char *buf;
430 int buflen;
07c56447 431{
432 int c;
433 char *p;
c13d1215 434 int y, x, oldx, oldy;
07c56447 435
e9db439c 436 if (cur_ms != NULLMS) {
437 more_flg = 1;
438 getyx(cur_ms->ms_input, y, x);
439 (void) wmove(cur_ms->ms_input, y, 0);
440
75cb4350 441 refresh_screen();
2aaf83c2 442 (void) waddstr(cur_ms->ms_input, prompt);
443 getyx(cur_ms->ms_input, y, x);
e9db439c 444
2aaf83c2 445 oldx = x;
c13d1215 446 oldy = y;
f659480d 447 p = buf;
448 while(1) {
2aaf83c2 449 (void) wmove(cur_ms->ms_input, y, x);
859891c0 450 (void) touchwin(cur_ms->ms_screen);
2aaf83c2 451 (void) wclrtoeol(cur_ms->ms_input);
75cb4350 452 (void) wrefresh(cur_ms->ms_input);
36606b78 453 c = getchar() & 0x7f;
2aaf83c2 454 switch (c) {
967b7c08 455 case CTL('C'):
0e8624c9 456 *p = '\0';
967b7c08 457 return 0;
458 case CTL('Z'):
34f47457 459 (void) kill(getpid(), SIGTSTP);
967b7c08 460 touchwin(curscr);
461 break;
462 case CTL('L'):
e9db439c 463 (void) wclear(cur_ms->ms_input);
464 (void) waddstr(cur_ms->ms_input, prompt);
b4e83c61 465 (void) touchwin(cur_ms->ms_input);
8fd71efe 466 (void) move(LINES - 1, 0);
b4e83c61 467 (void) wrefresh(curscr);
e9db439c 468 getyx(cur_ms->ms_input, y, x);
c13d1215 469 oldy = y;
470 oldx = x;
471 p = buf;
2aaf83c2 472 break;
6298c97d 473
e9db439c 474 case '\n':
475 case '\r':
f659480d 476 goto end_input;
6298c97d 477 /* these should be obtained by doing ioctl() on tty */
2aaf83c2 478 case '\b':
479 case '\177':
480 if (p > buf) {
481 p--;
482 x--;
c13d1215 483 if (x < 0) {
484 (void) wmove(cur_ms->ms_input, y, 0);
485 (void) wclrtoeol(cur_ms->ms_input);
486 y--;
487 x = cur_ms->ms_input->_maxx-1;
488 }
2aaf83c2 489 }
490 break;
967b7c08 491 case CTL('U'):
492 case CTL('G'):
493 case CTL('['):
2aaf83c2 494 x = oldx;
c13d1215 495 y = oldy;
e9db439c 496 p = buf;
2aaf83c2 497 break;
498 default:
9cbd2bba 499 /* (buflen - 1) leaves room for the \0 */
500 if (isprint(c) && (p - buf < buflen - 1)) {
967b7c08 501 (void) waddch(cur_ms->ms_input, c);
502 *p++ = c;
503 x++;
c13d1215 504 if (x >= cur_ms->ms_input->_maxx) {
505 x = 0;
506 y++;
507 }
967b7c08 508 } else
509 putchar(CTL('G'));
2aaf83c2 510 break;
07c56447 511 }
07c56447 512 }
f659480d 513 end_input:
514 (void) waddch(cur_ms->ms_input, '\n');
f659480d 515
516 (void) wclrtoeol(cur_ms->ms_input);
517 refresh_ms(cur_ms);
518 *p = '\0';
519 Start_paging();
6298c97d 520 goto gotit;
f659480d 521 } else {
2aaf83c2 522 printf("%s", prompt);
967b7c08 523 if (gets(buf) == NULL)
524 return 0;
facd6784 525 if (interrupt) {
526 interrupt = 0;
527 return 0;
528 }
2aaf83c2 529 Start_paging();
6298c97d 530 goto gotit;
07c56447 531 }
6298c97d 532gotit:
533 strcpy(buf, strtrim(buf));
534 return 1;
07c56447 535}
536
27de3061 537/* Prompt the user for input in the input window of cur_ms, but don't echo
538 and allow some control characters */
539int Password_input(prompt, buf, buflen)
540 char *prompt;
541 char *buf;
542 int buflen;
543{
544 int c;
545 char *p;
546 int y, x, oldx;
547
548 if (cur_ms != NULLMS) {
549 more_flg = 1;
550 getyx(cur_ms->ms_input, y, x);
551 (void) wmove(cur_ms->ms_input, y, 0);
552
553 touchwin(cur_ms->ms_screen);
554 refresh_ms(cur_ms);
555 (void) waddstr(cur_ms->ms_input, prompt);
556 getyx(cur_ms->ms_input, y, x);
557
558 oldx = x;
559 for (p = buf; p - buf < buflen;) {
560 (void) wmove(cur_ms->ms_input, y, x);
561 (void) wclrtoeol(cur_ms->ms_input);
562 refresh_ms(cur_ms);
36606b78 563 c = getchar() & 0x7f;
27de3061 564 switch (c) {
565 case CTL('C'):
566 return 0;
567 case CTL('Z'):
34f47457 568 (void) kill(getpid(), SIGTSTP);
27de3061 569 touchwin(curscr);
570 break;
571 case CTL('L'):
572 (void) wclear(cur_ms->ms_input);
573 (void) waddstr(cur_ms->ms_input, prompt);
76124208 574 refresh_ms(cur_ms);
8fd71efe 575 (void) move(LINES - 1, 0);
b4e83c61 576 (void) wrefresh(curscr);
27de3061 577 getyx(cur_ms->ms_input, y, x);
578 break;
579 case '\n':
580 case '\r':
581 (void) waddch(cur_ms->ms_input, '\n');
27de3061 582
583 (void) wclrtoeol(cur_ms->ms_input);
584 refresh_ms(cur_ms);
585 *p = '\0';
586 Start_paging();
587 return 1;
588 case '\b':
589 case '\177':
590 if (p > buf) {
591 p--;
592 x--;
593 }
594 break;
595 case CTL('U'):
596 x = oldx;
597 p = buf;
598 break;
599 default:
600 *p++ = c;
601 break;
602 }
603 }
604 }
605 else {
6df34521 606#ifdef POSIX
607 struct termios ttybuf, nttybuf;
98509c19 608#else
27de3061 609 struct sgttyb ttybuf, nttybuf;
6df34521 610#endif /* POSIX */
27de3061 611 printf("%s", prompt);
612 /* turn off echoing */
6df34521 613#ifdef POSIX
614 tcgetattr(0, &ttybuf);
98509c19 615 nttybuf = ttybuf;
616 nttybuf.c_lflag &= ~ECHO;
6df34521 617 tcsetattr(0, TCSANOW, &nttybuf);
98509c19 618 if (gets(buf) == NULL) {
6df34521 619 tcsetattr(0, TCSANOW, &ttybuf);
98509c19 620 putchar('\n');
621 return 0;
622 }
623 putchar('\n');
624 (void) ioctl(0, TCSETA, (char *)&ttybuf);
625#else
34f47457 626 (void) ioctl(0, TIOCGETP, (char *)&ttybuf);
27de3061 627 nttybuf = ttybuf;
628 nttybuf.sg_flags &= ~ECHO;
34f47457 629 (void)ioctl(0, TIOCSETP, (char *)&nttybuf);
27de3061 630 if (gets(buf) == NULL) {
34f47457 631 (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
27de3061 632 putchar('\n');
633 return 0;
634 }
635 putchar('\n');
34f47457 636 (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
6df34521 637#endif /* POSIX */
27de3061 638 Start_paging();
639 return 1;
640 }
34f47457 641 return 0;
27de3061 642}
643
2aaf83c2 644int lines_left;
645
646/* Start paging */
647/* This routine will cause the most recently put message to be the
648 one at the top of the screen when a ---More--- prompt is displayed */
649Start_paging()
650{
e9db439c 651 if (cur_ms != NULLMS) {
2aaf83c2 652 lines_left = LINES - cur_ms->ms_input_y - 1;
e9db439c 653 }
654 else {
2aaf83c2 655 lines_left = 23;
656 }
657}
658
659/* Turn off paging */
660Stop_paging()
661{
662 lines_left = -1;
663}
664
f659480d 665/* Print a message in the input window of cur_ms. */
07c56447 666Put_message(msg)
f659480d 667char *msg;
668{
669 char *copy, *line, *s;
670
34f47457 671 copy = (char *) malloc((u_int)COLS);
f659480d 672 s = line = msg;
859891c0 673 if (log_file) { /* if we're doing logging; we assume that the */
674 /* file has already been opened. */
675 (void) fprintf(log_file, "%s\n", msg);
676 fflush(log_file);
677 }
678
f659480d 679 while(*s++) {
680 if (s - line >= COLS-1) {
34f47457 681 (void) strncpy(copy, line, COLS-1);
f659480d 682 line += COLS-1;
683 } else if (*s == '\n') {
684 *s = '\0';
34f47457 685 (void) strcpy(copy, line);
f659480d 686 line = ++s;
687 } else
688 continue;
689 Put_line(copy);
690 }
691 Put_line(line);
692 free(copy);
693}
694
695/* Will be truncated to COLS characters. */
696Put_line(msg)
697char *msg;
07c56447 698{
e9db439c 699 int y, x, i;
700 char *msg1, chr;
701
702 if (!more_flg)
703 return;
2aaf83c2 704
e9db439c 705 if (lines_left >= 0) {
706 if (--lines_left == 0) {
2aaf83c2 707 /* Give the user a more prompt */
e9db439c 708 if (cur_ms != NULLMS) {
2aaf83c2 709 (void) wstandout(cur_ms->ms_input);
710 (void) wprintw(cur_ms->ms_input, "---More---");
711 (void) wstandend(cur_ms->ms_input);
712 refresh_ms(cur_ms);
36606b78 713 chr = getchar() & 0x7f;/* We do care what it is */
b5b88538 714 if (chr == 'q' || chr == 'Q' || chr == 3 /* ^C */) {
e9db439c 715 more_flg = 0;
716 return;
717 }
2aaf83c2 718 getyx(cur_ms->ms_input, y, x);
34f47457 719 /* x is a bitbucket; avoid lint problems */
720 x=x;
2aaf83c2 721 (void) wmove(cur_ms->ms_input, y, 0);
722 (void) wclrtoeol(cur_ms->ms_input);
e9db439c 723 }
724 else {
2aaf83c2 725 printf("---More (hit return)---");
d5d12a44 726 getchar();
2aaf83c2 727 }
728 Start_paging(); /* Reset lines_left */
729 }
730 }
e9db439c 731
732 if (cur_ms != NULLMS) {
34f47457 733 msg1 = (char *) calloc((u_int)COLS, 1);
f659480d 734 (void) strncpy(msg1, msg, COLS-1);
735 for (i = strlen(msg1); i < COLS - 1; i++)
e9db439c 736 msg1[i] = ' ';
737 (void) wprintw(cur_ms->ms_input, "%s\n", msg1);
e9db439c 738 }
739 else {
2aaf83c2 740 puts(msg);
741 }
07c56447 742}
743
744/* Refresh a menu_screen onto the real screen */
745refresh_ms(ms)
e9db439c 746 struct menu_screen *ms;
07c56447 747{
75cb4350 748 (void) wrefresh(ms->ms_title);
749 (void) wrefresh(ms->ms_menu);
750 (void) wrefresh(ms->ms_input);
2aaf83c2 751}
752
753/* Parse buf into a list of words, which will be placed in strings specified by
754 argv. Space for these strings must have already been allocated.
755 Only the first n characters of each word will be copied */
756Parse_words(buf, argv, n)
e9db439c 757 char *buf;
758 char *argv[];
2aaf83c2 759int n;
e9db439c 760
2aaf83c2 761{
762 char *start, *end; /* For sausage machine */
763 int argc;
764
765 start = buf;
e9db439c 766 for (argc = 0; argc < MAX_ARGC; argc++) {
767 while (isspace(*start))
768 start++; /* Kill whitespace */
769 if (*start == '\0')
770 break; /* Nothing left */
2aaf83c2 771 /* Now find the end of the word */
e9db439c 772 for (end = start; *end != '\0' && !isspace(*end); end++);
773 (void) strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */
774 argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */
2aaf83c2 775 start = end;
776 }
e9db439c 777 return (argc);
2aaf83c2 778}
779
780/* This is the internal form of Find_command, which recursively searches
781 for a menu_line with command command in the specified menu */
782/* It will search to a maximum depth of d */
e9db439c 783struct menu_line *
784find_command_from(c, m, d)
785 char *c;
786 struct menu *m;
787 int d;
2aaf83c2 788{
789 int line;
790 struct menu_line *maybe;
791
e9db439c 792 if (d < 0)
793 return ((struct menu_line *) 0); /* Too deep! */
794 for (line = 0; line < m->m_length; line++) {
795 if (!strcmp(c, m->m_lines[line].ml_command)) {
796 return (&m->m_lines[line]);
797 }
73b2adba 798 }
799 for (line = 0; line < m->m_length; line++) {
800 if (m->m_lines[line].ml_submenu != NULLMENU &&
801 (maybe = find_command_from(c, m->m_lines[line].ml_submenu, d - 1))
802 != (struct menu_line *) 0) {
e9db439c 803 return (maybe);
804 }
2aaf83c2 805 }
806 /* If we got to here, nothing works */
e9db439c 807 return ((struct menu_line *) 0);
07c56447 808}
2aaf83c2 809
810/* Find_command searches down the current menu tree */
811/* And returns a pointer to a menu_line with the specified command name */
812/* It returns (struct menu_line *) 0 if none is found */
e9db439c 813struct menu_line *
73b2adba 814Find_command(m, command)
815 Menu *m;
e9db439c 816 char *command;
2aaf83c2 817{
73b2adba 818 if (m == NULLMENU) {
e9db439c 819 return ((struct menu_line *) 0);
820 }
821 else {
73b2adba 822 return (find_command_from(command, m, MAX_MENU_DEPTH));
2aaf83c2 823 }
824}
22705d2b 825
859891c0 826/*ARGSUSED*/
827int
828toggle_logging(argc, argv)
829 int argc;
830 char *argv[];
831{
832 int pid;
833 char buf[BUFSIZ];
834
835 if (log_file == (FILE *) NULL) {
836 pid = getpid();
837 if (!whoami) {
859891c0 838 Put_message("I've lost my SENSE of DIRECTION! I have no IDEA who I AM!");
839 Put_message("My God... You've turned him into a DEMOCRAT!!");
840 Put_message(" -- Doonesbury");
841 Put_message("");
842 Put_message("translation: your log file can be found in \"/usr/tmp/a.out.pid\".");
843 whoami = "a.out";
844 (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
845 }
846 else
847 (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
848
849 /* open the file */
33a56ee9 850 log_file = fopen(buf,"a");
859891c0 851
852 if (log_file == (FILE *) NULL)
853 Put_message("Open of log file failed. Logging is not on.");
854 else
855 Put_message("Log file successfully opened.");
856 }
857 else { /* log_file is a valid pointer; turn off logging. */
858 (void) fflush(log_file);
859 (void) fclose(log_file);
860 log_file = (FILE *) NULL;
861 Put_message("Logging off.");
862 }
863 return(DM_NORMAL);
864}
This page took 0.285373 seconds and 5 git commands to generate.