PageRenderTime 66ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/user/mysql/readline/search.c

https://bitbucket.org/thelearninglabs/uclinux-distro-tll-public
C | 373 lines | 265 code | 48 blank | 60 comment | 49 complexity | 62b8cd17b48630f84cdaf3b224d716bd MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-2.0
  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 == '\0' || 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 (int count __attribute__((unused)), int key)
  209. {
  210. noninc_search (1, (key == '?') ? '?' : 0);
  211. return 0;
  212. }
  213. /* Reverse search the history list for a string. If the vi-mode code
  214. calls this, KEY will be `/'. */
  215. int
  216. rl_noninc_reverse_search (int count __attribute__((unused)), int key)
  217. {
  218. noninc_search (-1, (key == '/') ? '/' : 0);
  219. return 0;
  220. }
  221. /* Search forward through the history list for the last string searched
  222. for. If there is no saved search string, abort. */
  223. int
  224. rl_noninc_forward_search_again (int count __attribute__((unused)),
  225. int key __attribute__((unused)))
  226. {
  227. if (!noninc_search_string)
  228. {
  229. ding ();
  230. return (-1);
  231. }
  232. noninc_dosearch (noninc_search_string, 1);
  233. return 0;
  234. }
  235. /* Reverse search in the history list for the last string searched
  236. for. If there is no saved search string, abort. */
  237. int
  238. rl_noninc_reverse_search_again (int count __attribute__((unused)),
  239. int key __attribute__((unused)))
  240. {
  241. if (!noninc_search_string)
  242. {
  243. ding ();
  244. return (-1);
  245. }
  246. noninc_dosearch (noninc_search_string, -1);
  247. return 0;
  248. }
  249. static int
  250. rl_history_search_internal (count, direction)
  251. int count, direction;
  252. {
  253. HIST_ENTRY *temp, *old_temp;
  254. int line_len;
  255. maybe_save_line ();
  256. temp = old_temp = (HIST_ENTRY *)NULL;
  257. while (count)
  258. {
  259. temp = (direction < 0) ? previous_history () : next_history ();
  260. if (temp == 0)
  261. break;
  262. /* On an empty prefix, make this the same as previous-history. */
  263. if (rl_point == 0)
  264. {
  265. count--;
  266. continue;
  267. }
  268. if (STREQN (rl_line_buffer, temp->line, rl_point))
  269. {
  270. /* Don't find multiple instances of the same line. */
  271. if (prev_line_found && STREQ (prev_line_found, temp->line))
  272. continue;
  273. if (direction < 0)
  274. old_temp = temp;
  275. prev_line_found = temp->line;
  276. count--;
  277. }
  278. }
  279. if (temp == 0)
  280. {
  281. if (direction < 0 && old_temp)
  282. temp = old_temp;
  283. else
  284. {
  285. maybe_unsave_line ();
  286. ding ();
  287. return 1;
  288. }
  289. }
  290. line_len = strlen (temp->line);
  291. if (line_len >= rl_line_buffer_len)
  292. rl_extend_line_buffer (line_len);
  293. strcpy (rl_line_buffer, temp->line);
  294. rl_undo_list = (UNDO_LIST *)temp->data;
  295. rl_end = line_len;
  296. return 0;
  297. }
  298. /* Search forward in the history for the string of characters
  299. from the start of the line to rl_point. This is a non-incremental
  300. search. */
  301. int
  302. rl_history_search_forward (int count, int ignore __attribute__((unused)))
  303. {
  304. if (count == 0)
  305. return (0);
  306. if (rl_last_func != rl_history_search_forward)
  307. prev_line_found = (char *)NULL;
  308. return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
  309. }
  310. /* Search backward through the history for the string of characters
  311. from the start of the line to rl_point. This is a non-incremental
  312. search. */
  313. int
  314. rl_history_search_backward (int count, int ignore __attribute__((unused)))
  315. {
  316. if (count == 0)
  317. return (0);
  318. if (rl_last_func != rl_history_search_backward)
  319. prev_line_found = (char *)NULL;
  320. return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
  321. }