home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / pico / bind.c < prev    next >
C/C++ Source or Header  |  1998-08-27  |  11KB  |  419 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: bind.c,v 4.22 1998/08/27 23:01:21 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Key binding routines
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1998 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*    This file is for functions having to do with key bindings,
  31.     descriptions, help commands, and command line execution.
  32.  
  33.     written 11-feb-86 by Daniel Lawrence
  34.                                 */
  35.  
  36. #include    "headers.h"
  37.  
  38. #ifdef    ANSI
  39.     int arraylen(char **);
  40. #else
  41.     int arraylen();
  42. #endif
  43.  
  44. /* 
  45.  * help - help function for pico (UW pared down version of uemacs).
  46.  *      this function will intentionally garbage with helpful 
  47.  *      tips and then wait for a ' ' to be hit to then update the 
  48.  *        screen.
  49.  */
  50.  
  51.  
  52. static char *helptext[] = {
  53.     "\tPico Help Text",
  54.     " ",
  55.     "\tPico is designed to be a simple, easy-to-use text editor with a",
  56.     "\tlayout very similar to the pine mailer.  The status line at the",
  57.     "\ttop of the display shows pico's version, the current file being",
  58.     "\tedited and whether or not there are outstanding modifications",
  59.     "\tthat have not been saved.  The third line from the bottom is used",
  60.     "\tto report informational messages and for additional command input.",
  61.     "\tThe bottom two lines list the available editing commands.",
  62.     " ",
  63.     "\tEach character typed is automatically inserted into the buffer",
  64.     "\tat the current cursor position.  Editing commands and cursor",
  65.     "\tmovement (besides arrow keys) are given to pico by typing",
  66.     "\tspecial control-key sequences.  A caret, '^', is used to denote",
  67.     "~\tthe control key, sometimes marked \"CTRL\", so the ~C~T~R~L~-~q key",
  68.     "~\tcombination is written as ~^~Q.",
  69.     " ",
  70.     "\tThe following functions are available in pico (where applicable,",
  71.     "\tcorresponding function key commands are in parentheses).",
  72.     " ",
  73.     "~\t~^~G (~F~1)   Display this help text.",
  74.     " ",
  75.     "~\t~^~F        move Forward a character.",
  76.     "~\t~^~B        move Backward a character.",
  77.     "~\t~^~P        move to the Previous line.",
  78.     "~\t~^~N        move to the Next line.",
  79.     "~\t~^~A        move to the beginning of the current line.",
  80.     "~\t~^~E        move to the End of the current line.",
  81.     "~\t~^~V (~F~8)   move forward a page of text.",
  82.     "~\t~^~Y (~F~7)   move backward a page of text.",
  83.     " ",
  84.     "~\t~^~W (~F~6)   Search for (where is) text, neglecting case.",
  85.     "~\t~^~L        Refresh the display.",
  86.     " ",
  87.     "~\t~^~D        Delete the character at the cursor position.",
  88.     "~\t~^~^        Mark cursor position as beginning of selected text.",
  89.     "\t\t  Note: Setting mark when already set unselects text.",
  90.     "~\t~^~K (~F~9)   Cut selected text (displayed in inverse characters).",
  91.     "\t\t  Note: The selected text's boundary on the cursor side",
  92.     "\t\t        ends at the left edge of the cursor.  So, with ",
  93.     "\t\t        selected text to the left of the cursor, the ",
  94.     "\t\t        character under the cursor is not selected.",
  95.     "~\t~^~U (~F~1~0)  Uncut (paste) last cut text inserting it at the",
  96.     "\t\t  current cursor position.",
  97.     "~\t~^~I        Insert a tab at the current cursor position.",
  98.     " ",
  99.     "~\t~^~J (~F~4)   Format (justify) the current paragraph.",
  100.     "\t\t  Note: paragraphs delimited by blank lines or indentation.",
  101.     "~\t~^~T (~F~1~2)  To invoke the spelling checker",
  102.     "~\t~^~C (~F~1~1)  Report current cursor position",
  103.     " ",
  104.     "~\t~^~R (~F~5)   Insert an external file at the current cursor position.",
  105.     "~\t~^~O (~F~3)   Output the current buffer to a file, saving it.",
  106.     "~\t~^~X (~F~2)   Exit pico, saving buffer.",
  107.     "    ",
  108.     "\tPine and Pico are trademarks of the University of Washington.",
  109.     "\tNo commercial use of these trademarks may be made without prior",
  110.     "\twritten permission of the University of Washington.",
  111.     "    ",
  112.     "    End of Help.",
  113.     " ",
  114.     NULL
  115. };
  116.  
  117.  
  118. /*
  119.  * arraylen - return the number of bytes in an array of char
  120.  */
  121. arraylen(array)
  122. char **array;
  123. {
  124.     register int i=0;
  125.  
  126.     while(array[i++] != NULL) ;
  127.     return(i);
  128. }
  129.  
  130.  
  131. /*
  132.  * whelp - display help text for the composer and pico
  133.  */
  134. whelp(f, n)
  135.      int f, n;
  136. {
  137.     if(term.t_mrow == 0){  /* blank keymenu in effect */
  138.     if(km_popped == 0){
  139.         /* cause keymenu display */
  140.         km_popped = 2;
  141.         if(!Pmaster)
  142.           sgarbf = TRUE;
  143.  
  144.         return(TRUE);
  145.     }
  146.     }
  147.  
  148.     if(Pmaster){
  149.     VARS_TO_SAVE *saved_state;
  150.  
  151.     saved_state = save_pico_state();
  152.     (*Pmaster->helper)(Pmaster->composer_help,
  153.                Pmaster->headents
  154.                  ? "Help on the Pine Composer"
  155.                  : "Help on Signature Editor",
  156.                1);
  157.     if(saved_state){
  158.         restore_pico_state(saved_state);
  159.         free_pico_state(saved_state);
  160.     }
  161.  
  162.     ttresize();
  163.     picosigs();            /* restore any altered handlers */
  164.     curwp->w_flag |= WFMODE;
  165.     if(km_popped)  /* this will unpop us */
  166.       curwp->w_flag |= WFHARD;
  167.     }
  168.     else{
  169.     int mrow_was_zero = 0;
  170.  
  171.     /* always want keyhelp showing during help */
  172.     if(term.t_mrow == 0){
  173.         mrow_was_zero++;
  174.         term.t_mrow = 2;
  175.     }
  176.  
  177.     pico_help(helptext, "Help for Pico", 1);
  178.     /* put it back the way it was */
  179.     if(mrow_was_zero)
  180.       term.t_mrow = 0;
  181.     }
  182.  
  183.     sgarbf = TRUE;
  184. }
  185.  
  186. static KEYMENU menu_scroll[] = {
  187.     {NULL, NULL, KS_NONE},        {NULL, NULL, KS_NONE},
  188.     {NULL, NULL, KS_NONE},        {NULL, NULL, KS_NONE},
  189.     {NULL, NULL, KS_NONE},        {NULL, NULL, KS_NONE},
  190.     {"^X", "Exit Help", KS_NONE},    {NULL, NULL, KS_NONE},
  191.     {NULL, NULL, KS_NONE},        {NULL, NULL, KS_NONE},
  192.     {NULL, NULL, KS_NONE},        {NULL, NULL, KS_NONE}
  193. };
  194. #define    PREV_KEY    3
  195. #define    NEXT_KEY    9
  196.  
  197.  
  198. #define    OVERLAP    2        /* displayed page overlap */
  199.  
  200. /*
  201.  * scrollw - takes beginning row and ending row to diplay an array
  202.  *           of text lines.  returns either 0 if scrolling terminated
  203.  *           normally or the value of a ctrl character typed to end it.
  204.  *
  205.  * updates - 
  206.  *     01/11/89 - added stripe call if 1st char is tilde - '~'
  207.  *
  208.  */
  209. wscrollw(begrow, endrow, textp, textlen)
  210. int    begrow, endrow;
  211. char    *textp[];
  212. int    textlen;
  213. {
  214.     register int    loffset = 0; 
  215.     register int    prevoffset = -1; 
  216.     register int    dlines;
  217.     register int    i;
  218.     register int    cont;
  219.     register int    done = 0;
  220.     register char    *buf;
  221.     int     c;
  222.      
  223.     dlines = endrow - begrow - 1;
  224.     while(!done) {
  225.         /*
  226.          * diplay a page loop ...
  227.          */
  228.     if(prevoffset != loffset){
  229.                for(i = 0; i < dlines; i++){
  230.                 movecursor(i + begrow, 0);
  231.                 peeol();
  232.                 if((loffset+i) < textlen){
  233.             buf = &(textp[loffset+i][0]);
  234.             if(*buf == '~'){
  235.             buf++;
  236.             wstripe(begrow+i, 0, buf, '~');
  237.             }
  238.             else{
  239.             pputs(buf, 0);
  240.             }
  241.                 }
  242.             }
  243.         /*
  244.          * put up the options prompt
  245.          */
  246.             movecursor(begrow + dlines, 0);
  247.             cont = (loffset+dlines < textlen);
  248.             if(cont){                               /* continue ? */
  249.         menu_scroll[NEXT_KEY].name  = "^V";
  250.         menu_scroll[NEXT_KEY].label = "Next Pg";
  251.         }
  252.         else
  253.           menu_scroll[NEXT_KEY].name = NULL;
  254.  
  255.         if(loffset){
  256.         menu_scroll[PREV_KEY].name  = "^Y";
  257.         menu_scroll[PREV_KEY].label = "Prev Pg";
  258.         }
  259.         else
  260.           menu_scroll[PREV_KEY].name = NULL;
  261.  
  262.         wkeyhelp(menu_scroll);
  263.     }
  264.  
  265.     (*term.t_flush)();
  266.  
  267.         c = GetKey();
  268.  
  269.     prevoffset = loffset;
  270.     switch(c){
  271.         case  (CTRL|'X') :        /* quit */
  272.          case  F2  :
  273.         done = 1;
  274.         break;
  275.         case  (CTRL|'Y') :        /* prev page */
  276.         case  F7  :            /* prev page */
  277.         if((loffset-dlines-OVERLAP) > 0){
  278.                        loffset -= (dlines-OVERLAP);
  279.         }
  280.             else{
  281.             if(loffset != 0){
  282.             prevoffset = -1;
  283.             }
  284.             else{
  285.                 (*term.t_beep)();
  286.             }
  287.             loffset = 0;
  288.             }
  289.         break;
  290.         case  (CTRL|'V') :            /* next page */
  291.          case  F8  :
  292.         if(cont){
  293.                       loffset += (dlines-OVERLAP);
  294.         }
  295.         else{
  296.            (*term.t_beep)();
  297.         }
  298.         break;
  299.         case  '\016' :        /* prev-line */
  300.         case  (CTRL|'N') :
  301.           if(cont)
  302.         loffset++;
  303.           else
  304.         (*term.t_beep)();
  305.           break;
  306.         case  '\020' :        /* prev-line */
  307.         case  (CTRL|'P') :
  308.           if(loffset > 0)
  309.         loffset--;
  310.           else
  311.         (*term.t_beep)();
  312.           break;
  313.         case  '\014' :        /* refresh */
  314.         case  (CTRL|'L') :        /* refresh */
  315.             modeline(curwp);
  316.         update();
  317.         prevoffset = -1;
  318.         break;
  319.         case  NODATA :
  320.             break;
  321.         default :
  322.         emlwrite("Unknown Command.", NULL);
  323.         (*term.t_beep)();
  324.         break;
  325.     }
  326.     }
  327.     return(TRUE);
  328. }
  329.  
  330.  
  331. /*
  332.  * normalize_cmd - given a char and list of function key to command key
  333.  *           mappings, return, depending on gmode, the right command.
  334.  *           The list is an array of (Fkey, command-key) pairs.
  335.  *           sc is the index in the array that means to ignore fkey
  336.  *           vs. command key mapping
  337.  *
  338.  *          rules:  1. if c not in table (either fkey or command), let it thru
  339.  *                  2. if c matches, but in other mode, punt it
  340.  */
  341. normalize_cmd(c, list, sc)
  342. int c, sc;
  343. int list[][2];
  344. {
  345.     register int i;
  346.  
  347.     for(i=0; i < 12; i++){
  348.     if(c == list[i][(FUNC&c) ? 0 : 1]){    /* in table? */
  349.         if(i == sc)                /* SPECIAL CASE! */
  350.           return(list[i][1]);
  351.  
  352.         if(list[i][1] == NODATA)        /* no mapping ! */
  353.           return(c);
  354.  
  355.         if(((FUNC&c) == FUNC) ^ ((gmode&MDFKEY) == MDFKEY))
  356.           return(BADESC);            /* keystroke not allowed! */
  357.         else
  358.           return(list[i][1]);        /* never return func keys */
  359.     }
  360.     }
  361.  
  362. #ifdef _WINDOWS
  363.     /*
  364.      * Menu's get alpha key commands assigned to them.  Well, if we are in PF
  365.      * key mode then the alpha key commands don't work.  So, we flag them with
  366.      * a bit (MENU defined in estruct.h) so we can recognize them as different
  367.      * from a keyboard press.  Here we clear that flag so the command can be
  368.      * processed.
  369.      */
  370.     c &= ~MENU;
  371. #endif
  372.  
  373.     return(c);
  374. }
  375.  
  376.  
  377. /*
  378.  * rebind - replace the first function with the second
  379.  */
  380. rebindfunc(a, b)
  381.     int (*a) PROTO((int, int)), (*b) PROTO((int, int));
  382. {
  383.     KEYTAB *kp;
  384.  
  385.     kp = (Pmaster) ? &keytab[0] : &pkeytab[0];
  386.  
  387.     while(kp->k_fp != NULL){        /* go thru whole list, and */
  388.     if(kp->k_fp == a)
  389.       kp->k_fp = b;            /* replace all occurances */
  390.     kp++;
  391.     }
  392. }
  393.  
  394.  
  395. /*
  396.  * bindtokey - bind function f to command c
  397.  */
  398. bindtokey(c, f)
  399. int c, (*f) PROTO((int, int));
  400. {
  401.     KEYTAB *kp, *ktab = (Pmaster) ? &keytab[0] : &pkeytab[0];
  402.  
  403.     for(kp = ktab; kp->k_fp; kp++)
  404.       if(kp->k_code == c){
  405.       kp->k_fp = f;            /* set to new function */
  406.       break;
  407.       }
  408.  
  409.     /* not found? create new binding */
  410.     if(!kp->k_fp && kp < &ktab[NBINDS]){
  411.     kp->k_code     = c;        /* assign new code and function */
  412.     kp->k_fp       = f;
  413.     (++kp)->k_code = 0;        /* and null out next slot */
  414.     kp->k_fp       = NULL;
  415.     }
  416.  
  417.     return(TRUE);
  418. }
  419.