Annotation of Examples/AppKit/Draw/textUndo.subproj/TypingTextChange.m, revision 1.1.1.1

1.1       root        1: #import "textundo.h"
                      2: 
                      3: @implementation TypingTextChange
                      4: 
                      5: /*
                      6:  * A TypingTextChange object is created whenever and UndoText object wants
                      7:  * to insert or delete characters from the keyboard. TypingTextChanges are
                      8:  * not atomic like TextSelChanges. That is, no user events can come into the
                      9:  * UndoText during a TextSelChange. In contrast, a TypingTextChange has to
                     10:  * to wait for each keystroke until the change is completed. A typing change
                     11:  * is complete when another change is initiated, or when the UndoText gets
                     12:  * a keyDown: not adjacent to the current selection.
                     13:  */
                     14: 
                     15: #define TYPING_OPERATION NXLocalStringFromTable("Operations", "Typing", NULL, "The operation of typing some text into the document.")
                     16: 
                     17: - initView:aView
                     18: {
                     19:     [super initView:aView name:TYPING_OPERATION];
                     20: 
                     21:     insertionPoint = -1;
                     22:     subsumingChange = nil;
                     23:     firstKeyDown = YES;
                     24:     finished = NO;
                     25: 
                     26:     return self;
                     27: }
                     28: 
                     29: - saveBeforeChange
                     30: {
                     31:     NXSelPt start, end;
                     32: 
                     33:     [super saveBeforeChange];
                     34: 
                     35:     [textView getSel:&start :&end];
                     36:     insertionPoint = start.cp;
                     37: 
                     38:     return self;
                     39: }
                     40: 
                     41: - saveAfterChange
                     42: {
                     43:     /* Do nothing here. We'll take care of it in finishChange */
                     44: 
                     45:     return self;
                     46: }
                     47: 
                     48: /*
                     49:  * The subsumeChange: hook is used to let the typing change know that it
                     50:  * should end itself before the next change starts. However, if that change
                     51:  * is a delete: and its adjacent to the insertion point, then it was
                     52:  * a backspace and we don't want to terminate the typing change.
                     53:  *
                     54:  * In all the other cases, the new change can never be subsumed by the typing
                     55:  * change, but it takes the opportunity to call endChange.
                     56:  */
                     57: - (BOOL)subsumeChange:change
                     58: {
                     59:     if ([change isKindOf:[TypingTextChange class]]) {
                     60:         [change subsumedBy:self];
                     61:         return YES;
                     62:     }
                     63:     
                     64:     if ([change isKindOf:[DeleteTextChange class]] && [self canBeExtended]) {
                     65:        return YES;
                     66:     }
                     67: 
                     68:     return NO;
                     69: }
                     70: 
                     71: /*
                     72:  * This method is called by the ChangeManager when the user undoes this
                     73:  * change or when this change doesn't subsume a newly started change.
                     74:  */
                     75: 
                     76: - finishChange
                     77: {
                     78:     if (!finished) {
                     79:        [super saveAfterChange];
                     80:        [self setStart:insertionMin end:insertionMax];
                     81:        finished = YES;
                     82:     }
                     83:     return self;
                     84: }
                     85: 
                     86: - subsumedBy:change
                     87: {
                     88:     subsumingChange = change;
                     89:     return self;
                     90: }
                     91: 
                     92: /*
                     93:  * A typing change can be extended by a new keystroke if the selection is
                     94:  * adjacent to the insertion point maintained by the typing change. So, if
                     95:  * the user deletes a character, clicks somewhere else and then deletes
                     96:  * another character, two seperate change objects will be created.
                     97:  */
                     98: 
                     99: - (BOOL)canBeExtended
                    100: {
                    101:     NXSelPt start, end;
                    102:     BOOL returnVal = NO;
                    103: 
                    104:     [textView getSel:&start :&end];
                    105:     if (start.cp == end.cp) {
                    106:        if (start.cp == insertionPoint) {
                    107:            return YES;
                    108:        }
                    109:     } else if (end.cp == insertionPoint) {
                    110:        return YES;
                    111:     }
                    112: 
                    113:     return returnVal;
                    114: }
                    115: 
                    116: - deleteCharacter
                    117: {
                    118:     NXSelPt start, end;
                    119:     
                    120:     if (subsumingChange != nil)
                    121:         return [subsumingChange deleteCharacter];
                    122: 
                    123:     if (firstKeyDown) {
                    124:        [textView getSel:&start :&end];
                    125: 
                    126:        insertionMin = insertionMax = start.cp;
                    127: 
                    128:        if (start.cp == end.cp) {
                    129:            if (start.cp > 0) {
                    130:                insertionPoint = start.cp - 1;
                    131:            } else {
                    132:                insertionPoint = 0;
                    133:            }
                    134:        } else {
                    135:            insertionPoint = start.cp;
                    136:        }
                    137: 
                    138:        firstKeyDown = NO;
                    139:     } else {
                    140:        if (insertionPoint > 0) {
                    141:            insertionPoint--;
                    142:        }
                    143:     }
                    144:            
                    145:     if (insertionPoint < insertionMin) {
                    146:        insertionMin = insertionPoint;
                    147:     }
                    148: 
                    149:     return self;
                    150: }
                    151: 
                    152: /*
                    153:  * We don't do anything with the character (ch) right now, but a future
                    154:  * implementation might want to save each character in a more efficient
                    155:  * manner.
                    156:  */
                    157: 
                    158: - addCharacter:(int)ch
                    159: {
                    160:     NXSelPt start, end;
                    161: 
                    162:     if (subsumingChange != nil)
                    163:         return [subsumingChange addCharacter:ch];
                    164: 
                    165:     if (firstKeyDown) {
                    166:        [textView getSel:&start :&end];
                    167: 
                    168:        insertionMin = insertionMax = start.cp;
                    169:        insertionPoint = start.cp;
                    170:        firstKeyDown = NO;
                    171:     }
                    172: 
                    173:     insertionPoint++;
                    174: 
                    175:     if (insertionPoint > insertionMax) {
                    176:        insertionMax = insertionPoint;
                    177:     }
                    178: 
                    179:     return self;
                    180: }
                    181: 
                    182: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.