~ubuntu-branches/ubuntu/gutsy/lv/gutsy

« back to all changes in this revision

Viewing changes to src/find.c

  • Committer: Bazaar Package Importer
  • Author(s): GOTO Masanori
  • Date: 2003-11-16 01:21:59 UTC
  • Revision ID: james.westby@ubuntu.com-20031116012159-wpu27qhoxzskmjy0
Tags: upstream-4.50
ImportĀ upstreamĀ versionĀ 4.50

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * find.c
 
3
 *
 
4
 * All rights reserved. Copyright (C) 1996 by NARITA Tomio.
 
5
 * $Id: find.c,v 1.5 2003/11/13 03:08:19 nrt Exp $
 
6
 */
 
7
/*
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
 */
 
22
 
 
23
#include <stdlib.h>
 
24
 
 
25
#ifdef MSDOS
 
26
#include <dos.h>
 
27
#endif /* MSDOS */
 
28
 
 
29
#include <import.h>
 
30
#include <fetch.h>
 
31
#include <decode.h>
 
32
#include <screen.h>
 
33
#include <position.h>
 
34
#include <console.h>
 
35
#include <dfa.h>
 
36
#include <istr.h>
 
37
#include <guess.h>
 
38
#include <begin.h>
 
39
#include <find.h>
 
40
 
 
41
private i_str_t *searchPattern = NULL;
 
42
private ic_t firstLetter;
 
43
 
 
44
private boolean_t FindCheck( line_t *line )
 
45
{
 
46
  int i, iptr, cptr, tptr, hptr;
 
47
 
 
48
  for( hptr = 0 ; hptr < line->heads ; hptr++ )
 
49
    line->head[ hptr ].hit = FALSE;
 
50
  hptr = 0;
 
51
 
 
52
  for( iptr = 0 ; NOSET != line->istr[ iptr ].charset ; iptr++ ){
 
53
    if( firstLetter == line->istr[ iptr ].c ){
 
54
      for( cptr = iptr, tptr = 0 ; NOSET != searchPattern[ tptr ].charset ; tptr++, cptr++ ){
 
55
        if( line->istr[ cptr ].c != searchPattern[ tptr ].c )
 
56
          goto findNext;
 
57
        if( searchPattern[ tptr ].charset != line->istr[ cptr ].charset )
 
58
          goto findNext;
 
59
      }
 
60
      /*
 
61
       * string matched
 
62
       */
 
63
      while( iptr >= line->head[ hptr ].ptr )
 
64
        hptr++;
 
65
      line->head[ hptr ].hit = TRUE;
 
66
      for( i = iptr ; i < cptr ; i++ )
 
67
        line->istr[ i ].attr |= ATTR_STANDOUT;
 
68
      iptr = cptr - 1;
 
69
    }
 
70
findNext:
 
71
    /* dummy line */;
 
72
  }
 
73
 
 
74
  return line->head[ hptr ].hit;
 
75
}
 
76
 
 
77
private boolean_t FindOnly( i_str_t *istr )
 
78
{
 
79
  int iptr, cptr, tptr;
 
80
 
 
81
  for( iptr = 0 ; NOSET != istr[ iptr ].charset ; iptr++ ){
 
82
    if( firstLetter == istr[ iptr ].c ){
 
83
      for( cptr = iptr, tptr = 0 ; NOSET != searchPattern[ tptr ].charset ; tptr++, cptr++ ){
 
84
        if( searchPattern[ tptr ].c != istr[ cptr ].c )
 
85
          goto findOnlyNext;
 
86
        if( searchPattern[ tptr ].charset != istr[ cptr ].charset )
 
87
          goto findOnlyNext;
 
88
      }
 
89
      return TRUE;
 
90
    }
 
91
findOnlyNext:
 
92
    /* dummy line */;
 
93
  }
 
94
 
 
95
  return FALSE;
 
96
}
 
97
 
 
98
private boolean_t FindCheckRegexp( line_t *line )
 
99
{
 
100
  int i, iptr, cptr, hptr;
 
101
 
 
102
  for( hptr = 0 ; hptr < line->heads ; hptr++ )
 
103
    line->head[ hptr ].hit = FALSE;
 
104
  hptr = 0;
 
105
 
 
106
  for( iptr = 0 ; /* NOSET != line->istr[ iptr ].charset */ ; iptr++ ){
 
107
    if( TRUE != regexp_short_cut
 
108
       || regexp_first_letter == ToLower( line->istr[ iptr ].charset,
 
109
                                         line->istr[ iptr ].c ) ){
 
110
      cptr = iptr;
 
111
      if( TRUE == ReRun( line->istr, &cptr ) ){
 
112
        /*
 
113
         * string matched
 
114
         */
 
115
        if( cptr == iptr ){
 
116
          /* in case that pattern begins with '^' */
 
117
          line->head[ hptr ].hit = TRUE;
 
118
          line->istr[ iptr ].attr |= ATTR_STANDOUT;
 
119
        } else {
 
120
          while( iptr >= line->head[ hptr ].ptr )
 
121
            hptr++;
 
122
          line->head[ hptr ].hit = TRUE;
 
123
          for( i = iptr ; i <= cptr ; i++ )
 
124
            line->istr[ i ].attr |= ATTR_STANDOUT;
 
125
          iptr = cptr;
 
126
        }
 
127
      } else if( NOSET == line->istr[ cptr ].charset )
 
128
        break;
 
129
    }
 
130
    if( NOSET == line->istr[ iptr ].charset )
 
131
      break;
 
132
  }
 
133
 
 
134
  return line->head[ hptr ].hit;
 
135
}
 
136
 
 
137
private boolean_t FindOnlyRegexp( i_str_t *istr )
 
138
{
 
139
  int iptr, cptr;
 
140
 
 
141
  for( iptr = 0 ; /* NOSET != istr[ iptr ].charset */ ; iptr++ ){
 
142
    if( TRUE != regexp_short_cut
 
143
       || regexp_first_letter == ToLower( istr[ iptr ].charset,
 
144
                                         istr[ iptr ].c ) ){
 
145
      cptr = iptr;
 
146
      if( TRUE == ReRun( istr, &cptr ) )
 
147
        return TRUE;
 
148
      else if( NOSET == istr[ cptr ].charset )
 
149
        break;
 
150
    }
 
151
    if( NOSET == istr[ iptr ].charset )
 
152
      break;
 
153
  }
 
154
 
 
155
  return FALSE;
 
156
}
 
157
 
 
158
public void FindSetup()
 
159
{
 
160
  if( TRUE == regexp_search ){
 
161
    find_func = FindCheckRegexp;
 
162
    find_only_func = FindOnlyRegexp;
 
163
  } else {
 
164
    find_func = FindCheck;
 
165
    find_only_func = FindOnly;
 
166
  }
 
167
}
 
168
 
 
169
private void FindReset( file_t *f )
 
170
{
 
171
  int i, j, k;
 
172
  line_t *line;
 
173
  i_str_t *istr;
 
174
 
 
175
  for( i = 0 ; i < BLOCK_SIZE ; i++ ){
 
176
    if( TRUE == f->used[ i ] ){
 
177
      for( j = 0 ; j < f->page[ i ].lines ; j++ ){
 
178
        line = &f->page[ i ].line[ j ];
 
179
        istr = line->istr;
 
180
        for( k = 0 ; NOSET != istr[ k ].charset ; k++ ){
 
181
          if( CNTRL != istr[ k ].charset )
 
182
            istr[ k ].attr &= ~ATTR_STANDOUT;
 
183
        }
 
184
        if( NULL != f->find.pattern )
 
185
          (*find_func)( line );
 
186
      }
 
187
    }
 
188
  }
 
189
}
 
190
 
 
191
public boolean_t FindClearPattern( file_t *f )
 
192
{
 
193
  if( NULL != f->find.pattern ){
 
194
    IstrFree( f->find.pattern );
 
195
    f->find.pattern = NULL;
 
196
    searchPattern = NULL;
 
197
    FindReset( f );
 
198
    ReFreeDFA();
 
199
    return TRUE;
 
200
  } else {
 
201
    return FALSE;
 
202
  }
 
203
}
 
204
 
 
205
public byte *FindResetPattern( file_t *f, i_str_t *istr )
 
206
{
 
207
  byte *res = NULL;
 
208
 
 
209
  AdjustPatternCharset( f->inputCodingSystem, f->keyboardCodingSystem,
 
210
                       f->defaultCodingSystem, istr );
 
211
 
 
212
  searchPattern = istr;
 
213
  firstLetter = searchPattern[ 0 ].c;
 
214
 
 
215
  f->find.pattern = istr;
 
216
 
 
217
  if( TRUE == regexp_search ){
 
218
    if( NULL != (res = ReMakeDFA( istr )) ){
 
219
      IstrFree( f->find.pattern );
 
220
      f->find.pattern = NULL;
 
221
      searchPattern = NULL;
 
222
    }
 
223
  }
 
224
 
 
225
  return res;
 
226
}
 
227
 
 
228
public byte *FindSetPattern( file_t *f, i_str_t *istr )
 
229
{
 
230
  byte *res;
 
231
 
 
232
  if( NULL != f->find.pattern )
 
233
    IstrFree( f->find.pattern );
 
234
 
 
235
  f->find.first = TRUE;
 
236
  f->find.pos = f->screen.top;
 
237
 
 
238
  res = FindResetPattern( f, istr );
 
239
 
 
240
  FindReset( f );
 
241
 
 
242
  return res;
 
243
}
 
244
 
 
245
private boolean_t FindContinue( file_t *f, position_t *pos, boolean_t forward )
 
246
{
 
247
  int idx;
 
248
  unsigned int segment;
 
249
  int offset, foundOffset = 0;
 
250
  i_str_t *istr;
 
251
  boolean_t simple, res, found;
 
252
  byte *str;
 
253
 
 
254
  segment = pos->seg;
 
255
 
 
256
  f->eof = FALSE;
 
257
  found = FALSE;
 
258
 
 
259
  while( FALSE == f->eof ){
 
260
    if( FALSE == FileSeek( f, segment ) )
 
261
      return FALSE;
 
262
#ifdef MSDOS
 
263
    if( TRUE == allow_interrupt )
 
264
      bdos( 0x0b, 0, 0 );
 
265
#endif /* MSDOS */
 
266
    if( TRUE == kb_interrupted )
 
267
      break;
 
268
    for( offset = 0 ; offset < PAGE_SIZE && FALSE == f->eof ; offset++ ){
 
269
      str = FileLoadLine( f, &idx, &simple );
 
270
      if( 0 == idx )
 
271
        return FALSE;
 
272
      
 
273
      if( TRUE == simple )
 
274
        istr = DecodeSimple( IstrAlloc( ZONE_FREE, idx + 1 ),
 
275
                            str, &idx );
 
276
      else
 
277
        istr = Decode( IstrAlloc( ZONE_FREE, idx + 1 ),
 
278
                      f->inputCodingSystem, str, &idx );
 
279
      FileFreeLine( f );
 
280
 
 
281
      res = (*find_only_func)( istr );
 
282
      IstrFree( istr );
 
283
 
 
284
      if( TRUE == res ){
 
285
        if( TRUE == forward ){
 
286
          pos->seg = segment;
 
287
          pos->off = offset;
 
288
          return TRUE;
 
289
        } else {
 
290
          found = TRUE;
 
291
          foundOffset = offset;
 
292
        }
 
293
      }
 
294
    }
 
295
    if( TRUE == forward ){
 
296
      segment++;
 
297
    } else {
 
298
      if( TRUE == found ){
 
299
        pos->seg = segment;
 
300
        pos->off = foundOffset;
 
301
        return TRUE;
 
302
      }
 
303
      if( 0 == segment )
 
304
        return FALSE;
 
305
      else
 
306
        segment--;
 
307
    }
 
308
  }
 
309
 
 
310
  return FALSE;
 
311
}
 
312
 
 
313
public int FindForward( file_t *f )
 
314
{
 
315
  boolean_t flagFind, flagContinue;
 
316
  position_t pos;
 
317
  int count = 0;
 
318
 
 
319
  PositionAssign( pos, f->find.pos );
 
320
 
 
321
  if( FALSE == f->find.first ){
 
322
    flagContinue = FALSE;
 
323
    do {
 
324
      PositionInc( f, pos.seg, pos.blk, pos.off, pos.phy );
 
325
      count++;
 
326
      flagContinue = TRUE;
 
327
    } while( 0 );
 
328
    if( FALSE == flagContinue )
 
329
      return -1;
 
330
  } else {
 
331
    if( FALSE == FetchLine( f, pos.seg, pos.off ) )
 
332
      return -1;
 
333
    f->find.first = FALSE;
 
334
  }
 
335
 
 
336
  ConsoleEnableInterrupt();
 
337
 
 
338
  flagContinue = FALSE;
 
339
  flagFind = FALSE;
 
340
 
 
341
  /*
 
342
   * $B%-%c%C%7%eFb$N%5!<%A(B
 
343
   */
 
344
  do {
 
345
#ifdef MSDOS
 
346
    if( TRUE == allow_interrupt )
 
347
      bdos( 0x0b, 0, 0 );
 
348
#endif /* MSDOS */
 
349
    if( TRUE == kb_interrupted )
 
350
      break;
 
351
    if( TRUE == f->page[ pos.blk ].line[ pos.off ].head[ pos.phy ].hit ){
 
352
      flagFind = TRUE;
 
353
      break;
 
354
    }
 
355
    if( ++pos.phy >= f->page[ pos.blk ].line[ pos.off ].heads ){
 
356
      if( ++pos.off >= f->page[ pos.blk ].lines ){
 
357
        pos.seg++;
 
358
        pos.blk = Block( pos.seg );
 
359
        if( TRUE == f->used[ pos.blk ]
 
360
           && pos.seg == f->page[ pos.blk ].segment ){
 
361
          pos.off = 0;
 
362
        } else {
 
363
          flagContinue = TRUE;
 
364
          break;
 
365
        }
 
366
      }
 
367
      pos.phy = 0;
 
368
    }
 
369
    count++;
 
370
  } while( 1 );
 
371
 
 
372
  /*
 
373
   * $B%-%c%C%7%e30$N%5!<%A(B
 
374
   */
 
375
  if( TRUE == flagContinue ){
 
376
    if( TRUE == FindContinue( f, &pos, TRUE ) ){
 
377
      ConsoleDisableInterrupt();
 
378
      ScreenTop( f, 1 + pos.seg * PAGE_SIZE + pos.off );
 
379
      PositionAssign( pos, f->screen.top );
 
380
      while( FALSE == f->page[ pos.blk ].line[ pos.off ].head[ pos.phy ].hit ){
 
381
        PositionInc( f, pos.seg, pos.blk, pos.off, pos.phy );
 
382
      }
 
383
      ScreenTopPhysical( f, &pos );
 
384
      return -2;
 
385
    }
 
386
  }
 
387
 
 
388
  ConsoleDisableInterrupt();
 
389
 
 
390
  if( TRUE == flagFind ){
 
391
    ScreenTopPhysical( f, &pos );
 
392
    return count;
 
393
  } else {
 
394
    PositionAssign( pos, f->find.pos );         /* for MSDOS */
 
395
    ScreenTopPhysical( f, &pos );
 
396
    return -1;
 
397
  }
 
398
}
 
399
 
 
400
public int FindBackward( file_t *f )
 
401
{
 
402
  boolean_t flagFind, flagContinue;
 
403
  position_t pos;
 
404
  int count = 0;
 
405
 
 
406
  PositionAssign( pos, f->find.pos );
 
407
 
 
408
  if( FALSE == f->find.first ){
 
409
    flagContinue = FALSE;
 
410
    do {
 
411
      PositionDec( f, pos.seg, pos.blk, pos.off, pos.phy );
 
412
      count++;
 
413
      flagContinue = TRUE;
 
414
    } while( 0 );
 
415
    if( FALSE == flagContinue )
 
416
      return -1;
 
417
  } else {
 
418
    if( FALSE == FetchLine( f, pos.seg, pos.off ) )
 
419
      return -1;
 
420
    f->find.first = FALSE;
 
421
  }
 
422
 
 
423
  ConsoleEnableInterrupt();
 
424
 
 
425
  flagContinue = FALSE;
 
426
  flagFind = FALSE;
 
427
 
 
428
  /*
 
429
   * $B%-%c%C%7%eFb$N%5!<%A(B
 
430
   */
 
431
  do {
 
432
#ifdef MSDOS
 
433
    if( TRUE == allow_interrupt )
 
434
      bdos( 0x0b, 0, 0 );
 
435
#endif /* MSDOS */
 
436
    if( TRUE == kb_interrupted )
 
437
      break;
 
438
    if( TRUE == f->page[ pos.blk ].line[ pos.off ].head[ pos.phy ].hit ){
 
439
      flagFind = TRUE;
 
440
      break;
 
441
    }
 
442
    if( --pos.phy < 0 ){
 
443
      if( --pos.off < 0 ){
 
444
        if( pos.seg == 0 ){
 
445
          pos.phy++;
 
446
          pos.off++;
 
447
          break;
 
448
        }
 
449
        pos.seg--;
 
450
        pos.blk = Block( pos.seg );
 
451
        if( TRUE == f->used[ pos.blk ]
 
452
           && pos.seg == f->page[ pos.blk ].segment ){
 
453
          pos.off = f->page[ pos.blk ].lines - 1;
 
454
        } else {
 
455
          flagContinue = TRUE;
 
456
          break;
 
457
        }
 
458
      }
 
459
      pos.phy = f->page[ pos.blk ].line[ pos.off ].heads - 1;
 
460
    }
 
461
    count++;
 
462
  } while( 1 );
 
463
 
 
464
  /*
 
465
   * $B%-%c%C%7%e30$N%5!<%A(B
 
466
   */
 
467
  if( TRUE == flagContinue ){
 
468
    if( TRUE == FindContinue( f, &pos, FALSE ) ){
 
469
      ConsoleDisableInterrupt();
 
470
      ScreenTop( f, 1 + pos.seg * PAGE_SIZE + pos.off );
 
471
      PositionAssign( pos, f->screen.top );
 
472
      pos.phy = f->page[ pos.blk ].line[ pos.off ].heads - 1;
 
473
      while( FALSE == f->page[ pos.blk ].line[ pos.off ].head[ pos.phy ].hit ){
 
474
        PositionDec( f, pos.seg, pos.blk, pos.off, pos.phy );
 
475
      }
 
476
      ScreenTopPhysical( f, &pos );
 
477
      return -2;
 
478
    }
 
479
  }
 
480
 
 
481
  ConsoleDisableInterrupt();
 
482
 
 
483
  if( TRUE == flagFind ){
 
484
    ScreenTopPhysical( f, &pos );
 
485
    return count;
 
486
  } else {
 
487
    PositionAssign( pos, f->find.pos );         /* for MSDOS */
 
488
    ScreenTopPhysical( f, &pos );
 
489
    return -1;
 
490
  }
 
491
}