This is eText.Undo.m in view mode; [Download] [Up]
{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;}
\margl40
\margr40
{\colortbl;\red0\green0\blue0;\red255\green0\blue0;}
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc0\cf0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\i
\b FILENAME
\b0 :
\b\i0 eText.Undo.m\
\b0 //
\i
\b SUMMARY
\b0 :
\b\i0 Implementation of the Undo subsystem of eText
\b0 \
//
\b\i CATEGORY
\b0 :
\i0
\b Undo
\b0 \
//
\b\i PROTOCOLS
\b0 :
\i0
\b Uses UndoManager
\b0 \
//
\b\i INTERFACE
\b0 :
\i0
\b None
\b0 \
//
\b\i AUTHOR
\b0 :
\b\i0 Rohit Khare, portions by Jeff Martin of Bozell.
\b0 \
//
\b\i COPYRIGHT
\b0 :
\f1\i0 Ó
\f0\b 1993,94 California Institure of Technology, eText Project\
\b0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b\i Implementation Comments
\b0\i0 \
// These methods deal with undoManager. We may have some real problems\
// intercepting the data flow between "user" methods and internal ones\
// (e.g. paste vs replaceSelWithRTF:)\
// Unlike Jeff's UndoText, we do ours with undo record grouping and\
// and without writing new replace... 'Action' methods. At least, we'll try...\
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b\i History
\b0\i0 \
// 10/27/94:
\b Changed handling of typing undos to attempt coalescing.
\b0 \
// 10/17/94:
\b Cleaned up for eText5.
\b0 \
// 08/05/94:
\b Completely Rearchitected for 5.0. RK
\b0 \
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b Imported Interfaces
\b0 \
//\
#import "
\b eText.Undo.h
\b0 "\
\
\b static
\b0
\b int
\b0
\b undoLastPos
\b0 = -1;\
\b static
\b0
\b int
\b0
\b undoFirstPos
\b0 = -1;\
\b static
\b0
\b Stream
\b0 *
\b undoStream
\b0 = NULL; //
\i RK: Assumes only 1 Text is being edited
\i0 \
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\b\fc0\cf0 static
\b0
\b BOOL
\b0
\b isTyping
\b0 =
\b NO
\b0 ;\
#define
\b DELETE_KEY
\b0 (0x08)\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 \
NXTextFilterFunc
\b0
\b oldTextFilter
\b0 ; //
\i keep the old text filter around
\i0 \
\
\i @implementation eText(Undo)\
\i0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b eText Undo API\
\b0 //\
-
\b undoSelChange
\b0 :(const char *)actionName \{ //
\i Call
\b before
\b0 transaction\
if(sp0.cp < 0) return
\b nil
\b0 ;
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\i0\fc0\cf0 \
[self
\b registerLastTypingUndo
\b0 ]; //
\i Clear the queue...
\i0 \
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 \
if(sp0.cp != spN.cp) \{\
\b undoStream
\b0 = [[[Stream alloc] init]
\b openMemory
\b0 ];\
[self
\b writeETF
\b0 :[
\b undoStream
\b0 stream]
\b from
\b0 :
\b sp0
\b0 .cp
\b to
\b0 :
\b spN
\b0 .cp];\
\} else \{\
if(undoStream) [undoStream free];\
\b undoStream
\b0 =
\b NULL
\b0 ;\
\}\
\
[undoManager
\b setActionName
\b0 :
\b NXUniqueString
\b0 (actionName ? actionName : "")];\
[undoManager
\b beginUndoRecordGrouping
\b0 ];\
return self;\
\}\
-
\b undoParChange
\b0 :(const char *)actionName \{ //
\i Call
\b before
\b0 transaction\
\i0 int
\b boP
\b0 ,
\b eoP
\b0 ;\
\
\i if(sp0.cp < 0) return
\b nil
\b0 ; \
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\i0\fc0\cf0 [self
\b registerLastTypingUndo
\b0 ]; //
\i Clear the queue...
\i0 \
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 \
\b undoStream
\b0 = [[[Stream alloc] init]
\b openMemory
\b0 ];\
\b boP
\b0 = [self
\b positionFromLine
\b0 :[self
\b lineFromPosition
\b0 :
\b sp0
\b0 .cp]];\
\b eoP
\b0 = [self
\b positionFromLine
\b0 :([self
\b lineFromPosition
\b0 :
\b spN
\b0 .cp]
\b +1)
\b0 ];\
if (
\b eoP
\b0
\b <
\b0
\b boP
\b0 ) eoP = [self
\b textLength
\b0 ];\
[self
\b writeETF
\b0 :[
\b undoStream
\b0 stream]
\b from
\b0 :
\b boP
\b0
\b to
\b0 :
\b eoP
\b0 ];\
\
[undoManager
\b setActionName
\b0 :
\b NXUniqueString
\b0 (actionName ? actionName : "")];\
[undoManager
\b beginUndoRecordGrouping
\b0 ];\
return self;\
\}\
-
\b undoAffectedRange
\b0 :(
\b int
\b0 )from
\b to
\b0 :(
\b int
\b0 )to \{ //
\i Call
\b after
\b0 transaction\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\i0\fc0\cf0 [[[undoManager setUndoTarget:self] freeUndoArgs] \
\b replaceSelWith
\b0 :
\b undoStream
\b0 from:
\b from
\b0 to:
\b to
\b0 ];\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 [undoManager
\b endUndoRecordGrouping
\b0 ];\
\b undoStream
\b0 = NULL;\
[self
\b touch
\b0 ];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\fc0\cf0 return self;\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 \}\
\
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b Undo Stream Operations\
\b0 //\
\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\fc0\cf0 -
\b replaceSelWith
\b0 :
\i stream
\i0
\b from
\b0 :(int)
\i from
\i0
\b to
\b0 :(int)
\i to
\i0 \{\
\fc1\cf1 [self
\b setSel
\b0 :from :to];
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 \
\b0 [self
\b undoSelChange
\b0 :[undoManager
\b currentActionName
\b0 ]];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\gray300\fc2\cf2 // Replace the given range with the rtf in the given stream\
\gray0\fc0\cf0 [stream
\b rewind
\b0 ];
\fc1\cf1 \
if(stream && [stream stream]) \
[self
\b replaceSelWithRichText
\b0 :[
\b stream
\b0 stream]];\
else [self
\b replaceSel
\b0 :
\b NULL
\b0 ];\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0
\b0\fc1\cf1 if (sp0.cp < 0) [self setSel:0:0];\
\b\fc0\cf0 [self undoAffectedRange:from to:spN.cp];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\b0\fc0\cf0 return self;\
\}\
-
\b replaceSel
\b0 :(const char *)
\i str
\i0
\b from
\b0 :(int)
\i from
\i0
\b to
\b0 :(int)
\i to
\i0 \{\
\fc1\cf1 [self
\b setSel
\b0 :from :to];
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 \
\b0 [self
\b undoSelChange
\b0 :[undoManager
\b currentActionName
\b0 ]];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\gray300\fc2\cf2 // Replace the given range with the rtf in the given stream\
\gray0\fc1\cf1 if(
\b str
\b0 ) [self
\b replaceSel
\b0 :
\b str
\b0 ];\
else [self
\b replaceSel
\b0 :
\b ""
\b0 ];\
if (sp0.cp < 0) [self setSel:0:0];\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 [self undoAffectedRange:from to:spN.cp];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\b0\fc0\cf0 return self;\
\}\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 \
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b Selection Format Changes\
\b0 //\
-
\b changeFont
\b0 :sender \{\
id retval;\
\
[self
\b touch
\b0 ];\
if (sp0.cp == spN.cp) //
\i If the font is at a caret, just go on.
\i0 \
return [super
\b changeFont
\b0 :sender];\
\
[self
\b undoSelChange
\b0 :"
\b Change Font
\b0 "];\
if (![
\b sender
\b0
\b respondsTo
\b0 :@selector(
\b convertFont
\b0 :)])\
\b sender
\b0 = [
\b FontManager
\b0 new];\
retval = [super
\b changeFont
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
-
\b pasteFont
\b0 :sender \{\
id retval;\
[self
\b undoSelChange
\b0 :"
\b Paste Font
\b0 "];\
retval = [super
\b pasteFont
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
-
\b underline
\b0 :sender \{\
id retval;\
[self
\b undoSelChange
\b0 :"
\b Underline
\b0 "];\
retval = [super
\b underline
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
-
\b subscript
\b0 :sender \{\
id retval;\
\
[self
\b undoSelChange
\b0 :"
\b Subscript
\b0 "];\
retval = [super
\b subscript
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b superscript
\b0 :sender \{\
id retval;\
\
[self
\b undoSelChange
\b0 :"
\b Superscript
\b0 "];\
retval = [super
\b superscript
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b unscript
\b0 :sender \{\
id retval;\
[self
\b undoSelChange
\b0 :"
\b Unscript
\b0 "];\
retval = [super
\b unscript
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
-
\b setSelFont
\b0 :font \{\
id retval,newF;\
\
[self
\b touch
\b0 ];\
if ([font matrix] != NX_FLIPPEDMATRIX)\
newF = [Font newFont:[font name] size:[font pointSize]\
matrix:NX_FLIPPEDMATRIX];\
else newF = font;\
\
if (sp0.cp == spN.cp) //
\i If the font is at a caret, just go on.
\i0 \
return [super
\b setSelFont
\b0 :newF];\
\
[self
\b undoSelChange
\b0 :"
\b Set Font
\b0 "];\
retval = [super
\b setSelFont
\b0 :newF];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b setSelFontSize
\b0 :(
\b float
\b0 )size \{\
id retval;\
\
[self
\b undoSelChange
\b0 :"
\b Set Font Size
\b0 "];\
retval = [super
\b setSelFontSize
\b0 :size];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b setSelFontFamily
\b0 :(const char *)fontName \{\
id retval;\
\
[self
\b undoSelChange
\b0 :"
\b Set Font Family
\b0 "];\
retval = [super
\b setSelFontFamily
\b0 :fontName];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
-
\b setSelGray
\b0 :(
\b float
\b0 )value \{\
id retval;\
\
[self
\b touch
\b0 ];\
if (sp0.cp == spN.cp) //
\i If the color is at a caret, just go on.\
\i0 return [super
\b setSelGray
\b0 :value];\
\
[self
\b undoSelChange
\b0 :"
\b Set Text Gray
\b0 "];\
retval = [super
\b setSelGray
\b0 :value];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b setSelColor
\b0 :(
\b NXColor
\b0 )color \{\
id retval;\
\
[self
\b touch
\b0 ];\
if (sp0.cp == spN.cp) //
\i If the color is at a caret, just go on.
\i0 \
return [super
\b setSelColor
\b0 :color];\
\
[self
\b undoSelChange
\b0 :"
\b Set Text Color
\b0 "];\
retval = [super
\b setSelColor
\b0 :color];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b Paragraph Changes\
\b0 //\
-
\b pasteRuler
\b0 :sender \{\
id retval;\
[self
\b undoParChange
\b0 :"
\b Paste Ruler
\b0 "];\
retval = [super
\b pasteRuler
\b0 :sender];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b changeTabStopAt
\b0 :(
\b NXCoord
\b0 )oldX
\b to
\b0 :(
\b NXCoord
\b0 )newX \{\
id retval;\
[self
\b undoParChange
\b0 :"
\b Move Tab Stop
\b0 "];\
retval = [super
\b changeTabStopAt
\b0 :oldX
\b to
\b0 :newX];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
-
\b setSelProp
\b0 :(
\b NXParagraphProp
\b0 )prop
\b to
\b0 :(
\b NXCoord
\b0 )val \{\
id retval;\
[self
\b undoParChange
\b0 :"
\b Change Indentation
\b0 "];\
retval = [super
\b setSelProp
\b0 :prop
\b to
\b0 :val];\
[self
\b undoAffectedRange
\b0 :
\b sp0
\b0 .cp to:
\b spN
\b0 .cp];\
return retval;\
\}\
\
//ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\
//
\b UndoManager Delegate\
\b0 //\
-
\b undoManagerWillUndo
\b0 :sender \{ \
return [self
\b registerLastTypingUndo
\b0 ]; \}\
-
\b registerLastTypingUndo
\b0 \{\
if(
\b isTyping
\b0 ) \{\
if ((undoFirstPos != -1) &&(undoFirstPos != undoLastPos)) \{\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\fc1\cf1
\fc0\cf0 [[undoManager setUndoTarget:self] \
\b replaceSel:"" from:
\b0 undoFirstPos
\b to:
\b0 undoLastPos
\b ];
\b0 \
\}
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0
\b \
[undoManager setActionName:"Typing"];\
[undoManager endUndoRecordGrouping];\
\b0 undoFirstPos = undoLastPos = -1;\
\}\
isTyping = NO;\
return self;\
\}\
\i \
@end\
\i0 \
char *
\b undoFilterFunc
\b0 (eText *
\b self
\b0 , unsigned char *
\b text
\b0 , int *
\b len
\b0 , int
\b position
\b0 )\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\fc0\cf0 \{\
int start = self->sp0.cp, end = self->spN.cp;\
id undoManager = self->undoManager;\
\
if(oldTextFilter)
\b text
\b0 = (unsigned char *)(*
\b oldTextFilter
\b0 )\
(self, text, len, position);\
\gray300\fc2\cf2 \
\gray0\fc0\cf0 if (isTyping &&
\b !
\b0 ((
\b end == undoLastPos
\b0 ) || (
\b start
\b0 ==
\b undoFirstPos
\b0 )))\{\
\gray300\fc2\cf2 // If we are typing, and this is not a contiguous extension of the last\
// typing, then close the previous group\
\gray0\fc0\cf0 [self
\b registerLastTypingUndo
\b0 ];\
isTyping = NO;
\gray300\fc2\cf2 // This chains into the code immediately below
\gray0\fc0\cf0 \
\}\
\gray300\fc2\cf2 // If we're not typing yet, get cranking\
\gray0\fc0\cf0 if (!isTyping) \{\
isTyping = YES;\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 [undoManager setActionName:"Typing"];\
[undoManager beginUndoRecordGrouping];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\b0\fc0\cf0 \}\
\
\gray300\fc2\cf2 // This should never get called,since nuking one character already moves sp\
\gray0\fc1\cf1 //if ((start == end) && (text && (*text
\b == DELETE_KEY
\b0 )))\{\
\b // [self setSel:start-1 :end];\
\fc0\cf0 // start = self->sp0.cp, end = self->spN.cp;\
\b0\fc1\cf1 //\}\
\fc0\cf0
\gray300\fc2\cf2 // No matter what, we're about to nuke a section of text.\
// Note that we generate full RTF code for individual characters.\
// Jeff's old code avoided that by snapshotting the _entire_ document...\
\gray0\fc0\cf0 if
\fc1\cf1 (
\b start != end
\b0 ) \{\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 id stream = [[[Stream alloc] init] openMemory];\
[self
\b writeETF
\b0 :[stream
\b stream
\b0 ]
\b from
\b0 :start
\b to
\b0 :end];\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\fc0\cf0 [[[undoManager setUndoTarget:self] freeUndoArgs] \
\b replaceSelWith
\b0 :
\b stream
\b0 from:
\b start
\b0 to:
\b start
\b0 ];\
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\fc0\cf0 \
//[self replaceSel:""];
\b0\gray300\fc2\cf2 // could use objc_msgSendSuper() here\
\b\gray0\fc0\cf0 undoLastPos = start;\
undoFirstPos = start;\
\pard\tx540\tx1080\tx1620\tx2160\tx2700\tx3240\tx3780\tx4320\tx4860\tx5400\tx5940\tx6480\tx7020\tx7560\tx8100\tx8640\tx9180\tx9720\tx10260\tx10800\tx11340\b0\fc1\cf1 \}\
\
\gray300\fc2\cf2 // if it was a delete key, we're done; otherwise we have to undo\
// the subsequent
\i addition
\i0 of keystrokes
\gray0\fc0\cf0 \
\fc1\cf1 if (text && (*text
\b !=
\b0
\b DELETE_KEY
\b0 )) \{\
\fc0\cf0 [[undoManager setUndoTarget:self] \
\b replaceSel:"" from:position to:((position + *len))];
\fc1\cf1 \
\fc0\cf0 undoLastPos = position + *len;\
\b0 if (
\b undoFirstPos
\b0 ==
\b -1
\b0 ) \
\b undoFirstPos
\b0 =
\b position
\b0 ;\
\fc1\cf1 \}\
\fc0\cf0 return ((char *)text);\
\}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.