home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Other View Systems / PowerPlant PPob / FWPPobRd.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  26.2 KB  |  853 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWPPobRd.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //  ©1993-1996 Metrowerks Inc. All rights reserved.
  8. // 
  9. //  Portion of this code adapted from  PowerPlant's UReanimator.cp & URegistrar.cp
  10. //  in order to parse the PPob resource format.
  11. //
  12. //========================================================================================
  13.  
  14. #ifndef FWPPOBRD_H
  15. #include "FWPPobRd.h"
  16. #endif
  17.  
  18. #ifndef FWPPOBOB_H
  19. #include "FWPPobOb.h"
  20. #endif
  21.  
  22. #ifndef FWSVIEW_H
  23. #include "FWSView.h"
  24. #endif
  25.  
  26. #ifndef FWFRAME_H
  27. #include "FWFrame.h"
  28. #endif
  29.  
  30. #ifndef FWPART_H
  31. #include "FWPart.h"
  32. #endif
  33.  
  34. #ifndef FWSCROLR_H
  35. #include "FWScrolr.h"
  36. #endif
  37.  
  38. #ifndef FWGROWBX_H
  39. #include "FWGrowBx.h"
  40. #endif
  41.  
  42. #ifndef FWBUTTON_H
  43. #include "FWButton.h"
  44. #endif
  45.  
  46. #ifndef FWEDVIEW_H
  47. #include "FWEdView.h"
  48. #endif
  49.  
  50. #ifndef FWFILEOP_H
  51. #include "FWFileOp.h"
  52. #endif
  53.  
  54. #ifndef FWRESOUR_H
  55. #include "FWResour.h"
  56. #endif
  57.  
  58. #ifndef SLFILESY_H
  59. #include "SLFileSy.h"
  60. #endif
  61.  
  62. #ifndef FWMEMMGR_H
  63. #include "FWMemMgr.h"
  64. #endif
  65.  
  66. #ifndef FWMEMHLP_H
  67. #include "FWMemHlp.h"
  68. #endif
  69.  
  70. #ifndef SOM_FW_OMemorySink_xh
  71. #include "SLMemSin.xh"
  72. #endif
  73.  
  74. #include <stdio.h> 
  75.  
  76. //========================================================================================
  77. //     Some PowerPlant Types & Constants
  78. //========================================================================================
  79.  
  80. enum {
  81.     tag_ObjectData        = 'objd',
  82.     tag_BeginSubs        = 'begs',
  83.     tag_EndSubs            = 'ends',
  84.     tag_Include            = 'incl',
  85.     tag_UserObject        = 'user',
  86.     tag_ClassAlias        = 'dopl',
  87.     tag_Comment            = 'comm',
  88.     tag_End                = 'end.'
  89. };
  90.  
  91. typedef    long    TagID;
  92.  
  93. #define kLCaption_class_ID            'capt'
  94. #define kLDialogBox_class_ID        'dlog'
  95. #define kLEditField_class_ID        'edit'
  96. #define kLPicture_class_ID            'pict'
  97. #define kLGroupBox_class_ID            'gbox'
  98. #define kLListBox_class_ID            'lbox'
  99. #define kLPane_class_ID                'pane'
  100. #define kLStdPopupMenu_class_ID        'popm'
  101. #define kLScroller_class_ID            'scrl'
  102. #define kLActiveScroller_class_ID    'ascr'
  103. #define kLStdControl_class_ID        'sctl'
  104. #define kLStdButton_class_ID        'pbut'
  105. #define kLStdCheckBox_class_ID        'cbox'
  106. #define kLStdRadioButton_class_ID    'rbut'
  107. #define kLTextEdit_class_ID            'text'
  108. #define kLView_class_ID                'view'
  109. #define kLWindow_class_ID            'wind'
  110. #define kLRadioGroup_class_ID        'radg'
  111. #define kLTabGroup_class_ID            'tabg'
  112.  
  113. const ResIDT    Txtr_SystemFont    = 0;
  114. #define         fontNumber_Unknown    -1
  115.  
  116. #pragma options align=mac68k
  117.  
  118. typedef struct TextTraitsRecord {
  119.     short        size;
  120.     short        style;
  121.     short        justification;
  122.     short        mode;
  123.     RGBColor    color;
  124.     short        fontNumber;
  125.     Str255        fontName;
  126. } TextTraitsRecord, *TextTraitsPtr, **TextTraitsH;
  127.  
  128. struct SWindowInfo {
  129.     ResIDT            WINDid;
  130.     short            layer;
  131.     unsigned long    attributes;
  132.     short            minimumWidth;
  133.     short            minimumHeight;
  134.     short            maximumWidth;
  135.     short            maximumHeight;
  136.     short            standardSize[2];
  137.     long            userCon;
  138. };
  139.  
  140. #pragma options align=reset
  141.  
  142. enum {
  143.     windAttr_Modal            = 0x80000000,
  144.     windAttr_Floating        = 0x40000000,
  145.     windAttr_Regular        = 0x20000000,
  146.     windAttr_CloseBox        = 0x10000000,
  147.     windAttr_TitleBar        = 0x08000000,
  148.     windAttr_Resizable        = 0x04000000,
  149.     windAttr_SizeBox        = 0x02000000,
  150.     windAttr_Zoomable        = 0x01000000,
  151.     windAttr_ShowNew        = 0x00800000,
  152.     windAttr_Enabled        = 0x00400000,
  153.     windAttr_Targetable        = 0x00200000,
  154.     windAttr_GetSelectClick    = 0x00100000,
  155.     windAttr_HideOnSuspend    = 0x00080000,
  156.     windAttr_DelaySelect    = 0x00040000,
  157.     windAttr_EraseOnUpdate    = 0x00020000
  158. };
  159.  
  160. //========================================================================================
  161. //     FW_CPPobReader Static Members
  162. //========================================================================================
  163.  
  164. short                FW_CPPobReader::gClassCount = 0;
  165. ClassTableH            FW_CPPobReader::gTableH;
  166. FW_CSuperView*        FW_CPPobReader::gDefaultSuperView = 0;
  167. PaneIDT                FW_CPPobReader::gDefaultButtonID = 0;
  168. PaneIDT                FW_CPPobReader::gCancelButtonID = 0;
  169. FW_CPPobScrollBarScroller*    FW_CPPobReader::gScroller = 0;
  170. FW_PFileSpecification*        FW_CPPobReader::gCurResFileSpec = 0;
  171. FW_Boolean            FW_CPPobReader::gUseClassAlias = false;
  172. FW_Boolean            FW_CPPobReader::gFoundViewWithAlias = false;
  173. FW_Boolean            FW_CPPobReader::gUseDebugWarnings = true;
  174.  
  175. //========================================================================================
  176. //     class FW_CPPobReader
  177. //========================================================================================
  178.  
  179. #ifdef FW_BUILD_MAC
  180. #pragma segment fwppob
  181. #endif
  182.  
  183. // ---------------------------------------------------------------------------
  184. //        FW_CPPobReader::CreateSubViewsFromPPobResource
  185. // ---------------------------------------------------------------------------
  186.  
  187. FW_PlatformError FW_CPPobReader::CreateSubViewsFromPPobResource(Environment* ev, 
  188.                                                     FW_ResourceID resourceID, 
  189.                                                     FW_CSuperView* superview, 
  190.                                                     FW_MReceiver* receiver,
  191.                                                     EResourceFileKind resFileKind,
  192.                                                     FW_Boolean useDebugWarnings)
  193. {
  194.     FW_PlatformError error = FW_xNoError;
  195.  
  196.     // Reset globales
  197.     gDefaultSuperView = superview;
  198.     gScroller = 0;
  199.     gDefaultButtonID = 0;
  200.     gCancelButtonID = 0;
  201.     gFoundViewWithAlias = false;
  202.     gUseDebugWarnings = useDebugWarnings;
  203.  
  204.     // Pick the right resource file 
  205.     FW_PResourceFile* resFile = GetResFile(ev, resFileKind);
  206.     
  207.     // Try to find the PPob view resource 
  208.     FW_TRY
  209.     {
  210.         // Read the WIND resource if there is one
  211.         SetWindow(ev, *resFile, resourceID);
  212.  
  213.         // Create stream from PPob resource
  214.         FW_PResource ppobResource(ev, *resFile, resourceID, FW_kPPobType);
  215.         FW_PResourceSink sink(ev, ppobResource);
  216.         FW_CReadableStream ppobStream(sink);
  217.         
  218.         // PPob version is first data in the stream
  219.         short ppobVersion;
  220.         ppobStream >> ppobVersion;
  221.         if(ppobVersion != 2)
  222.             error = FW_xWrongViewResourceVersion;
  223.         else
  224.         {
  225.             // Read objects and create ODF views
  226.             ObjectsFromStream(ev, ppobStream);
  227.  
  228.             // Use RidL resource to link controls to the supplied receiver
  229.             if (receiver)
  230.                 PrivLinkReceiver(ev, *resFile, receiver, superview, resourceID);
  231.             
  232.             // Propagate the PostCreate method to finish creating the views
  233.             PostCreateViewFromStream(ev, superview);
  234.         }
  235.     }
  236.     FW_CATCH_BEGIN
  237.     FW_CATCH_REFERENCE(FW_XException, except)
  238.     {
  239.         error = except.GetPlatformError();
  240.     }
  241.     FW_CATCH_EVERYTHING()
  242.     {
  243.         error = FW_xUnknownError;
  244.     }
  245.     FW_CATCH_END
  246.  
  247.     delete resFile;
  248.     return error;    
  249. }
  250.  
  251. // ---------------------------------------------------------------------------
  252. //        FW_CPPobReader::GetResFileName
  253. // ---------------------------------------------------------------------------
  254.  
  255. void FW_CPPobReader::GetResFileName(Environment* ev, FW_CString& name)
  256. {
  257.     if (gCurResFileSpec != 0)
  258.         (*gCurResFileSpec)->GetName(ev, name);
  259.     else
  260.     {
  261.         FW_PSharedLibraryResourceFile shLibFile(ev);
  262.         FW_PFileSpecification shLibFileSpec(ev, shLibFile->GetFileSpecification(ev));
  263.         shLibFileSpec->GetName(ev, name);
  264.     }
  265. }
  266.  
  267. // ---------------------------------------------------------------------------
  268. //        FW_CPPobReader::GetResFile
  269. // ---------------------------------------------------------------------------
  270. // GetResFile returns 0 only when asking for a new resource file and cancelling
  271. // the file dialog.  Otherwise it returns a valid external resource file or 
  272. // the shared library itself.
  273.  
  274. FW_PResourceFile* FW_CPPobReader::GetResFile(Environment* ev, 
  275.                                                 EResourceFileKind resFileKind)
  276. {
  277.     FW_PResourceFile* resFile = 0;
  278.     OSType ppobFileTypes[] = {'rsrc', 'RSRC', 'APPL'};        // any other?
  279.  
  280.     if (resFileKind == kPartOnly || resFileKind == kPartOrAskUser)
  281.     {
  282.         resFile = FW_NEW(FW_PSharedLibraryResourceFile, (ev));    
  283.     }
  284.     if (resFileKind == kCurrentResFile)
  285.     {
  286.         if (gCurResFileSpec == 0)
  287.         {
  288.             // Try to open the resource file ::sources:<part_name>.rsrc that was used
  289.             // to build the project.
  290.             
  291.             FW_PSharedLibraryResourceFile shLibFile(ev);
  292.             FW_PFileSpecification shLibFileSpec(ev, shLibFile->GetFileSpecification(ev));
  293.             FW_PDirectorySpecification libDir(ev, shLibFileSpec->GetParentDirectory(ev));
  294.             FW_CString libName;
  295.             shLibFileSpec->GetName(ev, libName);
  296.             FW_CString fileName(":Sources:");
  297.             fileName += libName;
  298.             fileName += ".ppob";
  299.             
  300.             gCurResFileSpec = FW_NEW(FW_PFileSpecification, (ev, libDir, fileName));
  301.             if (FW_FileSystem_IsValidFile(ev, *gCurResFileSpec) == false)
  302.             {
  303.                 // Else put up the file dialog
  304.                 delete gCurResFileSpec;
  305.                 gCurResFileSpec = 0;
  306.                 FW_OFileSpecification* oSpec = FW_CChooseFile::ChooseFileToOpen(
  307.                                                 FW_COpenFileParameters(3, ppobFileTypes));
  308.                 if (oSpec != 0)
  309.                     gCurResFileSpec = FW_NEW(FW_PFileSpecification, (ev, oSpec));
  310.             }
  311.         }
  312.  
  313.         if (gCurResFileSpec != 0)
  314.             resFile = FW_NEW(FW_PResourceFile, (ev, *gCurResFileSpec));
  315.         else
  316.             resFile = FW_NEW(FW_PSharedLibraryResourceFile, (ev));    
  317.     }
  318.     else if (resFileKind == kNewResFile)
  319.     {
  320.         // Ask the user to pick a new file
  321.         FW_OFileSpecification* oSpec = FW_CChooseFile::ChooseFileToOpen(
  322.                                             FW_COpenFileParameters(3, ppobFileTypes));
  323.         if (oSpec != 0)
  324.         {
  325.             delete gCurResFileSpec;
  326.             gCurResFileSpec = FW_NEW(FW_PFileSpecification, (ev, oSpec));
  327.         }
  328.         if (gCurResFileSpec != 0)
  329.             resFile = FW_NEW(FW_PResourceFile, (ev, *gCurResFileSpec));
  330.     }
  331.  
  332.     return resFile;
  333. }
  334.  
  335. // ---------------------------------------------------------------------------
  336. //        FW_CPPobReader::CreateObject
  337. // ---------------------------------------------------------------------------
  338. // Create the factory object that will read the stream and create the ODF view
  339.  
  340. void* FW_CPPobReader::CreateObject(Environment* ev, FW_CReadableStream& stream,
  341.                                 ClassIDT classID, ClassIDT oldClassID)
  342. {
  343.     void    *theObject = NULL;
  344.     
  345.     // Handle the case of custom Window and Dialog classes: we cannot use the
  346.     // same UnknownView mechanism because the stream is not like LViews.
  347.     // We revert to normal Window and Dialog objects.
  348.     if (oldClassID == kLWindow_class_ID || oldClassID == kLDialogBox_class_ID)
  349.         classID = oldClassID;
  350.         
  351.     short index = FetchClassIndex(classID);
  352.  
  353.     // When the flag is set we could use oldClassID instead of classID 
  354.     // if it is not registered. This will show the parent view at least.
  355.     if (index == 0 && oldClassID != classID)
  356.     {
  357.         index = FetchClassIndex(oldClassID);
  358.         if (index != 0 && gUseClassAlias == false)
  359.             gFoundViewWithAlias = true;
  360.         if (gUseClassAlias == false) 
  361.             index = 0;
  362.     }
  363.     
  364.     if (index != 0) 
  365.     {
  366.         theObject = (*(*gTableH)[index - 1].creatorFunc)(ev, stream, classID);
  367.     }    
  368.     else
  369.     {
  370.         // When the class is not registered we create an "Unknown" object that
  371.         // will simply read the LPane data and create an ODF Unknown view to
  372.         // make it objvious that something is missing.
  373.         // If a scroller was just read we can be (almost) sure that we are now
  374.         // reading a LView instead of a LPane, so we use FW_CPPobUnknownSView
  375.         if (FW_CPPobReader::gScroller == 0)
  376.             theObject = new FW_CPPobUnknownView(ev, stream, classID);    
  377.         else    
  378.             theObject = new FW_CPPobUnknownSView(ev, stream, classID);    
  379.     }
  380.     return theObject;
  381. }
  382.  
  383. // ---------------------------------------------------------------------------
  384. //        FW_CPPobReader::SetWindow
  385. // ---------------------------------------------------------------------------
  386.  
  387. void FW_CPPobReader::SetWindow(Environment* ev,
  388.                     FW_PResourceFile& resFile, FW_ResourceID resourceID)
  389. {
  390.     // There may not be any WIND resource associated with the PPob resource
  391.     // in case the root view is not a window.  
  392.     FW_TRY
  393.     {        
  394.         // Read the separate WIND resource to get the window size and location
  395.         FW_PResource windResource(ev, resFile, resourceID, FW_kWINDType);
  396.         FW_PResourceSink sink(ev, windResource);
  397.         FW_CReadableStream windStream(sink);
  398.  
  399.         short top, left, right, bottom;
  400.         windStream >> top >> left >> bottom >> right;
  401.  
  402.         // Set extent to window size
  403.         FW_CPoint windowSize(FW_IntToFixed(right - left), FW_IntToFixed(bottom - top));
  404.         gDefaultSuperView->SetExtent(ev, windowSize);
  405.  
  406.         // Set root frame's window size and location    
  407.         FW_CFrame* frame = gDefaultSuperView->GetFrame(ev);
  408.         if (frame->IsRoot(ev))
  409.         {
  410.             FW_CWindow* win = frame->GetWindow(ev);
  411.             win->SetWindowPosition(ev, FW_CPoint(FW_IntToFixed(left), FW_IntToFixed(top)));
  412.             win->SetWindowSize(ev, windowSize);
  413.         }
  414.     }
  415.     FW_CATCH_BEGIN
  416.     FW_CATCH_REFERENCE(FW_XException, except)
  417.     {
  418.         // don't report missing WIND resource. We just don't change the frame.
  419.         if (except.GetPlatformError() != FW_xResourceNotFound &&
  420.                 except.GetPlatformError() != FW_xResourceNotLoaded)
  421.             FW_THROW_SAME();
  422.     }
  423.     FW_CATCH_END
  424. }
  425.  
  426. // ---------------------------------------------------------------------------
  427. //        FW_CPPobReader::PrivLinkReceiver
  428. // ---------------------------------------------------------------------------
  429. // This method loads the RidL resource created by Constructor which contains the
  430. // list of all controls ids in the root view. It finds the ODF controls and
  431. // connect then to the receiver (usually the frame).
  432. // Note: this will link the radio buttons and check boxes as well, although
  433. // one usually doesn't need to respond to clicks in these kinds of buttons.
  434.  
  435. void FW_CPPobReader::PrivLinkReceiver(Environment* ev, FW_PResourceFile& resFile,
  436.             FW_MReceiver* receiver, FW_CSuperView* container, FW_ResourceID resourceID)
  437. {
  438.     FW_TRY
  439.     {
  440.         FW_PResource ridlResource(ev, resFile, resourceID, FW_kRidLType);
  441.         FW_PResourceSink sink(ev, ridlResource);
  442.         FW_CReadableStream stream(sink);
  443.         
  444.         short     count;
  445.         long    viewID;        
  446.         stream >> count;
  447.         
  448.         for (int i = 0; i < count; i++) 
  449.         {
  450.             stream >> viewID;
  451.             FW_CView* view = container->FindViewByID(ev, viewID);
  452.             if (view == 0)
  453.             {
  454.                 PPOB_WARNING("PPobReader Warning: found invalid viewID in RidL resource!");
  455.                 continue;        
  456.             }
  457.             
  458.             FW_CControl* control = FW_DYNAMIC_CAST(FW_CControl, view);
  459.             if (control != 0)
  460.                 control->LinkControlTo(ev, receiver);            
  461.         }
  462.     }
  463.     FW_CATCH_BEGIN
  464.     FW_CATCH_REFERENCE(FW_XException, except)
  465.     {
  466.         PPOB_WARNING("PPobReader Warning: Failed to load RidL resource.");
  467.     }
  468.     FW_CATCH_END
  469. }
  470.  
  471. // ---------------------------------------------------------------------------
  472. //        FW_CPPobReader::CreateSubViewsFromPPob
  473. // ---------------------------------------------------------------------------
  474.  
  475. void FW_CPPobReader::LinkReceiverToControls(Environment* ev, FW_MReceiver* receiver,
  476.                             FW_CSuperView* container, FW_ResourceID resourceID)
  477. {
  478.     FW_PSharedLibraryResourceFile resFile(ev);
  479.     PrivLinkReceiver(ev, resFile, receiver, container, resourceID);
  480. }
  481.  
  482. // ---------------------------------------------------------------------------
  483. //        FW_CPPobReader::ObjectsFromStream
  484. // ---------------------------------------------------------------------------
  485.  
  486. void FW_CPPobReader::ObjectsFromStream(Environment* ev, FW_CReadableStream& stream)
  487. {
  488.     ClassIDT    aliasClassID = 'null';
  489.     
  490.     FW_CSuperView* defaultSuperView = gDefaultSuperView;    
  491.  
  492.     FW_Boolean        readingTags = true;
  493.     do {
  494.         void    *currentObject = NULL;    // Object created by current tag
  495.         TagID    theTag = tag_End;
  496.         
  497.         stream >> theTag;
  498.         
  499.         switch (theTag) {
  500.         
  501.         case tag_ObjectData: 
  502.         {        
  503.             gDefaultSuperView = defaultSuperView;
  504.                 
  505.             // Object data = byte length, class ID, and then the data for the object.                     
  506.             long    dataLength;
  507.             stream >> dataLength;
  508.             
  509.             long dataStart = ((FW_ORandomAccessSink *)stream.GetSink())->GetPosition(ev);
  510.  
  511.             ClassIDT    classID;
  512.             stream >> classID;
  513.             
  514.             ClassIDT oldClassID = classID;
  515.             
  516.             if (aliasClassID != 'null') 
  517.             {
  518.                 // previous tag specified an Alias for the ID of this Class.
  519.                 classID = aliasClassID;
  520.             }
  521.             
  522.             // Create the factory PPob object and read the stream
  523.             // (For unregistered classes we create a FW_CPPobUnknownView object)
  524.             currentObject = FW_CPPobReader::CreateObject(ev, stream, classID, oldClassID);
  525.             
  526.             // currentObject is null only for non LView classes
  527.             if (currentObject)
  528.             {
  529.                 // Create the real ODF view out of the factory object
  530.                 ((FW_CPPobView *) currentObject)->CreateODFView(ev);
  531.             }
  532.             
  533.             // Jump to the next object in the stream. This allows to ignore unknown classes
  534.             ((FW_ORandomAccessSink *)stream.GetSink())->SetPosition(ev, dataStart + dataLength);
  535.             
  536.             aliasClassID = 'null';    // Alias is no longer in effect
  537.             break;
  538.         }
  539.             
  540.         case tag_BeginSubs:
  541.             ObjectsFromStream(ev, stream);
  542.             break;
  543.             
  544.         case tag_EndSubs:
  545.         case tag_End:
  546.             readingTags = false;
  547.             break;
  548.             
  549.         case tag_UserObject: 
  550.             // This tag is only needed for Constructor. We can ignore it                
  551.             ClassIDT    superClassID;
  552.             stream >> superClassID;
  553.             break;
  554.             
  555.         case tag_ClassAlias:        
  556.             // The ClassAlias tag defines the ClassID the for the next object                
  557.             stream >> aliasClassID;
  558.             break;
  559.             
  560.         case tag_Comment: 
  561.             // The Comment tag denotes data used by PPob editors that PowerPlant ignores        
  562.             long    commentLength;
  563.             stream >> commentLength;
  564.             long    dataStart = ((FW_ORandomAccessSink *)stream.GetSink())->GetPosition(ev);
  565.             ((FW_ORandomAccessSink *)stream.GetSink())->SetPosition(ev, dataStart + commentLength);
  566.             break;
  567.             
  568.         default:
  569. //            SignalPStr_("\pUnrecognized Tag");
  570.             readingTags = false;
  571.             break;
  572.         }
  573.                         
  574.     } while (readingTags);
  575. }
  576.  
  577. // ---------------------------------------------------------------------------
  578. //        FW_CPPobReader::ReadWindowPPob
  579. // ---------------------------------------------------------------------------
  580.  
  581. void* FW_CPPobReader::ReadWindowPPob(Environment* ev, 
  582.                                 FW_CReadableStream& stream, ClassIDT id)
  583. {
  584. FW_UNUSED(id);
  585.     
  586.     // Read LWindow data
  587.     SWindowInfo    windowInfo;
  588.     stream.Read(&windowInfo, sizeof(SWindowInfo));
  589.         
  590.     // Use SizeBox flag to create a FW_CGrowBox instance. 
  591.     
  592.     FW_CFrame* frame = gDefaultSuperView->GetFrame(ev);
  593.     if (frame->IsRoot(ev) && (windowInfo.attributes & windAttr_SizeBox))
  594.     {
  595.         // Grow box location is hard-coded to bottom right corner of frame
  596.         // View id is hard-coded to 'grow' (non-root frames need to remove it)
  597.         // (gDefaultSuperView should be the same as the frame here)
  598.         FW_CFrame* frame = gDefaultSuperView->GetFrame(ev);
  599.         FW_CPoint loc = frame->GetSize(ev);
  600.         loc.x -= FW_IntToFixed(15);
  601.         loc.y -= FW_IntToFixed(15);
  602.         FW_CGrowBox* growBox = new FW_CGrowBox(ev, frame, 'grow', loc);
  603.     }
  604.     
  605.     return 0;
  606. }
  607.  
  608. // ---------------------------------------------------------------------------
  609. //        FW_CPPobReader::ReadDialogPPob
  610. // ---------------------------------------------------------------------------
  611.  
  612. void* FW_CPPobReader::ReadDialogPPob(Environment* ev, 
  613.                                 FW_CReadableStream& stream, ClassIDT id)
  614. {
  615.     // Read the Window data first
  616.     ReadWindowPPob(ev, stream, id);
  617.     
  618.     // Dialog adds the default and cancel button ids.  Globales will be used
  619.     // to test each button being created.
  620.     stream.Read(&gDefaultButtonID, 1);
  621.     stream.Read(&gCancelButtonID, 1);
  622.     
  623.     return 0;
  624. }
  625.  
  626. // ---------------------------------------------------------------------------
  627. //        FW_CPPobReader::RegisterAllPPClasses
  628. // ---------------------------------------------------------------------------
  629. //    Register all PowerPlant classes that can create objects from Stream data
  630.  
  631. void FW_CPPobReader::RegisterAllPPClasses()
  632. {
  633. //    FW_CPPobReader::RegisterClass(kLStdControl_class_ID,    FW_CNativeControl::Create);
  634. //    FW_CPPobReader::RegisterClass(kLPane_class_ID,            FW_CView::Create);
  635.     FW_CPPobReader::RegisterClass(kLCaption_class_ID,        FW_CPPobStaticText::Create);
  636.     FW_CPPobReader::RegisterClass(kLEditField_class_ID,        FW_CPPobEditView::Create);
  637.     FW_CPPobReader::RegisterClass(kLGroupBox_class_ID,        FW_CPPobGroupBox::Create);
  638.     FW_CPPobReader::RegisterClass(kLListBox_class_ID,        FW_CPPobListBox::Create);
  639.     FW_CPPobReader::RegisterClass(kLPicture_class_ID,        FW_CPPobPictSView::Create);
  640.     FW_CPPobReader::RegisterClass(kLStdPopupMenu_class_ID,    FW_CPPobPopupMenu::Create);
  641.     FW_CPPobReader::RegisterClass(kLStdButton_class_ID,     FW_CPPobButton::Create);
  642.     FW_CPPobReader::RegisterClass(kLStdCheckBox_class_ID,    FW_CPPobButton::Create);
  643.     FW_CPPobReader::RegisterClass(kLStdRadioButton_class_ID,FW_CPPobButton::Create);
  644.     FW_CPPobReader::RegisterClass(kLTextEdit_class_ID,        FW_CPPobTextEdit::Create);
  645.     FW_CPPobReader::RegisterClass(kLView_class_ID,            FW_CPPobSuperView::Create);
  646.  
  647.     FW_CPPobReader::RegisterClass(kLScroller_class_ID,        FW_CPPobScrollBarScroller::Create);
  648.     FW_CPPobReader::RegisterClass(kLActiveScroller_class_ID,FW_CPPobScrollBarScroller::Create);
  649.  
  650.     FW_CPPobReader::RegisterClass(kLWindow_class_ID,        ReadWindowPPob);
  651.     FW_CPPobReader::RegisterClass(kLDialogBox_class_ID,        ReadDialogPPob);
  652.  
  653.     FW_CPPobReader::RegisterClass(kLRadioGroup_class_ID,    FW_CPPobRadioCluster::Create);
  654.     FW_CPPobReader::RegisterClass(kLTabGroup_class_ID,        FW_CPPobViewTabber::Create);
  655.  
  656. #if 0
  657.     // Powerplant classes not supported yet
  658.     URegistrar::RegisterClass(LButton::class_ID,         (ClassCreatorFunc) LButton::CreateButtonStream);
  659.     URegistrar::RegisterClass(LPlaceHolder::class_ID,    (ClassCreatorFunc) LPlaceHolder::CreatePlaceHolderStream);
  660.     URegistrar::RegisterClass(LPrintout::class_ID,        (ClassCreatorFunc) LPrintout::CreatePrintoutStream);
  661.     URegistrar::RegisterClass('prto',                    (ClassCreatorFunc) LPrintout::CreateOldPrintoutStream);
  662.  
  663.     URegistrar::RegisterClass(LCicnButton::class_ID,    (ClassCreatorFunc) LCicnButton::CreateCicnButtonStream);
  664.     URegistrar::RegisterClass(LOffscreenView::class_ID,    (ClassCreatorFunc) LOffscreenView::CreateOffscreenViewStream);
  665.     URegistrar::RegisterClass(LTable::class_ID,            (ClassCreatorFunc) LTable::CreateTableStream);
  666.     URegistrar::RegisterClass(LIconPane::class_ID,        (ClassCreatorFunc) LIconPane::CreateIconPaneStream);
  667.     URegistrar::RegisterClass(LTextButton::class_ID,    (ClassCreatorFunc) LTextButton::CreateTextButtonStream);
  668. #endif
  669. }
  670.  
  671. // ---------------------------------------------------------------------------
  672. //        FW_CPPobReader::RegisterClass
  673. // ---------------------------------------------------------------------------
  674.  
  675. void FW_CPPobReader::RegisterClass(ClassIDT inClassID, ClassCreatorFunc    inCreatorFunc)
  676. {
  677.     short    classIndex = 1;                // One-based index into class table
  678.  
  679.     if (gClassCount == 0) 
  680.     {                
  681.         // Create new class table (ODNewHandle throws kODErrOutOfMemory if it fails)
  682.         gTableH = (ClassTableH) FW_CMemoryManager::AllocateSystemHandle(sizeof(ClassTable));
  683.         gClassCount = 1;
  684.                                     
  685.     } 
  686.     else 
  687.     {
  688.         // See if class is already in table
  689.         classIndex = FetchClassIndex(inClassID);
  690.         
  691.         if (classIndex == 0) 
  692.         {            
  693.             FW_CMemoryManager::ResizeSystemHandle((FW_PlatformHandle) gTableH,
  694.                                         (gClassCount+1) * sizeof(ClassTable));
  695.             gClassCount++;
  696.             classIndex = gClassCount;
  697.         }
  698.     }
  699.     // Store ID and CreatorFunc
  700.     (*gTableH)[classIndex - 1].classID = inClassID;
  701.     (*gTableH)[classIndex - 1].creatorFunc = inCreatorFunc;
  702. }
  703.  
  704. // ---------------------------------------------------------------------------
  705. //        FW_CPPobReader::DisposeClassTable
  706. // ---------------------------------------------------------------------------
  707. //    [LSD] when should this be called?
  708.  
  709. void FW_CPPobReader::DisposeClassTable()
  710. {
  711.     if (gTableH != NULL) {
  712.         FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle) gTableH);
  713.         gTableH = NULL;
  714.         gClassCount = 0;
  715.     }
  716. }
  717.  
  718. // ---------------------------------------------------------------------------
  719. //        FW_CPPobReader::FetchClassIndex
  720. // ---------------------------------------------------------------------------
  721.  
  722. short FW_CPPobReader::FetchClassIndex(ClassIDT inClassID)
  723. {
  724.     short        classIndex    = 0;
  725.     ClassTable    *tableP = *gTableH;
  726.  
  727.     for (short i = 0; i < gClassCount; i++) 
  728.     {
  729.         if (tableP[i].classID == inClassID) 
  730.         {
  731.             classIndex = i + 1;
  732.             break;
  733.         }
  734.     }
  735.     return classIndex;
  736. }
  737.  
  738. // ---------------------------------------------------------------------------
  739. //        FW_CPPobReader::ReadStr255
  740. // ---------------------------------------------------------------------------
  741.  
  742. FW_CString FW_CPPobReader::ReadStr255(FW_CReadableStream& stream)
  743. {
  744.     char    byteCount;
  745.  
  746.     stream >> byteCount;    
  747.  
  748.     FW_CAcquireTemporarySystemHandle handle(byteCount);
  749.     char* buffer = (char*) handle.GetPointer();
  750.     stream.Read(buffer, byteCount);
  751.     
  752.     return FW_CString(buffer, byteCount);
  753. }
  754.  
  755. // ---------------------------------------------------------------------------
  756. //        FW_CPPobReader::GetTextTraits
  757. // ---------------------------------------------------------------------------
  758. // Convert PP TextTraits resource to ODF font, justification and color
  759. // [LSD] todo: get  the transfer mode
  760.  
  761. void FW_CPPobReader::GetTextTraits(short textTraitsID, 
  762.                                     FW_CFont& font, 
  763.                                     FW_TextBoxOptions& horizJust,
  764.                                     FW_CColor& color)
  765. {
  766.     short    justification = teFlushDefault;
  767.  
  768.     TextTraitsH    traitsHdl = 0;
  769.     if (textTraitsID != Txtr_SystemFont) 
  770.     {
  771.         traitsHdl = (TextTraitsH) ::GetResource('Txtr', textTraitsID);
  772.     }
  773.     
  774.     if (traitsHdl != 0)
  775.     {
  776.         justification = (*traitsHdl)->justification;
  777.  
  778.         FW_CString fontName;
  779.         fontName.ReplaceAll((*traitsHdl)->fontName);
  780.         
  781.         // ODF style matches Mac Style enum in Types.h
  782.         FW_FontStyle style = (FW_FontStyle)(*traitsHdl)->style; 
  783.         int size = (*traitsHdl)->size;
  784.         if (size == 0)
  785.             size = 12;
  786.  
  787.         font = FW_CFont(fontName, style, FW_IntToFixed(size));
  788.         
  789.         color = (*traitsHdl)->color;
  790.     }
  791.     else
  792.     {
  793.         // Use standard system font by default    
  794.         font = FW_CFont(FW_kSystemFont);
  795.         
  796.         justification = ::GetSysDirection();
  797.         color = FW_kRGBBlack;
  798.     }
  799.  
  800.     // [LSD] TextTraits gives only the horizontal justification    
  801.     horizJust = FW_kTextBoxJustifyLeft;
  802.     if(justification == teJustRight)
  803.         horizJust = FW_kTextBoxJustifyRight;
  804.     else if (justification == teJustCenter)
  805.         horizJust = FW_kTextBoxJustifyHCenter;
  806.  
  807. }
  808.  
  809. // ---------------------------------------------------------------------------
  810. //        FW_CPPobReader::ReloadViews
  811. // ---------------------------------------------------------------------------
  812.  
  813. FW_PlatformError FW_CPPobReader::ReloadViews(Environment* ev, 
  814.                                             FW_ResourceID resourceID, 
  815.                                             FW_CFrame* frame, 
  816.                                             FW_MReceiver* receiver,
  817.                                             EResourceFileKind resFileKind,
  818.                                             FW_Boolean useDebugWarnings)
  819. {
  820.     // Delete the whole view hierarchy under the frame 
  821.     frame->DeleteAndResetViews(ev);
  822.     
  823.     // Reload the views
  824.     FW_PlatformError error = CreateSubViewsFromPPobResource(ev, resourceID, frame, 
  825.                                         receiver, resFileKind, useDebugWarnings);    
  826.     
  827.     frame->Invalidate(ev);
  828.  
  829.     return error;
  830. }
  831.  
  832. // ---------------------------------------------------------------------------
  833. //        FW_CPPobReader::PostCreateViewFromStream
  834. // ---------------------------------------------------------------------------
  835. // This method is the same as FW_CSuperView::PrivPostCreateViewFromStream which
  836. // cannot be used in ODF 1 because it's private.
  837.         
  838. void FW_CPPobReader::PostCreateViewFromStream(Environment* ev, FW_CSuperView* view)
  839. {
  840.     // Handle this view first
  841.     view->PostCreateViewFromStream(ev);
  842.     
  843.     // Propagate to its subviews if any
  844.     FW_CViewIterator ite(view);
  845.     for (FW_CView* subview = ite.First(); ite.IsNotComplete(); subview = ite.Next())
  846.     {
  847.         if (subview->HasSubViews(ev))
  848.             PostCreateViewFromStream(ev, (FW_CSuperView *)subview);
  849.         else
  850.             subview->PostCreateViewFromStream(ev);
  851.     }
  852. }
  853.