home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- // 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