menuverbs.c

Go to the documentation of this file.
00001 
00002 /*  $Id: menuverbs.c 1260 2006-04-13 06:13:10Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "quickdraw.h"
00033 #include "strings.h"
00034 #include "kb.h"
00035 #include "menu.h"
00036 #include "ops.h"
00037 #include "resources.h"
00038 #include "search.h"
00039 #include "shell.h"
00040 #include "shellhooks.h"
00041 #include "shellmenu.h"
00042 #include "shellundo.h"
00043 #include "lang.h"
00044 #include "langexternal.h"
00045 #include "tablestructure.h"
00046 #include "menueditor.h"
00047 #include "opinternal.h"
00048 #include "opverbs.h"
00049 #include "menuinternal.h"
00050 #include "meprograms.h"
00051 #include "menuverbs.h"
00052 #include "cancoon.h"
00053 #include "kernelverbdefs.h"
00054 
00055 
00056 
00057 #define menustringlist 166
00058 #define menutypestring 1
00059 #define menusizestring 2
00060 
00061 
00062 #define menuerrorlist 266
00063 #define nomenuerror 1
00064 #define namenotmenuerror 2
00065 
00066 
00067 typedef enum tymenutoken { /*verbs that are processed by menueditor.c*/
00068     
00069     zoomscriptfunc,
00070     
00071     buildmenubarfunc,
00072     
00073     clearmenubarfunc,
00074     
00075     isinstalledfunc,
00076     
00077     installfunc,
00078     
00079     removefunc,
00080     
00081     getscriptfunc,
00082     
00083     setscriptfunc,
00084     
00085     addmenucommandfunc,
00086     
00087     deletemenucommandfunc,
00088     
00089     addsubmenufunc,
00090     
00091     deletesubmenufunc,
00092     
00093     getcommandkeyfunc,
00094     
00095     setcommandkeyfunc,
00096     
00097     ctmenuverbs
00098     } tymenutoken;
00099 
00100 #if langexternalfind_optimization
00101 
00102     typedef tyexternalvariable tymenuvariable, *ptrmenuvariable, **hdlmenuvariable;
00103 
00104 #else
00105 
00106 typedef struct tymenuvariable { /*7.0b6 PBS: moved from menuverbs.c*/
00107     
00108     unsigned short id; /*tyexternalid: managed by langexternal.c*/
00109     
00110     unsigned short flinmemory: 1; /*if true, variabledata is an hdlmenurecord, else a dbaddress*/
00111     
00112     unsigned short flmayaffectdisplay: 1; /*not in memory, but being displayed in a table window*/
00113     
00114     long variabledata; /*either a hdlmenurecord or a dbaddress*/
00115     
00116     hdldatabaserecord hdatabase; // 5.0a18 dmb
00117 
00118     dbaddress oldaddress; /*last place this menubar doc was stored in db*/
00119     } tymenuvariable, *ptrmenuvariable, **hdlmenuvariable;
00120 
00121 #endif
00122 
00123         
00124 static short errornum = 0; /*error number exclusively for menu routines*/
00125 
00126 
00127 
00128 boolean menuverbgettypestring (hdlexternalvariable hvariable, bigstring bs) {
00129 #pragma unused (hvariable)
00130 
00131     getstringlist (menustringlist, menutypestring, bs);
00132     
00133     return (true);
00134     } /*menuverbgettypestring*/
00135     
00136 
00137 static boolean newmenuvariable (boolean flinmemory, long variabledata, hdlmenuvariable *h) {
00138 
00139     return (langnewexternalvariable (flinmemory, variabledata, (hdlexternalvariable *) h));
00140     } /*newmenuvariable*/
00141 
00142 
00143 boolean menuverbunload (hdlexternalvariable hvariable) {
00144     
00145     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00146     
00147     if ((**hv).flinmemory) { /*if it's on disk, don't need to do anything*/
00148         
00149         medisposemenurecord ((hdlmenurecord) (**hv).variabledata, false);
00150         
00151         (**hv).variabledata = (**hv).oldaddress;
00152         
00153         (**hv).oldaddress = 0;
00154         
00155         (**hv).flinmemory = false;
00156         }
00157     
00158     return (true);
00159     } /*menuverbunload*/
00160 
00161 
00162 static boolean menuverbinmemory (hdlmenuvariable hvariable) {
00163     
00164     /*
00165     5.0a18 dmb: support database linking
00166     */
00167     
00168     register hdlmenuvariable hv = hvariable;
00169     register dbaddress adr;
00170     hdlmenurecord hmenurecord;
00171     boolean fl;
00172     
00173     if ((**hv).flinmemory)
00174         return (true);
00175     
00176     dbpushdatabase ((**hv).hdatabase);
00177 
00178     adr = (dbaddress) (**hv).variabledata;
00179     
00180     fl = meloadmenurecord (adr, &hmenurecord);
00181 
00182     dbpopdatabase ();
00183 
00184     if (!fl)
00185         return (false);
00186     
00187     (**hv).variabledata = (long) hmenurecord;
00188     
00189     (**hv).oldaddress = adr;
00190     
00191     (**hv).flinmemory = true;
00192     
00193     (**hmenurecord).menurefcon = (long) hv; /*we can get from menu rec to variable rec*/
00194     
00195     return (true);
00196     } /*menuverbinmemory*/
00197 
00198 
00199 boolean menuverbgetsize (hdlexternalvariable hvariable, long *size) {
00200     
00201     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00202     register hdlmenurecord hm;
00203     short ctheads;
00204     
00205     if (!menuverbinmemory (hv))
00206         return (false);
00207     
00208     hm = (hdlmenurecord) (**hv).variabledata;
00209     
00210     oppushoutline ((**hm).menuoutline);
00211     
00212     ctheads = opcountheads ();
00213     
00214     oppopoutline ();
00215     
00216     *size = (long) ctheads;
00217     
00218     return (true);
00219     } /*menuverbgetsize*/
00220 
00221 
00222 boolean menuverbgetdisplaystring (hdlexternalvariable hvariable, bigstring bs) {
00223     
00224     /*
00225     get string for table display.  variable is in memory
00226     */
00227     
00228     long ctheads;
00229     
00230     if (!menuverbgetsize (hvariable, &ctheads))
00231         return (false);
00232     
00233     parsenumberstring (menustringlist, menusizestring, ctheads, bs);
00234 
00235     /*
00236     numbertostring (ctheads, bs);
00237     
00238     if (ctheads != 1)
00239         pushstring ("\p items", bs);
00240     else
00241         pushstring ("\p item", bs);
00242     */
00243     
00244     return (true);
00245     } /*menuverbgetdisplaystring*/
00246 
00247 
00248 boolean menuverbisdirty (hdlexternalvariable hvariable) {
00249     
00250     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00251     
00252     if (!(**hv).flinmemory) /*it's on disk, can't be dirty*/
00253         return (false);
00254     
00255     return (mesomethingdirty ((hdlmenurecord) (**hv).variabledata));
00256     } /*menuverbisdirty*/
00257 
00258 
00259 boolean menuverbsetdirty (hdlexternalvariable hvariable, boolean fldirty) {
00260     
00261     /*
00262     4/15/92 dmb: see comments in langexternalsetdirty
00263     
00264     note: it may be that this routine should clean every script when 
00265     fldirty is false
00266     */
00267     
00268     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00269     
00270     if (!menuverbinmemory (hv))
00271         return (false);
00272     
00273     (**(hdlmenurecord) (**hv).variabledata).fldirty = fldirty;
00274     
00275     return (true);
00276     } /*menuverbsetdirty*/
00277 
00278 
00279 boolean menuverbmemorypack (hdlexternalvariable hvariable, Handle *hpacked) {
00280     
00281     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00282     register hdlmenurecord hm;
00283     Handle hpush;
00284     register boolean fl;
00285     boolean fltempload;
00286     
00287     fltempload = !(**hv).flinmemory;
00288     
00289     if (!menuverbinmemory (hv))
00290         return (false);
00291     
00292     hm = (hdlmenurecord) (**hv).variabledata;
00293     
00294     fl = mesavemenurecord (hm, false, true, nil, &hpush);
00295     
00296     if (fltempload)
00297         menuverbunload ((hdlexternalvariable) hv);
00298     
00299     if (fl) {
00300         
00301         fl = pushhandle (hpush, *hpacked);
00302         
00303         disposehandle (hpush);
00304         }
00305     
00306     return (fl);
00307     } /*menuverbmemorypack*/
00308 
00309 
00310 boolean menuverbmemoryunpack (Handle hpacked, long *ixload, hdlexternalvariable *h) {
00311     
00312     /*
00313     create a new outline variable -- not in memory.
00314     
00315     this is a special entrypoint for the pack and unpack verbs.
00316     */
00317     
00318     Handle hpackedmenu;
00319     hdlmenurecord hmenurecord;
00320     register hdlmenurecord hm;
00321     
00322     if (!loadhandleremains (*ixload, hpacked, &hpackedmenu))
00323         return (false);
00324     
00325     if (!meunpackmenustructure (hpackedmenu, &hmenurecord)) /*always disposes of hpackedmenu*/
00326         return (false);
00327     
00328     hm = hmenurecord; /*move into register*/
00329     
00330     if (!newmenuvariable (true, (long) hm, (hdlmenuvariable *) h)) {
00331         
00332         medisposemenurecord (hm, false);
00333         
00334         return (false);
00335         }
00336     
00337     (**hm).menurefcon = (long) *h; /*point back to variable*/
00338     
00339     (**hm).fldirty = true;
00340     
00341     return (true);
00342     } /*menuverbmemoryunpack*/
00343 
00344 
00345 boolean menuverbpack (hdlexternalvariable hvariable, Handle *hpacked, boolean *flnewdbaddress) {
00346 
00347     /*
00348     6.2a15 AR: added flnewdbaddress parameter
00349     */
00350 
00351     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00352     register hdlmenurecord hm;
00353     dbaddress adr;
00354     boolean fl;
00355     boolean fltempload = false;
00356     boolean flpreservelinks;
00357     hdlwindowinfo hinfo;
00358     
00359     if (fldatabasesaveas) {
00360         
00361         fltempload = !(**hv).flinmemory;
00362         
00363         if (!menuverbinmemory (hv))
00364             return (false);
00365             
00366         *flnewdbaddress = true;
00367         }
00368     
00369     if (!(**hv).flinmemory) { /*simple case, menu is resident in the db*/
00370         
00371         adr = (dbaddress) (**hv).variabledata;
00372         
00373         *flnewdbaddress = false;
00374         
00375         goto pushaddress;
00376         }
00377     
00378     adr = (**hv).oldaddress; /*place where this menubar used to be stored*/
00379     
00380     hm = (hdlmenurecord) (**hv).variabledata;
00381     
00382     flpreservelinks = fldatabasesaveas && !fltempload;
00383     
00384     fl = mesavemenurecord (hm, flpreservelinks, false, &adr, nil);
00385     
00386     if (fltempload)
00387         menuverbunload ((hdlexternalvariable) hv);
00388     
00389     if (!fl)
00390         return (false);
00391     
00392     if (fldatabasesaveas)
00393         goto pushaddress;
00394 
00395     *flnewdbaddress = ((**hv).oldaddress != adr);
00396     
00397     (**hv).oldaddress = adr;
00398     
00399     (**hm).fldirty = false; /*we just saved off a new db version*/
00400     
00401     if (menuwindowopen ((hdlexternalvariable) hv, &hinfo) && (hinfo != nil))
00402         shellsetwindowchanges (hinfo, false);
00403     
00404     pushaddress:
00405     
00406     return (pushlongondiskhandle (adr, *hpacked));
00407     } /*menuverbpack*/
00408 
00409 
00410 boolean menuverbunpack (Handle hpacked, long *ixload, hdlexternalvariable *h) {
00411 
00412     dbaddress adr;
00413     
00414     if (!loadlongfromdiskhandle (hpacked, ixload, &adr)) 
00415         return (false);
00416         
00417     return (newmenuvariable (false, adr, (hdlmenuvariable *) h));
00418     } /*menuverbunpack*/
00419 
00420 
00421 boolean menuverbpacktotext (hdlexternalvariable hvariable, Handle htext) {
00422     
00423     /*
00424     5.0.2b20 dmb: unload if just loaded
00425     */
00426     
00427     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00428     register hdlmenurecord hm;
00429     boolean fl;
00430     boolean fltempload = !(**hv).flinmemory;
00431     
00432     if (!menuverbinmemory (hv))
00433         return (false);
00434     
00435     hm = (hdlmenurecord) (**hv).variabledata;
00436     
00437     fl = opoutlinetotextscrap ((**hm).menuoutline, false, htext);
00438     
00439     if (fltempload)
00440         menuverbunload ((hdlexternalvariable) hv);
00441     
00442     return (fl);
00443     } /*menuverbpacktotext*/
00444 
00445 
00446 boolean menuverbgettimes (hdlexternalvariable h, long *timecreated, long *timemodified) {
00447     
00448     register hdlmenuvariable hv = (hdlmenuvariable) h;
00449     register hdlmenurecord hm;
00450     register hdloutlinerecord ho;
00451     
00452     if (!menuverbinmemory (hv))
00453         return (false);
00454     
00455     hm = menudata = (hdlmenurecord) (**hv).variabledata;
00456     
00457     ho = (**hm).menuoutline;
00458     
00459     *timecreated = (**ho).timecreated;
00460     
00461     *timemodified = (**ho).timelastsave;
00462     
00463     return (true);
00464     } /*menuverbgettimes*/
00465 
00466 
00467 boolean menuverbsettimes (hdlexternalvariable h, long timecreated, long timemodified) {
00468     
00469     register hdlmenuvariable hv = (hdlmenuvariable) h;
00470     register hdlmenurecord hm;
00471     register hdloutlinerecord ho;
00472     
00473     if (!menuverbinmemory (hv))
00474         return (false);
00475     
00476     hm = menudata = (hdlmenurecord) (**hv).variabledata;
00477     
00478     ho = (**hm).menuoutline;
00479     
00480     (**ho).timecreated = timecreated;
00481     
00482     (**ho).timelastsave = timemodified;
00483     
00484     return (true);
00485     } /*menuverbsettimes*/
00486 
00487 
00488 static boolean mefindusedblocksvisit (hdlheadrecord hnode, ptrvoid refcon) {
00489     
00490     /*
00491     if there's a script attached to hnode, note the database usage.
00492     */
00493     
00494     ptrstring bsparent = (ptrstring) refcon;
00495     tymenuiteminfo item;
00496     bigstring bspath;
00497     
00498     if (megetmenuiteminfo (hnode, &item)) { /*something linked*/
00499         
00500         opgetheadstring (hnode, bspath);
00501         
00502         pushchar (']', bspath);
00503 
00504         insertstring (BIGSTRING ("\x02" " ["), bspath);
00505 
00506         insertstring (bsparent, bspath);
00507 
00508         return (statsblockinuse (item.linkedscript.adrlink, bspath));
00509         }
00510     
00511     return (true); /*keep visiting*/
00512     } /*mefindusedblocksvisit*/
00513 
00514 
00515 boolean menuverbfindusedblocks (hdlexternalvariable hvariable, bigstring bspath) {
00516     
00517     /*
00518     note the database usage for the entire menubar outline.  see dbstats.c
00519     */
00520     
00521     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00522     register hdlmenurecord hm;
00523     register hdloutlinerecord ho;
00524     register boolean fl;
00525     boolean fltempload;
00526     hdlheadrecord hcursor;
00527     hdlheadrecord hsummit;
00528     
00529     fltempload = !(**hv).flinmemory;
00530     
00531     if (!menuverbinmemory (hv))
00532         return (false);
00533     
00534     if (!statsblockinuse ((**hv).oldaddress, bspath))
00535         return (false);
00536     
00537     hm = menudata = (hdlmenurecord) (**hv).variabledata; /*move into register, global*/
00538     
00539     statsblockinuse ((**hm).adroutline, bspath);
00540     
00541     ho = (**hm).menuoutline;
00542     
00543     oppushoutline (ho);
00544     
00545     hcursor = (**ho).hbarcursor;
00546     
00547     oppopallhoists (); /*pop hoists, save state to be restored after saving*/
00548     
00549     (**ho).hbarcursor = hcursor; /*scotch tape!*/
00550     
00551     opoutermostsummit (&hsummit);
00552     
00553     fl = opsiblingvisiter (hsummit, false, &mefindusedblocksvisit, bspath);
00554     
00555     oprestorehoists (); /*restore the hoist state*/
00556     
00557     oppopoutline (); /*pop outline globals*/
00558     
00559     if (fltempload)
00560         menuverbunload ((hdlexternalvariable) hv);
00561     
00562     return (fl);
00563     } /*menuverbfindusedblocks*/
00564 
00565 
00566 boolean menuverbfind (hdlexternalvariable hvariable, boolean *flzoom) {
00567     
00568     /*
00569     5.1.5 dmb: fixed searching in guest databases
00570     */
00571     
00572     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00573     register hdlmenurecord hm, hmsave = menudata;
00574     register hdloutlinerecord ho;
00575     register boolean fl;
00576     boolean fltempload;
00577     boolean flwindowopen;
00578     hdlwindowinfo hinfo;
00579     boolean fldisplaywasenabled = true;
00580     
00581     fltempload = !(**hv).flinmemory;
00582     
00583     if (!menuverbinmemory (hv))
00584         return (false);
00585     
00586     hm = (hdlmenurecord) (**hv).variabledata;
00587     
00588     ho = (**hm).menuoutline;
00589 
00590     flwindowopen = menuwindowopen ((hdlexternalvariable) hv, &hinfo);
00591     
00592     if (flwindowopen && (hinfo != nil))
00593         shellpushglobals ((**hinfo).macwindow);
00594     
00595     else {
00596         shellpushglobals (nil);
00597         
00598         menudata = hm; //5.1.5 dmb: for search refcon callback, setting database
00599         
00600         oppushoutline (ho);
00601         
00602         fldisplaywasenabled = opdisabledisplay (); /*we haven't set up display context*/
00603         }
00604     
00605     fl = mesearchoutline (true, false, flzoom);
00606     
00607     if (!flwindowopen) {
00608         
00609         if (fldisplaywasenabled)
00610             openabledisplay ();
00611         
00612         oppopoutline ();
00613         
00614         menudata = hmsave;
00615         }
00616     
00617     shellpopglobals ();
00618     
00619     if (fltempload && !fl && !(**ho).fldirty)
00620         menuverbunload ((hdlexternalvariable) hv);
00621     
00622     return (fl);
00623     } /*menuverbfind*/
00624 
00625 
00626 boolean menunewmenubar (hdlhashtable htable, bigstring bs, hdlmenurecord *hnewrecord) {
00627 
00628     /*
00629     create a new menubar variable in the indicated table 
00630     with the indicated name.  returns a handle to the new
00631     menurecord.
00632     */
00633     
00634     register hdlmenurecord hm;
00635     hdlmenuvariable hv;
00636     
00637     if (!menewmenurecord (hnewrecord))
00638         return (false);
00639         
00640     hm = *hnewrecord; /*copy into register*/
00641         
00642     if (!newmenuvariable (true, (long) hm, &hv)) {
00643         
00644         medisposemenurecord (hm, false);
00645         
00646         return (false);
00647         }
00648         
00649     (**hv).variabledata = (long) hm; /*link the menu rec into the variable rec*/
00650     
00651     (**hm).menurefcon = (long) hv; /*the pointing is mutual*/
00652     
00653     if (!langsetexternalsymbol (htable, bs, idmenuprocessor, (Handle) hv)) {
00654         
00655         medisposemenurecord (hm, false);
00656         
00657         disposehandle ((Handle) hv);
00658         
00659         return (false);
00660         }
00661     
00662     return (true);
00663     } /*menunewmenubar*/
00664 
00665 
00666 static boolean menugetmenuvariable (hdlhashtable htable, bigstring bs, boolean *fltypeerror, hdlmenuvariable *hvariable) {
00667 
00668     /*
00669     return a handle to the menubar variable indicated by [htable, bs].  returns false
00670     if there isn't a variable with the indicated name, or if itsn't of type menubar.
00671     
00672     7/7/90 DW: return a flag to indicate if an error was caused by an undefined name
00673     or if a variable with the indicated name exists and is the wrong type.  the caller
00674     may want to do something different depending on which error.
00675     */
00676     
00677     hdlhashnode hnode;
00678     register boolean fl;
00679     tyvaluerecord val;
00680     register hdlexternalvariable hv;
00681     
00682     pushhashtable (htable);
00683     
00684     fl = langfindsymbol (bs, &htable, &hnode);
00685     
00686     pophashtable ();
00687     
00688     if (!fl) {
00689         
00690         *fltypeerror = false; /*it's an undefined variable error*/
00691         
00692         return (false);
00693         }
00694     
00695     *fltypeerror = true; /*if we return false below, it is a type error*/
00696     
00697     val = (**hnode).val;
00698     
00699     if (val.valuetype != externalvaluetype) /*it's defined, but it's not a menubar*/
00700         return (false);
00701         
00702     hv = (hdlexternalvariable) val.data.externalvalue;
00703     
00704     if ((**hv).id != idmenuprocessor) /*it's defined, it's external, but wrong type*/
00705         return (false);
00706         
00707     *hvariable = (hdlmenuvariable) hv;
00708     
00709     *fltypeerror = false; /*no error*/
00710     
00711     return (true);
00712     } /*menugetmenuvariable*/
00713             
00714 
00715 boolean menugetmenubar (hdlhashtable htable, bigstring bs, boolean flcreate, hdlmenurecord *hmenubar) {
00716 
00717     /*
00718     find the indicated menubar or create an empty one.
00719     */
00720     
00721     boolean fltypeerror;
00722     hdlmenuvariable hvariable;
00723     
00724     if (!menugetmenuvariable (htable, bs, &fltypeerror, &hvariable)) {
00725         
00726         if (!flcreate)
00727             return (false);
00728         
00729         if (fltypeerror) { /*don't over-write an existing variable of wrong type*/
00730             
00731             /*xxx -- error dialog goes here*/
00732             
00733             return (false);
00734             }
00735             
00736         return (menunewmenubar (htable, bs, hmenubar));
00737         }
00738     
00739     if (!menuverbinmemory (hvariable)) /*error swapping it in*/
00740         return (false);
00741         
00742     *hmenubar = (hdlmenurecord) (**hvariable).variabledata;
00743     
00744     return (true);
00745     } /*menugetmenubar*/
00746 
00747 
00748 static boolean getmenuparam (hdltreenode hfirst, short pnum, hdlmenuvariable *hv) {
00749     
00750     short id;
00751     
00752     if (!langexternalgetexternalparam (hfirst, pnum, &id, (hdlexternalvariable *) hv)) {
00753         
00754         errornum = namenotmenuerror;
00755         
00756         return (false);
00757         }
00758     
00759     if (id != idmenuprocessor) {
00760         
00761         errornum = namenotmenuerror;
00762         
00763         return (false);
00764         }
00765     
00766     return (true);
00767     } /*getmenuparam*/
00768     
00769 
00770 boolean menuwindowopen (hdlexternalvariable hvariable, hdlwindowinfo *hinfo) {
00771 
00772     /*
00773     5.0b9 dmb: for clipboard operations, must test hm for nil
00774     */
00775     
00776     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00777     hdlmenurecord hm;
00778     
00779     if (!(**hv).flinmemory)
00780         return (false);
00781     
00782     hm = (hdlmenurecord) (**hv).variabledata;
00783     
00784     if (hm == nil)
00785         return (false);
00786 
00787     shellfinddatawindow ((Handle) (**hv).variabledata, hinfo);
00788     
00789     return ((**hm).flwindowopen);
00790     } /*menuwindowopen*/
00791 
00792 
00793 boolean menuedit (hdlexternalvariable hvariable, hdlwindowinfo hparent, ptrfilespec fs, bigstring bstitle, rectparam rzoom) {
00794     
00795     /*
00796     5.0d19 dmb: set flwindowopen; use locals, not menu globals.
00797     */
00798     
00799     register hdlmenuvariable hv = (hdlmenuvariable) hvariable;
00800     hdlmenurecord hm;
00801     Rect rwindow;
00802     WindowPtr w;
00803     hdlwindowinfo hi;
00804     
00805     if ((**hv).flinmemory) {
00806             
00807         if (shellfinddatawindow ((Handle) (**hv).variabledata, &hi)) {
00808             
00809             if ((*rzoom).top > -2)
00810                 shellbringtofront (hi);
00811             
00812             return (true);
00813             }
00814         }
00815         
00816     if (!menuverbinmemory (hv)) /*error swapping menurecord into memory*/
00817         return (false);
00818         
00819     hm = (hdlmenurecord) (**hv).variabledata;
00820     
00821     rwindow = (**hm).menuwindowrect; /*window comes up where it was last time*/
00822     
00823     if (!newchildwindow (idmenueditorconfig, hparent, &rwindow, rzoom, bstitle, &w)) 
00824         return (false);
00825     
00826     getwindowinfo (w, &hi);
00827     
00828     (**hi).hdata = (Handle) hm; /*link data into shell's structure*/
00829     
00830     if (fs != nil)
00831         (**hi).fspec = *fs;
00832     
00833     shellpushglobals (w);
00834     
00835     meeditmenurecord ();
00836     
00837     shellpopglobals ();
00838     
00839     (**hm).flwindowopen = true;
00840     
00841     if ((**hm).fldirty)
00842         shellsetwindowchanges (hi, true);
00843     
00844     windowzoom (w); /*show the window to the user*/
00845     
00846     return (true);
00847     } /*menuedit*/
00848 
00849 
00850 static boolean menudisposevariable (hdlexternalvariable hvariable, boolean fldisk) {
00851     
00852     medisposemenurecord ((hdlmenurecord) (**hvariable).variabledata, fldisk);
00853     
00854     return (true);
00855     } /*menudisposevariable*/
00856 
00857 
00858 boolean menuverbdispose (hdlexternalvariable hvariable, boolean fldisk) {
00859     
00860     /*
00861     12/22/91 dmb: in order to release all db nodes properly, must force 
00862     menubar to be loaded when fldisk is true
00863     */
00864     
00865     register hdlexternalvariable hv = hvariable;
00866     
00867     if (fldisk) { /*load menubar into memory so that scripts can release their db nodes*/
00868         
00869         if (!menuverbinmemory ((hdlmenuvariable) hv))
00870             return (false);
00871         }
00872     
00873     return (langexternaldisposevariable (hv, fldisk, &menudisposevariable));
00874     } /*menuverbdispose*/
00875 
00876 
00877 boolean menuverbnew (Handle hdata, hdlexternalvariable *hvariable) {
00878     
00879     /*  
00880     12/29/91 dmb: added call to opsetctexpanded()
00881     */
00882     
00883     register hdlmenurecord hm;
00884     register hdlmenuvariable hv;
00885     hdlmenurecord hnewrecord;
00886     
00887     if (!menewmenurecord (&hnewrecord))
00888         return (false);
00889     
00890     hm = hnewrecord; /*copy into register*/
00891     
00892     if (!newmenuvariable (true, (long) hm, (hdlmenuvariable *) hvariable)) {
00893         
00894         medisposemenurecord (hm, false);
00895         
00896         return (false);
00897         }
00898     
00899     hv = (hdlmenuvariable) *hvariable; /*copy into register*/
00900     
00901     if (hdata != nil) {
00902         
00903         register hdloutlinerecord ho = (**hm).menuoutline;
00904         register hdloutlinerecord hsource = (hdloutlinerecord) hdata;
00905         hdlheadrecord hsummit = nil;
00906         
00907         oppushoutline (ho);
00908         
00909         opcopysiblings ((**hsource).hsummit, &hsummit);
00910         
00911         if (hsummit == nil) {
00912             
00913             oppopoutline ();
00914             
00915             medisposemenurecord (hm, false);
00916             
00917             disposehandle ((Handle) hv);
00918             
00919             return (false);
00920             }
00921         
00922         opsetsummit (ho, hsummit);
00923         
00924         opcopyformatting (hsource, ho);
00925         
00926         opdirtymeasurements (); //6.0a14 dmb
00927         
00928         opsetctexpanded (ho);
00929         
00930         oppopoutline ();
00931         }
00932     
00933     (**hv).variabledata = (long) hm; /*link the menu rec into the variable rec*/
00934     
00935     (**hm).menurefcon = (long) hv; /*the pointing is mutual*/
00936     
00937     return (true);
00938     } /*menuverbnew*/
00939 
00940 
00941 static boolean menubuildverb (void) {
00942     
00943     /*
00944     rebuild the menubar -- the active flag must be set in order for the changes
00945     to appear in the menubar.
00946     
00947     4/22/91 dmb: use new rebuildmenubarlist
00948     */
00949     
00950     return (rebuildmenubarlist ());
00951     } /*menubuildverb*/
00952 
00953 
00954 static boolean menuclearverb (void) {
00955     
00956     /*
00957     remove all of the menus from the menu bar
00958     */
00959     
00960     return (meclearmenubar ());
00961     } /*menuclearverb*/
00962 
00963 
00964 static boolean getmenuparaminmemory (hdltreenode hparam1, hdlmenurecord *hmenurecord) {
00965     
00966     /*
00967     the first parameter in hparam1 should point to a menu record.
00968     
00969     try to load it.
00970     */
00971     
00972     hdlmenuvariable hv;
00973     
00974     if (!getmenuparam (hparam1, 1, &hv))
00975         return (false);
00976     
00977     if (!menuverbinmemory (hv))
00978         return (false);
00979     
00980     *hmenurecord = (hdlmenurecord) (**hv).variabledata;
00981     
00982     return (true);
00983     } /*getmenuparaminmemory*/
00984 
00985 
00986 static boolean menuisinstalledverb (hdltreenode hparam1, tyvaluerecord *v) {
00987     
00988     hdlmenurecord hmenurecord;
00989     
00990     flnextparamislast = true;
00991     
00992     if (!getmenuparaminmemory (hparam1, &hmenurecord))
00993         return (false);
00994     
00995     (*v).data.flvalue = (**hmenurecord).flinstalled;
00996     
00997     return (true);
00998     } /*menuisinstalledverb*/
00999 
01000 
01001 static boolean getmainmenuvalue (hdltreenode hparam1, hdlmenu *hmenu, short *idmenu) {
01002     
01003     tyvaluerecord val;
01004     bigstring bsmenu;
01005     
01006     flnextparamislast = true;
01007     
01008     if (!getparamvalue (hparam1, 1, &val))
01009         return (false);
01010     
01011     if (val.valuetype != stringvaluetype)
01012         return (false);
01013     
01014     texthandletostring ((Handle) val.data.stringvalue, bsmenu);
01015     
01016     return (shelltgetmainmenu (bsmenu, hmenu, idmenu));
01017     } /*getmainmenuvalue*/
01018 
01019 
01020 static boolean menuinstallverb (hdltreenode hparam1, tyvaluerecord *v) {
01021     
01022     hdlmenurecord hmenurecord;
01023     hdlmenu hmainmenu;
01024     short idmainmenu;
01025     
01026     if (getmainmenuvalue (hparam1, &hmainmenu, &idmainmenu)) {
01027         
01028         insertmenu (hmainmenu, idmainmenu + 1);
01029         
01030         drawmenubar ();
01031         
01032         (*v).data.flvalue = true;
01033         
01034         return (true);
01035         }
01036     
01037     flnextparamislast = true;
01038     
01039     if (!getmenuparaminmemory (hparam1, &hmenurecord))
01040         return (false);
01041     
01042     (*v).data.flvalue = meinstallmenubar (hmenurecord);
01043     
01044     return (true);
01045     } /*menuinstallverb*/
01046 
01047 
01048 static boolean menuremoveverb (hdltreenode hparam1, tyvaluerecord *v) {
01049     
01050     hdlmenurecord hmenurecord;
01051     hdlmenu hmainmenu;
01052     short idmainmenu;
01053     
01054     if (getmainmenuvalue (hparam1, &hmainmenu, &idmainmenu)) {
01055         
01056         removemenu (idmainmenu);
01057         
01058         drawmenubar ();
01059         
01060         (*v).data.flvalue = true;
01061         
01062         return (true);
01063         }
01064     
01065     flnextparamislast = true;
01066     
01067     if (!getmenuparaminmemory (hparam1, &hmenurecord))
01068         return (false);
01069     
01070     (*v).data.flvalue = meremovemenubar (hmenurecord);
01071     
01072     return (true);
01073     } /*menuremoveverb*/
01074 
01075 
01076 static boolean menugetscriptverb (hdltreenode hparam1, tyvaluerecord *v) {
01077     
01078     /*
01079     menu/op globals are set.  copy the script attached to the menubar cursor 
01080     into the var param.  set v to true if sucessful, false if no script
01081     */
01082     
01083     hdlhashtable htable;
01084     bigstring bsname;
01085     hdloutlinerecord houtline;
01086     register hdloutlinerecord ho;
01087     boolean fljustloaded;
01088     tyvaluerecord scriptval;
01089     boolean fl;
01090     
01091     flnextparamislast = true;
01092     
01093     if (!getvarparam (hparam1, 1, &htable, bsname))
01094         return (false);
01095     
01096     if (!meloadscriptoutline (menudata, (**outlinedata).hbarcursor, &houtline, &fljustloaded)) /*fatal error*/
01097         return (false);
01098     
01099     ho = houtline; /*copy into register*/
01100     
01101     if (ho == nil) /*no script attached*/
01102         return (true);
01103     
01104     fl = langexternalnewvalue (idscriptprocessor, (Handle) ho, &scriptval);
01105     
01106     if (fljustloaded)
01107         opdisposeoutline (ho, false);
01108     
01109     if (!fl)
01110         return (false);
01111     
01112     if (!langsetsymboltableval (htable, bsname, scriptval)) {
01113         
01114         disposevaluerecord (scriptval, true);
01115         
01116         return (false);
01117         }
01118     
01119     (*v).data.flvalue = true;
01120     
01121     return (true);
01122     } /*menugetscriptverb*/
01123 
01124 
01125 static boolean menugetcommandkeyverb (hdltreenode hparam1, tyvaluerecord *v) {
01126     
01127     /*
01128     menu/op globals are set.  get the command key of the current headline
01129     */
01130     
01131     tymenuiteminfo item;
01132     bigstring bscommandkey;
01133     
01134     if (!langcheckparamcount (hparam1, 0)) /*shouldn't have any parameters*/
01135         return (false);
01136     
01137     setemptystring (bscommandkey);
01138     
01139     if (megetmenuiteminfo ((**outlinedata).hbarcursor, &item))
01140         if (item.cmdkey != chnul)
01141             getcommandkeystring (item.cmdkey, keycommand, bscommandkey);
01142 
01143     return (setstringvalue (bscommandkey, v));
01144     } /*menugetscriptverb*/
01145 
01146 
01147 static boolean menusetcommandkeyverb (hdltreenode hparam1, tyvaluerecord *v) {
01148     
01149     /*
01150     menu/op globals are set.  set the command key of the current headline
01151     */
01152     
01153     bigstring bscommandkey;
01154     
01155     flnextparamislast = true;
01156     
01157     if (!getstringvalue (hparam1, 1, bscommandkey))
01158         return (false);
01159     
01160     mesetcmdkey (lastchar (bscommandkey), keycommand);
01161     
01162     return (setbooleanvalue (true, v));
01163     } /* menusetcommandkeyverb */
01164 
01165 
01166 static boolean detachscript (hdlmenurecord hmenu, hdlheadrecord hnode) {
01167     
01168     /*
01169     menu/op globals are set.  remove the script from the specified node in hmenu
01170     */
01171     
01172     register hdlmenurecord hm = hmenu;
01173     
01174     if ((**hm).scriptnode != hnode) /*simple case, not attached*/
01175         return (true);
01176     
01177     if ((**hm).scriptwindow == nil) /*defensive driving*/
01178         return (false);
01179     
01180     shellpushglobals ((**hm).scriptwindow);
01181     
01182     killundo (); /*must toss undos before they're stranded*/
01183     
01184     shellpopglobals ();
01185     
01186     // meunloadscript (); /*detach the script from the window*/
01187     
01188     (**hm).scriptnode = nil;
01189     
01190     (**hm).scriptoutline = nil;
01191     
01192     return (true);
01193     } /*detachscript*/
01194 
01195 
01196 static boolean attachscript (hdlmenurecord hmenu, hdlheadrecord hnode, hdloutlinerecord hscript) {
01197     
01198     /*
01199     menu/op globals are set.  attach the script to the specified node in hmenu
01200     */
01201     
01202     register hdlmenurecord hm = hmenu;
01203     tymenuiteminfo item;
01204     
01205     megetmenuiteminfo (hnode, &item); /*gets prior cmd key, or clears bytes*/
01206     
01207     mereleaserefconroutine (hnode, true); /*toss existing script, if any*/
01208     
01209     if (hscript == nil)
01210         opemptyrefcon (hnode);
01211     
01212     else {
01213         
01214         (**hscript).fldirty = true; /*force save on this guy's script*/
01215         
01216         item.linkedscript.houtline = hscript;
01217         
01218         item.linkedscript.adrlink = nildbaddress; /*hasn't been allocated yet*/
01219         
01220         mesetmenuiteminfo (hnode, &item); /*attach!*/
01221         }
01222     
01223     if ((**hm).scriptwindow != nil)
01224         mesmashscriptwindow ();
01225     
01226     return (true);
01227     } /*attachscript*/
01228 
01229 
01230 static boolean menusetscriptverb (hdltreenode hparam1, tyvaluerecord *v) {
01231     
01232     /*
01233     menu/op globals are set.  attach the script to the menubar cursor 
01234     
01235     12/22/91 dmb: get previous values in refcon before setting up new script
01236     */
01237     
01238     register hdlmenurecord hm = menudata;
01239     hdlhashtable htable;
01240     bigstring bsname;
01241     tyvaluerecord scriptval;
01242     hdloutlinerecord hcopy;
01243     hdlheadrecord hcursor;
01244     hdlhashnode hnode;
01245     
01246     flnextparamislast = true;
01247     
01248     if (!getvarvalue (hparam1, 1, &htable, bsname, &scriptval, &hnode))
01249         return (false);
01250     
01251     if (!opvaltoscript (scriptval, &hcopy)) /*not a fatal error*/
01252         return (true);
01253     
01254     if (!opcopyoutlinerecord (hcopy, &hcopy))
01255         return (false);
01256     
01257     hcursor = (**outlinedata).hbarcursor;
01258     
01259     detachscript (hm, hcursor);
01260     
01261     attachscript (hm, hcursor, hcopy);
01262     
01263     /*
01264     megetmenuiteminfo (hcursor, &item); /%gets prior cmd key, or clears bytes%/
01265     
01266     mereleaserefconroutine (hcursor, true);
01267     
01268     (**hcopy).fldirty = true; /%force save on this guy's script%/
01269     
01270     item.linkedscript.houtline = hcopy;
01271     
01272     item.linkedscript.adrlink = nildbaddress; /%hasn't been allocated yet%/
01273     
01274     mesetmenuiteminfo (hcursor, &item);
01275     
01276     if ((**hm).scriptwindow != nil)
01277         mesmashscriptwindow ();
01278     */
01279     
01280     (*v).data.flvalue = true;
01281     
01282     return (true);
01283     } /*menusetscriptverb*/
01284 
01285 
01286 typedef struct tyfindinfo {
01287 
01288     ptrstring pfind;
01289 
01290     hdlheadrecord hfound;
01291     } tyfindinfo, *ptrfindinfo;
01292 
01293 
01294 static boolean findheadlinevisit (hdlheadrecord hnode, ptrvoid refcon) {
01295     
01296     ptrfindinfo findinfo = (ptrfindinfo) refcon;
01297     bigstring bs;
01298     
01299     opgetheadstring (hnode, bs);
01300     
01301     if (equalstrings ((*findinfo).pfind, bs)) {
01302         
01303         (*findinfo).hfound = hnode;
01304         
01305         return (false);
01306         }
01307     
01308     return (true); /*keep visiting*/
01309     } /*findheadlinevisit*/
01310 
01311 
01312 static void oprefreshdisplay () {
01313     
01314     if (opdisplayenabled ()) {
01315         
01316         opdirtymeasurements (); //6.0a14 dmb
01317         
01318         opsetctexpanded (outlinedata); //6.0a14 dmb
01319         
01320         opgetscrollbarinfo (true); /*bring scroll position in range*/
01321         
01322         opresetscrollbars ();
01323         
01324         opinvaldisplay ();
01325         }
01326     } /*oprefreshdisplay*/
01327 
01328 
01329 static hdlmenurecord hmenudatasave = nil;
01330 
01331 static boolean mepushmenudata (hdlmenurecord hmenurecord) {
01332     
01333     assert (hmenudatasave == nil);
01334     
01335     hmenudatasave = menudata;
01336     
01337     menudata = hmenurecord;
01338     
01339     return (oppushoutline ((**hmenurecord).menuoutline));
01340     } /*mepushmenudata*/
01341 
01342 
01343 static boolean mepopmenudata (void) {
01344     
01345     menudata = hmenudatasave;
01346     
01347     hmenudatasave = nil;
01348     
01349     return (oppopoutline ());
01350     } /*mepopmenudata*/
01351 
01352 
01353 static boolean getsubmenuvalue (hdltreenode hfirst, short pnum, hdlheadrecord *hsubmenu) {
01354     
01355     register hdloutlinerecord ho;
01356     Handle hpacked;
01357     hdlmenuvariable hv;
01358     boolean fl;
01359     
01360     if (!getmenuparam (hfirst, pnum, &hv))
01361         return (false);
01362     
01363     if (!langexternalmemorypack ((hdlexternalvariable) hv, &hpacked, HNoNode))
01364         return (false);
01365     
01366     fl = langexternalmemoryunpack (hpacked, (hdlexternalvariable *) &hv);
01367     
01368     disposehandle (hpacked);
01369     
01370     if (!fl)
01371         return (false);
01372     
01373     ho = (**(hdlmenurecord) (**hv).variabledata).menuoutline;
01374     
01375     *hsubmenu = (**ho).hsummit;
01376     
01377     (**ho).hsummit = nil;
01378     
01379     menuverbdispose ((hdlexternalvariable) hv, false);
01380     
01381     return (true);
01382     } /*getsubmenuvalue*/
01383 
01384 
01385 static void deletemenunode (hdlheadrecord hnode) {
01386     
01387     /*
01388     9/11/92 dmb: a bit of shared code between addmenucommand & deletemenucommand
01389     
01390     4.0b7 dmb: new implementation, handles marks, doesn't crash for unopened outlines
01391     */
01392     
01393     hdlheadrecord hbarcursor;
01394     boolean fldisplayenabled = opdisplayenabled ();
01395     
01396     if (fldisplayenabled)
01397         opdisabledisplay ();
01398     
01399     hbarcursor = (**outlinedata).hbarcursor;
01400     
01401     opclearallmarks ();
01402     
01403     opmoveto (hnode);
01404     
01405     opdelete ();
01406     
01407     if (opnodeinoutline (hbarcursor))
01408         opmoveto (hbarcursor);
01409     
01410     if (fldisplayenabled) {
01411     
01412         openabledisplay ();
01413         
01414         oprefreshdisplay ();
01415         }
01416     /*
01417     
01418     if ((**hnode).flexpanded && opdisplayenabled ()) {
01419         
01420         opdisabledisplay ();
01421         
01422         hbarcursor = (**outlinedata).hbarcursor;
01423         
01424         opmoveto (hnode);
01425         
01426         opdelete ();
01427         
01428         if (opnodeinoutline (hbarcursor))
01429             opmoveto (hbarcursor);
01430         
01431         openabledisplay ();
01432         
01433         oprefreshdisplay ();
01434         }
01435     else {
01436         
01437         opunlink (hnode);
01438         
01439         opdisposestructure (hnode, true);
01440         
01441     */
01442     } /*deletemenunode*/
01443 
01444 
01445 static boolean addmenucommandverb (hdltreenode hparam1, boolean flsubmenu, tyvaluerecord *v) {
01446     
01447     /*
01448     menu/op globals are _not_ set.  add a new menu item or submenu to a menubar, 
01449     or replace the script of any existing item, depending on the parameters 
01450     specified.
01451     
01452     9/11/92 dmb: when adding a submenu, delete existing item with same name
01453     
01454     9/28/92 dmb: move to the newly-deposited node
01455     
01456     2.1b4 dmb: set outlinesignature of newly-created scripts to 'LAND'
01457     */
01458     
01459     register hdltreenode hp1 = hparam1;
01460     register hdloutlinerecord ho;
01461     register hdlmenurecord hm;
01462     hdlheadrecord hnode;
01463     hdlheadrecord hdelete = nil;
01464     hdlmenurecord hmenurecord;
01465     bigstring bsmenu;
01466     bigstring bsitem;
01467     bigstring bsscript;
01468     tydirection dir;
01469     hdlwindowinfo hinfo;
01470     boolean fl;
01471     hdlheadrecord hsubmenu;
01472     boolean flmainmenu = false;
01473     tyfindinfo findinfo;
01474     
01475     fl = false; /*default return*/
01476     
01477     if (!getmenuparaminmemory (hp1, &hmenurecord)) /*the menu to be changed*/
01478         return (false);
01479     
01480     if (!getstringvalue (hp1, 2, bsmenu)) /*the title of the menu to add to*/
01481         return (false);
01482     
01483     if (flsubmenu) {
01484         
01485         flnextparamislast = true;
01486         
01487         if (!getsubmenuvalue (hp1, 3, &hsubmenu)) /*the submenu to be inserted*/
01488             return (false);
01489         
01490         flmainmenu = isemptystring (bsmenu); /*caller wants this to be a main menu*/
01491         
01492         if (flmainmenu)
01493             opgetheadstring (hsubmenu, bsmenu);
01494         else
01495             opgetheadstring (hsubmenu, bsitem);
01496         }
01497     else {
01498         
01499         if (!getstringvalue (hp1, 3, bsitem)) /*the item in the menu to add, or replace*/
01500             return (false);
01501         
01502         flnextparamislast = true;
01503         
01504         if (!getstringvalue (hp1, 4, bsscript)) /*the text of the script to be set*/
01505             return (false);
01506         }
01507     
01508     /*
01509     set up globals
01510     */
01511     
01512     hm = hmenurecord;
01513     
01514     ho = (**hm).menuoutline;
01515     
01516     if (shellfinddatawindow ((Handle) hm, &hinfo)) {
01517         
01518         shellpushglobals ((**hinfo).macwindow);
01519         
01520         pushundoaction (0); /*no undo*/
01521         }
01522     else
01523         mepushmenudata (hm);
01524     
01525     /*
01526     move headline to menu headline, creating it if necessary
01527     */
01528     
01529     findinfo.pfind = bsmenu;
01530     
01531     hnode = (**ho).hsummit;
01532     
01533     dir = down;
01534     
01535     if (!opsiblingvisiter (hnode, false, &findheadlinevisit, &findinfo)) { /*found the menu*/
01536         
01537         hnode = findinfo.hfound;
01538         
01539         if (flmainmenu) { /*delete it so it can be replaced*/
01540             
01541             hdelete = hnode;
01542             
01543             goto gotposition;
01544             }
01545         }
01546     else {
01547         
01548         hnode = oprepeatedbump (down, longinfinity, hnode, false);
01549         
01550         if (flmainmenu)
01551             goto gotposition;
01552         
01553         if (!opaddheadline (hnode, down, bsmenu, &hnode))
01554             goto exit;
01555         }
01556     
01557     /*
01558     move headline to item headline, creating it if necessary
01559     */
01560     
01561     findinfo.pfind = bsitem;
01562     
01563     if (!oprecursivelyvisit (hnode, 1, &findheadlinevisit, &findinfo)) { /*found the item*/
01564         
01565         hnode = findinfo.hfound;
01566         
01567         if (flsubmenu) /*delete it so it can be replaced*/
01568             hdelete = hnode;
01569         }
01570     else {
01571         
01572         if (ophassubheads (hnode)) {
01573             
01574             hnode = oprepeatedbump (down, longinfinity, (**hnode).headlinkright, false);
01575             
01576             dir = down;
01577             }
01578         else
01579             dir = right;
01580         
01581         if (flsubmenu)
01582             goto gotposition;
01583         
01584         if (!opaddheadline (hnode, dir, bsitem, &hnode))
01585             goto exit;
01586         }
01587     
01588     gotposition:
01589     
01590     if (flsubmenu) {
01591         /*
01592         insert the submenu
01593         */
01594         
01595         opdeposit (hnode, dir, hsubmenu);
01596         
01597         opresetlevels (hsubmenu);
01598         
01599         opfastcollapse (hsubmenu);
01600         
01601         if (hdelete != nil) /*delete old item*/
01602             deletemenunode (hdelete);
01603         
01604         opexpandto (hsubmenu);
01605         }
01606     else { 
01607         /*
01608         set up the script
01609         */
01610     
01611         if (isemptystring (bsscript))
01612             ho = nil;
01613         
01614         else {
01615             hdloutlinerecord houtline;
01616             hdlheadrecord hsummit;
01617             Handle hscript;
01618             
01619             if (!newtexthandle (bsscript, &hscript))
01620                 goto exit;
01621             
01622             if (!newoutlinerecord (&houtline)) {
01623                 
01624                 disposehandle (hscript);
01625                 
01626                 goto exit;
01627                 }
01628             
01629             ho = houtline; /*copy script outline into register*/
01630             
01631             if (!opnewstructure (hscript, &hsummit)) {
01632                 
01633                 opdisposeoutline (ho, false);
01634                 
01635                 goto exit;
01636                 }
01637             
01638             (**ho).outlinesignature = 'LAND';
01639             
01640             (**ho).fontnum = (**hm).defaultscriptfontnum;
01641             
01642             (**ho).fontsize = (**hm).defaultscriptfontsize;
01643             
01644             opsetsummit (ho, hsummit);
01645             
01646             oppushoutline (ho);
01647             
01648             opsetdisplaydefaults (ho);
01649             
01650             oppopoutline ();
01651             }
01652         
01653         /*
01654         connect it
01655         */
01656         
01657         detachscript (hm, hnode);
01658         
01659         attachscript (hm, hnode, ho);
01660         
01661         opexpandto (hnode);
01662         }
01663     
01664     oprefreshdisplay ();
01665     
01666     // now done by oprefreshdisplay - opsetctexpanded (outlinedata); /*re-compute in case we deposited to expanded node*/
01667     
01668     opdirtyoutline (); /*dirty the menubar outline*/
01669     
01670     langexternalsetdirty ((hdlexternalvariable) rootvariable, true); /*make sure changes are flagged*/
01671     
01672     /*
01673     if (htable == menubartable)
01674         langsymbolchanged (htable, bs, true);
01675     */
01676     
01677     fl = true;
01678     
01679     exit:
01680     
01681     if (hinfo != nil)
01682         shellpopglobals ();
01683     else
01684         mepopmenudata ();
01685     
01686     (*v).data.flvalue = fl;
01687     
01688     return (fl);
01689     } /*addmenucommandverb*/
01690 
01691 
01692 static boolean deletemenucommandverb (hdltreenode hparam1, boolean flsubmenu, tyvaluerecord *v) {
01693     
01694     /*
01695     menu/op globals are _not_ set.  delete a menu item or submenu from a 
01696     menubar, depending on the parameters specified.
01697     
01698     5.0a4 dmb: call ophassubheads with menu's outline globals pushed
01699     */
01700     
01701     register hdltreenode hp1 = hparam1;
01702     register hdloutlinerecord ho;
01703     register hdlmenurecord hm;
01704     hdlheadrecord hnode;
01705     hdlmenurecord hmenurecord;
01706     bigstring bsmenu;
01707     bigstring bsitem;
01708     hdlwindowinfo hinfo;
01709     tyfindinfo findinfo;
01710     boolean flchanged;
01711     
01712     if (!getmenuparaminmemory (hparam1, &hmenurecord))
01713         return (false);
01714     
01715     if (flsubmenu)
01716         flnextparamislast = true;
01717     
01718     if (!getstringvalue (hp1, 2, bsmenu))
01719         return (false);
01720     
01721     if (!flsubmenu) {
01722         
01723         flnextparamislast = true;
01724         
01725         if (!getstringvalue (hp1, 3, bsitem))
01726             return (false);
01727         }
01728     
01729     /*
01730     move headline to menu headline
01731     */
01732     
01733     hm = hmenurecord;
01734     
01735     ho = (**hm).menuoutline;
01736     
01737     findinfo.pfind = bsmenu;
01738     
01739     hnode = (**ho).hsummit;
01740     
01741     if (opsiblingvisiter (hnode, false, &findheadlinevisit, &findinfo)) /*didn't find the menu*/
01742         return (true);
01743     
01744     hnode = findinfo.hfound;
01745     
01746     /*
01747     move headline to item headline
01748     */
01749     
01750     if (!flsubmenu) {
01751         
01752         if (!isemptystring (bsitem)) {
01753             
01754             findinfo.pfind = bsitem;
01755             
01756             if (oprecursivelyvisit (hnode, 1, &findheadlinevisit, &findinfo)) /*didn't find the item*/
01757                 return (true);
01758             
01759             hnode = findinfo.hfound;
01760             }
01761         }
01762     
01763     /*
01764     delete the menu item
01765     */
01766     
01767     if (shellfinddatawindow ((Handle) hm, &hinfo)) {
01768         
01769         shellpushglobals ((**hinfo).macwindow);
01770         
01771         pushundoaction (0); /*no undo*/
01772         }
01773     else
01774         mepushmenudata (hm);
01775     
01776     if (ophassubheads (hnode) && !flsubmenu) /*it's not a single command*/
01777         flchanged = false;
01778     
01779     else {
01780         
01781         (**ho).fldirty = true; /*dirty the menubar outline*/
01782         
01783         deletemenunode (hnode);
01784         
01785         flchanged = true;
01786         }
01787     
01788     if (hinfo != nil)
01789         shellpopglobals ();
01790     else
01791         mepopmenudata ();
01792     
01793     if (flchanged)
01794         langexternalsetdirty ((hdlexternalvariable) rootvariable, true); /*make sure changes are flagged*/
01795     
01796     /*
01797     if (htable == menubartable)
01798         langsymbolchanged (htable, bs, true);
01799     */
01800     
01801     (*v).data.flvalue = flchanged;
01802     
01803     return (true);
01804     } /*deletemenucommandverb*/
01805 
01806 
01807 static boolean menufunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
01808     
01809     /*
01810     6/1/93 dmb: when vreturned is nil, return whether or not verb token must 
01811     be run in the Frontier process
01812     */
01813     
01814     register tyvaluerecord *v = vreturned;
01815     register boolean fl;
01816     WindowPtr targetwindow;
01817     
01818     if (v == nil) { /*need Frontier process?*/
01819         
01820         switch (token) {
01821             
01822             case isinstalledfunc:
01823             case getscriptfunc:
01824             case setscriptfunc:
01825                 return (false);
01826             
01827             default:
01828                 return (true);
01829             }
01830         }
01831     
01832     errornum = 0;
01833     
01834     setbooleanvalue (false, v); /*by default, menu functions return false*/
01835     
01836     switch (token) {/*these verbs don't need any special globals pushed*/
01837         
01838         case buildmenubarfunc:
01839             if (!langcheckparamcount (hparam1, 0)) /*shouldn't have any parameters*/
01840                 return (false);
01841             
01842             (*v).data.flvalue = menubuildverb ();
01843             
01844             return (true);
01845         
01846         case clearmenubarfunc:
01847             if (!langcheckparamcount (hparam1, 0))
01848                 return (false);
01849             
01850             (*v).data.flvalue = menuclearverb ();
01851             
01852             return (true);
01853         
01854         case isinstalledfunc:
01855             if (!menuisinstalledverb (hparam1, v))
01856                 goto error;
01857             
01858             return (true);
01859         
01860         case installfunc:
01861             if (!menuinstallverb (hparam1, v))
01862                 goto error;
01863             
01864             return (true);
01865         
01866         case removefunc:
01867             if (!menuremoveverb (hparam1, v))
01868                 goto error;
01869             
01870             return (true);
01871         
01872         case addmenucommandfunc:
01873             if (!addmenucommandverb (hparam1, false, v))
01874                 goto error;
01875             
01876             return (true);
01877         
01878         case deletemenucommandfunc:
01879             if (!deletemenucommandverb (hparam1, false, v))
01880                 goto error;
01881             
01882             return (true);
01883         
01884         case addsubmenufunc:
01885             if (!addmenucommandverb (hparam1, true, v))
01886                 goto error;
01887             
01888             return (true);
01889         
01890         case deletesubmenufunc:
01891             if (!deletemenucommandverb (hparam1, true, v))
01892                 goto error;
01893             
01894             return (true);
01895         } /*switch*/
01896     
01897     /*be sure there's a menu window in front -- set menueditor.c globals*/
01898     
01899     if (!langfindtargetwindow (idmenuprocessor, &targetwindow)) { /*all other verbs require an outline window in front*/
01900         
01901         errornum = nomenuerror;
01902         
01903         goto error;
01904         }
01905     
01906     shellpushglobals (targetwindow); /*following verbs assume that a menubar is pushed*/
01907     
01908     (*shellglobals.gettargetdataroutine) (idmenuprocessor); /*set op globals*/
01909     
01910     mecheckglobals (); /*copy handles from menudata to globals*/
01911     
01912     fl = false; /*default return value*/
01913     
01914     switch (token) { /*these verbs assume that the menueditor globals are set*/
01915         
01916         case zoomscriptfunc:
01917             if (!langcheckparamcount (hparam1, 0))
01918                 return (false);
01919             
01920             (*v).data.flvalue = mezoomscriptwindow ();
01921             
01922             fl = true;
01923             
01924             break;
01925             
01926         /*
01927         case findscriptfunc: {
01928             bigstring bs;
01929             boolean flinscript;
01930             
01931             flnextparamislast = true;
01932             
01933             if (!getstringvalue (hparam1, 1, searchparams.bsfind))
01934                 break;
01935             
01936             (*v).data.flvalue = mesearchoutline (false, searchparams.flwraparound, &flinscript);
01937             
01938             mepostcursormove ();
01939             
01940             fl = true;
01941             
01942             break;
01943             }
01944         
01945         case findfunc: {
01946             bigstring bs;
01947             
01948             flnextparamislast = true;
01949             
01950             if (!getstringvalue (hparam1, 1, searchparams.bsfind))
01951                 break;
01952             
01953             (*v).data.flvalue = opflatfind (false, true);
01954             
01955             mepostcursormove ();
01956             
01957             fl = true;
01958             
01959             break;
01960             }
01961         */
01962         
01963         case getscriptfunc:
01964             fl = menugetscriptverb (hparam1, v);
01965             
01966             break;
01967         
01968         case setscriptfunc:
01969             fl = menusetscriptverb (hparam1, v);
01970             
01971             break;
01972         
01973         case getcommandkeyfunc:
01974             fl = menugetcommandkeyverb (hparam1, v);
01975             
01976             break;
01977             
01978         case setcommandkeyfunc:
01979             fl = menusetcommandkeyverb (hparam1, v);
01980             
01981             break;
01982         } /*switch*/
01983     
01984     shellpopglobals ();
01985     
01986     return (fl);
01987     
01988     error:
01989     
01990     if (errornum != 0) /*get error string*/
01991         getstringlist (menuerrorlist, errornum, bserror);
01992     
01993     return (false);
01994     } /*menufunctionvalue*/
01995 
01996 
01997 static boolean menuinitverbs (void) {
01998     
01999     return (loadfunctionprocessor (idmenuverbs, &menufunctionvalue));
02000     } /*menuinitverbs*/
02001 
02002 
02003 static boolean menuverbkeystroke (void) {
02004     
02005     /*
02006     5.0b18 dmb: let langexternalsurfacekey decide what keys it needs
02007     */
02008 
02009     // if ((keyboardstatus.chkb == chenter) && (keyboardstatus.flcmdkey) && (keyboardstatus.flshiftkey)) {
02010         
02011     if (langexternalsurfacekey ((hdlexternalvariable) (**menudata).menurefcon))
02012         return (true);
02013     
02014     return (mekeystroke ());
02015     } /*menuverbkeystroke*/
02016 
02017 
02018 static boolean menuverbtitleclick (Point pt) {
02019     
02020     return (langexternaltitleclick (pt, (hdlexternalvariable) (**menudata).menurefcon));
02021     } /*menuverbtitleclick*/
02022 
02023 
02024 static boolean menuverbsetfont (void) {
02025     
02026     register short fontnum = (**menuwindowinfo).selectioninfo.fontnum;
02027     
02028     (**menudata).defaultscriptfontnum = fontnum; /*side-effect*/
02029     
02030     (**menudata).defaultscriptfontsize = (**menuwindowinfo).selectioninfo.fontsize;
02031     
02032     mecheckglobals ();
02033     
02034     return (opsetfont (fontnum));
02035     } /*menuverbsetfont*/
02036     
02037     
02038 static boolean menuverbsetsize (void) {
02039     
02040     register short fontsize = (**menuwindowinfo).selectioninfo.fontsize;
02041     
02042     (**menudata).defaultscriptfontsize = fontsize; /*side-effect*/
02043     
02044     (**menudata).defaultscriptfontnum = (**menuwindowinfo).selectioninfo.fontnum;
02045     
02046     mecheckglobals ();
02047     
02048     return (opsetsize (fontsize));
02049     } /*menuverbsetsize*/
02050     
02051 
02052 static boolean menuverbsetselectioninfo (void) {
02053     
02054     mecheckglobals ();
02055     
02056     return (opsetselectioninfo ());
02057     } /*menuverbsetselectioninfo*/
02058 
02059 
02060 static boolean menuverbrunscript (void) {
02061     
02062     mecheckglobals ();
02063     
02064     return (meuserselected ((**outlinedata).hbarcursor));
02065     } /*menuverbrunscript*/
02066 
02067 
02068 static boolean menuverbgetvariable (hdlexternalvariable *hvariable) {
02069     
02070     if (menudata == nil)
02071         return (false);
02072     
02073     *hvariable = (hdlexternalvariable) (**menudata).menurefcon;
02074     
02075     return (true);
02076     } /*menuverbgetvariable*/
02077 
02078 
02079 static boolean menuverbgettargetdata (short id) {
02080     
02081     /*
02082     a verb is about to be executed that acts on the indicated external type, or 
02083     on any shell window if id == -1.
02084     
02085     return true if we can handle verbs of that type and are able to set the 
02086     relevant globals
02087     */
02088     
02089     mesetglobals ();
02090     
02091     switch (id) {
02092         
02093         case -1:
02094             return (true);
02095         
02096         case idoutlineprocessor:
02097             return (true);
02098         
02099         case idwordprocessor:
02100             return (opeditsetglobals ());
02101             
02102         case idmenuprocessor: /*DW 6/19/91*/
02103             return (true);
02104         
02105         default:
02106             return (false);
02107         }
02108     } /*menuverbgettargetdata*/
02109 
02110 
02111 static boolean menuchildclose (WindowPtr w) {
02112     
02113     /*
02114     1/2/91 dmb: no longer call mescriptwindowclosed from here; scriptclose 
02115     will do it
02116     
02117     9/24/91 dmb: pass through return value from child
02118 
02119     5.0b11 dmb: back to the original logic; call mescriptwindowclosed
02120     from here, after we've popped the script's globals
02121     */
02122     
02123     boolean fl;
02124     
02125     assert (w == (**menudata).scriptwindow);
02126     
02127     shellpushglobals (w);
02128     
02129     fl = (*shellglobals.closeroutine) (); /*scripts.c get a shot at closing*/
02130     
02131     shellpopglobals ();
02132     
02133     if (fl)
02134         mescriptwindowclosed ();
02135     
02136     return (fl);
02137     } /*menuchildclose*/
02138     
02139     
02140 static boolean menucheckwindowrect (void) {
02141     
02142     /*
02143     return true if the menuwindowrect field of menudata changed.
02144     */
02145     
02146     register hdlmenurecord hm = menudata;
02147     Rect r;
02148     
02149     shellgetglobalwindowrect (menuwindowinfo, &r);
02150     
02151     if (equalrects (r, (**hm).menuwindowrect))
02152         return (false);
02153         
02154     (**hm).menuwindowrect = r;
02155     
02156     (**hm).fldirty = true;
02157     
02158     return (true);
02159     } /*menucheckwindowrect*/
02160 
02161 
02162 static boolean menuverbclose (void) {
02163     
02164     /*
02165     5.0d19 dmb: set hm's flwindowopen to false too, not just op's
02166 
02167     5.0b15 dmb: if we're not installed, remove us in case we were active
02168     */
02169     
02170     register hdlmenurecord hm = menudata;
02171     
02172     if (hm == nil) //already closed & disposed?
02173         return (true);
02174     
02175     killundo (); /*must toss undos before they're stranded*/
02176     
02177     shellclosewindow ((**hm).scriptwindow); 
02178     
02179     menucheckwindowrect ();
02180     
02181     (**hm).flactive = false;
02182     
02183     if (!(**hm).flinstalled) { /*not an installed menu; remove from menubar & dispose*/
02184         
02185         meremovemenubar (hm); //5.0b15
02186         
02187         medisposemenubar ((**hm).hmenustack);
02188         
02189         (**hm).hmenustack = nil;
02190         }
02191     
02192     mecheckglobals ();
02193     
02194     (**outlinedata).flwindowopen = false;
02195     
02196     (**hm).flwindowopen = false; /*5.0d19*/
02197     
02198     opcloseoutline ();
02199     
02200     return (true);
02201     } /*menuverbclose*/
02202 
02203 
02204 static boolean mebeginprint (void) {
02205     
02206     opbeginprint ();
02207     
02208     return (true);
02209     } /*mebeginprint*/
02210 
02211 
02212 static boolean meendprint (void) {
02213     
02214     opsetdisplaydefaults (outlinedata); //need to reset lineheights before next call
02215     
02216     meresize ();
02217     
02218     return (true);
02219     } /*meendprint*/
02220 
02221 
02222 boolean menustart (void) {
02223     
02224     /*
02225     set up callback routines record, and link our data into the shell's 
02226     data structure.
02227     */
02228     
02229     ptrcallbacks menucallbacks;
02230     register ptrcallbacks cb;
02231     
02232     assert (sizeof (tyexternalvariable) == sizeof (tymenuvariable));
02233     
02234     menuinitverbs ();
02235     
02236     meinit ();
02237     
02238     shellpushscraphook (&mescraphook);
02239     
02240     shellnewcallbacks (&menucallbacks);
02241     
02242     cb = menucallbacks; /*copy into register*/
02243     
02244     loadconfigresource (idmenueditorconfig, &(*cb).config);
02245         
02246     (*cb).configresnum = idmenueditorconfig;
02247         
02248     (*cb).windowholder = &menuwindow;
02249     
02250     (*cb).dataholder = (Handle *) &menudata;
02251     
02252     (*cb).infoholder = &menuwindowinfo;
02253     
02254     (*cb).setglobalsroutine = &mesetglobals;
02255     
02256     (*cb).pushroutine = &oppushglobals;
02257 
02258     (*cb).poproutine = &oppopglobals;
02259     
02260 #ifdef version42orgreater
02261     
02262     (*cb).disposerecordroutine = ccdisposefilerecord;
02263     
02264     (*cb).saveroutine = ccsavespecialfile;
02265 
02266 #endif
02267     
02268     (*cb).updateroutine = &meupdate;
02269     
02270     (*cb).activateroutine = &meactivate;
02271     
02272     (*cb).getcontentsizeroutine = &megetcontentsize;
02273     
02274     (*cb).resetrectsroutine = &meresetwindowrects;
02275     
02276     (*cb).resizeroutine = &meresize;
02277     
02278     (*cb).scrollroutine = &mescroll;
02279     
02280     (*cb).setscrollbarroutine = &megetscrollbarinfo;
02281     
02282     (*cb).mouseroutine = &memousedown;
02283 
02284     (*cb).rmouseroutine = &oprmousedown; /*7.0b13 PBS: right-click in menus*/
02285     
02286     (*cb).keystrokeroutine = &menuverbkeystroke;
02287     
02288     (*cb).titleclickroutine = &menuverbtitleclick;
02289     
02290     (*cb).cmdkeyfilterroutine = &mecmdkeyfilter;
02291     
02292     (*cb).cutroutine = &mecut;
02293     
02294     (*cb).copyroutine = &mecopy;
02295     
02296     (*cb).pasteroutine = &mepaste;
02297     
02298     (*cb).clearroutine = &meclear;
02299     
02300     (*cb).selectallroutine = &meselectall;
02301     
02302     (*cb).closeroutine = &menuverbclose;
02303     
02304     (*cb).getundoglobalsroutine = &megetundoglobals;
02305     
02306     (*cb).setundoglobalsroutine = &mesetundoglobals;
02307     
02308     (*cb).childcloseroutine = &menuchildclose;
02309     
02310     (*cb).idleroutine = &meidle;
02311     
02312     (*cb).adjustcursorroutine = &meadjustcursor;
02313     
02314     (*cb).gettargetdataroutine = &menuverbgettargetdata;
02315     
02316     (*cb).getvariableroutine = (shellgetvariablecallback) &menuverbgetvariable;
02317     
02318     (*cb).settextmoderoutine = &opsettextmode;
02319     
02320     (*cb).fontroutine = &menuverbsetfont;
02321     
02322     (*cb).sizeroutine = &menuverbsetsize;
02323     
02324     (*cb).setselectioninforoutine = &menuverbsetselectioninfo;
02325     
02326     (*cb).searchroutine = &menuverbsearch;
02327     
02328     (*cb).executeroutine = &menuverbrunscript;
02329     
02330     (*cb).setprintinfoproutine = &mesetprintinfo;
02331     
02332     (*cb).beginprintroutine = &mebeginprint;
02333     
02334     (*cb).endprintroutine = &meendprint;
02335     
02336     (*cb).printroutine = &meprint;
02337     
02338     return (true);
02339     } /*menustart*/
02340 
02341 
02342 
02343 

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