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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkTextIndex.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
 * tkTextIndex.c --
3
 *
4
 *      This module provides procedures that manipulate indices for
5
 *      text widgets.
6
 *
7
 * Copyright (c) 1992-1994 The Regents of the University of California.
8
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkTextIndex.c,v 1.1.1.1 2002-01-16 10:25:53 markom Exp $
14
 */
15
 
16
#include "default.h"
17
#include "tkPort.h"
18
#include "tkInt.h"
19
#include "tkText.h"
20
 
21
/*
22
 * Index to use to select last character in line (very large integer):
23
 */
24
 
25
#define LAST_CHAR 1000000
26
 
27
/*
28
 * Forward declarations for procedures defined later in this file:
29
 */
30
 
31
static char *           ForwBack _ANSI_ARGS_((char *string,
32
                            TkTextIndex *indexPtr));
33
static char *           StartEnd _ANSI_ARGS_(( char *string,
34
                            TkTextIndex *indexPtr));
35
 
36
/*
37
 *--------------------------------------------------------------
38
 *
39
 * TkTextMakeIndex --
40
 *
41
 *      Given a line index and a character index, look things up
42
 *      in the B-tree and fill in a TkTextIndex structure.
43
 *
44
 * Results:
45
 *      The structure at *indexPtr is filled in with information
46
 *      about the character at lineIndex and charIndex (or the
47
 *      closest existing character, if the specified one doesn't
48
 *      exist), and indexPtr is returned as result.
49
 *
50
 * Side effects:
51
 *      None.
52
 *
53
 *--------------------------------------------------------------
54
 */
55
 
56
TkTextIndex *
57
TkTextMakeIndex(tree, lineIndex, charIndex, indexPtr)
58
    TkTextBTree tree;           /* Tree that lineIndex and charIndex refer
59
                                 * to. */
60
    int lineIndex;              /* Index of desired line (0 means first
61
                                 * line of text). */
62
    int charIndex;              /* Index of desired character. */
63
    TkTextIndex *indexPtr;      /* Structure to fill in. */
64
{
65
    register TkTextSegment *segPtr;
66
    int index;
67
 
68
    indexPtr->tree = tree;
69
    if (lineIndex < 0) {
70
        lineIndex = 0;
71
        charIndex = 0;
72
    }
73
    if (charIndex < 0) {
74
        charIndex = 0;
75
    }
76
    indexPtr->linePtr = TkBTreeFindLine(tree, lineIndex);
77
    if (indexPtr->linePtr == NULL) {
78
        indexPtr->linePtr = TkBTreeFindLine(tree, TkBTreeNumLines(tree));
79
        charIndex = 0;
80
    }
81
 
82
    /*
83
     * Verify that the index is within the range of the line.
84
     * If not, just use the index of the last character in the line.
85
     */
86
 
87
    for (index = 0, segPtr = indexPtr->linePtr->segPtr; ;
88
            segPtr = segPtr->nextPtr) {
89
        if (segPtr == NULL) {
90
            indexPtr->charIndex = index-1;
91
            break;
92
        }
93
        index += segPtr->size;
94
        if (index > charIndex) {
95
            indexPtr->charIndex = charIndex;
96
            break;
97
        }
98
    }
99
    return indexPtr;
100
}
101
 
102
/*
103
 *--------------------------------------------------------------
104
 *
105
 * TkTextIndexToSeg --
106
 *
107
 *      Given an index, this procedure returns the segment and
108
 *      offset within segment for the index.
109
 *
110
 * Results:
111
 *      The return value is a pointer to the segment referred to
112
 *      by indexPtr;  this will always be a segment with non-zero
113
 *      size.  The variable at *offsetPtr is set to hold the
114
 *      integer offset within the segment of the character
115
 *      given by indexPtr.
116
 *
117
 * Side effects:
118
 *      None.
119
 *
120
 *--------------------------------------------------------------
121
 */
122
 
123
TkTextSegment *
124
TkTextIndexToSeg(indexPtr, offsetPtr)
125
    TkTextIndex *indexPtr;              /* Text index. */
126
    int *offsetPtr;                     /* Where to store offset within
127
                                         * segment, or NULL if offset isn't
128
                                         * wanted. */
129
{
130
    register TkTextSegment *segPtr;
131
    int offset;
132
 
133
    for (offset = indexPtr->charIndex, segPtr = indexPtr->linePtr->segPtr;
134
            offset >= segPtr->size;
135
            offset -= segPtr->size, segPtr = segPtr->nextPtr) {
136
        /* Empty loop body. */
137
    }
138
    if (offsetPtr != NULL) {
139
        *offsetPtr = offset;
140
    }
141
    return segPtr;
142
}
143
 
144
/*
145
 *--------------------------------------------------------------
146
 *
147
 * TkTextSegToOffset --
148
 *
149
 *      Given a segment pointer and the line containing it, this
150
 *      procedure returns the offset of the segment within its
151
 *      line.
152
 *
153
 * Results:
154
 *      The return value is the offset (within its line) of the
155
 *      first character in segPtr.
156
 *
157
 * Side effects:
158
 *      None.
159
 *
160
 *--------------------------------------------------------------
161
 */
162
 
163
int
164
TkTextSegToOffset(segPtr, linePtr)
165
    TkTextSegment *segPtr;              /* Segment whose offset is desired. */
166
    TkTextLine *linePtr;                /* Line containing segPtr. */
167
{
168
    TkTextSegment *segPtr2;
169
    int offset;
170
 
171
    offset = 0;
172
    for (segPtr2 = linePtr->segPtr; segPtr2 != segPtr;
173
            segPtr2 = segPtr2->nextPtr) {
174
        offset += segPtr2->size;
175
    }
176
    return offset;
177
}
178
 
179
/*
180
 *----------------------------------------------------------------------
181
 *
182
 * TkTextGetIndex --
183
 *
184
 *      Given a string, return the line and character indices that
185
 *      it describes.
186
 *
187
 * Results:
188
 *      The return value is a standard Tcl return result.  If
189
 *      TCL_OK is returned, then everything went well and the index
190
 *      at *indexPtr is filled in;  otherwise TCL_ERROR is returned
191
 *      and an error message is left in interp->result.
192
 *
193
 * Side effects:
194
 *      None.
195
 *
196
 *----------------------------------------------------------------------
197
 */
198
 
199
int
200
TkTextGetIndex(interp, textPtr, string, indexPtr)
201
    Tcl_Interp *interp;         /* Use this for error reporting. */
202
    TkText *textPtr;            /* Information about text widget. */
203
    char *string;               /* Textual description of position. */
204
    TkTextIndex *indexPtr;      /* Index structure to fill in. */
205
{
206
    register char *p;
207
    char *end, *endOfBase;
208
    Tcl_HashEntry *hPtr;
209
    TkTextTag *tagPtr;
210
    TkTextSearch search;
211
    TkTextIndex first, last;
212
    int wantLast, result;
213
    char c;
214
 
215
    /*
216
     *---------------------------------------------------------------------
217
     * Stage 1: check to see if the index consists of nothing but a mark
218
     * name.  We do this check now even though it's also done later, in
219
     * order to allow mark names that include funny characters such as
220
     * spaces or "+1c".
221
     *---------------------------------------------------------------------
222
     */
223
 
224
    if (TkTextMarkNameToIndex(textPtr, string, indexPtr) == TCL_OK) {
225
        return TCL_OK;
226
    }
227
 
228
    /*
229
     *------------------------------------------------
230
     * Stage 2: start again by parsing the base index.
231
     *------------------------------------------------
232
     */
233
 
234
    indexPtr->tree = textPtr->tree;
235
 
236
    /*
237
     * First look for the form "tag.first" or "tag.last" where "tag"
238
     * is the name of a valid tag.  Try to use up as much as possible
239
     * of the string in this check (strrchr instead of strchr below).
240
     * Doing the check now, and in this way, allows tag names to include
241
     * funny characters like "@" or "+1c".
242
     */
243
 
244
    p = strrchr(string, '.');
245
    if (p != NULL) {
246
        if ((p[1] == 'f') && (strncmp(p+1, "first", 5) == 0)) {
247
            wantLast = 0;
248
            endOfBase = p+6;
249
        } else if ((p[1] == 'l') && (strncmp(p+1, "last", 4) == 0)) {
250
            wantLast = 1;
251
            endOfBase = p+5;
252
        } else {
253
            goto tryxy;
254
        }
255
        *p = 0;
256
        hPtr = Tcl_FindHashEntry(&textPtr->tagTable, string);
257
        *p = '.';
258
        if (hPtr == NULL) {
259
            goto tryxy;
260
        }
261
        tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr);
262
        TkTextMakeIndex(textPtr->tree, 0, 0, &first);
263
        TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0,
264
                &last);
265
        TkBTreeStartSearch(&first, &last, tagPtr, &search);
266
        if (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) {
267
            Tcl_AppendResult(interp,
268
                    "text doesn't contain any characters tagged with \"",
269
                    Tcl_GetHashKey(&textPtr->tagTable, hPtr), "\"",
270
                            (char *) NULL);
271
            return TCL_ERROR;
272
        }
273
        *indexPtr = search.curIndex;
274
        if (wantLast) {
275
            while (TkBTreeNextTag(&search)) {
276
                *indexPtr = search.curIndex;
277
            }
278
        }
279
        goto gotBase;
280
    }
281
 
282
    tryxy:
283
    if (string[0] == '@') {
284
        /*
285
         * Find character at a given x,y location in the window.
286
         */
287
 
288
        int x, y;
289
 
290
        p = string+1;
291
        x = strtol(p, &end, 0);
292
        if ((end == p) || (*end != ',')) {
293
            goto error;
294
        }
295
        p = end+1;
296
        y = strtol(p, &end, 0);
297
        if (end == p) {
298
            goto error;
299
        }
300
        TkTextPixelIndex(textPtr, x, y, indexPtr);
301
        endOfBase = end;
302
        goto gotBase;
303
    }
304
 
305
    if (isdigit(UCHAR(string[0])) || (string[0] == '-')) {
306
        int lineIndex, charIndex;
307
 
308
        /*
309
         * Base is identified with line and character indices.
310
         */
311
 
312
        lineIndex = strtol(string, &end, 0) - 1;
313
        if ((end == string) || (*end != '.')) {
314
            goto error;
315
        }
316
        p = end+1;
317
        if ((*p == 'e') && (strncmp(p, "end", 3) == 0)) {
318
            charIndex = LAST_CHAR;
319
            endOfBase = p+3;
320
        } else {
321
            charIndex = strtol(p, &end, 0);
322
            if (end == p) {
323
                goto error;
324
            }
325
            endOfBase = end;
326
        }
327
        TkTextMakeIndex(textPtr->tree, lineIndex, charIndex, indexPtr);
328
        goto gotBase;
329
    }
330
 
331
    for (p = string; *p != 0; p++) {
332
        if (isspace(UCHAR(*p)) || (*p == '+') || (*p == '-')) {
333
            break;
334
        }
335
    }
336
    endOfBase = p;
337
    if (string[0] == '.') {
338
        /*
339
         * See if the base position is the name of an embedded window.
340
         */
341
 
342
        c = *endOfBase;
343
        *endOfBase = 0;
344
        result = TkTextWindowIndex(textPtr, string, indexPtr);
345
        *endOfBase = c;
346
        if (result != 0) {
347
            goto gotBase;
348
        }
349
    }
350
    if ((string[0] == 'e')
351
            && (strncmp(string, "end", (size_t) (endOfBase-string)) == 0)) {
352
        /*
353
         * Base position is end of text.
354
         */
355
 
356
        TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
357
                0, indexPtr);
358
        goto gotBase;
359
    } else {
360
        /*
361
         * See if the base position is the name of a mark.
362
         */
363
 
364
        c = *endOfBase;
365
        *endOfBase = 0;
366
        result = TkTextMarkNameToIndex(textPtr, string, indexPtr);
367
        *endOfBase = c;
368
        if (result == TCL_OK) {
369
            goto gotBase;
370
        }
371
 
372
        /*
373
         * See if the base position is the name of an embedded image
374
         */
375
 
376
        c = *endOfBase;
377
        *endOfBase = 0;
378
        result = TkTextImageIndex(textPtr, string, indexPtr);
379
        *endOfBase = c;
380
        if (result != 0) {
381
            goto gotBase;
382
        }
383
    }
384
    goto error;
385
 
386
    /*
387
     *-------------------------------------------------------------------
388
     * Stage 3: process zero or more modifiers.  Each modifier is either
389
     * a keyword like "wordend" or "linestart", or it has the form
390
     * "op count units" where op is + or -, count is a number, and units
391
     * is "chars" or "lines".
392
     *-------------------------------------------------------------------
393
     */
394
 
395
    gotBase:
396
    p = endOfBase;
397
    while (1) {
398
        while (isspace(UCHAR(*p))) {
399
            p++;
400
        }
401
        if (*p == 0) {
402
            break;
403
        }
404
 
405
        if ((*p == '+') || (*p == '-')) {
406
            p = ForwBack(p, indexPtr);
407
        } else {
408
            p = StartEnd(p, indexPtr);
409
        }
410
        if (p == NULL) {
411
            goto error;
412
        }
413
    }
414
    return TCL_OK;
415
 
416
    error:
417
    Tcl_AppendResult(interp, "bad text index \"", string, "\"",
418
            (char *) NULL);
419
    return TCL_ERROR;
420
}
421
 
422
/*
423
 *----------------------------------------------------------------------
424
 *
425
 * TkTextPrintIndex --
426
 *
427
 *
428
 *      This procedure generates a string description of an index,
429
 *      suitable for reading in again later.
430
 *
431
 * Results:
432
 *      The characters pointed to by string are modified.
433
 *
434
 * Side effects:
435
 *      None.
436
 *
437
 *----------------------------------------------------------------------
438
 */
439
 
440
void
441
TkTextPrintIndex(indexPtr, string)
442
    TkTextIndex *indexPtr;      /* Pointer to index. */
443
    char *string;               /* Place to store the position.  Must have
444
                                 * at least TK_POS_CHARS characters. */
445
{
446
    sprintf(string, "%d.%d", TkBTreeLineIndex(indexPtr->linePtr) + 1,
447
            indexPtr->charIndex);
448
}
449
 
450
/*
451
 *--------------------------------------------------------------
452
 *
453
 * TkTextIndexCmp --
454
 *
455
 *      Compare two indices to see which one is earlier in
456
 *      the text.
457
 *
458
 * Results:
459
 *      The return value is 0 if index1Ptr and index2Ptr refer
460
 *      to the same position in the file, -1 if index1Ptr refers
461
 *      to an earlier position than index2Ptr, and 1 otherwise.
462
 *
463
 * Side effects:
464
 *      None.
465
 *
466
 *--------------------------------------------------------------
467
 */
468
 
469
int
470
TkTextIndexCmp(index1Ptr, index2Ptr)
471
    TkTextIndex *index1Ptr;             /* First index. */
472
    TkTextIndex *index2Ptr;             /* Second index. */
473
{
474
    int line1, line2;
475
 
476
    if (index1Ptr->linePtr == index2Ptr->linePtr) {
477
        if (index1Ptr->charIndex < index2Ptr->charIndex) {
478
            return -1;
479
        } else if (index1Ptr->charIndex > index2Ptr->charIndex) {
480
            return 1;
481
        } else {
482
            return 0;
483
        }
484
    }
485
    line1 = TkBTreeLineIndex(index1Ptr->linePtr);
486
    line2 = TkBTreeLineIndex(index2Ptr->linePtr);
487
    if (line1 < line2) {
488
        return -1;
489
    }
490
    if (line1 > line2) {
491
        return 1;
492
    }
493
    return 0;
494
}
495
 
496
/*
497
 *----------------------------------------------------------------------
498
 *
499
 * ForwBack --
500
 *
501
 *      This procedure handles +/- modifiers for indices to adjust
502
 *      the index forwards or backwards.
503
 *
504
 * Results:
505
 *      If the modifier in string is successfully parsed then the
506
 *      return value is the address of the first character after the
507
 *      modifier, and *indexPtr is updated to reflect the modifier.
508
 *      If there is a syntax error in the modifier then NULL is returned.
509
 *
510
 * Side effects:
511
 *      None.
512
 *
513
 *----------------------------------------------------------------------
514
 */
515
 
516
static char *
517
ForwBack(string, indexPtr)
518
    char *string;               /* String to parse for additional info
519
                                 * about modifier (count and units).
520
                                 * Points to "+" or "-" that starts
521
                                 * modifier. */
522
    TkTextIndex *indexPtr;      /* Index to update as specified in string. */
523
{
524
    register char *p;
525
    char *end, *units;
526
    int count, lineIndex;
527
    size_t length;
528
 
529
    /*
530
     * Get the count (how many units forward or backward).
531
     */
532
 
533
    p = string+1;
534
    while (isspace(UCHAR(*p))) {
535
        p++;
536
    }
537
    count = strtol(p, &end, 0);
538
    if (end == p) {
539
        return NULL;
540
    }
541
    p = end;
542
    while (isspace(UCHAR(*p))) {
543
        p++;
544
    }
545
 
546
    /*
547
     * Find the end of this modifier (next space or + or - character),
548
     * then parse the unit specifier and update the position
549
     * accordingly.
550
     */
551
 
552
    units = p;
553
    while ((*p != 0) && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) {
554
        p++;
555
    }
556
    length = p - units;
557
    if ((*units == 'c') && (strncmp(units, "chars", length) == 0)) {
558
        if (*string == '+') {
559
            TkTextIndexForwChars(indexPtr, count, indexPtr);
560
        } else {
561
            TkTextIndexBackChars(indexPtr, count, indexPtr);
562
        }
563
    } else if ((*units == 'l') && (strncmp(units, "lines", length) == 0)) {
564
        lineIndex = TkBTreeLineIndex(indexPtr->linePtr);
565
        if (*string == '+') {
566
            lineIndex += count;
567
        } else {
568
            lineIndex -= count;
569
 
570
            /*
571
             * The check below retains the character position, even
572
             * if the line runs off the start of the file.  Without
573
             * it, the character position will get reset to 0 by
574
             * TkTextMakeIndex.
575
             */
576
 
577
            if (lineIndex < 0) {
578
                lineIndex = 0;
579
            }
580
        }
581
        TkTextMakeIndex(indexPtr->tree, lineIndex, indexPtr->charIndex,
582
                indexPtr);
583
    } else {
584
        return NULL;
585
    }
586
    return p;
587
}
588
 
589
/*
590
 *----------------------------------------------------------------------
591
 *
592
 * TkTextIndexForwChars --
593
 *
594
 *      Given an index for a text widget, this procedure creates a
595
 *      new index that points "count" characters ahead of the source
596
 *      index.
597
 *
598
 * Results:
599
 *      *dstPtr is modified to refer to the character "count" characters
600
 *      after srcPtr, or to the last character in the file if there aren't
601
 *      "count" characters left in the file.
602
 *
603
 * Side effects:
604
 *      None.
605
 *
606
 *----------------------------------------------------------------------
607
 */
608
 
609
        /* ARGSUSED */
610
void
611
TkTextIndexForwChars(srcPtr, count, dstPtr)
612
    TkTextIndex *srcPtr;                /* Source index. */
613
    int count;                          /* How many characters forward to
614
                                         * move.  May be negative. */
615
    TkTextIndex *dstPtr;                /* Destination index: gets modified. */
616
{
617
    TkTextLine *linePtr;
618
    TkTextSegment *segPtr;
619
    int lineLength;
620
 
621
    if (count < 0) {
622
        TkTextIndexBackChars(srcPtr, -count, dstPtr);
623
        return;
624
    }
625
 
626
    *dstPtr = *srcPtr;
627
    dstPtr->charIndex += count;
628
    while (1) {
629
        /*
630
         * Compute the length of the current line.
631
         */
632
 
633
        lineLength = 0;
634
        for (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;
635
                segPtr = segPtr->nextPtr) {
636
            lineLength += segPtr->size;
637
        }
638
 
639
        /*
640
         * If the new index is in the same line then we're done.
641
         * Otherwise go on to the next line.
642
         */
643
 
644
        if (dstPtr->charIndex < lineLength) {
645
            return;
646
        }
647
        dstPtr->charIndex -= lineLength;
648
        linePtr = TkBTreeNextLine(dstPtr->linePtr);
649
        if (linePtr == NULL) {
650
            dstPtr->charIndex = lineLength - 1;
651
            return;
652
        }
653
        dstPtr->linePtr = linePtr;
654
    }
655
}
656
 
657
/*
658
 *----------------------------------------------------------------------
659
 *
660
 * TkTextIndexBackChars --
661
 *
662
 *      Given an index for a text widget, this procedure creates a
663
 *      new index that points "count" characters earlier than the
664
 *      source index.
665
 *
666
 * Results:
667
 *      *dstPtr is modified to refer to the character "count" characters
668
 *      before srcPtr, or to the first character in the file if there aren't
669
 *      "count" characters earlier than srcPtr.
670
 *
671
 * Side effects:
672
 *      None.
673
 *
674
 *----------------------------------------------------------------------
675
 */
676
 
677
void
678
TkTextIndexBackChars(srcPtr, count, dstPtr)
679
    TkTextIndex *srcPtr;                /* Source index. */
680
    int count;                          /* How many characters backward to
681
                                         * move.  May be negative. */
682
    TkTextIndex *dstPtr;                /* Destination index: gets modified. */
683
{
684
    TkTextSegment *segPtr;
685
    int lineIndex;
686
 
687
    if (count < 0) {
688
        TkTextIndexForwChars(srcPtr, -count, dstPtr);
689
        return;
690
    }
691
 
692
    *dstPtr = *srcPtr;
693
    dstPtr->charIndex -= count;
694
    lineIndex = -1;
695
    while (dstPtr->charIndex < 0) {
696
        /*
697
         * Move back one line in the text.  If we run off the beginning
698
         * of the file then just return the first character in the text.
699
         */
700
 
701
        if (lineIndex < 0) {
702
            lineIndex = TkBTreeLineIndex(dstPtr->linePtr);
703
        }
704
        if (lineIndex == 0) {
705
            dstPtr->charIndex = 0;
706
            return;
707
        }
708
        lineIndex--;
709
        dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, lineIndex);
710
 
711
        /*
712
         * Compute the length of the line and add that to dstPtr->charIndex.
713
         */
714
 
715
        for (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;
716
                segPtr = segPtr->nextPtr) {
717
            dstPtr->charIndex += segPtr->size;
718
        }
719
    }
720
}
721
 
722
/*
723
 *----------------------------------------------------------------------
724
 *
725
 * StartEnd --
726
 *
727
 *      This procedure handles modifiers like "wordstart" and "lineend"
728
 *      to adjust indices forwards or backwards.
729
 *
730
 * Results:
731
 *      If the modifier is successfully parsed then the return value
732
 *      is the address of the first character after the modifier, and
733
 *      *indexPtr is updated to reflect the modifier. If there is a
734
 *      syntax error in the modifier then NULL is returned.
735
 *
736
 * Side effects:
737
 *      None.
738
 *
739
 *----------------------------------------------------------------------
740
 */
741
 
742
static char *
743
StartEnd(string, indexPtr)
744
    char *string;               /* String to parse for additional info
745
                                 * about modifier (count and units).
746
                                 * Points to first character of modifer
747
                                 * word. */
748
    TkTextIndex *indexPtr;      /* Index to mdoify based on string. */
749
{
750
    char *p;
751
    int c, offset;
752
    size_t length;
753
    register TkTextSegment *segPtr;
754
 
755
    /*
756
     * Find the end of the modifier word.
757
     */
758
 
759
    for (p = string; isalnum(UCHAR(*p)); p++) {
760
        /* Empty loop body. */
761
    }
762
    length = p-string;
763
    if ((*string == 'l') && (strncmp(string, "lineend", length) == 0)
764
            && (length >= 5)) {
765
        indexPtr->charIndex = 0;
766
        for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;
767
                segPtr = segPtr->nextPtr) {
768
            indexPtr->charIndex += segPtr->size;
769
        }
770
        indexPtr->charIndex -= 1;
771
    } else if ((*string == 'l') && (strncmp(string, "linestart", length) == 0)
772
            && (length >= 5)) {
773
        indexPtr->charIndex = 0;
774
    } else if ((*string == 'w') && (strncmp(string, "wordend", length) == 0)
775
            && (length >= 5)) {
776
        int firstChar = 1;
777
 
778
        /*
779
         * If the current character isn't part of a word then just move
780
         * forward one character.  Otherwise move forward until finding
781
         * a character that isn't part of a word and stop there.
782
         */
783
 
784
        segPtr = TkTextIndexToSeg(indexPtr, &offset);
785
        while (1) {
786
            if (segPtr->typePtr == &tkTextCharType) {
787
                c = segPtr->body.chars[offset];
788
                if (!isalnum(UCHAR(c)) && (c != '_')) {
789
                    break;
790
                }
791
                firstChar = 0;
792
            }
793
            offset += 1;
794
            indexPtr->charIndex += 1;
795
            if (offset >= segPtr->size) {
796
                segPtr = TkTextIndexToSeg(indexPtr, &offset);
797
            }
798
        }
799
        if (firstChar) {
800
            TkTextIndexForwChars(indexPtr, 1, indexPtr);
801
        }
802
    } else if ((*string == 'w') && (strncmp(string, "wordstart", length) == 0)
803
            && (length >= 5)) {
804
        int firstChar = 1;
805
 
806
        /*
807
         * Starting with the current character, look for one that's not
808
         * part of a word and keep moving backward until you find one.
809
         * Then if the character found wasn't the first one, move forward
810
         * again one position.
811
         */
812
 
813
        segPtr = TkTextIndexToSeg(indexPtr, &offset);
814
        while (1) {
815
            if (segPtr->typePtr == &tkTextCharType) {
816
                c = segPtr->body.chars[offset];
817
                if (!isalnum(UCHAR(c)) && (c != '_')) {
818
                    break;
819
                }
820
                firstChar = 0;
821
            }
822
            offset -= 1;
823
            indexPtr->charIndex -= 1;
824
            if (offset < 0) {
825
                if (indexPtr->charIndex < 0) {
826
                    indexPtr->charIndex = 0;
827
                    goto done;
828
                }
829
                segPtr = TkTextIndexToSeg(indexPtr, &offset);
830
            }
831
        }
832
        if (!firstChar) {
833
            TkTextIndexForwChars(indexPtr, 1, indexPtr);
834
        }
835
    } else {
836
        return NULL;
837
    }
838
    done:
839
    return p;
840
}

powered by: WebSVN 2.1.0

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