This is eTextContainer.m in view mode; [Download] [Up]
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTextContainer.m // SUMMARY: Implementation of a general container for eText regions // SUPERCLASS: Object // INTERFACE: None // PROTOCOLS: None // AUTHOR: Rohit Khare // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION COMMENTS // fragile. How to ensure that we have the only "live" handles to the // various embedded objects /////////////////////////////////////////////////////////////////////////////// // HISTORY // 05/08/94: Created. First actual implementation. // Late 93/4 Prototyped and tested in TextTest.app /////////////////////////////////////////////////////////////////////////////// #import "eTextContainer.h" @implementation eTextContainer // id theText // char *theChars; // NXRunArray *theRuns; // int nRuns, nChars; - init { [super init]; theText = nil; theChars = NULL; theRuns = NULL; return self; } - collapse:newText { NXSelPt start, end; int total = 0; NXRun *currentRun, *nextRun; int nextRunCnt; // cut: the contents into a copy in our members theText = newText; [theText getSel:&start :&end]; nChars = end.cp - start.cp; theChars = malloc((nChars+1) * sizeof(wchar)); [theText getSubstring:theChars start:start.cp length:nChars]; if (!theChars[nChars-1]) { // this is for smartcopy/smartpaste nChars--; end.cp--; } if (!theRuns) theRuns = (NXRunArray *)NXChunkZoneMalloc(sizeof(NXRun), sizeof(NXRun), [self zone]); theRuns->chunk.used = 0; total = 0; currentRun = [theText theRuns]->runs; nRuns = nextRunCnt = 0; while (total < end.cp) { if ((total + currentRun->chars) > start.cp) { // do we need to alloc more space? if (theRuns->chunk.used == theRuns->chunk.allocated) { theRuns=(NXRunArray *)NXChunkZoneRealloc((NXChunk *)theRuns,[self zone]); } theRuns->chunk.used += sizeof(NXRun); nextRun = (theRuns->runs) + nextRunCnt++; nRuns++; *nextRun = *currentRun; // how many characters are in our copy? // the current run extends from total to total+chars // we want chars from start.cp to end.cp. // the end points are MAX(start.cp, total) and // MIN(total+chars, end.cp) -- and the length is the diff. nextRun->chars= MIN(total + currentRun->chars, end.cp) - MAX(total, start.cp); // zero-out the info-fields so they don't get freed currentRun->info = nil; } total += currentRun->chars; currentRun++; } // In an undo-enabled system, we want to have a non-traceable delete: [[theText undoManager] disableUndoRegistration]; [theText delete:self]; [[theText undoManager] reenableUndoRegistration]; return self; } - expand:newText { [[theText undoManager] disableUndoRegistration]; [theText replaceSel:theChars length:nChars runs:theRuns]; [[theText undoManager] reenableUndoRegistration]; free(theChars); theChars = NULL; theRuns->chunk.used = 0; theText = nil; return self; } - free { if (theChars) free(theChars); if (theRuns && theRuns->chunk.used != 0) { free(theRuns); } return self = [super free]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.