home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / util / vim-3.0.lha / Vim / src / getchar.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  34KB  |  1,476 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * getchar.c
  11.  *
  12.  * functions related with getting a character from the user/mapping/redo/...
  13.  *
  14.  * manipulations with redo buffer and stuff buffer
  15.  * mappings and abbreviations
  16.  */
  17.  
  18. #include "vim.h"
  19. #include "globals.h"
  20. #include "proto.h"
  21. #include "param.h"
  22.  
  23. /*
  24.  * structure used to store one block of the stuff/redo/macro buffers
  25.  */
  26. struct bufblock
  27. {
  28.         struct bufblock *b_next;        /* pointer to next bufblock */
  29.         char_u            b_str[1];        /* contents (actually longer) */
  30. };
  31.  
  32. #define MINIMAL_SIZE 20                 /* minimal size for b_str */
  33.  
  34. /*
  35.  * header used for the stuff buffer and the redo buffer
  36.  */
  37. struct buffheader
  38. {
  39.         struct bufblock bh_first;        /* first (dummy) block of list */
  40.         struct bufblock *bh_curr;        /* bufblock for appending */
  41.         int             bh_index;        /* index for reading */
  42.         int             bh_space;        /* space in bh_curr for appending */
  43. };
  44.  
  45. static struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
  46. static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
  47. static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
  48.  
  49.     /*
  50.      * when block_redo is TRUE redo buffer will not be changed
  51.      * used by edit() to repeat insertions and 'V' command for redoing
  52.      */
  53. static int        block_redo = FALSE;
  54.  
  55. /*
  56.  * structure used for mapping
  57.  */
  58. struct mapblock
  59. {
  60.     struct mapblock *m_next;        /* next mapblock */
  61.     char_u            *m_keys;        /* mapped from */
  62.     int                 m_keylen;        /* strlen(m_keys) */
  63.     char_u            *m_str;         /* mapped to */
  64.     int              m_mode;        /* valid mode */
  65.     int                 m_noremap;        /* if non-zero no re-mapping for m_str */
  66. };
  67.  
  68. static struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
  69.                                     /* first dummy entry in maplist */
  70.  
  71. /*
  72.  * variables used by vgetorpeek() and flush_buffers()
  73.  *
  74.  * typestr contains all characters that are not consumed yet.
  75.  * The part in front may contain the result of mappings, abbreviations and
  76.  * @a commands. The lenght of this part is typemaplen.
  77.  * After it are characters that come from the terminal.
  78.  * no_abbr_cnt is the number of characters in typestr that should not be
  79.  * considered for abbreviations.
  80.  * Some parts of typestr may not be mapped. These parts are remembered in
  81.  * the noremaplist. 
  82.  */
  83. #define MAXMAPLEN 50                /* maximum length of key sequence to be mapped */
  84.                                     /* must be able to hold an Amiga resize report */
  85. static char_u    *typestr = NULL;    /* NUL-terminated buffer for typeahead characters */
  86. static char_u    typebuf[MAXMAPLEN + 3]; /* initial typestr */
  87.  
  88. static int        typemaplen = 0;        /* number of mapped characters in typestr */
  89. static int        no_abbr_cnt = 0;    /* number of chars without abbrev. in typestr */
  90.  
  91. /* 
  92.  * parts int typestr that should not be mapped are remembered with a list
  93.  * of noremap structs. Noremaplist is the first.
  94.  */
  95. struct noremap
  96. {
  97.     int                nr_off;            /* offset to not remappable chars */
  98.     int                nr_len;            /* number of not remappable chars */
  99.     struct noremap    *nr_next;        /* next entry in the list */
  100. };
  101.  
  102. static struct noremap noremaplist = {0, 0, NULL};
  103.  
  104. static void        free_buff __ARGS((struct buffheader *));
  105. static char_u    *get_bufcont __ARGS((struct buffheader *, int));
  106. static void        add_buff __ARGS((struct buffheader *, char_u *));
  107. static void        add_num_buff __ARGS((struct buffheader *, long));
  108. static void        add_char_buff __ARGS((struct buffheader *, int));
  109. static int        read_stuff __ARGS((int));
  110. static void        start_stuff __ARGS((void));
  111. static int        read_redo __ARGS((int));
  112. static void        init_typestr __ARGS((void));
  113. static void        gotchars __ARGS((char_u *, int));
  114. static int        vgetorpeek __ARGS((int));
  115. static void        showmap __ARGS((struct mapblock *));
  116.  
  117. /*
  118.  * free and clear a buffer
  119.  */
  120.     static void
  121. free_buff(buf)
  122.     struct buffheader *buf;
  123. {
  124.         register struct bufblock *p, *np;
  125.  
  126.         for (p = buf->bh_first.b_next; p != NULL; p = np)
  127.         {
  128.                 np = p->b_next;
  129.                 free(p);
  130.         }
  131.         buf->bh_first.b_next = NULL;
  132. }
  133.  
  134. /*
  135.  * return the contents of a buffer as a single string
  136.  */
  137.     static char_u *
  138. get_bufcont(buffer, dozero)
  139.     struct buffheader    *buffer;
  140.     int                    dozero;        /* count == zero is not an error */
  141. {
  142.         long_u            count = 0;
  143.         char_u            *p = NULL;
  144.         struct bufblock    *bp;
  145.  
  146. /* compute the total length of the string */
  147.         for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  148.                 count += STRLEN(bp->b_str);
  149.  
  150.         if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL)
  151.         {
  152.                 *p = NUL;
  153.                 for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  154.                         strcat((char *)p, (char *)bp->b_str);
  155.         }
  156.         return (p);
  157. }
  158.  
  159. /*
  160.  * return the contents of the record buffer as a single string
  161.  *    and clear the record buffer
  162.  */
  163.     char_u *
  164. get_recorded()
  165. {
  166.     char_u *p;
  167.  
  168.     p = get_bufcont(&recordbuff, TRUE);
  169.     free_buff(&recordbuff);
  170.     return (p);
  171. }
  172.  
  173. /*
  174.  * return the contents of the redo buffer as a single string
  175.  */
  176.     char_u *
  177. get_inserted()
  178. {
  179.         return(get_bufcont(&redobuff, FALSE));
  180. }
  181.  
  182. /*
  183.  * add string "s" after the current block of buffer "buf"
  184.  */
  185.     static void
  186. add_buff(buf, s)
  187.     register struct buffheader    *buf;
  188.     char_u                        *s;
  189. {
  190.     struct bufblock *p;
  191.     long_u             n;
  192.     long_u             len;
  193.  
  194.     if ((n = STRLEN(s)) == 0)                /* don't add empty strings */
  195.         return;
  196.  
  197.     if (buf->bh_first.b_next == NULL)        /* first add to list */
  198.     {
  199.         buf->bh_space = 0;
  200.         buf->bh_curr = &(buf->bh_first);
  201.     }
  202.     else if (buf->bh_curr == NULL)            /* buffer has already been read */
  203.     {
  204.         EMSG("Add to read buffer");
  205.         return;
  206.     }
  207.     else if (buf->bh_index != 0)
  208.         STRCPY(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index);
  209.     buf->bh_index = 0;
  210.  
  211.     if (buf->bh_space >= n)
  212.     {
  213.         strcat((char *)buf->bh_curr->b_str, (char *)s);
  214.         buf->bh_space -= n;
  215.     }
  216.     else
  217.     {
  218.         if (n < MINIMAL_SIZE)
  219.             len = MINIMAL_SIZE;
  220.         else
  221.             len = n;
  222.         p = (struct bufblock *)lalloc((long_u)(sizeof(struct bufblock) + len), TRUE);
  223.         if (p == NULL)
  224.             return; /* no space, just forget it */
  225.         buf->bh_space = len - n;
  226.         STRCPY(p->b_str, s);
  227.  
  228.         p->b_next = buf->bh_curr->b_next;
  229.         buf->bh_curr->b_next = p;
  230.         buf->bh_curr = p;
  231.     }
  232.     return;
  233. }
  234.  
  235.     static void
  236. add_num_buff(buf, n)
  237.     struct buffheader *buf;
  238.     long               n;
  239. {
  240.         char_u    number[32];
  241.  
  242.         sprintf((char *)number, "%ld", n);
  243.         add_buff(buf, number);
  244. }
  245.  
  246.     static void
  247. add_char_buff(buf, c)
  248.     struct buffheader *buf;
  249.     int               c;
  250. {
  251.         char_u    temp[2];
  252.  
  253.         temp[0] = c;
  254.         temp[1] = NUL;
  255.         add_buff(buf, temp);
  256. }
  257.  
  258. /*
  259.  * get one character from the stuff buffer
  260.  * If advance == TRUE go to the next char.
  261.  */
  262.     static int
  263. read_stuff(advance)
  264.     int            advance;
  265. {
  266.     register char_u c;
  267.     register struct bufblock *curr;
  268.  
  269.  
  270.     if (stuffbuff.bh_first.b_next == NULL)    /* buffer is empty */
  271.         return NUL;
  272.  
  273.     curr = stuffbuff.bh_first.b_next;
  274.     c = curr->b_str[stuffbuff.bh_index];
  275.  
  276.     if (advance)
  277.     {
  278.         if (curr->b_str[++stuffbuff.bh_index] == NUL)
  279.         {
  280.             stuffbuff.bh_first.b_next = curr->b_next;
  281.             free(curr);
  282.             stuffbuff.bh_index = 0;
  283.         }
  284.     }
  285.     return c;
  286. }
  287.  
  288. /*
  289.  * prepare stuff buffer for reading (if it contains something)
  290.  */
  291.     static void
  292. start_stuff()
  293. {
  294.     if (stuffbuff.bh_first.b_next != NULL)
  295.     {
  296.         stuffbuff.bh_curr = &(stuffbuff.bh_first);
  297.         stuffbuff.bh_space = 0;
  298.     }
  299. }
  300.  
  301. /*
  302.  * check if the stuff buffer is empty
  303.  */
  304.     int
  305. stuff_empty()
  306. {
  307.     return (stuffbuff.bh_first.b_next == NULL);
  308. }
  309.  
  310. /*
  311.  * Remove the contents of the stuff buffer and the mapped characters in the
  312.  * typeahead buffer (used in case of an error). If 'typeahead' is true,
  313.  * flush all typeahead characters (used when interrupted by a CTRL-C).
  314.  */
  315.     void
  316. flush_buffers(typeahead)
  317.     int typeahead;
  318. {
  319.     struct noremap *p;
  320.  
  321.     init_typestr();
  322.  
  323.     start_stuff();
  324.     while (read_stuff(TRUE) != NUL)
  325.         ;
  326.  
  327.     if (typeahead)            /* remove all typeahead */
  328.     {
  329.             /*
  330.              * We have to get all characters, because we may delete the first
  331.              * part of an escape sequence.
  332.              * In an xterm we get one char at a time and we have to get them all.
  333.              */
  334.         while (inchar(typestr, MAXMAPLEN, 10))    
  335.             ;
  336.         *typestr = NUL;
  337.     }
  338.     else                    /* remove mapped characters only */
  339.         STRCPY(typestr, typestr + typemaplen);
  340.     typemaplen = 0;
  341.     no_abbr_cnt = 0;
  342.     noremaplist.nr_len = 0;
  343.     noremaplist.nr_off = 0;
  344.     while (noremaplist.nr_next)
  345.     {
  346.         p = noremaplist.nr_next->nr_next;
  347.         free(noremaplis