home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / Help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-02  |  9.7 KB  |  401 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Help.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /* This file contains some sample code for handling dynamic balloon help.  The
  20. ** assumption here is that you used the AppsToGo program editor to add controls
  21. ** to the content of a window that have balloon help assigned to them. */
  22.  
  23.  
  24.  
  25. /*****************************************************************************/
  26.  
  27.  
  28.  
  29. #include "DTS.Lib2.h"
  30. #include "DTS.Lib.protos.h"
  31.  
  32. #ifndef __BALLOONS__
  33. #include <Balloons.h>
  34. #endif
  35.  
  36. #ifndef __PROCESSES__
  37. #include <Processes.h>
  38. #endif
  39.  
  40. #ifndef __RESOURCES__
  41. #include <Resources.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include "Utilities.h"
  46. #endif
  47.  
  48. #ifdef powerc
  49. #pragma options align=mac68k
  50. #endif
  51. typedef struct {
  52.     short    helpVers;
  53.     long    options;
  54.     short    procID;
  55.     short    variantForTip;
  56.     short    numMessages;
  57.     short    itemSize;
  58.     short    itemType[1];
  59. } hrctRec;
  60. typedef hrctRec *hrctRecPtr, **hrctRecHndl;
  61. #ifdef powerc
  62. #pragma options align=reset
  63. #endif
  64.  
  65. extern short    gQuickBalloons;
  66.  
  67. Boolean            gHaveQuickBalloon;
  68. PicHandle        gPicBalloon;
  69.  
  70. HMMessageRecord    gHelpMessage;
  71. Rect            gHelpMessageRct;
  72. ControlHandle    gHelpMessageCtl;
  73. WindowPtr        gHelpWithWindow;
  74.  
  75. extern short    gTECtl;
  76.  
  77. ControlHandle    ControlBalloonMessage(WindowPtr window, Point mouseLoc, HMMessageRecord *msg, Rect *msgRct,
  78.                                       short *pos, short *hrctID, short *itemID);
  79.  
  80.  
  81.  
  82. /*****************************************************************************/
  83. /*****************************************************************************/
  84.  
  85.  
  86.  
  87. #pragma segment Main
  88. Boolean    ControlBalloonHelp(WindowPtr window, short modifiers, Point mouseLoc)
  89. {
  90.     WindowPtr                ww;
  91.     ProcessSerialNumber        cpsn, fpsn;
  92.     ControlHandle            ctl;
  93.     short                    hrctID, itemID, pos;
  94.     Boolean                    procsSame;
  95.     HMMessageRecord            message, msg;
  96.     Rect                    messageRct;
  97.  
  98. #ifndef powerc
  99.     if (gSystemVersion < 0x0700)
  100.         if (!gQuickBalloons)
  101.             return(false);
  102. #endif
  103.  
  104.     if (gSystemVersion >= 0x0700) {
  105.         if (!window) {
  106.             if (gHelpMessage.hmmHelpType) HMRemoveBalloon();
  107.             gHelpMessage.hmmHelpType = 0;
  108.         }
  109.         if (gQuickBalloons) {
  110.             if ((modifiers & gQuickBalloons) == gQuickBalloons) {
  111.                 if (!HMGetBalloons())
  112.                     HMSetBalloons(gHaveQuickBalloon = true);
  113.             }
  114.             else {
  115.                 if (gHaveQuickBalloon) {
  116.                     if (HMGetBalloons()) {
  117.                         HMRemoveBalloon();
  118.                         HMSetBalloons(false);
  119.                     }
  120.                     gHaveQuickBalloon = false;
  121.                     gHelpMessage.hmmHelpType = 0;
  122.                 }
  123.             }
  124.         }
  125.         if (!window) return(false);
  126.     }
  127. #ifndef powerc
  128.     else {
  129.         if (!window) {
  130.             gHelpMessage.hmmHelpType = 0;
  131.             return(false);
  132.         }
  133.         gHaveQuickBalloon = ((modifiers & gQuickBalloons) == gQuickBalloons) ? true : false;
  134.         if (!gHaveQuickBalloon) {
  135.             gHelpMessage.hmmHelpType = 0;
  136.             return(false);
  137.         }
  138.     }
  139. #endif
  140.  
  141.     if (gSystemVersion >= 0x0700) {
  142.         if (!HMGetBalloons()) {
  143.             gHelpMessage.hmmHelpType = 0;
  144.             return(false);
  145.         }        /* Balloons have been turned off. */
  146.  
  147.         HMGetBalloonWindow(&ww);
  148.         if (!ww)
  149.             gHelpMessage.hmmHelpType = 0;
  150.                 /* There is no balloon currently, so there is no last message. */
  151.     }
  152. #ifndef powerc
  153.     else {
  154.         if (!GetNextWindow(nil, '6hlp'))
  155.             gHelpMessage.hmmHelpType = 0;
  156.     }
  157. #endif
  158.  
  159.     if (gSystemVersion >= 0x0700) {
  160.         GetCurrentProcess(&cpsn);
  161.         GetFrontProcess(&fpsn);
  162.         SameProcess(&cpsn, &fpsn, &procsSame);
  163.         if (!procsSame) {
  164.             gHelpMessage.hmmHelpType = 0;
  165.             return(false);
  166.         }        /* We aren't the front process, so leave. */
  167.     }
  168. #ifndef powerc
  169.     else {
  170.         if (gInBackground) {
  171.             gHelpMessage.hmmHelpType = 0;
  172.             return(false);
  173.         }
  174.     }
  175. #endif
  176.  
  177.     if (!GetWRefCon(window)) {
  178.         gHelpMessage.hmmHelpType = 0;
  179.         return(false);
  180.     }
  181.  
  182.     ctl = ControlBalloonMessage(window, mouseLoc, &message, &messageRct, &pos, &hrctID, &itemID);
  183.  
  184.     if (message.hmmHelpType) {
  185.         if (!EqualRect(&gHelpMessageRct, &messageRct))
  186.             gHelpMessage.hmmHelpType = -1;
  187.         if (!EqualData(&gHelpMessage, &message, sizeof(message))) {        /* If new balloon... */
  188.             gHelpMessage    = message;
  189.             gHelpMessageRct = messageRct;
  190.             gHelpMessageCtl = ctl;
  191.             gHelpWithWindow = window;
  192.             if (gSystemVersion >= 0x0700) {
  193.                 msg = message;
  194.                 if (message.hmmHelpType == khmmTERes) {
  195.                     if (gPicBalloon) KillPicture(gPicBalloon);
  196.                     gPicBalloon = BalloonText2PICT(window, &message);
  197.                     if (gPicBalloon) {
  198.                         msg.hmmHelpType = khmmPictHandle;
  199.                         msg.u.hmmPictHandle = gPicBalloon;
  200.                     }
  201.                 }
  202.                 HMShowBalloon(&msg, mouseLoc, &messageRct, nil, 0, pos, kHMRegularWindow);
  203.             }
  204. #ifndef powerc
  205.             else {
  206.                 if (gHaveQuickBalloon) {
  207.                     ww = GetNextWindow(nil, '6hlp');
  208.                     if (ww) {
  209.                         gHelpMessage.hmmHelpType = 0;
  210.                         return(false);
  211.                     }
  212.                     if (NewDocumentWindow(nil, '6hlp', false)) {
  213.                         gHelpMessage.hmmHelpType = 0;
  214.                         return(false);
  215.                     }
  216.                 }
  217.             }
  218. #endif
  219.         }
  220.         return(true);
  221.     }
  222.     else {
  223.         if (gSystemVersion >= 0x0700) {
  224.             if (gHelpMessage.hmmHelpType)
  225.                 HMRemoveBalloon();
  226.         }
  227.         gHelpMessage.hmmHelpType = 0;
  228.         if (gPicBalloon) {
  229.             KillPicture(gPicBalloon);
  230.             gPicBalloon = nil;
  231.         }
  232.     }
  233.  
  234.     return(false);
  235. }
  236.  
  237.  
  238.  
  239. /*****************************************************************************/
  240.  
  241.  
  242.  
  243. #pragma segment Main
  244. ControlHandle    ControlBalloonMessage(WindowPtr window, Point mouseLoc, HMMessageRecord *msg, Rect *msgRct,
  245.                                       short *pos, short *hrctID, short *itemID)
  246. {
  247.     Point                pt;
  248.     WindowPtr            oldPort;
  249.     ControlStyleInfo    cinfo;
  250.     Rect                rct;
  251.     short                charsUsed, i, j, cv, strNumID, strNumIndx;
  252.     long                ofst;
  253.     ControlHandle        ctl;
  254.     char                *cptr;
  255.     hrctRecHndl            hrct;
  256.     Ptr                    ptr;
  257.     static short        position[4] = {5, 6, 2, 1};
  258.  
  259.     msg->hmmHelpType  = 0;
  260.     *hrctID = *itemID = 0;
  261.  
  262.     GetPort(&oldPort);
  263.     SetPort(window);
  264.     pt = mouseLoc;
  265.     GlobalToLocal(&pt);
  266.     SetPort(oldPort);
  267.  
  268.     if (!WhichControl(pt, 0, window, &ctl)) return(nil);
  269.     if (!GetControlStyle(ctl, &cinfo))      return(nil);
  270.  
  271.     *msgRct = (*ctl)->contrlRect;
  272.     rct = (*(window->visRgn))->rgnBBox;
  273.     SectRect(&rct, msgRct, msgRct);
  274.     if (!PtInRect(pt, msgRct)) return(nil);
  275.  
  276.     cptr = (char *)cinfo.balloonHelp;
  277.     p2c((StringPtr)cptr);
  278.     if (!(*hrctID = c2dec(cptr, &charsUsed))) return(nil);
  279.     cptr += (charsUsed + 1);
  280.  
  281.     *itemID = c2dec(cptr, &charsUsed);
  282.     cptr += charsUsed;
  283.  
  284.     if (!(hrct = (hrctRecHndl)GetResource('hrct', *hrctID))) return(nil);
  285.  
  286.     if (*cptr == ',') {                                    /* If entry for inactive control... */
  287.         i = c2dec(++cptr, &charsUsed);
  288.         cptr += charsUsed;
  289.         if ((*ctl)->contrlHilite == 255) *itemID = i;    /* If control inactive... */
  290.     }
  291.  
  292.     while (*cptr == ':') {
  293.         cv = c2dec(++cptr, &charsUsed);
  294.         cptr += charsUsed;
  295.         i = j = c2dec(++cptr, &charsUsed);
  296.         cptr += charsUsed;
  297.         if (*cptr == ',') {                                    /* If entry for inactive control... */
  298.             j = c2dec(++cptr, &charsUsed);
  299.             cptr += charsUsed;
  300.         }
  301.         if (cv == (*ctl)->contrlValue) {
  302.             if (!(*ctl)->contrlHilite)       *itemID = i;    /* If control active... */
  303.             if ((*ctl)->contrlHilite == 255) *itemID = j;    /* If control inactive... */
  304.             break;
  305.         }
  306.     }
  307.  
  308.     if (!(hrct = (hrctRecHndl)GetResource('hrct', *hrctID))) return(nil);
  309.     if (*itemID > (*hrct)->numMessages)                      return(nil);
  310.     if (!*itemID)                                            return(nil);
  311.  
  312.     ofst = offsetof(hrctRec,itemSize);
  313.     for (i = 1; i < *itemID; ++i) {
  314.         ptr = (Ptr)*hrct;
  315.         ofst += *(short *)(ptr + ofst);
  316.     }
  317.     ofst += sizeof(short);                            /* Point to item type. */
  318.  
  319.     SetMem(msg, 0, sizeof(HMMessageRecord));        /* Clean out structure for compare purposes. */
  320.     ptr = (Ptr)*hrct;
  321.     msg->hmmHelpType = *(short *)(ptr + ofst);
  322.     ofst += sizeof(short);
  323.     ofst += (sizeof(Point) + sizeof(Rect));            /* Skip 'hrct' tip and rect. */
  324.     switch (msg->hmmHelpType) {
  325.         case kHMStringItem:
  326.             pcpy((StringPtr)msg->u.hmmString, (StringPtr)(ptr + ofst));
  327.             break;
  328.         case kHMPictItem:
  329.             msg->u.hmmPict = *(short *)(ptr + ofst);
  330.             break;
  331.         case kHMStringResItem:
  332.             strNumID = *(short *)(ptr + ofst);
  333.             ofst += sizeof(short);
  334.             strNumIndx = *(short *)(ptr + ofst);
  335.             msg->u.hmmStringRes.hmmResID = strNumID;
  336.             msg->u.hmmStringRes.hmmIndex = strNumIndx;
  337.             break;
  338.         case kHMTEResItem:
  339.             msg->u.hmmTERes = *(short *)(ptr + ofst);
  340.             break;
  341.         case kHMSTRResItem:
  342.             msg->u.hmmSTRRes = *(short *)(ptr + ofst);
  343.             break;
  344.     }
  345.  
  346.     LocalToGlobalRect(msgRct);
  347.     *pos = (mouseLoc.v > (msgRct->top + msgRct->bottom) / 2) ? 2 : 0;
  348.     if (mouseLoc.h > (msgRct->left + msgRct->right) / 2)
  349.         ++*pos;
  350.  
  351.     *pos = position[*pos];
  352.     return(ctl);
  353. }
  354.  
  355.  
  356.  
  357. /*****************************************************************************/
  358.  
  359.  
  360.  
  361. #pragma segment Main
  362. PicHandle    BalloonText2PICT(WindowPtr window, HMMessageRecord *msg)
  363. {
  364.     Rect            rct, **rh;
  365.     Handle            txt;
  366.     StScrpHandle    stl;
  367.     TEHandle        te;
  368.     PicHandle        pic;
  369.     short            ofst;
  370.     OSErr            err;
  371.  
  372.     if (msg->hmmHelpType != kHMTEResItem) return(nil);
  373.     if (!(rh  =      (Rect **)Get1Resource('RECT', msg->u.hmmTERes))) return(nil);
  374.     if (!(txt =               Get1Resource('TEXT', msg->u.hmmTERes))) return(nil);
  375.     if (!(stl = (StScrpHandle)Get1Resource('styl', msg->u.hmmTERes))) return(nil);
  376.  
  377.     rct = **rh;
  378.  
  379.     err = CTENew(gTECtl, false, window, &te, &rct, &rct, &rct, &rct, 32000, (cteNoBorder, cteStyledTE));
  380.     if (err) return(nil);
  381.  
  382.     DetachResource(txt);
  383.     DetachResource((Handle)stl);
  384.     DisposeHandle(CTESwapText(te, txt, stl, false));
  385.     DisposeHandle((Handle)stl);
  386.  
  387.     pic = OpenPicture(&rct);
  388.     if (pic) {
  389.         ofst = 0;
  390.         CTEPrint(te, &ofst, &rct);        /* The bottom of rct is now calculated, returned in rct.bottom. */
  391.         ClosePicture();
  392.         (*pic)->picFrame.bottom = rct.bottom;
  393.     }
  394.  
  395.     DisposeControl(CTEViewFromTE(te));
  396.     return(pic);
  397. }
  398.  
  399.  
  400.  
  401.