home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / LOBE.src.sit / LOBE.src / ShowIcon7.c < prev    next >
Text File  |  1994-12-18  |  8KB  |  251 lines

  1.  
  2. /* If you don't define SystemSixOrLater, you will need to link against */
  3. /* the library version of SysEnvirons */
  4.  
  5. #define SystemSixOrLater 1
  6.  
  7. #include <Icons.h>
  8. #include <OSUtils.h>
  9. #include <Resources.h>
  10. #include <Memory.h>
  11.  
  12. /*
  13.     ShowIcon7.c
  14.     
  15.     ShowINIT compatible routine that shows 'ICN#' and 'iclx' flavor icons.
  16.     For use by all INITs in System 7 and beyond.
  17.     
  18.     This code is based on Patrick C. Beard's ShowIconFamily
  19.     by Patrick C. Beard, which in turn was derived from the
  20.     original ShowInit by Paul Mercer, Darin Adler,
  21.     Paul Snively, and Steve Capps.
  22.     
  23.     Modified by James W. Walker for compatibility with IconWrap 1.2,
  24.     for use as a separate code resource, and to use the new System 7
  25.     icon-drawing routines.  This code is in the public domain.
  26.     
  27.     Dec 17, 1994 - Modified to work with MPW and universal headers.
  28.     IconFamilies.h is now offically called 'Icons.h'. QDGlobals
  29.     is now an official type. Removed inline assembly to rotate a
  30.     word left. -- Charlie Reiman
  31.     
  32.     Addresses for James W. Walker: 76367,2271@compuserve.com or
  33.         walkerj@math.scarolina.edu
  34.     
  35.     Instructions for use:
  36.     
  37.         ・ Create a family of icons with ResEdit 2.1 or later.  This will
  38.             include 'ICN#', 'icl4', & 'icl8' icons, all with the
  39.             same resource ID.
  40.         
  41.         To use within a larger INIT project:
  42.             ・ #define SEPARATE_CODE 0  below.
  43.             ・ Call ShowIcon7( id, adv ) with the resource id of
  44.                 the family that you used.  The Boolean parameter adv
  45.                 indicates whether you want the next use of ShowIcon7
  46.                 to advance to a new position.  Normally you pass TRUE,
  47.                 but you can get an animated-icon effect by passing FALSE
  48.                 all except the last time you call ShowIcon7.
  49.         
  50.         To use as a separate code resource:
  51.             ・ #define SEPARATE_CODE 1  below.
  52.             ・ Set the project type to code resource, set the code type
  53.                 and resource ID (I use type 'Code', ID -4048 for cdevs),
  54.                 compile and merge into your INIT or cdev file.
  55.                 Set the resource type to Locked, so you won't have
  56.                 to call HLock when you use it.
  57.             ・ In your main INIT code, call ShowIcon7 like so:
  58.                 pascal void (*ShowIcon7)( short resid, Boolean adv );
  59.                 Handle  show_init;
  60.                 
  61.                 show_init = GetResource( 'Code', -4048 );
  62.                 ShowIcon7 = (pascal void (*)(short, Boolean))
  63.                             StripAddress( *show_init );
  64.                 ShowIcon7( iconID, advance );
  65.  */
  66.  
  67. #define SEPARATE_CODE    0
  68.  
  69.  
  70. #if SEPARATE_CODE
  71. #define        ShowIcon7        main    /* JWW */
  72. #endif
  73.  
  74. #ifndef nil
  75. #define nil ((void*)0L)
  76. #endif
  77.  
  78. #ifndef topLeft
  79.     #define topLeft(r) ((Point*)&r)[0])
  80. #endif
  81. #ifndef botRight
  82.     #define botRight(r) ((Point*)&r)[1])
  83. #endif
  84.  
  85. typedef struct myQDGlobals {
  86.     QDGlobals    theGlobals;
  87.     long        end;        /* a5 points here */
  88. } myQDGlobals;                /* CJR */
  89.  
  90. /* prototypes */
  91. pascal void ShowIcon7(short iconId, Boolean advance);
  92. static void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible );
  93. static void Next_position( void );
  94. static void GetIconRect( register Rect* iconRect, Rect *screen_rect );
  95.  
  96. /* this is where it all happens. */
  97.  
  98. pascal void ShowIcon7( short iconId, Boolean advance )
  99. {
  100.     long    oldA5;
  101.     myQDGlobals qd;                /* our QD globals. */
  102.     SysEnvRec environment;        /* machine configuration. */
  103.     CGrafPort gp;                /* our grafport. */
  104.     Rect    icon_rect;
  105.     OSErr    err;
  106.     
  107.     /* get a value for A5, a structure that mirrors qd globals. */
  108.     oldA5 = SetA5((long)&qd.end);
  109.     InitGraf(&qd.theGlobals.thePort);
  110.     
  111.     /* find out what kind of machine this is. */
  112.     SysEnvirons(curSysEnvVers, &environment);
  113.  
  114.     GetIconRect( &icon_rect, &qd.theGlobals.screenBits.bounds );
  115.  
  116.     /*
  117.         The old IconWrap INIT patches CopyBits but does not know about
  118.         CopyMask or IconDispatch.  So in the color case, we draw the
  119.         black and white icon with an empty mask region.
  120.     */
  121.  
  122.     if ( (environment.systemVersion >= 0x0700) && environment.hasColorQD )
  123.     {
  124.         OpenCPort(&gp);
  125.         DrawBWIcon( iconId, &icon_rect, false );
  126.         err = PlotIconID( &icon_rect, atNone, ttNone, iconId );
  127.         CloseCPort(&gp);
  128.     }
  129.     else
  130.     {
  131.         OpenPort((GrafPtr)&gp);
  132.         DrawBWIcon( iconId, &icon_rect, true );
  133.         ClosePort((GrafPtr)&gp);
  134.     }
  135.     
  136.     if (advance)
  137.         Next_position(); /* JWW */
  138.  
  139.     SetA5(oldA5);
  140. }
  141.  
  142. /*
  143.     ShowInit's information is nestled at the tail end of CurApName.
  144.     It consists of a short which encodes the next horizontal offset,
  145.     and another short which is that value checksummed with the function below.
  146.  */
  147.  
  148. #define CurApName_LM    0x910
  149. #define ShowINITTable ((short*)(CurApName_LM + 32 - 4))
  150. #define CheckSumConst 0x1021        /* magic value to check-sum with. */
  151.  
  152. #define InitialXPosition 8            /* initial horizontal offset. */
  153. #define YOffset            40            /* constant from bottom to place the icon. */
  154. #define XOffset            40            /* amount to change it by. */
  155. #define ICON_WIDTH        32
  156. #define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
  157.  
  158. /* CheckSum() computes the magic value to determine if ShowInit's have run already. */
  159.  
  160. static short CheckSum(short x)
  161. {
  162.     register unsigned short y = x;
  163.     y = ( y >> 15 ) + (y << 1);    /* CJR -- was asm { rol.w #1, x } */
  164.     return (y ^ CheckSumConst);
  165. }
  166.  
  167. /*
  168.     GetIconRect() generates an appropriate rectangle to display the
  169.     next INIT's icon in.
  170.     It is also responsible for updating the horizontal
  171.     position in low memory.  This is a departure from
  172.     the original ShowInit code, which updates low
  173.     memory AFTER displaying the icon. -- changed by JWW
  174.     This code won't generate an icon position until it is certain that the icon can be loaded, so the
  175.     same behaviour occurs.
  176.     
  177.     This routine also generates a rectangle which is guaranteed to be onscreen.  It
  178.     does this by taking the horizontal offset modulo the screen width to generate
  179.     the horizontal position of the icon, and the offset divided by the screen
  180.     width to generate the proper row.
  181.  */
  182.  
  183. static void GetIconRect(register Rect* iconRect, Rect *screen_rect )
  184. {
  185.     register short screenWidth;
  186.     
  187.     screenWidth = screen_rect->right - screen_rect->left;
  188.     screenWidth -= screenWidth % XOffset;
  189.     /* if we are the first INIT to run we need to initialize the horizontal value. */
  190.     if (CheckSum(ShowINITTable[0]) != ShowINITTable[1])
  191.         ShowINITTable[0] = InitialXPosition;
  192.     
  193.     /* compute top left of icon's rect. */
  194.     iconRect->left = (ShowINITTable[0] % screenWidth);
  195.     iconRect->top = screen_rect->bottom -
  196.         YOffset * (1 + (ShowINITTable[0] / screenWidth));
  197.     iconRect->right = iconRect->left + 32;
  198.     iconRect->bottom = iconRect->top + 32;
  199.     
  200. }
  201.  
  202. /*
  203.     JWW: In Beard's original version, this was done at the end of
  204.     GetIconRect. That caused incorrect behavior when IconWrap 1.2 was
  205.     used to wrap icons.  Namely, if an INIT using that version of
  206.     ShowIconFamily was the first in a row, then the second icon in that
  207.     row would land on top of it.
  208. */
  209. static void Next_position( void )
  210. {
  211.     /* advance the position for the next icon. */
  212.     ShowINITTable[0] += XOffset;
  213.     
  214.     /* recompute the checksum. */
  215.     ShowINITTable[1] = CheckSum(ShowINITTable[0]);    
  216. }
  217.  
  218. /* DrawBWIcon() draws the 'ICN#' member of the icon family. */
  219.  
  220. void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible )
  221. {
  222.     Handle        icon;
  223.     BitMap        source, destination;
  224.     RgnHandle    empty_mask;
  225.     GrafPtr        port;
  226.     
  227.     icon = (Handle)Get1Resource('ICN#', iconId);
  228.     if (!icon)
  229.         return;
  230.     HLock(icon);
  231.     
  232.     /* prepare the source and destination bitmaps. */
  233.     source.baseAddr = *icon + 128;                    /* mask address. */
  234.     source.rowBytes = 4;
  235.     SetRect(&source.bounds, 0, 0, 32, 32);
  236.     GetPort( &port );
  237.     destination = ((GrafPtr)port)->portBits;
  238.     empty_mask = visible? nil : NewRgn();
  239.     
  240.     /* transfer the mask. */
  241.     CopyBits(&source, &destination, &source.bounds, icon_rect,
  242.         srcBic, empty_mask);
  243.     
  244.     /* and the icon. */
  245.     source.baseAddr = *icon;    
  246.     CopyBits(&source, &destination, &source.bounds, icon_rect,
  247.         srcOr, empty_mask);
  248.     
  249.     if (empty_mask) DisposeRgn( empty_mask );
  250. }
  251.