home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / lxprpas.zip / LXPROTO.C < prev    next >
Text File  |  1998-04-20  |  11KB  |  230 lines

  1. /********************************************************************
  2. *                                                                   *
  3. *  LXPROTO - A simple prototype statement inserter for LPEX.        *
  4. *                                                                   *
  5. *            (C) Copyright IBM Corporation 1989-1995                *
  6. *                                                                   *
  7. *********************************************************************
  8. *                                                                   *
  9. *  The PROTO command (which invokes LXPROTO.DLL) is best tied to    *
  10. *  a key (such as Ctrl-X). When invoked, it checks the content of   *
  11. *  the current line.  If there is a word under the cursor, or       *
  12. *  immediately before it, PROTO checks whether this word, prefixed  *
  13. *  with 'xxx' (where 'xxx' is the parameter supplied to PROTO) is a *
  14. *  current global variable.  If so, the value of the variable is    *
  15. *  treated as a set of elements to be inserted at the current       *
  16. *  position.  If no parameter is supplied, '#' is used.             *
  17. *                                                                   *
  18. *  Thus, given the global variable definition:                      *
  19. *                                                                   *
  20. *     GLOBAL.#if /if (?) {//} else {//}                             *
  21. *                                                                   *
  22. *  and the actionkey definition:                                    *
  23. *                                                                   *
  24. *     ACTION.c-x proto                                              *
  25. *                                                                   *
  26. *  pressing Ctrl-x when the cursor is on a line under the word "if" *
  27. *  will cause LPEX to replace the text with:                        *
  28. *                                                                   *
  29. *      if (?) {                                                     *
  30. *                                                                   *
  31. *      } else {                                                     *
  32. *                                                                   *
  33. *      }                                                            *
  34. *                                                                   *
  35. *  Note that:                                                       *
  36. *                                                                   *
  37. *  1. BLOCK SET WORD is used to locate word to use as a base for    *
  38. *     the global variable.  This allows the use of accented chars   *
  39. *     and numerics, but not of delimiters and specials.             *
  40. *                                                                   *
  41. *  2. The new text is aligned with the word on the original line.   *
  42. *                                                                   *
  43. *  3. The cursor is positioned at the first ? in the replacement    *
  44. *     text (or at the start of the first line if none).             *
  45. *                                                                   *
  46. *  4. The line separator ("/" in the example above) is taken as     *
  47. *     the first non-blank character in the variable definition.     *
  48. *                                                                   *
  49. *  5. Any text after the original word will be placed at the end    *
  50. *     of the last line of the replacement text.                     *
  51. *                                                                   *
  52. *********************************************************************
  53. *                                                                   *
  54. * Operation:                                                        *
  55. *  1. obtain content of current line                                *
  56. *  2. identify the word under the cursor (if none, return)          *
  57. *  3. prefix word with 'xxx' and check if this is a global variable *
  58. *  4. if no, return                                                 *
  59. *  5. delete current line                                           *
  60. *  6. scan variable definition, inserting lines                     *
  61. *  7. append remainder of original line to last line                *
  62. *  8. set position at first "?" (or first line).                    *
  63. *                                                                   *
  64. ********************************************************************/
  65.  
  66. #include <stdlib.h>
  67. #include <stdio.h>
  68. #include <string.h>
  69.  
  70. #include "lpexapi.h"
  71.  
  72.  
  73. #define  BLANK  ' '
  74.  
  75.  
  76. /* A large work area for LPEX calls */
  77. char result[MAXQUERY];                             /* result used for queries */
  78. char quer[100] = "GLOBAL.";                  /* used to test if global exists */
  79. char posi[100];                                       /* used to set position */
  80. char newl[300];                                /* used to hold inserted lines */
  81.  
  82.  
  83. char *lxxquer(char *item, char *buff)        /* return pointer to query value */
  84. {
  85.    char *p;
  86.  
  87.    lxquery(item, buff);                        /* returns "ITEM value" string */
  88.    p = buff;
  89.    while (*p != BLANK && *p != '\0') ++p;              /* step over item name */
  90.    if (*p == BLANK) ++p;                               /* and following blank */
  91.    return p;
  92. }
  93.  
  94. int lxxqnum(char *item)            /* returns as an int the result of a query */
  95. {
  96.    char work[100];
  97.    return atoi(lxxquer(item, work));
  98. }
  99.  
  100.  
  101. lxmain(uchr *arg)
  102. {
  103.    char *p, *q, *r, *s, buff[300];
  104.    int  i;
  105.    int  k;                                /* position of first "?" in pattern */
  106.    char delim;                                   /* line delimiter in pattern */
  107.    int  join1;                                    /* true if text before word */
  108.    int  join2;                                     /* true if text after word */
  109.    int  offset;                    /* start of word offset from start of line */
  110.    int  cnt;                                         /* counts inserted lines */
  111.    char autoparse[20];                    /* used to remember autoparse state */
  112.    int  noword = 0;
  113.    char blockdefaulttype[50];
  114.  
  115.    lxquery("BLOCKDEFAULTTYPE", blockdefaulttype);
  116.    lxcmd("SET BLOCKDEFAULTTYPE CHARACTER");
  117.  
  118.  
  119.    while (arg[0] == BLANK)                             /* skip leading blanks */
  120.       arg++;
  121.    p = quer + 7;
  122.    if (*arg == '\0')                                    /* set default prefix */
  123.       strcpy(p, "#");
  124.    else {
  125.       while (*arg != '\0' && *arg != BLANK)
  126.          *p++ = *arg++;                            /* set prefix as requested */
  127.       *p = '\0';
  128.       }
  129.  
  130.    lxquery("AUTOPARSE", buff);
  131.    strcpy(autoparse, buff);
  132.  
  133.    /* Get hold of the current element */
  134.    p = lxxquer("CONTENT", result);
  135.    i = lxxqnum("POSITION");
  136.    if (i > strlen(p) + 1)
  137.       noword = 1;
  138.    else if (lxcmd("BLOCK SET CHARACTER WORD") != 0)            /* mark the current word */
  139.       noword = 1;                                        /* can't find a word */
  140.    else {
  141.       lxcmd("BLOCK FIND");
  142.       offset = lxxqnum("POSITION") - 1;
  143.       q = p + offset;                            /* q points to start of word */
  144.       lxcmd("BLOCK FIND END");
  145.       i = lxxqnum("POSITION");
  146.       r = p + i;                        /* r points to char after end of word */
  147.       lxcmd("BLOCK CLEAR");
  148.       lxcall("SET", blockdefaulttype);
  149.  
  150.       if ((i = r - q) > 30)                            /* variable max length */
  151.          return 0;
  152.       s = quer + strlen(quer);
  153.  
  154.       memcpy(s, q, i);                               /* set up variable query */
  155.       memset(s+i, '\0', 1);
  156.       s = lxxquer(quer, buff);                               /* and get value */
  157.       noword = (*s == '\0');                      /* there isn't one, so exit */
  158.       }
  159.  
  160.    if (noword) {
  161.       /* lxcmd("MSG PROTO - cursor is not positioned on a prototype word."); */
  162.       lxcmd("ALARM");
  163.       return 0;
  164.       }
  165.  
  166.    lxcmd("SET AUTOPARSE OFF");
  167.    lxcmd("MARK SET PROTO.001");                  /* remember start of changes */
  168.    join1 = join2 = 0;
  169.    if (q != p) {                                        /* if preceding text: */
  170.       *q = '\0';
  171.       lxcall("INSERT", p);                              /*    insert before   */
  172.       join1 = 1;
  173.       }
  174.    if (*r != '\0') {                                    /* if following text: */
  175.       lxcall("INSERT", r);                              /*    insert after    */
  176.       join2 = 1;
  177.       lxcmd("PREV");
  178.       }
  179.  
  180.    cnt = 0;
  181.  
  182.    q = s; while (*q == BLANK) ++q;                      /* skip over blank(s) */
  183.    delim = *q++;                               /* get and skip over delimiter */
  184.  
  185.    k = 0;
  186.    p = newl;                               /* first line doesn't have padding */
  187.    while (*q != '\0') {                            /* while pattern not ended */
  188.       if (cnt == 1) {                            /* later lines do get padded */
  189.          memset(newl, BLANK, offset);                    /* pad start of line */
  190.          p = newl + offset;
  191.          }
  192.       r = p;
  193.       while (*q != delim && *q != '\0') {         /* for each line in pattern */
  194.          if (k == 0 && *q == '?') {                     /* if it is first "?" */
  195.             k = r - p + 1;                              /*   remember it      */
  196.             }
  197.          *r++ = *q++;
  198.          }
  199.       *r = '\0';
  200.       lxcall("INSERT", newl);                                  /* insert line */
  201.       if (cnt == 0 && join1 == 1) {                 /* join to preceding text */
  202.          lxcmd("PREV");
  203.          lxcmd("SPLITJOIN JOIN");
  204.          }
  205.       if (k > 0) {                                      /* if a "?" was found */
  206.          sprintf(posi, "SET POSITION %u", offset + k);
  207.          lxcmd(posi);                                     /* put cursor there */
  208.          lxcmd("MARK SET PROTO.002");                        /* note position */
  209.          k = -1;                              /* indicate mark 2 has been set */
  210.          }
  211.       if (*q == delim) ++q;                                 /* skip delimiter */
  212.       ++cnt;
  213.       }
  214.    if (join2 == 1) {                     /* join last line to succeeding text */
  215.       lxcmd("SPLITJOIN JOIN");
  216.       }
  217.  
  218.    /* go back to original line and delete it */
  219.    lxcmd("MARK FIND PROTO.001");
  220.    lxcmd("MARK CLEAR PROTO.001");
  221.    lxcmd("DELETE");
  222.    if (k < 0) {                                              /* "?" was found */
  223.       lxcmd("MARK FIND PROTO.002");                    /* so put cursor there */
  224.       lxcmd("MARK CLEAR PROTO.002");
  225.       }
  226.    lxcall("SET", autoparse);                         /* reset autoparse state */
  227.  
  228.    return 0;
  229. }
  230.