home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / mush5.7 / part05 / select.c < prev   
Encoding:
C/C++ Source or Header  |  1987-09-17  |  12.8 KB  |  421 lines

  1. /* select.c    (c) copyright 1986 (Dan Heller) */
  2.  
  3. /* 
  4.  * Routine which handle io (selection on file descriptors) between user and
  5.  * the various windows.
  6.  *
  7.  * In toolmode, the user types characters and each character is interpreted
  8.  * here and, if applicable, is sent to rite.c where it is appended to a 
  9.  * string similar to a tty driver and fgets. When the user types a '\n' the
  10.  * rite() routine returns the string and we call add_to_letter to append the
  11.  * string to the letter.  Signals are caught here as well.  that is the signal
  12.  * characters setup by the user are checked and if one matches, call the signal
  13.  * handling routine as if there were a real signal.
  14.  *
  15.  * Mouse handling is done here. See code for more detail.
  16.  */
  17. #include "mush.h"
  18. #define swap(a,b)         (a ^= b ^= a)   /* swap values of a pair of ints */
  19.  
  20. #define READ_MSG    (char *)'r'
  21. #define DEL_MSG        (char *)'d'
  22. #define UNDEL_MSG    (char *)'u'
  23. #define REPL_MSG    (char *)'R'
  24. #define SAVE_MSG    (char *)'s'
  25. #define PRNT_MSG    (char *)'p'
  26. #define PRE_MSG        (char *)'P'
  27. #define E_EDIT         (char *)'e'
  28. #define E_VIEW         (char *)'v'
  29. #define E_INCLUDE      (char *)'i'
  30. #define E_SEND        (char *)'S'
  31. #define E_ABORT       (char *)'a'
  32. #define MENU_HELP    (char *)'h'
  33. #define O_SAVE        (char *)'s'
  34. #define O_QUIT        (char *)'q'
  35. #define O_RSTR        (char *)'r'
  36.  
  37. #define N_MENU_ITEMS    8
  38. #define E_MENU_ITEMS    6
  39.  
  40. msg_io(gfxsw, ibits, obits, ebits, timer)
  41. register struct gfxsubwindow *gfxsw;
  42. register int *ibits,*obits,*ebits;
  43. struct timeval **timer;
  44. {
  45.     register char    *p;
  46.     struct inputevent     event;
  47.     static char     lastchar;
  48.     static int         line, count;
  49.  
  50.     if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  51.     *ibits = *obits = *ebits = 0;
  52.     return;
  53.     }
  54.     if (input_readevent(msg_sw->ts_windowfd, &event) == -1) {
  55.     error("input event");
  56.     return;
  57.     }
  58.     /*
  59.     if (ID == LOC_WINENTER) {
  60.     int x;
  61.     struct inputmask im;
  62.     win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  63.     win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  64.     }
  65.     */
  66.     if (ID >= KEY_LEFTFIRST)
  67.     if (ison(glob_flags, IS_GETTING))
  68.         print("Finish editing letter first");
  69.     else
  70.         (void) func_key(ID);
  71.     else if (isascii(ID) && (msg_pix || ison(glob_flags, IS_GETTING) ||
  72.     getting_opts)) {
  73.     if (getting_opts) {
  74.         /*
  75.          * txt.x <= 5 indicates not to accept typed input for options
  76.          * and function key setting.
  77.          */
  78.         if (txt.x > 5) {
  79.         /* ^C, ^\ or ^U kills line */
  80.         pw_char(msg_win, txt.x,txt.y, PIX_OR, fonts[curfont], '_');
  81.         if (ID == tchars.t_intrc || ID == tchars.t_quitc ||
  82.                         ID == _tty.sg_kill) {
  83.             rite(_tty.sg_kill), txt.x = 5;
  84.             if (getting_opts == 1)
  85.             option_line(line), display_opts(0);
  86.             else
  87.             set_key(0, 0, 0);
  88.         } else if (p = rite((char)ID)) {
  89.             /* if no string entered, preserve old value */
  90.             if (*p && getting_opts == 1)
  91.             add_opt(p, line);
  92.             if (getting_opts == 2)
  93.             set_key(p, 0,0);
  94.         } else
  95.             pw_char(msg_win, txt.x, txt.y, PIX_OR, fonts[curfont], '_');
  96.         }
  97.     }
  98.     /*
  99.      * This section MUST BE BEFORE the following "is_getting" section.
  100.      * If user displays a message while editing a letter, he must hit 'q'
  101.      * to return to edit mode.  He may not edit a new letter while one is
  102.      * already being edited.
  103.      */
  104.     else if (msg_pix)
  105.         if (isdigit(ID)) {
  106.         if (!isdigit(lastchar))
  107.             count = 0;
  108.         count = count * 10 + ID - '0';
  109.         } else {
  110.         /* scroll <count> lines */
  111.         if (!count || count > msg_pix->pr_size.y / l_height(curfont))
  112.             count = 1;
  113.         if (ID == 'k' || ID == 'K' || ID == '-')
  114.             scroll_win(-count);
  115.         else if (ID == '\n' || ID == '\r' || ID == 'j')
  116.             scroll_win(count);
  117.         else if (ID == ' ')
  118.             scroll_win(crt);
  119.         else if ((ID == 'q' || ID == 'Q') &&
  120.             ison(glob_flags, IS_GETTING)) {
  121.             pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
  122.             win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  123.             txt.x = 5, txt.y = msg_rect.r_height - l_height(curfont);
  124.             wprint("\n(continue editing letter)\n");
  125.             clr_bot_line();
  126.             pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_');
  127.         }
  128.         }
  129.     /*
  130.      * If msg_pix is NULL, then we are not reading a message. If we are
  131.      * editing a letter, then enter the keys typed.  If we are doing
  132.      * nothing, ignore this input.
  133.      */
  134.     else if (ison(glob_flags, IS_GETTING)) {
  135.         pw_char(msg_win, txt.x,txt.y, PIX_SRC^PIX_DST, fonts[curfont],'_');
  136.         if (lastchar != ltchars.t_lnextc &&
  137.         (ID == tchars.t_intrc || ID == tchars.t_quitc)) {
  138.             (void) rite(_tty.sg_kill);
  139.             (void) rm_edfile(SIGINT);
  140.         } else {
  141.         register int n = 1;
  142.         if (ID == tchars.t_eofc && txt.x == 5
  143.             || (p = rite((char)ID)) && !(n = add_to_letter(p)))
  144.             finish_up_letter();
  145.         else if (n > 0)
  146.             pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_');
  147.         }
  148.     }
  149.     lastchar = ID;
  150.     } else switch(ID) {
  151.     when MS_LEFT : case MS_MIDDLE:
  152.         if (getting_opts == 2)
  153.         if (ID == MS_LEFT)
  154.             set_key(NULL, event.ie_locx, event.ie_locy);
  155.         else {
  156.             register char *p = find_key(event.ie_locx, event.ie_locy);
  157.             if (p)
  158.             print("Function key %s:  %s", p, key_set_to(p));
  159.         }
  160.         else if (getting_opts) {
  161.         int y = event.ie_locy - 50;
  162.         if (y < -24)
  163.             break;
  164.         if (y < 0) {
  165.             register int x = event.ie_locx;
  166.             register int X = 60*l_width(LARGE);
  167.             if (x >= X && x <= X+16)
  168.             display_opts(-1); /* scroll options back one value */
  169.             else if (x >= X+20 && x <= X+36)
  170.             display_opts(1); /* scroll options forward one value */
  171.             break;
  172.         }
  173.         /* the user was typing something -- stopped by using mouse */
  174.         if (txt.x > 5) {
  175.             pw_char(msg_win, txt.x,txt.y, PIX_CLR, fonts[curfont], '_');
  176.             (void) rite(_tty.sg_kill), txt.x = 5;
  177.             option_line(line), display_opts(0);
  178.         }
  179.             line = y/20;
  180.         if (ID == MS_LEFT)
  181.             toggle_opt(line);
  182.         help_opt(line);   /* display help (short info) in both cases */
  183.         } else if (msg_pix)
  184.         if (ID == MS_LEFT)
  185.             scroll_win(crt-3);
  186.         else
  187.             scroll_win(-(crt-3));
  188.     when MS_RIGHT:
  189.         if (getting_opts)
  190.         (void) view_opts_menu(&event, gfxsw->gfx_windowfd);
  191.         else if (isoff(glob_flags, IS_GETTING))
  192.         (void) do_menu(&event, gfxsw->gfx_windowfd, current_msg);
  193.         else
  194.         (void) edit_menu(&event, gfxsw->gfx_windowfd);
  195.     otherwise: ;
  196.     }
  197.     *ibits = *obits = *ebits = 0;
  198. }
  199.  
  200. struct cursor *mice[3] = { &l_cursor, &m_cursor, &r_cursor };
  201.  
  202. hdr_io(gfxsw, ibits, obits, ebits, sw_timer)
  203. register struct gfxsubwindow *gfxsw;
  204. int *ibits,*obits,*ebits;
  205. struct timeval **sw_timer;
  206. {
  207.     static int         which_cursor;
  208.     struct inputmask     im;
  209.     struct inputevent     event;
  210.     int         line;
  211.  
  212.     if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  213.     *ibits = *obits = *ebits = 0;
  214.     return;
  215.     }
  216.     /* make curosr change which button is lit */
  217.     win_setcursor(gfxsw->gfx_windowfd, mice[which_cursor]);
  218.  
  219.     which_cursor = (which_cursor+1) % 3;
  220.     if (input_readevent(hdr_sw->ts_windowfd, &event) == -1) {
  221.     error("input event");
  222.     return;
  223.     }
  224.     /* I'm not sure why I have to do this.
  225.      * I'm doing it because sometimes the IO hangs completely and no input
  226.      * is accepted. What I do here is get the current mask, save it, then
  227.      * reset it. This action seems to flush the IO queue, and I don't have hung
  228.      * IO anymore.  This shouldn't be necessary, but it appears to work.
  229.      * (occurances have droped about 90%)
  230.      */
  231.     if (ID == LOC_WINENTER) {
  232.     int x;
  233.     win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  234.     win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  235.     }
  236.     /* just return -- we just wanted to make the cursor flicker */
  237.     if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER) {
  238.     *ibits = *obits = *ebits = 0;
  239.     return;
  240.     }
  241.     line = event.ie_locy / l_height(DEFAULT);
  242.     if (ID >= KEY_LEFTFIRST)
  243.     (void) func_key(ID);
  244.     else if (n_array[line] > msg_cnt)
  245.     if (!msg_cnt)
  246.         print("You have no messages -- this function is useless now.");
  247.     else
  248.         print("Message out of range.  Place mouse over a legal message.");
  249.     else switch(ID) {
  250.     when MS_LEFT: case MS_MIDDLE:
  251.         (void) do_menu((ID == MS_LEFT)? READ_MSG: DEL_MSG, 0,n_array[line]);
  252.     when MS_RIGHT:
  253.         (void) do_menu(&event, gfxsw->gfx_windowfd, n_array[line]);
  254.     otherwise : print("Unkown ID = %d", ID);
  255.     }
  256.     *ibits = *obits = *ebits = 0;
  257. }
  258.  
  259. /* if "fd" is 0, then event points to the action to be taken.
  260.  * otherwise, determine action to be taken by displaying a menu.
  261.  * message is the number current_msg should be changed to (may be the same).
  262.  */
  263. do_menu(event, fd, message)
  264. caddr_t event;
  265. {
  266.     static char buf[20];
  267.     struct menuitem *m_item;
  268.     char *action;
  269.     static struct menuitem msg_menu_items[] = {
  270.     { MENU_IMAGESTRING,  "Read",     READ_MSG   },
  271.     { MENU_IMAGESTRING,  "Delete",   DEL_MSG    },
  272.     { MENU_IMAGESTRING,  "Undelete", UNDEL_MSG  },
  273.     { MENU_IMAGESTRING,  "Reply",    REPL_MSG   },
  274.     { MENU_IMAGESTRING,  "Save",     SAVE_MSG   },
  275.     { MENU_IMAGESTRING,  "Preserve", PRE_MSG    },
  276.     { MENU_IMAGESTRING,  "Print",    PRNT_MSG   },
  277.     { MENU_IMAGESTRING,  "Help",     MENU_HELP  }
  278.     };
  279.     static struct menu help_menu = {
  280.         MENU_IMAGESTRING, "Item Help",
  281.     N_MENU_ITEMS, msg_menu_items,
  282.     (struct menu *)NULL, NULL
  283.     };
  284.     static struct menu msgs_menu = {
  285.         MENU_IMAGESTRING, buf, N_MENU_ITEMS,
  286.     msg_menu_items, &help_menu, NULL
  287.     };
  288.     /* to have the menu stack maintain order of menus upon each invokation,
  289.      * declare menu_ptr to be static and remove the following two lines
  290.      * after the declaration.
  291.      */
  292.     struct menu *menu_ptr = &msgs_menu;
  293.     msgs_menu.m_next = &help_menu;
  294.     help_menu.m_next = (struct menu *)NULL;
  295.  
  296.     if (!msg_cnt) {
  297.     print("No Messages.");
  298.     return;
  299.     }
  300.     if (fd) {
  301.     (void) sprintf(buf, "Message #%d", message+1);
  302.     if (m_item = menu_display(&menu_ptr, (struct inputevent *)event, fd))
  303.         action = m_item->mi_data;
  304.     else
  305.         return;
  306.     } else
  307.     action = event;
  308.  
  309.     if (menu_ptr == &help_menu || action == MENU_HELP) {
  310.     switch(action) {
  311.         when DEL_MSG: case UNDEL_MSG:
  312.         (void) help(fd, "menu_delete", tool_help);
  313.         when READ_MSG: (void) help(fd, "next", tool_help);
  314.         when REPL_MSG: (void) help(fd, "menu_respond", tool_help);
  315.         when SAVE_MSG: (void) help(fd, "save", tool_help);
  316.         when PRE_MSG: (void)  help(fd, "preserve", tool_help);
  317.         when PRNT_MSG: (void) help(fd, "printer", tool_help);
  318.         when MENU_HELP:
  319.         if (menu_ptr == &help_menu)
  320.             (void) help(fd, "help_menu_help_msg", tool_help);
  321.         else
  322.             (void) help(fd, "msg_menu", tool_help);
  323.     }
  324.     return;
  325.     }
  326.     set_isread(message);
  327.     if (action == SAVE_MSG) {
  328.     swap(current_msg, message);
  329.     ((struct inputevent *)event)->ie_code = MS_LEFT;
  330.     do_file_dir(save_item, 0, event);
  331.     swap(current_msg, message);
  332.     return;
  333.     } else if (action == PRNT_MSG  || action == PRE_MSG ||
  334.            action == UNDEL_MSG || action == DEL_MSG) {
  335.     fkey_misc(action, message);
  336.     return;
  337.     }
  338.     if (isoff(glob_flags, IS_GETTING)) {
  339.     current_msg = message;
  340.     (void) do_hdrs(0, DUBL_NULL, NULL);
  341.     }
  342.     if (action == REPL_MSG) {
  343.     respond_mail(respond_item, 0, event);
  344.     return;
  345.     } else if (ison(glob_flags, IS_GETTING)) {
  346.     print("Finish editing message first");
  347.     return;
  348.     }
  349.     display_msg(current_msg, (long)0);
  350. }
  351.  
  352. /* miscellaneous function key actions there are here because the defines
  353.  * for DEL_MSG, etc are here in this file and the function is called from
  354.  * here more often.
  355.  */
  356. fkey_misc(action, message)
  357. char *action;
  358. {
  359.     int argc;
  360.     register char **argv;
  361.     char buf[30];
  362.  
  363.     print("Message #%d ", message+1);
  364.     if (action == UNDEL_MSG || action == DEL_MSG)
  365.     print_more("%sd. ", sprintf(buf, "%selete",
  366.                 (action == DEL_MSG)? "d": "und"));
  367.     else if (action == PRNT_MSG) {
  368.     print_more("sent to printer");
  369.     (void) strcpy(buf, "lpr");
  370.     } else if (action == PRE_MSG)
  371.     print_more("%sd", strcpy(buf, "preseve"));
  372.     (void) sprintf(&buf[strlen(buf)], " %d", message+1);
  373.  
  374.     if (argv = make_command(buf, DUBL_NULL, &argc))
  375.     (void) do_command(argc, argv, msg_list);
  376.     return;
  377. }
  378.  
  379. view_opts_menu(event, fd)
  380. struct inputevent *event;
  381. {
  382.     static char buf[5];
  383.     struct menuitem *m_item;
  384.     char *action;
  385.     static struct menuitem opts_items[] = {
  386.     { MENU_IMAGESTRING,  "Save Options",    O_SAVE  },
  387.     { MENU_IMAGESTRING,  "Restore Options",    O_RSTR  },
  388.     { MENU_IMAGESTRING,  "Quit Options",    O_QUIT  },
  389.     { MENU_IMAGESTRING,  "Help",        MENU_HELP  }
  390.     };
  391.     static struct menu msgs_menu = {
  392.         MENU_IMAGESTRING, "Options", 4, opts_items, (struct menu *)NULL, NULL
  393.     };
  394.     struct menu *menu_ptr = &msgs_menu;
  395.  
  396.     if (m_item = menu_display(&menu_ptr, event, fd))
  397.     action = m_item->mi_data;
  398.     else
  399.     return;
  400.     switch(action) {
  401.     case O_SAVE:
  402.         save_opts(0, DUBL_NULL);
  403.     when O_RSTR:
  404.         init();
  405.         if (getting_opts == 1)
  406.         view_options();
  407.         else
  408.         set_fkeys();
  409.     when O_QUIT:
  410.         do_clear();
  411.         unlock_cursors(); /* actually resets msg_win's cursor */
  412.         if (isoff(glob_flags, IS_GETTING) && msg_cnt)
  413.         if (isoff(msg[current_msg].m_flags, DELETE))
  414.             display_msg(current_msg, (long)0);
  415.         else
  416.             (void) read_mail(NO_ITEM, 0, NO_EVENT);
  417.     when MENU_HELP:
  418.         (void) help(fd, (getting_opts == 1)? "options": "fkeys", tool_help);
  419.     }
  420. }
  421.