home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / MLTE SDK / MLTESampleCarbon / MLTESampleCarbon.c next >
Encoding:
C/C++ Source or Header  |  2000-05-10  |  23.1 KB  |  879 lines  |  [TEXT/CWIE]

  1. /* ------------------------------------------------------------------------
  2.     Apple Worldwide Developer Technical Support
  3.  
  4.     Multi-Lingual Text Editor Sample, Carbon version
  5.  
  6.     This file: MLTESampleCarbon.c
  7.  
  8.     Versions:    1.0        12/99
  9.  
  10.     Components:
  11.                 MLTESampleCarbon.mcp        Dec 17, 1999
  12.                 MLTESampleCarbon.c            Dec 17, 1999
  13.                 MLTESampleCarbon.h            Dec 17, 1999
  14.                 MLTESampleCarbon.rsrc        Dec 17, 1999
  15.  
  16.     MLTESampleCarbon is an example application that demonstrates the 
  17.     fundamental MLTE toolbox calls in a CarbonLib context; it does 
  18.     not demonstrate all the techniques you need for a large application.
  19.     
  20.     You may incorporate this sample code into your applications without
  21.     restriction, though the sample code has been provided "AS IS" and the
  22.     responsibility for its operation is 100% yours.  However, what you are
  23.     not permitted to do is to redistribute the source as "Apple Sample Code"
  24.     after having made changes. If you're going to re-distribute the source,
  25.     we require that you make it clear in the source that the code was
  26.     descended from Apple Sample Code, but that you've made changes.
  27.  
  28.     Copyright © 1999-2000 Apple Computer, Inc., All Rights Reserved
  29.     
  30. --------------------------------------------------------------------------- */
  31. #define TARGET_API_MAC_CARBON 1
  32. #include "MLTESampleCarbon.h"
  33.  
  34. void main(void)
  35. {    
  36.     Initialize();
  37.     EventLoop();    // call the main event loop
  38. }
  39.  
  40. void Initialize()
  41. {
  42.     Handle    menuBar;
  43.     MenuRef    menu;
  44.     long    response;
  45.     OSErr     err;
  46.  
  47.     InitCursor();
  48.     InstallAppleEventHandlers();
  49.     if (TXNVersionInformation == (void*)kUnresolvedCFragSymbolAddress)
  50.         BigBadError(eWrongSystem);
  51.         
  52.     InitMLTE();                             // default settings for MLTE
  53.     
  54.     menuBar = GetNewMBar(rMenuBar);            // read in menubar definition
  55.     if (menuBar == NULL)
  56.         BigBadError(eNoMemory);
  57.     SetMenuBar(menuBar);                    // install menus
  58.     DisposeHandle(menuBar);
  59.     
  60.     err = Gestalt(gestaltSystemVersion, &response); 
  61.     if ((err == noErr) && (response >= 0x00001000))  // Check whether we are on Mac OS X
  62.     {
  63.         menu = GetMenuHandle(mFile);
  64.         DeleteMenuItem(menu, iQuit);
  65.         DeleteMenuItem(menu, iQuitSeparator);        // if on X, accomodate Aqua Quit interface
  66.     }
  67.  
  68.     // Get a new TXNFontMenuObject...
  69.     // A TXNFontMenuObject is an opaque structure that describes and handles 
  70.     // all aspects of user interaction with a Font menu. The menu is created 
  71.     // dynamically. The application provides the menu title, the menu ID, and 
  72.     // the menu ID to use if any hierarchical menus are created.  Hierarchical 
  73.     // menus are created on systems with ATSUI.
  74.     err = TXNNewFontMenuObject(GetMenuHandle(mFont), mFont, kStartHierMenuID, &gTXNFontMenuObject);
  75.     if (err != noErr)
  76.         BigBadError(eNoMemory);
  77.     DrawMenuBar();
  78.  
  79.     gInBackground = false;    
  80.     gNumDocuments = 0;
  81.     
  82.     DoNew(NULL);                            // create a single empty document    
  83. }
  84.  
  85. void InitMLTE(void)
  86. {
  87.     OSStatus                            status;
  88.     SInt16                                qdFontID;
  89.     TXNMacOSPreferredFontDescription    defaults;  // fontFamilyID, point size, style, and script code
  90.     
  91.     GetFNum(kDefaultFontName, &qdFontID);
  92.     
  93.     defaults.fontID = qdFontID;
  94.       defaults.pointSize = kTXNDefaultFontSize;
  95.       defaults.encoding = CreateTextEncoding(kTextEncodingMacRoman, kTextEncodingDefaultVariant, kTextEncodingDefaultFormat);
  96.       defaults.fontStyle     = kTXNDefaultFontStyle;
  97.  
  98.     TXNInitOptions options = kTXNWantMoviesMask | kTXNWantSoundMask | kTXNWantGraphicsMask;
  99.  
  100.     status = TXNInitTextension(&defaults, 1, options);
  101.     if (status != noErr)
  102.         BigBadError(eNoMLTE);
  103. }
  104.  
  105. // Get events forever, handle in DoEvent. Call AdjustCursor each time.
  106. void EventLoop()
  107. {
  108.     RgnHandle    cursorRgn;
  109.     Boolean        gotEvent;
  110.     EventRecord    event;
  111.  
  112.     cursorRgn = NewRgn();            // pass WNE an empty region 1st time thru
  113.  
  114.     do {
  115.         gotEvent = WaitNextEvent(everyEvent, &event, GetSleep(), cursorRgn);
  116.  
  117.         if (gotEvent)
  118.         {
  119.             // make sure we have the right cursor before handling the event
  120.             AdjustCursor(cursorRgn);
  121.             DoEvent(&event);
  122.         }
  123.         else
  124.         {
  125.             DoIdle();                // perform idle tasks when it’s not our event
  126.     //        TXNTSMCheck(NULL, &event);   // No longer needed in Carbon
  127.         }
  128.     } while (true);                    // loop forever... we quit via ExitToShell
  129. }
  130.  
  131. // Determine what kind of event we have, and call the appropriate routines.
  132. void DoEvent(EventRecord *event)
  133. {
  134.     short        part;
  135.     WindowPtr    window;
  136.     Boolean isDialogEvent;
  137.     
  138.     isDialogEvent = IsDialogEvent(event);
  139.     
  140.     if (isDialogEvent) 
  141.     {
  142.         DialogPtr    theDialog = NULL;
  143.         short        itemHit;
  144.         Boolean        result;
  145.  
  146.         result = DialogSelect(event, &theDialog, &itemHit);
  147.     }
  148.     switch (event->what) {
  149.         case nullEvent:
  150.             // we idle for null/mouse moved events and for events which aren’t ours
  151.             DoIdle();
  152.             break;
  153.         case mouseDown:
  154.             part = FindWindow(event->where, &window);
  155.             switch (part) {
  156.                 case inMenuBar:             // process a mouse menu command (if any)
  157.                     AdjustMenus();            // bring ’em up-to-date
  158.                     DoMenuCommand(MenuSelect(event->where));
  159.                     break;
  160.                 case inContent:
  161.                     if (window != FrontWindow()) 
  162.                         SelectWindow(window);
  163.                     else
  164.                     {
  165.                         DoContentClick(window, event);
  166.                         AdjustMenus();
  167.                     }
  168.                     break;
  169.                 case inDrag:                // pass screenBits.bounds to get all gDevices
  170.                     BitMap    screenBits;
  171.                             
  172.                     GetQDGlobalsScreenBits(&screenBits);
  173.                     DragWindow(window, event->where, &screenBits.bounds);
  174.                     break;
  175.                 case inGoAway:
  176.                     if (TrackGoAway(window, event->where))
  177.                         DoCloseWindow(window); // we don’t care if the user cancelled
  178.                     break;
  179.                 case inGrow:
  180.                     DoGrowWindow(window, event);
  181.                     break;
  182.                 case inZoomIn:
  183.                 case inZoomOut:
  184.                     if (TrackBox(window, event->where, part))
  185.                         DoZoomWindow(window, part);
  186.                     break;
  187.             }
  188.             break;
  189.         case keyDown:
  190.         case autoKey:                       // check for menukey equivalents 
  191.             if (event->modifiers & cmdKey)  // Command key down
  192.             {
  193.                 if (event->what == keyDown) 
  194.                 {
  195.                     AdjustMenus();            // enable/disable/check menu items properly
  196.                     DoMenuCommand(MenuKey(event->message & charCodeMask));
  197.                 }
  198.             } 
  199.             else
  200.                 DoKeyDown(event);
  201.             break;
  202.         case activateEvt:
  203.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  204.             break;
  205.         case updateEvt:
  206.             DoUpdate((WindowPtr) event->message);
  207.             break;
  208.         // handle disk inserted events so uninitialized floppies are recognized.
  209.         case osEvt:
  210.             // 1.02 - must BitAND with 0x0FF to get only low byt
  211.             switch ((event->message >> 24) & 0x0FF) // high byte of message
  212.             {        
  213.                 case mouseMovedMessage:
  214.                     DoIdle();                // mouse-moved is also an idle event 
  215.                     break;
  216.                 case suspendResumeMessage:    // suspend/resume is also an activate/deactivate 
  217.                     gInBackground = (event->message & resumeFlag) == 0;
  218.                     DoActivate(FrontWindow(), !gInBackground);
  219.                     break;
  220.             }
  221.             break;
  222.     }
  223. }
  224.  
  225. //    Change the cursor's shape, depending on its position.
  226. void AdjustCursor(RgnHandle region)
  227. {
  228.     WindowPtr    window = FrontWindow();            // only adjust the cursor when we are in front
  229.     TXNObject object = NULL;
  230.     
  231.     if (IsAppWindow(window, &object)) 
  232.         TXNAdjustCursor(object, region);
  233. }
  234.  
  235. // Handle a mouseDown in the grow box of an active window.
  236. void DoGrowWindow(WindowPtr window, EventRecord *event)
  237. {
  238.     TXNObject    object = NULL;
  239.     
  240.     if (IsAppWindow(window, &object))
  241.         // Should only be called for a TXNObject whose view rect occupies the entire
  242.         // window (e.g., a window is passed to TXNNewObject with a NULL FrameRect.)
  243.         TXNGrowWindow(object, event);
  244. }
  245.  
  246. // Handle a mouseClick in the zoom box of an active window.
  247. void DoZoomWindow(WindowPtr window, short part)
  248. {
  249.     TXNObject    object = NULL;
  250.     OSErr status = noErr;
  251.     
  252.     if (IsAppWindow(window, &object)) 
  253.         // Should only be called for a TXNObject whose view rect occupies the entire
  254.         // window (e.g., a window is passed to TXNNewObject with a NULL FrameRect.)
  255.         TXNZoomWindow(object, part);
  256. }
  257.  
  258. // Called when an update event is received for a window.
  259. void DoUpdate(WindowPtr window)
  260. {
  261.     GrafPtr        savePort;
  262.     TXNObject    object = NULL;
  263.     
  264.     GetPort(&savePort);
  265.     
  266.     if (IsAppWindow(window, &object)) 
  267.         TXNUpdate(object);        // TXNUpdate calls BeginUpdate() and EndUpdate()
  268.     SetPort(savePort);
  269. }
  270.  
  271. //    Called when a window is activated or deactivated
  272. void DoActivate(WindowPtr window, Boolean  becomingActive)
  273. {
  274.     TXNObject        object             = NULL;
  275.     TXNFrameID         frameID            = 0;
  276.     OSStatus        status            = noErr;
  277.     
  278.     if (IsAppWindow(window, &object))
  279.     {
  280.         status = GetWindowProperty(window, 'GRIT', 'tFrm', sizeof(TXNFrameID), NULL, &frameID);
  281.  
  282.         if (becomingActive) 
  283.         {
  284.             TXNActivate(object, frameID, kScrollBarsAlwaysActive);
  285.             AdjustMenus();
  286.         } 
  287.         else 
  288.             TXNActivate(object, frameID, kScrollBarsSyncWithFocus);
  289.     }
  290.     // Focus the TXNObject. Scroll bars and insertion caret become active/inactive
  291.     TXNFocus(object, becomingActive);
  292. }
  293.  
  294. //    Called when a mouseDown occurs in the content of a window
  295. void DoContentClick(WindowPtr window, EventRecord *event)
  296. {
  297.     TXNObject    object = NULL;
  298.     
  299.     if (IsAppWindow(window, &object))
  300.         TXNClick(object, event);
  301. }
  302.  
  303. // Called for any keyDown or autoKey events, except when the Command key is held down.
  304. // Looks at the frontmost window to decide what to do with the key typed. 
  305. void DoKeyDown(EventRecord *event)
  306. {
  307.     WindowPtr    window = FrontWindow();
  308.     TXNObject    object = NULL;
  309.         
  310. //    if (IsAppWindow(window, &object)) 
  311. //        TXNKeyDown(object, event);  // No longer needed in Carbon
  312. }
  313.  
  314. //    Calculate sleep value for WaitNextEvent.
  315. static UInt32 GetSleep()
  316. {
  317.     UInt32        sleep;
  318.     WindowPtr    window;
  319.     TXNObject    object = NULL;
  320.     
  321.     window = FrontWindow();                    // and the front window is ours
  322.     if (IsAppWindow(window, &object)) 
  323.         sleep = TXNGetSleepTicks(object);    // and the selection is an insertion point... 
  324.     else
  325.         sleep = GetCaretTime();                // blink time for the insertion point
  326.  
  327.     return sleep;
  328. }
  329.  
  330. // Called when we get a null event. Calls TXNIdle.
  331. void DoIdle()
  332. {
  333.     WindowPtr    window = FrontWindow();
  334.     TXNObject    object = NULL;
  335.         
  336.     if (IsAppWindow(window, &object))
  337.         TXNIdle(object);
  338. }
  339.  
  340. //    Enable and disable menus based on the current state.
  341. void AdjustMenus()
  342. {
  343.     WindowPtr    window;
  344.     MenuHandle    menu;
  345.     Boolean        undo;
  346.     Boolean        cutCopyClear;
  347.     Boolean        paste;
  348.     TXNObject    object = NULL;
  349.     
  350.     window = FrontWindow();
  351.  
  352.     menu = GetMenuHandle(mFile);
  353.     if (gNumDocuments < kMaxOpenDocuments)
  354.         EnableMenuItem(menu, iNew);        // New is enabled when we can open more documents
  355.     else
  356.         DisableMenuItem(menu, iNew);
  357.         
  358.     if (window != NULL)                    // Printing and Close are enabled when a window is up
  359.     {
  360.         EnableMenuItem(menu, iPageSetup);
  361.         EnableMenuItem(menu, iPrint);    
  362.         EnableMenuItem(menu, iClose);
  363.     }
  364.     else
  365.     {
  366.         DisableMenuItem(menu, iPageSetup);
  367.         DisableMenuItem(menu, iPrint);    
  368.         DisableMenuItem(menu, iClose);
  369.     }
  370.     
  371.     menu = GetMenuHandle(mEdit);
  372.     undo = cutCopyClear = paste = false;
  373.     
  374.     if (IsAppWindow(window, &object)) 
  375.     {
  376.         if (!TXNIsSelectionEmpty(object))
  377.             cutCopyClear = true;    // Cut, Copy, Clear enabled for app windows with selections
  378.             
  379.         if (TXNIsScrapPastable())    // if there is text in the clipboard, paste is enabled
  380.             paste = true;
  381.     }
  382.     
  383.     if (undo)
  384.         EnableMenuItem(menu, iUndo);
  385.     else
  386.         DisableMenuItem(menu, iUndo);
  387.         
  388.     if (cutCopyClear) 
  389.     {
  390.         EnableMenuItem(menu, iCut);
  391.         EnableMenuItem(menu, iCopy);
  392.         EnableMenuItem(menu, iClear);
  393.     } 
  394.     else 
  395.     {
  396.         DisableMenuItem(menu, iCut);
  397.         DisableMenuItem(menu, iCopy);
  398.         DisableMenuItem(menu, iClear);
  399.     }
  400.     
  401.     if (paste)
  402.         EnableMenuItem(menu, iPaste);
  403.     else
  404.         DisableMenuItem(menu, iPaste);
  405.         
  406.     if (TXNDataSize(object))        // if there is data in the object
  407.         EnableMenuItem(menu, iSelectAll);
  408.     
  409.     InvalMenuBar();        // invalidate menubar - it gets updated next event loop
  410. }
  411.  
  412. //    Handles items chosen from the menu bar.
  413. void DoMenuCommand(long menuResult)
  414. {
  415.     short                menuID, menuItem;
  416.     short                itemHit;
  417.     WindowPtr            window;
  418.     OSStatus            status = noErr;
  419.     TXNObject            object = NULL;
  420.     TXNTypeAttributes    typeAttr;
  421.  
  422.     window = FrontWindow();
  423.     menuID = HiWord(menuResult);    // use macros to get menu 
  424.     menuItem = LoWord(menuResult);    // item number and menu number
  425.  
  426.     switch (menuID) 
  427.     {
  428.         case mApple:
  429.             switch (menuItem) 
  430.             {
  431.                 case iAbout:        // bring up alert for About
  432.                     itemHit = Alert(rAboutAlert, NULL);
  433.                     break;
  434.                 default:
  435.                     break;
  436.             }
  437.             break;
  438.         case mFile:
  439.             switch (menuItem) 
  440.             {
  441.                 case iNew:
  442.                     DoNew(NULL);
  443.                     break;
  444.                 case iClose:
  445.                     DoCloseWindow(FrontWindow());            // ignore the result
  446.                     break;
  447.                 case iPageSetup:
  448.                     if (IsAppWindow(window, &object)) 
  449.                         status = TXNPageSetup(object);
  450.                     break;
  451.                 case iPrint:
  452.                     if (IsAppWindow(window, &object)) 
  453.                         status = TXNPrint(object);
  454.                     break;
  455.                 case iQuit:
  456.                     Terminate();
  457.                     break;
  458.             }
  459.             break;
  460.         case mEdit:            
  461.             if (IsAppWindow(window, &object))
  462.             {
  463.                 switch (menuItem) 
  464.                 {
  465.                     case iUndo:
  466.                         TXNUndo(object);
  467.                         break;
  468.                     case iCut:
  469.                         status = TXNCut(object);
  470.                         if (status != noErr)
  471.                             AlertUser(eNoCut);
  472.                         break;
  473.                     case iCopy:
  474.                         status = TXNCopy(object);
  475.                         if (status != noErr)
  476.                             AlertUser(eNoCopy);
  477.                         break;
  478.                     case iPaste:
  479.                         status = TXNPaste(object);
  480.                         if (status != noErr)
  481.                             AlertUser(eNoPaste);
  482.                         break;
  483.                     case iClear:
  484.                         status = TXNClear(object);
  485.                         if (status != noErr)
  486.                             AlertUser(eNoClear);
  487.                         break;
  488.                     case iSelectAll:
  489.                         TXNSelectAll(object);
  490.                     default:
  491.                         break;
  492.                 }
  493.             }    
  494.         case mFont:            
  495.             if (IsAppWindow(window, &object))
  496.             {
  497.                 if (gTXNFontMenuObject != NULL)    // change to the selected font
  498.                      status = TXNDoFontMenuSelection(object, gTXNFontMenuObject, menuID, menuItem);
  499.                 if (status != noErr)             //    Check for error
  500.                     AlertUser(eNoFontName);
  501.                 break;
  502.             }
  503.         case mSize:
  504.             if (IsAppWindow(window, &object))
  505.             {
  506.                 static short aFontSizeList[] = {9, 10, 12, 14, 18, 24, 36};
  507.                 short shortValue = aFontSizeList[menuItem - 1];
  508.                 
  509.                 //    Specify the size attributes
  510.                 typeAttr.tag = kTXNQDFontSizeAttribute;
  511.                 typeAttr.size = kTXNQDFontSizeAttributeSize;
  512.                 typeAttr.data.dataValue = shortValue << 16;
  513.                 
  514.                 //    Set the size attributes
  515.                  status = TXNSetTypeAttributes(object, 1, &typeAttr, kTXNUseCurrentSelection, kTXNUseCurrentSelection);
  516.                  if (status != noErr)         //    Check for error
  517.                     AlertUser(eNoFontSize);
  518.                 break; 
  519.             }
  520.         case mStyle:
  521.             if (IsAppWindow(window, &object))
  522.             {
  523.                 Style    newStyle;
  524.                 
  525.                 switch (menuItem) 
  526.                 {
  527.                     case iPlain:
  528.                         newStyle = normal;        // 0        
  529.                         break;
  530.                     case iBold:
  531.                         newStyle = bold;        // 1                
  532.                         break;
  533.                     case iItalic:
  534.                         newStyle = italic;        // 2                
  535.                         break;
  536.                     case iUnderline:
  537.                         newStyle = underline;    // 3                
  538.                         break;
  539.                     case iOutline:
  540.                         newStyle = outline;        // 4                
  541.                         break;
  542.                     case iShadow:
  543.                         newStyle = shadow;        // 0x10                
  544.                         break;
  545.                     case iCondensed:
  546.                         newStyle = condense;    // 0x20                
  547.                         break;                    
  548.                     case iExtended:
  549.                         newStyle = extend;        // 0x40                
  550.                         break;
  551.                     default:
  552.                         break;
  553.                 }
  554.             
  555.                 // Specify the sytle attributes
  556.                 typeAttr.tag = kTXNQDFontStyleAttribute;
  557.                 typeAttr.size = kTXNQDFontStyleAttributeSize;
  558.                 typeAttr.data.dataValue = newStyle;
  559.  
  560.                 // Set the style attributes
  561.                 status = TXNSetTypeAttributes(object, 1, &typeAttr, kTXNUseCurrentSelection, kTXNUseCurrentSelection);
  562.                 if (status != noErr)         //    Check for error
  563.                     AlertUser(eNoFontStyle);
  564.                 break;
  565.             }
  566.         case mLayout:
  567.             if (menuItem <= iForceJustify)
  568.                 DoJustification(window, menuItem);
  569.             else
  570.                 DoWordWrap(window);
  571.             break;
  572.         default:
  573.             break;
  574.     }
  575.     
  576.     HiliteMenu(0);                            // unhighlight the menu
  577.     AdjustMenus();
  578. }
  579.  
  580. // Set the justification tag
  581. void DoJustification(WindowPtr window, short menuItem)
  582. {
  583.     TXNObject    object = NULL;
  584.     MenuHandle     layoutMenu;
  585.     OSStatus    status = noErr;
  586.     
  587.     layoutMenu = GetMenuHandle(mLayout);
  588.     
  589.     if (IsAppWindow(window, &object)) 
  590.     {
  591.         SInt32            justification;
  592.         TXNControlTag    controlTag[1];
  593.         TXNControlData    controlData[1];
  594.         
  595.         for (int i = 1; i <= iForceJustify; i++)    // brute technique to uncheck last item
  596.             CheckMenuItem(layoutMenu, i, false);
  597.         switch (menuItem) 
  598.         {
  599.             case iDefaultJustify:
  600.                 justification = kTXNFlushDefault;    // flush according to the line direction                        
  601.                 break;
  602.             case iLeftJustify:
  603.                 justification = kTXNFlushLeft;
  604.                 break;
  605.             case iRightJustify:
  606.                 justification = kTXNFlushRight;
  607.                 break;
  608.             case iCenterJustify:
  609.                 justification = kTXNCenter;
  610.                 break;
  611.             case iFullJustify:
  612.                 justification = kTXNFullJust;
  613.                 break;
  614.             case iForceJustify:
  615.                 justification = kTXNForceFullJust;    // flush left for all scripts
  616.                 break;
  617.             default:
  618.                 break;
  619.         }
  620.         CheckMenuItem(layoutMenu, menuItem, true);        // check this menu item
  621.         
  622.         controlTag[0] = kTXNJustificationTag;
  623.         status = TXNGetTXNObjectControls(object, 1, controlTag, controlData);
  624.         if (controlData[0].sValue != justification) // if we have a new justification
  625.         {                     
  626.             controlData[0].sValue = justification;
  627.             status = TXNSetTXNObjectControls(object, false, 1, controlTag, controlData);
  628.         }
  629.         if (status != noErr)
  630.             AlertUser(eNoJustification);
  631.     }
  632. }
  633.  
  634. // Toggle word wrapping
  635. void DoWordWrap(WindowPtr window)
  636. {
  637.     TXNObject    object = NULL;
  638.     MenuHandle     layoutMenu;
  639.     OSStatus    status = noErr;
  640.     
  641.     layoutMenu = GetMenuHandle(mLayout);
  642.     
  643.     if (IsAppWindow(window, &object))
  644.     {
  645.         TXNControlTag    controlTag[1];
  646.         TXNControlData    controlData[1];
  647.  
  648.         controlTag[0] = kTXNWordWrapStateTag;
  649.  
  650.         status = TXNGetTXNObjectControls(object, 1, controlTag, controlData);
  651.  
  652.         if (controlData[0].uValue == kTXNAutoWrap)         // if we are autowrapped
  653.         {             
  654.             controlData[0].uValue = kTXNNoAutoWrap;     // toggle to not autowrapped
  655.             CheckMenuItem(layoutMenu, iAutoWrap, false);// uncheck this menu item
  656.         }
  657.         else
  658.         {
  659.             controlData[0].uValue = kTXNAutoWrap;
  660.             CheckMenuItem(layoutMenu, iAutoWrap, true);    // check this menu item
  661.         }
  662.             
  663.         status = TXNSetTXNObjectControls(object, false, 1, controlTag, controlData);
  664.         if (status != noErr)
  665.             AlertUser(eNoWordWrap);
  666.     }
  667. }
  668.  
  669. // Create a new document and window.
  670. OSStatus DoNew(const FSSpec *fileSpecPtr)
  671. {
  672.     OSStatus        status = noErr;
  673.     WindowPtr        window;
  674.     MenuHandle         layoutMenu;
  675.     
  676.     window = GetNewCWindow(rDocWindow, NULL, (WindowPtr)-1L);
  677.     
  678.     if (window != NULL) 
  679.     {
  680.         TXNObject        object = NULL;
  681.         TXNFrameID        frameID    = 0;
  682.         WindowPtr        paramWindow = NULL;
  683.         Rect            frame;
  684.         TXNFrameOptions    frameOptions;
  685.         
  686.         frameOptions = kTXNShowWindowMask; // ShowWindow() not needed if kTXNShowWindowMask used
  687.         frameOptions |= kTXNWantHScrollBarMask | kTXNWantVScrollBarMask;
  688.         frameOptions |= kTXNDrawGrowIconMask | kTXNNoKeyboardSyncMask;
  689.         
  690.         paramWindow = window;
  691.         GetWindowPortBounds(window, &frame);
  692.  
  693.         status = TXNNewObject(    fileSpecPtr, 
  694.                                 paramWindow, 
  695.                                 &frame,
  696.                                 frameOptions,
  697.                                 kTXNTextEditStyleFrameType,
  698.                                 kTXNTextensionFile,
  699.                                 kTXNSystemDefaultEncoding,
  700.                                 &object,
  701.                                 &frameID, 
  702.                                 0);
  703.         if (status == noErr) 
  704.         {
  705.             status = TXNAttachObjectToWindow(object, (GWorldPtr) window, true);    
  706.             if (status != noErr)
  707.                 AlertUser(eNoAttachObjectToWindow);
  708.         }
  709.         
  710.         if (status == noErr)
  711.         {        
  712.             if (object != NULL) 
  713.             {
  714.                 Boolean    isAttached;
  715.  
  716.                 //    Activate the window.
  717.                 status = TXNActivate(object, frameID, kScrollBarsAlwaysActive);
  718.                 if (status != noErr)
  719.                     AlertUser(eNoActivate);
  720.             
  721.                 //    Set the ID type of this window.
  722.             // DG    storage->SetWindow(window);
  723.             // DG    storage->SetObjectAttributes(object, frameID, kTXNDocRefCon);
  724.             // DG    storage->SetFileSpec(fileSpecPtr);
  725.                 
  726.                 status = SetWindowProperty(window,'GRIT','tFrm',sizeof(TXNFrameID),&frameID);
  727.                 status = SetWindowProperty(window,'GRIT','tObj',sizeof(TXNObject),&object);
  728.                 
  729.                 //    Check if object is really attached to the window.
  730.                  isAttached = TXNIsObjectAttachedToWindow(object);
  731.                 if (!isAttached)
  732.                     AlertUser(eObjectNotAttachedToWindow);
  733.             }
  734.  
  735.             AdjustMenus();
  736.             gNumDocuments++;                            // will be decremented in DoCloseWindow
  737.             
  738.             DoJustification(window, iDefaultJustify);     // set justification default for new doc
  739.     
  740.             layoutMenu = GetMenuHandle(mLayout);
  741.             CheckMenuItem(layoutMenu, iAutoWrap, true);    // check this menu item
  742.         } 
  743.     }
  744.     else
  745.     {
  746.         DisposeWindow(window);
  747.         window = NULL;
  748.         AlertUser(eNoWindow);        // and tell user
  749.     }
  750.     return status;
  751. }
  752.  
  753. // Close a window. Handles desk accessory and application windows.
  754. Boolean DoCloseWindow(WindowPtr window)
  755. {
  756.     Boolean        isClosed     = true;
  757.     TXNObject    object         = NULL;
  758.  
  759.     if (IsAppWindow(window, &object)) 
  760.     {
  761. // DG    if (TXNGetChangeCount(object))    // if document has been changed
  762. // DG        isClosed = ShowSaveDialog(window, object);
  763.         if (isClosed) 
  764.         {
  765.             TXNDeleteObject(object);
  766.             DisposeWindow(window);
  767.             gNumDocuments -= 1;
  768.         }
  769.     }
  770.     AdjustMenus();
  771.     return isClosed;
  772. }
  773.  
  774. // Clean up and exit. Close all of the windows. If a cancel occurrs, return instead.
  775. void Terminate()
  776. {
  777.     WindowPtr    aWindow;
  778.     Boolean        closed;
  779.     
  780.     closed = true;
  781.     do {
  782.         aWindow = FrontWindow();                // get current front window
  783.         if (aWindow != NULL)
  784.             closed = DoCloseWindow(aWindow);    // close this window
  785.     }
  786.     while (closed && (aWindow != NULL));
  787.     if (closed)
  788.     {
  789.         // Dispose the font menu object before terminating Textension.
  790.         if (gTXNFontMenuObject != NULL) 
  791.         {
  792.             OSStatus    status;
  793.         
  794.             status = TXNDisposeFontMenuObject(gTXNFontMenuObject);
  795.             if (status != noErr)
  796.                 AlertUser(eNoDisposeFontMenuObject);
  797.  
  798.             //    Nullify font menu object even if error.
  799.             gTXNFontMenuObject = NULL;
  800.         }
  801.     }
  802.     TXNTerminateTextension();
  803.     ExitToShell();                        // exit if no cancellation
  804. }
  805.  
  806. // Check whether a window is a document window created by the application. They
  807. // are distinguished from dialogs and other windows by their windowKind userKind.
  808. Boolean IsAppWindow(WindowPtr window, TXNObject *object)
  809. {
  810.     OSErr status = noErr;
  811.     
  812.     status = GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, object);
  813.     return (window != NULL) && (GetWindowKind(window) == userKind);
  814. }
  815.  
  816. //    Display an alert that tells the user an error occurred.
  817. void AlertUser(short error)
  818. {
  819.     short        itemHit;
  820.     Str255        message;
  821.     Cursor        arrow;
  822.     
  823.     SetCursor(GetQDGlobalsArrow(&arrow));
  824.     GetIndString(message, kErrStrings, error);
  825.     ParamText(message, (ConstStr255Param)"",(ConstStr255Param)"", (ConstStr255Param)"");
  826.     itemHit = Alert(rUserAlert, NULL);
  827. }
  828.  
  829. // Used whenever a fatal error happens
  830. void BigBadError(short error)
  831. {
  832.     AlertUser(error);
  833.     ExitToShell();
  834. }
  835.  
  836. // install the core apple event handlers
  837. void InstallAppleEventHandlers(void)
  838. {
  839.     long result;
  840.     
  841.     OSErr err = Gestalt(gestaltAppleEventsAttr, &result);
  842.     
  843.     if (err == noErr)
  844.     {    // we should check the AEInstallEventHandler return value but since it's just a sample...
  845.         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOapp), 0, false);
  846.         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,   NewAEEventHandlerProc(HandleOdoc), 0, false);
  847.         AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,  NewAEEventHandlerProc(HandlePdoc), 0, false);
  848.         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQuit), 0, false);
  849.     }
  850. }
  851.  
  852. // Respond to an open application apple event
  853. pascal OSErr HandleOapp (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  854. {
  855. #pragma unused (aevt, reply, refCon)
  856.     return noErr;
  857. }
  858.  
  859. // Respond to an open document apple event
  860. pascal OSErr HandleOdoc (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  861. {
  862. #pragma unused (aevt, reply, refCon)
  863.     return errAEEventNotHandled;
  864. }
  865.  
  866. // Respond to a print apple event
  867. pascal OSErr HandlePdoc (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  868. {
  869. #pragma unused (aevt, reply, refCon)
  870.     return errAEEventNotHandled;
  871. }
  872.  
  873. // Respond to a quit apple event
  874. pascal OSErr HandleQuit (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  875. {
  876. #pragma unused (aevt, reply, refCon)
  877.     Terminate();
  878.     return noErr;
  879. }