home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Examples / AppKit / Draw / compatibility.m < prev    next >
Text File  |  1996-04-05  |  21KB  |  775 lines

  1. #import "draw.h"
  2. #import "compatibility.h"
  3.  
  4. /*
  5.  * This file is for compatibility with reading old draw files.
  6.  * Once we start using property lists for the pasteboard, we can even
  7.  * remove the -encodeWithCoder: and +initialize: methods below.
  8.  */
  9.  
  10. /*
  11.  * This is just a convenience method for reading old Draw files that
  12.  * have List classes archived in them.  It creates an NSMutableArray
  13.  * out of the passed in List.  It frees the List (it does this because
  14.  * it assumes you are converting to the new world and what nothing to
  15.  * do with the old world).
  16.  */
  17.  
  18. @implementation NSMutableArray(Compatibility)
  19.  
  20. - (id)initFromList:(id)aList
  21. {
  22.     int i, count;
  23.  
  24.     if ([aList isKindOf:[List class]]) {
  25.         count = [aList count];
  26.         [self initWithCapacity:count];
  27.         for (i = 0; i < count; i++) {
  28.             [self addObject:[aList objectAt:i]];
  29.         }
  30.     } else if ([aList isKindOf:[NSArray class]]) {
  31.         return [self initWithArray:aList];
  32.     } else {
  33.         /* should probably raise */
  34.     }
  35.  
  36.     return self;
  37. }
  38.  
  39. @end
  40.  
  41. @interface Graphic(FileCompatibility)
  42.  
  43. - (Graphic *)replaceWithImage;
  44. - (id)initWithCoder:(NSCoder *)stream;
  45. - (void)encodeWithCoder:(NSCoder *)stream;
  46.  
  47. @end
  48.  
  49. @interface Tiff : Graphic
  50. {
  51.     NSData *newData;
  52. }
  53.  
  54. - (Graphic *)replaceWithImage;
  55. - (id)initWithCoder:(NSCoder *)stream;
  56.  
  57. @end
  58.  
  59. @interface PSGraphic : Graphic
  60. {
  61.     NSMutableData *newData;
  62. }
  63.  
  64. - (Graphic *)replaceWithImage;
  65. - (id)initWithCoder:(NSCoder *)stream;
  66.  
  67. @end
  68.  
  69. @implementation Circle(FileCompatibility)
  70.  
  71. + (void)initialize
  72. /*
  73.  * This bumps the class version so that we can compatibly read
  74.  * old Graphic objects out of an archive.
  75.  */
  76. {
  77.     [Circle setVersion:1];
  78. }
  79.  
  80. @end
  81.  
  82. @implementation Curve(FileCompatibility)
  83.  
  84. + (void)initialize
  85. /*
  86.  * This bumps the class version so that we can compatibly read
  87.  * old Graphic objects out of an archive.
  88.  */
  89. {
  90.     [Curve setVersion:1];
  91. }
  92.  
  93. @end
  94.  
  95. @implementation Graphic(FileCompatibility)
  96.  
  97. + (void)initialize
  98. /*
  99.  * This sets the class version so that we can compatibly read
  100.  * old Graphic objects out of an archive.
  101.  */
  102. {
  103.     [Graphic setVersion:5];
  104. }
  105.  
  106. /* Compatibility method for old PSGraphic and Tiff classes. */
  107.  
  108. - (Graphic *)replaceWithImage
  109. {
  110.     return self;
  111. }
  112.  
  113. - (void)encodeWithCoder:(NSCoder *)stream
  114. {
  115.     gFlags.linewidthSet = (linewidth != 0.0);
  116.     gFlags.lineColorSet = lineColor ? YES : NO;
  117.     gFlags.fillColorSet = fillColor ? YES : NO;
  118.     [stream encodeValuesOfObjCTypes:"ffffii", &bounds.origin.x, &bounds.origin.y,
  119.     &bounds.size.width, &bounds.size.height, &gFlags, &identifier];
  120.     if (gFlags.linewidthSet) [stream encodeValuesOfObjCTypes:"f", &linewidth];
  121.     if (gFlags.lineColorSet) [stream encodeObject:lineColor];
  122.     if (gFlags.fillColorSet) [stream encodeObject:fillColor];
  123. }
  124.  
  125. - (id)initWithCoder:(NSCoder *)stream
  126. {
  127.     
  128.     int version;
  129.     float gray = NSBlack;
  130.  
  131.     version = [stream versionForClassName:[NSString stringWithCString:"Graphic"]];
  132.     if (version > 2) {
  133.     [stream decodeValuesOfObjCTypes:"ffffii", &bounds.origin.x, &bounds.origin.y,
  134.         &bounds.size.width, &bounds.size.height, &gFlags, &identifier];
  135.     } else if (version > 1) {
  136.     [stream decodeValuesOfObjCTypes:"ffffsi", &bounds.origin.x, &bounds.origin.y,
  137.         &bounds.size.width, &bounds.size.height, &gFlags, &identifier];
  138. #ifdef __LITTLE_ENDIAN__
  139.     *(unsigned int *)&gFlags = *(unsigned int *)&gFlags <<= 16;
  140. #endif    
  141.     } else {
  142.     [stream decodeValuesOfObjCTypes:"ffffs", &bounds.origin.x, &bounds.origin.y,
  143.         &bounds.size.width, &bounds.size.height, &gFlags];
  144. #ifdef __LITTLE_ENDIAN__
  145.     *(unsigned int *)&gFlags = *(unsigned int *)&gFlags <<= 16;
  146. #endif    
  147.     identifier = [[self class] nextCurrentGraphicIdentifier];
  148.     }
  149.     if (version > 1 && identifier >= [[self class] currentGraphicIdentifier]) [[self class] updateCurrentGraphicIdentifier:identifier+1];
  150.     if (gFlags.linewidthSet) [stream decodeValuesOfObjCTypes:"f", &linewidth];
  151.     if (version < 1) {
  152.     if (gFlags.lineColorSet) [stream decodeValuesOfObjCTypes:"f", &gray];
  153.     if (gFlags.fillColorSet && (gFlags.eofill | gFlags.fill)) {
  154.         lineColor = NSZoneMalloc((NSZone *)[self zone], (1) * sizeof(NSColor *));
  155.         lineColor = [[NSColor blackColor] retain];
  156.         fillColor = NSZoneMalloc((NSZone *)[self zone], (1) * sizeof(NSColor *));
  157.         fillColor = [[NSColor colorWithCalibratedWhite:gray alpha:1.0] retain];
  158.     } else if (gFlags.eofill | gFlags.fill) {
  159.         fillColor = NSZoneMalloc((NSZone *)[self zone], (1) * sizeof(NSColor *));
  160.         fillColor = [[NSColor colorWithCalibratedWhite:gray alpha:1.0] retain];
  161.         [self setOutlined:NO];
  162.     } else {
  163.         lineColor = NSZoneMalloc((NSZone *)[self zone], (1) * sizeof(NSColor *));
  164.         lineColor = [[NSColor colorWithCalibratedWhite:gray alpha:1.0] retain];
  165.     }
  166.     } else {
  167.     if (gFlags.lineColorSet) {
  168.         if (version < 5) {
  169.                 lineColor = [stream decodeNXColor];
  170.         } else {
  171.                 lineColor = [stream decodeObject];
  172.             }
  173.         if ([lineColor isEqual:[NSColor clearColor]]) {
  174.         lineColor = NULL;
  175.         [self setOutlined:NO];
  176.         } else {
  177.         [lineColor retain];
  178.         }
  179.     }
  180.     if (gFlags.fillColorSet) {
  181.             if (version < 5) {
  182.                 fillColor = [stream decodeNXColor];
  183.             } else {
  184.                 fillColor = [stream decodeObject];
  185.             }
  186.         if ([fillColor isEqual:[NSColor clearColor]] || ([fillColor alphaComponent] == 0.0)) {
  187.         fillColor = NULL;
  188.         [self setFill:FILL_NONE];
  189.         } else {
  190.         [fillColor retain];
  191.         }
  192.     }
  193.     }
  194.     
  195.     // from old awake method
  196.     [[self class] initClassVars];
  197.     
  198.     return self;
  199.  
  200. }
  201.  
  202. @end
  203.  
  204. @interface GraphicView(PrivateMethods)
  205. - (void)resetGUP;
  206. - (NSView *)createEditView;
  207. @end
  208.  
  209. @implementation GraphicView(FileCompatibility)
  210.  
  211. + (void)initialize
  212. /*
  213.  * We up the version of the class so that we can read old .draw files.
  214.  * See the read: method for how we use the version.
  215.  */
  216. {
  217.     [GraphicView setVersion:1];
  218. }
  219.  
  220. - (void)encodeWithCoder:(NSCoder *)stream
  221. {
  222.     
  223.     [super encodeWithCoder:stream];
  224.     [stream encodeValuesOfObjCTypes:"@sf", &glist, &gvFlags, &gridGray];
  225.     [stream encodeObject:editView];
  226.  
  227. }
  228.  
  229. - (id)initWithCoder:(NSCoder *)stream
  230. // Comment from the old awake method...
  231. /*
  232.  * After the GraphicView is unarchived, its cache must be created.
  233.  * If we are loading in this GraphicView just to print it, then we need
  234.  * not load up our cache.
  235.  */
  236. {
  237.     
  238.     int i;
  239.     NSArray *evsvs;
  240.     Graphic *graphic, *newGraphic;
  241.  
  242.     self = [super initWithCoder:stream];
  243.     [stream decodeValuesOfObjCTypes:"@sf", &glist, &gvFlags, &gridGray];
  244.     glist = [[NSMutableArray allocWithZone:[self zone]] initFromList:glist];
  245.     for (i = [glist count]-1; i >= 0; i--) {
  246.     graphic = [glist objectAtIndex:i];
  247.     newGraphic = [graphic replaceWithImage];
  248.     if (graphic != newGraphic) {
  249.         if (graphic) {
  250.         [glist replaceObjectAtIndex:i withObject:newGraphic];
  251.         } else {
  252.         [glist removeObjectAtIndex:i];
  253.         }
  254.     }
  255.     }
  256.     slist = [[NSMutableArray allocWithZone:[self zone]] initWithCapacity:[glist count]];
  257.     [self getSelection];
  258.     [self resetGUP];
  259.     if ([stream versionForClassName:@"GraphicView"] < 1) {
  260.     editView = [self createEditView];
  261.     } else {
  262.     editView = [[stream decodeObject] retain];
  263.     }
  264.  
  265.     evsvs = [editView subviews];
  266.     for (i = [evsvs count]-1; i >= 0; i--) {
  267.         [[evsvs objectAtIndex:i] release];
  268.     }
  269.     // from the old awake method
  270.     PSInit();
  271.     if (!InMsgPrint) {
  272.         NSRect bounds = [self bounds];
  273.         cacheImage = [[NSImage allocWithZone:[self zone]] initWithSize:bounds.size];
  274.     [self cache:bounds andUpdateLinks:NO];
  275.     }
  276.     [[self class] initClassVars];
  277.     [self registerForDragging];
  278.     
  279.     return self;
  280.  
  281. }
  282.  
  283. @end
  284.  
  285. @implementation Group(FileCompatibility)
  286.  
  287. - (Graphic *)replaceWithImage
  288. /*
  289.  * Since we got rid of Tiff and PSGraphic and replaced them
  290.  * with the unified Image graphic, we need to go through our
  291.  * list and replace all of them with an Image graphic.
  292.  */
  293. {
  294.     int i;
  295.     Graphic *graphic, *newGraphic;
  296.  
  297.     for (i = [components count]-1; i >= 0; i--) {
  298.         graphic = [components objectAtIndex:i];
  299.         newGraphic = [graphic replaceWithImage];
  300.         if (graphic != newGraphic) {
  301.             if (graphic) {
  302.                 [components replaceObjectAtIndex:i withObject:newGraphic];
  303.             } else {
  304.                 [components removeObjectAtIndex:i];
  305.             }
  306.         }
  307.     }
  308.  
  309.     return self;
  310. }
  311.  
  312. + (void)initialize
  313. /*
  314.  * This bumps the class version so that we can compatibly read
  315.  * old Graphic objects out of an archive.
  316.  */
  317. {
  318.     [Group setVersion:3];
  319. }
  320.  
  321. - (void)encodeWithCoder:(NSCoder *)stream
  322. {
  323.     [super encodeWithCoder:stream];
  324.     [stream encodeValuesOfObjCTypes:"@", &components];
  325.     [stream encodeValueOfObjCType:"c" at:&dontCache];
  326.     [stream encodeRect:lastRect];
  327.     [stream encodeValueOfObjCType:"c" at:&hasTextGraphic];
  328. }
  329.  
  330. static BOOL checkForTextGraphic(NSArray *list)
  331. {
  332.     int i;
  333.     Graphic *graphic;
  334.  
  335.     for (i = [list count]-1; i >= 0; i--) {
  336.         graphic = [list objectAtIndex:i];
  337.         if ([graphic isKindOfClass:[TextGraphic class]] || ([graphic isKindOfClass:[Group class]] && [(Group *)graphic hasTextGraphic])) return YES;
  338.     }
  339.  
  340.     return NO;
  341. }
  342.  
  343. - (id)initWithCoder:(NSCoder *)stream
  344. {
  345.  
  346.     self = [super initWithCoder:stream];
  347.     [stream decodeValuesOfObjCTypes:"@", &components];
  348.     components = [[NSMutableArray allocWithZone:[self zone]] initFromList:components];
  349.     lastRect = bounds;
  350.     if ([stream versionForClassName:[NSString stringWithCString:"Group"]] > 1) {
  351.         [stream decodeValueOfObjCType:"c" at:&dontCache];
  352.         lastRect = [stream decodeRect];
  353.     }
  354.     if ([stream versionForClassName:[NSString stringWithCString:"Group"]] > 2) {
  355.         [stream decodeValueOfObjCType:"c" at:&hasTextGraphic];
  356.     } else {
  357.         hasTextGraphic = checkForTextGraphic(components);
  358.     }
  359.     return self;
  360.  
  361. }
  362.  
  363. @end
  364.  
  365. @interface Image(PrivateMethods)
  366.  
  367. - doInitFromImage:(NSImage *)anImage;
  368.  
  369. @end
  370.  
  371. @implementation Image(FileCompatibility)
  372.  
  373. + (void)initialize
  374. {
  375.     [Image setVersion:7];
  376. }
  377.  
  378. - (void)encodeWithCoder:(NSCoder *)stream
  379. {
  380.  
  381.     [super encodeWithCoder:stream];
  382.     [stream encodeValueOfObjCType:"c" at:&amLinkButton];
  383.     [stream encodeValueOfObjCType:"c" at:&amIcon];
  384.     if (!amLinkButton) {
  385.         [stream encodeObject:image];
  386.         [stream encodeSize:originalSize];
  387.     }
  388.  
  389. }
  390.  
  391. - (id)initWithCoder:(NSCoder *)stream
  392. {
  393.  
  394.     BOOL alphaOk;
  395.     NSRect savedBounds;
  396.     int version, linkNumber;
  397.  
  398.     self = [super initWithCoder:stream];
  399.     version = [stream versionForClassName:[NSString stringWithCString:"Image"]];
  400.     if (version > 5) [stream decodeValueOfObjCType:"c" at:&amLinkButton];
  401.     if (version > 6) [stream decodeValueOfObjCType:"c" at:&amIcon];
  402.     if (amLinkButton) {
  403.         savedBounds = bounds;
  404.         [self doInitFromImage:[NSImage imageNamed:@"NSLinkButton"]];
  405.         bounds = savedBounds;
  406.     } else {
  407.         image = [[stream decodeObject] retain];
  408.         originalSize = [stream decodeSize];
  409.     }
  410.     if (version <= 2) [stream decodeValuesOfObjCTypes:"c", &alphaOk];
  411.     if (version == 4) {
  412.         [[stream decodeObject] retain];    // used to be the NSDataLink
  413.     } else if (version > 2 && version < 6) {
  414.         [stream decodeValuesOfObjCTypes:"i", &linkNumber];
  415.     }
  416.  
  417.     return self;
  418.  
  419. }
  420.  
  421. @end
  422.  
  423. @implementation Line(FileCompatibility)
  424.  
  425. + (void)initialize
  426. {
  427.     [Line setVersion:1];
  428. }
  429.  
  430. - (void)encodeWithCoder:(NSCoder *)stream
  431. {
  432.     [super encodeWithCoder:stream];
  433.     [stream encodeValueOfObjCType:"i" at:&startCorner];
  434. }
  435.  
  436. - (id)initWithCoder:(NSCoder *)stream
  437. {
  438.     self = [super initWithCoder:stream];
  439.     if ([stream versionForClassName:[NSString stringWithCString:"Line"]] > 0) {
  440.         [stream decodeValueOfObjCType:"i" at:&startCorner];
  441.     } else {
  442.         startCorner = LOWER_LEFT;
  443.     }
  444.     return self;
  445. }
  446.  
  447. @end
  448.  
  449. @implementation Polygon(FileCompatibility)
  450.  
  451. + (void)initialize
  452. /*
  453.  * This bumps the class version so that we can compatibly read
  454.  * old Graphic objects out of an archive.
  455.  */
  456. {
  457.     [Polygon setVersion:1];
  458. }
  459.  
  460. @end
  461.  
  462. @implementation PSGraphic
  463.  
  464. - (Graphic *)replaceWithImage
  465. {
  466.     Image *retval = [[Image allocWithZone:(NSZone *)[self zone]] initWithData:newData];
  467.     [retval setBounds:bounds];
  468.     if (!gFlags.selected) [retval deselect];
  469.     if (gFlags.locked) [retval lockGraphic];
  470.     [self release];
  471.     return retval;
  472. }
  473.  
  474. - (id)initWithCoder:(NSCoder *)stream
  475. {
  476.     int length;
  477.     float bbox[4];
  478.  
  479.     self = [super initWithCoder:stream];
  480.     [stream decodeValuesOfObjCTypes:"ffffi",&bbox[0],&bbox[1],&bbox[2],&bbox[3],&length];
  481.     newData = [[NSData alloc] initWithLength:length];
  482.     [stream decodeArrayOfObjCType:"c" count:length at:[newData mutableBytes]];
  483.     return self;
  484. }
  485.  
  486. /*
  487.  * No write: because PSGraphic is no longer used (replaced by Image).
  488.  * It is here only for compatibility.
  489.  */
  490.  
  491. @end
  492.  
  493. @implementation Rectangle(FileCompatibility)
  494.  
  495. + (void)initialize
  496. /*
  497.  * This bumps the class version so that we can compatibly read
  498.  * old Graphic objects out of an archive.
  499.  */
  500. {
  501.     [Rectangle setVersion:1];
  502. }
  503.  
  504. @end
  505.  
  506. @implementation Scribble(FileCompatibility)
  507.  
  508. + (void)initialize
  509. /*
  510.  * This bumps the class version so that we can compatibly read
  511.  * old Graphic objects out of an archive.
  512.  */
  513. {
  514.     [Scribble setVersion:1];
  515. }
  516.  
  517. - (void)encodeWithCoder:(NSCoder *)stream
  518. {
  519.  
  520.     int i, numFloats;
  521.  
  522.     [super encodeWithCoder:stream];
  523.  
  524.     [stream encodeValuesOfObjCTypes:"iffff",&length,&bbox[0],&bbox[1],&bbox[2],&bbox[3]];
  525.  
  526.     numFloats = (length + 1) << 1;
  527.     for (i = 0; i < numFloats; i++) {
  528.         [stream encodeValuesOfObjCTypes:"f", &points[i]];
  529.     }
  530.  
  531. }
  532.  
  533. - (id)initWithCoder:(NSCoder *)stream
  534. {
  535.  
  536.     int i;
  537.     float *p;
  538.  
  539.     self = [super initWithCoder:stream];
  540.  
  541.     [stream decodeValuesOfObjCTypes:"iffff",&length,&bbox[0],&bbox[1],&bbox[2],&bbox[3]];
  542.  
  543.     points = NSZoneMalloc((NSZone *)[self zone], ((length + 1) << 1) * sizeof(float));
  544.     userPathOps = NSZoneMalloc((NSZone *)[self zone], (length + 1) * sizeof(char));
  545.  
  546.     p = points;
  547.     for (i = 0; i <= length; i++) {
  548.         [stream decodeValuesOfObjCTypes:"f", p++];
  549.         [stream decodeValuesOfObjCTypes:"f", p++];
  550.         userPathOps[i] = dps_rlineto;
  551.     }
  552.     userPathOps[0] = dps_moveto;
  553.  
  554.     return self;
  555.  
  556. }
  557.  
  558. @end
  559.  
  560. @interface TextGraphic(PrivateMethods)
  561.  
  562. + (NSTextView *)drawText;
  563.  
  564. @end
  565.  
  566. @implementation TextGraphic(FileCompatibility)
  567.  
  568. + (void)initialize
  569. {
  570.     [TextGraphic setVersion:6];        /* class version, see initWithCoder: */
  571. }
  572.  
  573. - (void)encodeWithCoder:(NSCoder *)stream
  574. {
  575.     int length;
  576.     [super encodeWithCoder:stream];
  577.     length = [richTextData length];
  578.     [stream encodeValuesOfObjCTypes:"i", &length];
  579.     [stream encodeArrayOfObjCType:"c" count:length at:[richTextData bytes]];
  580. }
  581.  
  582. - (id)initWithCoder:(NSCoder *)stream
  583. {
  584.  
  585.     int version = [stream versionForClassName:[NSString stringWithCString:"TextGraphic"]];
  586.  
  587.     self = [super initWithCoder:stream];
  588.  
  589.     if (version < 1) {
  590.         NSCell *cell;
  591.     NSTextView *drawText = [[self class] drawText];
  592.         [stream decodeValuesOfObjCTypes:"@", &cell];
  593.         [drawText setString:[cell stringValue]];
  594.         font = [cell font];
  595.         [drawText setFont:[cell font]];
  596.         [drawText setTextColor:[self lineColor]];
  597.         [self setRichTextData:[drawText RTFFromRange:(NSRange){0, [[drawText string] length]}]];
  598.     } else {
  599.         int length;
  600.         char *unarchivedText;
  601.         [stream decodeValuesOfObjCTypes:"i", &length];
  602.         unarchivedText = (char *)NSZoneMalloc([self zone], length*sizeof(char));
  603.         [stream decodeArrayOfObjCType:"c" count:length at:unarchivedText];
  604.         richTextData = [[NSData dataWithBytesNoCopy:unarchivedText length:length] retain];
  605.     }
  606.  
  607.     if (version > 2 && version < 5) {
  608.         int linkNumber;
  609.         [stream decodeValuesOfObjCTypes:"i", &linkNumber];
  610.     } else if (version == 2) {
  611.         int linkNumber;
  612.         link = [[stream decodeObject] retain];
  613.         linkNumber = [link linkNumber];
  614.         link = nil;
  615.     }
  616.  
  617.     if (version > 3 && version < 6) {
  618.         BOOL isFormEntry;
  619.         [stream decodeValuesOfObjCTypes:"c", &isFormEntry];
  620.         gFlags.isFormEntry = isFormEntry ? YES : NO;
  621.     }
  622.  
  623.     [[self class] initClassVars];
  624.  
  625.     return self;
  626.  
  627. }
  628.  
  629. @end
  630.  
  631. @implementation Tiff
  632.  
  633. - (Graphic *)replaceWithImage
  634. {
  635.     Image *retval = [[Image allocWithZone:(NSZone *)[self zone]] initWithData:newData];
  636.     [retval setBounds:bounds];
  637.     if (!gFlags.selected) [retval deselect];
  638.     if (gFlags.locked) [retval lockGraphic];
  639.     [self release];
  640.     return retval;
  641. }
  642.  
  643. - (id)initWithCoder:(NSCoder *)stream
  644. {
  645.     NSBitmapImageRep *tempImageRep = [[NSBitmapImageRep alloc] initWithCoder:stream];
  646.     newData = [tempImageRep TIFFRepresentation];
  647.     [tempImageRep release];
  648.     return self;
  649. }
  650.  
  651. @end
  652.  
  653. @implementation DrawDocument(FileCompatibility)
  654.  
  655. #define DRAW_VERSION_3_0_PRERELEASE 234
  656. #define DRAW_VERSION_3_0 245
  657.  
  658. - (BOOL)loadDocument:(NXStream *)stream frameSize:(NSRect *)frame frameString:(NSString **)frameString
  659. /*
  660.  * For backwards compatibility only.
  661.  * Not used by the OpenStep version of this application except to read
  662.  * files created by pre-OpenStep versions of Draw.
  663.  *
  664.  * Loads an archived document from the specified filename.
  665.  * Loads the window frame specified in the archived document into the
  666.  * frame argument (if the frame argument is NULL, then the frame in
  667.  * the archived document is ignored).  Returns YES if the document
  668.  * has been successfully loaded, NO otherwise.  Note that this method
  669.  * destroys the receiving document, so use with extreme care
  670.  * (essentially, this should only be called when a new document is
  671.  * being created or an existing one is being reverted to its form
  672.  * on disk).
  673.  *
  674.  * An NS_DURING handler is needed around the NXTypedStream operations because
  675.  * if the user has asked that a bogus file be opened, the NXTypedStream will
  676.  * raise an error.  To handle the error, the NXTypedStream must be closed.
  677.  */
  678. {
  679.     char *archivedString;
  680.     int cgi, version;
  681.     volatile NSRect docFrame;
  682.     volatile BOOL retval = YES;
  683.     char *streamBuff = NULL;
  684.     int streamLen, streamCapacity;
  685.     NSData *streamData = nil;
  686.  
  687.     NS_DURING
  688.     NXGetMemoryBuffer(stream, &streamBuff, &streamLen, &streamCapacity);
  689.     if (streamBuff)  {
  690.         streamData = [NSData dataWithBytes:(const void *)streamBuff length:(unsigned)streamLen];
  691.         if (streamData)  {
  692.         NSUnarchiver *unarchiver = [[[NSUnarchiver allocWithZone:(NSZone *)[self zone]] initForReadingWithData:streamData] autorelease];
  693.         if (unarchiver)  {
  694.             [unarchiver setObjectZone:(NSZone *)[self zone]];
  695.             [unarchiver decodeValueOfObjCType:"i" at:&version];
  696.             printInfo = [[unarchiver decodeObject] retain];
  697.             if (version >= DRAW_VERSION_3_0_PRERELEASE) {
  698.             [unarchiver decodeValueOfObjCType:"*" at:&archivedString];
  699.             if (frameString) {
  700.                 *frameString = [[NSString allocWithZone:(NSZone *)[self zone]] initWithCString:archivedString];
  701.             } else {
  702.                 NSZoneFree([self zone], archivedString);
  703.             }
  704.             } else {
  705.             docFrame = [unarchiver decodeRect];
  706.             }
  707.             if (version >= DRAW_VERSION_3_0) {
  708.             [unarchiver decodeValueOfObjCType:"i" at:&cgi];
  709.             [Graphic updateCurrentGraphicIdentifier:cgi];
  710.             }
  711.             view = [[unarchiver decodeObject] retain];
  712.         }  else  {
  713.             retval = NO;
  714.         }
  715.         }  else  {
  716.         retval = NO;
  717.         }
  718.     }  else  {
  719.         retval = NO;
  720.     }
  721.     NS_HANDLER
  722.     retval = NO;
  723.     NS_ENDHANDLER
  724.     
  725.     if (retval && frame) *frame = docFrame;
  726.  
  727.     return retval;
  728. }
  729.  
  730. /* This is kind of an expensive way to check.  Should find a better way. */
  731.  
  732. + (BOOL)isPreOpenStepFile:(NSString *)file
  733. {
  734.     NSData *fileData;
  735.     int version = FIRST_OPENSTEP_VERSION;
  736.     NSUnarchiver *unarchiver = nil;
  737.  
  738.     NS_DURING  {
  739.         fileData = [NSData dataWithContentsOfFile:file];
  740.         if (fileData)  {
  741.             unarchiver = [[NSUnarchiver allocWithZone:(NSZone *)[(NSObject *)self zone]] initForReadingWithData:fileData];
  742.             if (unarchiver) [unarchiver decodeValueOfObjCType:"i" at:(int *)&version];
  743.         }
  744.     }  NS_HANDLER  {
  745.     }  NS_ENDHANDLER
  746.  
  747.     if (unarchiver) [unarchiver release];
  748.  
  749.     return (version < FIRST_OPENSTEP_VERSION);
  750. }
  751.  
  752. + openPreOpenStepFile:(NSString *)file
  753. {
  754.     DrawDocument *newDocument = nil;
  755.     NSRect contentViewFrame;
  756.     NXStream *stream;
  757.     NSString *frameString = @""; // will come back still "" if an old file is read
  758.  
  759.     if ((stream = NXMapFile([file cString], NX_READONLY))) {
  760.         newDocument = [super allocWithZone:[self newZone]];
  761.         [newDocument init];
  762.         if (stream && [newDocument loadDocument:stream frameSize:&contentViewFrame frameString:&frameString]) {
  763.             newDocument->window = [self createWindowForView:newDocument->view windowRect:&contentViewFrame frameString:[frameString isEqual:@""] ? nil : frameString];
  764.         } else {
  765.             [newDocument release];
  766.             newDocument = nil;
  767.         }
  768.         NXCloseMemory(stream, NX_FREEBUFFER);
  769.     }
  770.  
  771.     return newDocument;
  772. }
  773.  
  774. @end
  775.