home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Sample Code / AppsToGo / DTS.Lib / PICTControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  12.9 KB  |  567 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         pictcontrol.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.  
  20.  
  21. /*****************************************************************************/
  22.  
  23.  
  24.  
  25. #ifndef __PICTCONTROL__
  26. #include "PICTControl.h"
  27. #endif
  28.  
  29. #ifndef __CONTROLS__
  30. #include <Controls.h>
  31. #endif
  32.  
  33. #ifndef __DTSLib__
  34. #include "DTS.Lib.h"
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __FONTS__
  42. #include <Fonts.h>
  43. #endif
  44.  
  45. #ifndef __GWLAYERS__
  46. #include "GWLayers.h"
  47. #endif
  48.  
  49. #ifndef __MEMORY__
  50. #include <Memory.h>
  51. #endif
  52.  
  53. #ifndef __PACKAGES__
  54. #include <Packages.h>
  55. #endif
  56.  
  57. #ifndef __RESOURCES__
  58. #include <Resources.h>
  59. #endif
  60.  
  61. #ifndef __STRINGUTILS__
  62. #include "StringUtils.h"
  63. #endif
  64.  
  65. #ifndef __UTILITIES__
  66. #include "Utilities.h"
  67. #endif
  68.  
  69.  
  70.  
  71. /*****************************************************************************/
  72.  
  73.  
  74.  
  75. #if defined(powerc) || defined (__powerc)
  76. #pragma options align=mac68k
  77. #endif
  78. typedef struct cdefRsrcJMP {
  79.     long    jsrInst;
  80.     long    moveInst;
  81.     short    jmpInst;
  82.     long    jmpAddress;
  83. } cdefRsrcJMP;
  84. typedef cdefRsrcJMP *cdefRsrcJMPPtr, **cdefRsrcJMPHndl;
  85. #if defined(powerc) || defined(__powerc)
  86. #pragma options align=reset
  87. #endif
  88.  
  89.  
  90.  
  91. /*****************************************************************************/
  92.  
  93.  
  94.  
  95. short    gPICTCtl = rPICTCtl;
  96.  
  97. extern ControlHandle    gWhichCtlHit;
  98. extern Boolean            gWhichCtlDbl;
  99. extern Boolean            gWhichCtlTracking;
  100.  
  101. static pascal long        CPICTCtl   (short varCode, ControlHandle ctl, short msg, long parm);
  102. static pascal void        CPICTAction(ControlHandle ctl, short part);
  103. static pascal void        NoRect(GrafVerb verb, Rect *r);
  104. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id);
  105.  
  106. static cdefRsrcJMPHndl    gCDEF;
  107.  
  108.  
  109.  
  110. /*****************************************************************************/
  111. /*****************************************************************************/
  112. /*****************************************************************************/
  113.  
  114.  
  115.  
  116. #pragma segment Controls
  117. static pascal long    CPICTCtl(short varCode, ControlHandle ctl, short msg, long parm)
  118. {
  119.     Rect                viewRct, r;
  120.     short                thisHilite, keepHilite, i;
  121.     unsigned long        resPICTID, id, variant, sticky, offScreen, srcOrMode;
  122.     PicHandle            pict;
  123.     ControlHandle        cc;
  124.     WindowPtr            ww, curPort, keepPort;
  125.     LayerObj            wlayer, blayer;
  126.     RgnHandle            oldClip, newClip, colorRgn;
  127.     short                txFont, txSize, txMode, fnum;
  128.     Style                txFace;
  129.     QDProcs                qdp;
  130.     QDProcsPtr            oldqdp;
  131.     FontInfo            finfo;
  132.     ControlStyleInfo    cinfo;
  133.     char                hstate;
  134.     Handle                dh;
  135.  
  136.     static QDRectUPP    qdrupp;
  137.  
  138.     viewRct    = (*ctl)->contrlRect;
  139.     thisHilite = (*ctl)->contrlHilite;
  140.     resPICTID  = (*ctl)->contrlRfCon & 0x0000FFFFL;
  141.     variant    = (*ctl)->contrlRfCon & 0xFFFF0000L;
  142.     sticky     = variant & 0x00010000L;
  143.     offScreen  = variant & 0x00020000L;
  144.     srcOrMode  = variant & 0x00080000L;
  145.  
  146.     switch (msg) {
  147.  
  148.         case drawCntl:
  149.  
  150.             GetPort(&curPort);
  151.  
  152.             if (EmptyRgn(curPort->visRgn)) break;
  153.  
  154.             if (offScreen) {
  155.                 NewLayer(&wlayer, nil, nil, curPort, 0, 0);
  156.                 if (srcOrMode) (*wlayer)->xferMode = srcOr;
  157.                 r = curPort->portRect;
  158.                 SectRect(&r, &viewRct, &r);
  159.                 (*wlayer)->dstRect = r;                /* Minimize the size of the offscreen. */
  160.                 NewLayer(&blayer, wlayer, nil, nil, (*ctl)->contrlMin, 0);
  161.                 SetLayerWorld(blayer);
  162.                 InvalLayer(wlayer, r, false);
  163.             }
  164.  
  165.             if (sticky) {
  166.                 if (thisHilite < 2)
  167.                     thisHilite = (*ctl)->contrlValue;
  168.                 if (thisHilite == 2)
  169.                     thisHilite = 255;
  170.             }
  171.  
  172.             switch (thisHilite) {
  173.                 case 1:
  174.                 case 255:
  175.                     id = (thisHilite == 1) ? (resPICTID + 2) : (resPICTID + 4);
  176.  
  177.                     SetResLoad(false);
  178.                     if (!GetPICT(ctl, resPICTID, id)) id = resPICTID;
  179.                     SetResLoad(true);
  180.  
  181.                     (*ctl)->contrlRfCon = (id + variant - offScreen);
  182.                     keepHilite = (*ctl)->contrlHilite;
  183.                     (*ctl)->contrlHilite = 99;
  184.                     CPICTCtl(varCode, ctl, msg, parm);
  185.                     (*ctl)->contrlHilite = keepHilite;
  186.                     (*ctl)->contrlRfCon  = (resPICTID | variant);
  187.                     if (thisHilite == 1)
  188.                         if (id == resPICTID)
  189.                             InvertRect(&viewRct);
  190.                                 /* If there is no hilite==1 'PICT', invert the base 'PICT'. */
  191.                     break;
  192.                 default:
  193.                     EraseRect(&viewRct);        /* Start pict fresh and clean. */
  194.  
  195.                     pict = GetPICT(ctl, resPICTID, resPICTID);
  196.                     if (!pict) {
  197.                         FrameRect(&viewRct);
  198.                         break;
  199.                     }
  200.  
  201.                     hstate = HGetState((Handle)pict);        /* Lock it before moving something */
  202.                     HLock((Handle)pict);                    /* causes it to purge.               */
  203.  
  204.                     GetPort(&keepPort);
  205.                     SetPort((*ctl)->contrlOwner);
  206.                     colorRgn = LocalScreenDepthRegion(4);
  207.                     SetPort(keepPort);
  208.  
  209.                     oldClip = NewRgn();
  210.                     newClip = NewRgn();
  211.                     GetClip(oldClip);            /* Draw color area first. */
  212.                     RectRgn(newClip, &curPort->portRect);
  213.                     SectRgn(newClip, colorRgn, newClip);
  214.                     SetClip(newClip);
  215.                     DrawPicture(pict, &viewRct);
  216.                     HSetState((Handle)pict, hstate);
  217.  
  218.                     pict = GetPICT(ctl, resPICTID, resPICTID + 1);
  219.                     if (!pict)
  220.                         pict = GetPICT(ctl, resPICTID, resPICTID);
  221.                     if (pict) {
  222.                         hstate = HGetState((Handle)pict);
  223.                         HLock((Handle)pict);
  224.                         RectRgn(newClip, &curPort->portRect);    /* Draw b/w pict area. */
  225.                         DiffRgn(newClip, colorRgn, newClip);
  226.                         SetClip(newClip);
  227.                         DrawPicture(pict, &viewRct);
  228.                         HSetState((Handle)pict, hstate);
  229.                     }
  230.  
  231.                     SetClip(oldClip);
  232.                     DisposeRgn(oldClip);
  233.                     DisposeRgn(newClip);
  234.                     DisposeRgn(colorRgn);
  235.  
  236.                     break;
  237.             }
  238.  
  239.             GetPort(&ww);
  240.             txFont = ww->txFont;
  241.             txFace = ww->txFace;
  242.             txSize = ww->txSize;
  243.             if (!(variant & useWFont)) {
  244.                 TextFont(systemFont);
  245.                 TextFace(normal);
  246.                 TextSize(0);
  247.             }
  248.             else {
  249.                 if (GetControlStyle(ctl, &cinfo)) {
  250.                     TextFace(cinfo.fontStyle);
  251.                     fnum = systemFont;
  252.                     if (cinfo.font[0])
  253.                         GetFNum(cinfo.font, &fnum);
  254.                     TextFont(fnum);
  255.                     TextSize(cinfo.fontSize);
  256.                 }
  257.             }
  258.  
  259.             oldqdp = ww->grafProcs;
  260.             if (oldqdp)
  261.                 BlockMove(oldqdp, &qdp, sizeof(QDProcs));
  262.             else
  263.                 SetStdProcs(&qdp);
  264.             if (!qdrupp) {
  265. #if USES68KINLINES
  266.                 qdrupp = (QDRectUPP)NoRect;
  267. #else
  268.                 qdrupp = NewQDRectProc(NoRect);
  269. #endif
  270.             }
  271.             qdp.rectProc = qdrupp;
  272.             ww->grafProcs = &qdp;
  273.             txMode = ww->txMode;
  274.             TextMode(srcOr);
  275.  
  276.             HLock((Handle)ctl);
  277.             GetFontInfo(&finfo);
  278.             viewRct.top += (finfo.ascent + finfo.descent) / 2;
  279.             if (viewRct.top < viewRct.bottom)
  280.                 TETextBox((*ctl)->contrlTitle + 1, (*ctl)->contrlTitle[0], &viewRct, teCenter);
  281.             HUnlock((Handle)ctl);
  282.  
  283.             ww->grafProcs = oldqdp;
  284.             TextMode(txMode);
  285.  
  286.             TextFont(txFont);
  287.             TextFace(txFace);
  288.             TextSize(txSize);
  289.  
  290.             if (offScreen) {
  291.                 UpdateLayer(wlayer);
  292.                 ResetLayerWorld(blayer);
  293.                 DisposeThisAndBelowLayers(wlayer);
  294.             }
  295.  
  296.             break;
  297.  
  298.         case testCntl:
  299.  
  300.             if ((*ctl)->contrlHilite == 255) return(0);
  301.                 /* Control disabled, so no click.  (We probably don't get called in this case. */
  302.  
  303.             if (!sticky) return(PtInRect(*(Point *)&parm, &viewRct));
  304.                 /* Don't make user call WhichControl unless the variant
  305.                 ** is for double-clicking.  (Then it has to be called.) */
  306.  
  307.             if (ctl != gWhichCtlHit) return(0);
  308.                 /* WhichControl already found the control hit.  Unless it is the one
  309.                 ** found by WhichControl, consider it unhit. */
  310.  
  311.             if (gWhichCtlTracking) return(1);
  312.                 /* We already handled it, but the control manager is insistent. */
  313.  
  314.             if (!(*ctl)->contrlValue) {            /* Turn off any other controls in this family. */
  315.                 ww = (*ctl)->contrlOwner;
  316.                 for (cc = nil; (cc = CPICTNext(ww, cc, 1, true)) != nil;) {
  317.                     if (cc != ctl) {
  318.                         if (((*cc)->contrlMax & 0xFFF0) == ((*ctl)->contrlMax & 0xFFF0)) {
  319.                             if ((*cc)->contrlValue) {
  320.                                 (*cc)->contrlValue  = 0;
  321.                                 (*cc)->contrlHilite = 0;
  322.                                 CPICTCtl(varCode, cc, drawCntl, 0);
  323.                             }
  324.                         }
  325.                     }
  326.                 }
  327.             }
  328.  
  329.             (*ctl)->contrlValue = 1;
  330.             if (gWhichCtlDbl)                        /* If user double-clicked... */
  331.                 if (!((*ctl)->contrlMax & 0x01))    /* If double-clicking allowed... */
  332.                     (*ctl)->contrlValue = 2;
  333.  
  334.             CPICTCtl(varCode, ctl, drawCntl, 0);
  335.  
  336.             gWhichCtlTracking = true;
  337.             return(1);
  338.  
  339.             break;
  340.  
  341.         case calcCRgns:
  342.         case calcCntlRgn:
  343.             if (msg == calcCRgns)
  344.                 parm &= 0x00FFFFFF;
  345.             RectRgn((RgnHandle)parm, &viewRct);
  346.             break;
  347.  
  348.         case initCntl:
  349.             (*ctl)->contrlData = nil;
  350.             break;
  351.  
  352.         case dispCntl:
  353.             dh = (*ctl)->contrlData;
  354.             if (dh) {
  355.                 for (i = 0; i < 6; ++i) {
  356.                     pict = (*(PicHandle **)dh)[i];
  357.                     if (pict) KillPicture(pict);
  358.                 }
  359.                 DisposeHandle(dh);
  360.                 (*ctl)->contrlData = nil;
  361.             }
  362.             break;
  363.  
  364.         case posCntl:
  365.             break;
  366.  
  367.         case thumbCntl:
  368.             break;
  369.  
  370.         case dragCntl:
  371.             break;
  372.  
  373.         case autoTrack:
  374.             break;
  375.     }
  376.  
  377.     return(0);
  378. }
  379.  
  380.  
  381.  
  382. /*****************************************************************************/
  383.  
  384.  
  385.  
  386. #pragma segment Controls
  387. ControlHandle    CPICTNew(WindowPtr window, Rect *r, StringPtr title, Boolean vis, short val,
  388.                          short min, short max, short viewID, short refcon)
  389. {
  390.     WindowPtr        oldPort;
  391.     Rect            viewRct, rct;
  392.     Boolean            err;
  393.     ControlHandle    viewCtl;
  394.     unsigned long    variant;
  395.     PicHandle        pict;
  396.  
  397.     static ControlActionUPP    cupp;
  398.     static ControlDefUPP    cdefupp;
  399.  
  400.     GetPort(&oldPort);
  401.     SetPort(window);
  402.  
  403.     viewRct = *r;
  404.     viewCtl = nil;
  405.  
  406.     err = false;
  407.  
  408.     if (!gCDEF) {
  409.         gCDEF = (cdefRsrcJMPHndl)GetResource('CDEF', (viewID / 16));
  410.         if (gCDEF) {
  411.             if (!cdefupp) {
  412.                 cdefupp = NewControlDefProc(CPICTCtl);
  413.             }
  414.             (*gCDEF)->jmpAddress = (long)cdefupp;
  415.             FlushInstructionCache();    /* Make sure that instruction caches don't kill us. */
  416.         }
  417.         else err = true;
  418.     }
  419.  
  420.     if (!err) {
  421.         if (viewID & 0x04) {
  422.             viewID -= 0x04;
  423.             pict = (PicHandle)GetResource('PICT', refcon);
  424.             if (pict) {
  425.                 rct = (*pict)->picFrame;
  426.                 viewRct.right  = viewRct.left + (rct.right  - rct.left);
  427.                 viewRct.bottom = viewRct.top  + (rct.bottom - rct.top);
  428.             }
  429.         }
  430.         variant   = (viewID & 0x0F);
  431.         variant <<= 16;
  432.         viewCtl = NewControl(window, &viewRct, title, vis, val, min, max, viewID, (variant | refcon));
  433.         if (viewCtl) {
  434.             if (!cupp) cupp = NewControlActionProc(CPICTAction);
  435.             SetControlAction(viewCtl, cupp);
  436.         }
  437.         else
  438.             err = true;
  439.     }
  440.  
  441.     SetPort(oldPort);
  442.  
  443.     return(viewCtl);
  444. }
  445.  
  446.  
  447.  
  448. /*****************************************************************************/
  449.  
  450.  
  451.  
  452. #pragma segment Controls
  453. ControlHandle    CPICTNext(WindowPtr window, ControlHandle ctl, short dir, Boolean justActive)
  454. {
  455.     ControlHandle    nextCtl, priorCtl;
  456.  
  457.     if (!window) return(nil);
  458.     if (!gCDEF)  return(nil);
  459.  
  460.     if (dir > 0) {
  461.         if (!ctl)
  462.             ctl = ((WindowPeek)window)->controlList;
  463.         else
  464.             ctl = (*ctl)->nextControl;
  465.         while (ctl) {
  466.             if ((!justActive) || ((*ctl)->contrlVis)) {
  467.                 if ((!justActive) || ((*ctl)->contrlHilite != 255)) {
  468.                     if (*(*ctl)->contrlDefProc == *(Handle)gCDEF)
  469.                         return(ctl);
  470.                             /* The handle may be locked, which means that the hi-bit
  471.                             ** may be on, thus invalidating the compare.  Dereference the
  472.                             ** handles to get rid of this possibility. */
  473.                 }
  474.             }
  475.             ctl = (*ctl)->nextControl;
  476.         }
  477.         return(ctl);
  478.     }
  479.  
  480.     nextCtl = ((WindowPeek)window)->controlList;
  481.     for (priorCtl = nil; ;nextCtl = (*nextCtl)->nextControl) {
  482.         if ((!nextCtl) || (nextCtl == ctl)) return(priorCtl);
  483.         if ((!justActive) || ((*nextCtl)->contrlVis)) {
  484.             if ((!justActive) || ((*nextCtl)->contrlHilite != 255)) {
  485.                 if (*(*ctl)->contrlDefProc == *(Handle)gCDEF)
  486.                     priorCtl = nextCtl;
  487.                         /* The handle may be locked, which means that the hi-bit
  488.                         ** may be on, thus invalidating the compare.  Dereference the
  489.                         ** handles to get rid of this possibility. */
  490.             }
  491.         }
  492.     }
  493. }
  494.  
  495.  
  496.  
  497. /*****************************************************************************/
  498.  
  499.  
  500.  
  501. #pragma segment Controls
  502. Boolean    IsPICTCtl(ControlHandle ctl)
  503. {
  504.     if (ctl)
  505.         if (*(*ctl)->contrlDefProc == *(Handle)gCDEF)
  506.             return(true);
  507.                 /* The handle may be locked, which means that the hi-bit
  508.                 ** may be on, thus invalidating the compare.  Dereference the
  509.                 ** handles to get rid of this possibility. */
  510.     return(false);
  511. }
  512.  
  513.  
  514.  
  515. /*****************************************************************************/
  516.  
  517.  
  518.  
  519. #pragma segment Controls
  520. static pascal void    CPICTAction(ControlHandle ctl, short part)
  521. {
  522.     static short    lastPart = 0;
  523.  
  524.     if (lastPart != part) {
  525.         lastPart = part;
  526.         CPICTCtl(0, ctl, drawCntl, part);
  527.     }
  528. }
  529.  
  530.  
  531.  
  532. /*****************************************************************************/
  533.  
  534.  
  535.  
  536. #pragma segment Controls
  537. static pascal void    NoRect(GrafVerb verb, Rect *r)
  538. {
  539. #ifndef __MWERKS__
  540. #pragma unused (verb, r)
  541. #endif
  542. }
  543.  
  544.  
  545.  
  546. /*****************************************************************************/
  547.  
  548.  
  549.  
  550. #pragma segment Controls
  551. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id)
  552. {
  553.     Handle        dh;
  554.     PicHandle    pict;
  555.  
  556.     dh = (*ctl)->contrlData;
  557.     if (dh)
  558.         pict = (*(PicHandle **)dh)[id - baseID];
  559.     else
  560.         pict = (PicHandle)GetResource('PICT', id);
  561.  
  562.     return(pict);
  563. }
  564.  
  565.  
  566.  
  567.