OSDN Git Service

* Implement: LibEditText_BackFindString() API and surround functions. (Non-Tested.)
[drdeamon64/drdeamon64.git] / libedittext / drd64_libedittext_cursorfind.c
1 /*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
2
3                          D r . D e a m o n  6 4
4                         for INTEL64(R), AMD64(R)
5         
6    Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10
11  1. Redistributions of source code must retain the above copyright notice,
12     this list of conditions and the following disclaimer.
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions and the following disclaimer in the
15     documentation and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY Koine Yuusuke(koinec) ``AS IS'' AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL Koine Yuusuke(koinec) OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
30
31 /* File Info -----------------------------------------------------------
32 File: drd64_.c
33 Function: 
34 Comment: 
35 ----------------------------------------------------------------------*/
36
37 #define DRD64_SRC_LIBEDITTEXT_CURSORFIND
38 #include"drd64_libedittext.h"
39
40 #define LOCATION(n)     DRD64_ERR_LOCATION( \
41                                                 DRD64_ERROR_MODULE_LIBEDITTEXT, DRD64_ERROR_ARCH_NODEPEND, \
42                                                 DRD64_SRC_LIBEDITTEXT_CURSORFIND_SRCID, (n))
43
44
45 /*----------------------------------------------------------------------
46 FindString
47 FindNext
48 BackFindString
49 BackFindNext
50 ----------------------------------------------------------------------*/
51
52
53 /*----------------------------------------------------------------------
54 ----------------------------------------------------------------------*/
55 int
56         LibEditText_CursorFind_SetRegexString(
57                 LibEditText_Cursor      *p_cursor,
58                 char                            *pstr_regex,
59                 DWord                           dw_regexlen )
60 {
61         char    *pstr_now;
62         DWord   dw_cnt;
63
64         assert( NULL != p_cursor );
65         assert( NULL != pstr_regex );
66
67         // Check regex length & NULL terminator ---
68         if( DRD64_LIBEDITTEXT_DEFAULT_REGSTR_SIZE <= dw_regexlen )      {
69                 return -0x01;
70         }
71
72         pstr_now        = (pstr_regex + dw_regexlen);
73         for( dw_cnt = dw_regexlen; dw_cnt > 0; dw_cnt-- )       {
74                 if( *pstr_now == '\0' )         { break; }
75                 pstr_now--;
76         }
77
78         if( 0 == dw_cnt )       {
79                 return -0x02;
80         }
81
82         // Set regex string to CursorInfo ---
83         strncpy( p_cursor->str_regstr, pstr_regex, (dw_cnt + 1) );
84
85         return 0x00;
86 }
87
88
89 /*----------------------------------------------------------------------
90 ----------------------------------------------------------------------*/
91 DWord
92         LibEditText_CursorFind_GetFindingPostion(
93                 LibEditText_Cursor      *p_cursor )
94 {
95         DWord   dw_pos;
96
97         dw_pos  = p_cursor->dw_pos;
98         
99         if( 0 < p_cursor->dw_find_prevpos_len ) {
100                 if( p_cursor->dw_lineid != p_cursor->dw_find_prevlineid )
101                         { goto  goto_LibEditText_CursorFind_GetFindingPostion_post; }
102
103                 if( p_cursor->dw_pos < p_cursor->dw_find_prevpos_start )
104                         { goto  goto_LibEditText_CursorFind_GetFindingPostion_post; }
105
106                 if( p_cursor->dw_pos >=
107                                 (p_cursor->dw_find_prevpos_start + p_cursor->dw_find_prevpos_len ) )
108                         { goto  goto_LibEditText_CursorFind_GetFindingPostion_post; }
109
110                 dw_pos  = p_cursor->dw_find_prevpos_start + p_cursor->dw_find_prevpos_len;
111         }
112
113 goto_LibEditText_CursorFind_GetFindingPostion_post:
114         return dw_pos;
115 }
116                 
117
118 /*----------------------------------------------------------------------
119 ----------------------------------------------------------------------*/
120 int
121         LibEditText_CursorFind_ExecFindString(
122                 LibEditText_TextInfo    *p_tinfo, 
123                 LibEditText_Cursor              *p_cursor,
124                 DWord                                   *pdw_findlid,
125                 DWord                                   *pdw_line,
126                 DWord                                   *pdw_pos,
127                 DWord                                   *pdw_len )
128 {
129         int             i_result;
130         int             i_flag;
131         int             i_round;
132         int             i_brkcnt;
133         Byte    *pb_start;
134         DWord   dw_pstart;
135         DWord   dw_lnow;
136         DWord   dw_len;
137         DWord   dw_lidbase;
138         LibEditText_LineInfo    *p_line;
139         regmatch_t      t_match;
140
141         assert( NULL != p_tinfo );
142         assert( NULL != p_cursor );
143
144         // Exec Find ---
145         p_line  = LINFO(p_tinfo, p_cursor->dw_lineid);
146         assert( NULL != p_line );
147
148         dw_lidbase      = p_line->dw_id;
149         dw_lnow         = p_cursor->dw_line;
150         dw_pstart       = *pdw_pos;
151         pb_start        = p_tinfo->pb_text + p_line->dw_start + dw_pstart;
152         i_round         = 0x00;
153         i_brkcnt        = 0;
154
155         if( 0 < dw_pstart )     { i_flag        = REG_NOTBOL; }
156         else                            { i_flag        = 0x00; }
157
158         do      {
159                 i_result        = regexec( &(p_cursor->t_findreg), (const char *)pb_start,
160                                                                 1, &t_match, i_flag );
161                 if( 0x00 == i_result )  { break; }
162                 else if( REG_NOMATCH != i_result )      {
163                         return -0x10;
164                 }
165
166                 if( p_line->dw_id == dw_lidbase )       { i_brkcnt++; }
167
168                 // Going to Next-Line ---
169                 i_flag  = 0x00;
170                 p_line  = LINFO(p_tinfo, p_line->dw_next);
171                 dw_lnow++;
172                 if( NULL == p_line )    {
173                         p_line  = LINFO(p_tinfo, p_tinfo->dw_line_start);
174                         dw_lnow = 0;
175                         i_round = 0x01;
176                 }
177                 assert( NULL != p_line );
178                 dw_pstart       = 0;
179                 pb_start        = p_tinfo->pb_text + p_line->dw_start;
180
181         }while( 2 > i_brkcnt );
182         
183         if(( 2 == i_brkcnt ) && ( REG_NOMATCH == i_result ))
184                 { return LIBEDITTEXT_RET_FINDNOMATCH; } // NO match string in Text. 
185
186         dw_pstart       += (DWord)t_match.rm_so;                                        // Find String Pos.
187         dw_len          = (DWord)(t_match.rm_eo - t_match.rm_so);       // Find String Len.
188         // Find String Line is dw_lnow.
189
190         assert( dw_lnow < p_tinfo->dw_maxline );
191         assert( dw_pstart < p_line->dw_strlen );
192
193         *pdw_pos                = dw_pstart;
194         *pdw_len                = dw_len;
195         *pdw_findlid    = p_line->dw_id;
196         *pdw_line               = dw_lnow;
197         
198         i_result        = LIBEDITTEXT_RET_FINDMATCH;
199         if( 0x00 != i_round )   { i_result      = LIBEDITTEXT_RET_FINDMATCH_ROUND; }
200
201         return i_result;
202 }
203
204
205 /*----------------------------------------------------------------------
206 ----------------------------------------------------------------------*/
207 LIBEDITTEXT_CURSORFIND_EXTERN
208 int
209         LibEditText_CursorFind_FindString(
210                 LibEditText_TextInfo    *p_tinfo, 
211                 LibEditText_Cursor              *p_cursor,
212                 char                                    *pstr_regex,
213                 DWord                                   dw_regexlen,
214                 Byte                                    b_flagfind )
215 {
216         int             i_retfind;
217         int             i_result;
218         int             i_flag;
219         DWord   dw_pstart;
220         DWord   dw_len;
221         DWord   dw_line;
222         DWord   dw_findlid;
223         LibEditText_LineInfo    *p_line;
224
225         assert( NULL != p_tinfo );
226         assert( NULL != p_cursor );
227         assert( NULL != pstr_regex );
228
229         // Clear Before Find Data ---
230         LibEditText_CursorFind_FreeFindData( p_cursor );
231
232         // Check & Set regex String ---
233         i_result        = LibEditText_CursorFind_SetRegexString( p_cursor, pstr_regex, dw_regexlen );
234         if( 0x00 != i_result )  {
235                 return i_result;
236         }
237
238         // Compile regex string ---
239         i_flag  = REG_EXTENDED;
240         if( LIBEDITTEXT_FLAGFIND_IGNOREICASE & b_flagfind ) { i_flag    |= REG_ICASE; }
241
242         i_result        = regcomp( &(p_cursor->t_findreg), p_cursor->str_regstr, REG_EXTENDED );
243         if( 0x00 != i_result )  {
244                 LibEditText_CursorFind_FreeFindData( p_cursor );
245
246                 return i_result;
247         }
248
249         // Exec Find ---
250         dw_pstart       = p_cursor->dw_pos;
251         i_retfind       = LibEditText_CursorFind_ExecFindString(
252                                                         p_tinfo, p_cursor, &dw_findlid, &dw_line, &dw_pstart, &dw_len );
253         if( 0x00 > i_retfind )  {
254                 return i_retfind;
255         }
256         if( LIBEDITTEXT_RET_FINDNOMATCH == i_retfind )  { return i_retfind; }
257
258         p_line  = LINFO(p_tinfo, dw_findlid);
259         assert( NULL != p_line );
260
261         i_result        = LibEditText_CursorInfo_LocateCursor( p_tinfo, p_cursor, p_line, dw_line );
262         if( 0x00 != i_result )  {
263                 LibEditText_CursorFind_FreeFindData( p_cursor );
264                 return -0x20;
265         }
266
267         i_result        = LibEditText_CursorMove_SetPosition( p_tinfo, p_cursor, dw_pstart );
268         if( 0x00 != i_result )  {
269                 LibEditText_CursorFind_FreeFindData( p_cursor );
270                 return -0x21;
271         }
272         
273         p_cursor->dw_find_prevpos_start = dw_pstart;
274         p_cursor->dw_find_prevpos_len   = dw_len;
275         p_cursor->dw_find_prevlineid    = dw_findlid;
276
277         return i_retfind;
278 }
279
280
281 /*----------------------------------------------------------------------
282 ----------------------------------------------------------------------*/
283 LIBEDITTEXT_CURSORFIND_EXTERN
284 int
285         LibEditText_CursorFind_FindNextString(
286                 LibEditText_TextInfo    *p_tinfo, 
287                 LibEditText_Cursor              *p_cursor )
288 {
289         int             i_retfind;
290         int             i_result;
291         DWord   dw_pstart;
292         DWord   dw_len;
293         DWord   dw_line;
294         DWord   dw_findlid;
295         LibEditText_LineInfo    *p_line;
296
297         assert( NULL != p_tinfo );
298         assert( NULL != p_cursor );
299
300         // Check PrevFind Data ---
301         if(( '\0' == p_cursor->str_regstr[0] ) || ( 0 == p_cursor->dw_find_prevpos_len ))
302                 { return -0x01; }
303
304         // Exec Find ---
305         dw_pstart       = LibEditText_CursorFind_GetFindingPostion( p_cursor );
306         i_retfind       = LibEditText_CursorFind_ExecFindString(
307                                                         p_tinfo, p_cursor, &dw_findlid, &dw_line, &dw_pstart, &dw_len );
308         if( 0x00 > i_retfind )  {
309                 return i_retfind;
310         }
311         if( LIBEDITTEXT_RET_FINDNOMATCH == i_retfind )  { return i_retfind; }
312
313         p_line  = LINFO(p_tinfo, dw_findlid);
314         assert( NULL != p_line );
315
316         i_result        = LibEditText_CursorInfo_LocateCursor( p_tinfo, p_cursor, p_line, dw_line );
317         if( 0x00 != i_result )  {
318                 LibEditText_CursorFind_FreeFindData( p_cursor );
319                 return -0x20;
320         }
321
322         i_result        = LibEditText_CursorMove_SetPosition( p_tinfo, p_cursor, dw_pstart );
323         if( 0x00 != i_result )  {
324                 LibEditText_CursorFind_FreeFindData( p_cursor );
325                 return -0x21;
326         }
327         
328         p_cursor->dw_find_prevpos_start = dw_pstart;
329         p_cursor->dw_find_prevpos_len   = dw_len;
330         p_cursor->dw_find_prevlineid    = dw_findlid;
331
332         return i_retfind;
333 }
334
335
336 /*----------------------------------------------------------------------
337 ----------------------------------------------------------------------*/
338 int
339         LibEditText_CursorFind_ExecBackFindString(
340                 LibEditText_TextInfo    *p_tinfo, 
341                 LibEditText_Cursor              *p_cursor,
342                 DWord                                   *pdw_findlid,
343                 DWord                                   *pdw_line,
344                 DWord                                   *pdw_pos,
345                 DWord                                   *pdw_len )
346 {
347         int             i_result;
348         int             i_round;
349         Byte    *pb_start;
350         DWord   dw_end;
351         DWord   dw_pos;
352         DWord   dw_lnow;
353         DWord   dw_len;
354         DWord   dw_lidbase;
355         DWord   dw_nowbase;
356         DWord   dw_oldbase;
357         LibEditText_LineInfo    *p_line;
358         regmatch_t      t_match;
359         regmatch_t      t_oldmatch;
360
361         assert( NULL != p_tinfo );
362         assert( NULL != p_cursor );
363
364         // Exec Find ---
365         p_line  = LINFO(p_tinfo, p_cursor->dw_lineid);
366         assert( NULL != p_line );
367
368         dw_lidbase      = p_line->dw_id;
369         dw_lnow         = p_cursor->dw_line;
370         pb_start        = p_tinfo->pb_text + p_line->dw_start;
371         dw_end          = *pdw_pos;
372         i_round         = 0x00;
373
374         if( 0 == dw_end )       {
375                 if( 1 == p_tinfo->dw_maxline )
376                         { return LIBEDITTEXT_RET_FINDNOMATCH; } // NO match string in Text. 
377
378                 p_line  = LINFO(p_tinfo, p_line->dw_before);
379                 if( NULL == p_line )    {
380                         p_line  = LINFO(p_tinfo, p_tinfo->dw_line_end);
381                         dw_lnow = p_tinfo->dw_maxline - 1;
382                         i_round = 0x01;
383                 }
384                 else    {
385                         dw_lnow--;
386                 }
387                 assert( NULL != p_line );
388                 pb_start        = p_tinfo->pb_text + p_line->dw_start;
389                 dw_end          = p_line->dw_strlen;
390         }
391
392         do      {
393                 
394                 dw_nowbase      = 0;
395                 dw_oldbase      = 0;
396                 do      {
397                         i_result        = regexec( &(p_cursor->t_findreg),
398                                                                 (const char *)pb_start, 1, &t_match, 0x00 );
399
400                         if( 0x00 == i_result )  {
401                                 t_oldmatch.rm_so        = t_match.rm_so;
402                                 t_oldmatch.rm_eo        = t_match.rm_eo;
403                                 dw_oldbase                      = dw_nowbase;
404                         
405                                 pb_start        += t_match.rm_eo;
406                                 dw_nowbase      += t_match.rm_eo;
407                         }
408                 }while(( 0x00 == i_result ) && ( dw_nowbase < dw_end ));
409
410                 if(( 0x00 != i_result ) && ( REG_NOMATCH != i_result )) {
411                         return -0x10;
412                 }
413                 
414                 if( dw_nowbase >= dw_end )      {
415                         assert( 0x00 == i_result );
416                         i_result        = REG_NOMATCH;
417                 }
418
419                 assert( REG_NOMATCH == i_result );
420                 if( 0 < dw_nowbase )    {
421                         dw_pos  = dw_oldbase + t_oldmatch.rm_so;
422                         dw_len  = t_oldmatch.rm_eo - t_oldmatch.rm_so;
423                         // Find String Line is dw_lnow.
424                         i_result        = 0x00;
425                         break;
426                 }
427
428                 // Going to Before-Line ---
429                 p_line  = LINFO(p_tinfo, p_line->dw_before);
430                 if( NULL == p_line )    {
431                         p_line  = LINFO(p_tinfo, p_tinfo->dw_line_end);
432                         dw_lnow = p_tinfo->dw_maxline - 1;
433                         i_round = 0x01;
434                 }
435                 else    {
436                         dw_lnow--;
437                 }
438                 assert( NULL != p_line );
439                 pb_start        = p_tinfo->pb_text + p_line->dw_start;
440                 dw_end          = p_line->dw_strlen;
441
442         }while( p_line->dw_id != dw_lidbase );
443         
444         if( REG_NOMATCH == i_result )
445                 { return LIBEDITTEXT_RET_FINDNOMATCH; } // NO match string in Text. 
446
447         assert( dw_lnow < p_tinfo->dw_maxline );
448         assert( dw_pos < p_line->dw_strlen );
449
450         *pdw_pos                = dw_pos;
451         *pdw_len                = dw_len;
452         *pdw_findlid    = p_line->dw_id;
453         *pdw_line               = dw_lnow;
454         
455         i_result        = LIBEDITTEXT_RET_FINDMATCH;
456         if( 0x00 != i_round )   { i_result      = LIBEDITTEXT_RET_FINDMATCH_ROUND; }
457
458         return i_result;
459 }
460
461
462 /*----------------------------------------------------------------------
463 ----------------------------------------------------------------------*/
464 LIBEDITTEXT_CURSORFIND_EXTERN
465 int
466         LibEditText_CursorFind_BackFindString(
467                 LibEditText_TextInfo    *p_tinfo, 
468                 LibEditText_Cursor              *p_cursor,
469                 char                                    *pstr_regex,
470                 DWord                                   dw_regexlen,
471                 Byte                                    b_flagfind )
472 {
473         int             i_retfind;
474         int             i_result;
475         int             i_flag;
476         DWord   dw_pstart;
477         DWord   dw_len;
478         DWord   dw_line;
479         DWord   dw_findlid;
480         LibEditText_LineInfo    *p_line;
481
482         assert( NULL != p_tinfo );
483         assert( NULL != p_cursor );
484         assert( NULL != pstr_regex );
485
486         // Clear Before Find Data ---
487         LibEditText_CursorFind_FreeFindData( p_cursor );
488
489         // Check & Set regex String ---
490         i_result        = LibEditText_CursorFind_SetRegexString( p_cursor, pstr_regex, dw_regexlen );
491         if( 0x00 != i_result )  {
492                 return i_result;
493         }
494
495         // Compile regex string ---
496         i_flag  = REG_EXTENDED;
497         if( LIBEDITTEXT_FLAGFIND_IGNOREICASE & b_flagfind ) { i_flag    |= REG_ICASE; }
498
499         i_result        = regcomp( &(p_cursor->t_findreg), p_cursor->str_regstr, REG_EXTENDED );
500         if( 0x00 != i_result )  {
501                 LibEditText_CursorFind_FreeFindData( p_cursor );
502
503                 return i_result;
504         }
505
506         // Exec Find ---
507         dw_pstart       = p_cursor->dw_pos;
508         i_retfind       = LibEditText_CursorFind_ExecBackFindString(
509                                                         p_tinfo, p_cursor, &dw_findlid, &dw_line, &dw_pstart, &dw_len );
510         if( 0x00 > i_retfind )  {
511                 return i_retfind;
512         }
513         if( LIBEDITTEXT_RET_FINDNOMATCH == i_retfind )  { return i_retfind; }
514
515         p_line  = LINFO(p_tinfo, dw_findlid);
516         assert( NULL != p_line );
517
518         i_result        = LibEditText_CursorInfo_LocateCursor( p_tinfo, p_cursor, p_line, dw_line );
519         if( 0x00 != i_result )  {
520                 LibEditText_CursorFind_FreeFindData( p_cursor );
521                 return -0x20;
522         }
523
524         i_result        = LibEditText_CursorMove_SetPosition( p_tinfo, p_cursor, dw_pstart );
525         if( 0x00 != i_result )  {
526                 LibEditText_CursorFind_FreeFindData( p_cursor );
527                 return -0x21;
528         }
529         
530         p_cursor->dw_find_prevpos_start = dw_pstart;
531         p_cursor->dw_find_prevpos_len   = dw_len;
532         p_cursor->dw_find_prevlineid    = dw_findlid;
533
534         return i_retfind;
535 }
536
537
538 /*----------------------------------------------------------------------
539 ----------------------------------------------------------------------*/
540 LIBEDITTEXT_CURSORFIND_EXTERN
541 int
542         LibEditText_CursorFind_FreeFindData(
543                 LibEditText_Cursor              *p_cursor )
544 {
545         assert( NULL != p_cursor );
546
547         if( '\0' == p_cursor->str_regstr[0] )   { return 0x00; }
548
549         regfree( &(p_cursor->t_findreg) );
550         memset( &(p_cursor->t_findreg), 0x00, sizeof( regex_t ) );
551         memset( p_cursor->str_regstr, 0x00, DRD64_LIBEDITTEXT_DEFAULT_REGSTR_SIZE );
552
553         return 0x00;
554 }
555
556
557 /* EOF of drd64_.c ----------------------------------- */