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.