home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / git-4.3 / git-4 / git-4.3.7 / src / inputline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-08  |  19.4 KB  |  918 lines

  1. /* inputline.c -- input line management functions. */
  2.  
  3. /* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* Written by Tudor Hulubei and Andrei Pitis.  */
  20.  
  21.  
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25.  
  26. #include <stdio.h>
  27.  
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #else /* !HAVE_STDLIB_H */
  31. #include "ansi_stdlib.h"
  32. #endif /* !HAVE_STDLIB_H */
  33.  
  34. #include "xstring.h"
  35. #include "xmalloc.h"
  36. #include "configure.h"
  37. #include "history.h"
  38. #include "tty.h"
  39. #include "window.h"
  40. #include "inputline.h"
  41. #include "tilde.h"
  42. #include "misc.h"
  43.  
  44.  
  45. extern int  AnsiColorSequences;
  46.  
  47.  
  48. #define MAX_INPUT_HISTORY       512     /* big enough I suppose ... */
  49.  
  50.  
  51. #define INPUTLINE_FIELDS        6
  52.  
  53. static char *InputLineFields[INPUTLINE_FIELDS] =
  54. {
  55.     "InputLineForeground",
  56.     "InputLineBackground",
  57.     "InputLineBrightness",
  58.     "InputLineErrorForeground",
  59.     "InputLineErrorBackground",
  60.     "InputLineErrorBrightness",
  61. };
  62.  
  63. #ifdef HAVE_LINUX
  64. static int InputLineColors[INPUTLINE_FIELDS] =
  65. {
  66.     WHITE, BLACK, ON, RED, BLACK, ON
  67. };
  68. #else   /* !HAVE_LINUX */
  69. static int InputLineColors[INPUTLINE_FIELDS] =
  70. {
  71.     WHITE, BLACK, ON, WHITE, BLACK, ON
  72. };
  73. #endif  /* !HAVE_LINUX */
  74.  
  75. #define InputLineForeground             InputLineColors[0]
  76. #define InputLineBackground             InputLineColors[1]
  77. #define InputLineBrightness             InputLineColors[2]
  78. #define InputLineErrorForeground        InputLineColors[3]
  79. #define InputLineErrorBackground        InputLineColors[4]
  80. #define InputLineErrorBrightness        InputLineColors[5]
  81.  
  82.  
  83. /* Basic input line operations.  */
  84. #define IL_NO_OPERATION                          0
  85. #define IL_BACKWARD_CHAR                         1
  86. #define IL_FORWARD_CHAR                          2
  87. #define IL_BACKWARD_WORD                         3
  88. #define IL_FORWARD_WORD                          4
  89. #define IL_BEGINNING_OF_LINE                     5
  90. #define IL_END_OF_LINE                           6
  91. #define IL_INSERT_CHAR                           7
  92. #define IL_DELETE_CHAR                           8
  93. #define IL_BACKWARD_DELETE_CHAR                  9
  94. #define IL_BACKWARD_KILL_WORD                   10
  95. #define IL_RESET_LINE                           11
  96. #define IL_KILL_LINE                            12
  97. #define IL_KILL_TO_BEGINNING_OF_LINE            13
  98. #define IL_KILL_TO_END_OF_LINE                  14
  99. #define IL_JUST_ONE_SPACE                       15
  100. #define IL_DELETE_HORIZONTAL_SPACE              16
  101. #define IL_SET_STATIC_TEXT                      17
  102. #define IL_INSERT_TEXT                          18
  103. #define IL_SET_MARK                             19
  104. #define IL_KILL_REGION                          20
  105. #define IL_KILL_RING_SAVE                       21
  106. #define IL_YANK                                 22
  107. #define IL_EXCHANGE_POINT_AND_MARK              23
  108.  
  109.  
  110. #define IL_HORIZONTAL_SCROLL                    20
  111.  
  112.  
  113. #define IL_RESIZE(il_new_buffer_size)                   \
  114. {                                                       \
  115.     il->size   = il_new_buffer_size;                    \
  116.     il->buffer = xrealloc(il->buffer, il->size);        \
  117. }
  118.  
  119.  
  120. /* The input line.  */
  121. input_line_t *il = NULL;
  122.  
  123.  
  124. /* Check if 'c' is a separator.  */
  125.  
  126. static int
  127. il_separator(c)
  128.     char c;
  129. {
  130.     if ((c >= 'a' && c <= 'z') ||
  131.         (c >= 'A' && c <= 'Z') ||
  132.         (c >= '0' && c <= '9') ||
  133.         (c == '$')             ||
  134.         (c == '%'))
  135.         return 0;
  136.     else
  137.         return 1;
  138. }
  139.  
  140.  
  141. /* Store the text between the mark and the point into the kill_ring if
  142.    flags & IL_STORE.  Kill it if flags & IL_KILL.  */
  143.  
  144. static void
  145. il_region_command(flags)
  146.     int flags;
  147. {
  148.     size_t region_start;
  149.     size_t region_end;
  150.     size_t region_size;
  151.  
  152.  
  153.     /* If the region is empty, preserve the previous kill_ring.  */
  154.     if (il->mark == il->point)
  155.         return;
  156.  
  157.     /* Get the region limits.  */
  158.     if (il->mark > il->point)
  159.     {
  160.         region_start = il->point;
  161.         region_end   = il->mark;
  162.     }
  163.     else
  164.     {
  165.         region_start = il->mark;
  166.         region_end   = il->point;
  167.     }
  168.  
  169.     region_size = region_end - region_start;
  170.  
  171.     if (flags & IL_STORE)
  172.     {
  173.         if (il->kill_ring)
  174.             xfree(il->kill_ring);
  175.  
  176.         il->kill_ring = xmalloc(region_size + 1);
  177.         memcpy(il->kill_ring, il->buffer + region_start, region_size);
  178.         il->kill_ring[region_size] = '\0';
  179.     }
  180.  
  181.     if (flags & IL_KILL)
  182.     {
  183.         il->dynamic_length -= region_size;
  184.         il->length         -= region_size;
  185.         il->point           = region_start;
  186.         il->mark            = region_start;
  187.         strcpy(il->buffer + region_start, il->buffer + region_end);
  188.         IL_RESIZE(il->length + 1);
  189.     }
  190. }
  191.  
  192.  
  193. /* Free an input line structure.  */
  194.  
  195. void
  196. il_free(some_il)
  197.     input_line_t *some_il;
  198. {
  199.     if (some_il == NULL)
  200.         return;
  201.  
  202.     if (some_il->buffer)
  203.         xfree(some_il->buffer);
  204.  
  205.     if (some_il->kill_ring)
  206.         xfree(some_il->kill_ring);
  207.  
  208.     xfree(some_il);
  209. }
  210.  
  211.  
  212. /* The input_line constructor.  */
  213.  
  214. void
  215. il_init(_columns, _begin_y)
  216.     size_t _columns, _begin_y;
  217. {
  218.     char *data;
  219.  
  220.     il = (input_line_t *)xmalloc(sizeof(input_line_t));
  221.  
  222.     il->echo           = 1;
  223.     il->error          = 0;
  224.     il->buffer         = NULL;
  225.     il->kill_ring      = NULL;
  226.     il->columns        = _columns;
  227.     il->last_operation = IL_NO_OPERATION;
  228.  
  229.     il_reset_line();
  230.  
  231.     il->win = window_init(0, _begin_y, 1, _columns);
  232.  
  233.  
  234.     use_section("[GIT-Setup]");
  235.  
  236.     configuration_getvarinfo("HistoryFile", &data, 1, DO_SEEK);
  237.     il->history_file = tilde_expand(data ? data : "~/.githistory");
  238.  
  239.     use_section(AnsiColorSequences ? cSection : bwSection);
  240.  
  241.     get_colorset_var(InputLineColors, InputLineFields, INPUTLINE_FIELDS);
  242.  
  243.  
  244.     /* Initialize the history library stuff...  */
  245.     using_history();
  246.     read_history(il->history_file);
  247.     while (next_history());
  248.     stifle_history(MAX_INPUT_HISTORY);
  249. }
  250.  
  251.  
  252. /* Input line destructor.  */
  253.  
  254. void
  255. il_end()
  256. {
  257.     write_history(il->history_file);
  258.     window_end(il->win);
  259.  
  260.     il_free(il);
  261.     il = NULL;
  262. }
  263.  
  264.  
  265. /* Save the entire input_line structure.  Returns a pointer to the saved
  266.    structure.  */
  267.  
  268. input_line_t *
  269. il_save()
  270. {
  271.     input_line_t *saved_il = (input_line_t *)xmalloc(sizeof(input_line_t));
  272.  
  273.     *saved_il = *il;
  274.  
  275.     if (saved_il->buffer)
  276.     {
  277.         il->buffer = xmalloc(saved_il->size);
  278.         memcpy(il->buffer, saved_il->buffer, saved_il->size);
  279.     }
  280.  
  281.     if (saved_il->kill_ring)
  282.         il->kill_ring = xstrdup(saved_il->kill_ring);
  283.  
  284.     return saved_il;
  285. }
  286.  
  287.  
  288. /* Restore the input_line.  */
  289.  
  290. void
  291. il_restore(saved_il)
  292.     input_line_t *saved_il;
  293. {
  294.     if (saved_il == NULL)
  295.         return;
  296.  
  297.     il_free(il);
  298.     il = saved_il;
  299. }
  300.  
  301.  
  302. /* Set the echo state.  Returns the previous state of the echo flag.  */
  303. int
  304. il_echo(echo)
  305.     int echo;
  306. {
  307.     int old_echo_flag = il->echo;
  308.  
  309.     il->echo = echo;
  310.     return old_echo_flag;
  311. }
  312.  
  313.  
  314. /* Check if the input line is empty.  */
  315.  
  316. int
  317. il_is_empty()
  318. {
  319.     return il->dynamic_length == 0;
  320. }
  321.  
  322.  
  323. /* Set mark where point is.  */
  324.  
  325. void
  326. il_set_mark()
  327. {
  328.     il->mark = il->point;
  329. }
  330.  
  331.  
  332. /* Kill between point and mark.  The text is deleted but saved in the
  333.    kill ring.  */
  334.  
  335. void
  336. il_kill_region()
  337. {
  338.     il_region_command(IL_STORE | IL_KILL);
  339.     il->last_operation = IL_KILL_REGION;
  340. }
  341.  
  342.  
  343. /* Save the region as if killed, but don't kill it.  */
  344.  
  345. void
  346. il_kill_ring_save()
  347. {
  348.     il_region_command(IL_STORE);
  349.     il->last_operation = IL_KILL_RING_SAVE;
  350. }
  351.  
  352.  
  353. /* Reinsert the last stretch of killed text.  */
  354.  
  355. void
  356. il_yank()
  357. {
  358.     if (il->kill_ring)
  359.     {
  360.         il_insert_text(il->kill_ring);
  361.         il->last_operation = IL_YANK;
  362.     }
  363. }
  364.  
  365.  
  366. /* Exchange point and mark.  */
  367.  
  368. void
  369. il_exchange_point_and_mark()
  370. {
  371.     int point = il->point;
  372.     il->point = il->mark;
  373.     il->mark  = point;
  374. }
  375.  
  376.  
  377. /* Move the point backward one character.  */
  378.  
  379. void
  380. il_backward_char()
  381. {
  382.     if (il->point > il->static_length)
  383.     {
  384.         il->point--;
  385.         il->last_operation = IL_BACKWARD_CHAR;
  386.     }
  387. }
  388.  
  389.  
  390. /* Move the point forward one character.  */
  391.  
  392. void
  393. il_forward_char()
  394. {
  395.     if (il->point < il->length)
  396.     {
  397.         il->point++;
  398.         il->last_operation = IL_FORWARD_CHAR;
  399.     }
  400. }
  401.  
  402.  
  403. /* Move the point backward one word.  */
  404.  
  405. void
  406. il_backward_word()
  407. {
  408.     if (il->point > il->static_length)
  409.     {
  410.         while (il->point > il->static_length &&
  411.                il_separator(il->buffer[il->point - 1]))
  412.             il_backward_char();
  413.  
  414.         while (il->point > il->static_length &&
  415.                !il_separator(il->buffer[il->point - 1]))
  416.             il_backward_char();
  417.  
  418.         il->last_operation = IL_BACKWARD_WORD;
  419.     }
  420. }
  421.  
  422.  
  423. /* Move the point forward one word.  */
  424.  
  425. void
  426. il_forward_word()
  427. {
  428.     if (il->point < il->length)
  429.     {
  430.         while (il->point < il->length &&
  431.                il_separator(il->buffer[il->point]))
  432.             il_forward_char();
  433.  
  434.         while (il->point < il->length &&
  435.                !il_separator(il->buffer[il->point]))
  436.             il_forward_char();
  437.  
  438.         il->last_operation = IL_FORWARD_WORD;
  439.     }
  440. }
  441.  
  442.  
  443. /* Move the point at the beginning of the line.  */
  444.  
  445. void
  446. il_beginning_of_line()
  447. {
  448.     il->point = il->static_length;
  449.  
  450.     il->last_operation = IL_BEGINNING_OF_LINE;
  451. }
  452.  
  453.  
  454. /* Move the point at the end of the line.  */
  455.  
  456. void
  457. il_end_of_line()
  458. {
  459.     il->point = il->length;
  460.  
  461.     il->last_operation = IL_END_OF_LINE;
  462. }
  463.  
  464.  
  465. /* Insert 'c' at the point position.  */
  466.  
  467. void
  468. il_insert_char(c)
  469.     char c;
  470. {
  471.     if (!is_print(c))
  472.         return;
  473.  
  474.     if (il->length + 1 >= il->size)
  475.         IL_RESIZE(il->length + 1 + 32);
  476.  
  477.     memmove(il->buffer + il->point + 1,
  478.             il->buffer + il->point,
  479.             il->length - il->point + 1);
  480.     il->buffer[il->point] = c;
  481.     il->point++;
  482.     il->length++;
  483.     il->dynamic_length++;
  484.  
  485.     il->last_operation = IL_INSERT_CHAR;
  486. }
  487.  
  488.  
  489. /* Delete the character at the point.  */
  490.  
  491. void
  492. il_delete_char()
  493. {
  494.     if (il->point < il->length)
  495.     {
  496.         memcpy(il->buffer + il->point,
  497.                il->buffer + il->point + 1,
  498.                il->length - il->point + 1);
  499.  
  500.         il->length--;
  501.         il->dynamic_length--;
  502.  
  503.         if (il->length % 16 == 0)
  504.             IL_RESIZE(il->length + 1);
  505.  
  506.         il->last_operation = IL_DELETE_CHAR;
  507.     }
  508. }
  509.  
  510.  
  511. /* Delete the character before the point.  */
  512.  
  513. void
  514. il_backward_delete_char()
  515. {
  516.     if (il->point > il->static_length)
  517.     {
  518.         memcpy(il->buffer + il->point - 1,
  519.                il->buffer + il->point,
  520.                il->length - il->point + 1);
  521.  
  522.         il->point--;
  523.         il->length--;
  524.         il->dynamic_length--;
  525.  
  526.         if (il->length % 16 == 0)
  527.             IL_RESIZE(il->length + 1);
  528.  
  529.         il->last_operation = IL_BACKWARD_DELETE_CHAR;
  530.     }
  531. }
  532.  
  533.  
  534. /* Kill characters backward until encountering the end of a word.  */
  535.  
  536. void
  537. il_backward_kill_word()
  538. {
  539.     int old_mark  = il->mark;
  540.     int old_point = il->point;
  541.  
  542.     il_set_mark();
  543.     il_backward_word();
  544.     il_region_command(IL_STORE | IL_KILL);
  545.  
  546.     if (old_mark <= il->point)
  547.         il->mark = old_mark;
  548.     else
  549.         if (old_mark >= old_point)
  550.             il->mark = old_mark - (old_point - il->point);
  551.         else
  552.             il->mark = il->point;
  553.  
  554.     il->last_operation = IL_BACKWARD_KILL_WORD;
  555. }
  556.  
  557.  
  558. /* Delete the entire line (both the static & dynamic parts).  */
  559.  
  560. void
  561. il_reset_line()
  562. {
  563.     il->point          = 0;
  564.     il->mark           = 0;
  565.     il->length         = 0;
  566.     il->static_length  = 0;
  567.     il->dynamic_length = 0;
  568.  
  569.     IL_RESIZE(1);
  570.  
  571.     il->buffer[0] = '\0';
  572.  
  573.     il->last_operation = IL_RESET_LINE;
  574. }
  575.  
  576.  
  577. /* Delete the entire dynamic part of the line.  */
  578.  
  579. void
  580. il_kill_line(store)
  581.     int store;
  582. {
  583.     il_beginning_of_line();
  584.     il_set_mark();
  585.     il_end_of_line();
  586.     il_region_command(store | IL_KILL);
  587.     il->mark = il->point;
  588.  
  589.     il->last_operation = IL_KILL_LINE;
  590. }
  591.  
  592.  
  593. /* Delete the text between the beginning of the line and the point.  */
  594.  
  595. void
  596. il_kill_to_beginning_of_line()
  597. {
  598.     int old_mark = (il->mark <= il->point) ? il->static_length :
  599.                                              il->mark - il->point;
  600.  
  601.     il_set_mark();
  602.     il_beginning_of_line();
  603.     il_region_command(IL_STORE | IL_KILL);
  604.     il->mark = min(old_mark, il->length);
  605.  
  606.     il->last_operation = IL_KILL_TO_BEGINNING_OF_LINE;
  607. }
  608.  
  609.  
  610. /* Delete the text between the point and the end of line.  */
  611.  
  612. void
  613. il_kill_to_end_of_line()
  614.     int old_mark = il->mark;
  615.  
  616.     il_set_mark();
  617.     il_end_of_line();
  618.     il_region_command(IL_STORE | IL_KILL);
  619.     il->mark = min(old_mark, il->length);
  620.  
  621.     il->last_operation = IL_KILL_TO_END_OF_LINE;
  622.  
  623.  
  624. /* Remove all the tabs and spaces arround the point, leaving just one
  625.    space.  */
  626.  
  627. void
  628. il_just_one_space()
  629. {
  630.     if (il->buffer[il->point] == ' ')
  631.     {
  632.         il_delete_horizontal_space();
  633.         il_insert_char(' ');
  634.         il->last_operation = IL_JUST_ONE_SPACE;
  635.     }
  636. }
  637.  
  638.  
  639. /* Remove all the tabs and spaces arround the point.  */
  640.  
  641. void
  642. il_delete_horizontal_space()
  643. {
  644.     if (il->buffer[il->point] == ' ')
  645.     {
  646.         while (il->buffer[il->point] == ' ')
  647.             il_delete_char();
  648.  
  649.         while (il->dynamic_length && il->buffer[il->point - 1] == ' ')
  650.             il_backward_delete_char();
  651.  
  652.         il->last_operation = IL_DELETE_HORIZONTAL_SPACE;
  653.     }
  654. }
  655.  
  656.  
  657. /* Set up the static text at the beginning of the input line.  This text cannot
  658.    be modified by normal editing commands.  */
  659.  
  660. void
  661. il_set_static_text(static_text)
  662.     char *static_text;
  663. {
  664.     size_t len;
  665.  
  666.     if (static_text == NULL)
  667.         return;
  668.  
  669.     len = strlen(static_text);
  670.  
  671.     il->point += len - il->static_length;
  672.     il->mark  += len - il->static_length;
  673.  
  674.     if (len + il->dynamic_length + 1 > il->size)
  675.         IL_RESIZE(len + il->dynamic_length + 1);
  676.  
  677.     memmove(il->buffer + len,
  678.             il->buffer + il->static_length,
  679.             il->dynamic_length + 1);
  680.  
  681.     memcpy(il->buffer, static_text, len);
  682.  
  683.     il->length = (il->static_length = len) + il->dynamic_length;
  684.  
  685.     il->last_operation = IL_SET_STATIC_TEXT;
  686. }
  687.  
  688.  
  689. /* Insert 'text' at the point position.  */
  690.  
  691. void
  692. il_insert_text(text)
  693.     char *text;
  694. {
  695.     size_t len;
  696.  
  697.     if (text == NULL)
  698.         return;
  699.  
  700.     len = strlen(text);
  701.  
  702.     if (il->length + len + 1 > il->size)
  703.         IL_RESIZE(il->size + len + 1 + 32);
  704.  
  705.     memmove(il->buffer + il->point + len,
  706.             il->buffer + il->point,
  707.             il->length - il->point + 1);
  708.  
  709.     memcpy(il->buffer + il->point, text, len);
  710.  
  711.     il->point          += len;
  712.     il->length         += len;
  713.     il->dynamic_length += len;
  714.  
  715.     il->last_operation = IL_INSERT_TEXT;
  716. }
  717.  
  718.  
  719. /* Update the point.  */
  720.  
  721. void
  722. il_update_point()
  723. {
  724.     size_t len;
  725.  
  726.     tty_colors(il->error ? InputLineErrorBrightness : InputLineBrightness,
  727.                il->error ? InputLineErrorForeground : InputLineForeground,
  728.                il->error ? InputLineErrorBackground : InputLineBackground);
  729.  
  730.     len = (il->point >= il->columns) ?
  731.           il->point - il->columns + 1 + (IL_HORIZONTAL_SCROLL - 1) -
  732.           (il->point % IL_HORIZONTAL_SCROLL) : 0;
  733.  
  734.     window_cursormove(il->win, 0, il->point - len);
  735. }
  736.  
  737.  
  738. /* Update the entire input line.  */
  739.  
  740. void
  741. il_update()
  742. {
  743.     char *temp;
  744.     unsigned len;
  745.     tty_status_t status;
  746.     int old_tty_optimization_level;
  747.  
  748.  
  749.     tty_save(&status);
  750.     tty_cursor(OFF);
  751.  
  752.     tty_colors(il->error ? InputLineErrorBrightness : InputLineBrightness,
  753.                il->error ? InputLineErrorForeground : InputLineForeground,
  754.                il->error ? InputLineErrorBackground : InputLineBackground);
  755.  
  756.     len = (il->point >= il->columns) ?
  757.           il->point - il->columns + 1 + (IL_HORIZONTAL_SCROLL - 1) -
  758.           (il->point % IL_HORIZONTAL_SCROLL) : 0;
  759.  
  760.     temp = xmalloc(il->columns);
  761.  
  762.     memset(temp, ' ', il->columns);
  763.  
  764.     if (il->echo)
  765.         memcpy(temp, il->buffer + il->static_length + len,
  766.                min(il->length   - il->static_length - len,
  767.                    il->columns  - il->static_length));
  768.     else
  769.         memset(temp, '*',
  770.                min(il->length   - il->static_length - len,
  771.                    il->columns  - il->static_length));
  772.  
  773.     old_tty_optimization_level = tty_set_optimization_level(1);
  774.     window_cursormove_notify(il->win, 0, 0);
  775.     window_write(il->buffer, il->static_length);
  776.     window_write(temp, il->columns - il->static_length);
  777.     tty_set_optimization_level(old_tty_optimization_level);
  778.  
  779.     xfree(temp);
  780.     tty_restore(&status);
  781. }
  782.  
  783.  
  784. /* Update the entire input line and the point.  */
  785.  
  786. void
  787. il_full_update()
  788. {
  789.     il_update();
  790.     il_update_point();
  791. }
  792.  
  793.  
  794. /* Get the input line contents (only the dynamic part).
  795.    dest is a pointer to a NULL pointer or a pointer to a pointer allocated
  796.    with xmalloc().  */
  797.  
  798. int
  799. il_get_contents(dest)
  800.     char **dest;
  801. {
  802.     *dest = xrealloc(*dest, il->dynamic_length + 1);
  803.     memcpy(*dest, il->buffer + il->static_length, il->dynamic_length + 1);
  804.     return il->dynamic_length;
  805. }
  806.  
  807.  
  808. /* Display a message into the input line.  */
  809.  
  810. void
  811. il_message(message)
  812.     char *message;
  813. {
  814.     il_reset_line();
  815.     il_set_static_text(message ? message : "Wait....");
  816.     il_full_update();
  817. }
  818.  
  819.  
  820. void
  821. il_set_error_flag(flag)
  822.     int flag;
  823. {
  824.     il->error = flag;
  825. }
  826.  
  827.  
  828. /* input_line interface to the history library.  */
  829.  
  830. void
  831. il_history(dir)
  832.     int dir;
  833. {
  834.     static int browsing = 0;
  835.     static int last_history_position;
  836.     HIST_ENTRY *hist;
  837.  
  838.     switch (dir)
  839.     {
  840.         case IL_PREVIOUS:
  841.  
  842.             if (!browsing)
  843.             {
  844.                 browsing = 1;
  845.                 last_history_position = where_history();
  846.             }
  847.  
  848.             if ((hist = previous_history()))
  849.             {
  850.                 il->dynamic_length = strlen(hist->line);
  851.                 il->length         = il->static_length + il->dynamic_length;
  852.                 il->point          = il->length;
  853.  
  854.                 if (il->length + 1 > il->size)
  855.                     IL_RESIZE(il->length + 1);
  856.  
  857.                 strcpy(il->buffer + il->static_length, hist->line);
  858.  
  859.                 il_update();
  860.             }
  861.  
  862.             break;
  863.  
  864.         case IL_NEXT:
  865.  
  866.             if (!browsing)
  867.             {
  868.                 browsing = 1;
  869.                 last_history_position = where_history();
  870.             }
  871.  
  872.             if ((hist = next_history()))
  873.             {
  874.                 il->dynamic_length = strlen(hist->line);
  875.                 il->length         = il->static_length + il->dynamic_length;
  876.                 il->point          = il->length;
  877.  
  878.                 if (il->length + 1 > il->size)
  879.                     IL_RESIZE(il->length + 1);
  880.  
  881.                 strcpy(il->buffer + il->static_length, hist->line);
  882.             }
  883.             else
  884.                 il_kill_line(IL_DONT_STORE);
  885.  
  886.             il_update();
  887.             break;
  888.  
  889.         case IL_RECORD:
  890.  
  891.             if (browsing)
  892.             {
  893.                 history_set_pos(last_history_position);
  894.                 browsing = 0;
  895.             }
  896.  
  897.             if ((hist = previous_history()))
  898.             {
  899.                 if (strcmp(il->buffer + il->static_length, hist->line) != 0)
  900.                 {
  901.                     add_history(il->buffer + il->static_length);
  902.                     next_history();
  903.                 }
  904.             }
  905.             else
  906.                 add_history(il->buffer + il->static_length);
  907.  
  908.             next_history();
  909.             break;
  910.  
  911.         default:
  912.  
  913.             break;
  914.     }
  915. }
  916.