home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d5 / Telnet 2.6.1d5.src.sit.hqx / Telnet 2.6.1d5 src / source / debug / DlogUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-26  |  18.3 KB  |  689 lines

  1. /*
  2. *    DlogUtils.c
  3. *    Very Useful Dialog Utilities Apple SHOULD have provided in the toolbox...
  4. *
  5. *****************************************************************
  6. *    NCSA Telnet for the Macintosh                                *
  7. *                                                                *
  8. *    National Center for Supercomputing Applications                *
  9. *    Software Development Group                                    *
  10. *    152 Computing Applications Building                            *
  11. *    605 E. Springfield Ave.                                        *
  12. *    Champaign, IL  61820                                        *
  13. *                                                                *
  14. *    Copyright (c) 1986-1992,                                    *
  15. *    Board of Trustees of the University of Illinois                *
  16. *****************************************************************
  17. *  Revisions:
  18. *  8/92        Telnet 2.6:    Initial version.  Jim Browne
  19. */
  20.  
  21. #ifdef MPW
  22. #pragma segment Debug
  23. #endif
  24.  
  25. #include "TelnetHeader.h"
  26. #include "dialog_resrcdefs.h"
  27. #include "DlogUtils.proto.h"
  28. #include "netevent.proto.h"
  29. #include "newresrc.h"
  30.  
  31. #include "Popup.h"
  32. #include "popup.proto.h"
  33.  
  34. pascal short modalProc(DialogPtr dptr, EventRecord *evt, short *item);
  35. PROTO_UPP(modalProc, ModalFilter);
  36. pascal short FileHook(short item, DialogPtr theDialog);
  37. PROTO_UPP(FileHook, DlgHook);
  38. pascal Boolean    FolderFilter(FileParam *pbp);
  39. PROTO_UPP(FolderFilter, FileFilter);
  40.  
  41. void GetTEText( DialogPtr dptr, short item, Str255 str)
  42. {
  43.     short type;
  44.     Handle itemh;
  45.     Rect theRect;
  46.  
  47.     GetDItem(dptr, item, &type, &itemh, &theRect);
  48.     GetIText(itemh, str);
  49. }
  50.  
  51. void SetTEText( DialogPtr dptr, short item, Str255 str)
  52. {
  53.     short type;
  54.     Handle itemh;
  55.     Rect theRect;
  56.  
  57.     GetDItem(dptr, item, &type, &itemh, &theRect);
  58.     SetIText(itemh, str);
  59. }
  60.  
  61. void Hilite( DialogPtr dptr, short item, short value)
  62. {
  63.     short Type;
  64.     Handle Itemh;
  65.     Rect Box;
  66.  
  67.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  68.     HiliteControl((ControlHandle)Itemh, value);
  69. }
  70.  
  71. void FlipCheckBox( DialogPtr dptr, short item)
  72. {
  73.     short type;
  74.     Handle itemHdl;
  75.     Rect box;
  76.  
  77.     GetDItem(dptr, item, &type, &itemHdl, &box);
  78.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  79. }
  80.  
  81. void FlipRadioButton( DialogPtr dptr, short item)
  82. {
  83.     short type;
  84.     Handle itemHdl;
  85.     Rect box;
  86.  
  87.     GetDItem(dptr, item, &type, &itemHdl, &box);
  88.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  89. }
  90.  
  91. void SetCntrl( DialogPtr dptr, short item, short value)
  92. {
  93.     short Type;
  94.     Handle Itemh;
  95.     Rect Box;
  96.  
  97.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  98.     SetCtlValue((ControlHandle)Itemh, value);
  99. }
  100.  
  101. short GetCntlVal( DialogPtr dptr, short item)
  102. {
  103.     short Type;
  104.     Handle Itemh;
  105.     Rect Box;
  106.  
  107.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  108.     return GetCtlValue((ControlHandle)Itemh);
  109. }
  110.  
  111. #ifndef NO_UNIVERSAL
  112. void UItemAssign( DialogPtr dptr, short item, UserItemUPP proc)
  113. #else
  114. void UItemAssign( DialogPtr dptr, short item, ProcPtr proc)
  115. #endif
  116. /* sets the handler for a user item to the specified procedure. */
  117. {
  118.     Rect ibox;
  119.     char **ihndl;
  120.     short typ;
  121.  
  122.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  123.     SetDItem( dptr, item,  typ, (Handle) proc, &ibox);
  124. }
  125.  
  126. SIMPLE_UPP(OutlineItem, UserItem);
  127. pascal void OutlineItem( DialogPtr dptr, short itm)
  128. {
  129.     Rect ibox;
  130.     char **ihndl;
  131.     short typ;
  132.     short item=itm;
  133.     
  134.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  135.     PenSize( 3,3);
  136.     InsetRect( &ibox, -4,-4);
  137.     FrameRoundRect( &ibox, 16,16);
  138. }
  139.  
  140. SIMPLE_UPP(VersionNumber, UserItem);
  141. pascal void VersionNumber( DialogPtr dptr, short itm)
  142. {
  143.     Rect ibox;
  144.     char **ihndl;
  145.     short typ;
  146.     short item=itm;
  147.     VersRecHndl version;
  148.     Str63 versionString;
  149.  
  150.     if ((version = (VersRecHndl) GetResource('vers',1)) != nil)
  151.     {
  152.         BlockMove((*version)->shortVersion+*(*version)->shortVersion+1, versionString, *((*version)->shortVersion+*(*version)->shortVersion+1)+1);
  153.         ReleaseResource((Handle)version);
  154.     }
  155.     else
  156.         *versionString = 0;
  157.  
  158.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  159.     TextFont( 3);
  160.     TextSize( 9);
  161.     MoveTo( ibox.left+((ibox.right-ibox.left)/2)-(StringWidth(versionString)/2), ibox.bottom-2);
  162.     DrawString(versionString);
  163. }
  164.  
  165. SIMPLE_UPP(modalProc, ModalFilter);
  166. pascal short modalProc( DialogPtr dptr, EventRecord *evt, short *item)
  167. {
  168.     UNUSED_ARG(dptr)
  169.     short keyCode, key;
  170.  
  171.     if (evt->what == keyDown) {
  172.         key = evt->message & charCodeMask;
  173.         keyCode = (evt->message >>8) & 0xff ;
  174.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  175.             *item = DLOGOk;
  176.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  177.             }
  178.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  179.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  180.             *item = DLOGCancel;
  181.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  182.             }
  183.         }
  184.     Stask();
  185.     return(FALSE);
  186. }
  187.  
  188. void FlashButton (DialogPtr theDialog, short item)
  189. {
  190.     short itemType;
  191.     ControlHandle theItem;
  192.     Rect itemRect;
  193.     long myticks;
  194.     
  195.     if (item > 0) {
  196.         GetDItem(theDialog,item,&itemType,(Handle *)&theItem,&itemRect);
  197.         HiliteControl(theItem,1);
  198.         Delay(8,&myticks);
  199.         HiliteControl(theItem,0);
  200.     }
  201. }
  202.  
  203. SIMPLE_UPP(DLOGwOK, ModalFilter);
  204. pascal short DLOGwOK( DialogPtr dptr, EventRecord *evt, short *item)
  205. {
  206.     return(MyDLOGfilter(dptr, evt, item, true, false, false));
  207. }
  208.  
  209. SIMPLE_UPP(DLOGwOK_Cancel, ModalFilter);
  210. pascal short DLOGwOK_Cancel( DialogPtr dptr, EventRecord *evt, short *item)
  211. {
  212.     return(MyDLOGfilter(dptr, evt, item, true, true, false));
  213. }
  214.  
  215. SIMPLE_UPP(DLOGwOK_Cancel_Popup, ModalFilter);
  216. pascal short DLOGwOK_Cancel_Popup( DialogPtr dptr, EventRecord *evt, short *item)
  217. {
  218.     return(MyDLOGfilter(dptr, evt, item, true, true, true));
  219. }
  220.  
  221. //    Our standard modal dialog box filter.
  222. SIMPLE_UPP(MyDLOGfilter, ModalFilter);
  223. pascal short MyDLOGfilter( DialogPtr dptr, EventRecord *evt, short *item, 
  224.                             Boolean hasOK, Boolean hasCancel, Boolean hasPopup)
  225. {
  226.     short keyCode, key, iType;
  227.     Handle iHndl;
  228.     Rect iRect;
  229.  
  230.     SetPort(dptr);
  231.     if (evt->what == keyDown) {
  232.         key = evt->message & charCodeMask;
  233.         keyCode = (evt->message >>8) & 0xff ;
  234.         if (((key == 0x0d) || (key == 0x03)) && hasOK) { // 0x0d == return, 0x03 == enter
  235.             *item = DLOGOk;                // ok
  236.             FlashButton(dptr, DLOGOk);
  237.             return(-1);
  238.             }
  239.         if ((((key == '.') && (evt->modifiers & cmdKey)) ||
  240.             ((key == 0x1b) && (keyCode == 0x35))) && hasCancel) {    // 0x35 == escKey
  241.             *item = DLOGCancel;
  242.             FlashButton(dptr, DLOGCancel);
  243.             return(-1);
  244.             }
  245.         }
  246.     else if ((evt->what == updateEvt) && hasOK) {
  247.         if ((WindowPtr)evt->message == dptr) {
  248.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  249.             PenSize(3,3);
  250.             InsetRect(&iRect,-4,-4);
  251.             FrameRoundRect(&iRect,16,16);
  252.             }
  253.     }
  254.     
  255.     if ((evt->what == mouseDown) && hasPopup)
  256.         return(PopupMousedown(dptr, evt, item));
  257.  
  258.     Stask();
  259.     return(FALSE);
  260. }
  261.  
  262. #if 0
  263. //    Our standard modal dialog box filter with code to handle popup user items.
  264. pascal short MyDLOGfilterWPopupFilter( DialogPtr dptr, EventRecord *evt, short *item)
  265. {
  266.     short keyCode, key, iType;
  267.     Handle iHndl;
  268.     Rect iRect;
  269.  
  270.     SetPort(dptr);
  271.     if (evt->what == keyDown) {
  272.         key = evt->message & charCodeMask;
  273.         keyCode = (evt->message >>8) & 0xff ;
  274.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  275.             *item = DLOGOk;                // ok
  276.             FlashButton(dptr, DLOGOk);
  277.             return(-1);
  278.             }
  279.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  280.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  281.             *item = DLOGCancel;
  282.             FlashButton(dptr, DLOGCancel);
  283.             return(-1);
  284.             }
  285.         }
  286.     else if (evt->what == updateEvt) {
  287.         if ((WindowPtr)evt->message == dptr) {
  288.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  289.             PenSize(3,3);
  290.             InsetRect(&iRect,-4,-4);
  291.             FrameRoundRect(&iRect,16,16);
  292.             }
  293.     }
  294.     
  295.     if (evt->what == mouseDown) return(PopupMousedown(dptr, evt, item));
  296.     Stask();
  297.     return(FALSE);
  298. }
  299. #endif
  300.  
  301. #ifdef    NO_UNIVERSAL
  302. #define LMSetSFSaveDisk(SFSaveDiskValue) ((* (short *) 0x0214) = (SFSaveDiskValue))
  303. #define LMGetSFSaveDisk() (* (short *) 0x0214)
  304. #define LMGetCurDirStore() (* (long *) 0x0398)
  305. #define LMSetCurDirStore(CurDirStoreValue) ((* (long *) 0x0398) = (CurDirStoreValue))
  306. #endif
  307.  
  308. void    SelectDirectory(short *VRefNum, long *DirID)
  309. {
  310.     Point        where;
  311.     SFReply        sfr;
  312.     
  313.     LMSetSFSaveDisk( - (*VRefNum));
  314.     LMSetCurDirStore(*DirID);
  315.     
  316.     StandardFileCenter(&where, WDSET_DLOG);
  317.     
  318.     TelInfo->setdir = 0;                    /* clear dir found flag */
  319.     
  320.     SFPGetFile( where, NULL, FolderFilterUPP, -1, NULL,    /* BYU LSC */
  321.         FileHookUPP, &sfr, WDSET_DLOG,
  322.         modalProcUPP); 
  323.  
  324.     if (TelInfo->setdir)    {                /* we got a dir */
  325.         *VRefNum = - LMGetSFSaveDisk();
  326.         *DirID = LMGetCurDirStore();
  327.         }
  328. //    else {
  329. //        if(!sfr.good) return;    /* real cancel button got hit */
  330. //        GetWDInfo(sfr.vRefNum, VRefNum, DirID, &junk);
  331. //    }
  332.     
  333. }
  334.  
  335. SIMPLE_UPP(FileHook, DlgHook);
  336. pascal short    FileHook( short item, DialogPtr theDialog)
  337. {
  338. #ifdef    MPW
  339. #pragma unused(theDialog)
  340. #endif
  341.     if(item == 11) {                    /* Set Directory Button */
  342.             TelInfo->setdir = 1;
  343.             
  344.             return(3);        /* pretend we hit cancel, but we didn't */
  345.         }
  346.     else if (item == 12)
  347.         item = 9;            /* these don't count, map to disabled item */
  348.  
  349.     return(item);
  350. }
  351.  
  352. SIMPLE_UPP(FolderFilter, FileFilter);
  353. pascal Boolean    FolderFilter(FileParam *pbp)
  354. {
  355.     if (pbp->ioFlAttrib & 0x0010) return(FALSE);
  356.     else return(-1);
  357. }
  358.  
  359. OSErr SetIndString(StringPtr theStr,short resID,short strIndex)
  360. {
  361.    Handle theRes;               /* handle pointing to STR# resource */
  362.    short numStrings;            /* number of strings in STR# */
  363.    short ourString;             /* counter to index up to strIndex */
  364.    char *resStr;                /* string pointer to STR# string to replace */
  365.    long oldSize;                /* size of STR# resource before call */
  366.    long newSize;                /* size of STR# resource after call */
  367.    unsigned long offset;        /* resource offset to str to replace*/
  368.  
  369.    /* make sure index is in bounds */
  370.  
  371.    if (resID < 1)
  372.    return -1;
  373.  
  374.    /* make sure resource exists */
  375.  
  376.    theRes = GetResource('STR#',resID);
  377.    if (ResError()!=noErr)
  378.    return ResError();
  379.    if (!theRes || !(*theRes))
  380.    return resNotFound;
  381.  
  382.    HLock(theRes);
  383.    HNoPurge(theRes);
  384.  
  385.    /* get # of strings in STR# */
  386.  
  387.    BlockMove(*theRes,&numStrings,sizeof(short));
  388.    if (strIndex > numStrings)
  389.    return resNotFound;
  390.  
  391.    /* get a pointer to the string to replace */
  392.  
  393.    offset = sizeof(short);
  394.    resStr = (char *) *theRes + sizeof(short);
  395.    for (ourString=1; ourString<strIndex; ourString++) {
  396.    offset += 1+resStr[0];
  397.    resStr += 1+resStr[0];
  398.    }
  399.  
  400.    /* grow/shrink resource handle to make room for new string */
  401.  
  402.    oldSize = GetHandleSize(theRes);
  403.    newSize = oldSize - resStr[0] + theStr[0];
  404.    HUnlock(theRes);
  405.    SetHandleSize(theRes,newSize);
  406.    if (MemError()!=noErr) {
  407.    ReleaseResource(theRes);
  408.    return -1;
  409.    }
  410.    HLock(theRes);
  411.    resStr = *theRes + offset;
  412.  
  413.    /* move old data forward/backward to make room */
  414.  
  415.    BlockMove(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1);
  416.  
  417.    /* move new data in */
  418.  
  419.    BlockMove(theStr,resStr,theStr[0]+1);
  420.  
  421.    /* write resource out */
  422.  
  423.    ChangedResource(theRes);
  424.    WriteResource(theRes);
  425.    HPurge(theRes);
  426.    ReleaseResource(theRes);
  427.  
  428.    return ResError();
  429. }
  430.  
  431. /* A very special thanks to Steve Dorner (sdorner@qualcomm.com) for the following code! */
  432.  
  433. /************************************************************************
  434.  * GetNewMyDialog - get a new dialog, with a bit extra
  435.  ************************************************************************/
  436. WindowPtr GetNewMyDialog(short template,Ptr wStorage,WindowPtr behind,
  437.     void (*centerFunction)(short))
  438. {
  439.     WindowPtr win;
  440.     
  441.     if (wStorage == nil)
  442.     {
  443.         if ((wStorage=NewPtr(sizeof(DialogRecord)))==nil)
  444.             return (nil);
  445.     }
  446.     WriteZero(wStorage, sizeof(WindowRecord));
  447.     
  448.     (*centerFunction)(template);
  449.     win = GetNewDialog(template, wStorage, behind);
  450.     if (win==nil) return(nil);
  451.     SetPort(win);
  452. /*    win->contR = ((GrafPtr)win)->portRect; */
  453. /*    win->qWindow.refCon = CREATOR; */
  454.     return(win);
  455. }
  456.  
  457. /* Do a GetNewMyDialog, but make the text small... */
  458. WindowPtr GetNewMySmallDialog(short template,Ptr wStorage,WindowPtr behind,
  459.     void (*centerFunction)(short))
  460. {
  461.     short size;
  462.     DialogPtr dlogptr;
  463.     
  464.     size = 9;
  465.     SetDAFont(applFont);
  466.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  467.     SetDAFont(systemFont);
  468.     if (dlogptr==nil)
  469.         return 0;
  470.     SetPort(dlogptr);
  471.     TextSize(size);
  472.     TextFont(applFont);
  473.     {
  474.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  475.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  476.         (*teh)->txSize = size;
  477.         (*teh)->lineHeight = GetLeading(applFont,size);
  478.         (*teh)->fontAscent = GetAscent(applFont,size);
  479.     }            
  480.  
  481.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  482.         and then do a ShowWindow.  This keeps the Control Manager from every using Chicago
  483.         on our turf. -- JMB */
  484.         
  485.     if (! ((((DialogPeek) dlogptr)->window).visible)) ShowWindow(dlogptr);
  486.     
  487.     return(dlogptr);
  488. }
  489.  
  490. /* Do a GetNewMySmallDialog, but read the item titles from a STR#... */
  491. WindowPtr GetNewMySmallStrangeDialog(short template,Ptr wStorage,WindowPtr behind,
  492.     void (*centerFunction)(short))
  493. {
  494.     short         size, index, limit, itemType;
  495.     DialogPtr     dlogptr;
  496.     Handle        resource;
  497.     ControlHandle    itemHandle;
  498.     Rect        scratchRect;
  499.     Str255        scratchPstring;
  500.     
  501.     size = 9;
  502.     SetDAFont(applFont);
  503.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  504.     SetDAFont(systemFont);
  505.     if (dlogptr==nil)
  506.         return 0;
  507.     SetPort(dlogptr);
  508.     TextSize(size);
  509.     TextFont(applFont);
  510.     {
  511.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  512.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  513.         (*teh)->txSize = size;
  514.         (*teh)->lineHeight = GetLeading(applFont,size);
  515.         (*teh)->fontAscent = GetAscent(applFont,size);
  516.     }            
  517.  
  518.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  519.         and then do a ShowWindow.  This keeps the Control Manager from ever using Chicago
  520.         on our turf. -- JMB */
  521.     
  522.     if ((resource = GetResource('STR#', template)) != NULL) {
  523.         limit = *(short *)(*resource);
  524.         ReleaseResource(resource);
  525.         
  526.         for(index = 1; index <= limit; index++) {
  527.             GetDItem(dlogptr, index, &itemType, (Handle *)&itemHandle, &scratchRect);
  528.             if ((itemType == 7) && ((**itemHandle).contrlRfCon == 1991)) {
  529.                 GetIndString(scratchPstring, template, index);
  530.                 SetCTitle(itemHandle, scratchPstring);
  531.                 }
  532.             }
  533.         }
  534.                 
  535.     return(dlogptr);
  536. }
  537.  
  538. /**********************************************************************
  539.  * write zeroes over an area of memory
  540.  **********************************************************************/
  541. void WriteZero(Ptr pointer,long size)
  542. {
  543.     while (size--) *pointer++ = 0;
  544. }
  545.  
  546. /**********************************************************************
  547.  * figure out the appropriate leading for a font
  548.  **********************************************************************/
  549. short GetLeading(short fontID,short fontSize)
  550. {
  551.     FMInput fInInfo;
  552.     FMOutput *fOutInfo;
  553.     
  554.     /* set up the font input struct */
  555.     fInInfo.family = fontID;
  556.     fInInfo.size = fontSize;
  557.     fInInfo.face = 0;
  558.     fInInfo.needBits = FALSE;
  559.     fInInfo.device = 0;
  560.     fInInfo.numer.h = fInInfo.numer.v = 1;
  561.     fInInfo.denom.h = fInInfo.denom.v = 1;
  562.     
  563.     /* get the actual info */
  564.     fOutInfo = FMSwapFont(&fInInfo);
  565.     
  566.     return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
  567. }
  568.  
  569. /**********************************************************************
  570.  * find ascent font
  571.  **********************************************************************/
  572. short GetAscent(short fontID,short fontSize)
  573. {
  574.     FMInput fInInfo;
  575.     FMOutput *fOutInfo;
  576.     
  577.     /*    set up the font input struct */
  578.     fInInfo.family = fontID;
  579.     fInInfo.size = fontSize;
  580.     fInInfo.face = 0;
  581.     fInInfo.needBits = FALSE;
  582.     fInInfo.device = 0;
  583.     fInInfo.numer.h = fInInfo.numer.v = 1;
  584.     fInInfo.denom.h = fInInfo.denom.v = 1;
  585.     
  586.     /*    get the actual info */
  587.     fOutInfo = FMSwapFont(&fInInfo);
  588.     
  589.     return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
  590. }
  591.  
  592. /************************************************************************
  593.  * CenterRectIn - center one rect in another
  594.  ************************************************************************/
  595. void CenterRectIn(Rect *inner,Rect *outer)
  596. {
  597.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  598.                                      (outer->top+outer->bottom-inner->top-inner->bottom)/2);                                                                    
  599. }
  600.  
  601. /************************************************************************
  602.  * TopCenterRectIn - center one rect in (the bottom of) another
  603.  ************************************************************************/
  604. void TopCenterRectIn(Rect *inner,Rect *outer)
  605. {
  606.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  607.                                      outer->top-inner->top);                                                                    
  608. }
  609.  
  610. /************************************************************************
  611.  * BottomCenterRectIn - center one rect in (the bottom of) another
  612.  ************************************************************************/
  613. void BottomCenterRectIn(Rect *inner,Rect *outer)
  614. {
  615.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  616.                                      outer->bottom-inner->bottom);                                                                    
  617. }
  618.  
  619. /************************************************************************
  620.  * ThirdCenterRectIn - center one rect in (the top 1/3 of) another
  621.  ************************************************************************/
  622. void ThirdCenterRectIn(Rect *inner,Rect *outer)
  623. {
  624.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  625.                                      outer->top-inner->top +
  626.                                      (outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  627. }
  628.  
  629. void ThirdCenterDialog(short template)
  630. {
  631.   DialogTHndl dTempl;
  632.   Rect r = qd.screenBits.bounds;
  633.   r.top += GetMBarHeight();       
  634.   if ((dTempl=(DialogTHndl)GetResource('ALRT',template)) ||
  635.       (dTempl=(DialogTHndl)GetResource('DLOG',template)))
  636.     ThirdCenterRectIn(&(*dTempl)->boundsRect,&r);
  637. }
  638.  
  639. /************************************************************************
  640.  * StandardFileCenter - figure out where a stdfile dialog should go
  641.  ************************************************************************/
  642. void StandardFileCenter(Point *where, short id)
  643. {
  644.     Rect r,in;
  645.     DialogTHndl dTempl;             
  646.     if ((dTempl=(DialogTHndl)GetResource('ALRT',id)) ||
  647.             (dTempl=(DialogTHndl)GetResource('DLOG',id)))
  648.     {
  649.         r = (*dTempl)->boundsRect;
  650.         in = qd.screenBits.bounds;
  651.         in.top += GetMBarHeight();
  652.         ThirdCenterRectIn(&r,&in);
  653.         where->h = r.left;
  654.         where->v = r.top;
  655.     }
  656.     else
  657.     {
  658.         where->h = 100;
  659.         where->v = 100;
  660.     }
  661. }
  662.  
  663. /* Pascal string utilities */
  664.  
  665. /*    pstrcat - add string 'src' to end of string 'dst' */
  666. void pstrcat(StringPtr dst, StringPtr src)
  667. {
  668.     /* copy string in */
  669.     BlockMove(src + 1, dst + *dst + 1, *src);
  670.     /* adjust length byte */
  671.     *dst += *src;
  672. }
  673.  
  674. /*    pstrinsert - insert string 'src' at beginning of string 'dst' */
  675. void pstrinsert(StringPtr dst, StringPtr src)
  676. {
  677.     /* make room for new string */
  678.     BlockMove(dst + 1, dst + *src + 1, *dst);
  679.     /* copy new string in */
  680.     BlockMove(src + 1, dst + 1, *src);
  681.     /* adjust length byte */
  682.     *dst += *src;
  683. }
  684.  
  685. void pstrcpy(StringPtr dst, StringPtr src)
  686. {
  687.     BlockMove(src, dst, *src + 1);
  688. }
  689.