shellbuttons.c

Go to the documentation of this file.
00001 
00002 /*  $Id: shellbuttons.c 1200 2006-04-05 22:19:55Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "cursor.h"
00032 #include "memory.h"
00033 #include "quickdraw.h"
00034 #include "bitmaps.h"
00035 #include "frontierconfig.h"
00036 #include "font.h"
00037 #include "mouse.h"
00038 #include "scrollbar.h"
00039 #include "sounds.h"
00040 #include "strings.h"
00041 #include "shell.h"
00042 #include "shellbuttons.h"
00043 #include "shellprivate.h"
00044 #include "oplist.h"
00045 
00046 
00047 #define backgroundcolor lightblueindex
00048 
00049 #define backgroundpattern 128
00050 
00051 
00052 #ifdef MACVERSION
00053     #define flbitmapsallowed true /*bitmaps wreak havoc on debugging*/
00054 #endif
00055 #ifdef WIN95VERSION
00056     #define flbitmapsallowed false /*somehow, true value screws display*/
00057 #endif
00058 
00059 static boolean flbuttonbitmap = false; /*if true, don't use bitmaps*/
00060 
00061 static short mousebuttonnumber = 0; /*global for button tracking*/
00062 
00063 
00064 static void shellgetbuttonlist (hdlwindowinfo hinfo, hdllistrecord *buttonlist) {
00065 
00066     /*
00067     7.1b18 PBS: get the button list for a window.
00068     */
00069 
00070     if ((**hinfo).flsyntheticbuttons)
00071 
00072         *buttonlist = (hdllistrecord) (**hinfo).buttonlist;
00073 
00074     else
00075 
00076         *buttonlist = (hdllistrecord) shellglobals.buttonlist;
00077     } /*shellgetbuttonlist*/
00078 
00079 
00080 static long shellgetbuttonlistcount (hdlwindowinfo hinfo) {
00081     
00082     /*
00083     7.1b18 PBS: get the count of buttons.
00084     */
00085 
00086     hdllistrecord buttonlist;
00087 
00088     shellgetbuttonlist (hinfo, &buttonlist);
00089 
00090     if (buttonlist == nil)
00091         return (0L);
00092 
00093     return (opcountlistitems (buttonlist));
00094     } /*shellgetbuttonlistcount*/
00095 
00096 
00097 static void shellrefreshbuttonstatus (void) {
00098     
00099     hdlwindowinfo hw = shellwindowinfo;
00100     hdllistrecord buttonlist; // = (hdllistrecord) shellglobals.buttonlist;
00101     register short ct; // = (**buttonlist).ctitems;
00102     tybuttonstatus buttonstatus;
00103     unsigned short buttonsenabled = 0;
00104     unsigned short buttonsdisplayed = 0;
00105     short i;
00106     unsigned short flag = 1;
00107 
00108     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00109 
00110     ct = shellgetbuttonlistcount (shellwindowinfo);
00111 
00112     for (i = 1; i <= ct; i++) {
00113         
00114         (*shellglobals.buttonstatusroutine) (i, &buttonstatus);
00115         
00116         if (buttonstatus.flenabled)
00117             buttonsenabled |= flag;
00118 
00119         if (buttonstatus.fldisplay)
00120             buttonsdisplayed |= flag;
00121 
00122         flag <<= 1;
00123         }
00124 
00125     (**hw).buttonsenabled = buttonsenabled;
00126 
00127     (**hw).buttonsdisplayed = buttonsdisplayed;
00128     } /*shellrefreshbuttonstatus*/
00129 
00130 
00131 static boolean buttonenabled (short ix) {
00132     
00133     unsigned short flag = 1L << (ix - 1);
00134     
00135     return (((**shellwindowinfo).buttonsenabled & flag) != 0);
00136     } /*buttonenabled*/
00137 
00138 
00139 static boolean buttondisplayed (short ix) {
00140         
00141     unsigned short flag = 1L << (ix - 1);
00142     
00143     return (((**shellwindowinfo).buttonsdisplayed & flag) != 0);
00144     } /*buttondisplayed*/
00145 
00146 
00147 #if !TARGET_API_MAC_CARBON
00148 
00149 static short getbuttonstyle (short ix) {
00150     
00151     /*
00152     5.017 dmb: new button logic doesn't do bold anymore. we don't use it.
00153     */
00154 
00155     if (!(**shellwindowinfo).flwindowactive) /*inactive windows have no bold buttons*/
00156         return (normal);
00157     
00158     /*
00159     if (buttonstatusarray [ix].flbold)
00160         return (boldbuttonstyle);
00161     */
00162 
00163     return (normal);
00164     } /*getbuttonstyle*/
00165 
00166 #endif
00167 
00168 
00169 #ifdef flbuttoncolor
00170 
00171 static short getbuttoncolor (short ix) {
00172     
00173     /*
00174     if (colorenabled () && (**shellwindowinfo).flwindowactive)
00175         return (lightyellowindex);
00176     */
00177     
00178     return (whiteindex);
00179     } /*getbuttoncolor*/
00180 
00181 #endif
00182 
00183 static short countbuttons (void) {
00184     
00185     hdllistrecord buttonlist; // = (hdllistrecord) shellglobals.buttonlist;
00186     register short ct; // = (**buttonlist).ctitems;
00187     register short i;
00188     register short ctdisplayed;
00189 
00190     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00191 
00192     ct = shellgetbuttonlistcount (shellwindowinfo);
00193     
00194     ctdisplayed = 0;
00195     
00196     for (i = 1; i <= ct; i++) {
00197         
00198         if (buttondisplayed (i))
00199             ctdisplayed++;
00200         } /*for*/
00201         
00202     return (ctdisplayed);
00203     } /*countbuttons*/
00204     
00205 
00206 static short getbuttonwidth (void) {
00207     
00208     /*
00209     return the width of each button, using the current window's button list
00210     and the button font, size and style.  it's the maximum string width of
00211     the names in the button.
00212     */
00213     
00214     hdllistrecord buttonlist; // = (hdllistrecord) shellglobals.buttonlist;
00215     register short ct;
00216     register short i;
00217     register short maxpixels = 0;
00218     
00219     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00220 
00221     ct = shellgetbuttonlistcount (shellwindowinfo);
00222 
00223     //ct = (**buttonlist).ctitems;
00224     
00225     pushstyle (buttonfont, buttonsize, boldbuttonstyle);
00226     
00227     for (i = 1; i <= ct; i++) {
00228         
00229         if (buttondisplayed (i)) {
00230         
00231             bigstring bs;
00232             register short ctpixels;
00233             
00234             opgetliststring (buttonlist, i, nil, bs);
00235             
00236             ctpixels = stringpixels (bs);
00237             
00238             maxpixels = max (maxpixels, ctpixels);
00239             }
00240         } /*for*/
00241         
00242     popstyle ();
00243     
00244     i = maxpixels + (2 * buttontextinset); /*allow extra pixels on each side*/
00245     
00246     i = max (minbuttonwidth, i);
00247     
00248     return (i);
00249     } /*getbuttonwidth*/
00250     
00251 
00252 static short countdisplayedbefore (short ix) {
00253     
00254     register short ct = ix;
00255     register short ctdisplayed = 0;
00256     register short i;
00257     
00258     for (i = 1; i < ct; i++)
00259         if (buttondisplayed (i))
00260             ctdisplayed++;
00261             
00262     return (ctdisplayed);
00263     } /*countdisplayedbefore*/
00264     
00265     
00266 void shellgetbuttonrect (short ix, Rect *rbutton) {
00267     
00268     hdllistrecord buttonlist;
00269     register short ct;
00270     register short totalwidth;
00271     register short leftmargin;
00272     register short buttonwidth;
00273     Rect r;
00274     
00275     if (!buttondisplayed (ix)) {
00276         
00277         zerorect (rbutton);
00278         
00279         return;
00280         }
00281     
00282     buttonwidth = getbuttonwidth ();
00283     
00284     //buttonlist = (hdllistrecord) shellglobals.buttonlist;
00285 
00286     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00287     
00288     ct = countbuttons ();
00289     
00290     totalwidth = ((ct - 1) * pixelsbetweenbuttons) + (ct * buttonwidth);
00291     
00292     r = (**shellwindowinfo).buttonsrect;
00293     
00294     leftmargin = ((r.right - r.left) - totalwidth) / 2;
00295     
00296     leftmargin = max (leftmargin, pixelsbetweenbuttons);
00297     
00298     r.left += leftmargin;
00299     
00300     ct = countdisplayedbefore (ix);
00301     
00302     r.left += ct * (buttonwidth + pixelsbetweenbuttons);
00303     
00304     r.right = r.left + buttonwidth;
00305     
00306     r.top += buttontopinset;
00307     
00308     r.bottom -= buttonbottominset;
00309     
00310     *rbutton = r;
00311     } /*shellgetbuttonrect*/
00312 
00313 
00314 static void drawbuttonbackground (Rect r) {
00315     
00316     /*
00317     2.1b3 dmb: use 'ppat' for button background; easier to modify, less code to draw.
00318     */
00319     
00320     #ifdef gray3Dlook
00321         eraserect (r);
00322     #else
00323         //Code change by Timothy Paustian Friday, June 16, 2000 2:47:25 PM
00324         //Changed to Opaque call for Carbon
00325         if ((**shellwindowinfo).flwindowactive) {
00326             
00327             if (colorenabled ())
00328                 
00329                 #if TARGET_API_MAC_CARBON == 1
00330                 
00331                     DrawThemeWindowHeader (&r, kThemeStateActive);
00332                     
00333                 #else
00334                 
00335                     fillcolorrect (r, backgroundpattern);
00336                     
00337                 #endif
00338                                 
00339             else
00340                 #if TARGET_API_MAC_CARBON == 1
00341                 {
00342                 Pattern pat;
00343                 GetQDGlobalsGray(&pat);
00344                 FillRect (&r, &pat);
00345                 }
00346                 #else
00347                 fillrect (r, buttonbackground);
00348                 #endif
00349             }
00350         else
00351             #if TARGET_API_MAC_CARBON == 1
00352             {
00353             //Pattern pat;
00354             //GetQDGlobalsWhite(&pat);
00355             //FillRect (&r, &pat);
00356             DrawThemeWindowHeader (&r, kThemeStateInactive);
00357             }
00358             #else
00359             fillrect (r, whitebackground);
00360             #endif
00361     #endif
00362     } /*drawbuttonbackground*/
00363 
00364 
00365 #if TARGET_API_MAC_CARBON == 1
00366 
00367     typedef struct tybuttoninfo {
00368         
00369         bigstring bslabel;
00370         
00371         boolean flenabled: 1;
00372         } tybuttoninfo, *ptrbuttoninfo, **hdlbuttoninfo;
00373 
00374 
00375 static void
00376 MyThemeButtonDrawCallback (
00377         const Rect                  *bounds,
00378         ThemeButtonKind              kind,
00379         const ThemeButtonDrawInfo   *info,
00380         UInt32                       userData,
00381         SInt16                       depth,
00382         Boolean                      isColorDev)
00383 {
00384 #pragma unused (kind, info, depth, isColorDev)
00385         
00386         /*
00387         7.0b48 PBS: draw the label for a popup menu.
00388         */
00389         ptrbuttoninfo buttoninfo = (ptrbuttoninfo) userData;
00390         
00391         pushstyle (buttonfont, buttonsize, 0);
00392 
00393         //movepento ((*bounds).left, (*bounds).top + 10);
00394         
00395         centerbuttonstring (bounds, (*buttoninfo).bslabel, !((*buttoninfo).flenabled));
00396 
00397         popstyle ();
00398         } /*MyThemeButtonDrawCallback*/
00399 
00400 #endif
00401 
00402 
00403 void shelldrawbutton (short ix, boolean flpressed) {
00404     
00405     hdllistrecord buttonlist;
00406     Rect rbutton;
00407     bigstring bs;
00408     
00409     if (!buttondisplayed (ix))
00410         return;
00411     
00412     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00413     
00414     opgetliststring (buttonlist, ix, nil, bs);
00415     
00416     shellgetbuttonrect (ix, &rbutton);
00417     
00418     
00419     #if TARGET_API_MAC_CARBON == 1
00420     
00421         {
00422         ThemeButtonDrawInfo drawinfo;
00423         ThemeButtonDrawUPP drawupp;
00424         tybuttoninfo buttoninfo;
00425         boolean flenabled = buttonenabled (ix);
00426         Handle h;
00427 
00428         copystring (bs, buttoninfo.bslabel);
00429 
00430         buttoninfo.flenabled = flenabled;
00431         
00432         drawupp = NewThemeButtonDrawUPP (MyThemeButtonDrawCallback);
00433 
00434         drawinfo.state = kThemeButtonOn;
00435         
00436         if (flenabled)
00437             drawinfo.value = kThemeStateActive;
00438         else
00439             drawinfo.value = kThemeStateInactive;
00440             
00441         if (flpressed)
00442             drawinfo.value = kThemeStatePressed;
00443         
00444         drawinfo.adornment = 0;
00445         
00446         //eraserect (rbutton);
00447 
00448         newtexthandle (bs, &h); 
00449 
00450         DrawThemeButton (&rbutton, kThemeLargeBevelButton, &drawinfo, nil, nil, drawupp, (unsigned long) &buttoninfo); 
00451         
00452         //DisposeThemeButtonDrawUPP (MyThemeButtonDrawCallback);
00453         DisposeThemeButtonDrawUPP (drawupp);
00454         }
00455     
00456     
00457     #else
00458         
00459         {
00460         boolean flbitmap = false;
00461         
00462         if (flbitmapsallowed) {
00463         
00464             if (!flbuttonbitmap) 
00465                 flbitmap = openbitmap (rbutton, shellwindow);
00466             }
00467         
00468         if (flpressed) {
00469             
00470             drawbuttonbackground (rbutton);
00471             
00472             offsetrect (&rbutton, 1, 1); /*simulate a button being pressed -- multimedia!*/
00473             }
00474         
00475         #ifdef flbuttoncolor
00476         
00477         pushbackcolor (getbuttoncolor (ix));
00478         
00479         #endif
00480         
00481         eraseandframerect (rbutton);
00482         
00483         #ifdef flbuttoncolor
00484         
00485         popbackcolor ();
00486         
00487         #endif
00488         
00489         pushstyle (buttonfont, buttonsize, getbuttonstyle (ix));
00490         
00491         centerbuttonstring (&rbutton, bs, !buttonenabled (ix));
00492         
00493         popstyle ();
00494         
00495         /*
00496         if (!buttonenabled (ix)) {
00497             
00498             Rect r;
00499             
00500             r = rbutton;
00501             
00502             insetrect (&r, 1, 1);
00503             
00504             grayrect (r);
00505             }
00506         */
00507 
00508         if (flbitmap)
00509             closebitmap (shellwindow);
00510         
00511         if (!flpressed)
00512             dropshadowrect (rbutton, 1, flpressed);
00513         }
00514         
00515     #endif
00516     } /*shelldrawbutton*/
00517     
00518 
00519 void shelldrawbuttons (void) {
00520     
00521     register hdlwindowinfo hw = shellwindowinfo;
00522     hdllistrecord buttonlist;
00523     Rect r;
00524     short i;
00525     short ctbuttons;
00526     
00527     //buttonlist = (hdllistrecord) shellglobals.buttonlist;
00528 
00529     if ((**hw).flhidebuttons) /*7.1b18 PBS: windows may have hidden buttons*/
00530         return; 
00531 
00532     shellgetbuttonlist (hw, &buttonlist);   
00533 
00534     if (buttonlist == nil) /*no buttons for this window type*/
00535         return;
00536     
00537     shellrefreshbuttonstatus ();
00538     
00539     r = (**hw).buttonsrect;
00540     
00541     if (flbitmapsallowed)
00542         flbuttonbitmap = openbitmap (r, shellwindow);
00543     
00544     drawbuttonbackground (r);
00545     
00546     #ifndef gray3Dlook
00547         
00548         //#if !TARGET_API_MAC_CARBON
00549             movepento (r.left, r.bottom - 1);
00550             
00551             pendrawline (r.right, r.bottom - 1);
00552             
00553             if ((**hw).contentrect.bottom <= r.top) { /*content is above the buttons rect*/
00554             
00555                 movepento (r.left, r.top);
00556             
00557                 pendrawline (r.right, r.top);
00558                 }
00559         //#endif
00560     #endif
00561     
00562     ctbuttons = opcountlistitems (buttonlist);
00563     
00564     for (i = 1; i <= ctbuttons; i++)
00565         shelldrawbutton (i, false);
00566         
00567     if (flbuttonbitmap) {
00568         
00569         flbuttonbitmap = false; /*must be reset every time*/
00570         
00571         closebitmap (shellwindow);
00572         }
00573     
00574     validrect (r); /*no need to draw this again*/
00575     } /*shelldrawbuttons*/
00576     
00577 
00578 static void buttontracker (boolean flpressed) {
00579     
00580     /*
00581     callback routine for the mouse tracker.
00582     */
00583     
00584     pushclip ((**shellwindowinfo).buttonsrect);
00585     
00586     shelldrawbutton (mousebuttonnumber, flpressed);
00587     
00588     popclip ();
00589     } /*buttontracker*/
00590 
00591 
00592 void shellbuttonhit (Point pt) {
00593     
00594     hdllistrecord buttonlist;
00595     register short i;
00596     short ct;
00597     
00598     shellrefreshbuttonstatus ();
00599 
00600     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00601 
00602     ct = shellgetbuttonlistcount (shellwindowinfo);
00603     
00604     //buttonlist = (hdllistrecord) shellglobals.buttonlist;
00605     
00606     for (i = 1; i <= ct /*(**buttonlist).ctitems*/; i++) {
00607         
00608         Rect rbutton;
00609         
00610         shellgetbuttonrect (i, &rbutton);
00611         
00612         if (pointinrect (pt, rbutton)) {
00613             
00614             if (!buttonenabled (i)) {
00615                 
00616                 ouch ();
00617                 
00618                 return;
00619                 }
00620                 
00621             mousebuttonnumber = i;
00622             
00623             buttontracker (true); /*show button in its pressed state*/
00624             
00625             if (mousetrack (rbutton, &buttontracker)) {
00626                 
00627                 (*shellglobals.buttonroutine) (i);
00628                 
00629                 buttontracker (false); /*show button in its unpressed state*/
00630                 
00631                 (**shellwindowinfo).lastbuttonhit = i;
00632                 }
00633             
00634             /*
00635             shelldrawbuttons ();
00636             */
00637             
00638             return;
00639             }
00640         } /*for*/
00641         
00642     //ouch (); /*loop satisfied, click isn't in one of the buttons*/
00643     } /*shellbuttonhit*/
00644     
00645 
00646 void shellgetbuttonsrect (hdlwindowinfo hinfo, Rect *buttonsrect) {
00647     
00648     /*
00649     we control the height of the buttonsrect from here.  externally, the buttonsrect
00650     may be less than the full width of the window, especially if there's a vertical
00651     scrollbar linked to the window.
00652     
00653     11/17/90 DW: called externally from shellwindow.c.
00654     */
00655     
00656     Rect r;
00657     
00658     shellgetwindowrect (hinfo, &r);
00659     
00660     r.bottom = r.top + buttonsrectheight;
00661     
00662     *buttonsrect = r;
00663     } /*shellgetbuttonsrect*/
00664 
00665 
00666 void shellinvalbuttons (void) {
00667     
00668     /*
00669     can be called by a handler when it knows that the buttons need updating.
00670     
00671     5.0a17 dmb: use new buttonsenabled/displayed fields to intelligently
00672     update buttons
00673     */
00674     
00675     hdlwindowinfo hw = shellwindowinfo;
00676     unsigned short buttonsenabled = (**hw).buttonsenabled;
00677     unsigned short buttonsdisplayed = (**hw).buttonsdisplayed;
00678     
00679     shellrefreshbuttonstatus ();
00680     
00681     if (buttonsenabled != (**hw).buttonsenabled || 
00682         buttonsdisplayed != (**hw).buttonsdisplayed) {
00683     
00684         invalwindowrect (shellwindow, (**shellwindowinfo).buttonsrect);
00685         }
00686     } /*shellinvalbuttons*/
00687 
00688 
00689 boolean shellgetbuttonstring (short ix, bigstring bs) {
00690     
00691     hdllistrecord buttonlist;
00692     
00693     //buttonlist = (hdllistrecord) shellglobals.buttonlist;
00694 
00695     shellgetbuttonlist (shellwindowinfo, &buttonlist);
00696     
00697     return (opgetliststring (buttonlist, ix, nil, bs));
00698     } /*shellgetbuttonstring*/
00699 
00700 
00701 void shellbuttongetoptimalwidth (short *width) {
00702     
00703     /*
00704     provided for external callers who are willing to monkey with the width of
00705     their window to provide for a buttons list.
00706     
00707     we compute the optimum window width for the current window's button list.
00708     
00709     12/9/91 dmb: only consider displayed buttons
00710     */
00711     
00712     register short x;
00713     register short ct;
00714     
00715     shellrefreshbuttonstatus ();
00716     
00717     /*
00718     buttonlist = (hdllistrecord) shellglobals.buttonlist;
00719     
00720     ct = (**buttonlist).ctitems;
00721     */
00722     
00723     ct = countbuttons ();
00724     
00725     x = ct * getbuttonwidth ();
00726     
00727     x += (ct + 1) * pixelsbetweenbuttons; /*account for left and right margin*/
00728     
00729     *width = x;
00730     } /*shellbuttongetoptimalwidth*/
00731 
00732 
00733 void shellbuttonadjustcursor (Point pt) {
00734 #pragma unused (pt)
00735 
00736     setcursortype (cursorisarrow); /*no special button cursor, 4/23/90*/
00737     } /*shellbuttonadjustcursor*/
00738     
00739     
00740     

Generated on Wed May 31 18:20:01 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6