home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / Pict2Ascii 1.03 / Src / AS / CDocument.cp next >
Encoding:
Text File  |  1997-07-10  |  28.0 KB  |  1,056 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //    CDocument.cp                                    ©1997 BB's Team inc. All rights reserved
  3. // =================================================================================
  4. #include "PL_Utils.h"
  5. #include "PLConstants.h"
  6. #include "LDynamicPopupMenu.h"
  7. #include "CDynamicEditField.h"
  8. #include "CMemoryIndicator.h"
  9. #include "CGreyCaption.h"
  10. #include "GWorldSaver.h"
  11. #include "CDocument.h"
  12.  
  13. #include <LFile.h>
  14. #include <LPrintout.h>
  15. #include <LPlaceHolder.h>
  16. #include <LString.h>
  17. #include <LWindow.h>
  18. #include <LCaption.h>
  19. #include <LEditField.h>
  20. #include <PP_Messages.h>
  21. #include <PP_KeyCodes.h>
  22. #include <UMemoryMgr.h>
  23. #include <UWindows.h>
  24. #include <UReanimator.h>
  25. #include <UDrawingState.h>
  26. #include <UDesktop.h>
  27. #include <UPrintingMgr.h>
  28.  
  29. #ifdef PL_PROFILE
  30.     #include <UProfiler.h>
  31. #endif
  32.  
  33.  
  34. // ---------------------------------------------------------------------------------
  35. //        • CDocument(LCommander*, FSSpec*, CPreferences*)
  36. // ---------------------------------------------------------------------------------
  37. CDocument::CDocument(
  38.     LCommander        *inSuper,
  39.     FSSpec            *inFileSpec,
  40.     CPreferences    *inPreferences,
  41.     Boolean            inVisible)
  42.         : LSingleDoc (inSuper)
  43.         , mPreferences (inPreferences)
  44.         , mVisible(inVisible)
  45. {
  46.     // Create the window and show it
  47.     mWindow = LWindow::CreateWindow (rPPob_MainWindow, this);
  48.     Assert_ (mWindow != nil);
  49.     mWindow->SetDefaultSubModel (this); // MJS 97-05-29
  50.     if (mVisible) mWindow->Show();
  51.  
  52.     // Keep easy access to important Panes
  53.     mDynamicText = (CDynamicText*) mWindow -> FindPaneByID (kDynamicText);
  54.     Assert_ (mDynamicText != nil);
  55.  
  56.     mShowPane = (CGWorldPane*) mWindow -> FindPaneByID (kShowPane);
  57.     Assert_ (mShowPane != nil);
  58.  
  59.     //
  60.     // If the prefs are read from the prefs file, we initialize with them.
  61.     // if they're not, we initialize THEM with the default values set in
  62.     // the interface definition (Constructor PPob).
  63.     // We must set take care with buttons in radio groups, because only value
  64.     // Button_On makes them broadcast to the radio group to set off the others.
  65.  
  66.     // text traits
  67.     if ( mPreferences->IsOk() ) {
  68.         mPreferences->GetTextTraits (mTextTraits);
  69.         mDynamicText->SetTextTraits (mTextTraits);
  70.     }
  71.     else {
  72.         mDynamicText->GetTextTraits (mTextTraits);
  73.         mPreferences->SetTextTraits (mTextTraits);
  74.     }
  75.     mFontLight.SetTextTraits (mTextTraits);
  76.     mImageLight.SetTextTraits (mTextTraits);
  77.  
  78.     // optimize for screen / printer
  79.     if ( mPreferences->IsOk() )
  80.         if ( mPreferences->GetScreen() )
  81.             mWindow->SetValueForPaneID (kScreenButton, Button_On);
  82.         else
  83.             mWindow->SetValueForPaneID (kPrinterButton, Button_On);
  84.     else
  85.         mPreferences->SetScreen ( mWindow->GetValueForPaneID(kScreenButton) );
  86.     mFontLight.SetScreen (mPreferences->GetScreen());
  87.  
  88.     // Ascii 7/8 bits
  89.     if ( mPreferences->IsOk() )
  90.         if ( mPreferences->Get7Bits() )
  91.             mWindow->SetValueForPaneID (k7bitsButton, Button_On);
  92.         else
  93.             mWindow->SetValueForPaneID (k8bitsButton, Button_On);
  94.     else
  95.         mPreferences->Set7Bits ( mWindow->GetValueForPaneID (k7bitsButton) );
  96.     mFontLight.Set7Bits  (mPreferences->Get7Bits());
  97.  
  98.     // AutoContrast on/off
  99.     if ( mPreferences->IsOk() )
  100.         mWindow->SetValueForPaneID (kContrastCheck, mPreferences->GetContrast() );
  101.     else
  102.         mPreferences->SetContrast (mWindow->GetValueForPaneID(kContrastCheck) );
  103.     mGenText.SetContrast (mPreferences->GetContrast());
  104.  
  105.     //
  106.     // Initialize controls that are not in the window but in the prefs dialog
  107.     // The prefs ctor provides values for these ones
  108.     //
  109.     // mMonoSpace            global to all documents
  110.     // mConfirmPrinting    idem
  111.     // mBeep32k                idem
  112.     mFontLight.SetAllowed ( mPreferences->GetAllowed() );
  113.  
  114.     // This is too dangerous to save in prefs.
  115.     // We take it from the PPob
  116.     // I'll add a "default zoom" field in the preferences… in  another life.
  117.     mRatio = mWindow->GetValueForPaneID (kRatioEditField);
  118.  
  119.     // Set the area used to compute the font lightness
  120.     // We use the frame of the ShowPane… why not ?!
  121.     Rect theFrame;
  122.     mShowPane->CalcLocalFrameRect (theFrame);
  123.     mFontLight.SetRect (theFrame);
  124.  
  125.     // we don't allow normal events processing while computing…
  126.     mWindow->UpdatePort();
  127.  
  128.     // Initialize font and size popups
  129.     SetupControls ();
  130.     
  131.     // NOW we can add self as listener to all controls in the Window
  132.     // (no need for StopListening() and StartListening() to avoid unnecessary messages)
  133.     UReanimator::LinkListenerToControls (this, mWindow, rRidL_MainWindow);
  134.  
  135.     // we don't allow normal events processing while computing…
  136.     mWindow->UpdatePort();
  137.  
  138.     // Finally open the file
  139.     if ( OpenFile (*inFileSpec) )
  140.         SetModified (true);
  141. }
  142.  
  143.  
  144. // ---------------------------------------------------------------------------------
  145. //        • ~CDocument
  146. // ---------------------------------------------------------------------------------
  147. CDocument::~CDocument()
  148. {}
  149.  
  150.  
  151. // ---------------------------------------------------------------------------------
  152. //        • ~CDocument
  153. // ---------------------------------------------------------------------------------
  154. Boolean CDocument::UpdateZoom()
  155. {
  156. //        LEditField *theField = (LEditField*) mWindow->FindPaneByID (kRatioEditField);
  157.         CDynamicEditField *theField = (CDynamicEditField*) mWindow->FindPaneByID (kRatioEditField);
  158.         Assert_ (theField != nil);
  159.  
  160.         Int32        theRatio;
  161.         theRatio = theField->GetValue();
  162.  
  163.         if ( theRatio!=mRatio ) {
  164.             mRatio=theRatio;
  165.             ReadPictFile();
  166.         }
  167.         return true;
  168. }
  169.  
  170.  
  171. // ---------------------------------------------------------------------------------
  172. //        • HandleKeyPress
  173. // ---------------------------------------------------------------------------------
  174. Boolean CDocument::HandleKeyPress (const EventRecord &inKeyEvent)
  175. {
  176.     Int16        theKey = inKeyEvent.message & charCodeMask;
  177.  
  178.     if ( theKey==char_Enter || theKey==char_Return)
  179.         return CDocument::UpdateZoom ();
  180.     else
  181.         return LCommander::HandleKeyPress(inKeyEvent);
  182. }
  183.  
  184.  
  185. // ---------------------------------------------------------------------------------
  186. //        • SetupControls
  187. // ---------------------------------------------------------------------------------
  188. void CDocument::SetupControls (void)
  189. {
  190.     // Avoid too many messages while building
  191.     StopListening();
  192.  
  193. #ifdef powerc
  194.     SetStatus (nil);
  195. #endif
  196.  
  197.     //
  198.     // Font popup
  199.     //
  200.     
  201.     // Get the font popup.
  202.     LDynamicPopupMenu    *thePopup;
  203.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kFontPopup );
  204.     Assert_( thePopup != nil );
  205.     
  206.     Int16        theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  207.     Str255    theMenuText;
  208.  
  209.     // Eliminate non-mono-space fonts if so the user desires
  210.     if ( mPreferences->GetMonoSpace() )
  211.         for ( Int16 i=theCount; i>0; --i ) {
  212.  
  213.             ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  214.  
  215.             // update user info
  216.             LStr255 theText (rSTR, kCheckingMonoSpace);
  217.             theText.Append (theMenuText);
  218.             SetStatus (theText);
  219.             
  220.             if ( ::CompareString( mTextTraits.fontName, theMenuText, nil ) == 0 ) {
  221.                 // this is the one we want to set the popup to, don't delete !
  222.             }
  223.             else     if ( !PL_Utils::IsMonoSpace (theMenuText) )
  224.                 ::DeleteMenuItem (thePopup->GetMacMenuH(), i);
  225.         }
  226.  
  227.     // Reset the popup value
  228.     theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  229.     for ( Int16 i=1 ; i<=theCount ; ++i ) {
  230.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  231.         if ( ::CompareString( mTextTraits.fontName, theMenuText, nil ) == 0 ) {
  232.             thePopup->FinishedCreatingMenu (i);
  233.             break;
  234.         }
  235.     }
  236.     thePopup->Refresh();
  237.     
  238.     //
  239.     // Size popup
  240.     //
  241.  
  242.     // Get the size popup.
  243.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID ( kSizePopup );
  244.     Assert_( thePopup != nil );
  245.     
  246.     // Get the number of items in the menu (-2 for the 'Other…' item)
  247.     theCount = -2 + ::CountMenuItems( thePopup->GetMacMenuH() );
  248.  
  249.     // Set the popup value (assumes our size is in the popup !)
  250.     for ( Int16 i=1; i<=theCount; ++i ) {
  251.     
  252.         // Get the menu item text.
  253.         Str255    theMenuText;
  254.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  255.  
  256.         // Get the size referred to by the menu item.
  257.         Int32    theSize;
  258.         ::StringToNum( theMenuText, &theSize );
  259.  
  260.         if ( mTextTraits.size == theSize ) {
  261.         
  262.             // Set the value for the popup.
  263.             thePopup->FinishedCreatingMenu (i);
  264.             break;
  265.             
  266.         }
  267.     }
  268.     
  269.     // Adjust the size menu styles (bold where IM says it should)
  270.     AdjustSizeMenuForFont (mTextTraits.fontNumber);
  271.  
  272.     // Start listening again.            
  273.     StartListening();
  274. }
  275.  
  276.  
  277. // ---------------------------------------------------------------------------------
  278. //        • SetName
  279. // ---------------------------------------------------------------------------------
  280. void
  281. CDocument::SetName (Str63 inName)
  282. {
  283.     LStr255 name (inName);
  284.     LStr255 up (name);
  285.     ::UppercaseText((Ptr) &up[1], up[0], smSystemScript);
  286.     if (up.EndsWith ("PICT", 4) )
  287.         name.Replace (name.Length()-3, 4, "txt", 3);
  288.     else
  289.         name.Append (".txt",4);
  290.     
  291.     mWindow->SetDescriptor (name);
  292. }
  293.  
  294.  
  295. // ---------------------------------------------------------------------------------
  296. //        • OpenFile
  297. // ---------------------------------------------------------------------------------
  298. Boolean
  299. CDocument::OpenFile(
  300.     FSSpec    &inFileSpec )
  301. {
  302.     OSErr    err;
  303.  
  304.     // Create a new file object & open the data fork.
  305.     mFile = new LFile (inFileSpec);
  306.  
  307.     // Read the Pict, create an offscreen copy
  308.     err = ReadPictFile();
  309.  
  310.     // Set window title acording to the name of the file.
  311.     SetName (inFileSpec.name);
  312.  
  313.     // Flag that document has an associated file (not in this particular case !)
  314.     mIsSpecified = false;
  315.  
  316.     return (err==noErr);    
  317. }
  318.  
  319.  
  320. // ---------------------------------------------------------------------------------
  321. //        • ReadPictFile
  322. // ---------------------------------------------------------------------------------
  323. OSErr CDocument::ReadPictFile (void)
  324. {
  325.     OSErr    err;
  326.     
  327.     SetStatus (rSTR, kReadingPictFile);
  328.  
  329.     // Ask for room : they will change anyway
  330.     mImageLight.MakeRoom (true);        // light buffer : 1 float per text char
  331.     mGenText.MakeRoom ();                // text buffer  : 1 char per char
  332.     SetTextStr ("\p");                    // TE record    : idem, limited to 32k
  333.     mGreyPict.MakeRoom ();                // offscreen grey picture
  334.  
  335.     Int16 theDataFork;
  336.     theDataFork = mFile->OpenDataFork (fsRdWrPerm);
  337.     
  338. Try_ {
  339.  
  340.     // Read the Pict file into a Handle
  341.     Int32    fileLength;
  342.     err = ::GetEOF(theDataFork, &fileLength);
  343.     ThrowIfOSErr_(err);
  344.     
  345.     fileLength -= kPICTHeaderSize;
  346.  
  347.     // throws if mem fails.
  348.     // uses temp mem if not enough in core
  349.     // dtor is called if an exception is thrown
  350.     StHandleBlock thePict (fileLength, true, true);
  351.  
  352.     err = ::SetFPos(theDataFork, fsFromStart, kPICTHeaderSize);
  353.     ThrowIfOSErr_(err);
  354.  
  355.     err = ::FSRead(theDataFork, &fileLength, *(Handle)thePict);
  356.     ThrowIfOSErr_(err);
  357.  
  358.     mFile->CloseDataFork();
  359.     
  360.     // Finish creation of mGrey
  361.     Rect    offRect;
  362.     offRect = (**(PicHandle)(Handle)thePict).picFrame;    // (Handle) accessor, not PicHandle…
  363.     ::OffsetRect (&offRect, -offRect.left, -offRect.top);
  364.     offRect.right  *= mRatio/100.;
  365.     offRect.bottom *= mRatio/100.;
  366.  
  367.     // the real allocation happens here
  368.     mGreyPict.SetRect (offRect);
  369.  
  370.     // Copy the picture to offscreen
  371.     if ( mGreyPict.IsOK() ) {
  372.         GWorldSaver saveGW (mGreyPict);    
  373.         mGreyPict.Lock();
  374.         ::EraseRect ( &offRect );    
  375.         StColorState::Normalize();
  376.         ::DrawPicture ((PicHandle)(Handle)thePict, &offRect);
  377.         mGreyPict.Unlock();
  378.     }
  379.  
  380.     // dtor does ::DisposeHandle ((Handle)thePict);
  381. }
  382.  
  383. Catch_ (inErr) {
  384. } EndCatch_
  385.  
  386.     // erase message bar
  387.     SetStatus();
  388.     
  389.     // Tell'em we changed
  390.     mShowPane->SetGWorld (mGreyPict);
  391.     mImageLight.SetGreyWorld (&mGreyPict);
  392.     SetModified (true);
  393.     Compute();
  394.     
  395.     return err;
  396. }
  397.  
  398.  
  399. // ---------------------------------------------------------------------------------
  400. //        • DoAESave
  401. // ---------------------------------------------------------------------------------
  402. void
  403. CDocument::DoAESave(
  404.     FSSpec    &inFileSpec,
  405.     OSType    inFileType )
  406. {
  407.     // Delete the existing file object.
  408.     delete mFile;
  409.     
  410.     // Make a new file object.
  411.     mFile = new LFile (inFileSpec);
  412.     
  413.     // Get the proper file type.
  414.     OSType theFileType = 'TEXT';
  415.     if (inFileType !=fileType_Default)
  416.         theFileType = inFileType;
  417.  
  418.     // Make new file on disk
  419.     mFile->CreateNewDataFile ('CWIE', theFileType);    
  420.  
  421.     // Write out the data.
  422.     DoSave();
  423.  
  424.     // Change window title to reflect the new name.
  425.     mWindow->SetDescriptor (inFileSpec.name);
  426.  
  427.     // Document now has a specified file.
  428.     mIsSpecified = true;
  429. }
  430.  
  431.  
  432. // ---------------------------------------------------------------------------------
  433. //        • FindCommandStatus
  434. // ---------------------------------------------------------------------------------
  435. void
  436. CDocument::FindCommandStatus(
  437.     CommandT    inCommand,
  438.     Boolean        &outEnabled,
  439.     Boolean        &outUsesMark,
  440.     Char16        &outMark,
  441.     Str255        outName )
  442. {
  443.     switch ( inCommand ) {
  444.  
  445.         default:
  446.         {
  447.             // Call inherited.
  448.             LSingleDoc::FindCommandStatus( inCommand,
  449.                 outEnabled, outUsesMark, outMark, outName );
  450.         }
  451.         break;
  452.  
  453.     }
  454. }
  455.  
  456.  
  457. // ---------------------------------------------------------------------------
  458. //        • ObeyCommand
  459. // ---------------------------------------------------------------------------
  460. Boolean CDocument::ObeyCommand (
  461.     CommandT    inCommand,
  462.     void        *ioParam)
  463. {
  464.     Boolean        cmdHandled = true;
  465.  
  466.     switch (inCommand) {
  467.     
  468.         case cmd_PageSetup:
  469.             SetupPage();
  470.             break;
  471.             
  472.         case cmd_LooseFocus:
  473.             UpdateZoom();
  474.             break;
  475.             
  476.         case cmd_Preferences:
  477.             LStr255 allowed ( mFontLight.GetAllowed() );
  478.             mPreferences->DoDialog (allowed, mTextTraits.fontName);
  479.             if ( allowed != mPreferences->GetAllowed() ) {
  480.                 mFontLight.SetAllowed ( mPreferences->GetAllowed() );
  481.                 Compute ();
  482.             }
  483.             break;
  484.             
  485.         default:
  486.             cmdHandled = LSingleDoc::ObeyCommand(inCommand, ioParam);
  487.             break;
  488.     }
  489.     
  490.     return cmdHandled;
  491. }
  492.  
  493.  
  494. // ---------------------------------------------------------------------------------
  495. //        • AdjustSizeMenuForFont
  496. // ---------------------------------------------------------------------------------
  497. void
  498. CDocument::AdjustSizeMenuForFont (Int16 inFontNumber)
  499. {
  500.     // Get the size popup.
  501.     LDynamicPopupMenu    *thePopup;
  502.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kSizePopup );
  503.     Assert_( thePopup != nil );
  504.     
  505.     // Get the number of items in the menu.
  506.     Int16    theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  507.     
  508.     for ( Int16 i=1; i<=theCount -2 /* Other... */ ; ++i ) {
  509.     
  510.         // Get the menu item text.
  511.         Str255    theMenuText;
  512.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  513.         
  514.         // Get the size referred to by the menu item.
  515.         Int32    theSize;
  516.         ::StringToNum( theMenuText, &theSize );
  517.         
  518.         // Set the item style.
  519.         ::SetItemStyle( thePopup->GetMacMenuH(), i,
  520.             ::RealFont( inFontNumber, theSize ) ? bold : normal );
  521.     }
  522.     
  523.     // Refresh the popup.
  524.     thePopup->Refresh();
  525. }
  526.  
  527.  
  528. // ---------------------------------------------------------------------------------
  529. //        • DoSave
  530. // ---------------------------------------------------------------------------------
  531. void
  532. CDocument::DoSave()
  533. {
  534.     // Open the data fork.
  535.     mFile->OpenDataFork (fsRdWrPerm);
  536.  
  537.     // the GenText may contain a nil Text. A user should not ask
  538.     // for saving in such circumstances, but you never know...
  539.     Handle theTextH;
  540.     
  541.     theTextH = mGenText.GetText();
  542.     if ( theTextH==nil )
  543.         theTextH = mDynamicText->GetTextHandle();
  544.         
  545.     // Lock the text handle (locally)
  546.     StHandleLocker theLock (theTextH);
  547.  
  548.     // Write the text to the file.
  549.     mFile->WriteDataFork (*theTextH, ::GetHandleSize (theTextH));
  550.  
  551.     // Close the data fork.
  552.     mFile->CloseDataFork();
  553.  
  554.     // Saving makes doc un-dirty.
  555.     SetModified (false);
  556. }
  557.  
  558.  
  559. // ---------------------------------------------------------------------------------
  560. //        • ListenToMessage
  561. // ---------------------------------------------------------------------------------
  562. void
  563. CDocument::ListenToMessage (MessageT inMessage, void *ioParam)
  564. {
  565.  
  566.     UpdateZoom();
  567.     
  568.     switch ( inMessage ) {
  569.     
  570.         case msg_FontPopup:
  571.         {
  572.             // Get the font popup.
  573.             LDynamicPopupMenu    *thePopup;
  574.             thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID ( kFontPopup );
  575.             Assert_( thePopup != nil );
  576.  
  577.             // Get the menu item text. The value of the popup
  578.             // is passed in ioParam (it's a long integer).
  579.             ::GetMenuItemText( thePopup->GetMacMenuH(),
  580.                 *(Int32 *)ioParam, mTextTraits.fontName );
  581.  
  582.             // Get the font number.
  583.             ::GetFNum( mTextTraits.fontName, &mTextTraits.fontNumber );
  584.             
  585.             // Adjust the size menu styles.
  586.             AdjustSizeMenuForFont ( mTextTraits.fontNumber );
  587.             
  588.             // compute text with the new font and refresh view
  589.             mFontLight.SetTextTraits (mTextTraits);
  590.             mImageLight.SetTextTraits (mTextTraits);
  591.             Compute();
  592.             mPreferences->SetTextTraits (mTextTraits);
  593.         }
  594.         break;
  595.         
  596.         case msg_SizePopup:
  597.         {
  598.             // Get the size popup.
  599.             LDynamicPopupMenu    *thePopup;
  600.             thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kSizePopup );
  601.             Assert_( thePopup != nil );
  602.  
  603.             // Get the menu item text. The value of the popup
  604.             // is passed in ioParam (it's a long integer).
  605.             Str255    theMenuText;
  606.             ::GetMenuItemText( thePopup->GetMacMenuH(),
  607.                 *(Int32 *)ioParam, theMenuText );
  608.  
  609.             // Get the size referred to by the menu item.
  610.             Int32    theSize;
  611.             ::StringToNum( theMenuText, &theSize );
  612.  
  613.             // Set the size in the text traits.
  614.             mTextTraits.size = theSize;
  615.  
  616.             // compute text with the new font and refresh view
  617.             mFontLight.SetTextTraits (mTextTraits);
  618.             mImageLight.SetTextTraits (mTextTraits);
  619.             Compute();
  620.             mPreferences->SetTextTraits (mTextTraits);
  621.         }
  622.         break;
  623.         
  624.         case msg_ContrastCheck:
  625.         {
  626.             mGenText.SetContrast (*(Int32 *)ioParam==Button_On);
  627.             Compute();
  628.             mPreferences->SetContrast (*(Int32 *)ioParam==Button_On);
  629.         }
  630.         break;
  631.  
  632.         case msg_ControlClicked:
  633.         {
  634.             PaneIDT    thePaneID = ((LPane*)ioParam)->GetPaneID();
  635.             switch ( thePaneID) {
  636.                 case kScreenButton :
  637.                 case kPrinterButton :
  638.                     mFontLight.SetScreen        ( thePaneID==kScreenButton );
  639.                     mPreferences->SetScreen    ( thePaneID==kScreenButton );
  640.                     break;
  641.                 case k7bitsButton :
  642.                 case k8bitsButton :
  643.                     mFontLight.Set7Bits        ( thePaneID==k7bitsButton );
  644.                     mPreferences->Set7Bits    ( thePaneID==k7bitsButton );
  645.                     break;
  646.                 default :
  647.                     SysBeep (1);
  648.             }
  649.             Compute();
  650.         }
  651.         break;
  652.  
  653.         default:
  654.         {
  655.         }
  656.     }
  657. }
  658.  
  659.  
  660. // ---------------------------------------------------------------------------------
  661. //        • Compute
  662. // ---------------------------------------------------------------------------------
  663. void
  664. CDocument::Compute (void)
  665. {
  666.  
  667. #ifdef PL_PROFILE
  668. //    StProfileSection profile ("\pProfile", 4000, 50);
  669. #endif
  670.  
  671.     // Reset the col and row info
  672.     ClearInfo();
  673.  
  674.     // Reading Pict failed
  675.     if ( !mGreyPict.IsOK() ) {
  676.         SetTextStr (rSTR, kNoMemForPict);
  677.         return;
  678.     }
  679.     
  680.     // Update the FontLight
  681.     if (!mFontLight.IsUpToDate() ) {
  682.         mGenText.MakeRoom();
  683.         SetStatus (rSTR, kComputingFontLight);
  684.         mFontLight.Update ();
  685.         SetStatus ();
  686.     }
  687.  
  688.     // Still not UpToDate if a pb occured
  689.     if (!mFontLight.IsUpToDate() ) {
  690.         SetTextStr (rSTR, kNoMemForFont);
  691.         return;
  692.     }
  693.  
  694.     // Update the col and row info
  695.     UpdateInfo();
  696.     
  697.     // if the 32k limit is exceeded, tell the user
  698.     if ( mImageLight.GetTextSize() > 32000 )
  699.         if ( ! mPreferences->GetBeep32k() )
  700.             mPreferences->SetBeep32k (! TellOverflow());
  701.         else
  702.             SysBeep(1);
  703.     
  704.     // Update the ImageLight
  705.     if (!mImageLight.IsUpToDate() ) {
  706.         mGenText.MakeRoom();
  707.         SetStatus (rSTR, kComputingImageLight);
  708.         mImageLight.Update ();
  709.         SetStatus ();
  710.     }
  711.  
  712.     // Check we can go on
  713.     if ( mImageLight.GetLight()==nil ) {
  714.         SetTextStr (rSTR, kNoMemForPictLight);
  715.         return;
  716.     }
  717.     
  718.     // Update the GenText
  719.     SetStatus (rSTR, kComputingText);
  720.     mGenText.Update (mFontLight, mImageLight);
  721.     SetStatus ();
  722.     if (mGenText.GetText()==nil) {
  723.         SetTextStr (rSTR, kNoMemForText);
  724.         return;
  725.     }
  726.     SetModified (true);
  727.  
  728.     // Warning : do not invert SetWidth and SetTextPtr. I spent 2 hours on this one...
  729.     mDynamicText->SetTextTraits (mTextTraits);
  730.  
  731.     // Why 40 ? Better for some non-monospace fonts… but not enough
  732.     // for some other. Ought to be 1 or 2 if everything went fine.
  733.     mDynamicText->SetWidth ( mImageLight.GetPictWidth() + 40 );
  734.     
  735.     Handle theText = mGenText.GetText();
  736.     StHandleLocker theLock(theText);
  737.  
  738.     Int32 theSize;
  739.     theSize = mImageLight.GetTextSize();
  740.     if (theSize > 32000 )
  741.         theSize = 32000;
  742.  
  743.     mDynamicText->SetTextPtr ( (Ptr)(*theText), theSize );
  744.  
  745.     // Update the number of pages
  746.     UpdatePagesNumber();
  747. }
  748.  
  749.  
  750.  
  751. // ---------------------------------------------------------------------------------
  752. //        • UpdateInfo
  753. // ---------------------------------------------------------------------------------
  754. void CDocument::ClearInfo (void)
  755. {
  756.     mWindow->SetDescriptorForPaneID( kLinesCaption  , "\p" );
  757.     mWindow->SetDescriptorForPaneID( kColumnsCaption, "\p" );
  758.     mWindow->SetDescriptorForPaneID( kPagesCaption  , "\p" );
  759. }
  760.  
  761.  
  762. // ---------------------------------------------------------------------------------
  763. //        • UpdateInfo
  764. // ---------------------------------------------------------------------------------
  765. void CDocument::UpdateInfo (void)
  766. {
  767.     // Tell the size in line && column units
  768.     LStr255    theLStr;
  769.     Str255    theStr;
  770.     
  771.     theLStr  = mImageLight.GetHeightN();
  772.     GetIndString (theStr, rSTR, kLines);
  773.     theLStr += theStr;
  774.     mWindow->SetDescriptorForPaneID( kLinesCaption, theLStr );
  775.     
  776.     theLStr  = mImageLight.GetWidthN();
  777.     GetIndString (theStr, rSTR, kColumns);
  778.     theLStr += theStr;
  779.     mWindow->SetDescriptorForPaneID( kColumnsCaption, theLStr );
  780. }
  781.  
  782.  
  783. // ---------------------------------------------------------------------------------
  784. //        • UpdatePagesNumber
  785. // ---------------------------------------------------------------------------------
  786. void CDocument::UpdatePagesNumber (void)
  787. {
  788.     // Tell the size in pages, between parenthesis if partial (>32k)
  789.     LStr255    theLStr;
  790.     Str255    theStr;
  791.     Int32 thePages;
  792.     
  793.     thePages = DoMaybePrint (false);
  794.     if (thePages>0) {
  795.         theLStr  = thePages;
  796.         GetIndString (theStr, rSTR, kPages);
  797.         theLStr += theStr;
  798.         if (thePages>1)
  799.             theLStr += "\ps";
  800.         if ( mImageLight.GetTextSize() > 32000 )
  801.             theLStr  = "\p(" + theLStr + "\p)";
  802.         mWindow->SetDescriptorForPaneID( kPagesCaption, theLStr );
  803.     }
  804. }
  805.  
  806.  
  807.  
  808. // ---------------------------------------------------------------------------------
  809. //        • TellOverflow
  810. // ---------------------------------------------------------------------------------
  811. Boolean CDocument::TellOverflow (void)
  812. {
  813.         UDesktop::Deactivate();
  814.         Int16 answer = ::CautionAlert(ALRT_TellOverflow, nil);
  815.         UDesktop::Activate();
  816.         return answer==kButtonOk;
  817. }
  818.  
  819.  
  820. // ---------------------------------------------------------------------------------
  821. //        • SetStatus
  822. // ---------------------------------------------------------------------------------
  823. void CDocument::SetStatus (
  824.     ConstStringPtr    inDescriptor)
  825. {
  826.     // Update the status line
  827.     CGreyCaption *theCaption;
  828.     theCaption = (CGreyCaption*) mWindow -> FindPaneByID (kGreyCaption);
  829.     Assert_ (theCaption != nil);
  830.  
  831.     if (inDescriptor != nil)
  832.         theCaption->SetDescriptor (inDescriptor);    // (auto refresh)
  833.  
  834.     // Also update the memory indicator (no event loop at startup…)
  835.     CMemoryIndicator *theMemo;
  836.     theMemo = (CMemoryIndicator*) mWindow -> FindPaneByID (kMemoryIndicator);
  837.     Assert_ (theMemo != nil);
  838.     theMemo->SpendTime();        // (auto refresh)
  839. }
  840.  
  841.  
  842. // ---------------------------------------------------------------------------------
  843. //        • SetStatus
  844. // ---------------------------------------------------------------------------------
  845. void CDocument::SetStatus (
  846.     ResIDT    inSTR,
  847.     Int16        inIndex)
  848. {
  849.     LStr255    theMessage (inSTR, inIndex);
  850.     SetStatus (theMessage);
  851. }
  852.  
  853.  
  854. // ---------------------------------------------------------------------------------
  855. //        • SetTextStr
  856. // ---------------------------------------------------------------------------------
  857. void CDocument::SetTextStr (
  858.     ConstStringPtr    inMsg)
  859. {
  860.     TextTraitsRecord theTextTraits;
  861.     UTextTraits::LoadSystemTraits (theTextTraits);
  862.     mDynamicText->SetTextTraits (theTextTraits);
  863.     mDynamicText->SetTextPtr ((Ptr)&inMsg[1], inMsg[0]);
  864. }
  865.  
  866.  
  867. // ---------------------------------------------------------------------------------
  868. //        • SetTextStr
  869. // ---------------------------------------------------------------------------------
  870. void CDocument::SetTextStr (
  871.     ResIDT    inSTR,
  872.     Int16        inIndex)
  873. {
  874.     Str255    theText;
  875.     GetIndString (theText, inSTR, inIndex);
  876.     SetTextStr (theText);
  877. }
  878.  
  879.  
  880. // ---------------------------------------------------------------------------------
  881. //        • SetupPage
  882. // ---------------------------------------------------------------------------------
  883. void CDocument::SetupPage()
  884. {
  885.     UDesktop::Deactivate();
  886.  
  887.     if (!mPrintRecordH)
  888.         mPrintRecordH = UPrintingMgr::CreatePrintRecord();
  889.  
  890.     if (mPrintRecordH)
  891.         UPrintingMgr::AskPageSetup (mPrintRecordH);
  892.  
  893.     UDesktop::Activate();
  894.     
  895.     // the number of pages might have changed
  896.     UpdatePagesNumber();
  897. }
  898.  
  899.  
  900. // ---------------------------------------------------------------------------------
  901. //        • DoPrint
  902. // ---------------------------------------------------------------------------------
  903. void CDocument::DoPrint()
  904. {
  905.     DoMaybePrint (true);
  906. }
  907.  
  908.  
  909. // ---------------------------------------------------------------------------------
  910. //        • DoMaybePrint
  911. // ---------------------------------------------------------------------------------
  912. Int16 CDocument::DoMaybePrint (Boolean doIt)
  913. {
  914.     // Create the printout.
  915.     LPrintout *thePrintout = LPrintout::CreatePrintout (rPPob_Printout);
  916.     if (thePrintout==nil)
  917.         return -1;
  918.  
  919.     // Set the print record.
  920.     if (mPrintRecordH)
  921.         thePrintout->SetPrintRecord (mPrintRecordH);
  922.  
  923.     // Get the text PlaceHolder.
  924.     LPlaceHolder *thePlaceHolder = (LPlaceHolder*) thePrintout->FindPaneByID (kPlaceHolder);
  925.     Assert_ (thePlaceHolder!=nil);
  926.  
  927.     // Save the text frame, and set it to the text image
  928.     // PlaceHolders are based on frames dimensions, we need images dimensions
  929.     // and PlaceHolder::InstallOccupant is not virtual...
  930.     mDynamicText->PrepareToPrint();
  931.  
  932.     // Center only if the text fits on one page
  933.     SDimension16    thePlaceSize, theTextSize;
  934.     Int16                theAlignment = kAlignAbsoluteCenter;
  935.  
  936.     thePlaceHolder->GetFrameSize (thePlaceSize);
  937.     mDynamicText  ->GetFrameSize (theTextSize);
  938.     if (   thePlaceSize.width  < theTextSize.width
  939.         || thePlaceSize.height < theTextSize.height )
  940.         theAlignment = kAlignNone;
  941.     
  942.     // Install the text view in the PlaceHolder
  943.     thePlaceHolder->InstallOccupant (mDynamicText, theAlignment);
  944.     
  945.     // Count pages
  946.     UInt32 HPage, VPage;
  947.     thePrintout->CountPanels (HPage, VPage);
  948.  
  949.     if ( HPage*VPage > 1 ) {
  950.         
  951.         // Synchronize the PlaceHolder with the  characters dimensions.
  952.         // (The CDocument knows we are in fixed width, not the CDynamicText)
  953.         SetPrintFrameSize (thePlaceHolder);
  954.  
  955.         // ask confirmation if needed
  956.         if ( doIt && mPreferences->GetPrintConfirm() ) {
  957.  
  958.             LStr255 theStr;
  959.             theStr  = (Int32)(HPage*VPage);
  960.  
  961.             ParamText (theStr, "\p", "\p", "\p");
  962.             UDesktop::Deactivate();
  963.             Int16 answer = ::CautionAlert(ALRT_ConfirmPrinting, nil);
  964.             UDesktop::Activate();
  965.         
  966.             if ( answer==kButtonCancel )
  967.                 doIt = false;
  968.         }
  969.     }
  970.     
  971.     // Print.
  972.     if (doIt)
  973.         thePrintout->DoPrintJob();
  974.     
  975.     // Delete the printout.
  976.     delete thePrintout;
  977.     mDynamicText->RevertFromPrint();
  978.     
  979.     return HPage*VPage;
  980. }
  981.  
  982.  
  983. // ---------------------------------------------------------------------------------
  984. //        • SetPrintFrameSize
  985. // ---------------------------------------------------------------------------------
  986. void
  987. CDocument::SetPrintFrameSize (LPlaceHolder* inPlace)
  988. {
  989.     // Get the frame size.
  990.     SDimension16    theFrameSize;
  991.     inPlace->GetFrameSize (theFrameSize);
  992.     
  993.     // Get the text edit record handle.
  994.     TEHandle    theTextEditH = mDynamicText->GetMacTEH();
  995.     
  996.     // Calculate the number of lines per page.
  997.     Int16    theLinesPerPage;
  998.     theLinesPerPage = theFrameSize.height / (**theTextEditH).lineHeight;
  999.  
  1000.     // Calculate the number of chars per line
  1001.     Int16 theCharsPerLine;
  1002.     theCharsPerLine = theFrameSize.width/mImageLight.GetWidth();
  1003.     
  1004.     // Resize the frame to an integral number of lines/chars.
  1005.     inPlace->ResizeFrameTo (
  1006.         mImageLight.GetWidth() * theCharsPerLine+1,
  1007.         (**theTextEditH).lineHeight * theLinesPerPage,
  1008.         false );
  1009. }
  1010.  
  1011.  
  1012. // ---------------------------------------------------------------------------------
  1013. //        • Additional AppleScript support (Michael Schuerig 97-05-29)
  1014. // ---------------------------------------------------------------------------------
  1015.  
  1016. // ---------------------------------------------------------------------------------
  1017. //        • GetAEProperty
  1018. // ---------------------------------------------------------------------------------
  1019.  
  1020. void
  1021. CDocument::GetAEProperty(
  1022.     DescType        inProperty,
  1023.     const AEDesc    &inRequestedType,
  1024.     AEDesc            &outPropertyDesc) const
  1025. {
  1026.     switch (inProperty) {
  1027.     
  1028.         case pContents: {
  1029.             Handle theTextH = (((CDocument*)this)->mGenText).GetText();
  1030.             if ( theTextH==nil )
  1031.                 theTextH = mDynamicText->GetTextHandle();
  1032.             
  1033.             StHandleLocker theLock(theTextH);
  1034.             ThrowIfOSErr_( ::AECreateDesc(typeChar, *theTextH, ::GetHandleSize(theTextH), &outPropertyDesc) );
  1035.             
  1036.             break;
  1037.             }
  1038.         default:
  1039.             LSingleDoc::GetAEProperty(inProperty, inRequestedType,
  1040.                                             outPropertyDesc);
  1041.             break;
  1042.     }
  1043. }
  1044.  
  1045.  
  1046.  
  1047. void
  1048. CDocument::AttemptClose(
  1049.     Boolean    inRecordIt)
  1050. {
  1051.     if (mVisible)
  1052.         LSingleDoc::AttemptClose(inRecordIt);
  1053.     else
  1054.         Close();
  1055. }
  1056.