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