home *** CD-ROM | disk | FTP | other *** search
/ CD-ROM Today - The Disc! 8 / cdrt08.iso / mac / Shareware / HyperCard / demoCdef 120 ƒ / demo Source ƒ / dimText.c < prev    next >
Encoding:
Text File  |  1994-12-12  |  9.5 KB  |  363 lines  |  [TEXT/KAHL]

  1. //----------------------------------------------------------------------------------
  2. //    File        : dimText.c
  3. //    Date        : March 17, 1994
  4. //    Author        : James W. Walker
  5. //                :
  6. //                : renamed routines for consistency with coding style in daAssist.c
  7. //                :  Jim Stout (with apologies to JWW╔)
  8. //----------------------------------------------------------------------------------
  9. #include <GestaltEqu.h>
  10. #include "dimText.h"
  11.  
  12. #if THINK_C == 7
  13. #define UNIVERSAL_HEADERS 1
  14. #endif
  15.  
  16. static pascal void dimTextProc( short byteCnt, Ptr textAddr,
  17.         Point numerPt, Point denomPt );
  18.  
  19. /*    ---------------------------------------------------------------------
  20.     dimText.c            This is a group of routines for dimming text
  21.                         items in dialogs.  As is, it assumes that you are
  22.                         not using the dialog's refCon for anything else,
  23.                         and that you are not using the QuickDraw
  24.                         bottlenecks for anything else.
  25.     
  26.     This code can be used freely.  I ask that you tell me about any
  27.     improvements that you think of.
  28.     
  29.     James W. Walker        March 17, 1994
  30.     JWWalker@AOL.com
  31.     76367,2271@compuserve.com
  32.     ---------------------------------------------------------------------
  33. */
  34.  
  35. #define        SYSTEM_6_COMPATIBLE        1
  36.  
  37. typedef struct Dim_list_el {
  38.     short                item_num;
  39.     struct Dim_list_el    *next;
  40.     Rect                bounds;
  41.     Boolean                dim;
  42.     Boolean                editable;
  43. } Dim_list_el;
  44.  
  45. typedef struct {
  46.     Dim_list_el    *dim_list;
  47. #if UNIVERSAL_HEADERS
  48.     QDTextUPP    Old_text_proc;
  49. #else
  50.     pascal void (*Old_text_proc)( short, Ptr, Point, Point );
  51. #endif
  52. #ifdef SYSTEM_6_COMPATIBLE
  53.     Boolean        has_gray_text;
  54.     Boolean        has_CountDITL;
  55. #endif
  56. } Dim_data;
  57.  
  58.  
  59. /*    ---------------------------------------------------------------------
  60.     getDimData        Macro to get the list head.
  61.                         Just used to encapsulate the use of the refCon,
  62.                         so that if you need to store the list head
  63.                         somewhere else you will only need to change this
  64.                         and initDimText.
  65.     ---------------------------------------------------------------------
  66. */
  67. #define    getDimData( dp )        ((Dim_data *) ((WindowPeek)dp)->refCon)
  68.  
  69.  
  70. /*    ---------------------------------------------------------------------
  71.     initDimText        Set up a dialog for dimming text.  Call it once, soon
  72.                     after creating the dialog.
  73.     ---------------------------------------------------------------------
  74. */
  75. void initDimText( DialogPtr dp )
  76. {
  77.     Dim_data    *dim_data_p;
  78.     QDProcs        *qd_procs;
  79.     long        val;
  80.     
  81.     dim_data_p = (Dim_data *) NewPtrClear( sizeof(Dim_data) );
  82.     if (dim_data_p)
  83.     {
  84.         // Store the pointer where we can find it later
  85.         ((WindowPeek)dp)->refCon = (long) dim_data_p;
  86.         
  87.         // Patch the QuickDraw bottleneck for text
  88.         if ( (dp->portBits.rowBytes & 0x8000) == 0 )    // B&W port
  89.         {
  90.             qd_procs = (QDProcs *) NewPtrSysClear( sizeof(QDProcs) );
  91.             SetStdProcs( qd_procs );
  92.         }
  93.         else    // color port
  94.         {
  95.             qd_procs = (QDProcs *) NewPtrSysClear( sizeof(CQDProcs) );
  96.             SetStdCProcs( (CQDProcs *) qd_procs );
  97.         }
  98. #if UNIVERSAL_HEADERS
  99.         dim_data_p->Old_text_proc = qd_procs->textProc;
  100.         qd_procs->textProc = NewQDTextProc( dimTextProc );
  101. #else
  102.         dim_data_p->Old_text_proc =
  103.             (pascal void (*)(short, Ptr, Point, Point)) qd_procs->textProc;
  104.         qd_procs->textProc = (QDPtr) dimTextProc;
  105. #endif
  106.         dp->grafProcs = qd_procs;
  107.         
  108. #if SYSTEM_6_COMPATIBLE
  109.         // Which System 7 features are available?
  110.         dim_data_p->has_gray_text =
  111.             (Gestalt( gestaltQuickdrawFeatures, &val ) == noErr)
  112.             && ( (val & (1L << gestaltHasGrayishTextOr)) != 0 );
  113.         dim_data_p->has_CountDITL =
  114.             (Gestalt( gestaltDITLExtAttr, &val ) == noErr)
  115.             && ( (val & (1L << gestaltDITLExtPresent)) != 0 );
  116. #endif        
  117.  
  118.         makeDimmable( dp );
  119.     }
  120. }
  121.  
  122. /*    ---------------------------------------------------------------------
  123.     disposeDimText        Called once after you are through with a dialog.
  124.     ---------------------------------------------------------------------
  125. */
  126. void disposeDimText( DialogPtr dp )
  127. {
  128.     Ptr        maybe_null;
  129.     
  130.     disposeDimData( dp );
  131.     maybe_null = (Ptr) getDimData(dp);
  132.     if (maybe_null)
  133.         DisposePtr( maybe_null );
  134.     if (dp->grafProcs)
  135.     {
  136. #if UNIVERSAL_HEADERS
  137.         DisposeRoutineDescriptor( qd_procs->textProc );
  138. #endif
  139.         DisposePtr( (Ptr) dp->grafProcs );
  140.     }
  141.     dp->grafProcs = NULL;
  142. }
  143.  
  144. /*    ---------------------------------------------------------------------
  145.     dimText        Set the dimming state of a text item.
  146.     ---------------------------------------------------------------------
  147. */
  148. void dimText( DialogPtr dp, short item, Boolean dim )
  149. {
  150.     Dim_data    *dim_head;
  151.     Dim_list_el    *dimmable;
  152.     Rect        iRect;
  153.     Handle        iHandle;
  154.     short        iType;
  155.     short        disable_flag;
  156.     
  157.     dim_head = getDimData(dp);
  158.     if (dim_head != NULL)
  159.     {
  160.         dimmable = dim_head->dim_list;
  161.         // Try to find the right item number in the list.
  162.         while ( (dimmable != NULL) && (dimmable->item_num != item) )
  163.         {
  164.             dimmable = dimmable->next;
  165.         }
  166.         if (dimmable != NULL)    // found it...
  167.         {
  168.             dimmable->dim = dim;
  169.             GetDItem( dp, item, &iType, &iHandle, &iRect );
  170.             if (dimmable->editable)
  171.             {
  172.                 /*
  173.                     To dim an editable text item, we need to turn it
  174.                     into a static text item, and also take some care
  175.                     that it is not showing the insertion point or a
  176.                     selection range.
  177.                 */
  178.                 disable_flag = iType & itemDisable;
  179.                 if (dim)
  180.                 {
  181.                     TEDeactivate( ((DialogPeek) dp)->textH );
  182.                     if (item == ((DialogPeek) dp)->editField + 1 )
  183.                     {
  184.                         SelIText( dp, item, 0, 0 );
  185.                         ((DialogPeek) dp)->editField = -1;
  186.                     }
  187.                     SetDItem( dp, item, statText | disable_flag,
  188.                         iHandle, &iRect );
  189.                     ((DialogPeek) dp)->editField = -1;
  190.                     TEActivate( ((DialogPeek) dp)->textH );
  191.                     InvalRect( &iRect );
  192.                 }
  193.                 else
  194.                 {
  195.                     SetDItem( dp, item, editText | disable_flag,
  196.                         iHandle, &iRect );
  197.                     SelIText( dp, item, 0, 0 );
  198.                     EraseRect( &iRect );
  199.                     TEUpdate( &iRect, ((DialogPeek) dp)->textH );
  200.                 }
  201.             }
  202.             else
  203.             {
  204.                 InvalRect( &iRect );
  205.             }
  206.         }
  207.     }
  208. }
  209.  
  210.  
  211. /*    ---------------------------------------------------------------------
  212.     disposeDimData            Dispose of the individual dimming items.
  213.                             This is called by disposeDimText, so you will
  214.                             not ordinarily have to call it directly
  215.                             unless you are changing item lists
  216.                             dynamically using ShortenDITL and AppendDITL.
  217.     ---------------------------------------------------------------------
  218. */
  219. void disposeDimData( DialogPtr dp )
  220. {
  221.     Dim_data    *dim_head;
  222.     Dim_list_el    *next;
  223.     
  224.     dim_head = getDimData(dp);
  225.     while (dim_head->dim_list != NULL)
  226.     {
  227.         EraseRect( &dim_head->dim_list->bounds );
  228.         next = dim_head->dim_list->next;
  229.         DisposePtr( (Ptr) dim_head->dim_list );
  230.         dim_head->dim_list = next;
  231.     }
  232. }
  233.  
  234. /*    ---------------------------------------------------------------------
  235.     makeDimmable            Makes all text items in the dialog dimmable,
  236.                             both static and editable text.  Called by
  237.                             initDimText(), so you would not normally need
  238.                             to call it directly.
  239.                             But if you change the item list using
  240.                             ShortenDITL and AppendDITL, you would call
  241.                             disposeDimData() before the change and call
  242.                             makeDimmable() after the change.
  243.     ---------------------------------------------------------------------
  244. */
  245. void makeDimmable( DialogPtr dp )
  246. {
  247.     Dim_data    *dim_head;
  248.     Dim_list_el    *new_dim;
  249.     Rect        iRect;
  250.     Handle        iHandle;
  251.     short        iType, item, max_item;
  252.     
  253.     dim_head = getDimData(dp);
  254.     if (dim_head != NULL)
  255.     {
  256. #if SYSTEM_6_COMPATIBLE
  257.         if (dim_head->has_CountDITL)
  258.         {
  259.             max_item = CountDITL( dp );
  260.         }
  261.         else
  262.         {
  263.             max_item = (**(short **) (((DialogPeek) dp)->items)) + 1;
  264.         }
  265. #else
  266.         max_item = CountDITL( dp );
  267. #endif
  268.         
  269.         for (item = max_item; item > 0; --item)
  270.         {
  271.             GetDItem( dp, item, &iType, &iHandle, &iRect );
  272.             if ( (iType & (statText | editText)) != 0 )
  273.             {
  274.                 new_dim = (Dim_list_el *) 
  275.                     NewPtrClear( sizeof(Dim_list_el) );
  276.                 if (new_dim)
  277.                 {
  278.                     new_dim->next = dim_head->dim_list;
  279.                     dim_head->dim_list = new_dim;
  280.                     new_dim->item_num = item;
  281.                     new_dim->editable = (iType & editText) != 0;
  282.                     new_dim->bounds = iRect;
  283.                     if (new_dim->editable)
  284.                     {
  285.                         InsetRect( &new_dim->bounds, -3, -3 );
  286.                     }
  287.                 }
  288.             }
  289.         }
  290.     }
  291. }
  292.  
  293.  
  294. /*    ---------------------------------------------------------------------
  295.     dimTextProc                The QuickDraw bottleneck routine that does
  296.                             the actual dimming, and also draws the frame
  297.                             around dimmed editable text.
  298.     ---------------------------------------------------------------------
  299. */
  300. static pascal void dimTextProc( short byteCnt, Ptr textAddr,
  301.         Point numerPt, Point denomPt )
  302. {
  303.     short            item_num;
  304.     DialogPtr        dp;
  305.     Dim_list_el        *dimmable;
  306.     Dim_data        *dim_head;
  307.     Rect            gray_rect;
  308.     RgnHandle        save_clip;
  309.     PenState        save_pen;
  310.     
  311.     GetPort( &dp );
  312.     GetPenState( &save_pen );
  313.     dim_head = getDimData( dp );
  314.     item_num = FindDItem( dp, dp->pnLoc ) + 1;
  315.     dimmable = dim_head->dim_list;
  316.     while ( (dimmable != NULL) && (dimmable->item_num != item_num) )
  317.     {
  318.         dimmable = dimmable->next;
  319.     }
  320.     if ( (dimmable != NULL) && (dimmable->dim) )
  321.     {
  322. #if SYSTEM_6_COMPATIBLE
  323.         if (dim_head->has_gray_text)
  324. #endif
  325.         {
  326.             TextMode( grayishTextOr );
  327.         }
  328.         if (dimmable->editable)
  329.         {
  330.             save_clip = NewRgn();
  331.             GetClip( save_clip );
  332.             ClipRect( &dimmable->bounds );
  333.             FrameRect( &dimmable->bounds );
  334.             SetClip( save_clip );
  335.             DisposeRgn( save_clip );
  336.         }
  337.     }
  338.  
  339. #if UNIVERSAL_HEADERS
  340.     CallQDTextProc( dim_head->Old_text_proc, byteCnt, textAddr,
  341.         numerPt, denomPt );
  342. #else
  343.     dim_head->Old_text_proc( byteCnt, textAddr, numerPt, denomPt );
  344. #endif
  345.  
  346. #if SYSTEM_6_COMPATIBLE    
  347.     if ( !dim_head->has_gray_text && (dimmable != NULL) && dimmable->dim )
  348.     {
  349.         gray_rect = dimmable->bounds;
  350.         InsetRect( &gray_rect, 1, 1 );
  351.         PenMode( patBic );
  352.         /*
  353.             The reason I used a string literal rather than the QuickDraw
  354.             global gray is so that it can be used in a code resource
  355.             without problems.
  356.         */
  357.         PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55" );
  358.         PaintRect( &gray_rect );
  359.     }
  360. #endif
  361.     SetPenState( &save_pen );
  362. }
  363.