home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / SLAKWARE / D10 / TOOLS.TGZ / TOOLS.tar / usr / doc / tools-2.17 / example / editline.c < prev    next >
C/C++ Source or Header  |  1993-02-05  |  23KB  |  1,383 lines

  1. /*  $Revision: 1.4 $
  2. **
  3. **  Main editing routines for editline library.
  4. */
  5. #include "editline.h"
  6. #include <ctype.h>
  7.  
  8. extern const char version_string[];
  9.  
  10. const char * string = version_string+2;
  11. /*
  12. **  Manifest constants.
  13. */
  14. #define SCREEN_WIDTH    80
  15. #define SCREEN_ROWS    24
  16. #define NO_ARG        (-1)
  17. #define DEL        127
  18. #define CTL(x)        ((x) & 0x1F)
  19. #define ISCTL(x)    ((x) && (x) < ' ')
  20. #define UNCTL(x)    ((x) + 64)
  21. #define META(x)        ((x) | 0x80)
  22. #define ISMETA(x)    ((x) & 0x80)
  23. #define UNMETA(x)    ((x) & 0x7F)
  24. #if    !defined(HIST_SIZE)
  25. #define HIST_SIZE    20
  26. #endif    /* !defined(HIST_SIZE) */
  27.  
  28. /*
  29. **  Command status codes.
  30. */
  31. typedef enum _STATUS {
  32.     CSdone, CSeof, CSmove, CSdispatch, CSstay
  33. } STATUS;
  34.  
  35. /*
  36. **  The type of case-changing to perform.
  37. */
  38. typedef enum _CASE {
  39.     TOupper, TOlower
  40. } CASE;
  41.  
  42. /*
  43. **  Key to command mapping.
  44. */
  45. typedef struct _KEYMAP {
  46.     CHAR    Key;
  47.     STATUS    (*Function)();
  48. } KEYMAP;
  49.  
  50. /*
  51. **  Command history structure.
  52. */
  53. typedef struct _HISTORY {
  54.     int        Size;
  55.     int        Pos;
  56.     CHAR    *Lines[HIST_SIZE];
  57. } HISTORY;
  58.  
  59. /*
  60. **  Globals.
  61. */
  62. int        rl_eof;
  63. int        rl_erase;
  64. int        rl_intr;
  65. int        rl_kill;
  66.  
  67. STATIC CHAR        NIL[] = "";
  68. STATIC CONST CHAR    *Input = NIL;
  69. STATIC CHAR        *Line;
  70. STATIC CONST char    *Prompt;
  71. STATIC CHAR        *Yanked;
  72. STATIC char        *Screen;
  73. STATIC char        NEWLINE[]= CRLF;
  74. STATIC HISTORY        H;
  75. int        rl_quit;
  76. STATIC int        Repeat;
  77. STATIC int        End;
  78. STATIC int        Mark;
  79. STATIC int        OldPoint;
  80. STATIC int        Point;
  81. STATIC int        PushBack;
  82. STATIC int        Pushed;
  83. FORWARD KEYMAP        Map[33];
  84. FORWARD KEYMAP        MetaMap[16];
  85. STATIC SIZE_T        Length;
  86. STATIC SIZE_T        ScreenCount;
  87. STATIC SIZE_T        ScreenSize;
  88. STATIC char        *backspace;
  89. STATIC int        TTYwidth;
  90. STATIC int        TTYrows;
  91.  
  92. /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
  93. int        rl_meta_chars = 1;
  94.  
  95. /*
  96. **  Declarations.
  97. */
  98. STATIC CHAR    *editinput();
  99. extern int    read();
  100. extern int    write();
  101. #if    defined(USE_TERMCAP)
  102. extern char    *getenv();
  103. extern char    *tgetstr();
  104. extern int    tgetent();
  105. #endif    /* defined(USE_TERMCAP) */
  106.  
  107. /*
  108. **  TTY input/output functions.
  109. */
  110.  
  111. STATIC void
  112. TTYflush()
  113. {
  114.     if (ScreenCount) {
  115.     (void)write(1, Screen, ScreenCount);
  116.     ScreenCount = 0;
  117.     }
  118. }
  119.  
  120. STATIC void
  121. TTYput(c)
  122.     CHAR    c;
  123. {
  124.     Screen[ScreenCount] = c;
  125.     if (++ScreenCount >= ScreenSize - 1) {
  126.     ScreenSize += SCREEN_INC;
  127.     RENEW(Screen, char, ScreenSize);
  128.     }
  129. }
  130.  
  131. STATIC void
  132. TTYputs(p)
  133.     CHAR    *p;
  134. {
  135.     while (*p)
  136.     TTYput(*p++);
  137. }
  138.  
  139. STATIC void
  140. TTYshow(c)
  141.     CHAR    c;
  142. {
  143.     if (c == DEL) {
  144.     TTYput('^');
  145.     TTYput('?');
  146.     }
  147.     else if (ISCTL(c)) {
  148.     TTYput('^');
  149.     TTYput(UNCTL(c));
  150.     }
  151.     else if (rl_meta_chars && ISMETA(c)) {
  152.     TTYput('M');
  153.     TTYput('-');
  154.     TTYput(UNMETA(c));
  155.     }
  156.     else
  157.     TTYput(c);
  158. }
  159.  
  160. STATIC void
  161. TTYstring(p)
  162.     CHAR    *p;
  163. {
  164.     while (*p)
  165.     TTYshow(*p++);
  166. }
  167.  
  168. STATIC unsigned int
  169. TTYget()
  170. {
  171.     CHAR    c;
  172.  
  173.     TTYflush();
  174.     if (Pushed) {
  175.     Pushed = 0;
  176.     return PushBack;
  177.     }
  178.     if (*Input)
  179.     return *Input++;
  180.     return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
  181. }
  182.  
  183. #define TTYback()    (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
  184.  
  185. STATIC void
  186. TTYbackn(n)
  187.     int        n;
  188. {
  189.     while (--n >= 0)
  190.     TTYback();
  191. }
  192.  
  193. STATIC void
  194. TTYinfo()
  195. {
  196.     static int        init;
  197. #if    defined(USE_TERMCAP)
  198.     char        *term;
  199.     char        buff[2048];
  200.     char        *bp;
  201. #endif    /* defined(USE_TERMCAP) */
  202. #if    defined(TIOCGWINSZ)
  203.     struct winsize    W;
  204. #endif    /* defined(TIOCGWINSZ) */
  205.  
  206.     if (init) {
  207. #if    defined(TIOCGWINSZ)
  208.     /* Perhaps we got resized. */
  209.     if (ioctl(0, TIOCGWINSZ, &W) >= 0
  210.      && W.ws_col > 0 && W.ws_row > 0) {
  211.         TTYwidth = (int)W.ws_col;
  212.         TTYrows = (int)W.ws_row;
  213.     }
  214. #endif    /* defined(TIOCGWINSZ) */
  215.     return;
  216.     }
  217.     init++;
  218.  
  219.     TTYwidth = TTYrows = 0;
  220. #if    defined(USE_TERMCAP)
  221.     bp = &buff[0];
  222.     if ((term = getenv("TERM")) == NULL)
  223.     term = "dumb";
  224.     if (tgetent(buff, term) < 0) {
  225.        TTYwidth = SCREEN_WIDTH;
  226.        TTYrows = SCREEN_ROWS;
  227.        return;
  228.     }
  229.     backspace = tgetstr("le", &bp);
  230.     TTYwidth = tgetnum("co");
  231.     TTYrows = tgetnum("li");
  232. #endif    /* defined(USE_TERMCAP) */
  233.  
  234. #if    defined(TIOCGWINSZ)
  235.     if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
  236.     TTYwidth = (int)W.ws_col;
  237.     TTYrows = (int)W.ws_row;
  238.     }
  239. #endif    /* defined(TIOCGWINSZ) */
  240.  
  241.     if (TTYwidth <= 0 || TTYrows <= 0) {
  242.     TTYwidth = SCREEN_WIDTH;
  243.     TTYrows = SCREEN_ROWS;
  244.     }
  245. }
  246.  
  247.  
  248. /*
  249. **  Print an array of words in columns.
  250. */
  251. STATIC void
  252. columns(ac, av)
  253.     int        ac;
  254.     CHAR    **av;
  255. {
  256.     CHAR    *p;
  257.     int        i;
  258.     int        j;
  259.     int        k;
  260.     int        len;
  261.     int        skip;
  262.     int        longest;
  263.     int        cols;
  264.  
  265.     /* Find longest name, determine column count from that. */
  266.     for (longest = 0, i = 0; i < ac; i++)
  267.     if ((j = strlen((char *)av[i])) > longest)
  268.         longest = j;
  269.     cols = TTYwidth / (longest + 3);
  270.  
  271.     TTYputs((CHAR *)NEWLINE);
  272.     for (skip = ac / cols + 1, i = 0; i < skip; i++) {
  273.     for (j = i; j < ac; j += skip) {
  274.         for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
  275.         TTYput(*p);
  276.         if (j + skip < ac)
  277.         while (++len < longest + 3)
  278.             TTYput(' ');
  279.     }
  280.     TTYputs((CHAR *)NEWLINE);
  281.     }
  282. }
  283.  
  284. STATIC void
  285. reposition()
  286. {
  287.     int        i;
  288.     CHAR    *p;
  289.  
  290.     TTYput('\r');
  291.     TTYputs((CHAR *)Prompt);
  292.     for (i = Point, p = Line; --i >= 0; p++)
  293.     TTYshow(*p);
  294. }
  295.  
  296. STATIC void
  297. left(Change)
  298.     STATUS    Change;
  299. {
  300.     TTYback();
  301.     if (Point) {
  302.     if (ISCTL(Line[Point - 1]))
  303.         TTYback();
  304.         else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
  305.         TTYback();
  306.         TTYback();
  307.     }
  308.     }
  309.     if (Change == CSmove)
  310.     Point--;
  311. }
  312.  
  313. STATIC void
  314. right(Change)
  315.     STATUS    Change;
  316. {
  317.     TTYshow(Line[Point]);
  318.     if (Change == CSmove)
  319.     Point++;
  320. }
  321.  
  322. STATIC STATUS
  323. ring_bell()
  324. {
  325.     TTYput('\07');
  326.     TTYflush();
  327.     return CSstay;
  328. }
  329.  
  330. STATIC STATUS
  331. do_macro(c)
  332.     unsigned int    c;
  333. {
  334.     CHAR        name[4];
  335.  
  336.     name[0] = '_';
  337.     name[1] = c;
  338.     name[2] = '_';
  339.     name[3] = '\0';
  340.  
  341.     if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
  342.     Input = NIL;
  343.     return ring_bell();
  344.     }
  345.     return CSstay;
  346. }
  347.  
  348. STATIC STATUS
  349. do_forward(move)
  350.     STATUS    move;
  351. {
  352.     int        i;
  353.     CHAR    *p;
  354.  
  355.     i = 0;
  356.     do {
  357.     p = &Line[Point];
  358.     for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
  359.         if (move == CSmove)
  360.         right(CSstay);
  361.  
  362.     for (; Point < End && isalnum(*p); Point++, p++)
  363.         if (move == CSmove)
  364.         right(CSstay);
  365.  
  366.     if (Point == End)
  367.         break;
  368.     } while (++i < Repeat);
  369.  
  370.     return CSstay;
  371. }
  372.  
  373. STATIC STATUS
  374. do_case(type)
  375.     CASE    type;
  376. {
  377.     int        i;
  378.     int        end;
  379.     int        count;
  380.     CHAR    *p;
  381.  
  382.     (void)do_forward(CSstay);
  383.     if (OldPoint != Point) {
  384.     if ((count = Point - OldPoint) < 0)
  385.         count = -count;
  386.     Point = OldPoint;
  387.     if ((end = Point + count) > End)
  388.         end = End;
  389.     for (i = Point, p = &Line[i]; i < end; i++, p++) {
  390.         if (type == TOupper) {
  391.         if (islower(*p))
  392.             *p = toupper(*p);
  393.         }
  394.         else if (isupper(*p))
  395.         *p = tolower(*p);
  396.         right(CSmove);
  397.     }
  398.     }
  399.     return CSstay;
  400. }
  401.  
  402. STATIC STATUS
  403. case_down_word()
  404. {
  405.     return do_case(TOlower);
  406. }
  407.  
  408. STATIC STATUS
  409. case_up_word()
  410. {
  411.     return do_case(TOupper);
  412. }
  413.  
  414. STATIC void
  415. ceol()
  416. {
  417.     int        extras;
  418.     int        i;
  419.     CHAR    *p;
  420.  
  421.     for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
  422.     TTYput(' ');
  423.     if (ISCTL(*p)) {
  424.         TTYput(' ');
  425.         extras++;
  426.     }
  427.     else if (rl_meta_chars && ISMETA(*p)) {
  428.         TTYput(' ');
  429.         TTYput(' ');
  430.         extras += 2;
  431.     }
  432.     }
  433.  
  434.     for (i += extras; i > Point; i--)
  435.     TTYback();
  436. }
  437.  
  438. STATIC void
  439. clear_line()
  440. {
  441.     Point = -strlen(Prompt);
  442.     TTYput('\r');
  443.     ceol();
  444.     Point = 0;
  445.     End = 0;
  446.     Line[0] = '\0';
  447. }
  448.  
  449. STATIC STATUS
  450. insert_string(p)
  451.     CHAR    *p;
  452. {
  453.     SIZE_T    len;
  454.     int        i;
  455.     CHAR    *new;
  456.     CHAR    *q;
  457.  
  458.     len = strlen((char *)p);
  459.     if (End + len >= Length) {
  460.     if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
  461.         return CSstay;
  462.     if (Length) {
  463.         COPYFROMTO(new, Line, Length);
  464.         DISPOSE(Line);
  465.     }
  466.     Line = new;
  467.     Length += len + MEM_INC;
  468.     }
  469.  
  470.     for (q = &Line[Point], i = End - Point; --i >= 0; )
  471.     q[len + i] = q[i];
  472.     COPYFROMTO(&Line[Point], p, len);
  473.     End += len;
  474.     Line[End] = '\0';
  475.     TTYstring(&Line[Point]);
  476.     Point += len;
  477.  
  478.     return Point == End ? CSstay : CSmove;
  479. }
  480.  
  481.  
  482. STATIC CHAR *
  483. next_hist()
  484. {
  485.     return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
  486. }
  487.  
  488. STATIC CHAR *
  489. prev_hist()
  490. {
  491.     return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
  492. }
  493.  
  494. STATIC STATUS
  495. do_insert_hist(p)
  496.     CHAR    *