Annotation of Examples/AppKit/Draw/textUndo.subproj/TypingTextChange.m, revision 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.