|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.