This is UndoText.m in view mode; [Download] [Up]
#import "textundo.h" @interface UndoText(PrivateMethods) - getSelBeforeKeydown:(int *)start :(int *)end; @end #define FONT_OPERATION NXLocalStringFromTable("Operations", "Font", NULL, "The user action of changing the font of a bunch of selected graphical entities.") #define CUT_OPERATION NXLocalStringFromTable("Operations", "Cut", NULL, "The operation of cutting some graphical entities out of the document and putting them on the Pasteboard.") #define TEXT_COLOR_OPERATION NXLocalStringFromTable("Operations", "Text Color", NULL, "The operation of changing the color of some text.") #define TEXT_GRAY_OPERATION NXLocalStringFromTable("TextOperations", "Text Gray", NULL, "The operation of changing the gray of some text.") #define SET_FONT_OPERATION NXLocalStringFromTable("TextOperations", "Set Font", NULL, "The operation of changing the font of some text.") #define FONT_SIZE_OPERATION NXLocalStringFromTable("TextOperations", "Font Size", NULL, "The operation of changing the size of some text.") #define PASTE_FONT_OPERATION NXLocalStringFromTable("TextOperations", "Paste Font", NULL, "The operation of setting the font of some text based on the copy/paste font mechanism.") #define PASTE_RULER_OPERATION NXLocalStringFromTable("TextOperations", "Paste Ruler", NULL, "The operation of setting the paragraph properties of some text based on the copy/paste ruler mechanism.") #define SUBSCRIPT_OPERATION NXLocalStringFromTable("TextOperations", "Subscript", NULL, "The operation of subscripting some text.") #define SUPERSCRIPT_OPERATION NXLocalStringFromTable("TextOperations", "Superscript", NULL, "The operation of superscripting some text.") #define UNDERLINE_OPERATION NXLocalStringFromTable("TextOperations", "Underline", NULL, "The operation of underlining some text.") #define UNSCRIPT_OPERATION NXLocalStringFromTable("TextOperations", "Unscript", NULL, "The operation of eliminating any super or subscripting of some text.") #define TAB_MOVE_OPERATION NXLocalStringFromTable("TextOperations", "Tab Move", NULL, "The operation of changing the tab stops in some text.") #define ALIGN_LEFT_OPERATION NXLocalStringFromTable("TextOperations", "Align Left", NULL, "The operation of aligning a paragraph to the left.") #define ALIGN_RIGHT_OPERATION NXLocalStringFromTable("TextOperations", "Align Right", NULL, "The operation of aligning a paragraph to the right.") #define CENTER_OPERATION NXLocalStringFromTable("TextOperations", "Center", NULL, "The operation of centering some text.") #define JUSTIFY_OPERATION NXLocalStringFromTable("TextOperations", "Justify", NULL, "The operation of left and right justifying some text.") #define FIRST_INDENT_OPERATION NXLocalStringFromTable("TextOperations", "First Indent", NULL, "The operation of changing the first indent of some text.") #define INDENT_OPERATION NXLocalStringFromTable("TextOperations", "Indent", NULL, "The operation of changing the indentation of some text.") #define NEW_TAB_OPERATION NXLocalStringFromTable("TextOperations", "New Tab", NULL, "The operation of adding a tab stop to some text.") #define DELETE_TAB_OPERATION NXLocalStringFromTable("TextOperations", "Delete Tab", NULL, "The operation of deleting a tab stop in some text.") #define LEFT_MARGIN_OPERATION NXLocalStringFromTable("TextOperations", "Left Margin", NULL, "The operation of changing the left margin on some text.") #define RIGHT_MARGIN_OPERATION NXLocalStringFromTable("TextOperations", "Right Margin", NULL, "The operation of changing the right margin on some text.") #define PARAGRAPH_OPERATION NXLocalStringFromTable("TextOperations", "Paragraph Change", NULL, "The operation of changing some general paragraph properties of some text.") #define REPLACE_OPERATION NXLocalStringFromTable("TextOperations", "Replace", NULL, "The operation of replace a run of text.") @implementation UndoText /* * This subclass of Text overrides methods that allow the user to change the * information stored in a Text object. Before one of these changes, a Change * object is created to record what is about to happen. The change object is * given control (to record the current state of the text) before and after * the change actually happens. * * Keystroke changes are handled by a special filter function which looks at * the characters as they are entered. This class is plug compatible with * the Text class. If you use an UndoText in the presence of a ChangeManager, * the undo mechanism will work automatically. */ #define DELETE_KEY (0x08) static char *undoFilterFunc(UndoText *self, unsigned char *text, int *len, int position) { id change; unsigned char *p; int chars; if (self->oldTextFilter) { text = (unsigned char *) (*self->oldTextFilter)(self, text, len, position); } change = [[TypingTextChange alloc] initView:self]; [change startChange]; for (p = text, chars = *len; chars; ++p, --chars) { if (*p == DELETE_KEY) { [change deleteCharacter]; } else { [change addCharacter:(int) *p]; } } [change endChange]; return ((char *)text); } static BOOL selIsEmpty(UndoText *self) { return (self->sp0.cp == self->spN.cp); } - initFrame:(const NXRect *)frameRect { [super initFrame:frameRect]; oldTextFilter = [self textFilter]; [super setTextFilter:&undoFilterFunc]; return self; } /* * This is a utility method that deletes the current selection without * creating a Change object. This is primarily used by TextSelections so * that they can quietly remove themselves. */ - eraseSelection { [super delete:self]; return self; } /* * We need to provide access to the clickCount because the behavior of * delete: changes when clickCount > 1. This has to do with the smart * deletion of words. TextSelections get and set the clickCount. */ - (int)clickCount { return clickCount; } - setClickCount:(int)count { clickCount = count; return self; } /* * The text object will change the selection after the keyDown: but before * the filter function gets control. We simply preserve the original selection * for later use. */ - keyDown:(NXEvent *)event { NXSelPt start, end; [self getSel:&start :&end]; startBeforeKeydown = start.cp; endBeforeKeydown = end.cp; return [super keyDown:event]; } - setTextFilter:(NXTextFilterFunc)aFunc { oldTextFilter = aFunc; return self; } /* Methods that create change objects */ - clear:sender { return [self delete:sender]; } - cut:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:CUT_OPERATION]; [change startChange]; retval = [super cut:sender]; [change endChange]; return retval; } - delete:sender { id change; id retval = nil; if (!selIsEmpty(self)) { change = [[DeleteTextChange alloc] initView:self]; [change startChange]; retval = [super delete:sender]; [change endChange]; } return retval; } static id pasteboard = nil; - paste:sender { id change; id retval; BOOL canPaste; const NXAtom *types; if (pasteboard == nil) { pasteboard = [Pasteboard new]; } for (canPaste = NO, types = [pasteboard types]; *types; types++) { if(*types == NXAsciiPboardType || *types == NXRTFPboardType) { canPaste = YES; break; } } if (canPaste) { change = [[PasteTextChange alloc] initView:self]; [change startChange]; retval = [super paste:sender]; [change endChange]; } else { retval = nil; } return retval; } - setSelGray:(float)value { id change; id retval; change = [[TextSelColorChange alloc] initView:self name:TEXT_GRAY_OPERATION]; [change startChange]; retval = [super setSelGray:value]; [change endChange]; return retval; } - setSelColor:(NXColor)color { id change; id retval; change = [[TextSelColorChange alloc] initView:self name:TEXT_COLOR_OPERATION]; [change startChange]; retval = [super setSelColor:color]; [change endChange]; return retval; } - setSelFont:fontId { id change; id retval; change = [[TextSelChange alloc] initView:self name:SET_FONT_OPERATION]; [change startChange]; retval = [super setSelFont:fontId]; [change endChange]; return retval; } - setSelFontSize:(float)size { id change; id retval; change = [[TextSelChange alloc] initView:self name:FONT_SIZE_OPERATION]; [change startChange]; retval = [super setSelFontSize:size]; [change endChange]; return retval; } - setSelFontFamily:(const char *)fontName { return [super setSelFontFamily:fontName]; } - pasteFont:sender { id change; id retval; change = [[WholeTextChange alloc] initView:self name:PASTE_FONT_OPERATION]; [change startChange]; retval = [super pasteFont:sender]; [change endChange]; return retval; } - pasteRuler:sender { id change; id retval; change = [[WholeTextChange alloc] initView:self name:PASTE_RULER_OPERATION]; [change startChange]; retval = [super pasteRuler:sender]; [change endChange]; return retval; } - subscript:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:SUBSCRIPT_OPERATION]; [change startChange]; retval = [super subscript:sender]; [change endChange]; return retval; } - superscript:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:SUPERSCRIPT_OPERATION]; [change startChange]; retval = [super superscript:sender]; [change endChange]; return retval; } - underline:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:UNDERLINE_OPERATION]; [change startChange]; retval = [super underline:sender]; [change endChange]; return retval; } - unscript:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:UNSCRIPT_OPERATION]; [change startChange]; retval = [super unscript:sender]; [change endChange]; return retval; } - changeFont:sender { id change; id retval; change = [[TextSelChange alloc] initView:self name:FONT_OPERATION]; [change startChange]; retval = [super changeFont:sender]; [change endChange]; return retval; } - changeTabStopAt:(NXCoord)oldX to:(NXCoord)newX { id change; id retval; change = [[WholeTextChange alloc] initView:self name:TAB_MOVE_OPERATION]; [change startChange]; retval = [super changeTabStopAt:oldX to:newX]; [change endChange]; return retval; } - setSelProp:(NXParagraphProp)prop to:(NXCoord)val { id change; id retval; const char *name; switch(prop) { case NX_LEFTALIGN : name = ALIGN_LEFT_OPERATION; break; case NX_RIGHTALIGN : name = ALIGN_RIGHT_OPERATION; break; case NX_CENTERALIGN : name = CENTER_OPERATION; break; case NX_JUSTALIGN : name = JUSTIFY_OPERATION; break; case NX_FIRSTINDENT : name = FIRST_INDENT_OPERATION; break; case NX_INDENT : name = INDENT_OPERATION; break; case NX_ADDTAB : name = NEW_TAB_OPERATION; break; case NX_REMOVETAB : name = DELETE_TAB_OPERATION; break; case NX_LEFTMARGIN : name = LEFT_MARGIN_OPERATION; break; case NX_RIGHTMARGIN : name = RIGHT_MARGIN_OPERATION; break; default : name = PARAGRAPH_OPERATION; break; } change = [[WholeTextChange alloc] initView:self name:name]; [change startChange]; retval = [super setSelProp:prop to:val]; [change endChange]; return retval; } - replaceSel:(char *)str { id change; id retval; NXSelPt oldStart, oldEnd; NXSelPt newStart, newEnd; change = [[TextSelChange alloc] initView:self name:REPLACE_OPERATION]; [change startChange]; [super getSel:&oldStart :&oldEnd]; retval = [super replaceSel:str]; [super getSel:&newStart :&newEnd]; [super setSel:oldStart.cp :newEnd.cp]; [change endChange]; [super setSel:newStart.cp :newEnd.cp]; return retval; } - getSelBeforeKeydown:(int *)start :(int *)end { *start = startBeforeKeydown; *end = endBeforeKeydown; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.