menueditor.c

Go to the documentation of this file.
00001 
00002 /*  $Id: menueditor.c 1208 2006-04-05 23:51:45Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "mac.h"
00032 #include "memory.h"
00033 #include "strings.h"
00034 #include "bitmaps.h"
00035 #include "quickdraw.h"
00036 #include "font.h"
00037 #include "smallicon.h"
00038 #include "scrollbar.h"
00039 #include "icon.h"
00040 #include "kb.h"
00041 #include "ops.h"
00042 #include "cursor.h"
00043 #include "menu.h"
00044 #include "popup.h"
00045 #include "dialogs.h"
00046 #include "frontierwindows.h"
00047 #include "windowlayout.h"
00048 #include "zoom.h"
00049 #include "db.h"
00050 #include "tablestructure.h"
00051 #include "shell.h"
00052 #include "shellprivate.h"
00053 #include "shellundo.h"
00054 #include "shell.rsrc.h"
00055 #include "op.h"
00056 #include "opinternal.h"
00057 #include "scripts.h"
00058 #include "menueditor.h"
00059 #include "menuinternal.h"
00060 #include "cancoon.h"
00061 #include "langexternal.h"
00062 
00063 
00064 
00065 
00066 hdlmenurecord menudata;
00067 
00068 WindowPtr menuwindow; 
00069 
00070 hdlwindowinfo menuwindowinfo; 
00071 
00072 
00073 #define sizecmdkeyarray 256 /*room for 256 handles*/
00074 
00075 #define buttonfont geneva
00076 #define buttonsize 9
00077 #define buttonstyle 0
00078 
00079 #define roundrectsize 10
00080 
00081 
00082 
00083 #ifdef fldebug
00084 
00085 void mecheckglobals (void) {
00086     
00087     assert (menudata != nil);
00088     
00089     assert (outlinedata == (**menudata).menuoutline); 
00090     
00091     /*
00092     assert (outlinewindow == menuwindow);
00093     
00094     assert (outlinewindowinfo == menuwindowinfo);
00095     */
00096     } /*mecheckglobals*/
00097 
00098 #endif
00099 
00100 boolean mesetglobals (void) {
00101     
00102     if (menudata == nil) {
00103         
00104         opsetoutline (nil);
00105 
00106         return (false);
00107         }
00108 
00109     opsetoutline ((**menudata).menuoutline);
00110     
00111     outlinewindow = menuwindow;
00112     
00113     outlinewindowinfo = menuwindowinfo;
00114     
00115     if (outlinedata != nil)
00116         opeditsetglobals ();
00117     
00118     return (true);
00119     } /*mesetglobals*/
00120 
00121 
00122 hdldatabaserecord megetdatabase (hdlmenurecord hm) {
00123     
00124     return ((**(hdlexternalvariable) (**hm).menurefcon).hdatabase);
00125     } /*megetdatabase*/
00126 
00127     
00128 static void megetcursornode (hdlmenurecord hm, hdlheadrecord *hcursor) {
00129 #pragma unused (hm)
00130 
00131     assert (menudata != nil);
00132     
00133     *hcursor = (**(**menudata).menuoutline).hbarcursor;
00134     } /*megetcursornode*/
00135 
00136 
00137 boolean mescroll (tydirection dir, boolean flpage, long amount) {   
00138     
00139     mecheckglobals ();
00140     
00141     return (opscroll (dir, flpage, amount));
00142     } /*mescroll*/
00143     
00144     
00145 void megetscrollbarinfo (void) {
00146     
00147     mecheckglobals ();
00148     
00149     opresetscrollbars ();
00150     } /*megetscrollbarinfo*/
00151 
00152 
00153 static boolean mesetscrollbarsroutine (void) {
00154 
00155     register ptrwindowinfo pw = *menuwindowinfo;
00156     register ptroutlinerecord po = *outlinedata;
00157     
00158     (*pw).vertscrollinfo = (*po).vertscrollinfo; /*copy from outline record to window record*/
00159     
00160     (*pw).fldirtyscrollbars = true; /*force a refresh of scrollbars by the shell*/
00161     
00162     return (true);
00163     } /*mesetscrollbarsroutine*/
00164 
00165 
00166 /*
00167 static boolean medeactivateoutline (void) {
00168     
00169     mecheckglobals ();
00170     
00171     if ((**outlinedata).flactive)
00172         opactivate (false);
00173     
00174     return (true);
00175     } /%medeactivateoutline%/
00176 */
00177 
00178 static void meactivateoutline (void) {
00179     
00180     (**menudata).menuactiveitem = menuoutlineitem;
00181     
00182 
00183     mecheckglobals ();
00184     
00185     if (!(**outlinedata).flactive) {
00186         //WriteToConsole("Delta");
00187         opactivate (true);
00188 
00189     }
00190     } /*meactivateoutline*/
00191 
00192 
00193 static boolean megetscriptaddress (hdlheadrecord hnode, dbaddress *address) {
00194     
00195     tymenuiteminfo item;
00196     
00197     megetmenuiteminfo (hnode, &item); /*will clear item on failure*/
00198     
00199     *address = item.linkedscript.adrlink;
00200     
00201     return (true);
00202     } /*megetscriptaddress*/
00203 
00204 
00205 static boolean megetscriptoutline (hdlheadrecord hnode, hdloutlinerecord *hscript) {
00206     
00207     tymenuiteminfo item;
00208     
00209     megetmenuiteminfo (hnode, &item); /*will clear item on failure*/
00210     
00211     *hscript = item.linkedscript.houtline;
00212     
00213     return (true);
00214     } /*megetscriptoutline*/
00215 
00216 
00217 boolean mesetscriptoutline (hdlheadrecord hnode, hdloutlinerecord hscript) {
00218     
00219     tymenuiteminfo item;
00220     
00221     megetmenuiteminfo (hnode, &item);
00222     
00223     item.linkedscript.houtline = hscript;
00224     
00225     return (mesetmenuiteminfo (hnode, &item));
00226     } /*mesetscriptoutline*/
00227 
00228 
00229 static void medrawseparatorline (hdlheadrecord hnode, const Rect *rtext, boolean flselected, boolean flinverted) {
00230     
00231     /*
00232     7/10/92 dmb: don't set displaypixels to maxlevelwidth; doing so 
00233     ensures that all future maxlevelwidths can't decrease
00234     
00235     7.0b59 PBS: select the icon also.
00236     */
00237     
00238     register hdlheadrecord hn = hnode;
00239     register short h, v;
00240     register short pixels;
00241     hdloutlinerecord ho = outlinedata;
00242 
00243     v = ((*rtext).top + (*rtext).bottom) / 2;
00244     
00245     h = (*rtext).left;
00246     
00247     pushpen ();
00248     
00249     setgraypen ();
00250     
00251     movepento (h, v);
00252     
00253     pixels = opmaxlevelwidth (hn);
00254     
00255     /*
00256     (**hn).displaypixels = pixels;
00257     */
00258     
00259     h += pixels;
00260     
00261     pendrawline (h, v);
00262     
00263     poppen ();
00264     
00265     if (flselected) {
00266         
00267         Rect rframe = *rtext;
00268         
00269         //rframe.left -= 2; /*leave 2 extra pixels for prettier bar cursor*/
00270         
00271         rframe.right = h + 2; /*leave 2 extra pixels for prettier bar cursor*/
00272         
00273         rframe.left -= (**ho).iconwidth + (**ho).pixelsaftericon + texthorizinset; /*7.0b59 PBS: select icon.*/
00274 
00275         if (flinverted)
00276             invertrect (rframe);
00277         else
00278             grayframerect (rframe);
00279         }
00280     } /*medrawseparatorline*/
00281     
00282 
00283 static boolean medrawlineroutine (hdlheadrecord hnode, const Rect *textrect, boolean flselected, boolean flinverted) {
00284     
00285     /*
00286     a bottleneck routine that draws a line in the outline structure.  if it is one
00287     of the lines we're interested in, we draw it and return.  otherwise we call the
00288     standard line drawing routine implemented in op.c.
00289     
00290     the design of this callback structure follows the design of the QuickDraw 
00291     bottleneck routines.
00292     */
00293     
00294     bigstring bsnode;
00295     
00296     opgetheadstring (hnode, bsnode);
00297     
00298     if (stringlength (bsnode) >= 1) { /*length of string is at least 1*/
00299         
00300         if (getstringcharacter (bsnode, 0) == (byte) '-') { /*first character is a minus*/
00301             
00302             medrawseparatorline (hnode, textrect, flselected, flinverted);
00303             
00304             return (true);
00305             }
00306         }
00307     
00308     return (opdefaultdrawtext (hnode, textrect, flselected, flinverted));
00309     } /*medrawlineroutine*/
00310 
00311 
00312 void megetoutlinerect (Rect *r) {
00313     
00314     *r = (**menudata).menuoutlinerect;
00315     } /*megetoutlinerect*/
00316     
00317     
00318 static boolean meclearhandlevisit (hdlheadrecord hnode, ptrvoid refcon) {
00319 #pragma unused (refcon)
00320 
00321     tymenuiteminfo item;
00322     
00323     if (megetmenuiteminfo (hnode, &item)) {
00324         
00325         item.linkedscript.houtline = nil;
00326         
00327         mesetmenuiteminfo (hnode, &item);
00328         }
00329         
00330     return (true);
00331     } /*meclearhandlevisit*/
00332     
00333     
00334 static void meclearhandles (hdloutlinerecord ho) {
00335     
00336     /*
00337     after a structure is unpacked, we have to visit all the nodes and clear
00338     any handles linked in the refcon structure, since they are no longer
00339     valid.  we don't do this on saving because the handles are still in use.
00340     */
00341     
00342     opsiblingvisiter ((**ho).hsummit, false, &meclearhandlevisit, nil);
00343     } /*meclearhandles*/
00344 
00345 
00346 static boolean mesomethingdirtyvisit (hdlheadrecord hnode, ptrvoid refcon) {
00347 #pragma unused (refcon)
00348 
00349     register hdlheadrecord h = hnode;
00350     register hdloutlinerecord ho;
00351     tymenuiteminfo item;
00352     
00353     if (!megetmenuiteminfo (h, &item)) /*nothing linked, keep visiting*/
00354         return (true);
00355     
00356     ho = item.linkedscript.houtline; /*copy into register*/
00357     
00358     if (ho == nil)
00359         return (true);
00360     
00361     if ((**ho).fldirty)
00362         return (false); /*stop traversal*/
00363     
00364     return (true);
00365     } /*mesomethingdirtyvisit*/
00366 
00367 
00368 boolean mesomethingdirty (hdlmenurecord hmenurecord) {
00369     
00370     /*
00371     we want to know if something is dirty, either the menurecord itself or
00372     something linked into it.  someday, we may want to make this more efficient
00373     by having a system of callback routines, that percolate dirty bits up
00374     the ownership hierarchy.
00375     */
00376     
00377     register hdlmenurecord hm = hmenurecord;
00378     register hdloutlinerecord ho;
00379     hdlheadrecord hsummit;
00380     boolean flsomethingdirty;
00381     
00382     if ((**hm).fldirty)
00383         return (true);
00384         
00385     ho = (**hm).menuoutline;
00386     
00387     if ((**ho).fldirty)
00388         return (true);
00389         
00390     oppushoutline (ho);
00391     
00392     opoutermostsummit (&hsummit);
00393     
00394     flsomethingdirty = !opsiblingvisiter (hsummit, false, &mesomethingdirtyvisit, nil);
00395     
00396     oppopoutline ();
00397     
00398     return (flsomethingdirty);
00399     } /*mesomethingdirty*/
00400 
00401 
00402 boolean meloadoutline (dbaddress adr, hdloutlinerecord *houtline) {
00403     
00404     /*
00405     load the outline stored at database address adr.  if adr is nil, create a 
00406     new empty outline structure.  return false if something didn't work.
00407     
00408     5/21/92 dmb: fixed error handling when dbrefhandle fails.  (used to leave 
00409     outline pushed.)
00410     */
00411     
00412     register boolean fl;
00413     register hdloutlinerecord ho;
00414     Handle hpackedoutline;
00415     Rect r;
00416     long ixload = 0;
00417     
00418     *houtline = nil; /*default return*/
00419     
00420     oppushoutline (nil); /*preserve global*/
00421     
00422     if (adr == nildbaddress) { /*new structure is called for*/
00423         
00424         megetoutlinerect (&r);
00425         
00426         fl = opnewrecord (r, houtline);
00427         }
00428     else {
00429         fl = dbrefhandle (adr, &hpackedoutline);
00430         
00431         if (fl) {
00432             
00433             fl = opunpack (hpackedoutline, &ixload, houtline);
00434             
00435             disposehandle (hpackedoutline);
00436             }
00437         }
00438     
00439     ho = *houtline;
00440     
00441     oppopoutline (); /*restore global*/
00442     
00443     if (!fl)
00444         return (false);
00445     
00446     opvalidate (ho);
00447     
00448     (**ho).setscrollbarsroutine = &mesetscrollbarsroutine;
00449     
00450     (**ho).drawlinecallback = &medrawlineroutine;
00451     
00452     meclearhandles (ho);
00453     
00454     /*
00455     6/21/90 DW: this can be a problem if there's no outline window open.
00456     none of the callers seems to depend on these two calls.
00457     
00458     megetoutlinerect (&(**ho).outlinerect);
00459     
00460     opgetdisplayinfo ();
00461     */
00462     
00463     *houtline = ho;
00464         
00465     return (fl);
00466     } /*meloadoutline*/
00467 
00468 
00469 boolean mesaveoutline (hdloutlinerecord ho, dbaddress *adr) {
00470     
00471     /*
00472     save an outline in the database, and return the address of the database
00473     memory that was allocated.
00474     */
00475     
00476     register boolean fl;
00477     Handle hpackedoutline;
00478     
00479     hpackedoutline = nil; /*allocate a new handle for packing*/
00480     
00481     if (!oppackoutline (ho, &hpackedoutline))
00482         return (false);
00483     
00484     fl = dbsavehandle (hpackedoutline, adr);
00485     
00486     disposehandle (hpackedoutline);
00487     
00488     if (!fl)
00489         return (false);
00490     
00491     if (!fldatabasesaveas)
00492         (**ho).fldirty = false;
00493     
00494     return (true);
00495     } /*mesaveoutline*/
00496 
00497 
00498 static boolean mescriptfontchangeroutine (void) {
00499     
00500     /*
00501     called when the font of a script window has been changed.  we implement a 
00502     side-effect -- we save the current outline font and size as the default
00503     font and size for all new script windows.
00504     
00505     12/3/91 dmb: move outlinedata into local before pushing parent globals
00506     
00507     5.0.2b16 dmb: call opseteditbufferrect
00508     */
00509     
00510     register hdloutlinerecord ho = outlinedata; /*save off before pushing new globals*/
00511     
00512     shellpushparentglobals (); /*script window is in front, parent is a menu window*/
00513     
00514     assert (menudata != nil);
00515     
00516     (**menudata).defaultscriptfontnum = (**ho).fontnum;
00517     
00518     (**menudata).defaultscriptfontsize = (**ho).fontsize;
00519     
00520     shellpopglobals ();
00521     
00522     oppostfontchange ();
00523     
00524     return (true);
00525     } /*mescriptfontchangeroutine*/
00526 
00527 
00528 boolean meloadscriptoutline (hdlmenurecord hm, hdlheadrecord hnode, hdloutlinerecord *houtline, boolean *fljustloaded) {
00529     
00530     /*
00531     load in the outline linked to the indicated headrecord, return false if there was
00532     an error loading the outline.
00533     
00534     if *houtline returns as nil, and the function returns true, there's no script linked
00535     in -- if you're zooming a window you want to create a new linked script.
00536     
00537     12/13/90 dmb: added fljustloaded parameter for safe unloading.
00538 
00539     7.0b26 PBS: menubar scripts get fat headlines. Horizontal scrolling is disabled.
00540     */
00541     
00542     register boolean fl;
00543     dbaddress adr;
00544     Handle hpackedoutline;
00545     long ixload = 0;
00546     
00547     *fljustloaded = false;
00548     
00549     megetscriptoutline (hnode, houtline); /*is there a dirty copy already in memory?*/
00550     
00551     if (*houtline != nil) { /*a dirty script is already linked in*/
00552     
00553         opsetdisplaydefaults (*houtline);
00554         
00555         return (true);
00556         }
00557     
00558     megetscriptaddress (hnode, &adr);
00559     
00560     if (adr == nildbaddress) {
00561         
00562         *houtline = nil; /*no linked script*/
00563         
00564         return (true);
00565         }
00566     
00567     dbpushdatabase (megetdatabase (hm));
00568     
00569     fl = dbrefhandle (adr, &hpackedoutline);
00570     
00571     dbpopdatabase ();
00572 
00573     if (!fl) /*error loading from database*/
00574         return (false);
00575 
00576     
00577     fl = opunpack (hpackedoutline, &ixload, houtline);
00578 
00579     (***houtline).flfatheadlines = true; /*7.0b26 PBS: fat headlines in menubar scripts.*/
00580 
00581     (***houtline).flhorizscrolldisabled = true; /*7.0b26 PBS: horizontal scrolling is disabled.*/
00582     
00583     disposehandle (hpackedoutline);
00584     
00585     if (fl) {
00586     
00587         opsetdisplaydefaults (*houtline);
00588         
00589         *fljustloaded = true;
00590         }
00591     
00592     return (fl);
00593     } /*meloadscriptoutline*/
00594 
00595 
00596 static boolean meloadscript (hdlmenurecord hm, Rect rscript, hdloutlinerecord *houtline) {
00597     
00598     /*
00599     1/2/91 dmb: stick the cursor's hdlheadrecord into the script outline's 
00600     refcon.  this allows the script debugger to use mescripterrorroutine 
00601     (meprograms.c) after the script has been closed and unloaded.
00602     
00603     added hm parameter; avoid globals. we assume that the script window's globals are pushed
00604     */
00605     
00606     register hdloutlinerecord ho;
00607     hdlheadrecord hcursor;
00608     register boolean flnewscript = false;
00609     boolean flignore;
00610     
00611     megetcursornode (hm, &hcursor);
00612     
00613     if (!meloadscriptoutline (hm, hcursor, houtline, &flignore)) 
00614         return (false);
00615     
00616     ho = *houtline; /*copy into register*/
00617     
00618     if (ho == nil) { /*creating a new script outline*/
00619         
00620         flnewscript = true;
00621         
00622         assert (hm != nil);
00623         
00624         (**outlinewindowinfo).defaultfont = (**hm).defaultscriptfontnum;
00625         
00626         (**outlinewindowinfo).defaultsize = (**hm).defaultscriptfontsize;
00627         
00628         if (!opnewrecord (rscript, houtline))
00629             return (false);
00630         
00631         ho = *houtline;
00632         
00633         (**ho).outlinesignature = typeLAND;
00634         }
00635     
00636 //  opvalidate (ho);
00637     
00638     meclearhandles (ho);
00639     
00640     (**ho).flwindowopen = true;
00641     
00642     (**ho).outlinerect = rscript;
00643     
00644     if (flnewscript)
00645         (**ho).fltextmode = true;
00646     
00647     /*
00648     (**ho).fltextmode = bitboolean (flnewscript);
00649     */
00650     
00651     (**ho).horizscrollinfo.cur = (**ho).horizscrollinfo.min; /*always opens flush left*/
00652     
00653     (**ho).postfontchangecallback = &mescriptfontchangeroutine;
00654     
00655     (**ho).outlinerefcon = (long) hcursor; /*point back to headline -- for script debugger*/
00656     
00657     (**ho).outlinetype = outlineismenubarscript;
00658     
00659     (**ho).flfatheadlines = true;
00660     
00661     return (true);
00662     } /*meloadscript*/
00663 
00664 
00665 static boolean meunloadscript (hdlmenurecord hm) {
00666     
00667     /*
00668     1/2/91: killundo.  also, use opcloseoutline, not opunloadeditbuffer
00669     
00670     5.0b13 dmb: clean up; expect menubar's, not outline's globals to be set
00671     but take hm parameter anyway to reduce globals usage
00672     */
00673     
00674     register hdloutlinerecord ho = (**hm).scriptoutline;
00675     register hdlheadrecord hn = (**hm).scriptnode;
00676     WindowPtr w = (**hm).scriptwindow;
00677     
00678     assert (hm != nil);
00679     
00680     if (ho == nil) { /*defensive driving*/
00681         
00682         if (hn != nil)
00683             mesetscriptoutline (hn, nil); /*keep in synch*/
00684         
00685         return (false);
00686         }
00687     
00688     if (w != nil) {
00689         
00690         shellpushglobals (w);
00691         
00692         killundo (); /*must toss undos before they're stranded*/
00693         
00694         opcloseoutline (); /*prepare for dormancy, not in a window anymore*/
00695         }
00696     
00697     (**ho).flwindowopen = false;
00698     
00699     if (!(**ho).fldirty) { /*script isn't dirty, no reason to keep it around*/
00700         
00701         opdisposeoutline (ho, false);
00702         
00703         if (w != nil)
00704             shellclearwindowdata ();
00705         
00706         mesetscriptoutline (hn, nil);
00707         }
00708     
00709     if (w != nil)
00710         shellpopglobals ();
00711     
00712     return (true);
00713     } /*meunloadscript*/
00714 
00715 
00716 static boolean mehaslinkedtext (hdlheadrecord hnode) {
00717     
00718     tymenuiteminfo item;
00719     tylinkeditem linkeditem;
00720     
00721     if (!megetmenuiteminfo (hnode, &item)) 
00722         return (false);
00723     
00724     linkeditem = item.linkedscript;
00725     
00726     return ((linkeditem.adrlink != nildbaddress) || (linkeditem.houtline != nil));
00727     } /*mehaslinkedtext*/
00728 
00729 
00730 static void medisplayscriptbutton (boolean flpressed) {
00731     
00732     register hdlmenurecord hm = menudata;
00733     register boolean fl = flpressed;
00734     bigstring bs;
00735     Rect r, rfill;
00736     hdlheadrecord hcursor;
00737     
00738     r = (**hm).iconrect;    //dialoggetobjectrect (menuwindow, menuscriptitem, &r);
00739     
00740     if (isemptyrect (r))
00741         return;
00742 
00743     shellgetstring (scriptbuttonstring, bs);
00744     
00745     megetcursornode (hm, &hcursor);
00746     
00747     drawlabeledwindoidicon (r, bs, mehaslinkedtext (hcursor), fl);
00748     
00749     if (!fl) { /*not highlighted*/
00750         
00751         if ((**hm).scriptwindow != nil) { /*only relevant when window is open*/
00752     
00753             if ((**hm).flautosmash) { /***indicate autosmash is turned on*/
00754                 
00755                 rfill.left = rfill.top = 0;
00756                 
00757                 rfill.right = rfill.bottom = 13;
00758                 
00759                 centerrect (&rfill, r);
00760                 
00761                 offsetrect (&rfill, 0, -3);
00762                 
00763                 grayframerect (rfill);
00764                 }
00765             }
00766         }
00767     } /*medisplayscriptbutton*/
00768 
00769 
00770 boolean mesmashscriptwindow (void) {
00771     
00772     /*
00773     change the contents of the script window so that it displays the 
00774     script linked into the current bar cursor menu item.
00775     
00776     12/4/91 dmb: update the changes bit if the script windowinfo
00777     */
00778     
00779     register hdlmenurecord hm = menudata;
00780     register WindowPtr w = (**hm).scriptwindow;
00781     hdlheadrecord hcursor; 
00782     hdloutlinerecord houtline;
00783     register boolean fl;
00784     
00785     megetcursornode (hm, &hcursor);
00786     
00787     if ((**hm).scriptnode == hcursor) /*window already displays this guy*/
00788         return (true);
00789     
00790     meunloadscript (hm); /*detach the script window outline from the window*/
00791     
00792     shellpushglobals (w);
00793     
00794     fl = meloadscript (hm, (**outlinewindowinfo).contentrect, &houtline);
00795     
00796     if (fl)
00797         shellsetwindowchanges (shellwindowinfo, (**houtline).fldirty);
00798     
00799     shellpopglobals ();
00800     
00801     if (!fl)
00802         return (false);
00803     
00804     scriptsetdata (w, hcursor, houtline);
00805     
00806     mesetscriptoutline (hcursor, houtline); /*link outline record into menu*/
00807     
00808     (**hm).scriptnode = hcursor;
00809     
00810     (**hm).scriptoutline = houtline;
00811     
00812     return (true);
00813     } /*mesmashscriptwindow*/
00814 
00815 
00816 boolean mezoomscriptwindow (void) {
00817     
00818     /*
00819     5.0a10 dmb: call windowzoom here, after everything is set up. 
00820     for windows.
00821     */
00822 
00823     register hdlmenurecord hm = menudata;
00824     WindowPtr scriptwindow = (**hm).scriptwindow;
00825     hdlheadrecord hcursor;
00826     Rect rzoom;
00827     WindowPtr wnew;
00828     
00829     megetcursornode (hm, &hcursor);
00830     
00831     if (scriptwindow == nil) { /*window hasn't been zoomed*/
00832     
00833         rzoom = (**hm).iconrect; // dialoggetobjectrect (menuwindow, menuscriptitem, &rzoom);
00834         
00835         localtoglobalrect (menuwindow, &rzoom);
00836         
00837         if (!scriptzoomwindow ((**hm).scriptwindowrect, rzoom, hcursor, &wnew))
00838             return (false);
00839         
00840         (**hm).scriptwindow = scriptwindow = wnew;
00841         
00842         medisplayscriptbutton (false); /*display may change when window is open*/
00843         }
00844     
00845     if (!mesmashscriptwindow ()) { /*load window contents with script*/
00846         
00847         disposeshellwindow (scriptwindow);
00848         
00849         (**hm).scriptwindow = nil;
00850         
00851         return (false);
00852         }
00853     
00854     windowzoom (scriptwindow);
00855     
00856     windowbringtofront (scriptwindow); 
00857     
00858     return (true);
00859     } /*mezoomscriptwindow*/
00860 
00861 
00862 static boolean mefreshscriptwindow (void) {
00863     
00864     /*
00865     check to see if the script window is still displaying the script attached
00866     to the cursor in the menu structure.
00867     
00868     the cursor might have moved, the cursor might have been deleted, etc.
00869     
00870     returns true if it refreshed the window.
00871     
00872     wired-off 6/1/89 DW: user now has to hit the script button in the menu
00873     window to get the contents of the script window to change.
00874     */
00875     
00876     register hdlmenurecord hm = menudata;
00877     register hdlheadrecord hcursor;
00878     
00879     if (!(**hm).flautosmash) /*turned off*/
00880         return (false); 
00881     
00882     if ((**hm).scriptwindow == nil) /*no script window open*/
00883         return (false);
00884     
00885     hcursor = (**(**hm).menuoutline).hbarcursor;
00886     
00887     if ((**hm).scriptnode == hcursor) /*cursor didn't change*/
00888         return (false);
00889     
00890     return (mesmashscriptwindow ());
00891     } /*mefreshscriptwindow*/
00892 
00893 
00894 static byte megetcmdkey (hdlheadrecord hnode) {
00895     
00896     tymenuiteminfo item;
00897     
00898     megetmenuiteminfo (hnode, &item); /*will clear item on failure*/
00899     
00900     return (item.cmdkey);
00901     } /*megetcmdkey*/
00902 
00903 
00904 static void medisplaycmdkeypopup (void) { 
00905     
00906     register hdlmenurecord hm = menudata;
00907     register byte ch;
00908     hdlheadrecord hcursor;
00909     bigstring bs;
00910     Rect r;
00911     
00912     r = (**menudata).cmdkeypopuprect; // dialoggetobjectrect (menuwindow, menucmdkeypopupitem, &r);
00913     
00914     megetcursornode (hm, &hcursor);
00915     
00916     ch = megetcmdkey (hcursor);
00917     
00918     if (ch == chnul) {
00919         
00920         shellgetstring (cmdkeypopupstring, bs);
00921 
00922         pushchar (':', bs);
00923         }
00924     else
00925         getcommandkeystring (ch, keycommand, bs);
00926     
00927     drawpopup (r, bs, true);
00928     } /*medisplaycmdkeypopup*/
00929 
00930 
00931 /*
00932 static medisplaycmdkey (void) { 
00933     
00934     /%
00935     10/7/91 dmb: resurrected the seperate item for the setting the command key
00936     %/
00937     
00938     register unsigned char ch;
00939     hdlheadrecord hcursor;
00940     Rect r;
00941     
00942     dialoggetobjectrect (menuwindow, menucmdkeyitem, &r);
00943     
00944     openbitmap (r, menuwindow);
00945     
00946     eraserect (r);
00947     
00948     framerect (r);
00949     
00950     megetcursornode (&hcursor);
00951     
00952     ch = megetcmdkey (hcursor);
00953     
00954     pushclip (r);
00955     
00956     if (ch != chnul) {
00957         
00958         bigstring bs;
00959         
00960         setstringwithchar (ch, bs);
00961         
00962         pushstyle (geneva, 9, 0);
00963         
00964         centerstring (r, bs);
00965         
00966         popstyle ();
00967         }
00968     
00969     if ((**menudata).menuactiveitem == menucmdkeyitem) {
00970         
00971         insetrect (&r, 1, 1);
00972         
00973         invertrect (r);
00974         }
00975     
00976     popclip ();
00977     
00978     closebitmap (menuwindow);
00979     } /%medisplaycmdkey%/
00980 */
00981 
00982 
00983 static void mezoomdownwindow (WindowPtr w) {
00984     
00985     Rect r;
00986     
00987     if (w == nil) /*defensive driving*/
00988         return;
00989     
00990     r = (**menudata).iconrect; // dialoggetobjectrect (menuwindow, item, &r);
00991     //Code change by Timothy Paustian Monday, August 21, 2000 4:31:49 PM
00992     //Must pass a CGrafPtr to pushport on OS X to avoid a crash
00993     {
00994     CGrafPtr    thePort;
00995     #if TARGET_API_MAC_CARBON == 1
00996     thePort = GetWindowPort(menuwindow);
00997     #else
00998     thePort = (CGrafPtr)menuwindow;
00999     #endif
01000         
01001     pushport (thePort);
01002     }
01003     medisplayscriptbutton (true); /*simulate pressing the button*/
01004     
01005     popport ();
01006 
01007     localtoglobalrect (menuwindow, &r);
01008     
01009     zoomwindowtocenter (r, w);
01010     
01011         //Code change by Timothy Paustian Monday, August 21, 2000 4:31:49 PM
01012     //Must pass a CGrafPtr to pushport on OS X to avoid a crash
01013     {
01014     CGrafPtr    thePort;
01015     #if TARGET_API_MAC_CARBON == 1
01016     thePort = GetWindowPort(menuwindow);
01017     #else
01018     thePort = (CGrafPtr)menuwindow;
01019     #endif
01020         
01021     pushport (thePort);/*who knows what zoomport did to the port?*/
01022     }
01023     
01024     medisplayscriptbutton (false); /*hope it looks neat!!!*/
01025     
01026     popport ();
01027     } /*mezoomdownwindow*/
01028 
01029 
01030 boolean mescriptwindowclosed (void) {
01031     
01032     /*
01033     we need to be notified when the script window closes so we can update
01034     our data structures accordingly.
01035 
01036     5.0a10 dmb: instead of trying to fix Win crash, skip silly mezoomdownwindow
01037     */
01038     
01039     register hdlmenurecord hm = menudata;
01040     Rect r;
01041     
01042     meunloadscript (hm); /*detach the script from the window*/
01043     
01044     getglobalwindowrect ((**hm).scriptwindow, &r);
01045     
01046     (**hm).scriptwindowrect = r; /*remember for next time we zoom a script window*/
01047     
01048     #ifdef MACVERSION
01049     mezoomdownwindow ((**hm).scriptwindow); /*zoom it back to its button*/
01050     #endif
01051     
01052     (**hm).scriptwindow = nil;
01053     
01054     (**hm).scriptnode = nil;
01055     
01056     (**hm).scriptoutline = nil;
01057         
01058     //Code change by Timothy Paustian Monday, August 21, 2000 4:31:49 PM
01059     //Must pass a CGrafPtr to pushport on OS X to avoid a crash
01060     {
01061     CGrafPtr    thePort;
01062     #if TARGET_API_MAC_CARBON == 1
01063     thePort = GetWindowPort(menuwindow);
01064     #else
01065     thePort = (CGrafPtr)menuwindow;
01066     #endif
01067         
01068     pushport (thePort);/*who knows what zoomport did to the port?*/
01069     } 
01070     
01071     medisplayscriptbutton (false); /*update it immediately, better visually*/
01072     
01073     popport ();
01074     
01075     //windowsetchanges (menuwindow, true); /*the window is dirty*/  
01076     
01077     return (true);
01078     } /*mescriptwindowclosed*/
01079 
01080 
01081 void mepostcursormove (void) {
01082     
01083     /*
01084     a bundle of functionality that gets executed after the outline cursor moves.
01085     */
01086     
01087     medisplayscriptbutton (false); /*cursor might have linked text*/
01088     
01089     medisplaycmdkeypopup (); /*update dialog fields if there was a change*/
01090     
01091     mefreshscriptwindow ();
01092     
01093     (**menudata).flcursormoved = false;
01094     } /*mepostcursormove*/
01095 
01096 
01097 void meexpandto (hdlheadrecord hnode) {
01098     
01099     mecheckglobals ();
01100     
01101     opexpandto (hnode);
01102     
01103     opvisibarcursor (); /*in case barcursor was already hnode, but not visible*/
01104     
01105     mepostcursormove ();
01106     } /*meexpandto*/
01107 
01108 
01109 static void menubarchanged () {
01110     
01111     /*
01112     11/26/91 dmb: this functionality used to be implemented in menubar.c, but 
01113     we need to activate the callback when no menubarstack is connected, in case 
01114     there's one associated with a shared menu.  the callback is still managed 
01115     in menubar.c, but this is the only place that it's activated.
01116     */
01117     
01118     (*menubarcallbacks.menubarchangedroutine) (outlinedata);
01119     } /*menubarchanged*/
01120 
01121 
01122 void mesetcmdkey (byte ch, tykeyflags modifiers) { 
01123     
01124     /*
01125     5.0a24 dmb: made public, added modifiers parameter
01126     */
01127     
01128     register hdlmenurecord hm = menudata;
01129     register hdlheadrecord hcursor = (**(**hm).menuoutline).hbarcursor;
01130     tymenuiteminfo item;
01131     
01132     megetmenuiteminfo (hcursor, &item);
01133     
01134     if (ch == chbackspace) /*same as saying it has no keystroke*/
01135         ch = chnul;
01136     
01137     ch = uppercasechar (ch); /*cmd-keystrokes must be uppercase*/
01138     
01139     item.cmdkey = ch;
01140     
01141     item.cmdmodifiers = modifiers;
01142     
01143     mesetmenuiteminfo (hcursor, &item);
01144     
01145     opdirtyoutline ();
01146     
01147     medisplaycmdkeypopup ();
01148     
01149     menubarchanged ();
01150     
01151     memenuitemchanged ((**hm).hmenustack, hcursor);
01152     } /*mesetcmdkey*/
01153     
01154     
01155 static hdlheadrecord *globalcmdkeyarray = nil; /*for building the cmdkey popup menu*/
01156 
01157 
01158 static boolean mebuildcmdkeypopupvisit (hdlheadrecord hnode, ptrvoid refcon) {
01159 #pragma unused (refcon)
01160 
01161     register hdlheadrecord h = hnode;
01162     register unsigned char ch;
01163     
01164     if (!ophasrefcon (h)) /*no cmd-key attached to this line*/
01165         return (true);
01166     
01167     ch = megetcmdkey (h);
01168     
01169     if (ch == chnul) /*no cmd-key attached to this line*/
01170         return (true);
01171     
01172     globalcmdkeyarray [ch] = h; 
01173     
01174     return (true); /*keep traversing*/
01175     } /*mebuildcmdkeypopupvisit*/
01176 
01177 
01178 static boolean mefillcmdkeypopup (hdlmenu hmenu, short *highlighteditem) {
01179     
01180     /*
01181     2/21/91 dmb: added "set command key" item to replace functionality lost 
01182     by using new-style popup menu.  we could still have a direct entry item 
01183     next to the popup, but I don't think it's necessary.
01184     
01185     10/21/91 dmb: check the item of the cursor cmdkey, but select the dotted line
01186     */
01187     
01188     register hdloutlinerecord ho = (**menudata).menuoutline;
01189     register hdlheadrecord hnode;
01190     register short i;
01191     register short ixmenu = 0;
01192     bigstring bs;
01193     
01194     hnode = (**ho).hbarcursor;
01195     
01196     *highlighteditem = 2;
01197     
01198     if (true /*megetcmdkey (hnode) == chnul*/) { /*no cmd-key attached to this line*/
01199         
01200         shellgetstring (setcmdkeyitemstring, bs);
01201         
01202         pushmenuitem (hmenu, geneva9popupmenuid, bs, 0);
01203         
01204         pushdottedlinemenuitem (hmenu);
01205         
01206         ixmenu = 2;
01207         }
01208     
01209     for (i = 0; i < sizecmdkeyarray; i++) {
01210         
01211         hnode = globalcmdkeyarray [i];
01212         
01213         if (hnode != nil) {
01214             
01215             opgetheadstring (hnode, bs);
01216             
01217             pushmenuitem (hmenu, geneva9popupmenuid, bs, 0);
01218             
01219             setmenuitemcommandkey (hmenu, ++ixmenu, (char) i);
01220             
01221             if (hnode == (**ho).hbarcursor)
01222                 checkmenuitem (hmenu, ixmenu, true);
01223                 /*
01224                 *highlighteditem = ixmenu;
01225                 */
01226             }
01227         } /*for*/
01228     
01229     return (ixmenu > 0); /*true if there are any cmd key assignments*/
01230     } /*mefillcmdkeypopup*/
01231 
01232 
01233 static boolean mecmdkeypopupselect (hdlmenu hmenu, short ixmenu) {
01234     
01235     register hdlheadrecord hnode;
01236     short cmdkey;
01237     bigstring bs;
01238     
01239     if (ixmenu == 1) {
01240         
01241         cmdkey = megetcmdkey ((**(**menudata).menuoutline).hbarcursor);
01242         
01243         shellgetstring (cmdkeypromptstring, bs);
01244         
01245         if (chardialog (bs, &cmdkey)) {
01246         
01247             opsettextmode (false); /*leave edit mode*/
01248             
01249             mesetcmdkey ((byte) cmdkey, keycommand);
01250             }
01251         }
01252     else {
01253         
01254         getmenuitemcommandkey (hmenu, ixmenu, &cmdkey);
01255         
01256         hnode = globalcmdkeyarray [cmdkey];
01257         
01258         if (hnode != nil)
01259             meexpandto (hnode);
01260         }
01261     
01262     return (true);
01263     } /*mecmdkeypopupselect*/
01264 
01265 
01266 static boolean mecmdkeypopup (void) {
01267     
01268     hdlheadrecord cmdkeyarray [sizecmdkeyarray];
01269     Rect r;
01270     hdlheadrecord hsummit;
01271     boolean flgeneva9 = false;
01272     
01273     #if TARGET_API_MAC_CARBON
01274         flgeneva9 = true;
01275     #endif
01276     
01277     mecheckglobals ();
01278     
01279     clearbytes (&cmdkeyarray, longsizeof (cmdkeyarray));
01280     
01281     globalcmdkeyarray = (hdlheadrecord *) &cmdkeyarray; /*callbacks & visit routine use this guy*/
01282     
01283     opoutermostsummit (&hsummit);
01284     
01285     opsiblingvisiter (hsummit, false, &mebuildcmdkeypopupvisit, nil);
01286     
01287     r = (**menudata).cmdkeypopuprect; // dialoggetobjectrect (menuwindow, menucmdkeypopupitem, &r);
01288     
01289     popupmenuhit (r, flgeneva9, &mefillcmdkeypopup, &mecmdkeypopupselect);
01290     
01291     globalcmdkeyarray = nil; /*keep it nil while it isn't being used*/
01292     
01293     return (true);
01294     } /*mecmdkeypopup*/
01295 
01296 
01297 static void medisplayuseritems (void) {
01298     
01299     medisplaycmdkeypopup (); 
01300     
01301 //  medisplaycmdkey ();
01302     
01303     medisplayscriptbutton (false);
01304     } /*medisplayuseritems*/
01305     
01306 
01307 static boolean mescriptitemhit (boolean flmousedriven) {
01308     
01309     /*
01310     a special case for itemhit -- since we may be switching to a different window
01311     the display code has to be different.
01312     
01313     7/17/90 DW: we assume the script item hit was done by a human user hitting a 
01314     mouse button.  we track the mouse, if it's let up outside of the script item 
01315     we cancel the hit.
01316     */
01317     
01318     assert (menudata != nil);
01319     
01320     if (flmousedriven) {
01321         
01322         Rect r;
01323         
01324         if (optionkeydown ()) { /*toggle autosmash*/
01325             
01326             (**menudata).flautosmash = !(**menudata).flautosmash;
01327             
01328             medisplayscriptbutton (false); /*show the autosmash symbol*/
01329             
01330             return (true);
01331             }
01332         
01333         r = (**menudata).iconrect; // dialoggetobjectrect (menuwindow, menuscriptitem, &r);
01334         
01335         if (!trackicon (r, &medisplayscriptbutton)) /*user released mouse off of button*/
01336             return (true);
01337         }
01338     
01339     mecheckglobals ();
01340     
01341     opsettextmode (false); /*leave edit mode*/
01342     
01343     mezoomscriptwindow ();
01344     
01345     //windowsetchanges (menuwindow, true); /*the window is dirty*/
01346     
01347     return (true);
01348     } /*mescriptitemhit*/
01349 
01350 
01351 boolean memousedown (Point pt, tyclickflags flags) {
01352     
01353     /*
01354     7.0b23 PBS: fix crashing bug on Macs when choosing a right-click menu item.
01355     Trap for the control key and call oprmousedown, which handles right-clicks.
01356     */
01357 
01358     register hdlmenurecord hm;
01359     
01360     hm = menudata;
01361 
01362             
01363     #ifdef MACVERSION /*7.0b23 PBS: check for ctrl-clicking on Macs*/
01364 
01365         if (keyboardstatus.ctmodifiers && keyboardstatus.flcontrolkey) {
01366             return (oprmousedown (pt, flags)); /*Call right-click routine.*/
01367         }
01368 
01369     #endif
01370 
01371     if (pointinrect (pt, (**(**hm).menuoutline).outlinerect)) {
01372         
01373         mecheckglobals ();
01374         opmousedown (pt, flags);
01375         
01376         if (menudata == 0) return false;
01377         
01378         meactivateoutline (); /*trick -- avoid flicker -- activate after op moves cursor*/
01379         mepostcursormove (); 
01380         return (true);
01381         }
01382 
01383     setcursortype (cursorisarrow); /*erase any visual cues attached to cursor*/
01384 
01385     if (pointinrect (pt, (**hm).iconrect))
01386         return (mescriptitemhit (true));
01387 
01388     if (pointinrect (pt, (**hm).cmdkeypopuprect))
01389         return (mecmdkeypopup ());
01390 
01391         /*
01392         case menucmdkeyitem:
01393             medeactivateoutline ();
01394             
01395             (**menudata).menuactiveitem = item;
01396             
01397             medisplaycmdkey (); /%show it in its active form%/
01398             
01399             break;
01400         */
01401 
01402     return (false);
01403     } /*memousedown*/
01404 
01405 
01406 boolean mesetprintinfo (void) {
01407     
01408     mecheckglobals ();
01409     
01410     return (opsetprintinfo ());
01411     } /*mesetprintinfo*/
01412 
01413 
01414 boolean meprint (short pagenumber) {
01415     
01416     mecheckglobals ();
01417     
01418     return (opprint (pagenumber));
01419     } /*meprint*/
01420 
01421 
01422 boolean megetundoglobals (long *globals) {
01423     
01424     return (opeditgetundoglobals (globals));
01425     } /*megetundoglobals*/
01426 
01427 
01428 boolean mesetundoglobals (long globals, boolean flundo) {
01429     
01430     mesetglobals ();
01431     
01432     return (opeditsetundoglobals (globals, flundo));
01433     } /*mesetundoglobals*/
01434 
01435 
01436 /*
01437 merotateactiveitem (boolean flforward) {
01438     
01439     /%
01440     this is the response to a tab key (flforward == true) or a backtab 
01441     key (flforward == false).  we rotate to the next text item in the
01442     dialog box.
01443     
01444     10/23/90 dmb: now that there are only two items, this is much 
01445     simpler (no more switches)
01446     %/
01447     
01448     register hdlmenurecord hm = menudata;
01449     register short activeitem = (**hm).menuactiveitem;
01450     
01451     if (activeitem == menuoutlineitem) { /%switch from outline to command keys%/
01452         
01453         medeactivateoutline ();
01454         
01455         activeitem = menucmdxitem;
01456         }
01457     else {
01458     
01459         activeitem = menuoutlineitem;
01460         
01461         meactivateoutline ();
01462         }
01463     
01464     (**hm).menuactiveitem = activeitem;
01465 } /%merotateactiveitem%/
01466 */
01467 
01468 boolean mekeystroke (void) {
01469     
01470     register hdlmenurecord hm = menudata;
01471     byte chkb = keyboardstatus.chkb;
01472     //tydirection dir = keyboardstatus.keydirection;
01473     boolean flcmdkey = keyboardstatus.flcmdkey;
01474     
01475     #ifdef WIN95VERSION
01476         if (keyboardstatus.flcontrolkey)
01477             flcmdkey = true;
01478     #endif
01479 
01480     
01481     if ((chkb == chenter) && flcmdkey) {
01482         
01483         return (mescriptitemhit (false));
01484         }
01485     
01486     /*
01487     if (chkb == chtab) {
01488     
01489         merotateactiveitem (!keyboardstatus.flshiftkey);
01490         
01491         medisplayuseritems (); /%show it in its active/deactive state%/
01492         
01493         return (true);
01494         }
01495     */
01496     
01497     switch ((**hm).menuactiveitem) { /*send keystroke to appropriate user item*/
01498         
01499         /*
01500         case menucmdkeyitem:
01501             if (dir == nodirection) { /%not a motion keystroke%/
01502                 
01503                 switch (chkb) {
01504                     
01505                     case chtab: case chenter: case chescape:
01506                         meactivateoutline ();
01507                         
01508                         medisplaycmdkey (); /%show inactive state%/
01509                         
01510                         break;
01511                     
01512                     default:
01513                         mesetcmdkey (chkb);
01514                     }
01515                 
01516                 return (true);
01517                 }
01518             
01519             /%fall through, interpret as an op motion key, cmd-key item stays active%/
01520         */
01521         
01522         default:
01523             mecheckglobals ();
01524             
01525             opkeystroke ();
01526             
01527             mepostcursormove ();
01528             
01529             break;
01530         } /*switch*/
01531     
01532     /*
01533     if (dialogevent (&shellevent, menuwindow, &itemnumber)) {
01534     
01535         if ((**hm).menuactiveitem == menucmdkeyitem) 
01536             mesetcmdkey (); /%copy cmd-key from dialog to the outline%/
01537         }
01538     */
01539     
01540     return (true);
01541     } /*mekeystroke*/
01542 
01543 
01544 boolean mecmdkeyfilter (char chkb) {
01545     
01546     /*
01547     return false if the cmdkey is consumed, true if not.
01548     */
01549     
01550     /*
01551     if ((**menudata).menuactiveitem != menuoutlineitem) /%only outline snags cmdkeys%/
01552         return (true);
01553     */
01554         
01555     mecheckglobals ();
01556     
01557     if (opcmdkeyfilter (chkb)) /*op.c didn't consume the cmd-key*/
01558         return (true);
01559     
01560     mepostcursormove ();
01561     
01562     return (false); /*the cmd-key was consumed*/
01563     } /*mecmdkeyfilter*/
01564 
01565 
01566 static boolean metextchangedroutine (hdlheadrecord hnode, bigstring bsorig) {
01567 #pragma unused (bsorig)
01568 
01569     /*
01570     a callback routine, linked into the outlinerecord -- it gets called when
01571     the user has changed the text of one of the headlines.
01572     */
01573     
01574     menubarchanged ();
01575     
01576     return (memenuitemchanged ((**menudata).hmenustack, hnode));
01577     } /*metextchangedroutine*/
01578 
01579 
01580 static boolean meinsertlineroutine (hdlheadrecord hnode) {
01581 
01582     /*
01583     6/20/90 dmb:  a callback routine, called when a headline is inserted into 
01584     the outline.
01585     
01586     7/14/90 DW: work around double-return crash.  you have to hold down the
01587     option key to get it to update the menubar.
01588     
01589     7/27/90 DW: it crashed again -- saved file that crashes in doug.crash.
01590     
01591     7/31/90 dmb: bug described above was due to erronious bit calculation in 
01592     medeletemenu.  no longer have to hold down option key to enable this routine.
01593     
01594     10/30/91 dmb: set flcursormoved to keep button, popup up to date
01595     */
01596     
01597     assert (menudata != nil);
01598     
01599     (**menudata).flcursormoved = true;
01600     
01601     menubarchanged ();
01602     
01603     return (memenuitemadded ((**menudata).hmenustack, hnode));
01604     } /*meinsertlineroutine*/
01605 
01606 
01607 static boolean medeletelineroutine (hdlheadrecord hnode) {  
01608     
01609     /*
01610     a callback routine, it's called when the user has deleted a headline.
01611     
01612     10/30/91 dmb: call set flcursormoved to keep button, popup up to date
01613     
01614     8/17/92 dmb: if hnode is displayed in the script window, close it
01615     
01616     5.0a4 dmb: handle case where the scriptnode is subordinate to hnode
01617     */
01618     
01619     register hdlmenurecord hm = menudata;
01620     hdlheadrecord scriptnode;
01621     
01622     assert (hm != nil);
01623     
01624     (**hm).flcursormoved = true;
01625     
01626     menubarchanged ();
01627     
01628     scriptnode = (**hm).scriptnode;
01629     
01630     if (scriptnode != nil)
01631         if ((hnode == scriptnode) || opsubordinateto (scriptnode, hnode))
01632             shellclosewindow ((**hm).scriptwindow);
01633     
01634     return (memenuitemdeleted ((**hm).hmenustack, hnode));
01635     } /*medeletelineroutine*/
01636     
01637 
01638 static boolean meicon2click (hdlheadrecord hnode) {
01639     
01640     /*
01641     5.0a25 dmb: no reason not to enable this for menubars
01642     */
01643     
01644     if (ophassubheads (hnode))
01645         return (false);
01646     
01647     mezoomscriptwindow ();
01648     
01649     return (true);
01650     } /*meicon2click*/
01651 
01652 
01653 void mesetcallbacks (hdloutlinerecord houtline) {
01654     
01655     /*
01656     5.0a12 dmb: disable horizonal scrolling
01657     */
01658 
01659     register hdloutlinerecord ho = houtline;
01660     
01661     (**ho).backcolor = whitecolor;
01662     
01663     (**ho).pixelsaftericon = 3; /*skip this many pixels between icon and text*/
01664     
01665     (**ho).maxlinelen = 255; /*file names can be at most 31 characters long*/
01666     
01667     (**ho).fldonterasebackground = true;
01668 
01669     //(**ho).flusebitmaps = false; /*color bitmaps are slow in menubar windows; don't know why*/
01670     
01671     (**ho).setscrollbarsroutine = &mesetscrollbarsroutine;
01672         
01673     (**ho).drawlinecallback = &medrawlineroutine;
01674         
01675     (**ho).copyrefconcallback = &mecopyrefconroutine;
01676     
01677     (**ho).textualizerefconcallback = &metextualizerefconroutine;
01678     
01679     //(**ho).printrefconcallback = &meprintrefconroutine;
01680         
01681     (**ho).releaserefconcallback = &mereleaserefconroutine;
01682     
01683     (**ho).searchrefconcallback = &mesearchrefconroutine;
01684     
01685     (**ho).textchangedcallback = &metextchangedroutine;
01686     
01687     (**ho).insertlinecallback = &meinsertlineroutine;
01688     
01689     (**ho).deletelinecallback = &medeletelineroutine;
01690     
01691     (**ho).haslinkedtextcallback = &mehaslinkedtext;
01692     
01693     (**ho).setscrapcallback = (opsetscrapcallback) &mesetscraproutine;
01694     
01695     (**ho).getscrapcallback = (opgetscrapcallback) &megetscraproutine;
01696 
01697     (**ho).flhorizscrolldisabled = true; /*7.0b26 PBS: was commented out -- now restored.*/
01698     
01699     (**ho).icon2clickcallback = &meicon2click;
01700     } /*mesetcallbacks*/
01701 
01702 
01703 boolean meeditmenurecord (void) {
01704     
01705     /*
01706     assume that our globals, menudata, menuwindow and menuwindowinfo have been set up.
01707     
01708     we prepare the menudata menu record to be edited in menuwindow.
01709     
01710     2/26/91 dmb: commented-out movecursorto kluge; it shouldn't be needed any more.
01711     */
01712     
01713     register hdlmenurecord hm = menudata;
01714     register hdloutlinerecord ho = (**hm).menuoutline;
01715     
01716     mesetglobals ();
01717     
01718     meresetwindowrects (menuwindowinfo);
01719 
01720     meresize (); /*set the position of all objects in menu window*/
01721     
01722     //oppophoist (); /*for old, layered menubars*/
01723     
01724     opsetdisplaydefaults (ho);
01725     
01726     (**ho).flwindowopen = true;
01727     
01728     (**ho).flusebitmaps = false;
01729     
01730     meactivateoutline (); /*make sure we don't start w/the cmdkey item active*/
01731     
01732     return (true);
01733     } /*meeditmenurecord*/
01734     
01735     
01736 boolean menewmenurecord (hdlmenurecord *hmenurecord) {
01737     
01738     /*
01739     4/22/91 dmb: menu outline now points to menu variable
01740     
01741     10/22/91 dmb: correctly extract the default font/size for the menubar
01742     and script outlines from the config resources
01743     
01744     5.0b13 dmb: use langexternalgetconfig
01745     */
01746     
01747     register hdlmenurecord hm;
01748     hdloutlinerecord houtline = nil;
01749     register hdloutlinerecord ho = nil;
01750     tyconfigrecord lconfig;
01751     
01752     if (!newclearhandle (longsizeof (tymenurecord), (Handle *) hmenurecord))
01753         return (false);
01754     
01755     hm = *hmenurecord; /*copy into register*/
01756     
01757     (**hm).menuactiveitem = menuoutlineitem;
01758     
01759     (**hm).scriptwindowrect.top = -1; /*script window uses default rect*/
01760     
01761     (**hm).menuwindowrect.top = -1; /*menu window uses default rect*/
01762     
01763     if (!newoutlinerecord (&houtline)) 
01764         goto error;
01765     
01766     ho = houtline; /*copy into register*/
01767     
01768     (**hm).menuoutline = ho; /*link outline into menu structure*/
01769     
01770     (**ho).outlinerefcon = (long) hm; /*pointing is mutual*/
01771     
01772     mesetcallbacks (ho); /*link in callback routines*/
01773     
01774     bundle { /*set the default font for the menubar outline*/
01775         
01776         shellgetconfig (idmenueditorconfig, &lconfig);
01777         
01778         (**ho).fontnum = lconfig.defaultfont;
01779         
01780         (**ho).fontsize = lconfig.defaultsize;
01781         }
01782     
01783     bundle { /*set the default font for menubar scripts*/
01784         
01785         langexternalgetconfig (scriptvaluetype, idscriptconfig, &lconfig);
01786         
01787         (**hm).defaultscriptfontnum = lconfig.defaultfont;
01788         
01789         (**hm).defaultscriptfontsize = lconfig.defaultsize;
01790         }
01791     
01792     return (true);
01793     
01794     error:
01795     
01796     disposehandle ((Handle) hm);
01797     
01798     opdisposeoutline (ho, false);
01799     
01800     return (false);
01801     } /*menewmenurecord*/
01802 
01803 
01804 void medisposemenurecord (hdlmenurecord hmenurecord, boolean fldisk) {
01805     
01806     register hdlmenurecord hm = hmenurecord;
01807     
01808     medisposemenubar ((**hm).hmenustack);
01809     
01810     opdisposeoutline ((**hm).menuoutline, fldisk);
01811     
01812     if (fldisk) {
01813     
01814         dbpushdatabase (megetdatabase (hm));
01815 
01816         dbpushreleasestack ((**hm).adroutline, outlinevaluetype);
01817 
01818         dbpopdatabase ();
01819         }
01820     
01821     disposehandle ((Handle) hm);
01822     } /*medisposemenurecord*/
01823 
01824 
01825 /*dmb 10/4/90:  shouldn't need this; handled by releaserefconroutine
01826 
01827 boolean medisposevisit (hdlheadrecord hnode) {
01828     
01829     register hdloutlinerecord ho;
01830     tymenuiteminfo item;
01831     
01832     megetmenuiteminfo (hnode, &item);
01833     
01834     ho = item.linkedscript.houtline;
01835     
01836     if (ho != nil)
01837         opdisposeoutline (ho, false);
01838     
01839     return (true);
01840     } /%medisposevisit%/
01841 
01842 boolean medispose (void) {
01843     
01844     register hdlmenurecord hm = menudata;
01845     hdlheadrecord hsummit;
01846     
01847     mesetglobals ();
01848     
01849     opoutermostsummit (&hsummit);
01850     
01851     opsiblingvisiter (hsummit, false, &medisposevisit);
01852     
01853     opdisposeoutline (outlinedata, false);
01854     
01855     disposehandle ((Handle) hm);
01856     
01857     return (true);
01858     } /%medispose%/
01859 */
01860 
01861 
01862 boolean mecut (void) {
01863     
01864     mecheckglobals ();
01865     
01866     return (opcut ());
01867     } /*mecut*/
01868     
01869     
01870 boolean mecopy (void) {
01871     
01872     mecheckglobals ();
01873     
01874     return (opcopy ());
01875     } /*mecopy*/
01876     
01877     
01878 boolean mepaste (void) {
01879     
01880     mecheckglobals ();
01881     
01882     return (oppaste ());
01883     } /*mepaste*/
01884     
01885     
01886 boolean meclear (void) {
01887     
01888     mecheckglobals ();
01889     
01890     return (opclear ());
01891     } /*meclear*/
01892     
01893     
01894 boolean meselectall (void) {
01895     
01896     mecheckglobals ();
01897     
01898     return (opselectall ());
01899     } /*meselectall*/
01900     
01901     
01902 boolean meadjustcursor (Point pt) {
01903     
01904 //  Rect r;
01905     
01906 //  megetoutlinerect (&r);
01907     
01908     if (pointinrect (pt, (**menudata).menuoutlinerect)) {
01909     
01910         mecheckglobals ();
01911         
01912         return (opsetcursor (pt));
01913         }
01914     
01915 //  dialoggetobjectrect (menuwindow, menucmdkeypopupitem, &r);
01916     
01917     if (pointinrect (pt, (**menudata).cmdkeypopuprect)) {
01918         
01919         setcursortype (cursorispopup);
01920         
01921         return (true);
01922         }
01923     
01924 //  dialoggetobjectrect (menuwindow, menuscriptitem, &r); /*script button rect*/
01925     
01926     if (pointinrect (pt, (**menudata).iconrect)) {
01927         
01928         setcursortype (cursorisgo);
01929         
01930         return (true);
01931         }
01932         
01933     setcursortype (cursorisarrow);
01934     
01935     return (true);
01936     } /*meadjustcursor*/
01937     
01938     
01939 void meidle (void) {
01940     
01941     register hdlmenurecord hm = menudata;
01942     
01943     mecheckglobals ();
01944     
01945     if ((**hm).flcursormoved)
01946         mepostcursormove ();
01947     
01948     opidle ();
01949     
01950     /*
01951     if ((**hm).flzoomscriptwindow) {
01952         
01953         (**hm).flzoomscriptwindow = false;
01954         
01955         mezoomscriptwindow ();
01956         }
01957     */
01958     
01959     pushmenubarglobals ((**hm).hmenustack);
01960     
01961     mecheckdeletedmenu (-1, true); /*6/22/90 dmb: flush deleted menu*/
01962     
01963     popmenubarglobals ();
01964     
01965     if ((**hm).flcursormoved)
01966         mepostcursormove ();
01967     
01968     /*
01969     if (optionkeydown () && shiftkeydown ()) {
01970     
01971         opvalidate ((**hm).menuoutline);
01972         
01973         if (cmdkeydown ())
01974             Debugger ();
01975         }
01976     */
01977     } /*meidle*/
01978 
01979 
01980 void meactivate (boolean flactivate) {
01981     
01982     register boolean fl = flactivate;
01983     register hdlmenurecord hm = menudata;
01984     
01985     /*
01986     if (fl)
01987         ccsetmenubar (menudata);
01988     else
01989         ccsetmenubar (nil); /%use default menubar%/
01990     */
01991     
01992     if (!(**hm).flinstalled) { /*not an installed menu; appears only when window is active*/
01993         
01994         if (fl) { /*insert, but leave installed flag clear*/
01995             
01996             meinstallmenubar (hm);
01997             
01998             (**hm).flinstalled = false;
01999             }
02000         else {
02001             (**hm).flactive = false; //so remove will work
02002 
02003             meremovemenubar (hm);
02004             }
02005         }
02006     
02007     (**hm).flactive = bitboolean (fl);
02008     
02009     mecheckglobals ();
02010     
02011     if ((**hm).menuactiveitem == menuoutlineitem)
02012         opactivate (fl);
02013     } /*meactivate*/
02014 
02015 
02016 void meupdate (void) {
02017 
02018     Rect r;
02019     
02020     if (menudata == nil) // 5.0b10 dmb
02021         return;
02022 
02023     megetoutlinerect (&r);
02024     
02025     pushbackcolor (&(**outlinedata).backcolor);
02026     
02027     frame3sides (r);
02028     
02029     insetrect (&r, 1, 1);
02030     
02031     eraserect (r);
02032     
02033     popbackcolor ();
02034     
02035     mecheckglobals (); /*get ready to call op*/
02036     
02037     opupdate ();
02038     
02039     medisplayuseritems ();
02040     
02041     #if TARGET_API_MAC_CARBON == 1
02042     
02043         shelldrawwindowmessage (shellwindowinfo);
02044     
02045     #endif
02046 
02047     } /*meupdate*/
02048 
02049 
02050 boolean megetcontentsize (long *width, long *height) {
02051     
02052     /*
02053     6.0a13 dmb: use outlinerect, not menurect, to get pixel diff
02054     */
02055 
02056     Rect rcontent;
02057     Rect routline;
02058     short pixels;
02059     
02060     if (!opgetoutinesize (width, height))
02061         return (false);
02062     
02063     rcontent = (**menuwindowinfo).contentrect;
02064     
02065     routline = (**outlinedata).outlinerect;
02066     
02067     pixels = (rcontent.right - rcontent.left) - (routline.right - routline.left);
02068     
02069     *width += pixels;
02070     
02071     pixels = (rcontent.bottom - rcontent.top) - (routline.bottom - routline.top);
02072     
02073     *height += pixels;
02074     
02075     return (true);
02076     } /*megetcontentsize*/
02077 
02078 
02079 boolean meinstallmenubar (hdlmenurecord hmenurecord) {
02080     
02081     /*
02082     5.0b15 dmb: if we're active, we don't need to insert
02083     */
02084     
02085     register hdlmenurecord hm = hmenurecord;
02086     hdlmenubarstack hstack;
02087     
02088     hstack = (**hm).hmenustack; /*copy into register*/
02089     
02090     if (hstack == nil) { /*no menubar stack in this record*/
02091         
02092         if (!menewmenubar ((**hm).menuoutline, &hstack))
02093             return (false);
02094         
02095         (**hm).hmenustack = hstack;
02096         
02097         if (!mebuildmenubar (hstack))
02098             return (false);
02099         
02100         (**hstack).refcon = (long) megetdatabase (hm); // 5.1.5 for auto removal on close
02101         }
02102     
02103     if (!(**hm).flactive) //5.0b15
02104         if (!meinsertmenubar (hstack))
02105             return (false);
02106     
02107     (**hm).flinstalled = true;
02108     
02109     return (true);
02110     } /*meinstallmenubar*/
02111 
02112 
02113 boolean meremovemenubar (hdlmenurecord hmenurecord) {
02114     
02115     /*
02116     4/22/91 dmb: should we dispose the menubar stack at this point?
02117     
02118     5.0b15 dmb: if we're active, we don't shouldn't remove
02119     */
02120     
02121     register hdlmenurecord hm = hmenurecord;
02122     hdlmenubarstack hstack;
02123     
02124     hstack = (**hm).hmenustack; /*copy into register*/
02125     
02126     if (hstack == nil) /*no menubar stack in this record*/
02127         return (false);
02128     
02129     if (!(**hm).flactive) //5.0b15
02130         if (!medeletemenubar (hstack))
02131             return (false);
02132     
02133     (**hm).flinstalled = false;
02134     
02135     return (true);
02136     } /*meremovemenubar*/
02137 
02138 
02139 boolean meclearmenubar (void) {
02140 
02141     /*
02142     7.0b26 PBS: Save, clear, and restore the active menubar.
02143     This fixes an infinite loop -- because meremovemenubar (quite rightly)
02144     doesn't remove the active menu. But in this case we need to remove it
02145     then re-install it.*/
02146 
02147     
02148     register hdlmenubarlist hlist = menubarlist;
02149     register hdlmenubarstack hstack;
02150     register hdlmenurecord hm;
02151     hdlmenurecord hdlcurrmenu = nil;
02152     
02153     if (hlist == nil)
02154         return (true);
02155     
02156     while (true) {
02157         
02158         hstack = (**hlist).hfirst;
02159     
02160         if (hstack == nil) /*list is empty*/
02161             return (true);
02162         
02163         hm = (hdlmenurecord) (**(**hstack).menubaroutline).outlinerefcon;
02164 
02165         if ((**hm).flactive) { /*7.0b26 PBS: save active menubar*/
02166 
02167             hdlcurrmenu = hm;
02168 
02169             (**hm).flactive = false; /*allow active menubar to be removed.*/
02170             } /*if*/
02171         
02172         meremovemenubar (hm);
02173         }
02174 
02175     if (hdlcurrmenu != nil) /*7.0b26 PBS: restore the active menubar*/
02176         meinstallmenubar (hdlcurrmenu);
02177     } /*meclearmenubar*/
02178 
02179 
02180 void meinit (void) {
02181     
02182     menubarinit ();
02183     
02184     menubarcallbacks.getcmdkeyroutine = &megetcmdkey;
02185     } /*meinit*/
02186 
02187 
02188 
02189 

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