appletdialogs.c

Go to the documentation of this file.
00001 
00002 /*  $Id: appletdialogs.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /*© copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
00005 
00006 
00007 #include "applet.h"
00008 #include "appletquickdraw.h"
00009 #include "appletops.h"
00010 #include "appletresource.h"
00011 #include "appletmain.h"
00012 #include "appletdialogs.h"
00013 
00014 
00015 /*
00016 7/25/94 dmb: updated for Universal Headers, PowerPC
00017 */
00018 
00019 
00020 /*
00021 flag to control whether the user is interacting, or we're responding to an
00022 interapplication message. the error string is saved -- to be accessed by the
00023 GetErrorString verb.
00024 */
00025     boolean fldialogsenabled = true;
00026     bigstring bsalertstring;
00027     
00028 
00029 
00030 
00031 void setdialogtext (DialogPtr pdialog, short itemnumber, bigstring bs) {
00032 
00033     short itemtype;
00034     Handle itemhandle;
00035     Rect itemrect;
00036     
00037     GetDItem (pdialog, itemnumber, &itemtype, &itemhandle, &itemrect);
00038         
00039     SetIText (itemhandle, bs); 
00040     } /*setdialogtext*/
00041     
00042     
00043 void getdialogtext (DialogPtr pdialog, short itemnumber, bigstring bs) {
00044 
00045     short itemtype;
00046     Handle itemhandle;
00047     Rect itemrect;
00048     
00049     GetDItem (pdialog, itemnumber, &itemtype, &itemhandle, &itemrect);
00050                 
00051     GetIText (itemhandle, bs); 
00052     } /*getdialogtext*/
00053 
00054 
00055 void selectdialogtext (DialogPtr pdialog, short itemnumber) {
00056     
00057     SelIText (pdialog, itemnumber, 0, infinity); /*select all text*/
00058     } /*selectdialogtext*/      
00059 
00060 
00061 void disabledialogitem (DialogPtr pdialog, short itemnumber) {
00062     
00063     short itemtype;
00064     Handle itemhandle;
00065     Rect itemrect;
00066 
00067     GetDItem (pdialog, itemnumber, &itemtype, &itemhandle, &itemrect);
00068     
00069     if (itemtype < itemDisable) { /*it is enabled, disable it*/
00070     
00071         SetDItem (pdialog, itemnumber, itemtype + itemDisable, itemhandle, &itemrect);
00072         
00073         grayrect (itemrect);
00074         }
00075     } /*disabledialogitem*/
00076     
00077 
00078 void enabledialogitem (DialogPtr pdialog, short itemnumber) {
00079     
00080     short itemtype;
00081     Handle itemhandle;
00082     Rect itemrect;
00083 
00084     GetDItem (pdialog, itemnumber, &itemtype, &itemhandle, &itemrect);
00085     
00086     if (itemtype >= itemDisable) /*it is disabled, enable it*/
00087     
00088         SetDItem (pdialog, itemnumber, itemtype - itemDisable, itemhandle, &itemrect);
00089     } /*disabledialogitem*/
00090     
00091 
00092 void dialoggetobjectrect (DialogPtr pdialog, short objectnumber, Rect *r) {
00093 
00094     short itemtype;
00095     Handle itemhandle;
00096     
00097     GetDItem (pdialog, objectnumber, &itemtype, &itemhandle, r);
00098     } /*dialoggetobjectrect*/
00099     
00100     
00101 void parsedialogstring (bigstring bs) {
00102     
00103     register short i;
00104     
00105     for (i = 1; i <= stringlength (bs); i++) {
00106         
00107         if (bs [i] == '®')
00108             bs [i] = (char) 13;
00109         } /*for*/
00110     } /*parsedialogstring*/
00111     
00112     
00113 static short dialogcountitems (DialogPtr pdialog) {
00114     
00115     /*
00116     amazingly we have to klooge around to find out how many items there are
00117     in a dialog's item list.
00118     */
00119     
00120     register Handle h;
00121     
00122     h = (*(DialogPeek) pdialog).items;
00123     
00124     return ((**(short **) h) + 1); /*magic incantation -- Boozer says this works*/
00125     } /*dialogcountitems*/
00126 
00127 
00128 static boolean dialogitemisedittext (DialogPtr pdialog, short item) {
00129     
00130     short itemtype;
00131     Handle itemhandle;
00132     Rect itemrect;
00133     
00134     GetDItem (pdialog, item, &itemtype, &itemhandle, &itemrect);
00135     
00136     return (itemtype & editText); 
00137     } /*dialogitemisedittext*/
00138     
00139 
00140 static dialoghasedititems (DialogPtr pdialog) {
00141     
00142     register short i;
00143     register short ctitems;
00144     
00145     ctitems = dialogcountitems (pdialog);
00146     
00147     for (i = 1; i <= ctitems; i++) 
00148         if (dialogitemisedittext (pdialog, i))
00149             return (true);
00150     
00151     return (false);
00152     } /*dialoghasedititems*/
00153 
00154 
00155 static void dialoggetbuttonstring (DialogPtr pdialog, short item, bigstring bs) {
00156     
00157     short itemtype;
00158     Handle itemhandle;
00159     Rect itemrect;
00160 
00161     GetDItem (pdialog, item, &itemtype, &itemhandle, &itemrect);
00162     
00163     copystring ((**(ControlHandle) itemhandle).contrlTitle, bs);
00164     } /*dialoggetbuttonstring*/
00165 
00166 
00167 static void dialogsetbuttonstring (DialogPtr pdialog, short item, bigstring bs) {
00168     
00169     short itemtype;
00170     Handle itemhandle;
00171     Rect itemrect;
00172 
00173     GetDItem (pdialog, item, &itemtype, &itemhandle, &itemrect);
00174     
00175     SetCTitle ((ControlHandle) itemhandle, bs);
00176     } /*dialogsetbuttonstring*/
00177 
00178 
00179 static void setdefaultitem (DialogPtr pdialog, short defaultitem) {
00180     
00181     (*(DialogPeek) pdialog).aDefItem = defaultitem; /*filter will bolden this*/
00182     } /*setdefaultitem*/
00183 
00184 
00185 void boldenbutton (DialogPtr pdialog, short itemnumber) {
00186 
00187     /*
00188     draw a thick black ring around the OK button in the dialog.  
00189     */
00190     
00191     PenState savePen;
00192     short itemtype;
00193     Handle itemhandle;
00194     Rect itemrect;
00195     
00196     pushmacport (pdialog);
00197     
00198     GetPenState (&savePen); /*save the old pen state*/
00199     
00200     GetDItem (pdialog, itemnumber, &itemtype, &itemhandle, &itemrect); /*get the item’s rect*/
00201     
00202     InsetRect (&itemrect, -4, -4);
00203     
00204     PenSize (3, 3); /*make the pen fatter*/
00205     
00206     FrameRoundRect (&itemrect, 16, 16); /*draw the ring*/
00207 
00208     SetPenState (&savePen); /*restore the pen state*/
00209     
00210     popmacport ();
00211     } /*boldenbutton*/
00212 
00213 
00214 static boolean dialogitemtypeiscontrol (short itemtype) {
00215     
00216     register short x;
00217     
00218     x = itemtype % itemDisable; /*ignore enabledness*/
00219     
00220     return ((x >= ctrlItem) && (x <= (ctrlItem + resCtrl))); 
00221     } /*dialogitemtypeiscontrol*/
00222 
00223 
00224 static boolean dialogitemisbutton (DialogPtr pdialog, short item) {
00225     
00226     short itemtype;
00227     Handle itemhandle;
00228     Rect itemrect;
00229     
00230     if (item <= 0)
00231         return (false);
00232     
00233     GetDItem (pdialog, item, &itemtype, &itemhandle, &itemrect);
00234     
00235     return (dialogitemtypeiscontrol (itemtype));
00236     } /*dialogitemisbutton*/
00237     
00238 
00239 static void highlightdialogbutton (DialogPtr pdialog, short itemnumber, boolean flon) {
00240     
00241     register DialogPtr p = pdialog;
00242     register short val;
00243     short itemtype;
00244     Handle itemhandle;
00245     Rect itembox;
00246     
00247     if (pdialog == nil) /*defensive driving*/
00248         return;
00249         
00250     GetDItem (p, itemnumber, &itemtype, &itemhandle, &itembox);
00251     
00252     if (flon)
00253         val = inButton;
00254     else
00255         val = 0;
00256     
00257     HiliteControl ((ControlHandle) itemhandle, val); 
00258     } /*highlightdialogbutton*/
00259 
00260 
00261 static boolean dialogitemisenabled (DialogPtr pdialog, short item) {
00262     
00263     short itemtype;
00264     Handle itemhandle;
00265     Rect itemrect;
00266     
00267     GetDItem (pdialog, item, &itemtype, &itemhandle, &itemrect);
00268     
00269     return ((itemtype & itemDisable) == 0);
00270     } /*dialogitemisenabled*/
00271 
00272 
00273 static boolean dialogsimulatehit (DialogPtr pdialog, short item) {
00274     
00275     if (!(dialogitemisbutton (pdialog, item) && dialogitemisenabled (pdialog, item)))
00276         return (false);
00277     
00278     highlightdialogbutton (pdialog, item, true);
00279     
00280     delayticks (8);
00281     
00282     highlightdialogbutton (pdialog, item, false);
00283     
00284     return (true);
00285     } /*dialogsimulatehit*/
00286 
00287 
00288 static boolean dialogmapkeystroke (DialogPtr pdialog, bigstring bsmap, short *item) {
00289     
00290     /*
00291     map a keystroke onto a dialog item.  if no match, return false.
00292     
00293     for buttons, if the keystroke matches the first character of the button name,
00294     we return true with that item.  makes your choice of button names strategic.
00295     
00296     to get the number of items in the list, pull the first two bytes out of the
00297     dialog's itemhandle and add one.  an obvious problem if Apple changes the format
00298     of an item list handle.
00299     
00300     10/10/91 dmb: now take string to map instead of a character.  if bsmap is 
00301     longer than a single character, we look for an exact match (still ignoring case).
00302     
00303     2/7/92 dmb: use dialoghasedititems instead of looping through item list.
00304     */
00305     
00306     register short i;
00307     register boolean flcmdkeyrequired;
00308     short ctitems;
00309     bigstring bs;
00310     boolean flsinglechar;
00311     
00312     alllower (bsmap); /*search is unicase*/
00313     
00314     ctitems = dialogcountitems (pdialog);
00315     
00316     flsinglechar = stringlength (bsmap) == 1;
00317     
00318     if (flsinglechar) { /*mapping a single character -- check command key*/
00319         
00320         flcmdkeyrequired = dialoghasedititems (pdialog);
00321         
00322         if (flcmdkeyrequired && !cmdkeydown ())
00323             return (false);
00324         }
00325     
00326     for (i = 1; i <= ctitems; i++) {
00327         
00328         if (dialogitemisbutton (pdialog, i)) {
00329             
00330             dialoggetbuttonstring (pdialog, i, bs);
00331             
00332             if (stringlength (bs) > 0) {
00333                 
00334                 if (flsinglechar)
00335                     setstringlength (bs, 1);
00336                 
00337                 alllower (bs);
00338                 
00339                 if (equalstrings (bs, bsmap)) {
00340                     
00341                     *item = i;
00342                     
00343                     return (true);
00344                     }
00345                 }   
00346             }
00347         } /*for*/
00348     
00349     return (false); /*no mapping for the character*/
00350     } /*dialogmapkeystroke*/
00351 
00352 
00353 DialogPtr newmodaldialog (short id, short defaultitem) {
00354     
00355     register DialogPtr pdialog;
00356     
00357     cometofront ();
00358     
00359     arrowcursor ();
00360     
00361     pdialog = GetNewDialog (id, nil, (DialogPtr) -1L);
00362     
00363     if (pdialog == nil) 
00364         return (nil);
00365         
00366     centerwindow (pdialog, quickdrawglobal (screenBits).bounds);
00367     
00368     ShowWindow (pdialog);   
00369     
00370     if (defaultitem > 0)
00371         boldenbutton (pdialog, defaultitem); 
00372     
00373     setdefaultitem (pdialog, defaultitem);
00374     
00375     return (pdialog);
00376     } /*newmodaldialog*/
00377     
00378 
00379 static pascal Boolean modaldialogcallback (DialogPtr pdialog, EventRecord *ev, short *item) {
00380     
00381     /*
00382     standard dialog & alert event filtering.
00383     
00384     10/3/90 dmb: check result of dialogsimulatehit (which now checks enabledness). 
00385     only process background tasks on null events; dialog events have priority. 
00386     also, get default item instead of assuming item 1, and handle boldening.
00387     
00388     8/26/91 dmb: after backgrounding, make sure we're still in front.  otherwise, 
00389     the dialog manager will crash
00390     
00391     10/14/91 dmb: set shellevent.when to deter overzealous agent processing
00392     */
00393     
00394     short defaultitem = (*(DialogPeek) pdialog).aDefItem; /*was set by newmodaldialog*/
00395     short whatevent = (*ev).what;
00396     bigstring bsbutton;
00397     
00398     /*put callback here*/
00399     
00400     switch (whatevent) {
00401     
00402         case keyDown: case autoKey: {
00403             
00404             char chkb;
00405             boolean flcmdkey;
00406     
00407             chkb = (*ev).message & charCodeMask;
00408             
00409             flcmdkey = ((*ev).modifiers & cmdKey) == cmdKey;
00410             
00411             if ((chkb == chreturn) || (chkb == chenter)) { /*user hit return or enter*/
00412                 
00413                 if (defaultitem == 0)
00414                     return (0);
00415                 
00416                 if (!dialogsimulatehit (pdialog, defaultitem))
00417                     return (0);
00418                 
00419                 *item = defaultitem;
00420                 
00421                 return (-1); /*the dialog manager's version of true*/
00422                 }
00423             
00424             if ((chkb == chescape) || ((chkb == '.') && flcmdkey)) { /*escape or cmd-period*/
00425                 
00426                 getresourcestring (cancelbuttonstring, bsbutton);
00427                 }
00428             else
00429                 setstringwithchar (chkb, bsbutton);
00430             
00431             if (dialogmapkeystroke (pdialog, bsbutton, item)) {
00432                 
00433                 if (MenuKey ((*ev).message & charCodeMask)) { /*will be handled by system*/
00434                     
00435                     HiliteMenu (0);
00436                     
00437                     break;
00438                     }
00439                 
00440                 if (!dialogsimulatehit (pdialog, *item))
00441                     return (0);
00442                 
00443                 return (-1);
00444                 }
00445             
00446             break; /*keydown or autokey*/
00447             }
00448         
00449         case updateEvt:
00450         
00451             if ((defaultitem > 0) && ((*ev).message == (long) pdialog))
00452                 boldenbutton (pdialog, defaultitem);
00453             
00454             break;
00455         
00456         case nullEvent:
00457             SelectWindow (pdialog); /*make sure no one has screwed around with us*/
00458             
00459             break;
00460         
00461         } /*switch*/
00462     
00463     return (0); /*the dialog manager's version of false*/
00464     } /*modaldialogcallback*/
00465 
00466 
00467 #if GENERATINGCFM
00468 
00469     static RoutineDescriptor modaldialogcallbackDesc = BUILD_ROUTINE_DESCRIPTOR (uppModalFilterProcInfo, modaldialogcallback);
00470     
00471     #define modaldialogcallbackUPP &modaldialogcallbackDesc
00472     
00473 #else
00474 
00475     #define modaldialogcallbackUPP &modaldialogcallback
00476 
00477 #endif
00478 
00479 
00480 
00481 short runmodaldialog (void) {
00482     
00483     short itemnumber;
00484     
00485     ModalDialog (modaldialogcallbackUPP, &itemnumber);
00486     
00487     return (itemnumber);
00488     } /*runmodaldialog*/
00489     
00490     
00491 boolean alertdialog (bigstring bs) {
00492     
00493     #define alertdialogid 128 
00494     #define alertokitem 1
00495     #define alertmsgitem 3
00496     register DialogPtr pdialog;
00497     
00498     if (!fldialogsenabled) {
00499         
00500         copystring (bs, bsalertstring);
00501         
00502         return (true);
00503         }
00504 
00505     sysbeep;
00506     
00507     parsedialogstring (bs);
00508     
00509     if ((pdialog = newmodaldialog (alertdialogid, alertokitem)) == nil)
00510         return (false);
00511     
00512     setdialogtext (pdialog, alertmsgitem, bs);
00513     
00514     ShowWindow (pdialog);
00515     
00516     runmodaldialog ();
00517     
00518     DisposDialog (pdialog);
00519     
00520     #ifdef fldebug
00521         if (optionkeydown ())
00522             DebugStr ("\pHello");
00523     #endif
00524     
00525     return (true);
00526     } /*alertdialog*/
00527     
00528     
00529 short savedialog (bigstring fname) {
00530     
00531     /*
00532     as the user to save changes before closing the file.
00533     
00534     we return 1 if they chose Yes, 2 for No, 3 for Cancel.
00535     */
00536     
00537     #define savedialogid 131 
00538     #define saveyesitem 1
00539     #define savenoitem 2
00540     #define savecancelitem 3
00541     #define savemsgitem 4
00542     register DialogPtr pdialog;
00543     bigstring bs;
00544     short choice;
00545     
00546     copystring ("\pSave “", bs);
00547     
00548     pushstring (fname, bs);
00549     
00550     pushstring ("\p” before closing?", bs);
00551     
00552     if ((pdialog = newmodaldialog (savedialogid, saveyesitem)) == nil)
00553         return (1);
00554     
00555     setdialogtext (pdialog, savemsgitem, bs);
00556     
00557     ShowWindow (pdialog);
00558     
00559     switch (runmodaldialog ()) {
00560         
00561         case saveyesitem:
00562             choice = 1;
00563             
00564             break;
00565             
00566         case savenoitem:
00567             choice = 2;
00568             
00569             break;
00570             
00571         case savecancelitem:
00572             choice = 3;
00573             
00574             break;
00575             
00576         } /*switch*/
00577     
00578     DisposDialog (pdialog);
00579     
00580     return (choice);
00581     } /*savedialog*/
00582 
00583 
00584 boolean confirmdialog (bigstring bs) {
00585     
00586     #define confirmdialogid 129 
00587     #define confirmokitem 1
00588     #define confirmcancelitem 2
00589     #define confirmmsgitem 3
00590     register DialogPtr pdialog;
00591     register short item;
00592     
00593     parsedialogstring (bs);
00594     
00595     if ((pdialog = newmodaldialog (confirmdialogid, confirmokitem)) == nil)
00596         return (false);
00597     
00598     setdialogtext (pdialog, confirmmsgitem, bs);
00599     
00600     ShowWindow (pdialog);
00601     
00602     item = runmodaldialog ();
00603     
00604     DisposDialog (pdialog);
00605     
00606     return (item == confirmokitem);
00607     } /*confirmdialog*/
00608 
00609 
00610 boolean yesnodialog (bigstring bs) {
00611     
00612     #define yesnodialogid 129 
00613     #define yesnookitem 1
00614     #define yesnocancelitem 2
00615     #define yesnomsgitem 3
00616     register DialogPtr pdialog;
00617     register short item;
00618     
00619     parsedialogstring (bs);
00620     
00621     if ((pdialog = newmodaldialog (yesnodialogid, yesnookitem)) == nil)
00622         return (false);
00623     
00624     setdialogtext (pdialog, yesnomsgitem, bs);
00625     
00626     dialogsetbuttonstring (pdialog, yesnookitem, "\pYes");
00627     
00628     dialogsetbuttonstring (pdialog, yesnocancelitem, "\pNo");
00629     
00630     ShowWindow (pdialog);
00631     
00632     item = runmodaldialog ();
00633     
00634     DisposDialog (pdialog);
00635     
00636     return (item == yesnookitem);
00637     } /*yesnodialog*/
00638 
00639 
00640 short threewaydialog (bigstring bsprompt, bigstring leftbutton, bigstring midbutton, bigstring rightbutton) {
00641     
00642     #define threewaydialogid 131 
00643     #define leftbuttonitem 3
00644     #define midbuttonitem 2
00645     #define rightbuttonitem 1
00646     #define messageitem 4
00647     register DialogPtr pdialog;
00648     register short item;
00649     
00650     parsedialogstring (bsprompt);
00651     
00652     if ((pdialog = newmodaldialog (threewaydialogid, rightbuttonitem)) == nil)
00653         return (false);
00654     
00655     setdialogtext (pdialog, messageitem, bsprompt);
00656     
00657     dialogsetbuttonstring (pdialog, leftbuttonitem, leftbutton);
00658     
00659     dialogsetbuttonstring (pdialog, midbuttonitem, midbutton);
00660     
00661     dialogsetbuttonstring (pdialog, rightbuttonitem, rightbutton);
00662     
00663     ShowWindow (pdialog);
00664     
00665     item = runmodaldialog ();
00666     
00667     DisposDialog (pdialog);
00668     
00669     switch (item) {
00670         
00671         case leftbuttonitem:
00672             return (3);
00673             
00674         case midbuttonitem:
00675             return (2);
00676             
00677         case rightbuttonitem:
00678         default:
00679             return (1);
00680         } /*switch*/
00681     } /*threewaydialog*/
00682     
00683     
00684 boolean askdialog (bigstring bsprompt, bigstring bsanswer) {
00685     
00686     /*
00687     put up the standard "ask" dialog, with the provided prompt and return
00688     true if the user clicked on ok.  the answer is in bsanswer.
00689     */
00690     
00691     #define askdialogid 130
00692     #define askokitem 1
00693     #define askcancelitem 2
00694     #define askpromptitem 3
00695     #define askansweritem 4 
00696     register DialogPtr pdialog;
00697     register short itemnumber;
00698     
00699     ParamText (bsprompt, emptystring, emptystring, emptystring);
00700     
00701     if ((pdialog = newmodaldialog (askdialogid, askokitem)) == nil)
00702         return (false);
00703     
00704     setdialogtext (pdialog, askansweritem, bsanswer);
00705     
00706     selectdialogtext (pdialog, askansweritem);
00707     
00708     ShowWindow (pdialog);
00709     
00710     itemnumber = runmodaldialog ();
00711     
00712     getdialogtext (pdialog, askansweritem, bsanswer);
00713     
00714     DisposDialog (pdialog);
00715     
00716     return (itemnumber == askokitem);
00717     } /*askdialog*/
00718 
00719 
00720 boolean oserror (OSErr errcode) {
00721     
00722     bigstring bs;
00723     
00724     if (errcode == noErr)
00725         return (false);
00726     
00727     copystring ("\pMacintosh OS Error = ", bs);
00728     
00729     pushint (errcode, bs);
00730     
00731     alertdialog (bs);
00732     
00733     return (true);
00734     } /*oserror*/
00735     
00736     

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