appletquickdraw.c

Go to the documentation of this file.
00001 
00002 /*  $Id: appletquickdraw.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /* copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
00005 
00006 
00007 #include <GestaltEqu.h>
00008 #include <Palettes.h>
00009 #include <QDOffscreen.h>
00010 #include "appletdefs.h"
00011 #include "appletfont.h"
00012 #include "appletmemory.h"
00013 #include "appletquickdraw.h"
00014 
00015 /*
00016 7/25/94 dmb: updated old-style function declarations
00017 */
00018 
00019 RGBColor whitecolor = {65535, 65535, 65535};
00020 
00021 RGBColor blackcolor = {0, 0, 0};
00022 
00023 RGBColor lightbluecolor = {52428, 52428, 65535};
00024 
00025 RGBColor darkbluecolor = {0, 0, 32767};
00026 
00027 RGBColor darkgraycolor = {10922, 10922, 10922};
00028 
00029 RGBColor graycolor = {32767, 32767, 32767};
00030 
00031 RGBColor mediumgraycolor = {52428, 52428, 52428};
00032 
00033 RGBColor lightgraycolor = {61166, 61166, 61166};
00034 
00035 RGBColor lightyellowcolor = {65535, 65535, 52428};
00036 
00037 RGBColor lightgreencolor = {52428, 65535, 52428};
00038 
00039 RGBColor lightpurplecolor = {65535, 52428, 65535};
00040 
00041 RGBColor darkpurplecolor = {16384, 0, 16384};
00042 
00043 RGBColor lightredcolor = {65535, 52428, 52428};
00044 
00045 RGBColor darkredcolor = {32767, 0, 0};
00046 
00047 RGBColor darkgreencolor = {0, 32767, 0};
00048 
00049 typedef char smalliconbits [32];
00050 
00051 typedef smalliconbits *ptrsmalliconbits, **hdlsmalliconbits;
00052 
00053 
00054 #define useoffscreenworlds
00055 
00056 
00057 #ifdef useoffscreenworlds
00058 
00059     static boolean flhas32bitqd = false; /*32-bit quickdraw implemented?*/
00060     
00061     typedef struct tyoffscreen {
00062         
00063         boolean flbitmapopen;
00064         
00065         CGrafPtr psavedport;
00066         
00067         GDHandle hsavedgd;
00068         
00069         GWorldPtr poffscreenworld;
00070         
00071         Rect offscreenrect;
00072         
00073         Handle bitmapbasehandle;
00074         
00075         BitMap offscreenbitmap, savedbitmap;
00076         } tyoffscreen;
00077     
00078     static tyoffscreen bitoffscreen = {false, nil, nil, nil, {0, 0, 0, 0}, nil};
00079 
00080 #else
00081 
00082     typedef struct tyoffscreen {
00083     
00084         GDHandle origdevice;
00085         
00086         GrafPtr offptr;
00087         
00088         Rect offrect;
00089         
00090         boolean flsuccess;
00091         } tyoffscreen;
00092     
00093     static tyoffscreen bitoffscreen;
00094     
00095     typedef BitMap *typtrbitmap;
00096 
00097 #endif
00098 
00099 
00100 #define ctpens 5 /*we can remember pens up to 5 levels deep*/
00101 
00102 short toppens = 0;
00103 
00104 PenState penstack [ctpens];
00105 
00106 
00107 #define ctports 25 /*we can remember ports up to 25 levels deep*/
00108 
00109 short topport = 0;
00110 
00111 GrafPtr portstack [ctports];
00112 
00113 
00114 #define ctclip 5 /*we can remember clips up to 5 levels deep*/
00115 
00116 short topclip = 0;
00117 
00118 Rect clipstack [ctclip];
00119 
00120 
00121 #define ctstyle 5 /*we can remember font/size/styles up to 5 levels deep*/
00122 
00123 short topstyle = 0;
00124 
00125 struct {short fnum, fsize, fstyle;} stylestack [ctstyle];
00126 
00127 
00128 #define ctforecolors 5
00129 
00130 short topforecolor = 0;
00131 
00132 RGBColor forecolorstack [ctforecolors];
00133 
00134 
00135 #define ctbackcolors 5
00136 
00137 short topbackcolor = 0;
00138 
00139 RGBColor backcolorstack [ctbackcolors];
00140 
00141 
00142 
00143 
00144 
00145 boolean pushpen () {
00146     
00147     if (toppens >= ctpens)
00148         return (false);
00149         
00150     GetPenState (&penstack [toppens++]);
00151     
00152     return (true);
00153     } /*pushpen*/
00154     
00155 
00156 boolean poppen () {
00157     
00158     if (toppens <= 0)
00159         return (false);
00160         
00161     SetPenState (&penstack [--toppens]);
00162     
00163     return (true);
00164     } /*poppen*/
00165     
00166 
00167 boolean pushmacport (GrafPtr p) {
00168     
00169     if (topport >= ctports) {
00170         
00171         DebugStr ((ConstStr255Param)"\ppushmacport: no room on stack");
00172         
00173         return (false);
00174         }
00175 
00176     portstack [topport++] = quickdrawglobal (thePort);
00177     
00178     if (p != nil)
00179         SetPort (p);
00180         
00181     return (true);
00182     } /*pushmacport*/
00183         
00184 
00185 boolean popmacport () {
00186     
00187     if (topport <= 0) 
00188         return (false);
00189     
00190     SetPort (portstack [--topport]);
00191     
00192     return (true);
00193     } /*popmacport*/
00194 
00195 
00196 boolean pushclip (Rect r) {
00197     
00198     RgnHandle rgn;
00199     
00200     if (topclip >= ctclip)
00201         return (false);
00202     
00203     GetClip (rgn = NewRgn ());
00204     
00205     clipstack [topclip++] = (**rgn).rgnBBox;
00206     
00207     DisposeRgn (rgn);
00208     
00209     ClipRect (&r);
00210     
00211     return (true);
00212     } /*pushclip*/
00213         
00214 
00215 boolean popclip () {
00216     
00217     if (topclip <= 0)
00218         return (false);
00219     
00220     ClipRect (&clipstack [--topclip]);
00221     
00222     return (true);
00223     } /*popclip*/
00224 
00225 
00226 boolean pushstyle (short fnum, short fsize, short fstyle) {
00227     
00228     if (topstyle >= ctstyle)
00229         return (false);
00230         
00231     getfontsizestyle (
00232         &stylestack [topstyle].fnum, 
00233         
00234         &stylestack [topstyle].fsize, 
00235         
00236         &stylestack [topstyle].fstyle);
00237     
00238     topstyle++;
00239     
00240     setglobalfontsizestyle (fnum, fsize, fstyle);
00241     
00242     return (true);
00243     } /*pushstyle*/
00244         
00245 
00246 boolean popstyle (void) {
00247     
00248     if (topstyle <= 0)
00249         return (false);
00250     
00251     topstyle--;
00252     
00253     setfontsizestyle (
00254         stylestack [topstyle].fnum, 
00255         
00256         stylestack [topstyle].fsize, 
00257         
00258         stylestack [topstyle].fstyle);
00259         
00260     return (true);
00261     } /*popstyle*/
00262 
00263 
00264 short getmenubarheight (void) {
00265     
00266     return (GetMBarHeight ()); /*call Script Manager routine*/
00267     } /*getmenubarheight*/
00268 
00269 
00270 void setrect (Rect *rset, short top, short left, short bottom, short right) {
00271     
00272     Rect *r = rset;
00273     
00274     (*r).top = top;
00275     
00276     (*r).left = left;
00277     
00278     (*r).bottom = bottom;
00279     
00280     (*r).right = right;
00281     } /*setrect*/
00282     
00283     
00284 void localtoglobalrect (Rect *rchanged) {
00285 
00286     Point p1, p2;
00287     Rect r;
00288     
00289     r = *rchanged;
00290     
00291     p1.h = r.left;
00292     
00293     p1.v = r.top;
00294     
00295     LocalToGlobal (&p1);
00296     
00297     p2.h = r.right;
00298     
00299     p2.v = r.bottom;
00300     
00301     LocalToGlobal (&p2);
00302     
00303     Pt2Rect (p1, p2, &r);
00304     
00305     *rchanged = r;
00306     } /*localtoglobalrect*/
00307     
00308     
00309 void eraserect (Rect r) {
00310     
00311     EraseRect (&r);
00312     } /*eraserect*/
00313     
00314     
00315 void movepento (short h, short v) {
00316     
00317     MoveTo (h, v);
00318     } /*movepento*/
00319     
00320     
00321 void pendrawline (short h, short v) {
00322     
00323     LineTo (h, v);
00324     } /*pendrawline*/
00325     
00326     
00327 void invalrect (Rect r) {
00328     
00329     if (r.left >= r.right)
00330         return;
00331         
00332     if (r.top >= r.bottom)
00333         return;
00334         
00335     InvalRect (&r);
00336     } /*invalrect*/
00337     
00338 
00339 void smashrect (Rect r) {
00340     
00341     eraserect (r);
00342     
00343     invalrect (r);
00344     } /*smashrect*/
00345     
00346 
00347 void insetrect (Rect *r, short dh, short dv) {
00348     
00349     InsetRect (r, dh, dv);
00350     } /*insetrect*/
00351     
00352     
00353 boolean equalpoints (Point p1, Point p2) {
00354     
00355     return (EqualPt (p1, p2));
00356     } /*equalpoints*/
00357     
00358     
00359 boolean emptyrect (Rect r) {
00360     
00361     /*
00362     return false if there are any pixels contained inside the rectangle.
00363     */
00364     
00365     return ((r.top >= r.bottom) || (r.left >= r.right));
00366     } /*emptyrect*/
00367     
00368     
00369 boolean rectlessthan (Rect r1, Rect r2) {
00370     
00371     /*
00372     return true if r1 is "less than" r2.
00373     
00374     we look only at the top-left corners of the rectangles. a rectangle is
00375     less than the other rectangle if it's above the other guy vertically.
00376     
00377     if they're both at the same vertical position, then the guy to the left
00378     of the other is less than.
00379     
00380     this helps us implement a rational sort of tabbing thru objects, we go
00381     from top to bottom and left to right.
00382     */
00383     
00384     if (r1.top != r2.top) { /*comparison is based on tops*/
00385         
00386         return (r1.top < r2.top);
00387         }
00388     
00389     return (r1.left < r2.left);
00390     } /*rectlessthan*/
00391     
00392     
00393 static short absint (short x) {
00394     
00395     if (x < 0)
00396         x = -x;
00397         
00398     return (x);
00399     } /*absint*/
00400     
00401     
00402 short pointdist (Point pt1, Point pt2) {
00403     
00404     return (absint (pt1.h - pt2.h) + absint (pt1.v - pt2.v));
00405     } /*pointdist*/
00406 
00407 
00408 void centerrect (Rect *rcentered, Rect rcontains) {
00409     
00410     /*
00411     center the first rectangle within the second rectangle.
00412     */
00413     
00414     short height, width;
00415     Rect r;
00416     
00417     r = *rcentered;
00418     
00419     width = r.right - r.left;
00420     
00421     r.left = rcontains.left + ((rcontains.right - rcontains.left - width) / 2);
00422     
00423     r.right = r.left + width;
00424     
00425     height = r.bottom - r.top;
00426     
00427     r.top = rcontains.top + ((rcontains.bottom - rcontains.top - height) / 2);
00428     
00429     r.bottom = r.top + height;
00430     
00431     *rcentered = r;
00432     } /*centerrect*/
00433 
00434 
00435 void dropshadowrect (Rect rorig, short width, boolean flerase) {
00436     
00437     /*
00438     draw a drop-shadow to the right and below the indicated rectangle.  if flerase,
00439     then we fill the drop shadow area with white.
00440     */
00441     
00442     Rect r = rorig;
00443     short h, v;
00444     short i;
00445     
00446     if (flerase) {
00447         
00448         pushpen ();
00449         
00450         PenMode (patBic);
00451         }
00452         
00453     for (i = 0; i < width; i++) {
00454         
00455         h = r.right + i;
00456         
00457         MoveTo (h, r.top + i + 1);
00458         
00459         LineTo (h, r.bottom + width - 1);
00460         
00461         v = r.bottom + i;
00462         
00463         MoveTo (r.left + i + 1, v);
00464         
00465         LineTo (r.right + width - 1, v);
00466         } /*for*/
00467         
00468     if (flerase)
00469         poppen ();
00470     } /*dropshadowrect*/ 
00471     
00472     
00473 void invaldropshadow (Rect r, short width) {
00474     
00475     /*
00476     inval the rectangle and it's drop shadow.
00477     
00478     5/6/92 DW: work around IOWA problem when the drop shadow shrinks, there's
00479     no convenient way to inval the old drop shadow. if you ever decrease the
00480     drop shadow by more than 5 pixels you'll have to do a complete update.
00481     */
00482     
00483     r.right += width + 5;
00484     
00485     r.bottom += width + 5;
00486     
00487     InvalRect (&r);
00488     } /*invaldropshadow*/
00489     
00490 
00491 #define gestalttrap         0xA1AD
00492 #define unimplementedtrap   0xA09F
00493 
00494 
00495 static boolean gestaltavailable (void) {
00496 
00497     UniversalProcPtr gestaltaddr;
00498     UniversalProcPtr unimplementedaddr;
00499 
00500     gestaltaddr = NGetTrapAddress (gestalttrap, ToolTrap);
00501     
00502     unimplementedaddr = NGetTrapAddress (unimplementedtrap, ToolTrap);
00503     
00504     return (unimplementedaddr != gestaltaddr);  
00505     } /*gestaltavailable*/
00506     
00507     
00508 static boolean getgestaltattr (OSType selector, long *response) {
00509     
00510     OSErr errcode;
00511     
00512     if (!gestaltavailable ())
00513         return (false);
00514         
00515     errcode = Gestalt (selector, response);
00516     
00517     return (errcode == noErr);
00518     } /*getgestaltattr*/
00519     
00520     
00521 boolean systemhascolor (void) {
00522     
00523     static boolean flgotit = false;
00524     static boolean flhavecolor = false;
00525     
00526     if (!flgotit) {
00527     
00528         long templong;
00529     
00530         if (!getgestaltattr (gestaltQuickdrawVersion, &templong))
00531             flhavecolor = false;
00532         else
00533             flhavecolor = templong >= gestalt8BitQD;
00534             
00535         flgotit = true;
00536         }
00537     
00538     return (flhavecolor);
00539     } /*systemhascolor*/
00540 
00541 
00542 static short maxdepth (void) {
00543 
00544     GDHandle hdldevice;
00545 
00546     if (!systemhascolor ())
00547         return (1);
00548         
00549     hdldevice = GetMaxDevice (&quickdrawglobal (screenBits).bounds);
00550 
00551     if (hdldevice == nil)
00552         return (1);
00553         
00554     return ((**(**hdldevice).gdPMap).pixelSize);
00555     } /*maxdepth*/
00556     
00557     
00558 boolean colorenabled (void) {
00559 
00560     if (!systemhascolor ())
00561         return (false);
00562         
00563     return (maxdepth () > 1);
00564     } /*colorenabled*/
00565     
00566     
00567 static short iscolorport (GrafPtr pport) {
00568 
00569     return ((*(CGrafPtr) pport).portVersion < 0);
00570     } /*iscolorport*/
00571 
00572 
00573 static boolean getclut (short resid, CTabHandle *hdlctab) {
00574     
00575     Handle hdata;
00576     
00577     *hdlctab = nil;
00578     
00579     hdata = GetResource ('clut', resid);
00580     
00581     if (ResError () != noErr)
00582         return (false);
00583     
00584     *hdlctab = (CTabHandle) hdata;
00585     
00586     return (true);
00587     } /*getclut*/
00588 
00589 
00590 boolean oldclutconverter (short index, RGBColor *rgb) {
00591 
00592     CTabHandle hdlctab;
00593 
00594     getclut (128, &hdlctab);
00595     
00596     *rgb = (**hdlctab).ctTable [index].rgb;
00597 
00598     return (true);
00599     } /*oldclutconverter*/
00600     
00601     
00602 boolean pushforecolor (RGBColor *rgb) {
00603         
00604     if (colorenabled ()) {
00605     
00606         if (topforecolor >= ctforecolors) {
00607             
00608             DebugStr ((ConstStr255Param) "\ppushforecolor: no room on stack");
00609             
00610             return (false);
00611             }
00612     
00613         GetForeColor (&forecolorstack [topforecolor++]);
00614                 
00615         /*
00616         3/9/93 DW: copy the rgb record so the caller can pass us the 
00617         address of a field of a heap-allocated record.
00618         */
00619             {
00620             RGBColor rgbcopy = *rgb;
00621             
00622             RGBForeColor (&rgbcopy);
00623             }
00624         }
00625         
00626     return (true);
00627     } /*pushforecolor*/
00628         
00629 
00630 boolean popforecolor (void) {
00631     
00632     if (colorenabled ()) {
00633     
00634         if (topforecolor <= 0) {
00635             
00636             DebugStr ((ConstStr255Param) "\ppopforecolor: nothing on stack");
00637             
00638             return (false);
00639             }
00640         
00641         RGBForeColor (&forecolorstack [--topforecolor]);
00642         }
00643     
00644     return (true);
00645     } /*popforecolor*/
00646     
00647 
00648 boolean pushbackcolor (RGBColor *rgb) {
00649         
00650     if (colorenabled ()) {
00651         
00652         if (topbackcolor >= ctbackcolors) {
00653             
00654             DebugStr ((ConstStr255Param) "\ppushbackcolor: no room on stack");
00655             
00656             return (false);
00657             }
00658         
00659         GetBackColor (&backcolorstack [topbackcolor++]);
00660         
00661         /*
00662         3/9/93 DW: copy the rgb record so the caller can pass us the 
00663         address of a field of a heap-allocated record.
00664         */
00665             {
00666             RGBColor rgbcopy = *rgb;
00667             
00668             RGBBackColor (&rgbcopy);
00669             }
00670         }
00671         
00672     return (true);
00673     } /*pushbackcolor*/
00674         
00675 
00676 boolean popbackcolor (void) {
00677     
00678     if (colorenabled ()) {
00679     
00680         if (topbackcolor <= 0) {
00681             
00682             DebugStr ((ConstStr255Param) "\ppopbackcolor: nothing on stack");
00683             
00684             return (false);
00685             }
00686         
00687         RGBBackColor (&backcolorstack [--topbackcolor]);
00688         }
00689     
00690     return (true);
00691     } /*popbackcolor*/
00692     
00693     
00694 boolean pushcolors (RGBColor *forecolor, RGBColor *backcolor) {
00695     
00696     pushforecolor (forecolor);
00697     
00698     return (pushbackcolor (backcolor));
00699     } /*pushcolors*/
00700     
00701     
00702 boolean popcolors (void) {
00703     
00704     popforecolor ();
00705     
00706     return (popbackcolor ());
00707     } /*popcolors*/
00708     
00709     
00710 boolean equalcolors (RGBColor *rgb1, RGBColor *rgb2) {
00711     
00712     return (    
00713         ((*rgb1).red == (*rgb2).red) && 
00714         
00715         ((*rgb1).green == (*rgb2).green) && 
00716         
00717         ((*rgb1).blue == (*rgb2).blue));
00718     } /*equalcolors*/
00719     
00720     
00721 boolean pushgridcolor (RGBColor *rgbbase) {
00722     
00723     /*
00724     this color is used in drawing the grid in Iowa. we choose something
00725     that we think looks nice when superimposed on the base color. for dark
00726     colors it's brighter, for bright colors its darker. avoid jarring
00727     contrasts.
00728     */
00729     
00730     short diff = 10000;
00731     short maxval = whitecolor.red - diff;
00732     RGBColor rgb = *rgbbase;
00733     
00734     if (equalcolors (&rgb, &whitecolor))
00735         return (pushforecolor (&lightbluecolor));
00736         
00737     if (rgb.red > maxval)
00738         rgb.red -= diff;
00739     else
00740         rgb.red += diff;
00741     
00742     if (rgb.green > maxval)
00743         rgb.green -= diff;
00744     else
00745         rgb.green += diff;
00746     
00747     if (rgb.blue > maxval)
00748         rgb.blue -= diff;
00749     else
00750         rgb.blue += diff;
00751     
00752     return (pushforecolor (&rgb));
00753     } /*pushgridcolor*/
00754     
00755     
00756 boolean pushhighlightcolor (RGBColor *rgbbase) {
00757     
00758     /*
00759     the user is dragging to select a rectangle on the base color.
00760     
00761     we are looking for high contrast between the two colors.
00762     
00763     unfortunately, it doesn't appear to effect the color when
00764     we call this routine. must be something I don't understand about
00765     Color QuickDraw. DW 2/9/93.
00766     */
00767     
00768     unsigned long midpoint = (3 * whitecolor.red) / 2;
00769     RGBColor rgb = *rgbbase;
00770     long sum;
00771     
00772     sum = rgb.red + rgb.blue + rgb.green;
00773     
00774     if (sum > midpoint)
00775         rgb = blackcolor;
00776     else
00777         rgb = whitecolor;
00778         
00779     return (pushforecolor (&rgb));
00780     } /*pushhighlightcolor*/
00781     
00782     
00783 boolean getcolorpalette (WindowPtr w) {
00784 
00785     CTabHandle hclut;
00786     PaletteHandle hpalette;
00787 
00788     getclut (128, &hclut); 
00789             
00790     hpalette = GetPalette (w);
00791     
00792     if (hpalette == nil)
00793         hpalette = NewPalette (32, hclut, pmTolerant, 0x0000);
00794     else
00795         CTab2Palette (hclut, hpalette, pmTolerant, 0x0000);
00796 
00797     SetPalette (w, hpalette, true);
00798     
00799     ActivatePalette (w);
00800     
00801     return (true);
00802     } /*getcolorpalette*/
00803 
00804 
00805 #ifdef useoffscreenworlds
00806 
00807 static boolean openworld (Rect r, WindowPtr w) {
00808     
00809     /*
00810     9/22/93 dmb: use temp mem for offscreens
00811     */
00812     
00813     short fontnum, fontsize, fontstyle;
00814     PenState pen;
00815     
00816     GetGWorld (&bitoffscreen.psavedport, &bitoffscreen.hsavedgd);
00817     
00818     bitoffscreen.offscreenrect = r;
00819     
00820     localtoglobalrect (&r);
00821     
00822     if (bitoffscreen.poffscreenworld) {
00823         
00824         if (UpdateGWorld (&bitoffscreen.poffscreenworld, 0, &r, nil, nil, useTempMem) & gwFlagErr)
00825             return (false);
00826         }
00827     else {
00828         OSErr ec;
00829         
00830         ec = NewGWorld (&bitoffscreen.poffscreenworld, 0, &r, nil, nil, useTempMem); /*doug says turn last param to 0*/
00831         
00832         if (ec != noErr)
00833             return (false);
00834         }
00835     
00836     getfontsizestyle (&fontnum, &fontsize, &fontstyle);
00837     
00838     GetPenState (&pen);
00839     
00840     SetGWorld (bitoffscreen.poffscreenworld, nil);
00841     
00842     LockPixels (bitoffscreen.poffscreenworld->portPixMap);
00843         
00844     setfontsizestyle (fontnum, fontsize, fontstyle);
00845     
00846     SetPenState (&pen);
00847     
00848     SetOrigin (bitoffscreen.offscreenrect.left, bitoffscreen.offscreenrect.top);
00849     
00850     ClipRect (&bitoffscreen.poffscreenworld->portRect); /*recommended by Apple DTS*/
00851     
00852     CopyBits (
00853         &((GrafPtr) bitoffscreen.psavedport)->portBits,
00854         &((GrafPtr) bitoffscreen.poffscreenworld)->portBits,
00855         &bitoffscreen.poffscreenworld->portRect,
00856         &bitoffscreen.offscreenrect, srcCopy, nil);
00857         
00858     return (true);
00859     } /*openworld*/
00860 
00861 
00862 static void closeworld (WindowPtr w) {
00863     
00864     /*
00865     2/8/91 dmb: experiments show that we get better performance tossing 
00866     the gworld every time than we do using updategworld on the same one.
00867     */
00868     
00869     SetGWorld (bitoffscreen.psavedport, bitoffscreen.hsavedgd);
00870     
00871     pushforecolor (&blackcolor);    /* 2.2.96 dmb: need b&w to preserve colors correctly*/
00872     pushbackcolor (&whitecolor);
00873     
00874     CopyBits (
00875         &((GrafPtr) bitoffscreen.poffscreenworld)->portBits, 
00876         &((GrafPtr) bitoffscreen.psavedport)->portBits,
00877         &bitoffscreen.poffscreenworld->portRect, &bitoffscreen.offscreenrect, srcCopy, nil);
00878     
00879     popforecolor ();
00880     popbackcolor ();
00881     
00882     /*
00883     #ifdef coderesource
00884         
00885         DisposeGWorld (bitoffscreen.poffscreenworld);
00886         
00887         bitoffscreen.poffscreenworld = nil;
00888     
00889     #else
00890     
00891         UnlockPixels (bitoffscreen.poffscreenworld->portPixMap);
00892         
00893     #endif
00894     */
00895     
00896     DisposeGWorld (bitoffscreen.poffscreenworld);
00897         
00898     bitoffscreen.poffscreenworld = nil;
00899     } /*closeworld*/
00900 
00901 
00902 static boolean openmono (Rect r, WindowPtr w) {
00903     
00904     short nrowbytes;
00905     long nboxbytes;
00906     
00907     nrowbytes = (r.right - r.left + 7) / 8;
00908     
00909     if (odd (nrowbytes)) 
00910         nrowbytes++;
00911     
00912     nboxbytes = (r.bottom - r.top) * nrowbytes;
00913     
00914     bitoffscreen.bitmapbasehandle = appnewhandle (nboxbytes);
00915     
00916     if (bitoffscreen.bitmapbasehandle == nil)
00917         return (false);
00918     
00919     HLock (bitoffscreen.bitmapbasehandle);
00920     
00921     bitoffscreen.offscreenbitmap.baseAddr = *bitoffscreen.bitmapbasehandle;
00922     
00923     bitoffscreen.offscreenbitmap.rowBytes = nrowbytes;
00924     
00925     bitoffscreen.offscreenbitmap.bounds = r;
00926     
00927     bitoffscreen.savedbitmap = (*w).portBits;
00928     
00929     SetPortBits (&bitoffscreen.offscreenbitmap);
00930     
00931     return (true);
00932     } /*openmono*/
00933 
00934 
00935 static void closemono (WindowPtr w) {
00936     
00937     SetPortBits (&bitoffscreen.savedbitmap);
00938     
00939     CopyBits (
00940         &bitoffscreen.offscreenbitmap, &w->portBits, &bitoffscreen.offscreenbitmap.bounds, 
00941     
00942         &bitoffscreen.offscreenbitmap.bounds, srcCopy, nil);
00943    
00944     HUnlock (bitoffscreen.bitmapbasehandle);
00945     
00946     DisposeHandle (bitoffscreen.bitmapbasehandle);
00947     } /*closemono*/
00948 
00949 
00950 static boolean systemhas32bitqd (void) {
00951     
00952     long qdversion;
00953     
00954     if (Gestalt (gestaltQuickdrawVersion, &qdversion) == noErr)
00955         flhas32bitqd = qdversion >= gestalt32BitQD;
00956     else
00957         flhas32bitqd = false;
00958         
00959     return (flhas32bitqd);
00960     } /*systemhas32bitqd*/
00961 
00962 
00963 boolean openbitmap (Rect r, WindowPtr w) {
00964     
00965     boolean fl;
00966     
00967     if (bitoffscreen.flbitmapopen) /*can't nest offscreens*/
00968         return (false);
00969     
00970     if (systemhas32bitqd ())
00971         fl = openworld (r, w);
00972     else
00973         fl = openmono (r, w);
00974     
00975     bitoffscreen.flbitmapopen = fl;
00976     
00977     return (fl);
00978     } /*openbitmap*/
00979 
00980 
00981 void closebitmap (WindowPtr w) {
00982     
00983     if (bitoffscreen.flbitmapopen) {
00984         
00985         bitoffscreen.flbitmapopen = false;
00986         
00987         if (flhas32bitqd)
00988             closeworld (w);
00989         else
00990             closemono (w);
00991         }
00992     } /*closebitmap*/
00993 
00994 #else
00995 
00996 static void calcrowbytes (boolean flcolor, CGrafPtr offptr, Rect offrect, long *rowbytes) {
00997 
00998     short pixelsize;
00999     short numpix;
01000     long offbits;
01001 
01002     if (flcolor)
01003         pixelsize = (**(*offptr).portPixMap).pixelSize;
01004     else
01005         pixelsize = 1;
01006     
01007     numpix = offrect.right - offrect.left;
01008     
01009     offbits = pixelsize * numpix;
01010 
01011     *rowbytes = ((offbits + 15) / 16) * 2;
01012     } /*calcrowbytes*/
01013     
01014     
01015 static void optimizerect (Rect *r) {
01016 
01017     (*r).left = ((*r).left / 32) * 32;
01018     
01019     (*r).right = (((*r).right + 31) / 32) * 32;
01020     } /*optimizerect*/
01021     
01022 
01023 static boolean openpixmap (WindowPtr w, Rect offrect,  Boolean flcopy, tyoffscreen *offscreen) {
01024 
01025     Rect rectcopy;
01026     GDHandle maxdevice;
01027     long offrowbytes;
01028     long offsize;
01029     PixMapHandle temppixmap;
01030     Ptr tempptr;
01031     CTabHandle temppmtable;
01032     short err;
01033     short i;
01034     Handle temphandle;
01035     boolean flcolor;
01036     typtrbitmap destptr;
01037 
01038     (*offscreen).flsuccess = false;
01039 
01040     if (!SectRect (&(*w).portRect, &offrect, &rectcopy))
01041         return (false);
01042 
01043     SetPort (w);
01044                 
01045     if (flcopy)
01046         optimizerect (&offrect);
01047 
01048     (*offscreen).offrect = offrect;
01049     
01050     flcolor = iscolorport (w);
01051     
01052     if (flcolor) {
01053     
01054         localtoglobalrect (&rectcopy);
01055     
01056         maxdevice = GetMaxDevice (&rectcopy);
01057         
01058         if (maxdevice == nil)
01059             return (false);
01060     
01061         (*offscreen).origdevice = GetGDevice ();
01062         
01063         SetGDevice (maxdevice);
01064         
01065         (*offscreen).offptr = (GrafPtr) NewPtr (sizeof (CGrafPort));
01066         }
01067     else {
01068         (*offscreen).offptr = (GrafPtr) NewPtr (sizeof (GrafPort));
01069         }
01070     
01071     if (MemError () != 0) {
01072     
01073         /*DebugStr ((ConstStr255Param) "\pMemErr in openpixmap");*/
01074         
01075         return (false);
01076         }
01077     
01078     if (flcolor)
01079         OpenCPort ((CGrafPtr) (*offscreen).offptr);
01080     else
01081         OpenPort ((*offscreen).offptr);
01082     
01083     calcrowbytes (flcolor, (CGrafPtr) (*offscreen).offptr, offrect, &offrowbytes);
01084     
01085     offsize = (long) (offrect.bottom - offrect.top) * offrowbytes;
01086     
01087     tempptr = NewPtr (offsize);
01088     
01089     if (MemError () != 0) {
01090 
01091         /*DebugStr ("\pMemErr in openpixmap");*/
01092         
01093         SetPort (w);
01094         
01095         if (flcolor)
01096             CloseCPort ((CGrafPtr) (*offscreen).offptr);
01097         else
01098             ClosePort ((*offscreen).offptr);
01099 
01100         DisposPtr ((Ptr) (*offscreen).offptr);
01101         
01102         return (false);
01103         }
01104     
01105     if (flcolor) {
01106     
01107         temphandle = (Handle) (**(**maxdevice).gdPMap).pmTable;
01108         
01109         err = HandToHand (&temphandle);
01110         
01111         if (err != noErr) {
01112             
01113             /*DebugStr ("\pMemErr in openpixmap");*/
01114         
01115             SetPort (w);
01116             
01117             CloseCPort ((CGrafPtr) (*offscreen).offptr);
01118         
01119             DisposPtr ((Ptr) (*offscreen).offptr);
01120             
01121             DisposPtr (tempptr);
01122             
01123             return (false);
01124             }
01125             
01126         temppmtable = (CTabHandle) temphandle;
01127     
01128         temppixmap = (*(CGrafPtr) (*offscreen).offptr).portPixMap;
01129     
01130         (**temppixmap).baseAddr = tempptr;
01131         
01132         (**temppixmap).rowBytes = offrowbytes + 0x8000;
01133         
01134         (**temppixmap).bounds = offrect;
01135         
01136         for (i = 0; i <= (**temppmtable).ctSize; i++)
01137             (**temppmtable).ctTable[i].value = i;
01138             
01139         (**temppmtable).ctFlags = (**temppmtable).ctFlags & 0x7FFF;
01140     
01141         (**temppixmap).pmTable = temppmtable;
01142         }
01143     else {
01144         (*(*offscreen).offptr).portBits.baseAddr = tempptr;
01145         
01146         (*(*offscreen).offptr).portBits.rowBytes = offrowbytes;
01147 
01148         (*(*offscreen).offptr).portBits.bounds = offrect;
01149         }
01150     
01151     SetPort ((GrafPtr) (*offscreen).offptr);
01152     
01153     if (flcopy) {
01154     
01155         if (flcolor)
01156             destptr = (typtrbitmap) (*(*(CGrafPtr) (*offscreen).offptr).portPixMap);
01157         else
01158             destptr = &(*(*offscreen).offptr).portBits;
01159             
01160         CopyBits (&(*w).portBits, destptr, &offrect, &offrect, 0, nil);
01161         }
01162         
01163     (*offscreen).flsuccess = true;
01164     
01165     return (true);
01166     } /*openpixmap*/
01167 
01168 
01169 static void closepixmap (WindowPtr w, tyoffscreen offscreen) {
01170 
01171     PixMapHandle temppixmap;
01172     boolean flcolor;
01173     typtrbitmap sourceptr;
01174     
01175     if (!offscreen.flsuccess)
01176         return;
01177 
01178     SetPort (w);
01179     
01180     flcolor = iscolorport (w);
01181     
01182     if (flcolor) {
01183     
01184         SetGDevice (offscreen.origdevice);
01185         
01186         sourceptr = (typtrbitmap) (*(*(CGrafPtr) offscreen.offptr).portPixMap);
01187         }
01188     else
01189         sourceptr = &(*offscreen.offptr).portBits;
01190 
01191     pushforecolor (&blackcolor);    /* 2.2.96 dmb: need b&w to preserve colors correctly*/
01192     pushbackcolor (&whitecolor);
01193     
01194     CopyBits (sourceptr, &(*w).portBits, &offscreen.offrect, &offscreen.offrect, 0, nil);
01195     
01196     popforecolor ();
01197     popbackcolor ();
01198     
01199     if (flcolor) {
01200     
01201         temppixmap = (*(CGrafPtr) offscreen.offptr).portPixMap;
01202     
01203         DisposHandle ((Handle) (**temppixmap).pmTable);
01204         
01205         DisposPtr ((Ptr) (**temppixmap).baseAddr);
01206     
01207         CloseCPort ((CGrafPtr) offscreen.offptr);
01208         }
01209     else {
01210         DisposPtr ((Ptr) (*offscreen.offptr).portBits.baseAddr);
01211         
01212         ClosePort (offscreen.offptr);
01213         }
01214     
01215     DisposPtr ((Ptr) offscreen.offptr);
01216     } /*closepixmap*/
01217     
01218     
01219 boolean openbitmap (Rect offrect, WindowPtr w) {
01220     
01221     return (openpixmap (w, offrect, true, &bitoffscreen));
01222     } /*openbitmap*/
01223     
01224     
01225 void closebitmap (WindowPtr w) {
01226     
01227     closepixmap (w, bitoffscreen);
01228     } /*closebitmap*/
01229 
01230 #endif
01231 
01232     
01233 boolean plotsmallicon (Rect r, short iconlist, short iconnum, boolean flinvert) {
01234 
01235     hdlsmalliconbits hbits;
01236     short mode;
01237     BitMap bmap;
01238     WindowPtr w;
01239     
01240     GetPort (&w);
01241     
01242     hbits = (hdlsmalliconbits) GetResource ('SICN', iconlist);
01243     
01244     if (hbits == nil) /*failed to load the resource*/  
01245         return (false);
01246         
01247     r.right = r.left + widthsmallicon; /*we only pay attention to the top, left fields of rectangle*/
01248     
01249     r.bottom = r.top + heightsmallicon;
01250         
01251     bmap.baseAddr = (Ptr) &(*hbits) [iconnum];
01252     
01253     bmap.rowBytes = 2;
01254     
01255     bmap.bounds.top = bmap.bounds.left = 0; 
01256     
01257     bmap.bounds.bottom = r.bottom - r.top; 
01258     
01259     bmap.bounds.right = r.right - r.left;
01260     
01261     if (flinvert)
01262         mode = notSrcCopy;
01263     else 
01264         mode = srcOr; /*was srcCopy*/
01265         
01266     CopyBits (&bmap, &(*w).portBits, &bmap.bounds, &r, mode, nil);
01267     
01268     return (true);
01269     } /*plotsmallicon*/
01270     
01271     
01272 void drawicon (Rect r, short bitdepth, Handle hbits) {
01273     
01274     if (bitdepth == 1) {
01275         
01276         PlotIcon (&r, hbits);
01277         
01278         return;
01279         }
01280     } /*drawicon*/
01281 
01282 
01283 static void constraintorect (Rect *rconstrained, Rect rcontains, boolean flcenter) {
01284     
01285     Rect r;
01286     Rect rcentered;
01287     short dh = 0;
01288     short dv = 0;
01289     
01290     r = *rconstrained; /*copy into local*/
01291     
01292     /*first, limit size to size of screen*/
01293     
01294     r.right = min (r.right, r.left + (rcontains.right - rcontains.left));
01295     
01296     r.bottom = min (r.bottom, r.top + (rcontains.bottom - rcontains.top));
01297     
01298     /*now, if repositioning is necessary, center in that dimension*/
01299     
01300     rcentered = r;
01301     
01302     centerrect (&rcentered, rcontains);
01303     
01304     if (r.left < rcontains.left) {
01305         
01306         if (flcenter)
01307             dh = rcentered.left - r.left;
01308         else
01309             dh = rcontains.left - r.left;
01310         }
01311     else if (r.right > rcontains.right) {
01312         
01313         if (flcenter)
01314             dh = rcentered.right - r.right;
01315         else
01316             dh = rcontains.right - r.right;
01317         }
01318     
01319     if (r.top < rcontains.top) {
01320         
01321         if (flcenter)
01322             dv = rcentered.top - r.top;
01323         else
01324             dv = rcontains.top - r.top;
01325         }
01326     else if (r.bottom > rcontains.bottom) {
01327         
01328         if (flcenter)
01329             dv = rcentered.bottom - r.bottom;
01330         else
01331             dv = rcontains.bottom - r.bottom;
01332         }
01333     
01334     OffsetRect (&r, dh, dv);
01335     
01336     *rconstrained = r; /*copy back to parameter*/
01337     } /*constraintorect*/
01338 
01339 
01340 void constraintodesktop (Rect *rconstrained) {
01341     
01342     Rect rdesktop = (**LMGetGrayRgn ()).rgnBBox;
01343     
01344     InsetRect (&rdesktop, 10, 10);
01345     
01346     rdesktop.top += doctitlebarheight; /*leave room for a title bar at top of rectangle*/
01347     
01348     constraintorect (rconstrained, rdesktop, false);
01349     } /*constraintodesktop*/
01350     
01351         
01352 void ellipsize (Str255 bs, short width) {
01353 
01354     /*
01355     if the string fits inside the given number of pixels, fine -- do nothing
01356     and return.
01357     
01358     if not, return a string that does fit, with ellipses representing the 
01359     deleted characters.  ellipses are generated by pressing option-semicolon.
01360     */
01361     
01362     char len;
01363     short newwidth;
01364     
01365     if ((newwidth = StringWidth (bs)) <= width) /*nothing to do, the string fits*/
01366         return;
01367     
01368     len = bs [0]; /* current length in characters*/
01369     
01370     width -= CharWidth (''); /* subtract width of ellipses*/
01371         
01372     do { /*until it fits (or we run out of characters)*/
01373     
01374         newwidth -= CharWidth (bs [len]);
01375         
01376         --len;
01377     } while ((newwidth > width) && (len != 0));
01378     
01379     ++len; /*make room for the ellipses*/
01380     
01381     bs [len] = ''; 
01382     
01383     bs [0] = (char) len;
01384     } /*ellipsize*/
01385     
01386 
01387 void centerstring (Rect r, bigstring bs) {
01388     
01389     /*
01390     draw the string in the current font, size and style, centered inside
01391     the indicated rectangle.
01392     */
01393     
01394     short lh = globalfontinfo.ascent + globalfontinfo.descent; /*line height*/
01395     short rh = r.bottom - r.top;
01396     short rw = r.right - r.left;
01397     short h, v;
01398     
01399     ellipsize (bs, rw); /*make sure it fits inside the rectangle, width-wise*/
01400     
01401     h = r.left + ((rw - StringWidth (bs)) / 2);
01402     
01403     v = r.top + ((rh - lh) / 2) + globalfontinfo.ascent;
01404     
01405     MoveTo (h, v);
01406     
01407     pushclip (r);
01408     
01409     DrawString (bs);
01410     
01411     popclip ();
01412     } /*centerstring*/
01413 
01414 
01415 void centerwindow (WindowPtr w, Rect rscreen) {
01416 
01417     short h, v;
01418     Rect r;
01419     short minv;
01420     
01421     r = (*w).portRect;
01422     
01423     h = rscreen.left + (((rscreen.right - rscreen.left) - (r.right - r.left)) / 2);
01424     
01425     v = rscreen.top + (((rscreen.bottom - rscreen.top) - (r.bottom - r.top)) / 6);
01426     
01427     minv = getmenubarheight () + doctitlebarheight + 10;
01428     
01429     if (v < minv)
01430         v = minv;
01431     
01432     MoveWindow (w, h, v, false);
01433     } /*centerwindow*/
01434 
01435 
01436 void grayrect (Rect r) {
01437 
01438     pushpen ();
01439     
01440     PenMode (patBic);
01441     
01442     PenPat (&quickdrawglobal (gray));
01443     
01444     PaintRect (&r);
01445     
01446     poppen ();
01447     } /*grayrect*/
01448     
01449 
01450 boolean pointinrect (Point pt, Rect r) {
01451     
01452     return (PtInRect (pt, &r));
01453     } /*pointinrect*/
01454 
01455 
01456 void validrect (Rect r) {
01457     
01458     ValidRect (&r);
01459     } /*validrect*/
01460     
01461     
01462 void zerorect (Rect *rzero) {
01463     
01464     Rect *r = rzero;
01465     
01466     (*r).top = (*r).left = (*r).bottom = (*r).right = 0;
01467     } /*zerorect*/
01468 
01469     
01470 boolean pushemptyclip (void) {
01471     
01472     /*
01473     set up the clip region so that no display will occur
01474     */
01475     
01476     Rect r;
01477     
01478     zerorect (&r);
01479     
01480     return (pushclip (r));
01481     } /*pushemptyclip*/
01482 
01483 
01484 void globaltolocalpoint (WindowPtr w, Point *pt) {
01485     
01486     pushmacport (w);
01487     
01488     GlobalToLocal (pt);
01489     
01490     popmacport ();
01491     } /*globaltolocalpoint*/
01492     
01493     
01494 void localtoglobalpoint (WindowPtr w, Point *pt) {
01495     
01496     if (w == nil)
01497         w = quickdrawglobal (thePort);
01498         
01499     pushmacport (w);
01500     
01501     LocalToGlobal (pt);
01502     
01503     popmacport ();
01504     } /*localtoglobalpoint*/
01505     
01506     
01507 void scrollrect (Rect r, short dh, short dv) {
01508     
01509     /*
01510     a front end for the Macintosh routine that scrolls a rectangle of pixels.
01511     */
01512     
01513     RgnHandle rgn;
01514     
01515     rgn = NewRgn ();
01516     
01517     ScrollRect (&r, dh, dv, rgn);
01518     
01519     InvalRgn (rgn);
01520     
01521     /*FillRgn (rgn, gray);*/
01522     
01523     DisposeRgn (rgn);
01524     } /*scrollrect*/
01525 
01526 
01527 boolean equalrects (Rect r1, Rect r2) {
01528     
01529     return (
01530         (r1.top == r2.top) && (r1.left == r2.left) && 
01531         
01532         (r1.bottom == r2.bottom) && (r1.right == r2.right));
01533     } /*equalrects*/
01534 
01535 
01536 

Generated on Wed May 31 18:19:44 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6