home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / git-4.3 / git-4 / git-4.3.11 / src / inputline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  19.6 KB  |  1,106 lines

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