appletmain.c

Go to the documentation of this file.
00001 
00002 /*  $Id: appletmain.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 
00009 #include <iac.h>
00010 #include <iowacore.h>
00011 #include "appletinternal.h"
00012 #include "appletmsg.h"
00013 #include "appletmain.h"
00014 #include "appletmenu.h"
00015 #include "appletscrollbar.h"
00016 #include "appletmenuops.h"
00017 #include "appletresource.h"
00018 #include "appletidle.h"
00019 #include "appletwires.h"
00020 #include "appletfilemodified.h"
00021 #include "appletsyserror.h"
00022 
00023 
00024 
00025 #define fldoublestatusline false /*set true if you want a double line separating status bar from window content*/
00026 
00027 #define saveasprompt "\pSave As…"
00028 
00029 #define openprompt "\pOpen…"
00030 
00031 
00032 /*
00033 7/25/94 dmb: updated old-style function declarations
00034 */
00035 
00036 /*
00037 for communication with the applet body code -- it has copies of all the globals,
00038 and pointers to the callback routines that define the applet.
00039 */
00040     tyappletrecord app;
00041 
00042 /*
00043 globals used by the window visiter.
00044 */
00045     ptrfilespec pfsvisit;
00046     AEDesc *prefconvisit;
00047     bigstring bsvisit;
00048     short x1, x2; /*two short registers for visit routines*/
00049     hdlappwindow lastwindowvisited;
00050     
00051     
00052 /*
00053 set true if the last event was a keystroke and it was cmd-period.
00054 */
00055     boolean flcmdperiod = false;
00056     
00057 
00058 /*
00059 for fast events, we need to store a pointer to our application heap, so any
00060 allocations we do happen in the right heap.
00061 */
00062     static THz appletheapzone;
00063 
00064 
00065 typedef struct tydiskwindowinfo { /*saved on disk after the applet's data handle*/
00066     
00067     short versionnumber;
00068     
00069     Rect windowrect;
00070     
00071     short vertmin, vertmax, vertcurrent;
00072     
00073     short horizmin, horizmax, horizcurrent;
00074     
00075     diskfontstring defaultfontstring;
00076     
00077     short defaultsize;
00078     
00079     tyjustification defaultjustification;
00080     
00081     char waste [64]; /*room to grow*/
00082     } tydiskwindowinfo;
00083     
00084 EventRecord appletevent; /*the last event received by appletmain.c*/
00085     
00086 boolean flexitmainloop = false;
00087 
00088 
00089 #define nowindowerror 7 /*index into the verb error STR# list*/
00090 #define windowopenerror 8
00091 #define nopictcallbackerror 9
00092 #define notextcallbackerror 10
00093 #define noputtextcallbackerror 11
00094 #define noputpictcallbackerror 12
00095 
00096 
00097 static boolean flcurrentlyactive = true; /*we start active, then get juggled*/
00098 
00099 
00100 #define jugglerEvt 15 /*a suspend/resume event from the OS to us*/
00101 
00102 typedef struct tyjugglermessage {
00103     
00104     long eventtype: 8; /*bits 24 -- 31*/
00105     
00106     long reservedbits: 22; /*bits 2 -- 23*/
00107     
00108     long flconvertclipboard: 1; /*bit 1*/
00109     
00110     long flresume: 1; /*bit 0*/
00111     } tyjugglermessage;
00112 
00113 
00114 enum { /*key codes*/
00115     
00116     clearkey = 0x47,
00117     
00118     helpkey = 0x72,
00119     
00120     homekey = 0x73,
00121     
00122     endkey = 0x77,
00123     
00124     pgupkey = 0x74,
00125     
00126     pgdnkey = 0x79
00127     };
00128 
00129 
00130 
00131 
00132 static boolean filterfunctionkey (long *codeword) {
00133     
00134     short item;
00135     short menu = editmenu;
00136     
00137     switch (keyboardstatus.keycode) {
00138         
00139         case 'z':
00140             item = undoitem;
00141             
00142             break;
00143         
00144         case 'x':
00145             item = cutitem;
00146             
00147             break;
00148         
00149         case 'c':
00150             item = copyitem;
00151             
00152             break;
00153         
00154         case 'v':
00155             item = pasteitem;
00156             
00157             break;
00158         
00159         case clearkey:
00160             item = clearitem;
00161             
00162             break;
00163         
00164         case helpkey:
00165             item = helpitem;
00166             
00167             menu = extendedmenu;
00168             
00169             break;
00170             
00171         case homekey:
00172             item = homeitem;
00173             
00174             menu = extendedmenu;
00175             
00176             break;
00177             
00178         case endkey:
00179             item = enditem;
00180             
00181             menu = extendedmenu;
00182             
00183             break;
00184             
00185         case pgupkey:
00186             item = pageupitem;
00187             
00188             menu = extendedmenu;
00189             
00190             break;
00191             
00192         case pgdnkey:
00193             item = pagedownitem;
00194             
00195             menu = extendedmenu;
00196             
00197             break;
00198         
00199         default:
00200             return (false);
00201         } /*switch*/
00202     
00203     *codeword = ((long) menu << 16) + item;
00204     
00205     return (true);
00206     } /*filterfunctionkey*/
00207 
00208 
00209 void apperaserect (Rect r) {
00210     
00211     appprecallback ();
00212     
00213     pushclip (r);
00214     
00215     (*app.eraserectcallback) (r);
00216     
00217     popclip ();
00218     
00219     apppostcallback ();
00220     } /*apperaserect*/
00221     
00222 
00223 void setselectionstyleinfo (tyselectioninfo *pselinfo, boolean flpack) {
00224     
00225     union {
00226         
00227         short fontstyle;
00228         
00229         struct {
00230             
00231             int extrabits: 7; /*highest-order 7 bits are unused*/
00232             
00233             boolean flsubscript: 1;
00234             
00235             boolean flsuperscript: 1;
00236             
00237             boolean flextended: 1; /*not currently used*/
00238             
00239             boolean flcondensed: 1;
00240             
00241             boolean flshadow: 1;
00242             
00243             boolean floutline: 1;
00244             
00245             boolean flunderline: 1;
00246             
00247             boolean flitalic: 1;
00248             
00249             boolean flbold: 1;
00250             } stylebits;
00251         } u;
00252     
00253     tyselectioninfo x = *pselinfo;
00254     
00255     if (flpack) {
00256         
00257         u.fontstyle = 0; /*clear all bits*/
00258         
00259         u.stylebits.flsubscript = x.flsubscript;
00260         
00261         u.stylebits.flsuperscript = x.flsuperscript;
00262         
00263         u.stylebits.flextended = x.flextended;
00264         
00265         u.stylebits.flcondensed = x.flcondensed;
00266         
00267         u.stylebits.flshadow = x.flshadow;
00268         
00269         u.stylebits.floutline = x.floutline;
00270         
00271         u.stylebits.flunderline = x.flunderline;
00272         
00273         u.stylebits.flitalic = x.flitalic;
00274         
00275         u.stylebits.flbold = x.flbold;
00276         
00277         x.fontstyle = u.fontstyle;
00278         }
00279     else {
00280         u.fontstyle = x.fontstyle;
00281         
00282         x.flsubscript = bitboolean (u.stylebits.flsubscript);
00283         
00284         x.flsuperscript = bitboolean (u.stylebits.flsuperscript);
00285         
00286         x.flextended = bitboolean (u.stylebits.flextended);
00287         
00288         x.flcondensed = bitboolean (u.stylebits.flcondensed);
00289         
00290         x.flshadow = bitboolean (u.stylebits.flshadow);
00291         
00292         x.floutline = bitboolean (u.stylebits.floutline);
00293         
00294         x.flunderline = bitboolean (u.stylebits.flunderline);
00295         
00296         x.flitalic = bitboolean (u.stylebits.flitalic);
00297         
00298         x.flbold = bitboolean (u.stylebits.flbold);     
00299         }
00300     
00301     *pselinfo = x;
00302     } /*setselectionstyleinfo*/
00303     
00304         
00305 static void getgrowiconrect (hdlappwindow appwindow, Rect *rgrowicon) {
00306     
00307     WindowPtr w = (**appwindow).macwindow;
00308     Rect r;
00309     
00310     r = (*w).portRect;
00311     
00312     r.left = r.right - 15;
00313     
00314     r.top = r.bottom - 15;
00315     
00316     *rgrowicon = r;
00317     } /*getgrowiconrect*/
00318     
00319 
00320 void drawappgrowicon (hdlappwindow appwindow) {
00321     
00322     /*
00323     DW 6/24/93: made it so that it always just draws the grow
00324     icon, it never draws the lines for the scroll bars. this
00325     overwrote the status bar in clay basket. the scroll bars
00326     take care of updating these lines anyway.
00327     */
00328     
00329     WindowPtr w = (**appwindow).macwindow;
00330     Rect rclip;
00331         
00332     if ((**appwindow).flprinting)
00333         return;
00334         
00335     getgrowiconrect (appwindow, &rclip);
00336     
00337     pushclip (rclip);
00338     
00339     DrawGrowIcon (w);
00340     
00341     popclip ();
00342     } /*drawappgrowicon*/
00343     
00344 
00345 boolean apppushwindow (hdlappwindow appwindow) {
00346     
00347     return (pushmacport ((**appwindow).macwindow));
00348     } /*apppushwindow*/
00349     
00350 
00351 boolean apppopwindow (void) {
00352     
00353     return (popmacport ());
00354     } /*apppopwindow*/
00355     
00356     
00357 boolean apppushclip (Rect r) {
00358 
00359     /*
00360     this front-end for pushclip respects the current settings of the origin. applets
00361     should call this routine instead of calling the quickdraw.c routine.
00362     */
00363     
00364     hdlappwindow ha = app.appwindow;
00365     
00366     if (!pushclip (r))
00367         return (false);
00368     
00369     if ((**ha).originpushdepth > 0) 
00370         OffsetRgn ((*(**ha).macwindow).clipRgn, -(**ha).scrollorigin.h, -(**ha).scrollorigin.v);
00371     
00372     return (true);
00373     } /*apppushclip*/
00374     
00375     
00376 boolean apppopclip (void) {
00377 
00378     /*
00379     this front-end for popclip respects the current settings of the origin. applets
00380     should call this routine instead of calling the quickdraw.c routine.
00381     */
00382     
00383     hdlappwindow ha = app.appwindow;
00384     
00385     if (!popclip ())
00386         return (false);
00387     
00388     if ((**ha).originpushdepth > 0) 
00389         OffsetRgn ((*(**ha).macwindow).clipRgn, -(**ha).scrollorigin.h, -(**ha).scrollorigin.v);
00390 
00391     return (true);
00392     } /*apppopclip*/
00393     
00394 
00395 void appprecallback (void) {
00396     
00397     hdlappwindow ha = app.appwindow;
00398     
00399     if (ha != nil) {
00400         
00401         WindowPtr w = (**ha).macwindow;
00402         
00403         pushmacport (w);
00404         
00405         pushclip ((**ha).contentrect);
00406             
00407         (**ha).originpushdepth++;
00408         
00409         if ((**ha).originpushdepth == 1) { 
00410             
00411             SetOrigin ((**ha).scrollorigin.h, (**ha).scrollorigin.v);
00412         
00413             OffsetRgn ((*w).clipRgn, (**ha).scrollorigin.h, (**ha).scrollorigin.v);
00414             }
00415         }
00416     
00417     (*app.setglobalscallback) (); 
00418     } /*appprecallback*/
00419     
00420     
00421 void apppostcallback (void) {
00422     
00423     hdlappwindow ha = app.appwindow;
00424     
00425     if (app.dontpostcallback) { /*applet already did the post-callback call*/
00426         
00427         app.dontpostcallback = false; /*must be reset every time*/
00428         
00429         return;
00430         }
00431     
00432     if (ha != nil) {
00433         
00434         (**ha).originpushdepth--;
00435     
00436         if ((**ha).originpushdepth == 0) { 
00437             
00438             WindowPtr w = (**ha).macwindow;
00439             
00440             pushmacport (w);
00441             
00442             OffsetRgn ((*w).clipRgn, -(**ha).scrollorigin.h, -(**ha).scrollorigin.v);
00443         
00444             SetOrigin (0, 0);
00445             
00446             popmacport ();
00447             }
00448         
00449         popclip ();
00450         
00451         popmacport ();
00452         }
00453     } /*apppostcallback*/
00454     
00455     
00456 boolean appopenbitmap (Rect r, hdlappwindow appwindow) {
00457     
00458     return (openbitmap (r, (**appwindow).macwindow));
00459     } /*appopenbitmap*/
00460     
00461 
00462 boolean appclosebitmap (hdlappwindow appwindow) {
00463     
00464     closebitmap ((**appwindow).macwindow);
00465     
00466     return (true);
00467     } /*appclosebitmap*/
00468     
00469 
00470 boolean getappwindow (WindowPtr w, hdlappwindow *appwindow) {
00471     
00472     hdlappwindow ha;
00473     
00474     if (w == nil) /*it can happen: when using FrontWindow, and no window is open*/
00475         return (false);
00476     
00477     #ifdef appRunsCards
00478     
00479         if (isCardWindow (w))
00480             return (false);
00481     
00482     #endif
00483     
00484     ha = (hdlappwindow) GetWRefCon (w);
00485     
00486     *appwindow = ha;
00487     
00488     return (ha != nil);
00489     } /*getappwindow*/
00490     
00491     
00492 boolean findappwindow (Point pt, hdlappwindow *appwindow) {
00493     
00494     short part;
00495     WindowPtr w;
00496     
00497     *appwindow = nil; /*default*/
00498         
00499     part = FindWindow (pt, &w);
00500     
00501     if (w == nil) /*not pointing at any window*/
00502         return (false);
00503         
00504     return (getappwindow (w, appwindow));
00505     } /*findappwindow*/
00506 
00507 
00508 void getappdata (WindowPtr w, Handle *appdata) {
00509     
00510     hdlappwindow appwindow;
00511     
00512     if (getappwindow (w, &appwindow))
00513         *appdata = (**appwindow).appdata;
00514     else
00515         *appdata = nil;
00516     } /*getappdata*/
00517     
00518 
00519 void getappwindowtitle (hdlappwindow appwindow, bigstring bs) {
00520     
00521     if (appwindow == nil)
00522         setstringlength (bs, 0);
00523     else
00524         GetWTitle ((**appwindow).macwindow, bs);
00525     } /*getappwindowtitle*/
00526     
00527     
00528 void setappwindowtitle (hdlappwindow appwindow, bigstring bs) {
00529     
00530     SetWTitle ((**appwindow).macwindow, bs);
00531     } /*setappwindowtitle*/
00532     
00533     
00534 void hideappwindow (hdlappwindow appwindow) {
00535     
00536     HideWindow ((**appwindow).macwindow);
00537     } /*hideappwindow*/
00538     
00539 
00540 void setappwindowmadechanges (hdlappwindow appwindow) {
00541     
00542     assert (appwindow != nil);
00543     
00544     (**appwindow).flmadechanges = true;
00545     } /*setappwindowmadechanges*/
00546     
00547     
00548 boolean frontappwindow (hdlappwindow appwindow) {
00549     
00550     assert (appwindow != nil);
00551     
00552     return ((**appwindow).macwindow == FrontWindow ());
00553     } /*frontappwindow*/
00554     
00555     
00556 static void getappfilename (hdlappwindow appwindow, bigstring bs) {
00557     
00558     filegetfilename (&(**appwindow).filespec, bs);
00559     } /*getappfilename*/
00560     
00561 
00562 void getappwindowfilespec (hdlappwindow appwindow, ptrfilespec pfs) {
00563 
00564     hdlappwindow ha = appwindow;
00565     
00566     if ((**appwindow).fnum == 0) 
00567         clearbytes (pfs, longsizeof (tyfilespec)); /*Iowa 1.0b15*/
00568     else
00569         *pfs = (**ha).filespec;
00570     } /*getappwindowfilespec*/
00571     
00572         
00573 void showappwindow (hdlappwindow appwindow) {
00574     
00575     ShowWindow ((**appwindow).macwindow);
00576     } /*showappwindow*/
00577     
00578     
00579 void selectappwindow (hdlappwindow appwindow) {
00580 
00581     SelectWindow ((**appwindow).macwindow);
00582     } /*selectappwindow*/
00583     
00584     
00585 void invalappwindow (hdlappwindow appwindow, boolean flerase) {
00586     
00587     Rect r;
00588     
00589     pushmacport ((**appwindow).macwindow); 
00590     
00591     r = (**appwindow).windowrect;
00592     
00593     invalrect (r);
00594     
00595     if (flerase) 
00596         apperaserect (r);
00597         
00598     popmacport ();
00599     } /*invalappwindow*/
00600     
00601     
00602 void setappwindow (hdlappwindow appwindow) {
00603     
00604     app.appwindow = appwindow;
00605         
00606     if (appwindow == nil) {
00607         
00608         app.appdata = nil;
00609         
00610         undostack = nil;
00611         
00612         redostack = nil;
00613         }
00614     else {
00615         SetPort ((**appwindow).macwindow);
00616         
00617         ClipRect (&(**appwindow).contentrect);
00618         
00619         undostack = (hdlundostack) (**appwindow).undostack;
00620         
00621         redostack = (hdlundostack) (**appwindow).redostack;
00622         
00623         app.appdata = (**appwindow).appdata;
00624         
00625         (*app.setglobalscallback) (); /*app can copy from app.appdata to its own globals*/
00626         }
00627     } /*setappwindow*/
00628     
00629     
00630 boolean apprectneedsupdate (Rect r) {
00631     
00632     WindowPtr w = (**app.appwindow).macwindow;
00633     
00634     return (RectInRgn (&r, (*w).visRgn));
00635     } /*apprectneedsupdate*/
00636     
00637     
00638 void appinvalstatusseparator (void) {
00639     
00640     if (fldoublestatusline) {
00641     
00642         Rect r = (**app.appwindow).statusrect;
00643     
00644         r.top = r.bottom;
00645     
00646         r.bottom += 2;
00647     
00648         InvalRect (&r);
00649         }
00650     } /*appinvalstatusseparator*/
00651     
00652     
00653 void updateappwindow (hdlappwindow appwindow) {
00654     
00655     /*
00656     DW 4/24/92: reordered things for IOWA.
00657     
00658     DW 4/25/92: added updating of palette.
00659     
00660     DW 4/30/92: added pre-update callback to allow IOWA to inval all dirty objects.
00661     
00662     DW 3/18/93: reordered things again to make IOWA look nice. just staging.
00663     */
00664     
00665     hdlappwindow ha = appwindow;
00666     WindowPtr w = (**ha).macwindow;
00667     Rect rwindow = (*w).portRect;
00668     Rect rstatus = (**ha).statusrect;
00669     
00670     BeginUpdate (w);
00671     
00672     setappwindow (ha);
00673     
00674     /*update the status area*/ {
00675         
00676         if ((**ha).statuspixels > 0) { /*has a status area*/
00677             
00678             Rect r = rstatus;
00679                 
00680             if (apprectneedsupdate (r)) {
00681             
00682                 pushclip (r);
00683                 
00684                 (*app.updatestatuscallback) ();
00685                 
00686                 MoveTo (r.left, r.bottom - 1);
00687                 
00688                 LineTo (r.right, r.bottom - 1);
00689             
00690                 popclip ();
00691                 }
00692             
00693             if (fldoublestatusline) {
00694             
00695                 r.top = r.bottom;
00696                 
00697                 r.bottom += 4;
00698                 
00699                 if (apprectneedsupdate (r)) { /*draw the double separator line*/
00700                     
00701                     r.bottom -= 2;
00702                     
00703                     pushclip (rwindow);
00704                     
00705                     apperaserect (r);
00706                     
00707                     MoveTo (r.left, r.bottom);
00708             
00709                     LineTo (r.right, r.bottom);
00710                     
00711                     popclip ();
00712                     }
00713                 }
00714             }
00715         }
00716         
00717     /*update the palette*/ {
00718         
00719         if (app.haspalette) {
00720         
00721             if (apprectneedsupdate ((**(**ha).hpalette).r)) {
00722             
00723                 pushclip (rwindow);
00724             
00725                 paletteupdate ((**ha).hpalette);
00726         
00727                 popclip ();
00728                 }
00729             }
00730         }
00731         
00732     /*update the grow icon, scrollbars*/ {
00733         
00734         Rect r;
00735         
00736         pushclip (rwindow);
00737         
00738         getgrowiconrect (ha, &r);
00739         
00740         if (apprectneedsupdate (r)) 
00741             drawappgrowicon (ha);
00742             
00743         appdrawmessage (ha);
00744 
00745         updateappscrollbars (ha);
00746         
00747         popclip ();
00748         }
00749         
00750     /*let the applet update his stuff*/ {
00751         
00752         Rect rcontent = (**ha).contentrect;
00753         
00754         if (apprectneedsupdate (rcontent)) {
00755             
00756             appprecallback ();
00757             
00758             (**ha).updaterect = (**(*w).visRgn).rgnBBox;
00759             
00760             (*app.setglobalscallback) (); /*app can copy from app.appdata to its own globals*/
00761             
00762             (*app.updatecallback) ();
00763             
00764             apppostcallback ();
00765             }
00766         }
00767         
00768     /*for BarChart and Card Editor, no scroll bars, may need redraw of grow icon*/ {
00769         
00770         Rect r;
00771         
00772         getgrowiconrect (ha, &r);
00773         
00774         if (apprectneedsupdate (r)) 
00775             drawappgrowicon (ha);
00776         }
00777         
00778     EndUpdate (w);
00779     } /*updateappwindow*/
00780     
00781     
00782 void computewindowinfo (WindowPtr macwindow, hdlappwindow appwindow) {
00783     
00784     WindowPtr w = macwindow;
00785     hdlappwindow ha = appwindow;
00786     hdlpaletterecord hpal = (hdlpaletterecord) (**appwindow).hpalette;
00787     Rect r, rcontent, rstatus, rpalette;
00788     
00789     (**ha).windowrect = r = (*w).portRect;
00790     
00791     rcontent = r;
00792     
00793     /*take out for scrollbars*/ {
00794         
00795         short scrollbarwidth = getscrollbarwidth ();
00796         
00797         if (app.vertscroll)
00798             rcontent.right -= scrollbarwidth - 1;
00799         
00800         if (app.horizscroll)
00801             rcontent.bottom -= scrollbarwidth - 1;
00802         }
00803     
00804     if ((**ha).statuspixels > 0) { /*has a status area*/
00805     
00806         rcontent.top += (**ha).statuspixels;
00807         
00808         if (fldoublestatusline)
00809             rcontent.top += 3; /*a 3-pixel tall area separates status & content*/
00810         }
00811         
00812     if (app.haspalette) { /*has an icon palette*/
00813         
00814         rpalette = rcontent;
00815         
00816         rcontent.left += (**hpal).palettewidth;
00817         
00818         rpalette.right = rcontent.left;
00819         }
00820     else
00821         zerorect (&rpalette);   
00822     
00823     (**ha).oldcontentrect = (**ha).contentrect;
00824         
00825     (**ha).contentrect = rcontent;
00826     
00827     if (app.haspalette) 
00828         (**(**ha).hpalette).r = rpalette;
00829     
00830     rstatus = r; /*copy left, right, top*/
00831     
00832     rstatus.bottom = rstatus.top + (**ha).statuspixels;
00833     
00834     (**ha).statusrect = rstatus;
00835     
00836     (**ha).windowvertpixels = r.bottom - r.top;
00837     
00838     (**ha).windowhorizpixels = r.right - r.left;
00839     
00840     pushmacport (w);
00841     
00842     pushstyle ((**ha).defaultfont, (**ha).defaultsize, (**ha).defaultstyle);
00843     
00844     (**ha).fontheight = globalfontinfo.ascent + globalfontinfo.descent;
00845     
00846     popstyle ();
00847     
00848     popmacport ();
00849     
00850     (**ha).macwindow = w;
00851     } /*computewindowinfo*/
00852     
00853 
00854 void appgetdesktoprect (hdlappwindow appwindow, Rect *rwindow) {
00855     
00856     WindowPtr w = (**appwindow).macwindow;
00857     
00858     *rwindow = (*w).portRect;
00859     
00860     pushmacport (w);
00861             
00862     localtoglobalrect (rwindow);
00863             
00864     popmacport ();
00865     } /*appgetdesktoprect*/
00866     
00867     
00868 void disposeappwindow (hdlappwindow appwindow) {
00869     
00870     hdlappwindow ha = app.appwindow;
00871     WindowPtr w;
00872     
00873     if (ha == nil) /*4.1b1 dmb: allow for nil*/
00874         return;
00875     
00876     w = (**ha).macwindow;
00877     
00878     appprecallback ();
00879     
00880     (*app.disposerecordcallback) ();
00881     
00882     apppostcallback ();
00883     
00884     if (app.haspalette) 
00885         disposepalette ((hdlpaletterecord) (**ha).hpalette);
00886     
00887     disposescrollbar ((**ha).vertbar);
00888     
00889     disposescrollbar ((**ha).horizbar);
00890     
00891     disposeundostack ((hdlundostack) (**ha).undostack);
00892     
00893     disposeundostack ((hdlundostack) (**ha).redostack);
00894     
00895     DisposeWindow (w);
00896     
00897     AEDisposeDesc (&(**ha).iacdatarefcon); /*4.1b1 dmb*/
00898     
00899     disposehandle ((Handle) ha);
00900     
00901     setfrontglobals ();
00902     } /*disposeappwindow*/
00903     
00904 
00905 typedef boolean (*tyvisitapproutine) (hdlappwindow);
00906 
00907 
00908 boolean visitappwindows (tyvisitapproutine visitproc) {
00909     
00910     /*
00911     visit all the windows from front to back.  call the visitproc for each window, 
00912     if it returns false we stop the traversal and return false.
00913     
00914     the visitproc takes one parameter -- a hdlappwindow, indicating the window
00915     to be visited.
00916     
00917     return true if all the visits returned true.
00918     
00919     9/4/91 DW: add lastwindowvisited -- returns nil if no match found, returns
00920     pointing to the appwindow record for the window that matched the visitproc's
00921     criteria.
00922     */
00923     
00924     WindowPtr w = FrontWindow (), wnext;
00925     hdlappwindow appwindow;
00926     
00927     lastwindowvisited = nil;
00928     
00929     while (w != nil) {
00930         
00931         wnext = (WindowPtr) (*(WindowPeek) w).nextWindow; /*allow the visit callback to close the window*/
00932         
00933         if (!getappwindow (w, &appwindow))
00934             goto next;
00935         
00936         if (!(*visitproc) (appwindow)) { /*stop the traversal*/
00937         
00938             lastwindowvisited = appwindow; /*set global*/
00939             
00940             return (false);
00941             }
00942         
00943         next:
00944         
00945         w = wnext; 
00946         } /*while*/
00947         
00948     return (true); /*completed the traversal*/
00949     } /*visitappwindows*/
00950     
00951 
00952 boolean selectvisit (hdlappwindow appwindow) {
00953     
00954     bigstring bs;
00955     
00956     getappwindowtitle (appwindow, bs);
00957     
00958     if (!equalstrings (bsvisit, bs)) /*no match -- keep traversing*/
00959         return (true);
00960     
00961     /*found a match, select the window, stop the traversal*/
00962     
00963     selectappwindow (appwindow);
00964         
00965     return (false); /*stop the traversal*/
00966     } /*selectvisit*/
00967     
00968     
00969 boolean selectwindowbytitle (bigstring bs) {
00970 
00971     /*
00972     visit all the windows from front to back.  when we encounter one of the 
00973     app's windows check the window title.  if it equals bs, then select the 
00974     window and set the globals accordingly.
00975     
00976     return false if there is no app window with that name.
00977     */
00978     
00979     copystring (bs, bsvisit); /*copy into global so visit routine can access*/
00980     
00981     return (!visitappwindows (&selectvisit));
00982     } /*selectwindowbytitle*/   
00983     
00984     
00985 boolean findbytitlevisit (hdlappwindow appwindow) {
00986     
00987     bigstring bs;
00988     
00989     getappwindowtitle (appwindow, bs);
00990     
00991     if (!equalstrings (bsvisit, bs)) /*no match -- keep traversing*/
00992         return (true);
00993     
00994     return (false); /*stop the traversal*/
00995     } /*findbytitlevisit*/
00996     
00997     
00998 boolean findbywindowtitle (bigstring bstitle, hdlappwindow *appwindow) {
00999 
01000     copystring (bstitle, bsvisit); /*copy into global so visit routine can access*/
01001     
01002     visitappwindows (&findbytitlevisit);
01003     
01004     if (lastwindowvisited == nil)
01005         return (false);
01006         
01007     *appwindow = lastwindowvisited;
01008     
01009     return (true);
01010     } /*findbywindowtitle*/
01011     
01012     
01013 boolean findnthvisit (hdlappwindow appwindow) {
01014     
01015     return (++x2 < x1); /*visit until they're equal*/
01016     } /*findnthvisit*/
01017     
01018     
01019 boolean findnthwindow (short n, hdlappwindow *appwindow) {
01020     
01021     x1 = n; /*copy into a "register" for visit routine*/
01022     
01023     x2 = 0; /*another register*/
01024     
01025     visitappwindows (&findnthvisit);
01026     
01027     *appwindow = lastwindowvisited;
01028     
01029     return (lastwindowvisited != nil);
01030     } /*findnthwindow*/
01031     
01032     
01033 boolean countwindowsvisit (hdlappwindow appwindow) {
01034     
01035     x1++;
01036     
01037     return (true); /*keep going*/
01038     } /*countwindowsvisit*/
01039     
01040     
01041 short countwindows (void) {
01042     
01043     x1 = 0; /*copy into a "register" for visit routine*/
01044     
01045     visitappwindows (&countwindowsvisit);
01046     
01047     return (x1);
01048     } /*countwindows*/
01049     
01050     
01051 boolean resetdirtyscrollbarsvisit (hdlappwindow appwindow) {
01052     
01053     register hdlappwindow ha = appwindow;
01054     
01055     setappwindow (ha);
01056     
01057     if ((**ha).flresetscrollbars) {
01058         
01059         resetappscrollbars (ha);
01060         
01061         (**ha).flresetscrollbars = false; /*consume it*/
01062         }
01063     
01064     return (true); /*visit all open windows*/
01065     } /*resetdirtyscrollbarsvisit*/
01066     
01067     
01068 boolean resetdirtyscrollbars (void) {
01069 
01070     visitappwindows (&resetdirtyscrollbarsvisit);
01071     
01072     return (true);
01073     } /*resetdirtyscrollbars*/
01074     
01075     
01076 boolean getuntitledtitle (bigstring bs) {
01077     
01078     long ct = 1;
01079     hdlappwindow appwindow;
01080     
01081     while (true) {
01082         
01083         copystring ("\pUntitled ", bs);
01084         
01085         pushlong (ct++, bs);
01086         
01087         if (!findbywindowtitle (bs, &appwindow))
01088             return (true);
01089         } /*while*/
01090     } /*getuntitledtitle*/
01091     
01092 
01093 static boolean findbyfilevisit (hdlappwindow appwindow) {
01094     
01095     return (!equalfilespecs (&(**appwindow).filespec, pfsvisit));
01096     } /*findbyfilevisit*/
01097     
01098     
01099 boolean findbyfile (ptrfilespec pfs, hdlappwindow *appwindow) {
01100     
01101     pfsvisit = pfs;
01102     
01103     visitappwindows (&findbyfilevisit);
01104     
01105     if (lastwindowvisited == nil)
01106         return (false);
01107         
01108     *appwindow = lastwindowvisited;
01109     
01110     return (true);
01111     } /*findbyfile*/
01112 
01113 
01114 static boolean findbyrefconvisit (hdlappwindow appwindow) {
01115     
01116     if ((**appwindow).iacdatarefcon.descriptorType != (*prefconvisit).descriptorType)
01117         return (true);
01118     
01119     return (!equalhandles ((**appwindow).iacdatarefcon.dataHandle, (*prefconvisit).dataHandle));
01120     } /*findbyrefconvisit*/
01121 
01122 
01123 static boolean findbyrefcon (AEDesc *refon, hdlappwindow *appwindow) {
01124     
01125     prefconvisit = refon;
01126     
01127     visitappwindows (&findbyrefconvisit);
01128     
01129     if (lastwindowvisited == nil)
01130         return (false);
01131     
01132     *appwindow = lastwindowvisited;
01133     
01134     return (true);
01135     } /*findbyrefcon*/
01136 
01137 
01138 boolean setfrontglobalsvisit (hdlappwindow appwindow) {
01139     
01140     setappwindow (appwindow);
01141     
01142     return (false); /*stop the traversal*/
01143     } /*setfrontglobalsvisit*/
01144     
01145     
01146 boolean setfrontglobals (void) {
01147     
01148     setappwindow (nil);
01149     
01150     visitappwindows (&setfrontglobalsvisit);
01151     
01152     return (app.appwindow != nil);
01153     } /*setfrontglobals*/
01154 
01155 
01156 void moveappwindow (hdlappwindow appwindow, Rect r) {
01157     
01158     WindowPtr w = (**appwindow).macwindow;
01159         
01160     constraintodesktop (&r);
01161     
01162     SizeWindow (w, r.right - r.left, r.bottom - r.top, true);
01163     
01164     MoveWindow (w, r.left, r.top, false);
01165     
01166     computewindowinfo (w, appwindow);
01167     
01168     resizeappscrollbars (appwindow);
01169     
01170     resetappscrollbars (appwindow);
01171     } /*moveappwindow*/
01172     
01173 
01174 static void saveappwindowinfo (hdlappwindow appwindow, tydiskwindowinfo *appwindowinfo) {
01175     
01176     hdlappwindow ha = appwindow;
01177     tydiskwindowinfo x;
01178     
01179     clearbytes (&x, longsizeof (x));
01180     
01181     x.versionnumber = 1;
01182     
01183     appgetdesktoprect (ha, &x.windowrect);
01184     
01185     getscrollbarinfo ((**ha).vertbar, &x.vertmin, &x.vertmax, &x.vertcurrent);
01186     
01187     getscrollbarinfo ((**ha).horizbar, &x.horizmin, &x.horizmax, &x.horizcurrent);
01188     
01189     x.defaultsize = (**ha).defaultsize;
01190     
01191     x.defaultjustification = (**ha).defaultjustification;
01192     
01193     diskgetfontname ((**ha).defaultfont, x.defaultfontstring);
01194     
01195     *appwindowinfo = x;
01196     } /*saveappwindowinfo*/
01197     
01198 
01199 static void loadappwindowinfo (hdlappwindow appwindow, tydiskwindowinfo appwindowinfo) {
01200     
01201     hdlappwindow ha = appwindow;
01202     tydiskwindowinfo x = appwindowinfo;
01203     short fontnum;
01204     
01205     moveappwindow (ha, x.windowrect);
01206     
01207     setscrollbarinfo ((**ha).vertbar, x.vertmin, x.vertmax, x.vertcurrent);
01208     
01209     setscrollbarinfo ((**ha).horizbar, x.horizmin, x.horizmax, x.horizcurrent);
01210     
01211     /*
01212     (**ha).scrollorigin.v = x.vertcurrent;
01213     
01214     (**ha).scrollorigin.h = x.horizcurrent;
01215     */
01216     
01217     (**ha).defaultsize = x.defaultsize;
01218     
01219     (**ha).defaultjustification = x.defaultjustification;
01220     
01221     diskgetfontnum (x.defaultfontstring, &fontnum);
01222     
01223     (**ha).defaultfont = fontnum;
01224     } /*loadappwindowinfo*/
01225     
01226 
01227 boolean saveappwindow (ptrfilespec pfs) {
01228     
01229     hdlappwindow ha = app.appwindow;
01230     Handle h = nil;
01231     short rnum;
01232     boolean fl;
01233     
01234     watchcursor ();
01235     
01236     setstringlength (bsalertstring, 0);
01237     
01238     if ((**ha).fnum == 0) { /*file isn't open*/
01239     
01240         short fnum;
01241         
01242         if (!filenew (pfs, (**ha).creator, (**ha).filetype, &fnum)) {
01243             
01244             alertdialog ("\pError saving the front window.");
01245             
01246             return (false);
01247             }
01248         
01249         (**ha).fnum = fnum;
01250         }
01251     else { /*file is already open*/
01252         
01253         if (!fileseteof ((**ha).fnum, (long) 0)) {
01254             
01255             alertdialog ("\pError truncating the file.");
01256             
01257             return (false);
01258             }
01259         }
01260         
01261     appprecallback ();
01262     
01263     fl = (*app.packcallback) (&h); /*From Mayson Lancaster -- move this up in the routine, DW 12/9/93*/
01264     
01265     apppostcallback ();
01266     
01267     if (!fl) {
01268         
01269         alertdialog ("\pOut of memory.");
01270         
01271         goto error;
01272         }
01273             
01274     if (!filewritehandle ((**ha).fnum, h)) {
01275         
01276         alertdialog ("\pError writing to file.");
01277         
01278         goto error;
01279         }
01280     
01281     if (openresourcefile (pfs, &rnum)) {
01282     
01283         tydiskwindowinfo x; 
01284         Handle hoptions = nil;
01285         
01286         saveappwindowinfo (ha, &x);
01287         
01288         putresource (rnum, 'aptk', 128, longsizeof (x), &x);
01289         
01290         (*app.getoptionscallback) (&hoptions);
01291         
01292         if (hoptions != nil) {
01293         
01294             putresourcehandle (rnum, 'aptk', 129, hoptions);
01295         
01296             disposehandle (hoptions);
01297             }
01298         
01299         closeresourcefile (rnum);
01300         }
01301     
01302     disposehandle (h);
01303     
01304     (**ha).flmadechanges = false;
01305     
01306     if ((**ha).touchparentsonsave)
01307         filetouchallparentfolders (pfs);
01308     
01309     FlushVol (nil, (*pfs).vRefNum); /*12/12/93 DW*/
01310     
01311     appprecallback ();
01312     
01313     (*app.aftersavewindowcallback) ();
01314     
01315     apppostcallback ();
01316     
01317     return (true);
01318         
01319     error:
01320     
01321     disposehandle (h);
01322     
01323     return (false);
01324     } /*saveappwindow*/
01325     
01326 
01327 static void checkzoombeforeopen (hdlappwindow appwindow) {
01328 
01329     if ((**appwindow).flzoombeforeopen) {
01330         
01331         zoomappwindow (appwindow);
01332         
01333         (**appwindow).flzoombeforeopen = false;
01334         }
01335     } /*checkzoombeforeopen*/
01336     
01337     
01338 static void appinitfontdefaults (hdlappwindow ha) {
01339 
01340     (**ha).defaultfont = app.defaultfont;
01341     
01342     (**ha).defaultsize = app.defaultsize;
01343     
01344     (**ha).defaultstyle = app.defaultstyle;
01345     
01346     (**ha).defaultjustification = leftjustified;
01347     } /*appinitfontdefaults*/
01348     
01349 
01350 boolean newappwindow (bigstring bstitle, boolean flshowwindow) {
01351     
01352     hdlappwindow ha = app.appwindow;
01353     WindowPtr macwindow;
01354     boolean flrelative = false;
01355     short hwindow, vwindow;
01356     short widthwindow, heightwindow;
01357     Rect rwindow;
01358     bigstring bslastword;
01359     hdlscrollbar vertbar = nil, horizbar = nil;
01360     hdlundostack undostack = nil, redostack = nil;
01361     boolean fl;
01362     
01363     if (ha != nil) { /*seed window position from frontmost window*/
01364         
01365         appgetdesktoprect (ha, &rwindow);
01366         
01367         hwindow = rwindow.left + 17;
01368         
01369         vwindow = rwindow.top + 17;
01370         
01371         widthwindow = rwindow.right - rwindow.left;
01372                 
01373         heightwindow = rwindow.bottom - rwindow.top;
01374         
01375         flrelative = true;
01376         }
01377         
01378     if (!newclearhandle (longsizeof (tyappwindow), (Handle *) &app.appwindow))
01379         goto error;
01380         
01381     ha = app.appwindow; /*copy into register*/  
01382     
01383     (**ha).filetype = app.filetype; /*default*/
01384 
01385     (**ha).creator = app.creator; /*default*/
01386     
01387     (**ha).notsaveable = app.notsaveable; /*default*/
01388     
01389     (**ha).systemidleticks = app.systemidleticks; /*default*/
01390     
01391     (**ha).statuspixels = app.statuspixels; /*default*/
01392     
01393     (**ha).iacdatarefcon.descriptorType = typeNull; /*4.1b1 dmb*/
01394     
01395     if (app.usecolor && systemhascolor ()) {
01396     
01397         macwindow = GetNewCWindow (128, nil, (WindowPtr) -1);
01398         
01399         if (app.exactcolors)
01400             getcolorpalette (macwindow);
01401         
01402         (**ha).flcolorwindow = true;
01403         
01404         (**ha).forecolor = blackcolor;
01405         
01406         (**ha).backcolor = whitecolor;
01407         }
01408     else {
01409         macwindow = GetNewWindow (128, nil, (WindowPtr) -1);
01410         
01411         (**ha).flcolorwindow = false;
01412         }
01413         
01414     if (flrelative)
01415         SizeWindow (macwindow, widthwindow, heightwindow, false);
01416 
01417     if (macwindow == nil)
01418         goto error;
01419     
01420     if (app.vertscroll) {
01421     
01422         if (!newscrollbar (macwindow, true, &vertbar))
01423             goto error;
01424         }
01425         
01426     if (app.horizscroll) {
01427     
01428         if (!newscrollbar (macwindow, false, &horizbar))
01429             goto error;
01430         }
01431     
01432     (**ha).vertbar = vertbar;
01433     
01434     (**ha).horizbar = horizbar;
01435     
01436     if (!newundostack (&undostack))
01437         goto error;
01438     
01439     if (!newundostack (&redostack))
01440         goto error;
01441     
01442     (**ha).undostack = (Handle) undostack;
01443     
01444     (**ha).redostack = (Handle) redostack;
01445     
01446     if (flrelative) /*position window relative to previous window*/
01447         MoveWindow (macwindow, hwindow, vwindow, false);
01448     else
01449         centerwindow (macwindow, quickdrawglobal (screenBits).bounds);
01450     
01451     /*copystring (bstitle, (**ha).fname);*/ /*DW 6/14/92*/
01452     
01453     if (app.haspalette) {
01454         
01455         hdlpaletterecord hpal;
01456         
01457         hpal = newpalette (macwindow, app.ctpaletteicons);
01458         
01459         if (hpal == nil)
01460             goto error;
01461             
01462         (**ha).hpalette = hpal;
01463         }
01464     
01465     (**ha).macwindow = macwindow;
01466     
01467     computewindowinfo (macwindow, ha);
01468     
01469     appinitfontdefaults (ha);
01470     
01471     SetWRefCon (macwindow, (long) ha);
01472     
01473     pushmacport (macwindow);
01474     
01475     fl = (*app.newrecordcallback) (); /*this callback is allowed to change window size and pos*/
01476         
01477     popmacport ();
01478     
01479     if (!fl)
01480         goto error;
01481         
01482     computewindowinfo (macwindow, ha); /*window might have been changed by callback*/
01483     
01484     (**ha).appdata = app.appdata; /*copy handle alloc'd by newrecord*/
01485     
01486     lastword (bstitle, ':', bslastword); /*avoid displaying long paths*/
01487     
01488     setappwindowtitle (ha, bslastword);
01489     
01490     (**ha).selectioninfo.fldirty = true;
01491     
01492     resizeappscrollbars (ha);
01493     
01494     resetappscrollbars (ha);
01495     
01496     if (flshowwindow) {
01497         
01498         checkzoombeforeopen (ha);
01499         
01500         showappscrollbars (ha); /*4.1b1 dmb: do before showing window*/
01501         
01502         showappwindow (ha);
01503         }
01504             
01505     return (true);
01506     
01507     error:
01508     
01509     if (app.haspalette) 
01510         disposepalette ((hdlpaletterecord) (**ha).hpalette);
01511     
01512     disposeundostack (undostack);
01513     
01514     disposeundostack (redostack);
01515     
01516     disposescrollbar (vertbar);
01517     
01518     disposescrollbar (horizbar);
01519     
01520     macwindow = (**ha).macwindow;
01521     
01522     if (macwindow != nil)
01523         DisposeWindow (macwindow);
01524         
01525     disposehandle ((Handle) ha);
01526     
01527     setappwindow (nil);
01528     
01529     return (false);
01530     } /*newappwindow*/
01531     
01532     
01533 static void prepareandshowwindow (hdlappwindow ha) {
01534     
01535     /*
01536     4.1b1 dmb: new routine shared by openappwindow and editappwindow
01537     */
01538     
01539     resetappscrollbars (ha);
01540     
01541     showappscrollbars (ha);
01542     
01543     /*invalappwindow (ha, false); /*dmb 4.1b1 -- commented out*/
01544     
01545     appprecallback ();
01546     
01547     (*app.afteropenwindowcallback) ();
01548     
01549     apppostcallback ();
01550     
01551     checkzoombeforeopen (ha);
01552     
01553     showappwindow (ha);
01554     } /*prepareandshowwindow*/
01555 
01556 
01557 boolean newuntitledappwindow (boolean flshowwindow) {
01558         
01559     bigstring bstitle;
01560     Boolean result;
01561     
01562     getuntitledtitle (bstitle);
01563     
01564     result = newappwindow (bstitle, flshowwindow);
01565     
01566     // LDR: added 9/18/95; we need to make this callback to get the dragMgr stuff in place
01567     if (result) {
01568     
01569         appprecallback ();
01570         
01571         (*app.afteropenwindowcallback) ();
01572         
01573         apppostcallback ();
01574     }
01575     
01576     return (result);
01577     } /*newuntitledappwindow*/
01578     
01579 
01580 boolean openappwindow (ptrfilespec pfs) {
01581     
01582     OSType origfiletype = app.filetype, origfilecreator = app.creator;
01583     Handle hoptions = nil;
01584     hdlappwindow appwindow;
01585     hdlappwindow ha = nil;
01586     short fnum;
01587     Handle h;
01588     short rnum;
01589     boolean fl;
01590     bigstring fname;
01591     
01592     setstringlength (bsalertstring, 0);
01593     
01594     if ((*app.interpretfilecallback) (pfs)) /*the file has been processed, don't open a window*/
01595         return (true);
01596     
01597     if (findbyfile (pfs, &appwindow)) { /*the file is already open*/
01598         
01599         selectappwindow (appwindow);
01600         
01601         /*appsetmessage (appwindow, "\pThe file is already open.");*/
01602 
01603         return (true);
01604         }
01605     
01606     if (!fileopen (pfs, &fnum)) {
01607         
01608         alertdialog ("\pError opening the file.");
01609         
01610         return (false);
01611         }
01612         
01613     if (!filereadwholefile (fnum, &h)) {
01614         
01615         alertdialog ("\pError reading from file.");
01616         
01617         goto error;
01618         }
01619     
01620     /*the data fork of the file stays open while the user is editing it*/
01621     
01622     /*set up app.filetype and app.creator so that newrecord routine has these available*/ {
01623         
01624         tyfileinfo info;
01625         
01626         filegetinfo (pfs, &info);
01627         
01628         app.filetype = info.filetype;
01629         
01630         app.creator = info.filecreator;
01631         }
01632     
01633     app.openingfile = true; /*so newrecord routine can tell that a file is being opened -- hack!*/
01634     
01635     filegetfilename (pfs, fname);
01636     
01637     fl = newappwindow (fname, false);
01638     
01639     app.openingfile = false; 
01640     
01641     app.filetype = origfiletype;
01642     
01643     app.creator = origfilecreator;
01644     
01645     if (!fl) 
01646         goto error;
01647     
01648     ha = app.appwindow; /*copy into register*/
01649     
01650     if (openresourcefile (pfs, &rnum)) {
01651         
01652         tydiskwindowinfo x;
01653         
01654         if (getresource (rnum, 'aptk', 128, longsizeof (x), &x))
01655             loadappwindowinfo (ha, x); /*resize window, set fields of ha*/
01656         
01657         getresourcehandle (rnum, 'aptk', 129, &hoptions);
01658         
01659         closeresourcefile (rnum);
01660         }
01661         
01662     appprecallback ();
01663     
01664     fl = (*app.unpackcallback) (h);
01665     
01666     apppostcallback ();
01667         
01668     if (!fl) {
01669         
01670         /*alertdialog ("\pError reading from file.");*/ /*DW 12/31/95 -- commented*/
01671         
01672         goto error;
01673         }
01674         
01675     if (hoptions != nil) {
01676         
01677         appprecallback ();
01678         
01679         (*app.putoptionscallback) (hoptions);
01680         
01681         apppostcallback ();
01682         }
01683     
01684     disposehandle (h);
01685     
01686     disposehandle (hoptions);
01687     
01688     (**ha).appdata = app.appdata; /*copy from the app to our record*/
01689     
01690     (**ha).fnum = fnum;
01691     
01692     (**ha).filespec = *pfs;
01693     
01694     prepareandshowwindow (ha);
01695     
01696     return (true);
01697     
01698     error:
01699     
01700     disposeappwindow (ha); /*4.1b1 dmb: need to do this in case error is during unpack*/
01701     
01702     disposehandle (h);
01703     
01704     disposehandle (hoptions);
01705     
01706     fileclose (fnum);
01707     
01708     return (false);
01709     } /*openappwindow*/
01710 
01711 
01712 boolean editappwindow (Handle hpackeddata, OSType sender, AEDesc *refcon, bigstring bstitle) {
01713     
01714     /*
01715     4.1b1 dmb: new call to open a window and edit data that isn't from a file
01716     
01717     we consume hpackeddata iff we succeed. on error, caller must dispose it.
01718     */
01719     
01720     boolean fl = false;
01721     hdlappwindow appwindow;
01722     Handle h = hpackeddata;
01723     hdlappwindow ha;
01724     
01725     if (findbyrefcon (refcon, &appwindow)) {
01726         
01727         disposehandle (h);
01728         
01729         AEDisposeDesc (refcon);
01730         
01731         selectappwindow (appwindow);
01732         
01733         return (true);
01734         }
01735     
01736     if (stringlength (bstitle) == 0)
01737         getuntitledtitle (bstitle);
01738     
01739     app.openingfile = true; /*so newrecord routine can tell that a file is being opened -- hack!*/
01740     
01741     fl = newappwindow (bstitle, false);
01742     
01743     app.openingfile = false; 
01744     
01745     if (!fl)
01746         return (false);
01747     
01748     ha = app.appwindow; /*copy into register*/
01749     
01750     appprecallback ();
01751     
01752     fl = (*app.unpackcallback) (h);
01753     
01754     apppostcallback ();
01755     
01756     if (!fl)
01757         goto error;
01758     
01759     disposehandle (h);
01760     
01761     (**ha).appdata = app.appdata; /*copy from the app to our record*/
01762     
01763     (**ha).fliacdata = true;
01764     
01765     (**ha).iacdataowner = sender;
01766     
01767     (**ha).iacdatarefcon = *refcon;
01768     
01769     (**ha).flzoombeforeopen = true;
01770     
01771     prepareandshowwindow (ha);
01772     
01773     return (true);
01774     
01775     error:
01776     
01777         disposeappwindow (ha); /*need to do this in case error is during unpack*/
01778         
01779         return (false);
01780     } /*editverb*/
01781 
01782 
01783 static short savedialog (bigstring fname) {
01784     
01785     bigstring prompt;
01786 
01787     if (!fldialogsenabled) /*don't save changes*/
01788         return (2);
01789         
01790     sysbeep; /*call attention to the user*/
01791             
01792     copystring ("\pSave “", prompt);
01793     
01794     pushstring (fname, prompt);
01795     
01796     pushstring ("\p” before closing?", prompt);
01797     
01798     return (threewaydialog (prompt, "\pCancel", "\pNo", "\pYes"));
01799     } /*savedialog*/
01800     
01801     
01802 boolean closeappwindow (hdlappwindow appwindow, boolean fldialog) { 
01803     
01804     hdlappwindow ha = appwindow;
01805     
01806     appprecallback ();
01807     
01808     (*app.beforeclosewindowcallback) ();
01809     
01810     apppostcallback ();
01811     
01812     if ((**ha).flmadechanges && fldialog && (!(**ha).notsaveable)) {
01813         
01814         bigstring bs;
01815         
01816         getappwindowtitle (ha, bs);
01817         
01818         switch (savedialog (bs)) { /*Save “bs” before closing?*/
01819             
01820             case 1: { /*yes*/
01821                 hdlappwindow oldappwindow = app.appwindow;
01822                 boolean fl;
01823                 
01824                 setappwindow (ha);
01825                 
01826                 fl = savefrontwindow ();
01827                 
01828                 setappwindow (oldappwindow);
01829                 
01830                 if (!fl) /*user cancelled save*/
01831                     return (false);
01832                 
01833                 break;
01834                 }
01835                 
01836             case 2: /*no*/
01837                 break;
01838                 
01839             case 3: /*cancel*/
01840                 return (false);
01841                 
01842                 break;
01843             } /*switch*/
01844         }
01845     
01846     setappwindow (ha);
01847     
01848     fileclose ((**ha).fnum); 
01849 
01850     disposeappwindow (ha);
01851     
01852     return (true);
01853     } /*closeappwindow*/
01854     
01855 
01856 boolean closewindowvisit (hdlappwindow appwindow) {
01857     
01858     return (closeappwindow (appwindow, true));
01859     } /*closewindowvisit*/
01860     
01861 
01862 boolean closeallwindows (void) {
01863     
01864     #ifdef appRunsCards
01865     
01866         closeAllCardWindows (); /*close all shared windows*/
01867     
01868     #endif
01869     
01870     return (visitappwindows (&closewindowvisit));
01871     } /*closeallwindows*/
01872 
01873     
01874 static boolean invalallwindowsvisit (hdlappwindow appwindow) {
01875     
01876     invalappwindow (appwindow, false);
01877     
01878     return (true);
01879     } /*invalallwindowsvisit*/
01880     
01881 
01882 boolean invalallwindows (void) {
01883     
01884     return (visitappwindows (&invalallwindowsvisit));
01885     } /*invalallwindows*/
01886 
01887     
01888 static boolean eraseallwindowsvisit (hdlappwindow appwindow) {
01889     
01890     invalappwindow (appwindow, true);
01891     
01892     return (true);
01893     } /*eraseallwindowsvisit*/
01894     
01895 
01896 boolean eraseallwindows (void) {
01897     
01898     return (visitappwindows (&eraseallwindowsvisit));
01899     } /*eraseallwindows*/
01900 
01901 
01902 boolean saveaswindow (ptrfilespec pfs) {
01903     
01904     hdlappwindow ha = app.appwindow;
01905     bigstring oldname;
01906     bigstring fname;
01907         
01908     getappwindowtitle (ha, oldname);
01909 
01910     fileclose ((**ha).fnum); /*close the file if it's open*/
01911     
01912     (**ha).fnum = 0;
01913         
01914     if (!saveappwindow (pfs))
01915         return (false);
01916     
01917     filegetfilename (pfs, fname);
01918     
01919     /*
01920     if (app.embeddedtables) 
01921         renameEmbeddedTable (oldname, fname, &alertdialog);
01922     */
01923     
01924     (**ha).filespec = *pfs;
01925     
01926     setappwindowtitle (ha, fname);
01927     
01928     copystring (fname, bstargetwindowname);
01929     
01930     return (true);
01931     } /*saveaswindow*/
01932     
01933     
01934 boolean saveasfrontwindow (void) {
01935     
01936     hdlappwindow ha = app.appwindow;
01937     tyfilespec fs;
01938     
01939     getappwindowfilespec (ha, &fs);
01940         
01941     if (!sfdialog (true, saveasprompt, &fs, app.filefiltercallback, app.filetype))
01942         return (false);
01943         
01944     return (saveaswindow (&fs));
01945     } /*saveasfrontwindow*/
01946 
01947 
01948 static boolean saveiacdata (void) {
01949     
01950     /*
01951     1.0b19 dmb: odbEditor protocol -- send owner new data.
01952     */
01953     
01954     hdlappwindow ha = app.appwindow;
01955     AppleEvent event = {typeNull, nil};
01956     AppleEvent reply = {typeNull, nil};
01957     AEDesc desc;
01958     Handle h = nil;
01959     boolean fl;
01960     
01961     appprecallback ();
01962     
01963     fl = (*app.packcallback) (&h); /*From Mayson Lancaster -- move this up in the routine, DW 12/9/93*/
01964     
01965     apppostcallback ();
01966     
01967     if (!fl) {
01968         
01969         alertdialog ("\pOut of memory.");
01970         
01971         return (false);
01972         }
01973     
01974     if (!IACnewverb ((**ha).iacdataowner, (**ha).creator, 'swin', &event)) {
01975         
01976         disposehandle (h);
01977         
01978         return (false);
01979         }
01980     
01981     IACglobals.event = &event;
01982     
01983     if (!IACpushbinaryparam (h, (**ha).filetype, '----'))
01984         goto exit;
01985     
01986     desc = (**ha).iacdatarefcon;
01987     
01988     IACglobals.dontdisposenextparam = true;
01989     
01990     if (!IACpushbinaryparam (desc.dataHandle, desc.descriptorType, 'refc'))
01991         goto exit;
01992     
01993     if (!IACsendverb (&event, &reply))
01994         goto exit;
01995     
01996     (**ha).flmadechanges = false;
01997     
01998     appprecallback ();
01999     
02000     (*app.aftersavewindowcallback) ();
02001     
02002     apppostcallback ();
02003     
02004     fl = true;
02005     
02006     exit:
02007     
02008     AEDisposeDesc (&event); 
02009     
02010     AEDisposeDesc (&reply);
02011     
02012     return (fl);
02013     } /*saveiacdata*/
02014 
02015 
02016 boolean savefrontwindow (void) {
02017     
02018     hdlappwindow ha = app.appwindow;
02019     tyfilespec fs;
02020     
02021     if (ha == nil) /*defensive driving*/
02022         return (false);
02023     
02024     if ((**ha).fliacdata) /*4.1b1 dmb*/
02025         return (saveiacdata ());
02026     
02027     if ((**ha).fnum == 0)
02028         return (saveasfrontwindow ());
02029     
02030     fs = (**ha).filespec;
02031     
02032     return (saveappwindow (&fs));
02033     } /*savefrontwindow*/
02034     
02035     
02036 boolean closefrontwindow (void) {
02037 
02038     WindowPtr w = FrontWindow ();
02039     hdlappwindow appwindow;
02040     
02041     #ifdef appRunsCards
02042     
02043         if (closeCardWindow (w))
02044             return (true);
02045     
02046     #endif
02047                 
02048     getappwindow (w, &appwindow);
02049     
02050     return (closeappwindow (appwindow, true));
02051     } /*closefrontwindow*/
02052     
02053 
02054 boolean openfrontwindow (void) {
02055     
02056     tyfilespec fs;
02057     
02058     if (!sfdialog (false, openprompt, &fs, app.filefiltercallback, app.filetype))
02059         return (false);
02060         
02061     return (openappwindow (&fs));
02062     } /*openfrontwindow*/
02063     
02064     
02065 boolean revertfrontwindow (void) {
02066     
02067     hdlappwindow ha = app.appwindow;
02068     tyfilespec fs = (**ha).filespec;
02069     
02070     if ((**ha).flmadechanges && fldialogsenabled) {
02071         
02072         bigstring bs, bstitle;
02073         
02074         sysbeep; /*call attention to the user*/
02075             
02076         getappwindowtitle (ha, bstitle);
02077         
02078         copystring ("\pDiscard changes to “", bs);
02079         
02080         pushstring (bstitle, bs);
02081         
02082         pushstring ("\p”?", bs);
02083         
02084         if (!yesnodialog (bs))
02085             return (false);
02086             
02087         (**ha).flmadechanges = false; /*avoid dialog in closeappwindow call*/
02088         }
02089             
02090     closeappwindow (ha, fldialogsenabled);
02091         
02092     setfrontglobals (); /*seed new window from frontmost window*/
02093 
02094     return (openappwindow (&fs));
02095     } /*revertfrontwindow*/
02096     
02097     
02098 boolean exitmainloop (void) {
02099     
02100     boolean flquitcancelled;
02101     
02102     appprecallback ();
02103     
02104     flquitcancelled = (*app.beforequitcallback) (); /*returns true if no quit*/
02105     
02106     apppostcallback ();
02107     
02108     if (flquitcancelled) /*we've been told not to exit the program*/
02109         return (true);
02110     
02111     flexitmainloop = closeallwindows ();
02112     
02113     setfrontglobals (); /*some or all of the windows might now be closed*/
02114     
02115     return (true);
02116     } /*exitmainloop*/
02117 
02118 
02119 static void handleupdate (EventRecord *ev) {
02120     
02121     WindowPtr w = (WindowPtr) (*ev).message;
02122     hdlappwindow appwindow;
02123     
02124     if (!getappwindow (w, &appwindow))
02125         return;
02126     
02127     updateappwindow (appwindow);
02128     } /*handleupdate*/
02129     
02130     
02131 static void handlediskinserted (EventRecord *ev) {
02132     
02133     /*
02134     see Think Reference page for DIBadMount for more info
02135     */
02136     
02137     long message = (*ev).message;
02138     
02139     if ((message & 0xFFFF0000) != 0) { /*error mounting*/
02140         
02141         Point pt;
02142         OSErr ec;
02143         
02144         SetPt (&pt, 100, 100);
02145         
02146         ec = DIBadMount (pt, message);
02147         
02148         if (ec != noErr)
02149             return;
02150         }
02151     
02152     appprecallback ();
02153     
02154     (*app.diskinsertedcallback) (message & 0x0000FFFF);
02155     
02156     apppostcallback ();
02157     } /*handlediskinserted*/
02158     
02159 
02160 static void handleactivate (EventRecord *ev) {
02161 
02162     WindowPtr w = (WindowPtr) (*ev).message;
02163     boolean flactivate = (*ev).modifiers & activeFlag;
02164     hdlappwindow appwindow;
02165         
02166     if (!getappwindow (w, &appwindow))
02167         return;
02168     
02169     (**appwindow).flactive = flactivate;
02170     
02171     /*
02172     if (app.haspalette) 
02173         invalpalette ((hdlpaletterecord) (**appwindow).hpalette);
02174     */
02175     
02176     flipcustommenu (appwindow, flactivate);
02177     
02178     setappwindow (appwindow);
02179 
02180     activateappscrollbars (appwindow, flactivate);
02181     
02182     updateappwindow (appwindow); /*DW 9/16/93*/
02183     
02184     drawappgrowicon (appwindow);
02185     
02186     appprecallback (); 
02187 
02188     (*app.activatecallback) (flactivate);
02189     
02190     apppostcallback ();
02191     } /*handleactivate*/
02192     
02193     
02194 static void handledrag (EventRecord *ev, WindowPtr w) {
02195     
02196     Rect r;
02197 
02198     r = quickdrawglobal (screenBits).bounds; 
02199    
02200     r.top = r.top + getmenubarheight (); 
02201                
02202     r.left = r.left + dragscreenmargin;  
02203                
02204     r.right = r.right - dragscreenmargin;
02205                
02206     r.bottom = r.bottom - dragscreenmargin;
02207              
02208     DragWindow (w, (*ev).where, &r);   
02209     } /*handledrag*/
02210     
02211     
02212 static void setappwindowfrommacwindow (WindowPtr macwindow) {
02213 
02214     hdlappwindow appwindow;
02215     
02216     if (!getappwindow (macwindow, &appwindow))
02217         return;
02218     
02219     setappwindow (appwindow);
02220     } /*setappwindowfrommacwindow*/
02221     
02222     
02223 static void invalforgrow (Rect r) {
02224     
02225     pushclip (r);
02226     
02227     invalrect (r);
02228     
02229     /*
02230     FillRect (&r, gray); 
02231     */
02232     
02233     if (!app.eraseonresize)
02234         eraserect (r);
02235     
02236     /*
02237     pushbackcolor (&(**app.appwindow).backcolor);
02238     
02239     eraserect (r);
02240     
02241     popbackcolor ();
02242     */
02243     
02244     popclip ();
02245     } /*invalforgrow*/
02246     
02247     
02248 void adjustaftergrow (WindowPtr w, Rect oldportrect) {
02249     
02250     /*
02251     8/26/92 DW: optimize. we now ask for the old portrect for the window
02252     and only inval any parts of the window that are newly exposed.
02253     
02254     11/4/92 DW: erase the grow box first. with all the optimization we now
02255     have, it can take an annoying amount of time for it to get erased.
02256     */
02257     
02258     hdlappwindow ha;
02259     short scrollbarwidth = getscrollbarwidth ();
02260     
02261     /*erase the grow box, avoid annoying delay*/ {
02262         
02263         Rect r = oldportrect;
02264         
02265         r.left = r.right - scrollbarwidth;
02266         
02267         r.top = r.bottom - scrollbarwidth;
02268         
02269         invalforgrow (r);
02270         }
02271     
02272     setappwindowfrommacwindow (w);
02273         
02274     /*smart inval*/ {
02275         
02276         Rect portrect = (*w).portRect;
02277         Rect r;
02278         
02279         r.left = oldportrect.right - scrollbarwidth;
02280         
02281         r.right = portrect.right;
02282         
02283         r.top = oldportrect.top;
02284         
02285         r.bottom = portrect.bottom;
02286         
02287         invalforgrow (r);
02288         
02289         r.top = oldportrect.bottom - scrollbarwidth;
02290         
02291         r.bottom = portrect.bottom;
02292         
02293         r.left = oldportrect.left;
02294         
02295         r.right = portrect.right;
02296         
02297         invalforgrow (r);
02298         }
02299 
02300     ha = app.appwindow;
02301     
02302     computewindowinfo (w, ha);
02303     
02304     appprecallback (); 
02305     
02306     (*app.windowresizecallback) ();
02307     
02308     apppostcallback ();
02309     
02310     resizeappscrollbars (ha);
02311     
02312     resetappscrollbars (ha);
02313     
02314     invalscrollbar ((**ha).vertbar); 
02315     
02316     invalscrollbar ((**ha).horizbar);
02317     
02318     /*always inval the grow icon*/ {
02319         
02320         Rect r;
02321         
02322         getgrowiconrect (ha, &r);
02323     
02324         invalforgrow (r);
02325         }
02326     
02327     setappwindowmadechanges (ha); /*we save window size and position*/
02328     } /*adjustaftergrow*/
02329     
02330     
02331 static void erasewindow (WindowPtr w) {
02332         
02333     Rect r = (*w).portRect;
02334     
02335     pushmacport (w);
02336     
02337     pushclip (r);
02338     
02339     /*EraseRect (&r);*/
02340     
02341     apperaserect (r);
02342     
02343     InvalRect (&r);
02344     
02345     popclip ();
02346     
02347     popmacport ();
02348     } /*erasewindow*/
02349 
02350 
02351 static void handlegrow (Point pt, WindowPtr w) {
02352     
02353     long x;
02354     Rect boundsrect;
02355     Rect r;
02356     Rect oldportrect = (*w).portRect;
02357     
02358     boundsrect.left = app.minwindowwidth;
02359     
02360     boundsrect.top = app.minwindowheight; 
02361     
02362     r = quickdrawglobal (screenBits).bounds;
02363     
02364     boundsrect.right = r.right - r.left; /*maximum window width*/
02365     
02366     boundsrect.bottom = r.bottom - r.top; /*maximum window height*/
02367     
02368     x = GrowWindow (w, pt, &boundsrect);
02369     
02370     /*DW 12/10/93*/ {
02371         
02372         hdlappwindow appwindow;
02373         Rect r;
02374         
02375         getappwindow (w, &appwindow);
02376         
02377         getgrowiconrect (appwindow, &r);
02378         
02379         EraseRect (&r);
02380         }
02381     
02382     SizeWindow (w, LoWord (x), HiWord (x), false);
02383     
02384     if (app.eraseonresize) 
02385         erasewindow (w);
02386     
02387     adjustaftergrow (w, oldportrect);
02388     } /*handlegrow*/
02389     
02390 
02391 void zoomappwindow (hdlappwindow appwindow) {
02392     
02393     hdlappwindow ha = appwindow;
02394     WindowPtr w = (**ha).macwindow;
02395     WStateData **hstatedata = (WStateData **) (*(WindowPeek) w).dataHandle; 
02396     short scrollbarwidth = getscrollbarwidth ();
02397     Rect rzoomed, rcurrent;
02398     Rect oldportrect = (*w).portRect;
02399     short part;
02400     
02401     if (app.eraseonresize) /*DW 7/16/93*/
02402         erasewindow (w);
02403     
02404     appgetdesktoprect (ha, &rcurrent);
02405     
02406     rzoomed = (**hstatedata).stdState; /*default*/
02407     
02408     if (!optionkeydown ()) { /*allow option key to over-ride "smart" zoom*/
02409         
02410         boolean fl;
02411         
02412         appprecallback ();
02413         
02414         fl = (*app.getcontentsizecallback) ();
02415         
02416         apppostcallback ();
02417         
02418         if (fl) {
02419             
02420             short height = (**ha).zoomheight;
02421             short width = (**ha).zoomwidth;
02422             Rect r;
02423             
02424             if ((**ha).statuspixels > 0) 
02425                 height += (**ha).statuspixels + 3; /*a 3-pixel line separates status & content*/
02426             
02427             width += (**ha).contentrect.left;
02428             
02429             /*allow for scrollbars and/or grow icon*/ {
02430                 
02431                 if (app.horizscroll)
02432                     height += scrollbarwidth;
02433                 
02434                 if (app.vertscroll)
02435                     width += scrollbarwidth;
02436                 }
02437             
02438             /*allow for the window's title*/ {
02439                 
02440                 bigstring bs;
02441                 short titlewidth;
02442                 
02443                 pushstyle (systemFont, 12, normal);
02444                 
02445                 getappwindowtitle (ha, bs);
02446                 
02447                 titlewidth = StringWidth (bs) + 64;
02448                 
02449                 if (width < titlewidth)
02450                     width = titlewidth;
02451                 
02452                 popstyle ();
02453                 }
02454             
02455             if (app.haspalette) {
02456                 
02457                 short palheight, palwidth;
02458                 
02459                 getpalettesize ((**ha).hpalette, &palheight, &palwidth);
02460                 
02461                 if (height < palheight)
02462                     height = palheight;
02463                 }
02464         
02465             if (width < app.minwindowwidth)
02466                 width = app.minwindowwidth;
02467                 
02468             if (height < app.minwindowheight)
02469                 height = app.minwindowheight;
02470                 
02471             r = rcurrent;
02472             
02473             r.right = r.left + width;
02474             
02475             r.bottom = r.top + height;
02476             
02477             constraintodesktop (&r);
02478             
02479             rzoomed = r;
02480             }
02481         }
02482 
02483     if (equalrects (rzoomed, rcurrent))
02484         part = inZoomIn;
02485     else {
02486         (**hstatedata).stdState = rzoomed;
02487         
02488         part = inZoomOut;
02489         }
02490     
02491     ZoomWindow (w, part, true);
02492     
02493     if (part == inZoomOut) { /*quickly fill ugly white space*/
02494         
02495         Rect r = (*w).portRect;
02496         
02497         if (app.vertscroll) /*avoid flicker in the scrollbar areas*/
02498             r.right -= scrollbarwidth;
02499             
02500         if (app.horizscroll) /*avoid flicker in the scrollbar areas*/
02501             r.bottom -= scrollbarwidth;
02502         
02503         apperaserect (r);
02504         }
02505         
02506     adjustaftergrow (w, oldportrect);
02507     
02508     /*scroll the contents if there's room to show everything*/ {
02509         
02510         if (part == inZoomOut) {
02511         
02512             Rect r = (**ha).contentrect;
02513             short minscroll, maxscroll, currentscroll;
02514                     
02515             if ((r.bottom - r.top) >= (**ha).zoomheight) {
02516             
02517                 getscrollbarinfo ((**ha).vertbar, &minscroll, &maxscroll, &currentscroll);
02518                 
02519                 setscrollbarcurrent ((**ha).vertbar, minscroll);
02520                 
02521                 /*note #1 -- in this case the vertical scrollbar is not inval'd anymore*/
02522                 }
02523             
02524             getscrollbarinfo ((**ha).horizbar, &minscroll, &maxscroll, &currentscroll);
02525             
02526             setscrollbarcurrent ((**ha).horizbar, minscroll);
02527                 
02528             appprecallback ();
02529             
02530             (*app.scrolltocallback) ();
02531             
02532             apppostcallback ();
02533             }
02534         }
02535                 
02536     invalscrollbar ((**ha).vertbar); /*smash a bug above us, see note #1*/
02537     
02538     updateappwindow (ha);
02539     } /*zoomappwindow*/
02540 
02541 
02542 boolean selectallcommand (void) {
02543     
02544     boolean fl;
02545     
02546     appprecallback ();
02547     
02548     fl = (*app.selectallcallback) ();
02549     
02550     apppostcallback ();
02551     
02552     return (fl);
02553     } /*selectallcommand*/
02554     
02555 
02556 void appsetfont (bigstring fontname) {
02557 
02558     hdlappwindow ha = app.appwindow;
02559     short fontnumber;
02560     
02561     GetFNum (fontname, &fontnumber);
02562     
02563     (**ha).selectioninfo.fontnum = fontnumber;
02564     
02565     appprecallback (); 
02566     
02567     (*app.setfontcallback) ();
02568     
02569     apppostcallback ();
02570     
02571     (**ha).selectioninfo.fldirty = true;
02572     
02573     (**ha).defaultfont = fontnumber; /*side-effect, 7/6/92 DW*/
02574     } /*appsetfont*/
02575             
02576     
02577 void appsetfontsize (short size) {
02578                 
02579     hdlappwindow ha = app.appwindow;
02580 
02581     (**ha).selectioninfo.fontsize = size;
02582     
02583     appprecallback (); 
02584     
02585     (*app.setsizecallback) ();
02586     
02587     apppostcallback ();
02588     
02589     (**ha).selectioninfo.fldirty = true;
02590     
02591     (**ha).defaultsize = size; /*side-effect, 7/6/92 DW*/
02592     } /*appsetfontsize*/
02593     
02594     
02595 static void handlekeystroke (EventRecord *ev) {
02596     
02597     /*
02598     11/12/92 dmb: added functionkey handling; also, allow cmd-arrows to be 
02599     processed by the app's keystroke callback
02600     */
02601     
02602     char ch = (*ev).message & charCodeMask;
02603     boolean flcmdkey = (*ev).modifiers & cmdKey;
02604     long codeword;
02605     
02606     flcmdperiod = flcmdkey && (ch == '.'); /*set global*/
02607     
02608     #if false /*not needed, per Frontier 3.0 readme file*/
02609     
02610         if (SharedScriptRunning ()) { /*cmd-period terminates the script*/
02611         
02612             if (flcmdperiod) { 
02613             
02614                 CancelSharedScript (); /*cancel the shared menu script*/
02615                 
02616                 return;
02617                 }
02618             }
02619     #endif
02620     
02621     setkeyboardstatus (*ev); 
02622     
02623     if (filterfunctionkey (&codeword)) {
02624         
02625         HiliteMenu (HiWord (codeword));
02626         
02627         handlemenu (codeword);
02628         
02629         return;
02630         }
02631     
02632     if (flcmdkey && !arrowkey (ch)) {
02633     
02634         handlemenu (MenuKey (ch));
02635         
02636         return;
02637         }
02638     
02639     if (keyboardstatus.keydirection == nodirection) /*DW 9/6/93*/
02640         ObscureCursor ();
02641         
02642     if (app.appwindow != nil) {
02643         
02644         appprecallback (); 
02645         
02646         (*app.keystrokecallback) ();
02647         
02648         apppostcallback ();
02649         }
02650     } /*handlekeystroke*/
02651     
02652     
02653 static void handlecontent (EventRecord *ev, WindowPtr w) {
02654     
02655     hdlappwindow ha = app.appwindow;
02656     Point pt = (*ev).where;
02657     hdlscrollbar scrollbar;
02658     short part;
02659         
02660     globaltolocalpoint (w, &pt);
02661 
02662     if (findscrollbar (pt, w, &scrollbar, &part)) { 
02663         
02664         /*DW 12/16/93 -- it could be one of Iowa's scrollbars*/
02665         
02666         if (scrollbar == (**ha).vertbar) {
02667         
02668             handlescrollbar (true, scrollbar, part, pt);
02669         
02670             return;
02671             }
02672         
02673         if (scrollbar == (**ha).horizbar) {
02674         
02675             handlescrollbar (false, scrollbar, part, pt);
02676         
02677             return;
02678             }
02679         }
02680         
02681     /*send mouse hit to the applet*/
02682     
02683     mousestatus.localpt = pt;
02684     
02685     mousestatus.fldoubleclick = mousedoubleclick ((*ev).where);
02686     
02687     if (PtInRect (pt, &(**ha).contentrect)) {
02688         
02689         mousestatus.localpt.h += (**ha).scrollorigin.h;
02690     
02691         mousestatus.localpt.v += (**ha).scrollorigin.v;
02692         
02693         setkeyboardstatus (*ev); /*applet can tell if shift key is down, other modifiers*/
02694     
02695         appprecallback (); 
02696         
02697         (*app.mousecallback) ();
02698         
02699         apppostcallback ();
02700         }
02701 
02702     if (PtInRect (pt, &(**ha).statusrect)) {
02703         
02704         setkeyboardstatus (*ev); /*applet can tell if shift key is down, other modifiers*/
02705     
02706         pushclip ((**ha).statusrect);
02707         
02708         (*app.mouseinstatuscallback) ();
02709         
02710         popclip ();
02711         }
02712         
02713     if (app.haspalette) {
02714 
02715         if (PtInRect (pt, &(**(**ha).hpalette).r))
02716             palettemousedown ((**ha).hpalette);
02717         }
02718         
02719     if (PtInRect (pt, &(**ha).messagerect))
02720         appmessageclick (ha);
02721     } /*handlecontent*/
02722     
02723 
02724 static void handlemouseup (EventRecord *ev) {
02725     
02726     /*
02727     call this when you receive an mouse up event.  if the last mouse down was
02728     a double click, we set things up so that the next single click will not
02729     be interpreted as a double click.
02730     */
02731     
02732     if (!mousestatus.fldoubleclickdisabled) {
02733         
02734         mousestatus.mouseuptime = (*ev).when;
02735         
02736         mousestatus.mouseuppoint = (*ev).where;
02737         
02738         mousestatus.mousedowntime = 0L; /*hasn't happened yet*/
02739         }
02740     
02741     mousestatus.fldoubleclickdisabled = false; /*next mouse up is important*/
02742     } /*handlemouseup*/
02743 
02744 
02745 static void handlemousedown (EventRecord *ev) {
02746 
02747     short part;
02748     WindowPtr w;
02749     
02750     mousestatus.mousedowntime = (*ev).when; /*set globals so we can detect a 2click*/
02751     
02752     mousestatus.mousedownpoint = (*ev).where;
02753     
02754     part = FindWindow ((*ev).where, &w);
02755     
02756     switch (part) {
02757     
02758         case inMenuBar: 
02759             handlemenu (MenuSelect ((*ev).where)); 
02760             
02761             break;
02762         
02763         case inContent:
02764             if (w != nil) {
02765             
02766                 if (w != FrontWindow ()) { /*just like all other Mac programs*/
02767                     
02768                     SelectWindow (w);
02769                     
02770                     mousestatus.fldoubleclickdisabled = true; /*DW 9/1/93 -- avoid annoying launches in clay basket*/
02771                                     
02772                     return; /*the mouse click is consumed by the bringtofront operation*/
02773                     }   
02774                 }
02775             
02776             setfrontglobals ();
02777             
02778             handlecontent (ev, w);
02779             
02780             break;
02781         
02782         case inSysWindow:
02783             SystemClick (ev, w); 
02784             
02785             break;
02786         
02787         case inDrag:
02788             handledrag (ev, w);
02789             
02790             break;
02791             
02792         case inGrow:
02793             handlegrow ((*ev).where, w);
02794             
02795             break;
02796             
02797         case inGoAway:
02798             if (TrackGoAway (w, (*ev).where)) {
02799             
02800                 if (optionkeydown ())
02801                     closeallwindows ();
02802                 else
02803                     closefrontwindow ();
02804                 }
02805                 
02806             break;
02807         
02808         case inZoomOut: case inZoomIn:
02809             if (TrackBox (w, (*ev).where, part))
02810                 zoomappwindow (app.appwindow);
02811             
02812             break;
02813         
02814         } /*switch*/
02815     } /*handlemousedown*/
02816     
02817     
02818 static boolean jugglervisit (hdlappwindow appwindow) {
02819     
02820     hdlappwindow ha = appwindow;
02821     boolean fl = flcurrentlyactive && ((**ha).macwindow == FrontWindow ());
02822     
02823     setappwindow (ha);
02824     
02825     activateappscrollbars (ha, fl);
02826     
02827     appprecallback ();
02828     
02829     (*app.switchcallback) (fl); /*DW 8/28/93*/
02830     
02831     apppostcallback ();
02832     
02833     drawappgrowicon (ha); 
02834     
02835     return (true);
02836     } /*jugglervisit*/
02837     
02838     
02839 static void handlejuggler (EventRecord *ev) {
02840     
02841     boolean flresume;
02842     tyjugglermessage jmsg;
02843     
02844     moveleft (&(*ev).message, &jmsg, longsizeof (jmsg));
02845     
02846     if (jmsg.eventtype == 1) { /*suspend or resume subevent*/
02847         
02848         flresume = jmsg.flresume; /*copy into register*/
02849         
02850         if (jmsg.flconvertclipboard) { /*11/3/91 DW: get to this later*/
02851             }
02852         
02853         appprecallback (); 
02854         
02855         (*app.resumecallback) (flresume); 
02856         
02857         apppostcallback ();
02858         
02859         flcurrentlyactive = flresume; /*set global before visit*/
02860         
02861         visitappwindows (&jugglervisit); /*send message to all open windows*/
02862         }
02863     } /*handlejuggler*/
02864 
02865 
02866 static boolean handledialogevent (EventRecord *ev) {
02867     
02868     /*
02869     if the event belongs to a dialog, allow it to be processed in 
02870     the standard way. the applet toolkit doesn't currently support the 
02871     creation of modeless dialogs, but we must be a host to them anyway.
02872     */
02873     
02874     DialogPtr dlog;
02875     short itemnumber;
02876     
02877     if (!IsDialogEvent (ev)) 
02878         return (false);
02879     
02880     DialogSelect (ev, &dlog, &itemnumber);
02881     
02882     return (true);
02883     } /*handledialogevent*/
02884 
02885 
02886 boolean flappopenfileonidle; /*can be set externally, for iowawires.c*/
02887 
02888 tyfilespec fsidleopen;
02889 
02890 
02891 static void appidle (void) {
02892     
02893     if (flappopenfileonidle) {
02894         
02895         flappopenfileonidle = false;
02896         
02897         openappwindow (&fsidleopen);
02898         }
02899 
02900     appprecallback ();
02901     
02902     (*app.idlecallback) ();
02903     
02904     (*app.preupdatecallback) ();
02905     
02906     apppostcallback ();     
02907     } /*appidle*/
02908     
02909     
02910 static boolean appletmainvalidatevisit (hdlappwindow appwindow) {
02911     
02912     /*
02913     DW 10/9/94 -- it appears that the flactive bit in the appwindow 
02914     record for the Reader window is incorrect when a card is in front.
02915     
02916     the problem was in bbsAppleTalkAPI.c -- we were throwing away events
02917     while waiting for a reply to a message. oops.
02918     */
02919     
02920         /*
02921         if (((**appwindow).macwindow == FrontWindow ()) && flcurrentlyactive)
02922             assert ((**appwindow).flactive);
02923         else
02924             assert (!(**appwindow).flactive);
02925         */
02926     
02927     return (true); /*keep visiting*/
02928     } /*appletmainvalidatevisit*/
02929     
02930     
02931 static void appletmainvalidate (void) {
02932     
02933     visitappwindows (&appletmainvalidatevisit);
02934     } /*appletmainvalidate*/
02935     
02936     
02937 static boolean nulleventvisit (hdlappwindow appwindow) {
02938     
02939     setappwindow (appwindow);
02940     
02941     appidle ();
02942             
02943     return (true); /*keep traversing*/
02944     } /*nulleventvisit*/
02945     
02946     
02947 void appleteventhandler (EventRecord *ev) {
02948     
02949     /*
02950     if you have an event, and have determined that it's not for you, pass it
02951     thru this routine for processing. 
02952     
02953     this routine is ideal for card routines to pass to apprunmodalresource 
02954     as its event filter or to call it from their event filter.
02955     */
02956     
02957     WindowPtr oldfrontwindow = FrontWindow ();
02958 
02959     if (countwindows () == 0) { /*DW 10/27/95, updated 11/17/95*/
02960     
02961         setcursortype (cursorisarrow);
02962         
02963         disableeditmenuitems ();
02964         }
02965     
02966     app.commanderror = false; /*9/3/93 DW: app can raise an error flag which some functions watch*/
02967     
02968     appresetsystemidle (ev); /*based on event type, might start another idle watch*/
02969         
02970     switch ((*ev).what) {
02971     
02972         case keyDown: case autoKey: 
02973             handlekeystroke (ev);
02974             
02975             break;
02976             
02977         case mouseDown:
02978             handlemousedown (ev);
02979            
02980             break;
02981             
02982         case mouseUp:
02983             handlemouseup (ev);
02984             
02985             break;
02986            
02987         case activateEvt:
02988             handleactivate (ev); 
02989            
02990             break;
02991         
02992         case osEvt:
02993             handlejuggler (ev);
02994             
02995             break;
02996 
02997         case updateEvt:
02998             handleupdate (ev);
02999            
03000             break;
03001             
03002         case diskEvt:
03003             handlediskinserted (ev);
03004             
03005             break;
03006             
03007         case nullEvent:
03008             visitappwindows (&nulleventvisit);
03009             
03010             resetdirtyscrollbars ();
03011             
03012             setfrontglobals (); /*the menus reflect the status of the frontmost window*/
03013             
03014             adjustmenus ();
03015             
03016             appidle ();
03017             
03018             appsystemidle ();
03019             
03020             if (flcurrentlyactive)
03021                 CheckSharedMenus (firstsharedmenu);
03022             
03023             #ifdef fldebug
03024                 appletmainvalidate ();
03025             #endif
03026     
03027             break;
03028             
03029         case kHighLevelEvent:
03030             AEProcessAppleEvent (ev);
03031             
03032             break;
03033         } /*switch*/
03034         
03035     if (FrontWindow () != oldfrontwindow) { /*a different window is in front*/
03036         
03037         if (setfrontglobals ())
03038             (**app.appwindow).selectioninfo.fldirty = true; /*force update of selection info*/
03039         else
03040             flipcustommenu (nil, false); /*DW 8/19/93: last window just closed, get rid of any custom menus*/
03041         }
03042     } /*appleteventhandler*/
03043     
03044 
03045 void appleteventdispatcher (EventRecord *ev) {
03046     
03047     /*
03048     the event might be for the Dialog Manager (handling a modeless dialog)
03049     or a window sharing component, or for the applet itself.
03050     
03051     we pass the event thru each entity, if it returns false, we go to the
03052     next one. finally we pass it thru the applet hierarchy.
03053     */
03054     
03055     if (!handledialogevent (ev)) {
03056         
03057         #ifdef appRunsCards
03058         
03059             boolean flcloseallwindows;
03060         
03061             if (isModelessCardEvent (ev, &flcloseallwindows)) {
03062                 
03063                 if (flcloseallwindows) /*user option-clicked in close box of a card window*/
03064                     closeallwindows ();
03065                     
03066                 return;
03067                 }
03068         #endif
03069     
03070         IACglobals.waitroutine = &appwaitroutine; /*for waiting after sending an Apple Event*/
03071 
03072         setfrontglobals (); /*event applies to frontmost window*/
03073         
03074         GetMouse (&mousestatus.localpt);
03075 
03076         appleteventhandler (ev); 
03077         }
03078     } /*appleteventdispatcher*/
03079     
03080     
03081 static boolean idleclosevisit (hdlappwindow appwindow) {
03082     
03083     if ((**appwindow).flcloseonidle)        
03084         closeappwindow (appwindow, true);
03085         
03086     return (true); /*keep traversing*/
03087     } /*idleclosevisit*/
03088     
03089     
03090 static void checkcloseonidle (void) {
03091     
03092     /*8/31/94 DW
03093     the clay basket message editor wants to close a message 
03094     editing window after it has been successfully uploaded to
03095     the server. it does so by setting a flag in the appwindow
03096     record, we watch for it here and close the window in a 
03097     safe place.
03098     */
03099     
03100     visitappwindows (&idleclosevisit);
03101     } /*checkcloseonidle*/
03102 
03103 
03104 static long getwaitticks (void) {
03105         
03106     long ticks = 10;
03107     
03108     if (!flcurrentlyactive)
03109         ticks = 20;
03110 
03111     return (ticks);
03112     } /*getwaitticks*/
03113     
03114     
03115 void maineventloop (void) {
03116     
03117     EventRecord ev;
03118     
03119     while (!flexitmainloop) {
03120         
03121         keyboardclearescape ();
03122         
03123         checkcloseonidle ();
03124         
03125         WaitNextEvent (everyEvent, &ev, getwaitticks (), nil);
03126         
03127         appletevent = ev; /*set global, can be accessed by anyone with an interest*/
03128         
03129         appleteventdispatcher (&ev);
03130         } /*while*/
03131     } /*maineventloop*/
03132 
03133 
03134 boolean appserviceeventqueue (void) {
03135     
03136     /*
03137     pop and process all waiting events, return true when we get to a null 
03138     event. return false if the user selected the quit command, or otherwise
03139     wants the program to terminate.
03140     
03141     8/8/92 DW: return false also if the user presses cmd-period.
03142     */
03143     
03144     EventRecord ev;
03145     
03146     flcmdperiod = false;
03147     
03148     while (!flexitmainloop) {
03149         
03150         WaitNextEvent (everyEvent, &ev, getwaitticks (), nil);
03151         
03152         if (ev.what == nullEvent) /*got all the meaningful events*/
03153             return (true);
03154         
03155         appleteventdispatcher (&ev);
03156         
03157         if (flcmdperiod) {
03158             
03159             /*sysbeep;*/
03160             
03161             return (false);
03162             }
03163         } /*while*/
03164         
03165     return (false); /*user must have selected the quit command*/
03166     } /*appserviceeventqueue*/
03167 
03168 
03169 static void initscrap (void) {
03170     
03171     PScrapStuff x;
03172     
03173     x = InfoScrap ();
03174     
03175     if ((*x).scrapState < 0) /*following advice of THINK Reference*/
03176         ZeroScrap ();
03177     } /*initscrap*/
03178     
03179 
03180 static boolean noopcallback (void) {
03181     
03182     /*sysbeep;*/
03183     
03184     return (false);
03185     } /*noopcallback*/
03186     
03187     
03188 static void checkcallback (tyappcallback *cb) {
03189     
03190     if (*cb == nil) /*the applet doesn't define this callback*/
03191         *cb = &noopcallback;
03192     } /*checkcallback*/
03193     
03194     
03195 static void normaleraserectcallback (Rect r) {
03196     
03197     EraseRect (&r);
03198     } /*normaleraserectcallback*/
03199     
03200     
03201 static boolean normalsetfontcallback (void) {
03202     
03203     hdlappwindow ha = app.appwindow;
03204     tyselectioninfo x = (**ha).selectioninfo;
03205     
03206     if (x.fontnum != -1)
03207         (**ha).defaultfont = x.fontnum;
03208     
03209     if (x.fontsize != -1)
03210         (**ha).defaultsize = x.fontsize;
03211         
03212     invalappwindow (ha, true);
03213     
03214     return (true);
03215     } /*normalsetfontcallback*/
03216     
03217     
03218 static void checknilcallbacks (void) {
03219     
03220     installscroll (); /*install default handlers if appropriate*/
03221     
03222     checkcallback (&app.newrecordcallback); 
03223     
03224     checkcallback (&app.disposerecordcallback); 
03225     
03226     checkcallback (&app.idlecallback); 
03227     
03228     checkcallback ((tyappcallback *) &app.activatecallback);
03229     
03230     checkcallback ((tyappcallback *) &app.switchcallback);
03231     
03232     checkcallback (&app.updatecallback);
03233     
03234     checkcallback (&app.preupdatecallback);
03235     
03236     checkcallback (&app.windowresizecallback);
03237     
03238     checkcallback (&app.iacmessagecallback);
03239     
03240     checkcallback (&app.iacfastmessagecallback);
03241     
03242     checkcallback ((tyappcallback *) &app.packcallback);
03243     
03244     checkcallback ((tyappcallback *) &app.unpackcallback);
03245     
03246     checkcallback ((tyappcallback *) &app.gettextcallback); 
03247     
03248     checkcallback ((tyappcallback *) &app.getpictcallback); 
03249     
03250     checkcallback ((tyappcallback *) &app.scrollcallback); 
03251     
03252     checkcallback ((tyappcallback *) &app.resetscrollcallback); 
03253     
03254     checkcallback (&app.scrolltocallback); 
03255     
03256     checkcallback (&app.pagesetupcallback);
03257     
03258     checkcallback (&app.openprintcallback);
03259     
03260     checkcallback ((tyappcallback *) &app.printpagecallback);
03261     
03262     checkcallback (&app.closeprintcallback);
03263     
03264     checkcallback ((tyappcallback *) &app.puttextcallback);
03265     
03266     checkcallback ((tyappcallback *) &app.putpictcallback);
03267     
03268     checkcallback (&app.haveselectioncallback);
03269     
03270     checkcallback (&app.selectallcallback);
03271     
03272     checkcallback (&app.keystrokecallback);
03273     
03274     checkcallback (&app.mousecallback);
03275     
03276     checkcallback (&app.mouseinstatuscallback);
03277     
03278     checkcallback (&app.updatestatuscallback);
03279     
03280     checkcallback ((tyappcallback *) &app.menucallback);
03281     
03282     checkcallback (&app.insertmenucallback);
03283     
03284     checkcallback (&app.setselectioninfocallback);
03285         
03286     if (app.setfontcallback == nil)
03287         app.setfontcallback = &normalsetfontcallback;
03288     
03289     if (app.setsizecallback == nil)
03290         app.setsizecallback = &normalsetfontcallback;
03291             
03292     checkcallback (&app.setstylecallback);
03293     
03294     checkcallback (&app.setjustifycallback);
03295     
03296     checkcallback ((tyappcallback *) &app.copycallback);
03297         
03298     checkcallback (&app.clearcallback);
03299     
03300     checkcallback ((tyappcallback *) &app.pastecallback);
03301     
03302     checkcallback (&app.initmacintoshcallback);
03303     
03304     checkcallback ((tyappcallback *) &app.resumecallback);
03305     
03306     checkcallback (&app.openappcallback);
03307     
03308     checkcallback ((tyappcallback *) &app.opendoccallback);
03309     
03310     if (app.eraserectcallback == nil)
03311         app.eraserectcallback = &normaleraserectcallback;
03312         
03313     checkcallback ((tyappcallback *) &app.getcontentsizecallback);
03314     
03315     checkcallback ((tyappcallback *) &app.setglobalscallback);
03316     
03317     checkcallback ((tyappcallback *) &app.getoptionscallback);
03318     
03319     checkcallback ((tyappcallback *) &app.putoptionscallback);
03320     
03321     checkcallback ((tyappcallback *) &app.getundoglobalscallback);
03322     
03323     checkcallback ((tyappcallback *) &app.setundoglobalscallback);
03324     
03325     checkcallback ((tyappcallback *) &app.afteropenwindowcallback);
03326     
03327     checkcallback ((tyappcallback *) &app.beforeclosewindowcallback);
03328     
03329     checkcallback ((tyappcallback *) &app.beforequitcallback);
03330     
03331     checkcallback ((tyappcallback *) &app.diskinsertedcallback);
03332     
03333     checkcallback ((tyappcallback *) &app.interpretfilecallback);
03334     
03335     checkcallback ((tyappcallback *) &app.aftersavewindowcallback);
03336     
03337     if (app.alertcallback == nil)
03338         app.alertcallback = &alertdialog;
03339     } /*checknilcallbacks*/
03340     
03341     
03342 static pascal void pascalalertdialog (Str255 s) {
03343     
03344     if (stringlength (s) > 0)
03345         alertdialog (s);
03346     } /*pascalalertdialog*/
03347     
03348     
03349 static pascal void pascaleventfilter (EventRecord *ev) {
03350     
03351     appleteventdispatcher (ev);
03352     } /*pascaleventfilter*/
03353     
03354     
03355 static boolean managersinited = false;
03356 
03357     
03358 boolean appletinitmanagers (void) { /*4/13/93 DW: returns a boolean, for Card Editor*/
03359 
03360     initmacintosh ();
03361     
03362     checknilcallbacks (); /*initmenus uses a callback routine*/
03363     
03364     if (app.minwindowwidth == 0)
03365         app.minwindowwidth = 125;
03366         
03367     if (app.minwindowheight == 0)
03368         app.minwindowheight = 100;
03369         
03370     app.dontpostcallback = false; 
03371     
03372     appletheapzone = GetZone ();
03373     
03374     initmenus ();
03375     
03376     initscrap ();
03377     
03378     initsyserror ();
03379 
03380     IACinit ();
03381     
03382     clearbytes (&mousestatus, longsizeof (mousestatus));
03383     
03384     #ifdef appRunsCards
03385     
03386         initIowaRuntime ();
03387     
03388     #endif
03389         
03390     InitSharedMenus (&pascalalertdialog, &pascaleventfilter);
03391         
03392     initappletwires (); 
03393     
03394     (*app.initmacintoshcallback) ();
03395     
03396     managersinited = true;
03397     
03398     return (true);
03399     } /*appletinitmanagers*/
03400     
03401     
03402 void runapplet (void) {
03403     
03404     if (!managersinited) 
03405         appletinitmanagers ();
03406     
03407     maineventloop ();
03408     
03409     #if false
03410     
03411         IACremovesystemhandlers ();
03412         
03413     #endif
03414     } /*runapplet*/
03415     
03416     
03417     

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