home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Frameworks / PennyWise™ Framework / PennyView / Source / TextWindow.c < prev   
Encoding:
Text File  |  1994-08-11  |  34.2 KB  |  1,192 lines  |  [TEXT/KAHL]

  1. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  2. //                                                                                //
  3. //                                                                                //
  4. //                    Copyright PennyWise Software, 1994.                            //
  5. //                                                                                //
  6. //            Part of the PennyWise Software Application Framework                //
  7. //                                                                                //
  8. //                                                                                //
  9. //            TextWindow.c            Written by Peter Kaplan                    //
  10. //                                                                                //
  11. //                                                                                //
  12. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  13. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  14. //
  15. //    This is a template for a PennyWise Software Application Framework window
  16. //
  17. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  18. #include "PWFramework.h"
  19. #include "PWWindowList.h"
  20. #include "WindowID.h"
  21. #include "TextWindow.h"
  22. #include <PWPrintUtils.h>
  23. #include "ErrorDialog.h"
  24. #include "HandleMenus.h"
  25. #include <PWMenuUtils.h>
  26. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  27. // These procedures are static. They will only be called by name from here
  28. // outside refrences will use our window proc list.
  29. static    void    ThisWindowCreate    (EventRecord* theEvent, WindowPtr theWindow);
  30. static    short    ThisWindowDispose    (EventRecord* theEvent, WindowPtr theWindow);
  31. static    void    ThisWindowZoomIn    (EventRecord* theEvent, WindowPtr theWindow);
  32. static    void    ThisWindowZoomOut    (EventRecord* theEvent, WindowPtr theWindow);
  33. static    void    ThisWindowResize    (EventRecord* theEvent, WindowPtr theWindow);
  34. static    void    ThisWindowClick        (EventRecord* theEvent, WindowPtr theWindow);
  35. static    void    ThisWindowUpdate    (EventRecord* theEvent, WindowPtr theWindow);
  36. static    void    ThisWindowActivate    (EventRecord* theEvent, WindowPtr theWindow);
  37. static    void    ThisWindowDeactivate(EventRecord* theEvent, WindowPtr theWindow);
  38. static    void    ThisWindowDrag        (EventRecord* theEvent, WindowPtr theWindow);
  39. static    void    ThisWindowIdle        (EventRecord* theEvent, WindowPtr theWindow);
  40. static    void    ThisWindowCursor    (EventRecord* theEvent, WindowPtr theWindow);
  41. static    void    ThisWindowKeyDown    (EventRecord* theEvent, WindowPtr theWindow);
  42. static    void    ThisWindowPreMenu    (EventRecord* theEvent, WindowPtr theWindow);
  43. static    void    ThisWindowPostMenu    (EventRecord* theEvent, WindowPtr theWindow);
  44. static    short    ThisWindowDoMenu    (EventRecord* theEvent, WindowPtr theWindow, short theMenu, short theItem, short theWindowID);
  45. static    void    ThisWindowGrowRect    (EventRecord* theEvent, WindowPtr theWindow, Rect* theRect);
  46. static    void    ThisWindowGetScrap    (EventRecord* theEvent, WindowPtr theWindow);
  47. static    void    ThisWindowPutScrap    (EventRecord* theEvent, WindowPtr theWindow);
  48. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  49. static unsigned    long    GetModTime(FSSpecPtr theSpec);
  50. static void                CalcEditWindowRects(WindowPtr    theWindow, Rect* viewRect, Rect *destRect, Rect *scrollRect);
  51. static void                AdjustTEScroll(WindowPtr theWindow, ControlHandle theScrollbar, TEHandle hTE);
  52. static void                SaveTheWindow(WindowPtr theWindow);
  53. static Boolean            GetNewFileSpec(WindowPtr theWindow, FSSpecPtr theSpec);
  54. static void                AsmClikLoop(void);
  55. static void                AdjustViewRect( TEHandle theTE);
  56. static pascal void         VActionProc(ControlHandle control, short part);
  57. static pascal ProcPtr     GetOldClikLoop(void);
  58. static pascal void         PascalClikLoop(void);
  59. static void             PrintNote(WindowPtr theWindow, Boolean withPrompt);
  60. static void             GetNextLine(CharsHandle    hChars, short    offset,short pageWidth, short *wordLength);
  61. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  62. // This record holds all the information about this window
  63. // You can add fields to this record.
  64. // NOTE:ALL WINDOW RECORDS MUST START WITH THIS
  65. //        HEADER OR ELSE THE FRAMEWORK WILL NOT 
  66. //        FUNCTION PROPERLY. YOU'VE BEEN WARNED!
  67. typedef struct    OurWinRecord {
  68.     WindowParamHeader    theHeader;
  69.     short                isDirty;
  70.     ProcPtr                theClik;
  71.     TEHandle            hTE;
  72.     ControlHandle        theScrollbar;
  73.     FSSpec                theSpec;
  74.     unsigned long        theModTime;
  75.     }OurWinRecord, *OurWinPtr, **OurWinHandle;
  76. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  77. // Macros for accessing the header data
  78. // you can add your own as you add fields
  79. // to the OurWinRecord. 
  80. // NOTE:THESE MACROS ASSUME theData HOLDS
  81. //        A VALID COPY OF OurWinHandle. 
  82. #define THE_ID        (*theData)->theHeader.theID
  83. #define IS_DIRTY    (*theData)->isDirty
  84. #define HTE            (*theData)->hTE
  85. #define CLICK        (*theData)->theClik
  86. #define SCROLLBAR    (*theData)->theScrollbar
  87. #define FILESPEC    (*theData)->theSpec
  88. #define MODTIME        (*theData)->theModTime
  89. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  90. #define TEXT_WINDOW_RES_ID    128
  91. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  92. void InitTextWindowHandlers()
  93. {
  94.     PWInstallWindowType    (kWINDOW_ID_TextWindow, kWINDOW_TYPE_APPLICATION);
  95.     PWInstallCreate        (kWINDOW_ID_TextWindow, ThisWindowCreate);
  96.     PWInstallDispose    (kWINDOW_ID_TextWindow, ThisWindowDispose);
  97.     PWInstallZoomIn        (kWINDOW_ID_TextWindow, ThisWindowZoomIn);
  98.     PWInstallZoomOut    (kWINDOW_ID_TextWindow, ThisWindowZoomOut);
  99.     PWInstallResize        (kWINDOW_ID_TextWindow, ThisWindowResize);
  100.     PWInstallClick        (kWINDOW_ID_TextWindow, ThisWindowClick);
  101.     PWInstallUpdate        (kWINDOW_ID_TextWindow, ThisWindowUpdate);
  102.     PWInstallActivate    (kWINDOW_ID_TextWindow, ThisWindowActivate);
  103.     PWInstallDeactivate    (kWINDOW_ID_TextWindow, ThisWindowDeactivate);
  104.     PWInstallIdle        (kWINDOW_ID_TextWindow, ThisWindowIdle);
  105.     PWInstallCursor        (kWINDOW_ID_TextWindow, ThisWindowCursor);
  106.     PWInstallKeyDown    (kWINDOW_ID_TextWindow, ThisWindowKeyDown);
  107.     PWInstallDrag        (kWINDOW_ID_TextWindow, ThisWindowDrag);
  108.     PWInstallPreMenu    (kWINDOW_ID_TextWindow, ThisWindowPreMenu);
  109.     PWInstallMenu        (kWINDOW_ID_TextWindow, ThisWindowDoMenu);
  110.     PWInstallPostMenu    (kWINDOW_ID_TextWindow, ThisWindowPostMenu);
  111.     PWInstallGrowRect    (kWINDOW_ID_TextWindow, ThisWindowGrowRect);
  112.     PWInstallBackground    (kWINDOW_ID_TextWindow, NULL);
  113.     PWInstallScrap2Appl    (kWINDOW_ID_TextWindow, ThisWindowGetScrap);
  114.     PWInstallAppl2Scrap    (kWINDOW_ID_TextWindow, ThisWindowPutScrap);
  115. }
  116. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  117. static    void    ThisWindowCreate    (EventRecord* theEvent, WindowPtr theWindow)
  118. {
  119. // This routine will very rarely contain anything worthwhile
  120. // You will make custom routines for most windows that will be exported
  121. // via the include file
  122. }
  123. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  124. //    Since we will be exporting this we don't have to conform to any particular input format
  125. void    TextWindowOpen(FSSpecPtr    theSpec)
  126. {
  127. WindowPtr        theWindow;        // The window we create
  128. OurWinHandle    theData;        // The Data for our window
  129. TEHandle        theTE;            // The TE field for our window
  130. Rect            viewRect;        // viewRect of TE 
  131. Rect            destRect;        // destRect of TE
  132. Rect            scrollRect;        // Rect for scrollbar
  133. ControlHandle    theScrollbar;    // Control for scrollbar
  134. OSErr            theErr;            // File System Errors
  135. short            fRefNum;        // File Ref Num for this file
  136. Handle             theHandle;        // Handle to text in TE Record
  137. long            curEOF;            // EOF of file 
  138.  
  139.     theWindow = GetNewWindow(TEXT_WINDOW_RES_ID, NULL, (WindowPtr)-1);
  140.     if (theWindow) {
  141.         // We sucessfully got the window
  142.         
  143.         // Now we have to allocate our storage
  144.         theData = (OurWinHandle) NewHandle(sizeof(OurWinRecord));
  145.         if (theData) {
  146.             // We sucessfully allocated storage
  147.             
  148.             // So Lets set the port to our new window
  149.             SetPort(theWindow);
  150.                         
  151.             // Figure out the size of the TE & Scroll
  152.             CalcEditWindowRects( theWindow, &viewRect, &destRect, &scrollRect);
  153.  
  154.             theTE = TENew( &destRect, &viewRect);
  155.             if (theTE) {
  156.                 TEAutoView(TRUE,theTE);
  157.                 
  158.                 // Swap the Click routines
  159.                 CLICK = (ProcPtr) (*theTE)->clikLoop;
  160.                 (*theTE)->clikLoop = (ClikLoopProcPtr) AsmClikLoop;
  161.                 TEFeatureFlag(teFOutlineHilite,TEBitSet,theTE);
  162.     
  163.                 // Create the scrollbar on the right side of the screen
  164.                 theScrollbar = NewControl(theWindow, &scrollRect, theSpec->name ,TRUE,0,0,0,16,0);
  165.                 if (theScrollbar) {
  166.                 
  167.                     // Now lets set the fields
  168.                     THE_ID        = kWINDOW_ID_TextWindow;
  169.                     IS_DIRTY    = FALSE;
  170.                     HTE         = theTE;
  171.                     SCROLLBAR     = theScrollbar;
  172.                     
  173.                     // Here we would fill the TE
  174.                     if (theSpec) {
  175.                         
  176.                         // Set the title name
  177.                         SetWTitle(theWindow, theSpec->name);
  178.                         
  179.                         // Store the Spec
  180.                         BlockMove(theSpec, &FILESPEC, sizeof(FSSpec));
  181.                         
  182.                         // Set the last mod date;
  183.                         MODTIME = GetModTime(theSpec);
  184.                         
  185.                         theErr = FSpOpenDF(theSpec,fsRdPerm,&fRefNum);
  186.                         if (noErr == theErr) {
  187.                             
  188.                             // We have a file
  189.                             // lets read in the data
  190.                             
  191.                             // How long is the file?
  192.                             GetEOF(fRefNum,&curEOF);
  193.                             
  194.                             // If it is bigger than 32k TE Cant handle it
  195.                             if (curEOF > 32767 )
  196.                                 curEOF = 32767;
  197.                                 
  198.                             // lets make the handle for the
  199.                             // TE field as long as the file
  200.                             theHandle = (*theTE)->hText;
  201.                             SetHandleSize(theHandle,curEOF);
  202.                             
  203.                             // We got the handle lets fill it!
  204.                             if (theHandle) {
  205.                                 HLock(theHandle);
  206.                                 
  207.                                 if (FSRead(fRefNum,&curEOF,*theHandle) == noErr) {
  208.                                     (*theTE)->teLength = curEOF;
  209.                                     }
  210.                                 
  211.                                 HUnlock(theHandle);
  212.                                 TECalText(theTE);
  213.                                 }
  214.                             FSClose(fRefNum);
  215.                             }
  216.                         else {
  217.                             // We could not open the file 
  218.                             // Open the window blank
  219.                             SysBeep(1);
  220.                             MODTIME = 0;
  221.                             }
  222.                         }
  223.                     else {
  224.                         MODTIME = 0;
  225.                         }
  226.                     
  227.                     AdjustViewRect( theTE);
  228.                     AdjustTEScroll( theWindow, theScrollbar, theTE);
  229.  
  230.                     // Put our data in the refCon
  231.                     SetWRefCon(theWindow, (long) theData);
  232.                     
  233.                     // Show it & select it before we leave
  234.                     ShowWindow(theWindow);
  235.                     SelectWindow(theWindow);
  236.                     }
  237.                 else {
  238.                     DisposeWindow(theWindow);
  239.                     theWindow = NULL;
  240.                     DisposeHandle((Handle)theData);
  241.                     TEDispose(theTE);
  242.                     }
  243.                 }
  244.             else {
  245.                 // We could not allocate memory for our window's data
  246.                 // So lets get rid of the data
  247.                 DisposeWindow(theWindow);
  248.                 theWindow = NULL;
  249.                 DisposeHandle((Handle)theData);
  250.                 }
  251.             }
  252.         else {
  253.             // We could not allocate memory for our window's data
  254.             // So lets get rid of the data
  255.             DisposeWindow(theWindow);
  256.             theWindow = NULL;
  257.             }
  258.         }
  259.     
  260.     if (!theWindow) {
  261.         SysBeep(1);
  262.         // We did not create the window
  263.         // You will probably want to put up a dialog here to explain why
  264.         }
  265. }
  266. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  267. static    short    ThisWindowDispose    (EventRecord* theEvent, WindowPtr theWindow)
  268. {
  269. OurWinHandle    theData;
  270. short            theResults;
  271. Str63            theString;
  272.  
  273.     theData = (OurWinHandle) GetWRefCon(theWindow);
  274.     
  275.     // Want to save it
  276.     theResults = kBTTN_DONT;
  277.     
  278.     if (IS_DIRTY) {
  279.         // Data has been changed we would probably want to put up 
  280.         // a “Save Changes to x” dialog here 
  281.         // But I'm just going to reset IS_DIRTY
  282.         GetWTitle( theWindow, theString);
  283.         
  284.         theResults    = SaveDialog(theString);
  285.         if (theResults == kBTTN_OK) {
  286.             if (GetNewFileSpec( theWindow, &FILESPEC)) {
  287.                 SaveTheWindow( theWindow);
  288.                 IS_DIRTY = FALSE;
  289.                 theResults == kBTTN_DONT; 
  290.                 }
  291.             else {
  292.                 theResults == kBTTN_CANCEL;
  293.                 }
  294.             }
  295.         }
  296.     
  297.     if (theResults == kBTTN_DONT) {
  298.         // Now lets break it down
  299.         HideWindow(theWindow);
  300.         DisposeHandle((Handle)theData);
  301.         DisposeWindow(theWindow);
  302.         }
  303.  
  304. return (theResults==kBTTN_DONT)?TRUE:FALSE;    // True if we closed it, false if we did not [ex. pressed cancel in save dialog]    
  305. }
  306. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  307. static    void    ThisWindowZoomIn    (EventRecord* theEvent, WindowPtr theWindow)
  308. {    // The defaults will do the right thing
  309. }
  310. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  311. static    void    ThisWindowZoomOut    (EventRecord* theEvent, WindowPtr theWindow)
  312. {    // The defaults will do the right thing
  313. Rect        theRect;
  314. WStateData    *wsdp;
  315.  
  316.     // This makes the window only zoom out to the "Page Setup" size
  317.     // This will change the size depending on the Print, Etc.
  318.  
  319.     GetPageSize(&theRect);
  320.     // De-ref the data--make sure we don't move memory
  321.     wsdp = (WStateData*) *(((WindowPeek)theWindow)->dataHandle);
  322.     // Don't forget the inset 16
  323.     wsdp->stdState.right = wsdp->stdState.left +  (theRect.right- theRect.left);
  324. }
  325. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  326. static    void    ThisWindowResize    (EventRecord* theEvent, WindowPtr theWindow)
  327. {
  328. OurWinHandle    theData;
  329. GrafPtr            oldPort;
  330. Rect            viewRect;
  331. Rect            destRect;
  332. Rect            scrollRect;
  333. #define            WIDE    scrollRect.right - scrollRect.left
  334. #define            HIGH    scrollRect.bottom - scrollRect.top
  335.  
  336.     // Do the port swapping
  337.     GetPort(&oldPort);
  338.     SetPort(theWindow);
  339.  
  340.     // Get our data record
  341.     theData = (OurWinHandle) GetWRefCon(theWindow);
  342.     
  343.     // Erase the window completely
  344.     EraseRect(&theWindow->portRect);
  345.  
  346.     // Calculate the TE rects for this window
  347.     CalcEditWindowRects( theWindow, &viewRect, &destRect, &scrollRect);
  348.     
  349.     // Set the dest & view rects
  350.     (*HTE)->destRect = destRect;        
  351.     (*HTE)->viewRect = viewRect;
  352.     TECalText(HTE);
  353.     
  354.     // Adjust the view rect for correct height
  355.     AdjustViewRect(HTE);
  356.     
  357.     // Make sure the text is visible
  358.     TESelView(HTE);    
  359.  
  360.     // Move & size the control
  361.     (*SCROLLBAR)->contrlVis = FALSE;
  362.     MoveControl(SCROLLBAR,scrollRect.left,scrollRect.top);
  363.     SizeControl(SCROLLBAR,WIDE,HIGH);
  364.  
  365.     // Adjust the scroll values to proper levels
  366.     AdjustTEScroll( theWindow, SCROLLBAR, HTE);
  367.     (*SCROLLBAR)->contrlVis = TRUE;
  368.         
  369.     // make sure the whole window gets redrawn in update
  370.     InvalRect(&theWindow->portRect);
  371.  
  372.     // put the port back the way we found it
  373.     SetPort(oldPort);
  374.     
  375. #undef WIDE
  376. #undef HIGH
  377. }
  378. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  379. static    void    ThisWindowClick        (EventRecord* theEvent, WindowPtr theWindow)
  380. {
  381. OurWinHandle    theData;
  382. Point            localPoint;
  383. GrafPtr            oldPort;
  384. ControlHandle    theControl;
  385. short            thePart;
  386. short            theValue;
  387. short            offsetNew;
  388. short            offsetOld;
  389.  
  390.     GetPort(&oldPort);
  391.     SetPort(theWindow);
  392.  
  393.     localPoint = theEvent->where;
  394.     GlobalToLocal(&localPoint);
  395.     
  396.     theData = (OurWinHandle) GetWRefCon(theWindow);
  397.  
  398.  
  399.     thePart = FindControl(localPoint, theWindow, &theControl);
  400.     switch ( thePart ) {
  401.         case 0:    // It is not in the scroll bar
  402.             if (theEvent->modifiers&shiftKey) {
  403.                 // We are shift Clicking extend the selection
  404.                 
  405.                 // Where is the click occuring
  406.                 offsetNew = TEGetOffset(localPoint,HTE);
  407.                 
  408.                 if ((*HTE)->selStart == (*HTE)->selEnd) {
  409.                     // It happend with no current selection
  410.                     offsetOld = (*HTE)->selStart;
  411.                     }
  412.                 else {
  413.                     // we have a selection, handle it
  414.                     if ((*HTE)->selStart > offsetNew) {
  415.                         offsetOld = (*HTE)->selEnd;
  416.                         }
  417.                     else if ((*HTE)->selEnd < offsetNew) {
  418.                         offsetOld = (*HTE)->selStart;
  419.                         }
  420.                     else {
  421.                         offsetOld = (*HTE)->selStart;
  422.                         }
  423.                     }
  424.                 // Now make it the right order
  425.                 if (offsetOld<offsetNew) 
  426.                     TESetSelect(offsetOld,offsetNew,HTE);
  427.                 else 
  428.                     TESetSelect(offsetNew,offsetOld,HTE);
  429.  
  430.                 }
  431.             else
  432.                 TEClick(localPoint,FALSE,HTE);
  433.             break;
  434.         case inThumb:
  435.             theValue = GetCtlValue(theControl);
  436.             thePart = TrackControl(theControl, localPoint, NULL);
  437.             if (thePart != 0) {
  438.                 theValue -= GetCtlValue(theControl);
  439.                 
  440.                 /* value now has CHANGE in value; if value changed, scroll */
  441.                 if ( theValue != 0 )
  442.                     TEScroll(0, theValue * (*HTE)->lineHeight, HTE);
  443.             }
  444.             break;
  445.         default:                        /* they clicked in an arrow, so track & scroll */
  446.             theValue = TrackControl(theControl, localPoint, (ProcPtr) VActionProc);
  447.             break;
  448.         }
  449.     SetPort(oldPort);
  450. }
  451. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  452. static    void    ThisWindowUpdate    (EventRecord* theEvent, WindowPtr theWindow)
  453. {
  454. OurWinHandle    theData;
  455. GrafPtr            oldPort;
  456.  
  457.     GetPort(&oldPort);
  458.     SetPort(theWindow);
  459.  
  460.     theData = (OurWinHandle) GetWRefCon(theWindow);
  461.     
  462.     DrawGrowIcon(theWindow);
  463.  
  464.     EraseRect(&((*HTE)->viewRect));
  465.     TEUpdate( &theWindow->portRect, HTE);    
  466.     
  467.     UpdtControl(theWindow,theWindow->visRgn);
  468.     
  469.     SetPort(oldPort);}
  470. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  471. static    void    ThisWindowActivate    (EventRecord* theEvent, WindowPtr theWindow)
  472. {
  473. OurWinHandle    theData;
  474. GrafPtr            oldPort;
  475.  
  476.  
  477.     GetPort(&oldPort);
  478.     SetPort(theWindow);
  479.  
  480.     theData = (OurWinHandle) GetWRefCon(theWindow);
  481.         
  482.     // Call DrawGrowIcon if the window has a grow box
  483.     DrawGrowIcon(theWindow);
  484.  
  485.     TEActivate( HTE);
  486.     HiliteControl(SCROLLBAR,0);
  487.     
  488.     SetPort(oldPort);
  489. }
  490. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  491. static    void    ThisWindowDeactivate(EventRecord* theEvent, WindowPtr theWindow)
  492. {
  493. OurWinHandle    theData;
  494. GrafPtr            oldPort;
  495.  
  496.  
  497.     GetPort(&oldPort);
  498.     SetPort(theWindow);
  499.  
  500.     theData = (OurWinHandle) GetWRefCon(theWindow);
  501.     
  502.     // Deactivate items here
  503.     
  504.     // Call DrawGrowIcon if the window has a grow box
  505.     DrawGrowIcon(theWindow);
  506.  
  507.     TEDeactivate( HTE);
  508.  
  509.     HiliteControl(SCROLLBAR, 255);
  510.         
  511.     SetPort(oldPort);
  512. }
  513. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  514. static    void    ThisWindowDrag        (EventRecord* theEvent, WindowPtr theWindow)
  515. {    // The default does the right thing
  516. }
  517. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  518. static    void    ThisWindowIdle        (EventRecord* theEvent, WindowPtr theWindow)
  519. {
  520. OurWinHandle    theData;
  521. GrafPtr            oldPort;
  522.  
  523.  
  524.     GetPort(&oldPort);
  525.     SetPort(theWindow);
  526.  
  527.     theData = (OurWinHandle) GetWRefCon(theWindow);
  528.     
  529.     TEIdle( HTE);    
  530.     
  531.     SetPort(oldPort);
  532. }
  533. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  534. static    void    ThisWindowCursor    (EventRecord* theEvent, WindowPtr theWindow)
  535. {
  536. OurWinHandle    theData;
  537. GrafPtr            oldPort;
  538. CursHandle        hCurs;
  539. Rect            controlRect;
  540. Point            localPoint;
  541. RgnHandle        theRgn;
  542.  
  543.  
  544.     GetPort(&oldPort);
  545.     SetPort(theWindow);
  546.  
  547.     theData = (OurWinHandle) GetWRefCon(theWindow);
  548.     
  549.     theRgn = NewRgn();
  550.     if (theRgn) {
  551.         // Adjust the cursor here
  552.         if (PtInRgn( theEvent->where, ((WindowPeek)theWindow)->contRgn))  {
  553.         
  554.             // OK the mouse is in the window lets find out where
  555.             
  556.             localPoint = theEvent->where;
  557.             GlobalToLocal(&localPoint);
  558.         
  559.             // Make a box the size of viewRect
  560.             controlRect = theWindow->portRect;
  561.             controlRect.right-=16;
  562.             controlRect.bottom-=16;
  563.             
  564.             if (PtInRect(localPoint,&controlRect)) {
  565.                 // OK its in the viewRect area make the cursor an iBeam
  566.                 LocalToGlobal(&(((Point*)&(controlRect))[0]));
  567.                 LocalToGlobal(&(((Point*)&(controlRect))[1]));
  568.                 
  569.                 // Set the mouse moved to be the box we are in
  570.                 RectRgn(gMouseMovedRgn,&controlRect);
  571.                 hCurs = GetCursor(1);
  572.                 HLock((Handle)hCurs);
  573.                 SetCursor(*hCurs);
  574.                 }
  575.             else {
  576.                 controlRect = theWindow->portRect;
  577.                 controlRect.top = controlRect.bottom -16;
  578.                     
  579.                 LocalToGlobal(&(((Point*)&(controlRect))[0]));
  580.                 LocalToGlobal(&(((Point*)&(controlRect))[1]));
  581.                 RectRgn(theRgn,&controlRect);
  582.                 
  583.                 controlRect = (*SCROLLBAR)->contrlRect;
  584.                 LocalToGlobal(&(((Point*)&(controlRect))[0]));
  585.                 LocalToGlobal(&(((Point*)&(controlRect))[1]));
  586.                 RectRgn(gMouseMovedRgn,&controlRect);
  587.                 
  588.                 UnionRgn(theRgn,gMouseMovedRgn,gMouseMovedRgn);
  589.                 SetCursor(&arrow);
  590.                 }
  591.             }
  592.         else {
  593.             SetRectRgn(gMouseMovedRgn,-32768,-32768,32767,32767);
  594.             DiffRgn(gMouseMovedRgn,((WindowPeek)theWindow)->contRgn,gMouseMovedRgn);
  595.             SetCursor(&arrow);
  596.             }
  597.             
  598.         DisposeRgn(theRgn);
  599.         }
  600.         
  601.  
  602.     SetPort(oldPort);
  603. }
  604. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  605. static    void    ThisWindowKeyDown    (EventRecord* theEvent, WindowPtr theWindow)
  606. {
  607. OurWinHandle    theData;
  608. GrafPtr            oldPort;
  609. short            keyCode;
  610. short            charCode;
  611.  
  612.     GetPort(&oldPort);
  613.     SetPort(theWindow);
  614.  
  615.     theData = (OurWinHandle) GetWRefCon(theWindow);
  616.  
  617.     keyCode  = (theEvent->message&keyCodeMask)>>8;
  618.     charCode = theEvent->message&charCodeMask;
  619.     
  620.     if ( keyCode == 8 || (*HTE)->teLength - ((*HTE)->selEnd - (*HTE)->selStart) + 1 < 32767) {
  621.         TEKey(charCode,HTE);
  622.         IS_DIRTY = TRUE;
  623.         AdjustTEScroll( theWindow,  SCROLLBAR, HTE);
  624.  
  625.         }
  626.     else
  627.         SysBeep(1);
  628.  
  629.     SetPort(oldPort);
  630. }
  631. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  632. static    void    ThisWindowPreMenu    (EventRecord* theEvent, WindowPtr theWindow)
  633. {
  634. OurWinHandle    theData;
  635. GrafPtr            oldPort;
  636. Str63            theString;
  637. Boolean            quotes;
  638.  
  639.  
  640.     GetPort(&oldPort);
  641.     SetPort(theWindow);
  642.  
  643.     theData = (OurWinHandle) GetWRefCon(theWindow);
  644.     
  645.     // Enable and disable items
  646.     // change item names etc.
  647.     
  648.     // When we inable undo, we can add this
  649.     DisableItem( gMenuEdit, kEDIT_UNDO);
  650.  
  651.     // If we are not selecting any text
  652.     if ((*HTE)->selStart == (*HTE)->selEnd) {
  653.         // Disable Cut, Copy, Clear
  654.         DisableItem( gMenuEdit, kEDIT_CUT);
  655.         DisableItem( gMenuEdit, kEDIT_COPY);
  656.         DisableItem( gMenuEdit, kEDIT_CLEAR);
  657.         }
  658.     else {
  659.         // What test are we selecting
  660.         if (((*HTE)->selEnd - (*HTE)->selStart) > 16) {
  661.             GetIndString( theString, 100, 1);
  662.             quotes = FALSE;
  663.             }
  664.         else {
  665.             BlockMove(&(*((*HTE)->hText))[(*HTE)->selStart], &theString[1], ((*HTE)->selEnd - (*HTE)->selStart));
  666.             theString[0] = ((*HTE)->selEnd - (*HTE)->selStart);
  667.             quotes = TRUE;
  668.             }
  669.  
  670.         AddNameToMenu( gMenuEdit, kEDIT_CUT, theString, FALSE, quotes);
  671.         AddNameToMenu( gMenuEdit, kEDIT_COPY, theString, FALSE, quotes);
  672.         AddNameToMenu( gMenuEdit, kEDIT_CLEAR, theString, FALSE, quotes);
  673.         }
  674.         
  675.     // Lets handle the file name stuff
  676.     GetWTitle(theWindow, theString);
  677.     AddNameToMenu( gMenuFile, kFILE_SAVE, theString, FALSE, TRUE);
  678.     AddNameToMenu( gMenuFile, kFILE_CLOSE, theString, FALSE, TRUE);
  679.     AddNameToMenu( gMenuFile, kFILE_PRINT, theString, TRUE, TRUE);
  680.     
  681.     // If we have no TEXT in the Scrap
  682.     if (TEGetScrapLen()==0) {
  683.         // Disable Paste
  684.         DisableItem( gMenuEdit, kEDIT_PASTE);
  685.         }
  686.     
  687.     if (!IS_DIRTY) {
  688.         DisableItem( gMenuFile, kFILE_SAVE);
  689.         }
  690.  
  691.     SetPort(oldPort);
  692. }
  693. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  694. static    void    ThisWindowPostMenu    (EventRecord* theEvent, WindowPtr theWindow)
  695. {
  696. OurWinHandle    theData;
  697. GrafPtr            oldPort;
  698.  
  699.  
  700.     GetPort(&oldPort);
  701.     SetPort(theWindow);
  702.  
  703.     theData = (OurWinHandle) GetWRefCon(theWindow);
  704.     
  705.     // Enable and disable items
  706.     // change item names etc.
  707.     EnableItem( gMenuFile, kFILE_SAVE);
  708.  
  709.  
  710.     EnableItem( gMenuEdit, kEDIT_UNDO);
  711.  
  712.      SetMenuItemToIndString(kMENU_ID_EDIT, kEDIT_CUT, gMenuEdit);
  713.     SetMenuItemToIndString(kMENU_ID_EDIT, kEDIT_COPY, gMenuEdit);
  714.     SetMenuItemToIndString(kMENU_ID_EDIT, kEDIT_CLEAR, gMenuEdit);
  715.     
  716.      SetMenuItemToIndString(kMENU_ID_FILE, kFILE_SAVE, gMenuFile);
  717.     SetMenuItemToIndString(kMENU_ID_FILE, kFILE_CLOSE, gMenuFile);
  718.     SetMenuItemToIndString(kMENU_ID_FILE, kFILE_PRINT, gMenuFile);
  719.  
  720.     EnableItem( gMenuEdit, kEDIT_CUT);
  721.     EnableItem( gMenuEdit, kEDIT_COPY);
  722.     EnableItem( gMenuEdit, kEDIT_CLEAR);
  723.     EnableItem( gMenuEdit, kEDIT_PASTE);
  724.     
  725.         
  726.     SetPort(oldPort);
  727. }
  728. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  729. static    short    ThisWindowDoMenu    (EventRecord* theEvent, WindowPtr theWindow, short theMenu, short theItem, short theWindowID)
  730. {
  731. short            theResult;
  732. OurWinHandle    theData;
  733. Str255            theString;
  734.  
  735.     theResult = TRUE;
  736.     theData = (OurWinHandle) GetWRefCon(theWindow);
  737.     
  738.     // if we don't handle it return false so the defaults will pick it up
  739.     switch (theMenu) {
  740.         case kMENU_ID_FILE:
  741.             switch (theItem) {
  742.                 case kFILE_SAVE:
  743.                     {
  744.  
  745.                     if (MODTIME != GetModTime(&FILESPEC)) {
  746.                         // The file has been changed since we last 
  747.                         // used it.
  748.                         GetWTitle(theWindow, theString);
  749.                         ErrorDialog(500, 1, theString);
  750.                         }
  751.                     else {
  752.                         SaveTheWindow( theWindow);
  753.                         }
  754.                     }
  755.                     break;
  756.             
  757.                 case kFILE_SAVEAS:
  758.                     if (GetNewFileSpec( theWindow,  &FILESPEC)) {
  759.                         SetWTitle(theWindow, FILESPEC.name);
  760.                         SaveTheWindow( theWindow);
  761.                         }
  762.                     break;
  763.                 case kFILE_PRINT:
  764.                     PrintNote( theWindow,  TRUE);
  765.                     break;
  766.                 case kFILE_PONE:
  767.                     PrintNote( theWindow,  FALSE);
  768.                     break;
  769.                 default:
  770.                     theResult = FALSE;
  771.                     break;
  772.                 }
  773.             break;
  774.         case kMENU_ID_EDIT:
  775.             switch (theItem) {
  776.                 //case kEDIT_UNDO:
  777.                 //    break;
  778.                 case kEDIT_CUT:
  779.                     ZeroScrap();
  780.                     TECut(HTE);
  781.                     IS_DIRTY = TRUE;
  782.                     break;
  783.                 case kEDIT_COPY:
  784.                     ZeroScrap();
  785.                     TECopy(HTE);
  786.                     IS_DIRTY = TRUE;
  787.                     break;
  788.                 case kEDIT_PASTE:
  789.                     TEPaste(HTE);
  790.                     IS_DIRTY = TRUE;
  791.                     break;
  792.                 case kEDIT_CLEAR:
  793.                     TEDelete(HTE);
  794.                     IS_DIRTY = TRUE;
  795.                     break;
  796.                 case kEDIT_SEL_ALL:
  797.                     TESetSelect(0,32767,HTE);
  798.                     break;
  799.                 default:
  800.                     theResult = FALSE;
  801.                     break;
  802.                 }
  803.             break;
  804.         default:
  805.             theResult = FALSE;
  806.         }
  807.     AdjustTEScroll( theWindow, SCROLLBAR, HTE);
  808.  
  809. return theResult;
  810. }
  811. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  812. static    void    ThisWindowGrowRect    (EventRecord* theEvent, WindowPtr theWindow, Rect* theRect)
  813. {
  814. // This simply is the size of the rect the window can grow to
  815. SetRect(theRect, 64, 64, 32767, 32767);
  816. }
  817. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  818. static    void    ThisWindowGetScrap(EventRecord* theEvent, WindowPtr theWindow)
  819. {
  820. // This routine will get called when your application gets a resumeEvent 
  821. // AND the convertClipboardFlag bit is set
  822. // What must be done is the convertion of the clipboard to a private scrap
  823. TEFromScrap();
  824. }
  825. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  826. static    void    ThisWindowPutScrap(EventRecord* theEvent, WindowPtr theWindow)
  827. {
  828. // This routine will get called when your application gets a suspendEvent 
  829. // What must be done is the convertion of the private scrap to the clipboard
  830. TEToScrap();
  831. }
  832. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  833. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  834. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  835. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  836. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  837. // Utility Routines for this window
  838. unsigned long    GetModTime(FSSpecPtr theSpec)
  839. {
  840. HFileParam        pb;
  841.  
  842.     pb.ioCompletion = NULL;
  843.     pb.ioVRefNum = theSpec->vRefNum;
  844.     pb.ioFVersNum = 0;
  845.     pb.ioFDirIndex = 0;
  846.     pb.ioNamePtr = theSpec->name;
  847.     pb.ioDirID = theSpec->parID;
  848.     
  849.     PBHGetFInfo((HParmBlkPtr)&pb,FALSE);
  850.     
  851. return pb.ioFlMdDat;
  852. }
  853. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  854. pascal void VActionProc(ControlHandle control, short part)
  855. {
  856. OurWinHandle    theData;
  857. short            value;
  858. short            max;
  859. short            amount;
  860. WindowPtr        window;
  861. Rect            viewRect;
  862.     
  863.     if ( part != 0 ) {                /* if it was actually in the control */
  864.         window = (*control)->contrlOwner;
  865.         theData = (OurWinHandle)GetWRefCon(window);
  866.  
  867.         value = GetCtlValue(control);
  868.         max = GetCtlMax(control);
  869.         amount = 0;
  870.         viewRect = (*HTE)->viewRect;
  871.         switch ( part ) {
  872.             case inUpButton:
  873.                 if (value>0) {
  874.                     amount = (*HTE)->lineHeight;
  875.                     value--;
  876.                     }
  877.                 break;
  878.             case inDownButton:        /* one line */
  879.                 if (value<max) {
  880.                     amount = -(*HTE)->lineHeight;
  881.                     value++;
  882.                     }
  883.                 break;
  884.             case inPageUp:            /* one page */
  885.                 amount = (viewRect.bottom - viewRect.top);
  886.                 value += -(viewRect.bottom - viewRect.top) / (*HTE)->lineHeight;
  887.                 break;
  888.             case inPageDown:
  889.                 amount = -(viewRect.bottom - viewRect.top);
  890.                 value += (viewRect.bottom - viewRect.top) / (*HTE)->lineHeight;
  891.                 break;
  892.         }
  893.         if ( amount != 0) {
  894.             TEPinScroll(0,amount,HTE);
  895.             SetCtlValue(control, value);
  896.             }
  897.     }
  898. }
  899. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  900. pascal ProcPtr GetOldClikLoop()
  901. {
  902. WindowPtr            theWindow;
  903. OurWinHandle    theData;
  904.  
  905.     theWindow = FrontWindow();
  906.     theData = (OurWinHandle) GetWRefCon(theWindow);
  907.     return ((*theData)->theClik);
  908. }
  909. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  910. pascal void PascalClikLoop()
  911. {
  912.     WindowPtr    window;
  913.     RgnHandle    region;
  914.     window = FrontWindow();
  915.     region = NewRgn();
  916.     GetClip(region);                    /* save clip */
  917.     ClipRect(&window->portRect);
  918. //    AdjustScrollValues(window, true);    /* pass true for canRedraw */
  919.     SetClip(region);                    /* restore clip */
  920.     DisposeRgn(region);
  921. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  922. void AsmClikLoop()
  923. {
  924.     asm {            
  925.             MOVEM.L        D1-D2/A1,-(SP)        ; D0 and A0 need not be saved
  926.             CLR.L        -(SP)                ; make space for procedure pointer
  927.             JSR            GetOldClikLoop        ; get the old clikLoop
  928.             MOVEA.L        (SP)+,A0            ; into A0
  929.             MOVEM.L        (SP)+,D1-D2/A1        ; restore the world as it was
  930.             
  931.             JSR            (A0)                ; and execute old clikLoop
  932.  
  933.             MOVEM.L        D1-D2/A1,-(SP)        ; D0 and A0 need not be saved
  934.             JSR            PascalClikLoop        ; do our clikLoop
  935.             MOVEM.L        (SP)+,D1-D2/A1        ; restore the world as it was
  936.             MOVEQ        #1,D0                ; clear the zero flag so TextEdit keeps going
  937.             RTS
  938.     }
  939. }
  940. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  941. void CalcEditWindowRects(WindowPtr    theWindow, Rect* viewRect, Rect *destRect, Rect *scrollRect)
  942. {
  943.     scrollRect->top = theWindow->portRect.top - 1;
  944.     scrollRect->left = theWindow->portRect.right - 15;
  945.     scrollRect->bottom = theWindow->portRect.bottom - 14;
  946.     scrollRect->right = theWindow->portRect.right + 1;
  947.     
  948.     viewRect->top = theWindow->portRect.top + 1;
  949.     viewRect->left = theWindow->portRect.left + 1;
  950.     viewRect->right = theWindow->portRect.right - 16;
  951.     viewRect->bottom = theWindow->portRect.bottom - 16;
  952.     *destRect = *viewRect;
  953.     InsetRect(destRect, 4, 0);
  954. }
  955. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  956. void AdjustViewRect(TEHandle hTE)
  957. {
  958.     (*hTE)->viewRect.bottom = ((((*hTE)->viewRect.bottom - (*hTE)->viewRect.top) / (*hTE)->lineHeight)
  959.                             * (*hTE)->lineHeight) + (*hTE)->viewRect.top;
  960. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  961. void AdjustTEScroll(WindowPtr theWindow, ControlHandle theScrollbar, TEHandle hTE)
  962. {
  963. short        value, lines, max;
  964. short        oldValue, oldMax;
  965.  
  966.     oldMax = GetCtlMax(theScrollbar);
  967.     oldValue = GetCtlValue(theScrollbar);
  968.     
  969.     lines = (*hTE)->nLines;
  970.  
  971.     // If the last item is a return make adjustment
  972.     if ( *(*(*hTE)->hText + (*hTE)->teLength - 1) == 0x0D )
  973.         lines += 1;
  974.     
  975.     max = lines - (((*hTE)->viewRect.bottom - (*hTE)->viewRect.top) /(*hTE)->lineHeight);
  976.  
  977.     max = (max<0)?0:max;
  978.     value =((*hTE)->viewRect.top - (*hTE)->destRect.top) / (*hTE)->lineHeight;    
  979.  
  980.     SetCtlMax(theScrollbar, max);
  981.     SetCtlValue(theScrollbar, value);
  982. }
  983. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  984. void    SaveTheWindow(WindowPtr theWindow)
  985. {
  986. OurWinHandle    theData;
  987. GrafPtr            oldPort;
  988. short            fRefNum;
  989. OSErr            theErr;
  990. Handle            theHandle;
  991. long            curEOF;
  992.  
  993.  
  994.     GetPort(&oldPort);
  995.     SetPort(theWindow);
  996.  
  997.     theData = (OurWinHandle) GetWRefCon(theWindow);
  998.     
  999.     theErr = FSpOpenDF(&FILESPEC,fsRdWrPerm,&fRefNum);
  1000.     if (noErr == theErr) {
  1001.         
  1002.         // Get the handle to the text
  1003.         theHandle = (*HTE)->hText;
  1004.         
  1005.         // We got the handle lets save the file
  1006.         if (theHandle) {
  1007.         
  1008.             // Lock it down
  1009.             HLock(theHandle);
  1010.             
  1011.             // Get the size
  1012.             curEOF = GetHandleSize(theHandle);
  1013.             
  1014.             // Write it
  1015.             if (FSWrite(fRefNum,&curEOF,*theHandle) == noErr) {
  1016.                 // All Is well, make it not dirty
  1017.                 IS_DIRTY = FALSE;
  1018.                 
  1019.                 // And set the EOF
  1020.                 SetEOF(fRefNum,curEOF);
  1021.                 }
  1022.             else {
  1023.                 // Who knows what could go wrong here but!
  1024.                 SysBeep(1);
  1025.                 }
  1026.             
  1027.             // Unlock the handle
  1028.             HUnlock(theHandle);
  1029.             }
  1030.         else {
  1031.             // Could not get the handle
  1032.             SysBeep(1);
  1033.             }
  1034.             
  1035.         FSClose(fRefNum);
  1036.         MODTIME = GetModTime(&FILESPEC);
  1037.         }
  1038.     else {
  1039.         // Could not open the file
  1040.         SysBeep(1);
  1041.         }
  1042.  
  1043.     SetPort(oldPort);
  1044. }
  1045. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  1046. Boolean GetNewFileSpec(WindowPtr theWindow, FSSpecPtr theSpec)
  1047. {
  1048. Str63                theString;
  1049. Str32                thePrompt;
  1050. StandardFileReply    reply;
  1051.  
  1052.     GetWTitle(theWindow, theString);
  1053.     GetIndString(thePrompt, 100,2);
  1054.     StandardPutFile( thePrompt, theString, &reply);
  1055.     if (reply.sfGood) {
  1056.         BlockMove(&reply.sfFile, theSpec, sizeof(FSSpec));
  1057.         FSpDelete(theSpec);
  1058.         FSpCreate(theSpec,'PKLP','TEXT',0);
  1059.         return TRUE;
  1060.         }
  1061.     else 
  1062.         return FALSE;
  1063. }
  1064. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  1065. void PrintNote(WindowPtr theWindow, Boolean withPrompt)
  1066. {
  1067. OurWinHandle    theData;
  1068. Rect            printRect;
  1069. GrafPtr            oldPort;
  1070. TEHandle        hTE;
  1071. Boolean            done;
  1072. FontInfo        fInfo;
  1073. long            pageNumber;
  1074. Rect            viewRect;
  1075. Rect            destRect;
  1076. short            textWidth;
  1077. short            pageWidth;
  1078. short            offset;
  1079. short            count;
  1080. short            textTotalLength;
  1081. CharsHandle        hChars;
  1082. short            wordWidth;
  1083. short            wordLength;
  1084. short            vert;
  1085. Boolean            pageFull;
  1086.  
  1087.     GetPort(&oldPort);
  1088.  
  1089.     theData = (OurWinHandle)GetWRefCon(theWindow);
  1090.  
  1091.     if (withPrompt)
  1092.         DoPrintDialog();
  1093.     
  1094.     StartPrinting();
  1095.  
  1096.     done = FALSE;
  1097.     pageFull = FALSE;
  1098.     pageNumber = 1;
  1099.  
  1100.  
  1101.     offset = 0;
  1102.     count = 0;
  1103.  
  1104.     // Set the font and get the info
  1105.     TextFont(theWindow->txFont);
  1106.     TextSize(theWindow->txSize);
  1107.     TextFace(theWindow->txFace);
  1108.     GetFontInfo(&fInfo);
  1109.  
  1110.     hTE = HTE;
  1111.  
  1112.     hChars = TEGetText(hTE);
  1113.     textTotalLength = GetHandleSize(hChars);
  1114.     HLock((Handle)hChars);
  1115.  
  1116.     
  1117.     while (!done) {
  1118.         GetPageSizeWhileOpen(&printRect);
  1119.         pageWidth = printRect.right - printRect.left;        
  1120.             
  1121.         // reset the font
  1122.         TextFont(theWindow->txFont);
  1123.         TextSize(theWindow->txSize);
  1124.         TextFace(theWindow->txFace);
  1125.         
  1126.         vert = printRect.top + fInfo.ascent + fInfo.leading + fInfo.descent;
  1127.  
  1128.         while (vert < printRect.bottom - fInfo.descent && offset < textTotalLength) {        
  1129.             GetNextLine(hChars, offset, pageWidth, &wordLength);
  1130.             MoveTo(printRect.left, vert);
  1131.  
  1132.             // Get rid of invisibles at the begining of line
  1133.             while ((*hChars)[offset] < 33 && (*hChars)[offset] != 13) {
  1134.                 offset++;
  1135.                 wordLength--;
  1136.                 }
  1137.             if (offset+wordLength > textTotalLength)
  1138.                 wordLength = textTotalLength - offset;
  1139.                 
  1140.             DrawText(*hChars,offset,wordLength);
  1141.             offset+=wordLength;
  1142.             if ((*hChars)[offset] == 13)
  1143.                 offset++;
  1144.             
  1145.             vert+=fInfo.ascent + fInfo.leading + fInfo.descent;
  1146.             }
  1147.             
  1148.         if (offset >= textTotalLength) {
  1149.             done = TRUE;
  1150.             }
  1151.         
  1152.         if (!done) NextPage();
  1153.         }
  1154.  
  1155.     HUnlock((Handle)hChars);
  1156.         
  1157.     StopPrinting();
  1158.  
  1159.     SetPort(oldPort);
  1160. }
  1161. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  1162. void GetNextLine(CharsHandle    hChars, short    offset,short pageWidth, short *wordLength)
  1163. {
  1164. short    ourLength;
  1165. short    ourWidth;
  1166.  
  1167.     ourLength = 0;
  1168.     ourWidth = 0;
  1169.     
  1170.     while (ourWidth <  pageWidth) {
  1171.         *wordLength = ourLength;
  1172.         
  1173.         if (((*hChars)[offset + ourLength]) == 13) {
  1174.             // its a return key so add it to the line and return
  1175.             // because it is a natural break
  1176.             *wordLength = ourLength;
  1177.             return;
  1178.             }
  1179.         else {
  1180.             ourWidth = TextWidth((*hChars),offset,++ourLength);
  1181.             }
  1182.         }
  1183.     // peal off last word
  1184.     while ((*hChars)[offset+(*wordLength)] > 32 && *wordLength>0) {
  1185.         (*wordLength)--;
  1186.         }
  1187.     if (*wordLength<=0) 
  1188.         *wordLength = ourLength;
  1189. }
  1190. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••