home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / common / seq.c < prev    next >
C/C++ Source or Header  |  1997-06-22  |  9KB  |  396 lines

  1. /*-
  2.  * Copyright (c) 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  * Copyright (c) 1992, 1993, 1994, 1995, 1996
  5.  *    Keith Bostic.  All rights reserved.
  6.  *
  7.  * See the LICENSE file for redistribution information.
  8.  */
  9.  
  10. #include "config.h"
  11.  
  12. #ifndef lint
  13. static const char sccsid[] = "@(#)seq.c    10.10 (Berkeley) 3/30/96";
  14. #endif /* not lint */
  15.  
  16. #include <sys/types.h>
  17. #include <sys/queue.h>
  18.  
  19. #include <bitstring.h>
  20. #include <ctype.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include "common.h"
  28.  
  29. /*
  30.  * seq_set --
  31.  *    Internal version to enter a sequence.
  32.  *
  33.  * PUBLIC: int seq_set __P((SCR *, CHAR_T *,
  34.  * PUBLIC:    size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
  35.  */
  36. int
  37. seq_set(sp, name, nlen, input, ilen, output, olen, stype, flags)
  38.     SCR *sp;
  39.     CHAR_T *name, *input, *output;
  40.     size_t nlen, ilen, olen;
  41.     seq_t stype;
  42.     int flags;
  43. {
  44.     CHAR_T *p;
  45.     SEQ *lastqp, *qp;
  46.     int sv_errno;
  47.  
  48.     /*
  49.      * An input string must always be present.  The output string
  50.      * can be NULL, when set internally, that's how we throw away
  51.      * input.
  52.      *
  53.      * Just replace the output field if the string already set.
  54.      */
  55.     if ((qp =
  56.         seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
  57.         if (LF_ISSET(SEQ_NOOVERWRITE))
  58.             return (0);
  59.         if (output == NULL || olen == 0) {
  60.             p = NULL;
  61.             olen = 0;
  62.         } else if ((p = v_strdup(sp, output, olen)) == NULL) {
  63.             sv_errno = errno;
  64.             goto mem1;
  65.         }
  66.         if (qp->output != NULL)
  67.             free(qp->output);
  68.         qp->olen = olen;
  69.         qp->output = p;
  70.         return (0);
  71.     }
  72.  
  73.     /* Allocate and initialize SEQ structure. */
  74.     CALLOC(sp, qp, SEQ *, 1, sizeof(SEQ));
  75.     if (qp == NULL) {
  76.         sv_errno = errno;
  77.         goto mem1;
  78.     }
  79.  
  80.     /* Name. */
  81.     if (name == NULL || nlen == 0)
  82.         qp->name = NULL;
  83.     else if ((qp->name = v_strdup(sp, name, nlen)) == NULL) {
  84.         sv_errno = errno;
  85.         goto mem2;
  86.     }
  87.     qp->nlen = nlen;
  88.  
  89.     /* Input. */
  90.     if ((qp->input = v_strdup(sp, input, ilen)) == NULL) {
  91.         sv_errno = errno;
  92.         goto mem3;
  93.     }
  94.     qp->ilen = ilen;
  95.  
  96.     /* Output. */
  97.     if (output == NULL) {
  98.         qp->output = NULL;
  99.         olen = 0;
  100.     } else if ((qp->output = v_strdup(sp, output, olen)) == NULL) {
  101.         sv_errno = errno;
  102.         free(qp->input);
  103. mem3:        if (qp->name != NULL)
  104.             free(qp->name);
  105. mem2:        free(qp);
  106. mem1:        errno = sv_errno;
  107.         msgq(sp, M_SYSERR, NULL);
  108.         return (1);
  109.     }
  110.     qp->olen = olen;
  111.  
  112.     /* Type, flags. */
  113.     qp->stype = stype;
  114.     qp->flags = flags;
  115.  
  116.     /* Link into the chain. */
  117.     if (lastqp == NULL) {
  118.         LIST_INSERT_HEAD(&sp->gp->seqq, qp, q);
  119.     } else {
  120.         LIST_INSERT_AFTER(lastqp, qp, q);
  121.     }
  122.  
  123.     /* Set the fast lookup bit. */
  124.     if (qp->input[0] < MAX_BIT_SEQ)
  125.         bit_set(sp->gp->seqb, qp->input[0]);
  126.  
  127.     return (0);
  128. }
  129.  
  130. /*
  131.  * seq_delete --
  132.  *    Delete a sequence.
  133.  *
  134.  * PUBLIC: int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
  135.  */
  136. int
  137. seq_delete(sp, input, ilen, stype)
  138.     SCR *sp;
  139.     CHAR_T *input;
  140.     size_t ilen;
  141.     seq_t stype;
  142. {
  143.     SEQ *qp;
  144.  
  145.     if ((qp = seq_find(sp, NULL, NULL, input, ilen, stype, NULL)) == NULL)
  146.         return (1);
  147.     return (seq_mdel(qp));
  148. }
  149.  
  150. /*
  151.  * seq_mdel --
  152.  *    Delete a map entry, without lookup.
  153.  *
  154.  * PUBLIC: int seq_mdel __P((SEQ *));
  155.  */
  156. int
  157. seq_mdel(qp)
  158.     SEQ *qp;
  159. {
  160.     LIST_REMOVE(qp, q);
  161.     if (qp->name != NULL)
  162.         free(qp->name);
  163.     free(qp->input);
  164.     if (qp->output != NULL)
  165.         free(qp->output);
  166.     free(qp);
  167.     return (0);
  168. }
  169.  
  170. /*
  171.  * seq_find --
  172.  *    Search the sequence list for a match to a buffer, if ispartial
  173.  *    isn't NULL, partial matches count.
  174.  *
  175.  * PUBLIC: SEQ *seq_find
  176.  * PUBLIC:    __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
  177.  */
  178. SEQ *
  179. seq_find(sp, lastqp, e_input, c_input, ilen, stype, ispartialp)
  180.     SCR *sp;
  181.     SEQ **lastqp;
  182.     EVENT *e_input;
  183.     CHAR_T *c_input;
  184.     size_t ilen;
  185.     seq_t stype;
  186.     int *ispartialp;
  187. {
  188.     SEQ *lqp, *qp;
  189.     int diff;
  190.  
  191.     /*
  192.      * Ispartialp is a location where we return if there was a
  193.      * partial match, i.e. if the string were extended it might
  194.      * match something.
  195.      *
  196.      * XXX
  197.      * Overload the meaning of ispartialp; only the terminal key
  198.      * search doesn't want the search limited to complete matches,
  199.      * i.e. ilen may be longer than the match.
  200.      */
  201.     if (ispartialp != NULL)
  202.         *ispartialp = 0;
  203.     for (lqp = NULL, qp = sp->gp->seqq.lh_first;
  204.         qp != NULL; lqp = qp, qp = qp->q.le_next) {
  205.         /*
  206.          * Fast checks on the first character and type, and then
  207.          * a real comparison.
  208.          */
  209.         if (e_input == NULL) {
  210.             if (qp->input[0] > c_input[0])
  211.                 break;
  212.             if (qp->input[0] < c_input[0] ||
  213.                 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
  214.                 continue;
  215.             diff = memcmp(qp->input, c_input, MIN(qp->ilen, ilen));
  216.         } else {
  217.             if (qp->input[0] > e_input->e_c)
  218.                 break;
  219.             if (qp->input[0] < e_input->e_c ||
  220.                 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
  221.                 continue;
  222.             diff =
  223.                 e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
  224.         }
  225.         if (diff > 0)
  226.             break;
  227.         if (diff < 0)
  228.             continue;
  229.         /*
  230.          * If the entry is the same length as the string, return a
  231.          * match.  If the entry is shorter than the string, return a
  232.          * match if called from the terminal key routine.  Otherwise,
  233.          * keep searching for a complete match.
  234.          */
  235.         if (qp->ilen <= ilen) {
  236.             if (qp->ilen == ilen || ispartialp != NULL) {
  237.                 if (lastqp != NULL)
  238.                     *lastqp = lqp;
  239.                 return (qp);
  240.             }
  241.             continue;
  242.         }
  243.         /*
  244.          * If the entry longer than the string, return partial match
  245.          * if called from the terminal key routine.  Otherwise, no
  246.          * match.
  247.          */
  248.         if (ispartialp != NULL)
  249.             *ispartialp = 1;
  250.         break;
  251.     }
  252.     if (lastqp != NULL)
  253.         *lastqp = lqp;
  254.     return (NULL);
  255. }
  256.  
  257. /*
  258.  * seq_close --
  259.  *    Discard all sequences.
  260.  *
  261.  * PUBLIC: void seq_close __P((GS *));
  262.  */
  263. void
  264. seq_close(gp)
  265.     GS *gp;
  266. {
  267.     SEQ *qp;
  268.  
  269.     while ((qp = gp->seqq.lh_first) != NULL) {
  270.         if (qp->name != NULL)
  271.             free(qp->name);
  272.         if (qp->input != NULL)
  273.             free(qp->input);
  274.         if (qp->output != NULL)
  275.             free(qp->output);
  276.         LIST_REMOVE(qp, q);
  277.         free(qp);
  278.     }
  279. }
  280.  
  281. /*
  282.  * seq_dump --
  283.  *    Display the sequence entries of a specified type.
  284.  *
  285.  * PUBLIC: int seq_dump __P((SCR *, seq_t, int));
  286.  */
  287. int
  288. seq_dump(sp, stype, isname)
  289.     SCR *sp;
  290.     seq_t stype;
  291.     int isname;
  292. {
  293.     CHAR_T *p;
  294.     GS *gp;
  295.     SEQ *qp;
  296.     int cnt, len, olen;
  297.  
  298.     cnt = 0;
  299.     gp = sp->gp;
  300.     for (qp = gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
  301.         if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
  302.             continue;
  303.         ++cnt;
  304.         for (p = qp->input,
  305.             olen = qp->ilen, len = 0; olen > 0; --olen, ++p)
  306.             len += ex_puts(sp, KEY_NAME(sp, *p));
  307.         for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
  308.             len -= ex_puts(sp, " ");
  309.  
  310.         if (qp->output != NULL)
  311.             for (p = qp->output,
  312.                 olen = qp->olen, len = 0; olen > 0; --olen, ++p)
  313.                 len += ex_puts(sp, KEY_NAME(sp, *p));
  314.         else
  315.             len = 0;
  316.  
  317.         if (isname && qp->name != NULL) {
  318.             for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
  319.                 len -= ex_puts(sp, " ");
  320.             for (p = qp->name,
  321.                 olen = qp->nlen; olen > 0; --olen, ++p)
  322.                 (void)ex_puts(sp, KEY_NAME(sp, *p));
  323.         }
  324.         (void)ex_puts(sp, "\n");
  325.     }
  326.     return (cnt);
  327. }
  328.  
  329. /*
  330.  * seq_save --
  331.  *    Save the sequence entries to a file.
  332.  *
  333.  * PUBLIC: int seq_save __P((SCR *, FILE *, char *, seq_t));
  334.  */
  335. int
  336. seq_save(sp, fp, prefix, stype)
  337.     SCR *sp;
  338.     FILE *fp;
  339.     char *prefix;
  340.     seq_t stype;
  341. {
  342.     CHAR_T *p;
  343.     SEQ *qp;
  344.     size_t olen;
  345.     int ch;
  346.  
  347.     /* Write a sequence command for all keys the user defined. */
  348.     for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
  349.         if (stype != qp->stype || !F_ISSET(qp, SEQ_USERDEF))
  350.             continue;
  351.         if (prefix)
  352.             (void)fprintf(fp, "%s", prefix);
  353.         for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
  354.             ch = *p++;
  355.             if (ch == CH_LITERAL || ch == '|' ||
  356.                 isblank(ch) || KEY_VAL(sp, ch) == K_NL)
  357.                 (void)putc(CH_LITERAL, fp);
  358.             (void)putc(ch, fp);
  359.         }
  360.         (void)putc(' ', fp);
  361.         if (qp->output != NULL)
  362.             for (p = qp->output,
  363.                 olen = qp->olen; olen > 0; --olen) {
  364.                 ch = *p++;
  365.                 if (ch == CH_LITERAL || ch == '|' ||
  366.                     KEY_VAL(sp, ch) == K_NL)
  367.                     (void)putc(CH_LITERAL, fp);
  368.                 (void)putc(ch, fp);
  369.             }
  370.         (void)putc('\n', fp);
  371.     }
  372.     return (0);
  373. }
  374.  
  375. /*
  376.  * e_memcmp --
  377.  *    Compare a string of EVENT's to a string of CHAR_T's.
  378.  *
  379.  * PUBLIC: int e_memcmp __P((CHAR_T *, EVENT *, size_t));
  380.  */
  381. int
  382. e_memcmp(p1, ep, n)
  383.     CHAR_T *p1;
  384.     EVENT *ep;
  385.     size_t n;
  386. {
  387.     if (n != 0) {
  388.                 do {
  389.                         if (*p1++ != ep->e_c)
  390.                                 return (*--p1 - ep->e_c);
  391.             ++ep;
  392.                 } while (--n != 0);
  393.         }
  394.         return (0);
  395. }
  396.