search.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* search.c - code for non-incremental searching in emacs and vi modes. */
  2. /* Copyright (C) 1992 Free Software Foundation, Inc.
  3.    This file is part of the Readline Library (the Library), a set of
  4.    routines for providing Emacs style line input to programs that ask
  5.    for it.
  6.    The Library is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 1, or (at your option)
  9.    any later version.
  10.    The Library is distributed in the hope that it will be useful, but
  11.    WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.    General Public License for more details.
  14.    The GNU General Public License is often shipped with GNU software, and
  15.    is generally kept in a file called COPYING or LICENSE.  If you do not
  16.    have a copy of the license, write to the Free Software Foundation,
  17.    675 Mass Ave, Cambridge, MA 02139, USA. */
  18. #define READLINE_LIBRARY
  19. #if defined (HAVE_CONFIG_H)
  20. #  include <config.h>
  21. #endif
  22. #include <sys/types.h>
  23. #include <stdio.h>
  24. #if defined (HAVE_UNISTD_H)
  25. #  include <unistd.h>
  26. #endif
  27. #if defined (HAVE_STDLIB_H)
  28. #  include <stdlib.h>
  29. #else
  30. #  include "ansi_stdlib.h"
  31. #endif
  32. #include "rldefs.h"
  33. #include "readline.h"
  34. #include "history.h"
  35. #ifdef abs
  36. #  undef abs
  37. #endif
  38. #define abs(x) (((x) >= 0) ? (x) : -(x))
  39. extern char *xmalloc (), *xrealloc ();
  40. /* Variables imported from readline.c */
  41. extern int rl_point, rl_end, rl_line_buffer_len;
  42. extern int rl_editing_mode;
  43. extern char *rl_prompt;
  44. extern char *rl_line_buffer;
  45. extern HIST_ENTRY *saved_line_for_history;
  46. extern Function *rl_last_func;
  47. /* Functions imported from the rest of the library. */
  48. extern int _rl_free_history_entry ();
  49. extern char *_rl_make_prompt_for_search ();
  50. extern void rl_extend_line_buffer ();
  51. static char *noninc_search_string = (char *) NULL;
  52. static int noninc_history_pos;
  53. static char *prev_line_found = (char *) NULL;
  54. /* Search the history list for STRING starting at absolute history position
  55.    POS.  If STRING begins with `^', the search must match STRING at the
  56.    beginning of a history line, otherwise a full substring match is performed
  57.    for STRING.  DIR < 0 means to search backwards through the history list,
  58.    DIR >= 0 means to search forward. */
  59. static int
  60. noninc_search_from_pos (string, pos, dir)
  61.      char *string;
  62.      int pos, dir;
  63. {
  64.   int ret, old;
  65.   old = where_history ();
  66.   history_set_pos (pos);
  67.   if (*string == '^')
  68.     ret = history_search_prefix (string + 1, dir);
  69.   else
  70.     ret = history_search (string, dir);
  71.   if (ret != -1)
  72.     ret = where_history ();
  73.   history_set_pos (old);
  74.   return (ret);
  75. }
  76. /* Search for a line in the history containing STRING.  If DIR is < 0, the
  77.    search is backwards through previous entries, else through subsequent
  78.    entries. */
  79. static void
  80. noninc_dosearch (string, dir)
  81.      char *string;
  82.      int dir;
  83. {
  84.   int oldpos, pos, line_len;
  85.   HIST_ENTRY *entry;
  86.   if (string == 0 || *string == '' || noninc_history_pos < 0)
  87.     {
  88.       ding ();
  89.       return;
  90.     }
  91.   pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
  92.   if (pos == -1)
  93.     {
  94.       /* Search failed, current history position unchanged. */
  95.       maybe_unsave_line ();
  96.       rl_clear_message ();
  97.       rl_point = 0;
  98.       ding ();
  99.       return;
  100.     }
  101.   noninc_history_pos = pos;
  102.   oldpos = where_history ();
  103.   history_set_pos (noninc_history_pos);
  104.   entry = current_history ();
  105. #if defined (VI_MODE)
  106.   if (rl_editing_mode != vi_mode)
  107. #endif
  108.   history_set_pos (oldpos);
  109.   line_len = strlen (entry->line);
  110.   if (line_len >= rl_line_buffer_len)
  111.     rl_extend_line_buffer (line_len);
  112.   strcpy (rl_line_buffer, entry->line);
  113.   rl_undo_list = (UNDO_LIST *)entry->data;
  114.   rl_end = strlen (rl_line_buffer);
  115.   rl_point = 0;
  116.   rl_clear_message ();
  117.   if (saved_line_for_history)
  118.     _rl_free_history_entry (saved_line_for_history);
  119.   saved_line_for_history = (HIST_ENTRY *)NULL;
  120. }
  121. /* Search non-interactively through the history list.  DIR < 0 means to
  122.    search backwards through the history of previous commands; otherwise
  123.    the search is for commands subsequent to the current position in the
  124.    history list.  PCHAR is the character to use for prompting when reading
  125.    the search string; if not specified (0), it defaults to `:'. */
  126. static void
  127. noninc_search (dir, pchar)
  128.      int dir;
  129.      int pchar;
  130. {
  131.   int saved_point, c;
  132.   char *p;
  133.   maybe_save_line ();
  134.   saved_point = rl_point;
  135.   /* Use the line buffer to read the search string. */
  136.   rl_line_buffer[0] = 0;
  137.   rl_end = rl_point = 0;
  138.   p = _rl_make_prompt_for_search (pchar ? pchar : ':');
  139.   rl_message (p, 0, 0);
  140.   free (p);
  141. #define SEARCH_RETURN rl_restore_prompt (); return
  142.   /* Read the search string. */
  143.   while ((c = rl_read_key ()))
  144.     {
  145.       switch (c)
  146. {
  147. case CTRL('H'):
  148. case RUBOUT:
  149.   if (rl_point == 0)
  150.     {
  151.       maybe_unsave_line ();
  152.       rl_clear_message ();
  153.       rl_point = saved_point;
  154.       SEARCH_RETURN;
  155.     }
  156.   rl_rubout (1, c);
  157.   break;
  158. case CTRL('W'):
  159.   rl_unix_word_rubout (1, c);
  160.   break;
  161. case CTRL('U'):
  162.   rl_unix_line_discard (1, c);
  163.   break;
  164. case RETURN:
  165. case NEWLINE:
  166.   goto dosearch;
  167.   /* NOTREACHED */
  168.   break;
  169. case CTRL('C'):
  170. case CTRL('G'):
  171.   maybe_unsave_line ();
  172.   rl_clear_message ();
  173.   rl_point = saved_point;
  174.   ding ();
  175.   SEARCH_RETURN;
  176. default:
  177.   rl_insert (1, c);
  178.   break;
  179. }
  180.       (*rl_redisplay_function) ();
  181.     }
  182.  dosearch:
  183.   /* If rl_point == 0, we want to re-use the previous search string and
  184.      start from the saved history position.  If there's no previous search
  185.      string, punt. */
  186.   if (rl_point == 0)
  187.     {
  188.       if (!noninc_search_string)
  189. {
  190.   ding ();
  191.   SEARCH_RETURN;
  192. }
  193.     }
  194.   else
  195.     {
  196.       /* We want to start the search from the current history position. */
  197.       noninc_history_pos = where_history ();
  198.       if (noninc_search_string)
  199. free (noninc_search_string);
  200.       noninc_search_string = savestring (rl_line_buffer);
  201.     }
  202.   rl_restore_prompt ();
  203.   noninc_dosearch (noninc_search_string, dir);
  204. }
  205. /* Search forward through the history list for a string.  If the vi-mode
  206.    code calls this, KEY will be `?'. */
  207. int
  208. rl_noninc_forward_search (count, key)
  209.      int count, key;
  210. {
  211.   noninc_search (1, (key == '?') ? '?' : 0);
  212.   return 0;
  213. }
  214. /* Reverse search the history list for a string.  If the vi-mode code
  215.    calls this, KEY will be `/'. */
  216. int
  217. rl_noninc_reverse_search (count, key)
  218.      int count, key;
  219. {
  220.   noninc_search (-1, (key == '/') ? '/' : 0);
  221.   return 0;
  222. }
  223. /* Search forward through the history list for the last string searched
  224.    for.  If there is no saved search string, abort. */
  225. int
  226. rl_noninc_forward_search_again (count, key)
  227.      int count, key;
  228. {
  229.   if (!noninc_search_string)
  230.     {
  231.       ding ();
  232.       return (-1);
  233.     }
  234.   noninc_dosearch (noninc_search_string, 1);
  235.   return 0;
  236. }
  237. /* Reverse search in the history list for the last string searched
  238.    for.  If there is no saved search string, abort. */
  239. int
  240. rl_noninc_reverse_search_again (count, key)
  241.      int count, key;
  242. {
  243.   if (!noninc_search_string)
  244.     {
  245.       ding ();
  246.       return (-1);
  247.     }
  248.   noninc_dosearch (noninc_search_string, -1);
  249.   return 0;
  250. }
  251. static int
  252. rl_history_search_internal (count, direction)
  253.      int count, direction;
  254. {
  255.   HIST_ENTRY *temp, *old_temp;
  256.   int line_len;
  257.   maybe_save_line ();
  258.   temp = old_temp = (HIST_ENTRY *)NULL;
  259.   while (count)
  260.     {
  261.       temp = (direction < 0) ? previous_history () : next_history ();
  262.       if (temp == 0)
  263.         break;
  264.       /* On an empty prefix, make this the same as previous-history. */
  265.       if (rl_point == 0)
  266. {
  267.   count--;
  268.   continue;
  269. }
  270.       if (STREQN (rl_line_buffer, temp->line, rl_point))
  271. {
  272.   /* Don't find multiple instances of the same line. */
  273.   if (prev_line_found && STREQ (prev_line_found, temp->line))
  274.     continue;
  275.           if (direction < 0)
  276.             old_temp = temp;
  277.           prev_line_found = temp->line;
  278.           count--;
  279. }
  280.     }
  281.   if (temp == 0)
  282.     {
  283.       if (direction < 0 && old_temp)
  284. temp = old_temp;
  285.       else
  286. {
  287.   maybe_unsave_line ();
  288.   ding ();
  289.   return 1;
  290. }
  291.     }
  292.   line_len = strlen (temp->line);
  293.   if (line_len >= rl_line_buffer_len)
  294.     rl_extend_line_buffer (line_len);
  295.   strcpy (rl_line_buffer, temp->line);
  296.   rl_undo_list = (UNDO_LIST *)temp->data;
  297.   rl_end = line_len;
  298.   return 0;
  299. }
  300. /* Search forward in the history for the string of characters
  301.    from the start of the line to rl_point.  This is a non-incremental
  302.    search. */
  303. int
  304. rl_history_search_forward (count, ignore)
  305.      int count, ignore;
  306. {
  307.   if (count == 0)
  308.     return (0);
  309.   if (rl_last_func != rl_history_search_forward)
  310.     prev_line_found = (char *)NULL;
  311.   return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
  312. }
  313. /* Search backward through the history for the string of characters
  314.    from the start of the line to rl_point.  This is a non-incremental
  315.    search. */
  316. int
  317. rl_history_search_backward (count, ignore)
  318.      int count, ignore;
  319. {
  320.   if (count == 0)
  321.     return (0);
  322.   if (rl_last_func != rl_history_search_backward)
  323.     prev_line_found = (char *)NULL;
  324.   return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
  325. }