This is eText.Pasteboard.m in view mode; [Download] [Up]
{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;} \margl40 \margr40 {\colortbl;\red0\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.Pasteboard.m\ \b0 // \i \b SUMMARY \b0 : \b\i0 Implementation of interactions between eText and Pasteboards \b0 \ // \b\i CATEGORY \b0 : \i0 \b Pasteboard \b0 \ // \b\i PROTOCOLS \b0 : \i0 \b None \b0 \ // \b\i INTERFACE \b0 : \i0 \b None \b0 \ // \b\i AUTHOR \b0 : \b\i0 Rohit Khare \b0 \ // \b\i COPYRIGHT \b0 : \f1\i0 Ó \f0\b 1993,94 California Institute of Technology, eText Project\ \b0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i Implementation Comments \b0\i0 \ // All actions should get routed to read/write \i Selection \i0 To/From \i Pasteboard \i0 .\ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i History \b0\i0 \ // 02/12/95: \b Changed Pasting policy to prefer creation of annotiations. \b0 \ // 11/20/94: \b Realized that most apps can't handle filename && ASCII, stupidly. \b0 \ // 11/20/94: \b Extended to use writeASCII on copying selections to PBoard. \b0 \ // 10/31/94: \b Added detectors for smartPaste. \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.Pasteboard.h \b0 "\ \ #define \b eTETFPboardType \b0 NXUniqueString(" \b eText ETF pasteboard type \b0 ")\ \ \i @implementation eText(Pasteboard)\ \i0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Centralized Selection Management \b0 \ //\ - \b readSelectionFromPasteboard \b0 :pboard \{\ return [self \b readSelectionFromPasteboard \b0 :pboard \b linked \b0 : \b NO \b0 ];\}\ - \b readSelectionFromPasteboard \b0 :pboard \b linked \b0 :( \b BOOL \b0 )isLinked \{\ \b NXSelPt \b0 a,b;\ \b NXStream \b0 * \b memstream \b0 ;\ NXAtom \b supportedTypes \b0 [9];\ NXAtom \b foundType \b0 ;\ \ // \i 1) is there a selection? what types do we have?\ \i0 [self \b getSel \b0 :&a :&b];\ if (!((a. \b cp \b0 \b >= 0 \b0 ) && [self \b isEditable \b0 ]))\ return \b nil \b0 ;\ \ // \i All possible "Pasteable" types: \i0 \ supportedTypes[0] = \b eTETFPboardType \b0 ;\ supportedTypes[1] = \b NXRTFDPboardType \b0 ;\ supportedTypes[2] = \b NXRTFPboardType \b0 ;\ supportedTypes[3] = \b NXTabularTextPboardType \b0 ;\ supportedTypes[4] = \b NXAsciiPboardType \b0 ;\ supportedTypes[5] = \b NXColorPboardType \b0 ;\ supportedTypes[6] = \b NXFontPboardType \b0 ;\ supportedTypes[7] = \b NXRulerPboardType \b0 ;\ supportedTypes[8] = \b NXFilenamePboardType \b0 ;\ supportedTypes[9] = NULL;\ \b foundType \b0 = [pboard \b findAvailableTypeFrom \b0 : \b supportedTypes \b0 num: \b 2 \b0 ];\ \ // \i 2) If we found nothing, try creating an Annotation for it\ \i0 // \i 2a) NEW POLICY: If we can create an annotation, && no etf, do it\ \i0 if ( \b !foundType && \b0 [etApp \b annotationByPboard \b0 : \b pboard \b0 ]) \{\ [self \b insertAnnotation \b0 : [[[etApp \b annotationByPboard \b0 : \b pboard \b0 ] alloc]\ \b initFromPboard \b0 : \b pboard \b0 \b inDoc \b0 : \b etDoc \b0 \b linked \b0 : \b isLinked \b0 ]];\ \ \b foundType \b0 = [pboard \b findAvailableTypeFrom \b0 : \b supportedTypes \b0 num: \b 8 \b0 ];\ \ // \i e) If we have filenames, parse them out and instantiate each one. \i0 \ \b // \i NOTE THAT THIS DOESN'T WORK YET!!!!!! FIX ME!\ \b0\i0 \} else if (foundType == \b NXFilenamePboardType \b0 ) \{\ NXLogError(" \b eText tried to read an NXFilenamePboardType. \b0 ");\ [self insertAnnotation: [[[etApp annotationByPboard:pboard] alloc]\ initFromPboard:pboard inDoc:etDoc linked:isLinked]];\ // \i 3) do we have RTFD? This is a _very_ special case, and is mutex to ETF\ \i0 \} else if (foundType == \b NXRTFDPboardType \b0 ) \{\ // \b\i this is really gruesome code. Don't look \b0\i0 .\ \b Text \b0 * \b rtfd \b0 ;\ \b NXRect \b0 \b rect \b0 ;\ \b Class \b0 \b oldHandler \b0 ;\ \ // \i unload the old \\NeXTGraphic handler \i0 \ \b oldHandler \b0 = [eText classForDirective:" \b NeXTGraphic \b0 "];\ // \i And load in NeXT's crap. All cause they serialize to a private form. \i0 \ [eText \b registerDirective \b0 :" \b NeXTGraphic \b0 " \ \b forClass \b0 :[Text \b graphicCellClass \b0 ]];\ rect.origin.x = 0; rect.origin.y = 0;\ rect.size.height = MAXFLOAT; rect.size.width = MAXFLOAT;\ \b rtfd \b0 = [[ \b Text \b0 alloc] \b initFrame \b0 :& \b rect \b0 ]; // \i NeXT's Text class \i0 \ [rtfd \b setMonoFont \b0 : \b NO \b0 ];\ [rtfd \b setGraphicsImportEnabled \b0 : \b YES \b0 ];\ [rtfd \b setSel \b0 :0 :[rtfd \b textLength \b0 ]];\ [ \b rtfd \b0 \b readSelectionFromPasteboard \b0 : \b pboard \b0 ]; // \i Text \i0 \i groks RTFD \i0 \ if ([rtfd textLength]) \{\ \b NXRTFDError \b0 \b ret \b0 ;\ \ \b ret \b0 =[rtfd \b saveRTFDTo \b0 :" \b /tmp/eTextRTFDConversionStoreFile.rtfd \b0 "\ \b removeBackup \b0 :YES \b errorHandler \b0 :nil];\ // \i get that crappy NXGraphicCell code out of my kernel NOW!!! \i0 \ rtfd = [rtfd \b free \b0 ];\ [eText \b registerDirective \b0 :" \b NeXTGraphic \b0 " \ \b forClass \b0 : \b oldHandler \b0 ];\ \ if (ret == \b NX_RTFDErrorNone \b0 ) \{\ NXAtom oldP,oldT; int start;\ \ // \i now parse in the good stuff \i0 \ // \i temporarily set this doc's docInfoPath to tempName \i0 \ \b oldP \b0 = [[etDoc \b docInfo \b0 ] \b docPath \b0 ];\ \b oldT \b0 = [[etDoc \b docInfo \b0 ] \b docTitle \b0 ];\ start = sp0.cp;\ [[etDoc \b docInfo \b0 ]\ \b setDocPath \b0 :" \b /tmp/eTextRTFDConversionStoreFile.rtfd \b0 "];\ \ // \i issue a read for the "RTF" part of the data \i0 \ [self \b undoSelChange \b0 :" \b Paste RTFD \b0 "];\ [ \b super \b0 \b readSelectionFromPasteboard \b0 :pboard];\ [self \b undoAffectedRange \b0 :start \b to \b0 :spN.cp];\ \ // \i preserves the traditional semantics of pasting \i0 \ // \i since readSelection doesn't move the cursor \i0 \ [self \b setSel \b0 :sp0.cp :sp0.cp];\ \ [[etDoc \b docInfo \b0 ] \b setDocPath \b0 :oldP];\ [[etDoc \b docInfo \b0 ] \b setDocTitle \b0 :oldT];\ \}\ \i // unfortunately, the objects created may want persistent\ // access to the files on disk, so we can't nuke them.\ // There's possibly a bug here relating to the use of a single,\ // shared ConversionStoreFile to hold all this shit.\ // Oh, for want of a OOfilesystem with autorelease!\ \i0 \}\ // \i get that crappy NXGraphicCell code out of my kernel NOW!!! \i0 \ [eText \b registerDirective \b0 :" \b NeXTGraphic \b0 " \ \b forClass \b0 : \b oldHandler \b0 ];\ // \i 4) do we have ETF or RTF (in that preference order?)\ \i0 \} else if ((foundType == \b eTETFPboardType \b0 ) ||\ (foundType == \b NXRTFPboardType \b0 ))\{\ // \i OK, just paste in the ETF/RTF code \i0 \ \b memstream \b0 = [pboard \b readTypeToStream \b0 : \b foundType \b0 ];\ if (memstream) \{\ char buf[3]; int \b smart \b0 =0; // \i Default is to assume dumbpaste \i0 \ int start = sp0.cp;\ \ if ([self getSubstring: \b buf \b0 start: \b spN \b0 .cp length: \b 1 \b0 ] != -1)\{\ \b smart \b0 = ( \b strchr \b0 ( \b\fc1\cf1 postSelSmartTable \b0 , buf[0] \fc0\cf0 ) ? 0 : 1);\ \}\ [self \b undoSelChange \b0 :" \b Paste ETF/RTF \b0 "];\ [self \b replaceSelWithRichText \b0 : \b memstream \b0 ]; // \i subsumes ETF as well \i0 .\ if (!( \b smart \b0 &&\ ([self getSubstring: \b buf \b0 start: \b spN \b0 .cp length: \b 1 \b0 ] != -1) &&\ (buf[0] == ' ')))\ \b smart = 0 \b0 ;\ [self \b undoAffectedRange \b0 :start \b to \b0 :(spN.cp + \b smart \b0 )];\ \b NXCloseMemory \b0 ( \b memstream \b0 , NX_FREEBUFFER);\ \}\ // \i 5) do we have ASCII or Tabular Text?\ \i0 \}else if ((foundType == \b NXAsciiPboardType \b0 ) ||\ (foundType == \b NXTabularTextPboardType \b0 ))\{\ // \i OK, just paste in the ASCII code \i0 \ char *data; int len, \b start \b0 = \b sp0.cp \b0 ;\ \ [self \b undoSelChange \b0 :" \b Paste PlainText \b0 "];\ [pboard \b readType \b0 : \b foundType \b0 data:&data length:&len];\ [self \b replaceSel \b0 :data \b length \b0 :len]; // \i subsumes TabText as well \i0 .\ [pboard \b deallocatePasteboardData \b0 :data length:len];\ [self \b undoAffectedRange \b0 :start \b to \b0 :spN.cp];\ return self;\ // \i 6) do we have Color data?\ \i0 \} else if (foundType == \b NXColorPboardType \b0 ) \{\ [self \b setSelColor \b0 : \b NXReadColorFromPasteboard \b0 (pboard)];\ // \i 7) do we have Font data? \i0 \ // \i 8) do we have Ruler data?\ \i0 \} else if ((foundType == \b NXFontPboardType \b0 ) ||\ (foundType == \b NXRulerPboardType \b0 )) \{\ // \i this is kind of funky: we pull a little switcheroo on Text \i0 \ id \b targetPboard \b0 ;\ char * \b saveData \b0 ,* \b newData \b0 ;\ int \b saveLen \b0 , \b newLen \b0 ;\ NXAtom \b targetType \b0 [1];\ \ // \i determine the targetPboard \i0 \ if (foundType == \b NXRulerPboardType \b0 ) \{\ targetPboard = [Pasteboard newName: \b NXRulerPboard \b0 ];\ *targetType = \b NXRulerPboardType \b0 ;\ \} else \{\ targetPboard = [Pasteboard newName: \b NXFontPboard \b0 ];\ *targetType = \b NXFontPboardType \b0 ;\ \}\ \ // \i save data from targetPboard \i0 \ [ \b targetPboard \b0 \b readType \b0 :* \b targetType\ \b0 data:&saveData length:&saveLen];\ \ // \i copy data from pboard to targetPboard \i0 \ [ \b pboard \b0 \b readType \b0 :* \b targetType\ \b0 data:&newData length:&newLen];\ [ \b targetPboard \b0 \b declareTypes \b0 : \b targetType \b0 num:1 owner:nil];\ [ \b targetPboard \b0 \b writeType \b0 :* \b targetType \b0 data:newData length:newLen];\ \ // \i perform operation \i0 \ if (foundType == \b NXRulerPboardType \b0 ) \{\ [self \b pasteRuler \b0 :self];\ \} else \{\ [self \b pasteFont \b0 :self];\ \}\ \ // \i restore data to targetPboard \i0 \ [ \b targetPboard \b0 \b declareTypes \b0 : \b targetType \b0 num:1 owner:nil];\ [ \b targetPboard \b0 \b writeType \b0 :* \b targetType \b0 data:saveData length:saveLen];\ \ // \i free both datas \i0 \ [ \b targetPboard \b0 \b deallocatePasteboardData \b0 : \b saveData \b0 length:saveLen];\ [ \b pboard \b0 \b deallocatePasteboardData \b0 : \b newData \b0 length:newLen];\ \} \ return self;\ \}\ - \b writeSelectionToPasteboard \b0 :pboard \{\ \b NXSelPt \b0 a,b;\ int pos,k,N;\ \b NXRun \b0 * \b curr \b0 ;\ \b NXStream \b0 * \b memstream \b0 ;\ NXAtom \b supportedTypes \b0 [5];\ \ // \i 1) is there a selection of nonzero length?\ \i0 [self \b getSel \b0 :&a :&b];\ if (!(( \b a.cp >=0 \b0 ) && [self \b isEditable \b0 ] && ( \b b.cp != a.cp \b0 ))) return \b nil \b0 ;\ \ // \i 2) Initialize our pboard\ // after some extensive experimentation, calling writeSelection does\ // seem to work after all. The issue is that a real "copy" can have a\ // "NeXT smart paste pasteboard type" which wstopb cannot. Tests in\ // Edit reveal that this has no effect. Some keen user may find one though. \ \i0 supportedTypes[0] = \b eTETFPboardType \b0 ;\ supportedTypes[1] = \b NXRTFPboardType \b0 ;\ supportedTypes[2] = \b NXAsciiPboardType \b0 ;\ supportedTypes[ \b 3 \b0 ] = \b NXFilenamePboardType \b0 ;\ supportedTypes[ \b 3 \b0 ] = \b NULL \b0 ;\ supportedTypes[4] = NULL;\ [ \b pboard \b0 \b declareTypes \b0 : \b supportedTypes \b0 num: \b\fs36 3 \b0\fs24 owner: \b nil \b0 ];\ \ \b memstream \b0 = \b NXOpenMemory \b0 (NULL,0,NX_READWRITE);\ if (memstream) \{\ [self \b writeETF \b0 : \b memstream \b0 \b from \b0 :sp0.cp \b to \b0 :spN.cp];\ [pboard \b writeType \b0 : \b eTETFPboardType \b0 \b fromStream \b0 : \b memstream \b0 ];\ \b NXCloseMemory \b0 ( \b memstream \b0 , NX_FREEBUFFER);\ \}\ \ \b memstream \b0 = \b NXOpenMemory \b0 (NULL,0,NX_READWRITE);\ if (memstream) \{\ [self \b writeRTF \b0 :memstream \b from \b0 :sp0.cp \b to \b0 :spN.cp];\ [pboard \b writeType \b0 : \b NXRTFPboardType \b0 \b fromStream \b0 : \b memstream \b0 ];\ \b NXCloseMemory \b0 ( \b memstream \b0 , NX_FREEBUFFER);\ \}\ \ \b memstream \b0 = \b NXOpenMemory \b0 (NULL,0,NX_READWRITE);\ if (memstream) \{\ [self \b writeASCII \b0 :memstream \b from \b0 :sp0.cp \b to \b0 :spN.cp];\ [pboard \b writeType \b0 : \b NXAsciiPboardType \b0 \b fromStream \b0 : \b memstream \b0 ];\ \b NXCloseMemory \b0 ( \b memstream \b0 , NX_FREEBUFFER);\ \}\ \ \i // [pboard \b writeType \b0 : \b NXFilenamePboardType \b0 \b data \b0 :[[etDoc \b docInfo \b0 ] \b docPath \b0 ]\ // \b length \b0 : \b strlen \b0 ([[etDoc \b docInfo \b0 ] \b docPath \b0 ]) \b +1 \b0 ];\ \i0 \ // \i 3) are there Annotations in our selection?\ \i0 pos=0;\ N = theRuns->chunk.used/sizeof(NXRun);\ curr = theRuns->runs;\ for (k=0; ((k < N) && (b.cp > pos)); k++) \{\ if ((curr->info) && (a.cp <= pos) && \ [curr-> \b info \b0 \b respondsTo \b0 :@selector( \b addToPboard: \b0 )]) \ [curr-> \b info \b0 \b addToPboard \b0 : \b pboard \b0 ];\ \i // this is kosher because a second addType of the same type fails.\ // but a second writeType:of a different type might!\ \i0 pos += curr->chars;\ curr++;\ \}\ return self;\ \}\ - ( \b BOOL \b0 ) \b writeSelectionToPasteboard \b0 :pboard \b types \b0 :( \b NXAtom \b0 *)types\ \{\ id retVal;\ int \b numTypes \b0 = \b 0 \b0 ;\ \ retVal=[self \b writeSelectionToPasteboard \b0 :pboard];\ // \i now check to see that one of _types_ is on the pboard to return YES \i0 \ while(types && types[numTypes])\{ \ \i \i0 if (types[numTypes] == \b NXFilenamePboardType \b0 ) \{\ if (retVal)\ [pboard \b addTypes \b0 :&(types[numTypes]) num: \b 1 \b0 owner: \b nil \b0 ];\ else \ [pboard \b declareTypes \b0 :&(types[numTypes]) num: \b 1 \b0 owner: \b nil \b0 ];\ [pboard \b writeType \b0 : \b NXFilenamePboardType \b0 \b data \b0 :[[etDoc \b docInfo \b0 ] \b docPath \b0 ]\ \b length \b0 : \b strlen \b0 ([[etDoc \b docInfo \b0 ] \b docPath \b0 ]) \b +1 \b0 ];\ \}\ \b numTypes++ \b0 ; // \i Counter\ \i0 \}\ \b return \b0 ([pboard \b findAvailableTypeFrom \b0 : \b types \b0 \b num \b0 : \b numTypes \b0 ] ? \b YES \b0 : \b NO \b0 );\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Dropping \b0 \ //\ - ( \b NXDragOperation \b0 ) \b draggingEntered \b0 :(id <NXDraggingInfo>)sender \{\ return [self \b draggingUpdated \b0 :sender];\}\ - ( \b NXDragOperation \b0 ) \b draggingUpdated \b0 :(id <NXDraggingInfo>)sender \{\ NXSelPt a,b;\ NXPoint p;\ NXCoord l,r,t,bot;\ \b NXDragOperation \b0 \b sourceMask \b0 = [sender \b draggingSourceOperationMask \b0 ];\ \ // \i Check for self-drags \i0 \ [self \b getMarginLeft \b0 :&l right:&r top:&t bottom:&bot]; \ \b p \b0 = [sender \b draggingLocation \b0 ];\ if (( \b p.x \b0 < ( \b l + SCROLLWIDTH \b0 )) && ([sender \b draggingSource \b0 ] == \b self \b0 ))\ return \b NX_DragOperationNone \b0 ;\ \ // \i Check that the selection exists and isEditable \i0 \ [self getSel:&a :&b];\ if (!(( \b a.cp >=0 \b0 ) && [self \b isEditable \b0 ]))\ return \b NX_DragOperationNone \b0 ;\ \ \i // It would be really nice to check whether the dragging Source is an\ // Annotation and is *within* the current selection (auto-destruct!)\ // Instead, it is the responsibility of each Annotation (see eTImage)\ // Also, consider laying the image in the window at the insertionPoint\ \i0 \ if (sourceMask & \b NX_DragOperationLink \b0 ) \{\ return NX_DragOperationLink;\ \} else if (sourceMask & \b NX_DragOperationCopy \b0 ) \{\ return NX_DragOperationCopy;\ \} else if (sourceMask & \b NX_DragOperationGeneric \b0 ) \{\ return NX_DragOperationGeneric;\ \}\ return \b NX_DragOperationNone \b0 ;\ \}\ - ( \b BOOL \b0 ) \b prepareForDragOperation \b0 :(id <NXDraggingInfo>)sender \{\ \i // Future Feature: slide to the insertion point? NXSelPt sp0?\ // Edit implementation: remove the temp image of *entered/exit\ \i0 return \b YES \b0 ;\ \}\ - ( \b BOOL \b0 ) \b performDragOperation \b0 :(id <NXDraggingInfo>)sender \{\ [self \b readSelectionFromPasteboard \b0 :[sender \b draggingPasteboard \b0 ] \ \b linked \b0 :([sender \b draggingSourceOperationMask \b0 ] & \b NX_DragOperationLink \b0 )];\ return \b YES \b0 ;\ \}\ - \b concludeDragOperation \b0 :(id <NXDraggingInfo>)sender \{\ [[self \b window \b0 ] \b makeKeyAndOrderFront \b0 :self];\ return self;\ \}\ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Changing Fonts \b0 \ //\ - \b acceptFont \b0 :(Font *)fontA \b atPoint \b0 :(NXPoint *)p \{\ id font;\ \ if ([fontA \b matrix \b0 ] != \b NX_FLIPPEDMATRIX \b0 )\ \b font \b0 = [Font \b newFont \b0 :[fontA name] \ size:[fontA pointSize] \ matrix: \b NX_FLIPPEDMATRIX \b0 ];\ else \b font \b0 = fontA;\ \ if (sp0.cp == spN.cp) // \i "insert" a font at a flashing caret.\ \i0 [self \b setSel \b0 :sp0.cp :(sp0.cp+1)];\ [self \b setSelFont \b0 : \b font \b0 ]; // \i undo is in setSelFont: \i0 \ // \i [self \b setSel \b0 :sp0.cp :spN.cp]; Remind Text object where the selection is! \i0 \ return self;\ \}\ - \b replaceFont \b0 :(Font *)oldFontA \b with \b0 :(Font *)newFontA \{\ id oldFont, newFont;\ int k,N;\ NXRun *curr;\ \ // \i First, check that the font matrices are in order \i0 \ if ([oldFontA \b matrix \b0 ] != \b NX_FLIPPEDMATRIX \b0 )\ \b oldFont \b0 = [Font \b newFont \b0 :[ \b oldFontA \b0 name] \ size:[ \b oldFontA \b0 pointSize] \ matrix: \b NX_FLIPPEDMATRIX \b0 ];\ else \b oldFont \b0 = oldFontA;\ \ if ([newFontA \b matrix \b0 ] != \b NX_FLIPPEDMATRIX \b0 )\ \b newFont \b0 = [Font \b newFont \b0 :[ \b newFontA \b0 name] \ size:[ \b newFontA \b0 pointSize] \ matrix: \b NX_FLIPPEDMATRIX \b0 ];\ else \b newFont \b0 = newFontA;\ \ // \i Freeze the display, Loop over all the NXRuns, recalc \i0 \ [[self window] \b disableFlushWindow \b0 ];\ \b N \b0 = \b theRuns \b0 ->chunk. \b used \b0 /sizeof(NXRun);\ \b curr \b0 = theRuns-> \b runs \b0 ;\ for (k=0; \b k < N \b0 ; k++) \{\ if ( \b curr->font \b0 == \b oldFont \b0 ) \b \ curr->font \b0 = \b newFont \b0 ; \ curr++;\ \} \ [self \b calcLine \b0 ];\ [[[[self window] \b display \b0 ] \b reenableFlushWindow \b0 ] \b\fc1\cf1 flushWindowIfNeeded \b0\fc0\cf0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Edit Menu \b0 \ //\ - \b copy \b0 :sender \{\ [self \b writeSelectionToPasteboard \b0 :[Pasteboard newName: \b NXGeneralPboard \b0 ]];\ return self;\ \}\ - \b paste \b0 :sender \{\ return [self \b readSelectionFromPasteboard \b0 :[Pasteboard newName: \b NXGeneralPboard \b0 ]];\ \}\ - \b clear \b0 :sender \{\ return [self \b delete \b0 :sender];\}\ - \b delete \b0 :sender \{\ id retval;\ if ( \b sp0 \b0 .cp \b == \b0 \b spN \b0 .cp) return \b nil \b0 ;\ [self \b undoSelChange \b0 :" \b Delete Selection \b0 "];\ retval = [super \b delete \b0 :sender];\ [self \b undoAffectedRange \b0 : \b sp0 \b0 .cp \b to \b0 : \b sp0 \b0 .cp];\ return retval;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Services Menu \b0 \ //\ - \b validRequestorForSendType \b0 :(NXAtom)typeSent\ \b andReturnType \b0 :(NXAtom)typeReturned\ \{\ \i // OK, so sue me, we can't advertise that we send images and audio\ // by actually confirming it dynamically -- that's too damn expensive\ // Originally, we only checked if the sent type was one of:\ // NXFilenamePboardType,NXAsciiPboardType,NXRTFPboardType\ // Now, we just say what the hell and return self.\ // If the requestor actually wanted audio data and the selection is\ // text, tough luck. But this way, EqB's Edit Equation works...\ \i0 if ( \b typeReturned \b0 && ( \b ! \b0 [self \b isEditable \b0 ])) return \b nil \b0 ;\ return \b self \b0 ;\ \}\ \ \i @end }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.