home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / ytalk-3.0 / part01 / menu.c < prev    next >
C/C++ Source or Header  |  1993-08-20  |  19KB  |  900 lines

  1. /* menu.c */
  2.  
  3. /*               NOTICE
  4.  *
  5.  * Copyright (c) 1990,1992,1993 Britt Yenne.  All rights reserved.
  6.  * 
  7.  * This software is provided AS-IS.  The author gives no warranty,
  8.  * real or assumed, and takes no responsibility whatsoever for any 
  9.  * use or misuse of this software, or any damage created by its use
  10.  * or misuse.
  11.  * 
  12.  * This software may be freely copied and distributed provided that
  13.  * no part of this NOTICE is deleted or edited in any manner.
  14.  * 
  15.  */
  16.  
  17. /* Mail comments or questions to ytalk@austin.eds.com */
  18.  
  19. #include "header.h"
  20. #include <fcntl.h>
  21. #include "menu.h"
  22.  
  23. /* This particular file was written real early one night (morning?)
  24.  * while trying to stay awake long enough to do laundry.  I hereby take
  25.  * extra-special pains to absolve myself of any and all responsibility
  26.  * for this source.
  27.  */
  28.  
  29. static void main_menu_sel();
  30. menu_item *menu_ptr = NULL;        /* current menu in processing */
  31. static int menu_len;            /* number of items in current menu */
  32. static int menu_long;            /* longest item of current menu */
  33. static int menu_line;            /* current line number of menu */
  34. static int text_pos = -1;        /* text offset if non-negative */
  35. static int text_ypos = -1, text_xpos = -1; /* text coord if non-negative */
  36.  
  37. extern void raw_term();            /* our raw interface to the terminal */
  38.  
  39. /* some menus... */
  40.  
  41. static menu_item main_menu[] = {
  42.     { "Main Menu",        NULL,        ' ' },
  43.     { "",            NULL,        ' ' },
  44.     { "add a user",        main_menu_sel,    'a' },
  45.     { "delete a user",        main_menu_sel,    'd' },
  46.     { "options",        main_menu_sel,    'o' },
  47.     { "shell",            main_menu_sel,    's' },
  48.     { "user list",        main_menu_sel,    'u' },
  49.     { "output user to file",    main_menu_sel,    'w' },
  50.     { "quit",            main_menu_sel,    'q' },
  51.     { "",            NULL,        '\0'}    /* MUST BE LAST */
  52. };
  53.  
  54. #define MAXUMENU 52
  55. static menu_item user_menu[MAXUMENU];    /* this one changes each time */
  56. static menu_item option_menu[20];    /* options menu buffer */
  57. static menu_item yes_no_menu[1];    /* yes/no entry menu */
  58. static menu_item mesg_menu[1];        /* message menu */
  59.  
  60. static char text_str[MAXTEXT+1];    /* string entry buffer */
  61. static menu_item text_menu[2];        /* string entry menu */
  62. static char user_buf[MAXUMENU][80];    /* user list buffers */
  63.  
  64. /* major hack below... [maniacal laughter] */
  65.  
  66. static int got_error = 0;
  67. static char err_str[8][MAXERR];
  68. static menu_item error_menu[] = {
  69.     { "Ytalk Error",        NULL,        ' ' },
  70.     { "",            NULL,        ' ' },
  71.     { NULL,            show_error,    ' ' },
  72.     { NULL,            show_error,    ' ' },
  73.     { "",            NULL,        ' ' },
  74.     { NULL,            show_error,    ' ' },
  75.     { NULL,            show_error,    ' ' },
  76.     { "",            NULL,        ' ' },
  77.     { NULL,            show_error,    ' ' },
  78.     { NULL,            show_error,    ' ' },
  79.     { "",            NULL,        ' ' },
  80.     { NULL,            show_error,    ' ' },
  81.     { NULL,            show_error,    ' ' },
  82.     { "",            NULL,        '\0'}    /* MUST BE LAST */
  83. };
  84.  
  85. /* ---- local functions ---- */
  86.  
  87. static yuser *output_user = NULL;
  88.  
  89. static void
  90. do_output(filename)
  91.   char *filename;
  92. {
  93.     int fd;
  94.  
  95.     if(output_user == NULL)
  96.     return;
  97.     if((fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, 0600)) < 0)
  98.     {
  99.     show_error(filename);
  100.     return;
  101.     }
  102.     output_user->output_fd = fd;
  103.     spew_term(output_user, fd, output_user->rows, output_user->cols);
  104.     output_user = NULL;
  105. }
  106.  
  107. static void
  108. do_output_user(user)
  109.   yuser *user;
  110. {
  111.     /* if he has an open descriptor, close it */
  112.  
  113.     if(user->output_fd > 0)
  114.     {
  115.     close(user->output_fd);
  116.     user->output_fd = 0;
  117.     if(show_mesg("Output Terminated", NULL) >= 0)
  118.         update_menu();
  119.     return;
  120.     }
  121.  
  122.     /* else open one */
  123.  
  124.     output_user = user;
  125.     if(show_text("Output filename?", do_output) >= 0)
  126.     update_menu();
  127.     else
  128.     output_user = NULL;
  129. }
  130.  
  131. static void
  132. do_invite(name)
  133.   char *name;
  134. {
  135.     invite(name, 1);
  136. }
  137.  
  138. static void
  139. main_menu_sel(key)
  140.   ychar key;
  141. {
  142.     switch(key)
  143.     {
  144.     case 'a':    /* add a user */
  145.         if(show_text("Add Which User?", do_invite) >= 0)
  146.         update_menu();
  147.         break;
  148.     case 'd':    /* delete a user */
  149.         if(show_user_menu("Delete Which User?", free_user) >= 0)
  150.         update_menu();
  151.         break;
  152.     case 'o':    /* show options */
  153.         if(show_option_menu() >= 0)
  154.         update_menu();
  155.         break;
  156.     case 's':    /* invoke a shell */
  157.         kill_menu();
  158.         execute(NULL);
  159.         break;
  160.     case 'u':    /* show a user list */
  161.         if(show_user_list() >= 0)
  162.         update_menu();
  163.         break;
  164.     case 'w':    /* output user to file */
  165.         if(show_user_menu("Output Which User?", do_output_user) >= 0)
  166.         update_menu();
  167.         break;
  168.     case 'q':    /* quit */
  169.         bail(0);
  170.     }
  171. }
  172.  
  173. static void
  174. option_menu_sel(key)
  175.   ychar key;
  176. {
  177.     register yuser *u;
  178.     u_long old_flags;
  179.  
  180.     old_flags = def_flags;
  181.     switch(key)
  182.     {
  183.     case 's':    /* toggle scrolling */
  184.         def_flags ^= FL_SCROLL;
  185.         break;
  186.     case 'w':    /* toggle word wrap */
  187.         def_flags ^= FL_WRAP;
  188.         break;
  189.     case 'i':    /* toggle automatic imports */
  190.         def_flags ^= FL_IMPORT;
  191.         break;
  192.     case 'v':    /* toggle automatic invitations */
  193.         def_flags ^= FL_INVITE;
  194.         break;
  195.     case 'r':    /* toggle automatic re-rings */
  196.         def_flags ^= FL_RING;
  197.         break;
  198.     }
  199.  
  200.     if(old_flags != def_flags)
  201.     {
  202.     for(u = user_list; u != NULL; u = u->unext)
  203.         if(!(u->flags & FL_LOCKED))
  204.         u->flags = def_flags;
  205.     }
  206.  
  207.     if(show_option_menu() >= 0)
  208.     update_menu();
  209.     else
  210.     kill_menu();
  211. }
  212.  
  213. static void
  214. user_menu_sel(key)
  215.   ychar key;
  216. {
  217.     register int i;
  218.     register yuser *u;
  219.  
  220.     /* Remember... the user list could have changed between the time
  221.      * I created the user menu and the time I just now selected one
  222.      * of the users from it.
  223.      */
  224.     for(i = 0; i < menu_len; i++)
  225.     if(user_menu[i].key == key)
  226.     {
  227.         for(u = user_list; u; u = u->unext)
  228.         if(u->key == key
  229.         && strcmp(u->full_name, user_menu[i].item) == 0)
  230.         {
  231.             user_menu[0].func(u);
  232.             break;
  233.         }
  234.         break;
  235.     }
  236.     if(menu_ptr == user_menu)
  237.     kill_menu();
  238. }
  239.  
  240. #define MENU_EXTRA 7    /* number of extra characters per menu screen item */
  241.  
  242. static void
  243. generate_text_length()
  244. {
  245.     menu_long = me->t_cols - MENU_EXTRA - 2;
  246.     if(menu_long < 5 || menu_long > MAXTEXT)
  247.     menu_long = MAXTEXT;
  248. }
  249.  
  250. static void
  251. generate_yes_no_length()
  252. {
  253.     menu_long = strlen(yes_no_menu[0].item) - 2;
  254. }
  255.  
  256. static void
  257. pad_str(from, len, to)
  258.   char *from, *to;
  259.   int len;
  260. {
  261.     for(; len > 0 && *from; len--, from++)
  262.     *(to++) = *from;
  263.     for(; len > 0; len--)
  264.     *(to++) = ' ';
  265.     *to = '\0';
  266. }
  267.  
  268. /* ---- global functions ---- */
  269.  
  270. /* End any menu processing.
  271.  */
  272. void
  273. kill_menu()
  274. {
  275.     register int i;
  276.  
  277.     if(menu_ptr != NULL)
  278.     {
  279.     menu_ptr = NULL;
  280.     redraw_term(me, 0);
  281.     flush_term(me);
  282.     text_pos = -1;
  283.     text_ypos = -1;
  284.     text_xpos = -1;
  285.     }
  286.     if(got_error)
  287.     {
  288.     got_error = 0;
  289.     for(i = 0; error_menu[i].key != '\0'; i++)
  290.         if(error_menu[i].func != NULL)
  291.         error_menu[i].item = NULL;
  292.     }
  293. }
  294.  
  295. /* Update menu information.
  296.  */
  297. void
  298. update_menu()
  299. {
  300.     register ychar *c;
  301.     register char *d;
  302.     register int j, i, y, x;
  303.     static ychar *buf = NULL;
  304.     static int buflen = 0;
  305.  
  306.     if(menu_ptr == NULL)
  307.     return;
  308.     
  309.     /* process any input */
  310.  
  311.     if(io_len > 0)
  312.     {
  313.     ychar ic;
  314.  
  315.     if(menu_ptr == text_menu)
  316.     {
  317.         for(; io_len > 0; io_len--)
  318.         {
  319.         ic = *(io_ptr++);
  320.  
  321.         if(ic > ' ' && ic <= '~')
  322.         {
  323.             if(text_pos >= menu_long)
  324.             putc(7, stderr);
  325.             else
  326.             {
  327.             text_str[text_pos] = (char)ic;
  328.             if(text_ypos >= 0)
  329.                 raw_term(me, text_ypos, text_xpos + text_pos,
  330.                 text_str + text_pos, 1);
  331.             text_str[++text_pos] = '\0';
  332.             }
  333.         }
  334.         else if(ic == me->old_rub)
  335.         {
  336.             if(text_pos > 0)
  337.             {
  338.             text_str[--text_pos] = '\0';
  339.             if(text_ypos >= 0)
  340.                 raw_term(me, text_ypos, text_xpos + text_pos,
  341.                 " ", 1);
  342.             }
  343.         }
  344.         else if(ic == me->KILL || ic == me->WORD)
  345.         {
  346.             if(text_pos > 0)
  347.             {
  348.             text_str[0] = '\0';
  349.             text_pos = 0;
  350.             if(text_ypos > 0)
  351.                 raw_term(me, text_ypos, text_xpos,
  352.                 "     ", menu_long);
  353.             }
  354.         }
  355.         else if(ic == '\n' || ic == '\r')
  356.         {
  357.             if(text_pos > 0)
  358.             {
  359.             text_str[text_pos] = '\0';    /* just to be sure */
  360.             kill_menu();
  361.             text_menu[0].func(text_str);
  362.             }
  363.             else
  364.             kill_menu();
  365.             return;
  366.         }
  367.         else if(ic == 27 || ic == 4)
  368.         {
  369.             kill_menu();
  370.             return;
  371.         }
  372.         }
  373.         if(text_ypos >= 0)
  374.         {
  375.         raw_term(me, text_ypos, text_xpos + text_pos, NULL, 0);
  376.         flush_term(me);
  377.         return;
  378.         }
  379.     }
  380.     else if(menu_ptr == yes_no_menu)
  381.     {
  382.         /* don't handle yes/no input here */
  383.     }
  384.     else if(menu_ptr == mesg_menu)
  385.     {
  386.         ic = *(io_ptr++);
  387.         io_len--;
  388.         kill_menu();
  389.         if(mesg_menu[0].func)
  390.         mesg_menu[0].func(ic);
  391.         return;
  392.     }
  393.     else
  394.     {
  395.         ic = *(io_ptr++);
  396.         io_len--;
  397.         if(ic == ' ' || ic == '\n' || ic == '\r')
  398.         {
  399.         /* scroll the menu */
  400.  
  401.         menu_line += me->t_rows - 1;
  402.         if(menu_line >= menu_len)
  403.         {
  404.             kill_menu();
  405.             return;
  406.         }
  407.         i = menu_len - (me->t_rows - 1);    /* last full screen */
  408.         if(i < menu_line)
  409.             menu_line = i;
  410.         }
  411.         else if(ic > ' ' && ic <= '~')
  412.         {
  413.         for(i = 0; i < menu_len; i++)
  414.             if(menu_ptr[i].key == ic && menu_ptr[i].func != NULL)
  415.             {
  416.             menu_ptr[i].func(ic);
  417.             /*
  418.              * THE WHOLE WORLD COULD BE DIFFERENT NOW.
  419.              */
  420.             i = -1;
  421.             break;
  422.             }
  423.         if(i >= 0)
  424.             kill_menu();
  425.         return;
  426.         }
  427.         else
  428.         {
  429.         kill_menu();
  430.         return;
  431.         }
  432.     }
  433.     }
  434.  
  435.     /* Check the buffer.  Keep in mind that we could be here because
  436.      * the window size has changed.
  437.      */
  438.  
  439.     if(menu_ptr == text_menu)
  440.     {
  441.     generate_text_length();
  442.     text_ypos = -1;        /* assume it's not displayed */
  443.     text_xpos = -1;
  444.     }
  445.     else if(menu_ptr == yes_no_menu)
  446.     {
  447.     menu_len = 1;
  448.     menu_line = 0;
  449.     generate_yes_no_length();
  450.     }
  451.     if(menu_long > buflen)
  452.     {
  453.     buflen = menu_long + 64;
  454.     buf = (ychar *)realloc_mem(buf, buflen + MENU_EXTRA);
  455.     }
  456.  
  457.     /* get starting X and Y coord */
  458.  
  459.     x = center(me->t_cols, menu_long + MENU_EXTRA);
  460.     if(menu_line == 0)
  461.     {
  462.     if(menu_len + 2 <= me->t_rows)
  463.     {
  464.         y = center(me->t_rows, menu_len + 2);
  465.         raw_term(me, y++, x, "#####", menu_long + MENU_EXTRA);
  466.     }
  467.     else
  468.         y = 0;
  469.     }
  470.     else
  471.     y = 0;
  472.  
  473.     /* show as many menu lines as we can */
  474.  
  475.     for(i = menu_line; y+1 < me->t_rows && i < menu_len; i++, y++)
  476.     {
  477.     c = buf;
  478.     *(c++) = '#';
  479.     *(c++) = ' ';
  480.     if(menu_ptr[i].key == ' ')
  481.     {
  482.         j = 0;
  483.         if(menu_ptr == text_menu)
  484.         {
  485.         if(i > 0)
  486.         {
  487.             *(c++) = '>';
  488.             *(c++) = ' ';
  489.             j += 2;
  490.             text_ypos = y;
  491.             text_xpos = x + j + 2;
  492.         }
  493.         }
  494.         else if(menu_ptr != yes_no_menu)
  495.         {
  496.         int temp;
  497.         temp = center(menu_long + 3, strlen(menu_ptr[i].item));
  498.         for(; j < temp; j++)
  499.             *(c++) = ' ';
  500.         }
  501.         for(d = menu_ptr[i].item; *d; d++, j++)
  502.         *(c++) = (ychar)*d;
  503.         for(; j < menu_long + 3; j++)
  504.         *(c++) = ' ';
  505.     }
  506.     else
  507.     {
  508.         *(c++) = menu_ptr[i].key;
  509.         *(c++) = ':';
  510.         *(c++) = ' ';
  511.         for(d = menu_ptr[i].item, j = 0; *d; d++, j++)
  512.         *(c++) = (ychar)*d;
  513.         for(; j < menu_long; j++)
  514.         *(c++) = ' ';
  515.     }
  516.     *(c++) = ' ';
  517.     *(c++) = '#';
  518.     raw_term(me, y, x, buf, c - buf);
  519.     }
  520.     if(y < me->t_rows)
  521.     {
  522.     if(i < menu_len)
  523.     {
  524.         c = buf;
  525.         *(c++) = '#';
  526.         *(c++) = ' ';
  527.         *(c++) = ' ';
  528.         *(c++) = ' ';
  529.         *(c++) = ' ';
  530.         for(d = "(more)", j = 0; *d; d++, j++)
  531.         *(c++) = (ychar)*d;
  532.         for(; j < menu_long; j++)
  533.         *(c++) = ' ';
  534.         *(c++) = ' ';
  535.         *(c++) = '#';
  536.         raw_term(me, y, x, buf, c - buf);
  537.         raw_term(me, y, x + 12, NULL, 0);
  538.     }
  539.     else
  540.     {
  541.         raw_term(me, y, x, "#####", menu_long + MENU_EXTRA);
  542.         if(menu_ptr == text_menu)
  543.         raw_term(me, text_ypos, text_xpos + text_pos, NULL, 0);
  544.         else if(menu_ptr == yes_no_menu)
  545.         raw_term(me, y-1, x + menu_long + MENU_EXTRA - 2, NULL, 0);
  546.         else
  547.         raw_term(me, y, me->t_cols / 2, NULL, 0);
  548.     }
  549.     }
  550.     flush_term(me);
  551. }
  552.  
  553. /* Show a menu, overriding any existing menu.
  554.  */
  555. int
  556. show_menu(menu, len)
  557.   menu_item *menu;
  558.   int len;
  559. {
  560.     register int i, j;
  561.  
  562.     if(me->t_rows < 2)
  563.     {
  564.     show_error("show_menu: window too small");
  565.     return -1;
  566.     }
  567.  
  568.     /* scan the menu for problems */
  569.  
  570.     menu_long = 0;
  571.     for(i = 0; i < len; i++)
  572.     {
  573.     if((j = strlen(menu[i].item)) > menu_long)
  574.         menu_long = j;
  575.     if(menu[i].key < ' ' || menu[i].key >= '~')
  576.     {
  577.         show_error("show_menu: invalid key");
  578.         return -1;
  579.     }
  580.     }
  581.     if(menu_long <= 0)
  582.     {
  583.     show_error("show_menu: menu too small");
  584.     return -1;
  585.     }
  586.     if(menu_long < 10)
  587.     menu_long = 10;
  588.     
  589.     /* set up the menu for display */
  590.  
  591.     menu_ptr = menu;
  592.     menu_len = len;
  593.     menu_line = 0;
  594.     
  595.     return 0;
  596. }
  597.  
  598. /* Show a text entry menu, overriding any existing menu.
  599.  */
  600. int
  601. show_text(prompt, func)
  602.   char *prompt;
  603.   void (*func)();
  604. {
  605.     if(me->t_rows < 3)
  606.     {
  607.     show_error("show_text: window too small");
  608.     return -1;
  609.     }
  610.  
  611.     /* set up the menu for display */
  612.  
  613.     text_menu[0].item = prompt;
  614.     text_menu[0].func = func;
  615.     text_menu[0].key = ' ';
  616.  
  617.     text_str[0] = '\0';
  618.     text_menu[1].item = text_str;
  619.     text_menu[1].func = NULL;
  620.     text_menu[1].key = ' ';
  621.  
  622.     menu_ptr = text_menu;
  623.     menu_len = 2;
  624.     menu_line = 0;
  625.     text_ypos = -1;
  626.     text_xpos = -1;
  627.     text_pos = 0;
  628.     generate_text_length();
  629.     
  630.     return 0;
  631. }
  632.  
  633. /* Show a message in a menu.
  634.  */
  635. int
  636. show_mesg(mesg, func)
  637.   char *mesg;
  638.   void (*func)();
  639. {
  640.     /* set up the menu for display */
  641.  
  642.     mesg_menu[0].item = mesg;
  643.     mesg_menu[0].func = func;
  644.     mesg_menu[0].key = ' ';
  645.  
  646.     return show_menu(mesg_menu, 1);
  647. }
  648.  
  649. int
  650. show_main_menu()
  651. {
  652.     static int main_items = 0;
  653.  
  654.     if(main_items == 0)
  655.     {
  656.     while(main_menu[main_items].key != '\0')
  657.         main_items++;
  658.     }
  659.     return show_menu(main_menu, main_items);
  660. }
  661.  
  662. int
  663. show_option_menu()
  664. {
  665.     register int i = 0;
  666.  
  667.     option_menu[i].item = "Options Menu";
  668.     option_menu[i].func = NULL;
  669.     option_menu[i].key = ' ';
  670.     i++;
  671.  
  672.     option_menu[i].item = "";
  673.     option_menu[i].func = NULL;
  674.     option_menu[i].key = ' ';
  675.     i++;
  676.  
  677.     if(def_flags & FL_SCROLL)
  678.     option_menu[i].item = "turn scrolling off";
  679.     else
  680.     option_menu[i].item = "turn scrolling on";
  681.     option_menu[i].func = option_menu_sel;
  682.     option_menu[i].key = 's';
  683.     i++;
  684.  
  685.     if(def_flags & FL_WRAP)
  686.     option_menu[i].item = "turn word-wrap off";
  687.     else
  688.     option_menu[i].item = "turn word-wrap on";
  689.     option_menu[i].func = option_menu_sel;
  690.     option_menu[i].key = 'w';
  691.     i++;
  692.  
  693.     if(def_flags & FL_IMPORT)
  694.     option_menu[i].item = "turn auto-import off";
  695.     else
  696.     option_menu[i].item = "turn auto-import on";
  697.     option_menu[i].func = option_menu_sel;
  698.     option_menu[i].key = 'i';
  699.     i++;
  700.  
  701.     if(def_flags & FL_INVITE)
  702.     option_menu[i].item = "turn auto-invite off";
  703.     else
  704.     option_menu[i].item = "turn auto-invite on";
  705.     option_menu[i].func = option_menu_sel;
  706.     option_menu[i].key = 'v';
  707.     i++;
  708.  
  709.     if(def_flags & FL_RING)
  710.     option_menu[i].item = "turn auto-rering off";
  711.     else
  712.     option_menu[i].item = "turn auto-rering on";
  713.     option_menu[i].func = option_menu_sel;
  714.     option_menu[i].key = 'r';
  715.     i++;
  716.  
  717.     return show_menu(option_menu, i);
  718. }
  719.  
  720. int
  721. show_user_menu(title, func)
  722.   char *title;
  723.   void (*func)();
  724. {
  725.     register int i;
  726.     register yuser *u;
  727.  
  728.     user_menu[0].item = title;
  729.     user_menu[0].func = func;
  730.     user_menu[0].key = ' ';
  731.  
  732.     user_menu[1].item = "";
  733.     user_menu[1].func = NULL;
  734.     user_menu[1].key = ' ';
  735.  
  736.     for(i = 2, u = user_list; u != NULL && i < MAXUMENU; u = u->unext)
  737.     if(u != me)
  738.     {
  739.         if(u->key != '\0')
  740.         {
  741.         strcpy(user_buf[i], u->full_name);
  742.         user_menu[i].item = user_buf[i];
  743.         user_menu[i].func = user_menu_sel;
  744.         user_menu[i].key = u->key;
  745.         i++;
  746.         }
  747.     }
  748.     
  749.     if(i > 2)
  750.     return show_menu(user_menu, i);
  751.     kill_menu();
  752.     return -1;
  753. }
  754.  
  755. int
  756. show_user_list()
  757. {
  758.     register int i;
  759.     register yuser *u;
  760.     static char name_buf[25], stat_buf[25];
  761.  
  762.     i = 0;
  763.  
  764.     user_menu[i].item = "User List";
  765.     user_menu[i].func = NULL;
  766.     user_menu[i].key = ' ';
  767.     i++;
  768.  
  769.     user_menu[i].item = "Name            Winsize [My_Size] Software       ";
  770.     user_menu[i].func = NULL;
  771.     user_menu[i].key = ' ';
  772.     i++;
  773.  
  774.     user_menu[i].item = "";
  775.     user_menu[i].func = NULL;
  776.     user_menu[i].key = ' ';
  777.     i++;
  778.  
  779.     for(u = connect_list; u && i < MAXUMENU; u = u->next)
  780.     if(u != me)
  781.     {
  782.         if(u->remote.vmajor > 2)
  783.         sprintf(stat_buf, "YTalk V%d.%d",
  784.             u->remote.vmajor, u->remote.vminor);
  785.         else if(u->remote.vmajor == 2)
  786.         sprintf(stat_buf, "YTalk V2.?");
  787.         else
  788.         sprintf(stat_buf, "UNIX Talk");
  789.         pad_str(u->full_name, 15, name_buf);
  790.         pad_str(stat_buf, 15, stat_buf);
  791.         sprintf(user_buf[i], "%s %3.3dx%3.3d [%3.3dx%3.3d] %s",
  792.         name_buf,
  793.         u->remote.cols, u->remote.rows,
  794.         u->remote.my_cols, u->remote.my_rows,
  795.         stat_buf);
  796.  
  797.         user_menu[i].item = user_buf[i];
  798.         user_menu[i].func = NULL;
  799.         user_menu[i].key = ' ';
  800.         i++;
  801.     }
  802.  
  803.     for(u = wait_list; u && i < MAXUMENU; u = u->next)
  804.     {
  805.     pad_str(u->full_name, 15, name_buf);
  806.     pad_str("<unconnected>", 15, stat_buf);
  807.     sprintf(user_buf[i], "%s                   %s",
  808.         name_buf,
  809.         stat_buf);
  810.  
  811.     user_menu[i].item = user_buf[i];
  812.     user_menu[i].func = NULL;
  813.     user_menu[i].key = ' ';
  814.     i++;
  815.     }
  816.     
  817.     return show_menu(user_menu, i);
  818. }
  819.  
  820. int
  821. show_error_menu(str1, str2)
  822.   char *str1, *str2;
  823. {
  824.     register int i;
  825.  
  826.     for(i = 0; error_menu[i].key != '\0'; i++)
  827.     if(error_menu[i].item == NULL)
  828.     {
  829.         strncpy(err_str[got_error], str1, MAXERR);
  830.         err_str[got_error][MAXERR-1] = '\0';
  831.         error_menu[i++].item = err_str[got_error++];
  832.  
  833.         strncpy(err_str[got_error], str2, MAXERR);
  834.         err_str[got_error][MAXERR-1] = '\0';
  835.         error_menu[i++].item = err_str[got_error++];
  836.  
  837.         return show_menu(error_menu, i);
  838.     }
  839.     return 0;
  840. }
  841.  
  842. /* Prompt user for yes/no response.  Return the response.  It is
  843.  * necessary for this function to hang until an answer is received.
  844.  */
  845. int
  846. yes_no(prompt)
  847.   char *prompt;
  848. {
  849.     int out = 0;
  850.  
  851.     yes_no_menu[0].func = NULL;
  852.     yes_no_menu[0].key = ' ';
  853.  
  854.     /* show the menu and call input_loop() */
  855.  
  856.     do {
  857.     yes_no_menu[0].item = prompt;
  858.     menu_ptr = yes_no_menu;
  859.     update_menu();
  860.     input_loop();
  861.     if(menu_ptr != yes_no_menu || yes_no_menu[0].item != prompt)
  862.     {
  863.         /* somebody pre-empted us */
  864.         kill_menu();
  865.         io_len = 0;
  866.     }
  867.     for(; io_len > 0; io_len--, io_ptr++)
  868.     {
  869.         if(*io_ptr == 'y' || *io_ptr == 'Y')
  870.         {
  871.         out = 'y';
  872.         break;
  873.         }
  874.         if(*io_ptr == 'n' || *io_ptr == 'N' || *io_ptr == 27)
  875.         {
  876.         out = 'n';
  877.         break;
  878.         }
  879.     }
  880.     } while(out == 0);
  881.  
  882.     kill_menu();
  883.     io_len = 0;
  884.     return out;
  885. }
  886.  
  887. void
  888. update_user_menu()
  889. {
  890.     if(menu_ptr == user_menu)
  891.     {
  892.     redraw_term(me, 0);
  893.     if(user_menu[0].func)    /* it's a user menu */
  894.         (void)show_user_menu(user_menu[0].item, user_menu[0].func);
  895.     else    /* it's a user status list */
  896.         (void)show_user_list();
  897.     update_menu();
  898.     }
  899. }
  900.