home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / gui / macutil.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  54.5 KB  |  2,071 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /***********************************************************************************
  20.  * macutil.cp
  21.  *
  22.  * Various mac utility routines
  23.  *
  24.  ***********************************************************************************/
  25.  
  26. #include <stdarg.h>
  27.  
  28. #include <Traps.h>
  29. #include <LPlaceHolder.h>
  30. #include <LHandleStream.h>
  31. //#include <LTextEngine.h>
  32. #include "macutil.h"
  33. #include "resgui.h"
  34. #include "uprefd.h"
  35. #include "ufilemgr.h"
  36. #include "uerrmgr.h"
  37. #include "xp.h"
  38. #include "cstring.h"
  39. #include "xpassert.h"
  40. #include "xp_trace.h"
  41. #include "macgui.h"
  42. #include "prefapi.h"
  43. #include "MoreDesktopMgr.h"
  44. extern "C" {
  45.     #include "asyncCursors.h"
  46. }
  47.  
  48. #include "mfinder.h" // needed for workaround function to bug in Apple's
  49.                      // ::TruncText and ::TruncString - andrewb 6/20/97
  50.                      
  51. #include "MoreMixedMode.h"
  52. #include "PascalString.h"
  53.  
  54. /*-----------------------------------------------------------------------------
  55.     Layout Utilities
  56. -----------------------------------------------------------------------------*/
  57.  
  58. // Another mlanett special
  59. static void GetImageRect( LView* view, SPoint32* topLeft, SPoint32* botRight );
  60. static void GetImageRect( LView* view, SPoint32* topLeft, SPoint32* botRight )
  61. {
  62. /*    
  63.     Return the visible image of this view.
  64. */
  65.     SPoint32        frameLocation;
  66.     SDimension16    frameSize;
  67.     SPoint32        imageLocation;
  68.  
  69.     view->GetFrameLocation( frameLocation );
  70.     view->GetFrameSize( frameSize );
  71.     view->GetImageLocation( imageLocation );
  72.  
  73.     // convert local rectangle to image rectangle
  74.     topLeft->h     = frameLocation.h - imageLocation.h; // frameLocation.h - portOrigin.h - imageLocation.h;
  75.     botRight->h = topLeft->h + frameSize.width;
  76.     topLeft->v     = frameLocation.v - imageLocation.v; // frameLocation.v - portOrigin.v - imageLocation.v;
  77.     botRight->v = topLeft->v + frameSize.height;
  78. }
  79.  
  80. void RevealInImage( LView* view, SPoint32 selTopLeft, SPoint32 selBotRight )
  81. {
  82. /*
  83.     Scroll the minimum amount necessary to reveal this image rectangle.
  84.     In this diagram, the selection is scrolled above the visible rectangle.
  85.     Therefore selection-top is less than image-top, so we need to scroll
  86.     down by above-amount.
  87.                 /---\
  88.             /---|   |
  89.             |    \---/
  90.             v
  91.     /--------------\
  92.     |              |
  93.     |              |
  94.     |              |
  95.     |              |
  96.     \--------------/
  97. */
  98.     SPoint32    iTopLeft;
  99.     SPoint32    iBotRight;
  100.  
  101.     GetImageRect( view, &iTopLeft, &iBotRight );
  102.     
  103.     Int32 aboveAmount = selTopLeft.v - 20 - iTopLeft.v;
  104.     Int32 belowAmount = selTopLeft.v + 20 - iTopLeft.v;
  105.     Int32 leftAmount = selTopLeft.h - iTopLeft.h;
  106.     Int32 rightAmount = selBotRight.h - iBotRight.h;
  107.     
  108.     if ( aboveAmount < 0 )
  109.         view->ScrollImageBy( 0, aboveAmount, TRUE );
  110.     else if ( ( selBotRight.v - iBotRight.v ) > 0 )
  111.     {
  112.         // don't scroll the top off!
  113.         // belowAmount and aboveAmount are negative
  114.         // belowAmount must be (absolute) less than aboveAmount
  115.         view->ScrollImageBy( 0, belowAmount > aboveAmount ? aboveAmount : belowAmount, TRUE );
  116.     }
  117.     
  118.     if ( leftAmount < 0 )
  119.         view->ScrollImageBy( leftAmount, 0, TRUE );
  120.     else if ( rightAmount > 0 )
  121.     {
  122.         // don't scroll the left off!
  123.         // belowAmount and leftAmount are negative
  124.         // belowAmount must be (absolute) less than aboveAmount
  125.         view->ScrollImageBy( rightAmount > leftAmount? leftAmount: rightAmount, 0, TRUE );
  126.     }
  127. }
  128.  
  129. Boolean TooDifferent( const Point& a, const Point& b )
  130. {
  131.     return abs( b.h - a.h ) >= MOUSE_HYSTERESIS || abs( b.v - a.v ) >= MOUSE_HYSTERESIS;
  132. }
  133.  
  134. short WaitForMouseAction( const Point& initial, long clickStart, long delay )
  135. {
  136.     Point        current;
  137.     long        now;
  138.     
  139.     while ( ::StillDown() )
  140.     {
  141.         ::GetMouse( ¤t );
  142.         if ( TooDifferent( initial, current ) )
  143.             return MOUSE_DRAGGING;
  144.         now = ::TickCount();
  145.         if ( abs( now - clickStart ) > delay)
  146.             return MOUSE_TIMEOUT;
  147.     }
  148.     
  149.     return MOUSE_UP_EARLY;
  150. }
  151.  
  152.  
  153. int // offset
  154. CalcCurrentSelected (lo_FormElementSelectData * selectData, Boolean fromDefaults)
  155. {
  156.     int offset = 0;
  157.     
  158.     lo_FormElementOptionData * optionData;
  159.     PA_LOCK(optionData, lo_FormElementOptionData *, selectData->options);
  160.     for (int i=0; i<selectData->option_cnt; i++) {
  161.         char * itemName = NULL;
  162.         PA_LOCK(itemName, char*, optionData[i].text_value);
  163.         if (fromDefaults) {
  164.             if (optionData[i].def_selected) {
  165.                 offset = i;
  166.                 break;
  167.             }
  168.         }
  169.         else {
  170.             if (optionData[i].selected) {
  171.                 offset = i;
  172.                 break;
  173.             }
  174.         }
  175.         PA_UNLOCK(optionData[i].text_value);
  176.     }
  177.     PA_UNLOCK(selectData->options);
  178.     
  179.     return offset;
  180. }
  181.  
  182. /*-----------------------------------------------------------------------------
  183.     Generic Utilities
  184. -----------------------------------------------------------------------------*/
  185.  
  186. Rect CenterInRect( Point thing, Rect destSpace )
  187. {
  188.     Point        destSize;
  189.     Point        centeredSize;
  190.     Rect        centeredThing;
  191.     
  192.     destSize.h = destSpace.right - destSpace.left;
  193.     destSize.v = destSpace.bottom - destSpace.top;
  194.     centeredSize.h = MIN( destSize.h, thing.h );
  195.     centeredSize.v = MIN( destSize.v, thing.v );
  196.     centeredThing.left = destSpace.left + ( destSize.h - centeredSize.h ) / 2;
  197.     centeredThing.top = destSpace.top + ( destSize.v - centeredSize.v ) / 2;
  198.     centeredThing.right = centeredThing.left + centeredSize.h;
  199.     centeredThing.bottom = centeredThing.top + centeredSize.v;
  200.     return centeredThing;
  201. }
  202.  
  203. /*-----------------------------------------------------------------------------
  204.     String Copying
  205. -----------------------------------------------------------------------------*/
  206.  
  207. unsigned char* CopyString( unsigned char* destination, const unsigned char* source )
  208. {
  209.     BlockMove (source, destination, source[0]+1);
  210.     return destination;
  211. }
  212.  
  213. unsigned char* CopyString( unsigned char* destination, const char* source )
  214. {
  215.     destination[0] = strlen (source);
  216.     BlockMove (source, destination + 1, destination[0]);
  217.     return destination;
  218. }
  219.  
  220. char* CopyString( char* destination, const unsigned char* source )
  221. {
  222.     BlockMove (source + 1, destination, source[0]);
  223.     destination[source[0]] = 0;
  224.     return destination;
  225. }
  226.  
  227. char* CopyString( char* destination, const char* source )
  228. {
  229.     register int length = strlen (source);
  230.     BlockMove (source, destination, length + 1);
  231.     return destination;
  232. }
  233.  
  234. void CopyAlloc(char ** destination, StringPtr source)
  235. {
  236.     // NET_SACopy frees a non-null destination itself
  237.     //if (*destination != NULL)
  238.     //    XP_FREE(*destination);
  239.     p2cstr(source);
  240.     
  241.     // We don't really want to delete any existing storage for destination so borrow
  242.     // some code from NET_SACopy and skip the XP_FREE of destination
  243.     //NET_SACopy(destination, (char*)source);
  244.     if (! source)
  245.     {
  246.         *destination = NULL;
  247.     }
  248.     else
  249.     {
  250.         *destination = (char *) XP_ALLOC (XP_STRLEN((const char *)source) + 1);
  251.         if (*destination != NULL)
  252.             XP_STRCPY (*destination, (const char *)source);
  253.     }
  254.     
  255.     c2pstr((char*)source);
  256. }
  257.  
  258. // Takes colons out of a string
  259. void StripColons( CStr31& fileName )
  260. {
  261.     short count;
  262.     
  263.     for ( count = 1; count <= fileName.Length(); count++ )
  264.         if ( fileName[count] == ':' )
  265.             fileName[count] = ' ';
  266. }
  267.  
  268. // strips single instances of ch from the given string.
  269. // If ch appears twice in a row, the second one is not removed.
  270. void StripChar( CStr255& str, char ch )
  271. {
  272.     int len = str.Length();
  273.     for (short i = 1; i <= len; i++)
  274.         if (str[i] == ch) {
  275.             BlockMoveData(&str[i + 1], &str[i], len - i);
  276.             i++;
  277.             len -= 1;
  278.         }
  279.     str[0] = len;
  280. }
  281.  
  282. // Ñ Takes a string of text (dragged/pasted), and turns
  283. // it into a URL (strips CR, whitespace preceeding/trailing <>
  284. void CleanUpTextToURL(char* text)
  285. {
  286.     if (text == NULL)
  287.         return;
  288.     
  289.     long len = XP_STRLEN(text);
  290.             
  291.     int i=0;
  292.     
  293.     if (text[0] == '<')    // Swallow the surrounding '<' and '>'
  294.         ::BlockMoveData(&text[1], &text[0], len);
  295.     
  296.     while (text[i] != 0) // Loop till whitespace
  297.     {
  298.         if (XP_IS_SPACE(text[i]))
  299.             break;
  300.         i++;
  301.     }
  302.     if (text[i-1] == '>')    // Swallow the ending '>'
  303.         i--;
  304.  
  305.     text[i] = 0;    
  306. }
  307.  
  308. void CleanUpLocationString (CStr255 & url)
  309. {
  310. //    Strips spaces & returns at end of url (happens often
  311. //    when you paste into url box)
  312.     int last;
  313.     while ((last = url.Length()) != 0) {
  314.         if (url[last] == '\n' || url[last] == ' ' || url[last] == '\r')
  315.             url.Length()--;
  316.         else break;
  317.     }
  318. }
  319.  
  320. // TRUE if the key is down. Bypasses the event loop
  321. Boolean IsThisKeyDown(const UInt8 theKey)
  322. {
  323.     KeyMap map;
  324.     
  325.     GetKeys(map);
  326.     
  327.     return ((*((UInt8 *)map + (theKey >> 3)) >> (theKey & 7)) & 1) != 0;
  328. } // IsThisKeyDown - don's improved non-union (as in struct) version
  329.  
  330.  
  331.  
  332. // A mess that figures out if cmd-. was pressed
  333. /* Borrowed from tech note 263 */
  334.  
  335. #define kMaskModifiers      0xFE00         // we need the modifiers without the
  336.                                            // command key for KeyTrans
  337. #define kMaskVirtualKey     0x0000FF00     // get virtual key from event message
  338.                                            // for KeyTrans
  339. #define kUpKeyMask          0x0080
  340. #define kShiftWord          8              // we shift the virtual key to mask it
  341.                                            // into the keyCode for KeyTrans
  342. #define kMaskASCII1         0x00FF0000     // get the key out of the ASCII1 byte
  343. #define kMaskASCII2         0x000000FF     // get the key out of the ASCII2 byte
  344. #define kPeriod             0x2E           // ascii for a period
  345. Boolean CmdPeriod()
  346. {
  347.     EvQElPtr        eventQ = (EvQElPtr)LMGetEventQueue()->qHead;
  348.  
  349.     while (eventQ != NULL)
  350.     {
  351.         EventRecord * theEvent =  (EventRecord *)&eventQ->evtQWhat;
  352.  
  353.           UInt16    keyCode;
  354.           UInt32      state;
  355.           long     virtualKey, keyInfo, lowChar, highChar, keyCId;
  356.           Handle   hKCHR;
  357.         Ptr         KCHRPtr;
  358.     
  359.     
  360.         if (((*theEvent).what == keyDown) || ((*theEvent).what == autoKey)) {
  361.     
  362.             // see if the command key is down.  If it is, find out the ASCII
  363.             // equivalent for the accompanying key.
  364.     
  365.             if ((*theEvent).modifiers & cmdKey ) {
  366.     
  367.                 virtualKey = ((*theEvent).message & kMaskVirtualKey) >> kShiftWord;
  368.                 // And out the command key and Or in the virtualKey
  369.                 keyCode    = short(((*theEvent).modifiers & kMaskModifiers) | virtualKey);
  370.                 state      = 0;
  371.     
  372.     
  373.                 hKCHR = nil;  /* set this to nil before starting */
  374.                  KCHRPtr = (Ptr)GetScriptManagerVariable(smKCHRCache);
  375.     
  376.                 if ( !KCHRPtr ) {
  377.                     keyCId = ::GetScriptVariable(short(GetScriptManagerVariable(smKeyScript)), smScriptKeys);
  378.     
  379.                     hKCHR   = GetResource('KCHR',short(keyCId));
  380.                     KCHRPtr = *hKCHR;
  381.                 }
  382.                 if (KCHRPtr) {
  383.                     keyInfo = KeyTranslate(KCHRPtr, keyCode, &state);
  384.                     if (hKCHR)
  385.                         ReleaseResource(hKCHR);
  386.                 } else
  387.                     keyInfo = (*theEvent).message;
  388.     
  389.                 lowChar =  keyInfo &  kMaskASCII2;
  390.                 highChar = (keyInfo & kMaskASCII1) >> 16;
  391.                 if (lowChar == kPeriod || highChar == kPeriod)
  392.                     return TRUE;
  393.     
  394.             }  // end the command key is down
  395.         }  // end key down event
  396.         eventQ = (EvQElPtr)eventQ->qLink;
  397.     }
  398.     return FALSE;
  399. }
  400.  
  401. // Sets button state and redraws it
  402. void SetEnable( LPane* button, Boolean enable )
  403. {
  404.     if ( !button->IsEnabled() && enable )
  405.         button->Enable();
  406.     else if ( button->IsEnabled() && !enable )
  407.         button->Disable();
  408. }
  409.  
  410. // Changes the string to something acceptable to mac menu manager
  411. void CreateMenuString( CStr255& itemName )
  412. {
  413.     itemName=NET_UnEscape(itemName);
  414.     if ( itemName.Length() > 50 )    // Cut it down to reasonable size
  415.     {
  416.         itemName.Length() = 50;
  417.         itemName += "...";
  418.     }
  419.     if ( itemName.Length() && itemName[ 1 ] == '-' )
  420.         itemName[ 1 ] = '╨';
  421. }
  422.  
  423. // TextHandleToHardLineBreaks
  424. // converts TextEdit handle to text handle that has hard carriage returns.
  425.  
  426. Handle TextHandleToHardLineBreaks( CSimpleTextView &inTextView )
  427. {
  428.     Handle theOldText = inTextView.GetTextHandle();
  429.     ThrowIfNULL_(theOldText);
  430.     
  431.     SInt32 theTotalLength = inTextView.GetTextLength();
  432.     
  433. //    TextRangeT theTotalRange =     inEngine->GetTotalRange();
  434.  
  435. //    Int32 theLineCount =  inEngine->CountParts(theTotalRange, cLine);
  436.  
  437.     Int32 theLineCount = inTextView.CountLines();
  438.     
  439.     // text will expand by at most as many line breaks as there are lines
  440.     Handle theNewText = ::NewHandle(theTotalLength + theLineCount);
  441.     ThrowIfNULL_(theNewText);
  442.  
  443.     // Lock down both text buffers
  444.     StHandleLocker theOldLock(theOldText);
  445.     StHandleLocker theNewLock(theNewText);
  446.     
  447.     Int32 theBreakCount = 0;
  448.     Int32 theNewTextOffset = 0;
  449.     SInt32    lineStart     = 0;
  450.     SInt32    lineEnd            = 0;
  451.         
  452.     Boolean bEatAgain = false;
  453.     
  454.     for (Int32 theIndex = 1; theIndex <= theLineCount; theIndex++)
  455.         {
  456. //        TextRangeT theLineRange;
  457. //        inEngine->FindNthPart(theTotalRange, cLine, theIndex, &theLineRange);
  458.             
  459.             // Waste appears to be Zero based rather than 1
  460.             inTextView.GetLineRange( theIndex - 1, &lineStart, &lineEnd );
  461.                     
  462.             ::BlockMoveData(*theOldText + lineStart, *theNewText + theNewTextOffset, lineEnd - lineStart );
  463.             theNewTextOffset += lineEnd - lineStart;
  464.  
  465.             Boolean eatNextLine = ((theIndex + 1) < theLineCount)                     && // This is to prevent overflow on end
  466.                                 (((*theOldText)[lineStart] == '>'         &&
  467.                                 (*theOldText)[lineEnd + 1] != '>'))        ||
  468.                                  bEatAgain;
  469.                                  
  470.             if ((*theNewText)[theNewTextOffset -1 ] == CR)
  471.                 {
  472.                 (*theNewText)[theNewTextOffset - 1] = CR;
  473.                 bEatAgain = false;
  474.                 }
  475.             else
  476.                 {
  477.                 if (eatNextLine)
  478.                     bEatAgain = true;    // Only
  479.                 else
  480.                     {
  481.                     (*theNewText)[++theNewTextOffset - 1] = CR;
  482.                     bEatAgain = false;
  483.                     }
  484.                 }
  485.         }
  486.  
  487.     ::SetHandleSize(theNewText, theNewTextOffset); // Reduce the size of the handle
  488.     return theNewText;
  489. }
  490.  
  491.  
  492. void ConstrainTo( const long& min, const long& max, long& value )
  493. {
  494.     XP_WARN_ASSERT( min <= value && value <= max );
  495.     if ( value < min )
  496.         value = min;
  497.     else if ( value > max )
  498.         value = max;
  499. }
  500.  
  501. void * StructCopy(const void * struc, UInt32 size)
  502. {
  503.     if (struc == NULL)
  504.         return NULL;
  505.  
  506.     void * newStruct = XP_ALLOC(size);
  507.     if (newStruct == NULL)
  508.         return NULL;
  509.     ::BlockMoveData(struc, newStruct, size);
  510.     return newStruct;
  511. }
  512.  
  513.  
  514. void SetMenuSize( LStdPopupMenu* popup, short shouldBe )
  515. {
  516.     MenuHandle        menu;
  517.     short            count;
  518.     
  519.     menu = popup->GetMacMenuH();
  520.     count = ::CountMItems( menu );
  521.     
  522.     while ( shouldBe > count )
  523.     {    
  524.         InsertMenuItem( menu, "\p ", count );
  525.         count++;
  526.     }
  527.     
  528.     while ( shouldBe < count )
  529.     {
  530.         DeleteMenuItem( menu, count );
  531.         count--;
  532.     }
  533.     
  534.     popup->SetMinValue( 1 );
  535.     popup->SetMaxValue( shouldBe );
  536. }
  537.  
  538. void SetMenuSizeForLGAPopup( LGAPopup* popup, short shouldBe )
  539. {
  540.     MenuHandle        menu;
  541.     short            count;
  542.     
  543.     menu = popup->GetMacMenuH();
  544.     count = ::CountMItems( menu );
  545.     
  546.     while ( shouldBe > count )
  547.     {    
  548.         InsertMenuItem( menu, "\p ", count );
  549.         count++;
  550.     }
  551.     
  552.     while ( shouldBe < count )
  553.     {
  554.         DeleteMenuItem( menu, count );
  555.         count--;
  556.     }
  557.     
  558.     popup->SetMinValue( 1 );
  559.     popup->SetMaxValue( shouldBe );
  560. }
  561.  
  562. void SetMenuItem( CommandT whichItem, Boolean toState )
  563. {
  564.     ResIDT        menuID;
  565.     MenuHandle    menu = NULL;
  566.     Int16        item;
  567.     LMenuBar*    currentMenuBar;
  568.  
  569.     currentMenuBar = LMenuBar::GetCurrentMenuBar();
  570.  
  571.     if (currentMenuBar)
  572.         currentMenuBar->FindMenuItem( whichItem, menuID, menu, item );
  573.      if (menu)
  574.      {
  575.          if ( toState )
  576.              SetItemMark( menu, item, checkMark );
  577.          else
  578.              SetItemMark( menu, item, noMark );
  579.      }
  580. }
  581.  
  582. // ---------------------------------------------------------------------------
  583. //        Ñ myStringToNum [static]
  584. // ---------------------------------------------------------------------------
  585. //    Utility used the USizeMenu routines to convert strings to numbers that
  586. //    ignores anything that's not a number
  587.  
  588. #define    IsNumber_( x )    (( x ) >= '0' && ( x ) <= '9')
  589.  
  590. void myStringToNum( const CStr255& inString, Int32* outNum )
  591. {
  592.     CStr255        temp;
  593.     short        j = 1;
  594.     
  595.     for ( short i = 1; i <= inString[ 0 ]; i++ )
  596.     {
  597.         if ( IsNumber_( inString[ i ] ) )
  598.             temp[ j++ ] = inString[ i ];
  599.     }
  600.     
  601.     temp[0] = j - 1;
  602.     if (temp.Length() > 0)
  603.         StringToNum( temp, outNum );
  604. }
  605.  
  606. short PointsToPixels( short inPoints, short iRes )
  607. {
  608.     return ( (float)inPoints / 120.0 ) * iRes;
  609. }
  610.  
  611. void SetCaptionDescriptor( LCaption* captionToSet, const CStr255& newText,
  612.     const TruncCode trunc )
  613. {
  614.     XP_ASSERT( captionToSet );
  615.     
  616.     CStr255            tempText( newText );
  617.     SDimension16    captionSize;
  618.     
  619.     captionToSet->GetFrameSize( captionSize );
  620.     
  621.     // DANGER! There is a hideous crashing bug in Apple's ::TruncString
  622.     // (and ::TruncText) when called with TruncMiddle
  623.     if (trunc == truncMiddle)
  624.         MiddleTruncationThatWorks(tempText, captionSize.width - 4);
  625.     else
  626.         TruncString( captionSize.width - 4, tempText, trunc );
  627.     captionToSet->SetDescriptor( tempText );
  628.     captionToSet->Refresh();
  629. }
  630.  
  631. void GetDateTimeString( CStr255& dateTime )
  632. {
  633.     unsigned long        dt;
  634.     
  635.     ::GetDateTime( &dt );
  636.     ::DateString( dt, longDate, dateTime, NULL );
  637. }
  638.  
  639. unsigned short GetTextLengthInPixels( LTextEdit* textEdit );
  640. unsigned short GetTextLengthInPixels( LTextEdit* textEdit )
  641. {
  642.     XP_ASSERT( textEdit );
  643.     
  644.     unsigned short        width = 0;
  645.     TEHandle            macTEH = NULL;
  646.     Handle                text = NULL;
  647.     short                length = 0;
  648.     
  649.     // Ñ this sets up the current port with the right text traits
  650.     if ( textEdit->FocusDraw() )
  651.     {
  652.         macTEH = textEdit->GetMacTEH();
  653.         XP_ASSERT( macTEH );
  654.  
  655.         text = (*macTEH)->hText;        
  656.         if ( text )
  657.         {
  658.             length = (*macTEH)->teLength;
  659.             HLock( text );
  660.             width = TextWidth( *text, 0, length );
  661.             HUnlock( text );
  662.         }
  663.     }
  664.     return width;
  665. }
  666.  
  667. // Could be optimized
  668. char * GetPaneDescriptor(LPane * pane)
  669. {
  670.     char * ret = nil;
  671.     CStr255 ptempStr;
  672.     pane->GetDescriptor(ptempStr);    
  673.     cstring ctempStr((unsigned char*)ptempStr);
  674.     if (ctempStr.length() > 0)
  675.         StrAllocCopy(ret, ctempStr);
  676.     return ret;
  677. }
  678.  
  679. void TurnOn( LControl* control )
  680. {
  681.     control->SetValue( TRUE );
  682.     control->BroadcastMessage( msg_ControlClicked, (void*)control );
  683. }
  684.  
  685. Boolean SetPopupToNamedItem( LStdPopupMenu* whichMenu, const CStr255& itemText )
  686. {
  687.     MenuHandle        menuH;
  688.     short            menuSize;
  689.     Str255            fontName;
  690.     
  691.     menuH = whichMenu->GetMacMenuH();
  692.     menuSize = CountMItems( menuH );
  693.     
  694.     for ( short i = 1; i <= menuSize; i++ )
  695.     {
  696.         ::GetMenuItemText( menuH, i, fontName );
  697.         if ( itemText == (CStr255)fontName )
  698.         {
  699.             whichMenu->SetValue( i );
  700.             return TRUE;
  701.         }
  702.     }
  703.     return FALSE;
  704. }
  705.  
  706. Boolean SetLGAPopupToNamedItem( LGAPopup* whichMenu, const CStr255& itemText )
  707. {
  708.     MenuHandle        menuH;
  709.     short            menuSize;
  710.     Str255            fontName;
  711.     
  712.     menuH = whichMenu->GetMacMenuH();
  713.     menuSize = CountMItems( menuH );
  714.     
  715.     for ( short i = 1; i <= menuSize; i++ )
  716.     {
  717.         ::GetMenuItemText( menuH, i, fontName );
  718.         if ( itemText == (CStr255)fontName )
  719.         {
  720.             whichMenu->SetValue( i );
  721.             return TRUE;
  722.         }
  723.     }
  724.     return FALSE;
  725. }
  726.  
  727. unsigned long GetFreeSpaceInBytes( short vRefNum )
  728. {
  729.     HVolumeParam    pb;
  730.     OSErr            err;
  731.     unsigned long    result;
  732.     
  733.     pb.ioCompletion = NULL;
  734.     pb.ioVolIndex = 0;
  735.     pb.ioNamePtr = NULL;
  736.     pb.ioVRefNum = vRefNum;
  737.     
  738.     err = PBHGetVInfoSync( (HParmBlkPtr)&pb );
  739.     
  740.     if ( err == noErr )
  741.         result = pb.ioVFrBlk * pb.ioVAlBlkSiz;
  742.     else
  743.         result = 0;
  744.     
  745.     return result;
  746. }
  747.  
  748. // Ñ force a window to appear on the desktop
  749. void ForceWindowOnScreen( LWindow* window )
  750. {
  751.     // Ñ╩get the desktop region
  752.     StRegion        desktopRgn( LMGetGrayRgn() );
  753.     
  754.     Rect            windowFrame;
  755.     window->CalcPortFrameRect( windowFrame );
  756.     windowFrame = PortToGlobalRect( window, windowFrame );
  757.     
  758.     StRegion        windowRgn( windowFrame );
  759.  
  760.     StRegion        destRgn;
  761.     Rect            newRect;
  762.     
  763.     ::SectRgn( windowRgn, desktopRgn, destRgn );
  764.     
  765.     if ( ::EmptyRgn( destRgn ) ||
  766.         !::EqualRgn( destRgn, windowRgn ) )
  767.     {
  768.         newRect = (**(static_cast<RgnHandle>(destRgn))).rgnBBox;
  769.         
  770.         // Ñ add 20 for title, 20 for menu bar
  771.         newRect.top = 40 + 2;
  772.         newRect.bottom = newRect.top + ( windowFrame.bottom - windowFrame.top );
  773.         newRect.left = 2;
  774.         newRect.right = newRect.left + ( windowFrame.right - windowFrame.left );
  775.  
  776.         window->DoSetBounds( newRect );
  777.     }
  778.  
  779. }
  780.  
  781. void GrowWindowToScreenHeight( LWindow* win )
  782. {
  783.     GDHandle        device;
  784.     Rect            windowFrame;
  785.     
  786.     win->CalcPortFrameRect( windowFrame );
  787.     windowFrame = PortToGlobalRect( win, windowFrame );
  788.  
  789.     device = WindowOnSingleDevice( win );
  790.     if ( device )
  791.     {
  792.         windowFrame.bottom = (**device).gdRect.bottom - 5;
  793.         win->DoSetBounds( windowFrame );
  794.     }
  795. }
  796.     
  797. static
  798. Boolean WillBeVisible( Rect& windowRect )
  799. {
  800.     Rect            newRect;
  801.     Boolean            result = FALSE;
  802.     
  803.     StRegion        desktopRgn( LMGetGrayRgn() );
  804.     StRegion        windowRgn( windowRect );
  805.     StRegion        destRgn;
  806.  
  807.     ::SectRgn( windowRgn, desktopRgn, destRgn );
  808.  
  809.     newRect = (**static_cast<RgnHandle>(destRgn)).rgnBBox;
  810.     
  811.     if ( EmptyRgn( destRgn ) )
  812.         result = FALSE;
  813.     else if ( !EqualRect( &newRect, &windowRect ) )
  814.         result = FALSE;
  815.     else
  816.         result = TRUE;
  817.     
  818.     return result;
  819. }
  820.  
  821. void StaggerWindow( LWindow* win )
  822. {
  823.     WindowPtr        nextWindow;
  824.     LWindow*        similarWindow;
  825.     Rect            similarBounds;
  826.     Rect            bounds;
  827.     Boolean            changed = FALSE;
  828.         
  829.     win->CalcPortFrameRect( bounds );
  830.     bounds = PortToGlobalRect( win, bounds );        
  831.     // Ñ╩find the window with the same ID
  832.     //        if it has the same top left corner, offset our rect by 20, 5
  833.     nextWindow = ::FrontWindow();
  834.     while ( nextWindow )
  835.     {
  836.         similarWindow = LWindow::FetchWindowObject( nextWindow );
  837.         nextWindow = (WindowPtr)( (WindowPeek)nextWindow )->nextWindow;
  838.         if (    similarWindow &&
  839.                 similarWindow->GetPaneID() == win->GetPaneID() )
  840.         {
  841.             similarWindow->CalcPortFrameRect( similarBounds );
  842.             similarBounds = PortToGlobalRect( similarWindow, similarBounds );
  843.             
  844.             if ( ( similarBounds.top == bounds.top )  &&
  845.                  ( similarBounds.left == bounds.left ) )
  846.             {
  847.                 ::OffsetRect( &bounds, 5, 20) ;
  848.                 changed = TRUE;
  849.                 // Ñ loop again,  because we might run into another window
  850.                 nextWindow = ::FrontWindow();
  851.             }
  852.         }
  853.     }
  854.     if ( changed )
  855.         win->DoSetBounds( bounds );
  856. }
  857.  
  858. GDHandle WindowOnSingleDevice( LWindow* win )
  859. {
  860.     // Ñ loop thru all GDevices
  861.     Rect        windowFrame;
  862.     GDHandle    device;
  863.     
  864.     win->CalcPortFrameRect( windowFrame );
  865.     windowFrame = PortToGlobalRect( win, windowFrame );
  866.  
  867.     device = GetDeviceList();
  868.     
  869.     while ( device )
  870.     {
  871.         if ( UDrawingUtils::IsActiveScreenDevice( device ) )
  872.         {
  873.             Rect    intersection;
  874.             // Ñ find intersection of Window with this active screen Device
  875.             if ( ::SectRect( &windowFrame, &(**device).gdRect, &intersection ) )
  876.             {
  877.                 // Ñ window intersects this Device
  878.                 if ( ::EqualRect( &windowFrame, &intersection ) )
  879.                     return device;
  880.             }
  881.                 
  882.         }
  883.         device = GetNextDevice( device );
  884.     }
  885.     return NULL;
  886. }
  887.  
  888. #define SAVE_VERSION 23
  889.  
  890. // Ñ saving/restoring of the window's default state
  891. Boolean RestoreDefaultWindowState(LWindow* inWindow)
  892. {
  893.     if (inWindow == NULL)
  894.         return false;
  895.             
  896.     // We are responsible for disposing of the window data
  897.     Handle theWindowData = CPrefs::ReadWindowData(inWindow->GetPaneID());
  898.     if (theWindowData == NULL)
  899.         return false;
  900.     
  901.     // The destructor of the stream will kill the window data
  902.     LHandleStream stream(theWindowData);
  903.  
  904.     Int32 version;
  905.     stream.ReadData(&version, sizeof( version ) );
  906.     if ( version != SAVE_VERSION )
  907.         return false;
  908.         
  909.     Rect theWindowBounds;
  910.     stream.ReadData(&theWindowBounds, sizeof(theWindowBounds));
  911.  
  912.     if (theWindowBounds.right > theWindowBounds.left &&
  913.         theWindowBounds.bottom > theWindowBounds.top &&
  914.         WillBeVisible(theWindowBounds) )
  915.         inWindow->DoSetBounds(theWindowBounds);
  916.  
  917.     inWindow->RestorePlace(&stream);
  918.     ForceWindowOnScreen(inWindow);
  919.  
  920.     return true;
  921. }
  922.  
  923. void StoreDefaultWindowState( LWindow* win )
  924. {
  925.     if ( !win )
  926.         return;
  927.         
  928.     LHandleStream        stream;
  929.     Rect                windowBounds;
  930.     Int32                version = SAVE_VERSION;
  931.         
  932.     stream.WriteData( &version, sizeof( version ) );
  933.  
  934.     win->EstablishPort();
  935.     win->CalcPortFrameRect( windowBounds );
  936.     windowBounds = PortToGlobalRect( win, windowBounds );
  937.     stream.WriteData( &windowBounds, sizeof( windowBounds ) );
  938.  
  939.     win->SavePlace( &stream );
  940.  
  941.     CPrefs::WriteWindowData( stream.GetDataHandle(), win->GetPaneID() );
  942. }
  943.  
  944. // Is front window modal? Used for command enabling
  945. Boolean IsFrontWindowModal()
  946. {
  947.     return UDesktop::FrontWindowIsModal();
  948. }
  949.  
  950. // Ñ╩Fetch a window title resource and fill in the current profile name
  951. void GetUserWindowTitle(short id, CStr255& title)
  952. {
  953.     char profileName[32];
  954.     int len = 32;
  955.     PREF_GetCharPref("profile.name", profileName, &len);
  956.  
  957.     ::GetIndString( title, WINDOW_TITLES_RESID, id );
  958.     
  959.     StringParamText(title, profileName);
  960. }
  961.  
  962.         
  963. // Returns true if we are the front application
  964. Boolean IsFrontApplication()
  965. {
  966.     ProcessSerialNumber     netscapeProcess;
  967.     ProcessSerialNumber        frontProcess;
  968.     Boolean                    inFront;
  969.  
  970.     OSErr err = ::GetCurrentProcess( &netscapeProcess );
  971.     if ( err != noErr )
  972.         return FALSE;
  973.     err = ::GetFrontProcess( &frontProcess );
  974.     if ( err != noErr )
  975.         return FALSE;
  976.     err = ::SameProcess( &frontProcess, &netscapeProcess, &inFront );
  977.     if ( err != noErr )
  978.         return FALSE;
  979.     return inFront;
  980. }
  981.  
  982. void MakeFrontApplication()
  983. {
  984.     ProcessSerialNumber     netscapeProcess;
  985.     OSErr err = ::GetCurrentProcess( &netscapeProcess );
  986.     if (err == noErr)
  987.         SetFrontProcess(&netscapeProcess);
  988. }
  989.  
  990. void FrameSubpaneSubtle( LView* view, LPane* pane )
  991. {
  992.     Rect    subFrame;
  993.     
  994.     GetSubpaneRect( view, pane, subFrame );
  995.     ::InsetRect( &subFrame, -1, -1 );
  996.     UGraphics::FrameRectSubtle( subFrame, true );
  997. }
  998.  
  999. void GetSubpaneRgn( LView* view, LPane* pane, RgnHandle rgn )
  1000. {
  1001.     Rect    frame;
  1002.     GetSubpaneRect( view, pane, frame );
  1003.     ::RectRgn( rgn, &frame );
  1004. }
  1005.  
  1006. void GetSubpaneRect( LView* view, LPane* pane, Rect& frame )
  1007. {
  1008.     XP_ASSERT( view );
  1009.     XP_ASSERT( pane );
  1010.     pane->CalcPortFrameRect( frame );
  1011.     view->PortToLocalPoint( *(Point*)&( frame.top ) );
  1012.     view->PortToLocalPoint( *(Point*)&( frame.bottom) );
  1013. }
  1014.  
  1015. void WriteVersionTag( LStream* stream, Int32 version )
  1016. {
  1017.     stream->WriteData( &version, sizeof( version ) );
  1018. }
  1019.  
  1020. Boolean ReadVersionTag( LStream* stream, Int32 version )
  1021. {
  1022.     Int32        versionTag;
  1023.     stream->ReadData( &versionTag, sizeof( versionTag ) );
  1024.     return ( versionTag == version );
  1025. }
  1026.  
  1027. void TrySetCursor( int whichCursor )
  1028. {
  1029.     Cursor** c = GetCursor( whichCursor );
  1030.     if ( c )
  1031.         SetCursor( *c );
  1032. #ifdef DEBUG
  1033.     else
  1034.         SysBeep( 1 );
  1035. #endif
  1036. }
  1037.  
  1038. void StripNewline( CStr255& msg )
  1039. {
  1040.     if ( msg[ msg.Length() ] == '\n' )
  1041.         msg[ msg.Length() ] = 0;
  1042. }
  1043.  
  1044. void StripDoubleCRs( CStr255& msg )
  1045. {
  1046.     Boolean lastCR = FALSE;
  1047.     for ( UInt32 i = 1; i < msg.Length(); i++ )
  1048.     {
  1049.         if ( msg[ i ] == CR)
  1050.         {
  1051.             if ( lastCR )
  1052.             {
  1053.                 msg[ i - 1 ] = ' ';
  1054.                 lastCR = FALSE;
  1055.             }
  1056.             else
  1057.                 lastCR = TRUE;
  1058.         }
  1059.         else
  1060.             lastCR = FALSE;
  1061.     }
  1062. }
  1063.  
  1064. int ConvertCRtoLF(CStr255 & msg)
  1065. {
  1066.     int ret = 0;
  1067.     for ( long i = 1; i <= msg[0]; i++ )
  1068.         if ( msg[ i ] == LF )
  1069.         {
  1070.             msg[ i ] = CR;
  1071.             ret++;
  1072.         }
  1073.     return ret;
  1074. }
  1075.  
  1076. Rect RectFromTwoPoints( Point p1, Point p2 )
  1077. {
  1078.     Rect r;
  1079.     r.top = MIN( p1.v, p2.v );
  1080.     r.bottom = MAX( p1.v, p2.v );
  1081.     r.left = MIN( p1.h, p2.h );
  1082.     r.right = MAX( p1.h, p2.h );
  1083.  
  1084.     return r;
  1085. }
  1086.  
  1087. // Return true if inEnclosingRect encloses any portion of inCheckRect
  1088. Boolean RectInRect(const Rect *inCheckRect, const Rect *inEnclosingRect) {
  1089.  
  1090.     return (!::EmptyRect(inEnclosingRect) &&
  1091.                 !((inCheckRect->right <= inEnclosingRect->left) || 
  1092.                    (inCheckRect->bottom <= inEnclosingRect->top) ||
  1093.                      (inCheckRect->left >= inEnclosingRect->right) || 
  1094.                      (inCheckRect->top >= inEnclosingRect->bottom)));
  1095. }
  1096.  
  1097. const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
  1098. const RGBColor rgbWhite = { 0xFFFF, 0xFFFF, 0xFFFF };
  1099.  
  1100.  
  1101. void DrawAntsRect( Rect&r, short mode )
  1102. {
  1103.     ::PenPat( &(UQDGlobals::GetQDGlobals()->gray) );
  1104.     ::PenMode( mode );
  1105.     ::RGBForeColor( &rgbBlack );
  1106.     ::RGBBackColor( &rgbWhite );
  1107.     ::FrameRect( &r );
  1108. }
  1109.  
  1110. FontInfo SafeGetFontInfo(ResIDT textTraits)
  1111. {
  1112.     StTextState textState;
  1113.     UTextTraits::SetPortTextTraits(textTraits);
  1114.     FontInfo fInfo;
  1115.     ::GetFontInfo(&fInfo);
  1116.     return fInfo;
  1117. }
  1118.  
  1119. void FrameButton( const Rect& box, Boolean pushed )
  1120. {
  1121.     UGraphics::FrameRectSubtle(box, pushed);
  1122. }
  1123.  
  1124. void HiliteRect( const Rect& r )
  1125. {
  1126.     LMSetHiliteMode( LMGetHiliteMode() & ! ( 1 << hiliteBit ) ) ;
  1127.     ::InvertRect( &r );
  1128. }
  1129.  
  1130. void HiliteRgn( const RgnHandle& r )
  1131. {
  1132.     LMSetHiliteMode( LMGetHiliteMode() & ! ( 1 << hiliteBit ) ) ;
  1133.     ::InvertRgn( r );
  1134. }
  1135.     
  1136. LPane* FindPaneHitBy( const Point& globalMouse )
  1137. {
  1138.     Int16        part;
  1139.     WindowPtr    macWindowP;
  1140.     LPane*        inPane = NULL;
  1141.  
  1142.     part = ::FindWindow( globalMouse, &macWindowP );
  1143.     if ( macWindowP && part == inContent )
  1144.     {
  1145.         LWindow*    whichWin;
  1146.         whichWin = LWindow::FetchWindowObject( macWindowP );
  1147.         if ( whichWin )
  1148.         {
  1149.             Point        localMouse;
  1150.             LPane*        nextPane;
  1151.                 
  1152.             localMouse = globalMouse;
  1153.             whichWin->GlobalToPortPoint( localMouse );
  1154.             inPane = whichWin->FindSubPaneHitBy( localMouse.h, localMouse.v );
  1155.             nextPane = inPane;
  1156.             while ( nextPane )
  1157.             {
  1158.                 inPane = nextPane;
  1159.                 nextPane = nextPane->FindSubPaneHitBy( localMouse.h, localMouse.v );
  1160.             }
  1161.         }
  1162.     }
  1163.     return inPane;
  1164. }
  1165.  
  1166. // ---------------------------------------------------------------
  1167. //        Good 'ol Mac File Utilities
  1168. // ---------------------------------------------------------------
  1169.  
  1170.  
  1171. /*----------------------------------------------------------------------
  1172.         Get a full pathname given a sig and type
  1173.         In: sig of process to look for  ('MOSS' for nav but should use emSignature instead)
  1174.                 type of process to look for  (typically APPL)
  1175.         Out:Returns the file path as a nul-terminated allocated block
  1176.                 that must be freed by the caller using XP_FREE.
  1177.             Returns NULL on error;
  1178.             
  1179.         Q: Should the path contain / for the root? i.e. should it be
  1180.             file:///MacHD/...
  1181.         or    file://MacHD/..        ** this form used now.
  1182. ------------------------------------------------------------------------*/
  1183. char *PathURLFromProcessSignature (OSType sig, OSType type)
  1184. {
  1185.     ProcessSerialNumber    targetPSN;            // return process number
  1186.     FSSpec                 targetFileSpec;        // return file spec
  1187.     char                *appPath = NULL;
  1188.     char                *urlPath = NULL;
  1189.     char                prefix[] = "file:/";
  1190.     OSErr                 err;
  1191.     
  1192.     // Get the file spec of our app
  1193.     err = FindProcessBySignature(sig, type, targetPSN, &targetFileSpec);
  1194.     if (err != noErr) return NULL;
  1195.     
  1196.     appPath = CFileMgr::EncodedPathNameFromFSSpec(targetFileSpec, true);
  1197.     if (appPath == NULL) return NULL;
  1198.     
  1199.     urlPath = (char *)XP_ALLOC(strlen(appPath) + strlen(prefix) + 1);
  1200.     if (urlPath == NULL) {
  1201.         XP_FREE(appPath);
  1202.         return NULL;
  1203.     }
  1204.     
  1205.     XP_STRCPY(urlPath, prefix);
  1206.     XP_STRCPY(urlPath + strlen(prefix), appPath), 
  1207.     
  1208.     XP_FREE(appPath);
  1209.     
  1210.     return urlPath;
  1211. }
  1212.  
  1213. // Given a process signature, gets its serial number
  1214. ProcessSerialNumber GetPSNBySig( OSType sig )
  1215. {
  1216.     OSErr                    err;
  1217.     FSSpec                    fileSpec;
  1218.     ProcessInfoRec            info;
  1219.     ProcessSerialNumber        psn;
  1220.  
  1221.     info.processAppSpec = &fileSpec;
  1222.     psn.highLongOfPSN = 0;
  1223.     psn.lowLongOfPSN  = kNoProcess;
  1224.     while ( GetNextProcess( &psn ) == noErr)
  1225.     {
  1226.         info.processInfoLength = sizeof( ProcessInfoRec );
  1227.         info.processName = NULL;
  1228.         err= GetProcessInformation( &psn, &info );
  1229.         if ( info.processSignature == sig )
  1230.             return psn;
  1231.     }
  1232.     Throw_( paramErr );
  1233.     return psn;
  1234. }
  1235.  
  1236. #define NO_PROCESS -1        // Constant used to indicate that there is no process in the PSN
  1237. // Creates an NoProcess serial number
  1238. ProcessSerialNumber MakeNoProcessPSN()
  1239. {
  1240.     ProcessSerialNumber psn;
  1241.     psn.highLongOfPSN = NO_PROCESS;
  1242.     psn.lowLongOfPSN = NO_PROCESS;
  1243.     return psn;
  1244. }
  1245.  
  1246. // Do we have a process
  1247. Boolean HasProcess( const ProcessSerialNumber& psn )
  1248. {
  1249.     return ( ( psn.highLongOfPSN != NO_PROCESS ) || 
  1250.             ( psn.lowLongOfPSN!=NO_PROCESS ) );
  1251. }
  1252.  
  1253. // Given an application signature, finds the process
  1254. OSErr FindProcessBySignature(OSType sig,
  1255.                             OSType processType,
  1256.                             ProcessSerialNumber& psn,
  1257.                             FSSpec* fileSpec)
  1258. {
  1259.     OSErr err;
  1260.     
  1261.     ProcessInfoRec info;
  1262.  
  1263.     psn.highLongOfPSN = 0;
  1264.     psn.lowLongOfPSN  = kNoProcess;
  1265.     do
  1266.     {
  1267.         err= GetNextProcess(&psn);
  1268.         if( err == noErr )
  1269.         {
  1270.  
  1271.             info.processInfoLength = sizeof(ProcessInfoRec);
  1272.             info.processName = NULL;
  1273.             info.processAppSpec = fileSpec;
  1274.  
  1275.             err= GetProcessInformation(&psn, &info);
  1276.         }
  1277.     } while( (err == noErr) && 
  1278.             ((info.processSignature != sig) || 
  1279.             (info.processType != processType)));
  1280.  
  1281.     if( err == noErr )
  1282.         psn = info.processNumber;
  1283.  
  1284.     return err;
  1285. } // FindProcessBySignature 
  1286.  
  1287.  
  1288. extern Boolean HasAppleEventObjects();
  1289.  
  1290. // On the 68K, the OSL glue checks to see whether it is 
  1291. // installed. If it's not, the functions do nothing. On the PPC,
  1292. // if the Code Fragment Manager is unable to resolve an OSL
  1293. // stub, it performs an ExitToShell. Therefore we must
  1294. // insure that the OSL is available before calling any of
  1295. // its functions. These are called throughout PowerPlant's
  1296. // LModel* classes.
  1297.  
  1298. // gestaltObjectSupportLibraryInSystem = 1,
  1299. // gestaltObjectSupportLibraryPowerPCSupport = 2
  1300. // gestaltAppleEventsPresent
  1301. // gestaltScriptingSupport
  1302. // gestaltOSLInSystem ├├├ not gestaltObjectSupportLibraryPowerPCSupport
  1303. Boolean HasAppleEventObjects()
  1304. {
  1305.     static Boolean isKnown = false, isInstalled = false;
  1306.     
  1307.     
  1308.     if (!isKnown) 
  1309.     {
  1310.         long attr = 0;
  1311.         Boolean ae = UEnvironment::HasGestaltAttribute(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
  1312.         Boolean ppc = UEnvironment::HasGestaltAttribute(gestaltAppleEventsAttr, gestaltOSLInSystem);
  1313. #ifdef powerc
  1314.         isInstalled = ae && ppc;
  1315. #else
  1316.         isInstalled = 1; // we're linked with glue which always works
  1317. #endif
  1318.         isKnown = true;
  1319.     }
  1320.     return isInstalled;
  1321. }
  1322.  
  1323. /*----------------------------------------------------------------------------
  1324.     GetDropLocationDirectory
  1325.     
  1326.     Given an 'alis' drop location AEDesc, return the volume reference
  1327.     number and directory ID of the directory.
  1328.     
  1329.     Entry:    dropLocation = pointer to 'alis' AEDesc record.
  1330.     
  1331.     Exit:    function result = error code.
  1332.             *volumeID = volume reference number.
  1333.             *directoryID = directory ID.
  1334.             
  1335.     From Apple "HFS Drag Sample" sample code.
  1336. ----------------------------------------------------------------------------*/
  1337. OSErr GetDropLocationDirectory (AEDesc *dropLocation, long *directoryID, short *volumeID)
  1338. {
  1339.     OSErr            result;
  1340.     AEDesc            targetDescriptor;    // 'fss ' descriptor for target directory
  1341.     FSSpec            targetLocation;        // FSSpec for target directory
  1342.     CInfoPBRec        getTargetInfo;        // paramBlock to get targetDirID
  1343.     
  1344.     // Coerce the 'alis' descriptor to a 'fss ' descriptor
  1345.     result = AECoerceDesc(dropLocation, typeFSS, &targetDescriptor);
  1346.     if (result != noErr)
  1347.         return (result); 
  1348.     
  1349.     // Extract the FSSpec from targetDescriptor
  1350.     BlockMoveData((Ptr)(*targetDescriptor.dataHandle), (Ptr)&targetLocation, sizeof(FSSpec));
  1351.     
  1352.     result = AEDisposeDesc(&targetDescriptor);
  1353.     if (result != noErr)
  1354.         return (result);
  1355.     
  1356.     // Use PBGetCatInfo to get the directoryID of the target directory from the FSSpec
  1357.     
  1358.     getTargetInfo.dirInfo.ioNamePtr = targetLocation.name;
  1359.     getTargetInfo.dirInfo.ioVRefNum = targetLocation.vRefNum;
  1360.     getTargetInfo.dirInfo.ioFDirIndex = 0;
  1361.     getTargetInfo.dirInfo.ioDrDirID = targetLocation.parID;
  1362.     
  1363.     result = PBGetCatInfoSync(&getTargetInfo);
  1364.     if (result != noErr)
  1365.         return (result);
  1366.     
  1367.     // return directory ID and volume reference number
  1368.     
  1369.     *directoryID = getTargetInfo.dirInfo.ioDrDirID;
  1370.     *volumeID = targetLocation.vRefNum;
  1371.     
  1372.     return result;
  1373. }
  1374.  
  1375. /*----------------------------------------------------------------------------
  1376.     DragTargetWasTrash
  1377.     
  1378.     Check to see if the target of a drag and drop was the Finder trashcan.
  1379.     
  1380.     Entry:    dragRef = drag reference.
  1381.     
  1382.     Exit:    function result = true if target was trash.
  1383. ----------------------------------------------------------------------------*/
  1384.  
  1385. Boolean DragTargetWasTrash (DragReference dragRef)
  1386. {
  1387.     AEDesc dropLocation;
  1388.     OSErr err = noErr;
  1389.     long dropDirID, trashDirID;
  1390.     short dropVRefNum, trashVRefNum;
  1391.     
  1392.     err = GetDropLocation(dragRef, &dropLocation);
  1393.     if (err != noErr) return false;
  1394.     
  1395.     if (dropLocation.descriptorType == typeNull) goto exit;
  1396.     
  1397.     err = GetDropLocationDirectory(&dropLocation, &dropDirID, &dropVRefNum);
  1398.     if (err != noErr) goto exit;
  1399.     
  1400.     err = FindFolder(dropVRefNum, kTrashFolderType, false, &trashVRefNum,
  1401.         &trashDirID);
  1402.     if (err != noErr) goto exit;
  1403.     
  1404.     if (dropVRefNum != trashVRefNum || dropDirID != trashDirID) goto exit;
  1405.  
  1406.     AEDisposeDesc(&dropLocation);
  1407.     return true;
  1408.  
  1409. exit:
  1410.  
  1411.     AEDisposeDesc(&dropLocation);
  1412.     return false;
  1413. }
  1414.  
  1415.  
  1416. long LArrowControl::fLastTicks = 0;
  1417. long LArrowControl::fDelay = 20;
  1418. long LArrowControl::fHits = 0;
  1419.  
  1420. LArrowControl::LArrowControl( const SPaneInfo& inPaneInfo, MessageT valueMessage ):
  1421.     LControl( inPaneInfo, valueMessage, 0, 0, 0 )
  1422. {
  1423.     mCurrPict = mArrowsPict;
  1424. }
  1425.  
  1426. void LArrowControl::HiliteControl( Int16 inHotSpot, Boolean inCurrInside )
  1427. {
  1428.     if ( inCurrInside )
  1429.     {
  1430.         if ( inHotSpot == mTopHalf )
  1431.             mCurrPict = mArrowsTopLit;
  1432.         else if ( inHotSpot == mBottomHalf )
  1433.             mCurrPict = mArrowsBotLit;
  1434.     }
  1435.     else
  1436.         mCurrPict = mArrowsPict;
  1437.         
  1438.     DrawSelf();
  1439. }
  1440.  
  1441. void LArrowControl::DrawSelf()
  1442. {
  1443.     PicHandle        macPictureH = GetPicture( mCurrPict );
  1444.     if ( macPictureH )
  1445.     {
  1446.         Rect            pictureBounds;
  1447.  
  1448.         CalcLocalFrameRect( pictureBounds );        
  1449.         ::DrawPicture( macPictureH, &pictureBounds );
  1450.         
  1451.     }
  1452. }
  1453.  
  1454. Boolean LArrowControl::PointInHotSpot( Point inPoint, Int16 inHotSpot )
  1455. {
  1456.     Rect        localFrame;
  1457.     Int16        midPoint;
  1458.     
  1459.     CalcLocalFrameRect( localFrame );
  1460.     midPoint = ( localFrame.bottom - localFrame.top ) / 2;
  1461.     
  1462.     if ( inHotSpot == mTopHalf )
  1463.         localFrame.bottom = midPoint;
  1464.     else
  1465.         localFrame.top = midPoint;
  1466.  
  1467.     return PtInRect( inPoint, &localFrame );    
  1468. }
  1469.  
  1470. Int16 LArrowControl::FindHotSpot( Point inPoint )
  1471. {
  1472.     Rect        localFrame;
  1473.     Int16        midPoint;
  1474.     
  1475.     CalcLocalFrameRect( localFrame );
  1476.     midPoint = ( localFrame.bottom - localFrame.top ) / 2;
  1477.     
  1478.     if ( inPoint.v < midPoint )
  1479.         return mTopHalf;
  1480.     else    
  1481.         return mBottomHalf;
  1482. }
  1483.  
  1484. void LArrowControl::HotSpotAction( Int16 inHotSpot, Boolean inCurrInside, Boolean inPrevInside )
  1485. {
  1486.     
  1487.     if ( inCurrInside != inPrevInside )
  1488.     {
  1489.         FocusDraw();
  1490.         HiliteControl( inHotSpot, inCurrInside );
  1491.     }
  1492.     
  1493.     if ( inCurrInside )
  1494.     {
  1495.         if ( ( ::TickCount() - fLastTicks ) < fDelay )
  1496.             return;
  1497.     
  1498.         if ( fDelay == 0 )
  1499.             fDelay = 20;
  1500.                 
  1501.         fHits++;
  1502.         if ( fHits > 6 )
  1503.             fDelay = 5;
  1504.         
  1505.         fLastTicks = TickCount();
  1506.         
  1507.         BroadcastMessage( mValueMessage, &inHotSpot );
  1508.     }
  1509.     else
  1510.     {
  1511.         fHits = 0;
  1512.         fDelay = 20;
  1513.     }
  1514. }
  1515.  
  1516. void LArrowControl::HotSpotResult( Int16 /*inHotSpot*/ )
  1517. {
  1518.     mCurrPict = mArrowsPict;
  1519.     
  1520.     DrawSelf();
  1521.     
  1522.     fHits = 0;
  1523.     fDelay = 0;
  1524. }
  1525.  
  1526. /*=============================================================================
  1527.     File & Stream Classes Utilities
  1528. =============================================================================*/
  1529.  
  1530. /*-----------------------------------------------------------------------------
  1531.     StOpenResFile opens the resource fork and closes it later
  1532. -----------------------------------------------------------------------------*/
  1533.  
  1534. StOpenResFile::StOpenResFile (LFile *file, short perms)
  1535. {
  1536.     fFile = file;
  1537.     file->OpenResourceFork (perms);
  1538. }
  1539.  
  1540. StOpenResFile::~StOpenResFile ()
  1541. {
  1542.     // LAM may not be required to UpdateResFile
  1543.     // CloseResFile is supposed to call UpdateResFile
  1544.     //::UpdateResFile (fFile->GetResourceForkRefNum());
  1545.     fFile->CloseResourceFork();
  1546. }
  1547.  
  1548. /*-----------------------------------------------------------------------------
  1549.     StUseResFile uses an open resource fork and stops using it later.
  1550. -----------------------------------------------------------------------------*/
  1551.  
  1552. StUseResFile::StUseResFile( short refnum )
  1553. {
  1554.     fPrevResFile = CurResFile();
  1555.     
  1556.     if (refnum != -1)
  1557.         UseResFile( refnum );
  1558. }
  1559.  
  1560. StUseResFile::~StUseResFile()
  1561. {
  1562.     UseResFile( fPrevResFile );
  1563. }
  1564.  
  1565. //========================================================================================
  1566. // CLASS CStringListRsrc
  1567. //========================================================================================
  1568.  
  1569. typedef short**    IntegerHandle;
  1570. //----------------------------------------------------------------------------------------
  1571. // CStringListRsrc::GetString: 
  1572. //----------------------------------------------------------------------------------------
  1573.  
  1574. void CStringListRsrc::GetString(short index, CStr255& theString) const
  1575. {
  1576.     if (fStrListID != 0)
  1577.         GetIndString(theString, fStrListID, index);
  1578. } // CStringListRsrc::GetString 
  1579.  
  1580. //----------------------------------------------------------------------------------------
  1581. // CStringListRsrc::FindString: 
  1582. //----------------------------------------------------------------------------------------
  1583.  
  1584. short CStringListRsrc::FindString(const CStr255& theString, Boolean addString)
  1585. {
  1586.     CStr255 testString;
  1587.     short numStrings = this->CountStrings();
  1588.  
  1589.     for (short i = 1; i <= numStrings; ++i)
  1590.     {
  1591.         this->GetString(i, testString);
  1592.  
  1593.         if (testString == theString)
  1594.             return i;                                // found it! return the index
  1595.     }
  1596.     
  1597.     // CString is not found, should we add it?
  1598.     if (addString == kAddString)
  1599.         return this->AppendString(theString);        // added it! return the index
  1600.  
  1601.     // CString not found...sigh!
  1602.     return 0;
  1603. } // CStringListRsrc::FindString 
  1604.  
  1605. //----------------------------------------------------------------------------------------
  1606. // CStringListRsrc::AppendString: 
  1607. //----------------------------------------------------------------------------------------
  1608.  
  1609. short CStringListRsrc::AppendString(const CStr255& theString)
  1610. {
  1611.     long result;
  1612.     short totalStringLength = theString.Length() + kLengthByte;
  1613.     Handle aHandle = Get1Resource('STR#', fStrListID);
  1614.     if (aHandle)
  1615.     {
  1616.         if (!*aHandle)
  1617.             ::LoadResource(aHandle);
  1618.         
  1619.         if (*aHandle)
  1620.         {
  1621.             SInt8 flags = ::HGetState(aHandle);
  1622.             ::HNoPurge(aHandle);
  1623.             Size itsSize = GetHandleSize(aHandle);
  1624.             if (itsSize > 0)
  1625.             {
  1626.                 short numStrings = this->CountStrings();
  1627.                 SetHandleSize(aHandle, itsSize + totalStringLength);
  1628.                 (**((IntegerHandle) aHandle)) = ++numStrings;                // increment the count of strings in the STR# resource
  1629.  
  1630.                 // needs a failure handler
  1631.                 result = Munger(aHandle, itsSize, NULL, totalStringLength, &theString, totalStringLength);
  1632.                 if (result > 0)
  1633.                 {
  1634.                     // mark it as changed
  1635.                     ChangedResource(aHandle);
  1636.                     ::HSetState(aHandle, flags);
  1637.  
  1638.                     return numStrings;
  1639.                 }
  1640.                 ::HSetState(aHandle, flags);
  1641.             }
  1642.         }
  1643.     }
  1644.     else
  1645.     {
  1646.         // must create the resource...
  1647.         aHandle = NewHandle(sizeof(short) + totalStringLength);
  1648.         (**((IntegerHandle) aHandle)) = 1;                // set the count of strings in the STR# resource
  1649.         result = Munger(aHandle, sizeof(short), NULL, totalStringLength, &theString, totalStringLength);
  1650.         if (result > 0)
  1651.         {
  1652.             AddResource(aHandle, 'STR#', fStrListID, fStrListRsrcName);
  1653.             ThrowIfResError_();    // if fails, it's most likely because the file is read-only
  1654.  
  1655.             SetResAttrs(aHandle, resPurgeable);
  1656.     
  1657.             // Need the following ChangedResource call because the SetResAttrs call on the previous
  1658.             // line cleared the "resChanged" attribute of the resource.
  1659.             ChangedResource(aHandle);
  1660.     
  1661.             return 1;
  1662.         }
  1663.     }
  1664.     return 0;    
  1665. } // CStringListRsrc::AppendString 
  1666.  
  1667. //----------------------------------------------------------------------------------------
  1668. // CStringListRsrc::ClearAll: 
  1669. //----------------------------------------------------------------------------------------
  1670.  
  1671. void CStringListRsrc::ClearAll()
  1672. {
  1673.     Handle aHandle = Get1Resource('STR#', fStrListID);
  1674.     if (aHandle)
  1675.     {
  1676.         if (!*aHandle)
  1677.             ::LoadResource(aHandle);
  1678.         
  1679.         if (*aHandle)
  1680.         {
  1681.             SInt8 flags = ::HGetState(aHandle);
  1682.             ::HNoPurge(aHandle);
  1683.             SetHandleSize(aHandle, sizeof(short));
  1684.             (**((IntegerHandle) aHandle)) = 0;                // set the count of strings in the STR# resource
  1685.  
  1686.             // mark it as changed
  1687.             ChangedResource(aHandle);
  1688.             ::HSetState(aHandle, flags);
  1689.         }
  1690.     }
  1691. } // CStringListRsrc::ClearAll 
  1692.  
  1693. //----------------------------------------------------------------------------------------
  1694. // CStringListRsrc::CountStrings: 
  1695. //----------------------------------------------------------------------------------------
  1696.  
  1697. short CStringListRsrc::CountStrings() const
  1698. {
  1699.     // return the leading integer in the STR# resource:
  1700.     //
  1701.     // type 'STR#' {
  1702.     //      integer = $$Countof(StringArray);
  1703.     //      array StringArray {
  1704.     //              pstring;
  1705.     //      };
  1706.     // };
  1707.  
  1708.     Handle aHandle = Get1Resource('STR#', fStrListID);
  1709.     if (aHandle)
  1710.     {
  1711.         if (!*aHandle)
  1712.             ::LoadResource(aHandle);
  1713.         
  1714.         if (*aHandle)
  1715.             return **((IntegerHandle) aHandle);
  1716.     }
  1717.     return 0;
  1718. } // CStringListRsrc::CountStrings 
  1719.  
  1720. //----------------------------------------------------------------------------------------
  1721. // CStringListRsrc::GetListName: 
  1722. //----------------------------------------------------------------------------------------
  1723.  
  1724. void CStringListRsrc::GetListName(CStr255& theString)
  1725. {
  1726.     // Do we have the name in our field?
  1727.     if ( fStrListRsrcName.Length () > 0 )
  1728.         theString = fStrListRsrcName;
  1729.     else            //    We don't have the name so try and get it from the resource
  1730.     {
  1731.         short    itsRsrcID;
  1732.         CStr255    itsName;
  1733.         ResType    itsType;
  1734.  
  1735.         // Get the resource's handle
  1736.         Handle aHandle = Get1Resource('STR#', fStrListID);
  1737.         if (aHandle)
  1738.         {
  1739.             // Extract the resource info from the handle
  1740.             GetResInfo ( aHandle, &itsRsrcID, &itsType, itsName );
  1741.             if ( itsName.Length () > 0 )
  1742.             {
  1743.                 theString = itsName;
  1744.                 
  1745.                 // Store the name in our field
  1746.                 fStrListRsrcName = theString;
  1747.             }
  1748.             
  1749.             ReleaseResource ( aHandle );
  1750.         }
  1751.         else        // Sorry we don't have anything so return an empty CString
  1752.             theString = CStr255::sEmptyString;
  1753.     
  1754.     }
  1755. } // CStringListRsrc::GetListName 
  1756.  
  1757. //----------------------------------------------------------------------------------------
  1758. // CStringListRsrc::RemoveAt: 
  1759. //----------------------------------------------------------------------------------------
  1760.  
  1761. void CStringListRsrc::RemoveAt(short index)
  1762. {
  1763.     if ((index > 0) && (index <= this->CountStrings()))
  1764.     {
  1765.         Handle aHandle = Get1Resource('STR#', fStrListID);
  1766.         if (aHandle)
  1767.         {
  1768.             if (!*aHandle)
  1769.                 ::LoadResource(aHandle);
  1770.             
  1771.             if (*aHandle)
  1772.             {
  1773.                 SInt8 flags = ::HGetState(aHandle);
  1774.                 ::HNoPurge(aHandle);
  1775.                 
  1776.                 Size originalSize = GetHandleSize(aHandle);
  1777.  
  1778.                 // determine the accumulated size
  1779.                 Size accumulatedSize = sizeof(short);    // the accumulated size is the size of the count
  1780.                 for (short i = 1; i < index; ++i)
  1781.                     accumulatedSize += (*((CStringPtr) (*aHandle + accumulatedSize))).Length() + kLengthByte;
  1782.                 
  1783.                 // determine the actual CString size
  1784.                 Size stringSize = (*((CStringPtr) (*aHandle + accumulatedSize))).Length() + kLengthByte;
  1785.  
  1786.                 // move the the data in the handle
  1787.                 BlockMoveData(*aHandle + accumulatedSize + stringSize, *aHandle + accumulatedSize,
  1788.                                 originalSize - accumulatedSize - stringSize);
  1789.  
  1790.                 // trim the handle down to its new size
  1791.                 SetHandleSize(aHandle, originalSize - stringSize);
  1792.  
  1793.                 // decrement count of strings in STR# resource
  1794.                 --(**((IntegerHandle) aHandle));
  1795.  
  1796.                 // mark it as changed
  1797.                 ChangedResource(aHandle);
  1798.                 
  1799.                 ::HSetState(aHandle, flags);
  1800.             }
  1801. #if qDebugMsg
  1802.             else
  1803.                 fprintf(stderr, "CStringListRsrc::RemoveAt can't load STR# = %d.\n", fStrListID);
  1804. #endif
  1805.         }
  1806. #if qDebugMsg
  1807.         else
  1808.             fprintf(stderr, "CStringListRsrc::RemoveAt can't find STR# = %d.\n", fStrListID);
  1809. #endif
  1810.     }
  1811. #if qDebugMsg
  1812.     else
  1813.         fprintf(stderr, "CStringListRsrc::RemoveAt there's no CString at %d to remove!\n", index);
  1814. #endif
  1815. } // CStringListRsrc::RemoveAt 
  1816.  
  1817. //----------------------------------------------------------------------------------------
  1818. // CStringListRsrc::ReplaceAt: 
  1819. //----------------------------------------------------------------------------------------
  1820.  
  1821. void CStringListRsrc::ReplaceAt(const CStr255& theString, short index)
  1822. {
  1823.     if ((index > 0) && (index <= this->CountStrings()))
  1824.     {
  1825.         Handle aHandle = Get1Resource('STR#', fStrListID);
  1826.         if (aHandle)
  1827.         {
  1828.             if (!*aHandle)
  1829.                 ::LoadResource(aHandle);
  1830.             
  1831.             if (*aHandle)
  1832.             {
  1833.                 SInt8 flags = ::HGetState(aHandle);
  1834.                 ::HNoPurge(aHandle);
  1835.                 
  1836.                 Size newStringSize = theString.Length() + kLengthByte;    // the actual CString size
  1837.                 Size originalSize = GetHandleSize(aHandle);
  1838.  
  1839.                 // determine the accumulated size of the valid portion of the resource
  1840.                 Size accumulatedSize = sizeof(short);    // the accumulated size is the size of the count
  1841.                 for (short i = 1; i < index; ++i)
  1842.                     accumulatedSize += (*((CStringPtr) (*aHandle + accumulatedSize))).Length() + kLengthByte;
  1843.                 
  1844.                 // determine the actual CString size
  1845.                 Size oldStringSize = (*((CStringPtr) (*aHandle + accumulatedSize))).Length() + kLengthByte;
  1846.                 
  1847.                 // determine the new handle size
  1848.                 Size newHandleSize = originalSize + (newStringSize - oldStringSize);
  1849.  
  1850.                 // determine whether to grow or shrink the handle?
  1851.                 if (newStringSize > oldStringSize)
  1852.                 {
  1853.                     // grow the handle
  1854.                     SetHandleSize(aHandle, newHandleSize);
  1855.  
  1856.                     // move the bytes
  1857.                     BlockMoveData(*aHandle + accumulatedSize + oldStringSize, *aHandle + accumulatedSize + newStringSize,
  1858.                                     originalSize - accumulatedSize - oldStringSize);
  1859.                 }
  1860.                 else if (oldStringSize > newStringSize)
  1861.                 {
  1862.                     // move the bytes
  1863.                     BlockMoveData(*aHandle + accumulatedSize + oldStringSize, *aHandle + accumulatedSize + newStringSize,
  1864.                                     originalSize - accumulatedSize - oldStringSize);
  1865.  
  1866.                     // shrink the handle
  1867.                     SetHandleSize(aHandle, newHandleSize);
  1868.                 }
  1869.  
  1870.                 // assign the CString
  1871.                 *((CStr255*) (*aHandle + accumulatedSize)) = theString;
  1872.                 
  1873.                 // mark it as changed
  1874.                 ChangedResource(aHandle);
  1875.                 
  1876.                 ::HSetState(aHandle, flags);
  1877.             }
  1878. #if qDebugMsg
  1879.             else
  1880.                 fprintf(stderr, "CStringListRsrc::ReplaceAt can't load STR# = %d.\n", fStrListID);
  1881. #endif
  1882.         }
  1883. #if qDebugMsg
  1884.         else
  1885.             fprintf(stderr, "CStringListRsrc::ReplaceAt can't find STR# = %d.\n", fStrListID);
  1886. #endif
  1887.     }
  1888. #if qDebugMsg
  1889.     else
  1890.         fprintf(stderr, "CStringListRsrc::ReplaceAt there's no CString at %d to replace!\n", index);
  1891. #endif
  1892. } // CStringListRsrc::ReplaceAt 
  1893.  
  1894.  
  1895.  
  1896.  
  1897. StWatchCursor::StWatchCursor()    { ::SetCursor( (CursPtr)*(::GetCursor(watchCursor)) ); }
  1898. StWatchCursor::~StWatchCursor()    { ::SetCursor( &(UQDGlobals::GetQDGlobals()->arrow) ); }
  1899.  
  1900. //-----------------------------------
  1901. void StringParamText(
  1902.     CStr255& ioFormatString,
  1903.     SInt32 inReplaceNumber0,
  1904.     SInt32 inReplaceNumber1,
  1905.     SInt32 inReplaceNumber2,
  1906.     SInt32 inReplaceNumber3)
  1907. //    Replace the characters "^0" ..."^3"within ioString with numerals. 
  1908. //    If "^0" or "^1" is not found in ioString, the method does nothing.
  1909. //-----------------------------------
  1910. {
  1911.     char t0[15], t1[15], t2[15], t3[15];
  1912.     sprintf(t0, "%ld", inReplaceNumber0);
  1913.     sprintf(t1, "%ld", inReplaceNumber1);
  1914.     sprintf(t2, "%ld", inReplaceNumber2);
  1915.     sprintf(t3, "%ld", inReplaceNumber3);
  1916.     ::StringParamText(ioFormatString, t0, t1, t2, t3);
  1917. }
  1918.  
  1919. //-----------------------------------
  1920. void StringParamText(
  1921.     CStr255& ioFormatString,
  1922.     const char* inReplaceText0,
  1923.     const char* inReplaceText1,
  1924.     const char* inReplaceText2,
  1925.     const char* inReplaceText3)
  1926. //    Replace the substrings "^0" ..."^3" within ioString with inReplaceText0 ... inReplaceText3. 
  1927. //    (substring is just removed if inReplaceTextn is null). 
  1928. //    If any of the substrings "^0"..."^3" is not found in ioString, nothing happens there.
  1929. //-----------------------------------
  1930. {
  1931.     LStr255 resultString = (ConstStringPtr)&ioFormatString;
  1932.     char target[] = "^0";
  1933.     const char* replaceString[] = {
  1934.                     inReplaceText0,
  1935.                     inReplaceText1,
  1936.                     inReplaceText2,
  1937.                     inReplaceText3 };
  1938.     for (int i = 0; i < 4; i++)
  1939.     {
  1940.         UInt8 position = resultString.Find(target, 1);
  1941.         if ( position )
  1942.         {
  1943.             const char* rs = replaceString[i];
  1944.             if ( rs )
  1945.                 resultString.Replace(position, 2, rs, strlen(rs));
  1946.             else
  1947.                 resultString.Remove(position, 2);
  1948.         }
  1949.         target[1]++; // morph it into "^1" etc.  ASCII standard supports this.
  1950.     }
  1951.     ioFormatString = (ConstStringPtr)resultString;
  1952. }
  1953.  
  1954. // This code is taken from June 97 Dev.CD
  1955. enum
  1956. {
  1957.     kPromisedFlavor                = 'fssP',
  1958.     kPromisedFlavorFindFile        = 'rWm1'
  1959. };
  1960.  
  1961. static Size MinimumBytesForFSSpec (const FSSpec *fss)
  1962. {
  1963.     //
  1964.     //    Some senders don't bother sending the unused bytes of the
  1965.     //    file name. This function helps make sure the FSSpec is
  1966.     //    minimally sane by computing the minimum number of bytes it
  1967.     //    would take to store it.
  1968.     //
  1969.     //    THIS FUNCTION CANNOT MOVE MEMORY.
  1970.     //
  1971.  
  1972.     return sizeof (*fss) - sizeof (fss->name) + *(fss->name) + 1;
  1973. }
  1974.  
  1975. OSErr GetHFSFlavorFromPromise
  1976.     (DragReference dragRef, ItemReference itemRef,
  1977.         HFSFlavor *hfs, Boolean isSupposedlyFromFindFile)
  1978. {
  1979.     OSErr             err = noErr;
  1980.     PromiseHFSFlavor  phfs;
  1981.     Size              size = sizeof (phfs);
  1982.  
  1983.     err = GetFlavorData
  1984.         (dragRef,itemRef,flavorTypePromiseHFS,&phfs,&size,0);
  1985.  
  1986.     if (!err)
  1987.     {
  1988.         if (size != sizeof (phfs))
  1989.             err = cantGetFlavorErr;
  1990.         else
  1991.         {
  1992.             Boolean isFromFindFile =
  1993.                 phfs.promisedFlavor == kPromisedFlavorFindFile;
  1994.  
  1995.             if (isSupposedlyFromFindFile != isFromFindFile)
  1996.                 err = paramErr;
  1997.             else
  1998.             {
  1999.                 size = sizeof (hfs->fileSpec);
  2000.                 err = GetFlavorData
  2001.                     (dragRef,itemRef,phfs.promisedFlavor,
  2002.                         &(hfs->fileSpec),&size,0);
  2003.  
  2004.                 if (!err)
  2005.                 {
  2006.                     Size minSize = MinimumBytesForFSSpec
  2007.                         (&(hfs->fileSpec));
  2008.  
  2009.                     if (size < minSize)
  2010.                         err = cantGetFlavorErr;
  2011.                     else
  2012.                     {
  2013.                         hfs->fileType     = phfs.fileType;
  2014.                         hfs->fileCreator  = phfs.fileCreator;
  2015.                         hfs->fdFlags      = phfs.fdFlags;
  2016.                     }
  2017.                 }
  2018.             }
  2019.         }
  2020.     }
  2021.     return err;
  2022. }
  2023. // End of cut and paste
  2024.  
  2025. void GetDesktopIconSuiteFor( OSType inFileCreator, OSType inFileType, short inSize, Handle** ioHandle )
  2026. {
  2027.     Assert_( inSize == kLargeIcon || inSize == kSmallIcon  );
  2028.  
  2029.     Handle* h = *ioHandle;
  2030.     
  2031.     if (inFileCreator && inFileType )
  2032.     {
  2033.         Handle handle;
  2034.         OSErr err = ::NewIconSuite(h);
  2035.         short i = 0;
  2036.         if (!err && *h)
  2037.         {
  2038.             for ( i = 0; i< 3; i++ )
  2039.             {
  2040.                     err = ::DTGetIcon(nil, 0, inSize , inFileCreator, inFileType, &handle);
  2041.                 
  2042.                     if (!err)
  2043.                         err = ::AddIconToSuite(handle, *h, ::DTIconToResIcon( inSize  ) );
  2044.                     inSize++;
  2045.                     if( err )
  2046.                         break;
  2047.             }
  2048.             if( !err && i == 0 ) // Didn't find at least the B&W icon
  2049.             {
  2050.                 ::DisposeIconSuite(*h, true);
  2051.                 *h = nil;
  2052.             }                    
  2053.         }
  2054.     }
  2055.     if (!*h) 
  2056.     {
  2057.         ::GetIconSuite(h, 133, 
  2058.             inSize == kLargeIcon ?    kSelectorAllLargeData : kSelectorAllSmallData );
  2059.     }
  2060. }
  2061.  
  2062. StSpinningBeachBallCursor::StSpinningBeachBallCursor ()
  2063. {
  2064.     startAsyncCursors();
  2065. }
  2066.  
  2067. StSpinningBeachBallCursor::~StSpinningBeachBallCursor()
  2068. {
  2069.     stopAsyncCursors();
  2070. }
  2071.