OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [readline/] [isearch.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* **************************************************************** */
2
/*                                                                  */
3
/*                      I-Search and Searching                      */
4
/*                                                                  */
5
/* **************************************************************** */
6
 
7
/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
8
 
9
   This file contains the Readline Library (the Library), a set of
10
   routines for providing Emacs style line input to programs that ask
11
   for it.
12
 
13
   The Library is free software; you can redistribute it and/or modify
14
   it under the terms of the GNU General Public License as published by
15
   the Free Software Foundation; either version 2, or (at your option)
16
   any later version.
17
 
18
   The Library is distributed in the hope that it will be useful, but
19
   WITHOUT ANY WARRANTY; without even the implied warranty of
20
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
   General Public License for more details.
22
 
23
   The GNU General Public License is often shipped with GNU software, and
24
   is generally kept in a file called COPYING or LICENSE.  If you do not
25
   have a copy of the license, write to the Free Software Foundation,
26
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
27
#define READLINE_LIBRARY
28
 
29
#if defined (HAVE_CONFIG_H)
30
#  include <config.h>
31
#endif
32
 
33
#include <sys/types.h>
34
 
35
#include <stdio.h>
36
 
37
#if defined (HAVE_UNISTD_H)
38
#  include <unistd.h>
39
#endif
40
 
41
#if defined (HAVE_STDLIB_H)
42
#  include <stdlib.h>
43
#else
44
#  include "ansi_stdlib.h"
45
#endif
46
 
47
#include "rldefs.h"
48
#include "readline.h"
49
#include "history.h"
50
 
51
#include "rlprivate.h"
52
#include "xmalloc.h"
53
 
54
/* Variables exported to other files in the readline library. */
55
unsigned char *_rl_isearch_terminators = (unsigned char *)NULL;
56
 
57
/* Variables imported from other files in the readline library. */
58
extern HIST_ENTRY *saved_line_for_history;
59
 
60
/* Forward declarations */
61
static int rl_search_history __P((int, int));
62
 
63
/* Last line found by the current incremental search, so we don't `find'
64
   identical lines many times in a row. */
65
static char *prev_line_found;
66
 
67
/* Search backwards through the history looking for a string which is typed
68
   interactively.  Start with the current line. */
69
int
70
rl_reverse_search_history (sign, key)
71
     int sign, key;
72
{
73
  return (rl_search_history (-sign, key));
74
}
75
 
76
/* Search forwards through the history looking for a string which is typed
77
   interactively.  Start with the current line. */
78
int
79
rl_forward_search_history (sign, key)
80
     int sign, key;
81
{
82
  return (rl_search_history (sign, key));
83
}
84
 
85
/* Display the current state of the search in the echo-area.
86
   SEARCH_STRING contains the string that is being searched for,
87
   DIRECTION is zero for forward, or 1 for reverse,
88
   WHERE is the history list number of the current line.  If it is
89
   -1, then this line is the starting one. */
90
static void
91
rl_display_search (search_string, reverse_p, where)
92
     char *search_string;
93
     int reverse_p, where;
94
{
95
  char *message;
96
  int msglen, searchlen;
97
 
98
  searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
99
 
100
  message = xmalloc (searchlen + 33);
101
  msglen = 0;
102
 
103
#if defined (NOTDEF)
104
  if (where != -1)
105
    {
106
      sprintf (message, "[%d]", where + history_base);
107
      msglen = strlen (message);
108
    }
109
#endif /* NOTDEF */
110
 
111
  message[msglen++] = '(';
112
 
113
  if (reverse_p)
114
    {
115
      strcpy (message + msglen, "reverse-");
116
      msglen += 8;
117
    }
118
 
119
  strcpy (message + msglen, "i-search)`");
120
  msglen += 10;
121
 
122
  if (search_string)
123
    {
124
      strcpy (message + msglen, search_string);
125
      msglen += searchlen;
126
    }
127
 
128
  strcpy (message + msglen, "': ");
129
 
130
  rl_message ("%s", message, 0);
131
  free (message);
132
  (*rl_redisplay_function) ();
133
}
134
 
135
/* Search through the history looking for an interactively typed string.
136
   This is analogous to i-search.  We start the search in the current line.
137
   DIRECTION is which direction to search; >= 0 means forward, < 0 means
138
   backwards. */
139
static int
140
rl_search_history (direction, invoking_key)
141
     int direction, invoking_key;
142
{
143
  /* The string that the user types in to search for. */
144
  char *search_string;
145
 
146
  /* The current length of SEARCH_STRING. */
147
  int search_string_index;
148
 
149
  /* The amount of space that SEARCH_STRING has allocated to it. */
150
  int search_string_size;
151
 
152
  /* The list of lines to search through. */
153
  char **lines, *allocated_line;
154
 
155
  /* The length of LINES. */
156
  int hlen;
157
 
158
  /* Where we get LINES from. */
159
  HIST_ENTRY **hlist;
160
 
161
  register int i;
162
  int orig_point, orig_line, last_found_line;
163
  int c, found, failed, sline_len;
164
 
165
  /* The line currently being searched. */
166
  char *sline;
167
 
168
  /* Offset in that line. */
169
  int line_index;
170
 
171
  /* Non-zero if we are doing a reverse search. */
172
  int reverse;
173
 
174
  /* The list of characters which terminate the search, but are not
175
     subsequently executed.  If the variable isearch-terminators has
176
     been set, we use that value, otherwise we use ESC and C-J. */
177
  unsigned char *isearch_terminators;
178
 
179
  orig_point = rl_point;
180
  last_found_line = orig_line = where_history ();
181
  reverse = direction < 0;
182
  hlist = history_list ();
183
  allocated_line = (char *)NULL;
184
 
185
  isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
186
                                                : (unsigned char *)"\033\012";
187
 
188
  /* Create an arrary of pointers to the lines that we want to search. */
189
  maybe_replace_line ();
190
  i = 0;
191
  if (hlist)
192
    for (i = 0; hlist[i]; i++);
193
 
194
  /* Allocate space for this many lines, +1 for the current input line,
195
     and remember those lines. */
196
  lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
197
  for (i = 0; i < hlen; i++)
198
    lines[i] = hlist[i]->line;
199
 
200
  if (saved_line_for_history)
201
    lines[i] = saved_line_for_history->line;
202
  else
203
    {
204
      /* Keep track of this so we can free it. */
205
      allocated_line = xmalloc (1 + strlen (rl_line_buffer));
206
      strcpy (allocated_line, &rl_line_buffer[0]);
207
      lines[i] = allocated_line;
208
    }
209
 
210
  hlen++;
211
 
212
  /* The line where we start the search. */
213
  i = orig_line;
214
 
215
  rl_save_prompt ();
216
 
217
  /* Initialize search parameters. */
218
  search_string = xmalloc (search_string_size = 128);
219
  *search_string = '\0';
220
  search_string_index = 0;
221
  prev_line_found = (char *)0;           /* XXX */
222
 
223
  /* Normalize DIRECTION into 1 or -1. */
224
  direction = (direction >= 0) ? 1 : -1;
225
 
226
  rl_display_search (search_string, reverse, -1);
227
 
228
  sline = rl_line_buffer;
229
  sline_len = strlen (sline);
230
  line_index = rl_point;
231
 
232
  found = failed = 0;
233
  for (;;)
234
    {
235
      Function *f = (Function *)NULL;
236
 
237
      /* Read a key and decide how to proceed. */
238
      c = rl_read_key ();
239
 
240
      if (_rl_keymap[c].type == ISFUNC)
241
        {
242
          f = _rl_keymap[c].function;
243
 
244
          if (f == rl_reverse_search_history)
245
            c = reverse ? -1 : -2;
246
          else if (f == rl_forward_search_history)
247
            c =  !reverse ? -1 : -2;
248
        }
249
 
250
#if 0
251
      /* Let NEWLINE (^J) terminate the search for people who don't like
252
         using ESC.  ^M can still be used to terminate the search and
253
         immediately execute the command. */
254
      if (c == ESC || c == NEWLINE)
255
#else
256
      /* The characters in isearch_terminators (set from the user-settable
257
         variable isearch-terminators) are used to terminate the search but
258
         not subsequently execute the character as a command.  The default
259
         value is "\033\012" (ESC and C-J). */
260
      if (strchr (isearch_terminators, c))
261
#endif
262
        {
263
          /* ESC still terminates the search, but if there is pending
264
             input or if input arrives within 0.1 seconds (on systems
265
             with select(2)) it is used as a prefix character
266
             with rl_execute_next.  WATCH OUT FOR THIS!  This is intended
267
             to allow the arrow keys to be used like ^F and ^B are used
268
             to terminate the search and execute the movement command. */
269
          if (c == ESC && _rl_input_available ())       /* XXX */
270
            rl_execute_next (ESC);
271
          break;
272
        }
273
 
274
      if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G'))
275
        {
276
          rl_execute_next (c);
277
          break;
278
        }
279
 
280
      switch (c)
281
        {
282
        case -1:
283
          if (search_string_index == 0)
284
            continue;
285
          else if (reverse)
286
            --line_index;
287
          else if (line_index != sline_len)
288
            ++line_index;
289
          else
290
            ding ();
291
          break;
292
 
293
          /* switch directions */
294
        case -2:
295
          direction = -direction;
296
          reverse = direction < 0;
297
          break;
298
 
299
        case CTRL ('G'):
300
          strcpy (rl_line_buffer, lines[orig_line]);
301
          rl_point = orig_point;
302
          rl_end = strlen (rl_line_buffer);
303
          rl_restore_prompt();
304
          rl_clear_message ();
305
          if (allocated_line)
306
            free (allocated_line);
307
          free (lines);
308
          return 0;
309
 
310
#if 0
311
        /* delete character from search string. */
312
        case -3:
313
          if (search_string_index == 0)
314
            ding ();
315
          else
316
            {
317
              search_string[--search_string_index] = '\0';
318
              /* This is tricky.  To do this right, we need to keep a
319
                 stack of search positions for the current search, with
320
                 sentinels marking the beginning and end. */
321
            }
322
          break;
323
#endif
324
 
325
        default:
326
          /* Add character to search string and continue search. */
327
          if (search_string_index + 2 >= search_string_size)
328
            {
329
              search_string_size += 128;
330
              search_string = xrealloc (search_string, search_string_size);
331
            }
332
          search_string[search_string_index++] = c;
333
          search_string[search_string_index] = '\0';
334
          break;
335
        }
336
 
337
      for (found = failed = 0;;)
338
        {
339
          int limit = sline_len - search_string_index + 1;
340
 
341
          /* Search the current line. */
342
          while (reverse ? (line_index >= 0) : (line_index < limit))
343
            {
344
              if (STREQN (search_string, sline + line_index, search_string_index))
345
                {
346
                  found++;
347
                  break;
348
                }
349
              else
350
                line_index += direction;
351
            }
352
          if (found)
353
            break;
354
 
355
          /* Move to the next line, but skip new copies of the line
356
             we just found and lines shorter than the string we're
357
             searching for. */
358
          do
359
            {
360
              /* Move to the next line. */
361
              i += direction;
362
 
363
              /* At limit for direction? */
364
              if (reverse ? (i < 0) : (i == hlen))
365
                {
366
                  failed++;
367
                  break;
368
                }
369
 
370
              /* We will need these later. */
371
              sline = lines[i];
372
              sline_len = strlen (sline);
373
            }
374
          while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
375
                 (search_string_index > sline_len));
376
 
377
          if (failed)
378
            break;
379
 
380
          /* Now set up the line for searching... */
381
          line_index = reverse ? sline_len - search_string_index : 0;
382
        }
383
 
384
      if (failed)
385
        {
386
          /* We cannot find the search string.  Ding the bell. */
387
          ding ();
388
          i = last_found_line;
389
          continue;             /* XXX - was break */
390
        }
391
 
392
      /* We have found the search string.  Just display it.  But don't
393
         actually move there in the history list until the user accepts
394
         the location. */
395
      if (found)
396
        {
397
          int line_len;
398
 
399
          prev_line_found = lines[i];
400
          line_len = strlen (lines[i]);
401
 
402
          if (line_len >= rl_line_buffer_len)
403
            rl_extend_line_buffer (line_len);
404
 
405
          strcpy (rl_line_buffer, lines[i]);
406
          rl_point = line_index;
407
          rl_end = line_len;
408
          last_found_line = i;
409
          rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
410
        }
411
    }
412
 
413
  /* The searching is over.  The user may have found the string that she
414
     was looking for, or else she may have exited a failing search.  If
415
     LINE_INDEX is -1, then that shows that the string searched for was
416
     not found.  We use this to determine where to place rl_point. */
417
 
418
  /* First put back the original state. */
419
  strcpy (rl_line_buffer, lines[orig_line]);
420
 
421
  rl_restore_prompt ();
422
 
423
  /* Free the search string. */
424
  free (search_string);
425
 
426
  if (last_found_line < orig_line)
427
    rl_get_previous_history (orig_line - last_found_line, 0);
428
  else
429
    rl_get_next_history (last_found_line - orig_line, 0);
430
 
431
  /* If the string was not found, put point at the end of the line. */
432
  if (line_index < 0)
433
    line_index = strlen (rl_line_buffer);
434
  rl_point = line_index;
435
  rl_clear_message ();
436
 
437
  if (allocated_line)
438
    free (allocated_line);
439
  free (lines);
440
 
441
  return 0;
442
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.