langexternal.c

Go to the documentation of this file.
00001 
00002 /*  $Id: langexternal.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 "cursor.h"
00033 #include "kb.h"
00034 #include "mouse.h"
00035 #include "strings.h"
00036 #include "db.h"
00037 #include "file.h"
00038 #include "font.h"
00039 #include "frontierconfig.h"
00040 #include "shell.h"
00041 #include "shellhooks.h"
00042 #include "shellprivate.h"
00043 #include "lang.h"
00044 #include "langinternal.h"
00045 #include "langtokens.h"
00046 #include "tablestructure.h"
00047 #include "langexternal.h"
00048 #include "cancoon.h"
00049 #include "menuverbs.h"
00050 #include "opverbs.h"
00051 #include "pictverbs.h"
00052 #include "tableverbs.h"
00053 #include "wpverbs.h"
00054 #ifdef fliowa
00055     #include "iowaverbs.h" /*3/18/92 dmb*/
00056 #endif
00057 #include "tableformats.h" /*7.0b6 PBS*/
00058 #include "menuverbs.h" /*7.0b6 PBS*/
00059 #include "op.h" /*7.0b6 PBS*/
00060 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00061 
00062 
00063 /*
00064 boolean langexternalload (hdlexternalvariable hvariable, Handle *h) {
00065     
00066     register hdlexternalvariable hv = hvariable;
00067     
00068     if ((**hv).flpathlink) {
00069         bigstring bspath;
00070         short fnum;
00071         boolean fl;
00072         
00073         copyheapstring ((hdlstring) (**hv).variabledata, bspath);
00074         
00075         if (!openfile (bspath, 0, &fnum))
00076             return (false);
00077         
00078         fl = filereadhandle (fnum, h);
00079         
00080         closefile (fnum);
00081         
00082         return (fl);
00083         }
00084     
00085     return (dbrefhandle ((dbaddress) (**hv).variabledata, h));
00086     } /%langexternalload%/
00087 
00088 
00089 boolean langexternalsave (hdlexternalvariable hvariable, Handle h, dbaddress *adr) {
00090     
00091     register hdlexternalvariable hv = hvariable;
00092     
00093     if ((**hv).flpathlink) {
00094         bigstring bspath;
00095         short fnum;
00096         boolean fl;
00097         
00098         copyheapstring ((hdlstring) *adr, bspath);
00099         
00100         if (!fileopenorcreate (bspath, 0, 'LAND', '2CLK', &fnum))
00101             return (false);
00102         
00103         fl = filewritehandle (fnum, h);
00104         
00105         closefile (fnum);
00106         
00107         return (fl);
00108         }
00109     
00110     return (dbassignhandle (h, adr));
00111     } /%langexternalsave%/
00112 */
00113 
00114 tyexternalid langexternalgettype (tyvaluerecord val) {
00115     
00116     /*
00117     call this when you know that val.valuetype is externalvaluetype.
00118     
00119     we hide the details of how the type of an external value is stored.
00120     */
00121     
00122     if (val.valuetype != externalvaluetype) /*defensive driving*/
00123         return ((tyexternalid) -1);
00124     
00125     return ((tyexternalid) (**(hdlexternalhandle) val.data.externalvalue).id);
00126     } /*langexternalgettype*/
00127     
00128     
00129 static boolean langexternalgetinfo (bigstring bs, hdlhashtable *htable, langvaluecallback *valueroutine) {
00130     
00131     /*
00132     a very central bottleneck -- we translate the name of an EFP (something like
00133     "shell" or "wp") into a symbol table and a routine which can be called to
00134     get a function value.
00135     
00136     indicate in flwindow whether the EFP requires that a window be open in order to
00137     evaluate a functionvalue.
00138     */
00139     
00140     tyvaluerecord val;
00141     register hdlhashtable ht;
00142     hdlhashnode hnode;
00143     
00144     if (!langgetsymbolval (bs, &val, &hnode)) /*has special case for root*/
00145         return (false);
00146     
00147     if (!tablevaltotable (val, htable, hnode))
00148         return (false);
00149         
00150     ht = *htable; /*copy into register*/
00151     
00152     *valueroutine = (**ht).valueroutine;
00153     
00154     return (true);
00155     } /*langexternalgetinfo*/
00156     
00157 
00158 boolean langexternalgettable (bigstring bs, hdlhashtable *htable) {
00159     
00160     langvaluecallback valueroutine;
00161     
00162     return (langexternalgetinfo (bs, htable, &valueroutine));
00163     } /*langexternalgettable*/
00164 
00165 
00166 boolean langexternalvaltotable (tyvaluerecord val, hdlhashtable *htable, hdlhashnode hnode) {
00167     
00168     return (tablevaltotable (val, htable, hnode));
00169     } /*langexternalvaltotable*/
00170 
00171 
00172 boolean langexternalfindvariable (hdlexternalvariable hv, hdlhashtable *htable, bigstring bsname) {
00173     
00174     #if langexternalfind_optimization
00175 
00176     if (hv != nil && (**hv).hexternaltable != nil && (**hv).hexternalnode != nil) {
00177 
00178         *htable = (**hv).hexternaltable;
00179 
00180         gethashkey ((**hv).hexternalnode, bsname);
00181         
00182         return true;
00183         }
00184 
00185     #endif
00186 
00187     return (tablefindvariable (hv, htable, bsname));
00188     } /*langexternalfindvariable*/
00189 
00190 
00191 boolean langexternalgettablevalue (hdltreenode hfirst, short pnum, hdlhashtable *htable) {
00192     
00193     return (gettablevalue (hfirst, pnum, htable));
00194     } /*langexternalgettablevalue*/
00195 
00196 
00197 hdldatabaserecord langexternalgetdatabase (hdlexternalvariable hv) {
00198     
00199     if (hv == nil)
00200         return (nil);
00201     
00202     return ((**hv).hdatabase);
00203     } /*langexternalgetdatabase*/
00204 
00205 
00206 void langexternalsetdatabase (hdlexternalvariable hv, hdldatabaserecord hdb) {
00207     
00208     /*
00209     5.1.4 dmb: set the database of the external object, only if it's new (i.e.
00210     it wasn't loaded from a database, in which case the database is fixed)
00211     */
00212 
00213     if (hv == nil || hdb == nil)
00214         return;
00215     
00216     if ((**hv).hdatabase == hdb)
00217         return;
00218     
00219     if ((**hv).flinmemory && (**hv).oldaddress == nildbaddress) // a new object, not from disk
00220         (**hv).hdatabase = hdb;
00221     } /*langexternalsetdatabase*/
00222 
00223 
00224 /*
00225 boolean langexternalarrayreference (bigstring bsarrayname, short ix, tyvaluerecord *valref) {
00226     
00227     /%
00228     we want to isolate the interpreter from understanding how arrays are stored.
00229     that's why this routine is part of the "external" interface of the language.
00230     
00231     the punchline -- an array is stored as an outline!  surprise!!!
00232     %/
00233     
00234     register hdlexternalhandle h;
00235     tyvaluerecord val;
00236     bigstring bs;
00237     Handle hnode;
00238     hdlexternalhandle hnew;
00239     
00240     if (!langgetsymbolval (bsarrayname, &val)) {
00241         
00242         langparamerror (unknownidentifiererror, bsarrayname);
00243         
00244         return (false);
00245         }
00246         
00247     if (val.valuetype != externalvaluetype) {
00248         
00249         langparamerror (notarrayerror, bsarrayname);
00250         
00251         return (false);
00252         }
00253     
00254     h = (hdlexternalhandle) val.data.externalvalue;
00255     
00256     if ((**h).id != idoutlineprocessor) {
00257         
00258         langparamerror (notarrayerror, bsarrayname);
00259         
00260         return (false);
00261         }
00262     
00263     if (!opverbarrayreference ((**h).hdata, ix, &hnode)) {
00264         
00265         langparamerror (arrayreferror, bsarrayname);
00266         
00267         return (false);
00268         }
00269     
00270     if (!newclearhandle (sizeof (tyexternalhandle), (Handle *) &hnew))
00271         return (false);
00272         
00273     h = hnew; /%copy into register%/
00274     
00275     pushtmpstack ((Handle) h); /%we just allocated a temporary value%/
00276     
00277     (**h).id = idheadrecord;
00278     
00279     (**h).hdata = hnode;
00280     
00281     setexternalvalue ((Handle) h, valref);
00282     
00283     return (true);
00284     } /%langexternalarrayreference%/
00285 */
00286 
00287 
00288 boolean langsetexternalsymbol (hdlhashtable htable, bigstring bs, tyexternalid id, Handle hdata) {
00289     
00290     /*
00291     called by an External Function Processor (EFP) to link his data into the
00292     current symboltable.  bs is the name of the variable, id tells us who is
00293     responsible for the data, and hdata is the handle we move around to move
00294     the data, and pass back to the EFP when he needs to do something with it.
00295     */
00296     
00297     register hdlexternalvariable hv = (hdlexternalvariable) hdata;
00298     tyvaluerecord val;
00299     register boolean fl;
00300     
00301     (**hv).id = id;
00302     
00303     setexternalvalue ((Handle) hv, &val);
00304     
00305     fl = hashtableassign (htable, bs, val);
00306     
00307     return (fl);
00308     } /*langsetexternalsymbol*/
00309 
00310 
00311 static boolean langexternalsetsave (hdlhashtable htable, bigstring bs, boolean fldontsave) {
00312     
00313     /*
00314     set the dont-save bit on the variable whose name is the indicated string.
00315     */
00316     
00317     hdlhashnode hnode;
00318     register boolean fl;
00319     
00320     pushhashtable (htable);
00321     
00322     fl = langfindsymbol (bs, &htable, &hnode);
00323     
00324     pophashtable ();
00325     
00326     if (fl)
00327         (**hnode).fldontsave = fldontsave;
00328         
00329     return (fl);
00330     } /*langexternalsetsave*/
00331     
00332     
00333 boolean langexternaldontsave (hdlhashtable htable, bigstring bs) {
00334     
00335     /*
00336     set the dont-save bit on the variable whose name is the indicated string.
00337     */
00338     
00339     return (langexternalsetsave (htable, bs, true));
00340     } /*langexternaldontsave*/
00341     
00342     
00343 boolean langexternalpleasesave (hdlhashtable htable, bigstring bs) {
00344     
00345     /*
00346     clear the dont-save bit on the variable whose name is the indicated string.
00347     */
00348     
00349     return (langexternalsetsave (htable, bs, false));
00350     } /*langexternalpleasesave*/
00351     
00352     
00353 boolean langexternaltypestring (hdlexternalhandle h, bigstring bs) {
00354     
00355     /*
00356     get the type string for the external value handle.
00357     */
00358     
00359     register hdlexternalvariable hv = h;
00360         
00361     switch ((**hv).id) {
00362         
00363         case idoutlineprocessor: case idscriptprocessor:
00364             opverbgettypestring (hv, bs);
00365             
00366             break;
00367         
00368         case idwordprocessor:
00369             wpverbgettypestring (hv, bs);
00370             
00371             break;
00372         
00373         case idtableprocessor:
00374             tableverbgettypestring (hv, bs);
00375             
00376             break;
00377         
00378         case idmenuprocessor:
00379             menuverbgettypestring (hv, bs);
00380             
00381             break;
00382             
00383         case idpictprocessor:
00384             pictverbgettypestring (hv, bs);
00385             
00386             break;
00387         
00388         #ifdef fliowa
00389         
00390         case idcardprocessor:
00391             cardverbgettypestring (hv, bs);
00392             
00393             break;
00394         
00395         #endif
00396         
00397         default:
00398             langgetmiscstring (unknownstring, bs);
00399             
00400             break;
00401         } /*switch*/
00402         
00403     return (true);
00404     } /*langexternaltypestring*/
00405 
00406 
00407 boolean langexternalgetdisplaystring (hdlexternalhandle h, bigstring bs) {
00408     
00409     /*
00410     10/22/90 dmb: now that we treat the external handle's data as an 
00411     external variable, we can factor some code.  now we only need to 
00412     switch on the id if the variable is in memory
00413     */
00414     
00415     register hdlexternalvariable hv = (hdlexternalvariable) h;
00416     
00417     setemptystring (bs);
00418     
00419     if (hv == nil) /*defensive driving*/
00420         return (false);
00421     
00422     if (!(**hv).flinmemory) {
00423         
00424         langgetmiscstring (ondiskstring, bs);
00425         
00426         /*
00427         copystring ("\pon disk", bs);
00428         */
00429         
00430         /*
00431         copystring ("\pon disk at ", bs);
00432         
00433         pushlong ((**hv).variabledata, bs);
00434         */
00435         
00436         return (true);
00437         }
00438     
00439     switch ((**h).id) {
00440         
00441         case idoutlineprocessor: case idscriptprocessor:
00442             opverbgetsummitstring (hv, bs);
00443             
00444             break;
00445         
00446         case idwordprocessor:
00447             wpverbgetdisplaystring (hv, bs);
00448             
00449             break;
00450         
00451         case idtableprocessor:
00452             tableverbgetdisplaystring (hv, bs);
00453             
00454             break;
00455             
00456         case idmenuprocessor:
00457             menuverbgetdisplaystring (hv, bs);
00458             
00459             break;
00460             
00461         case idpictprocessor:
00462             pictverbgetdisplaystring (hv, bs);
00463             
00464             break;
00465         
00466         #ifdef fliowa
00467         
00468         case idcardprocessor:
00469             cardverbgetdisplaystring (hv, bs);
00470             
00471             break;
00472         
00473         #endif
00474         
00475         default:
00476             langgetmiscstring (unknownstring, bs);
00477             
00478             break;
00479         } /*switch*/
00480         
00481     return (true);
00482     } /*langexternalgetdisplaystring*/
00483     
00484 
00485 static boolean langexternalvariablewindowopen (hdlexternalvariable hvariable, hdlwindowinfo *hinfo) {
00486     
00487     /*
00488     4/15/92 dmb: extracted from langexternalwindowopen, which takes a value parameter
00489     */
00490     
00491     register hdlexternalvariable hv = hvariable;
00492     
00493     *hinfo = nil; /*5.0d19 dmb*/
00494     
00495     switch ((**hv).id) {
00496     
00497         case idtableprocessor:
00498             return (tablewindowopen (hv, hinfo));
00499             
00500         case idoutlineprocessor: case idscriptprocessor:
00501             return (opwindowopen (hv, hinfo));
00502             
00503         case idwordprocessor:
00504             return (wpwindowopen (hv, hinfo));
00505             
00506         case idmenuprocessor:
00507             return (menuwindowopen (hv, hinfo));
00508             
00509         case idpictprocessor:
00510             return (pictwindowopen (hv, hinfo));
00511         
00512         #ifdef fliowa
00513         
00514         case idcardprocessor:
00515             return (cardwindowopen (hv, hinfo));
00516         
00517         #endif
00518         
00519         } /*switch*/
00520 
00521     return (false);
00522     } /*langexternalvariablewindowopen*/
00523 
00524 
00525 boolean langexternalregisterwindow (hdlexternalvariable hv) {
00526     
00527     /*
00528     5.1.5b10 dmb: even if windowgetpath fails, the fspec has the (unsaved) default name
00529     */
00530     
00531     hdlwindowinfo hinfo;
00532     WindowPtr w;
00533     tyfilespec fs;
00534     bigstring bsname;
00535     tyvaluerecord val;
00536     
00537     if (!langexternalvariablewindowopen (hv, &hinfo))
00538         return (false);
00539     
00540     if (hinfo == nil)
00541         return (false);
00542 
00543     w = (**hinfo).macwindow;
00544     
00545     if (!isfilewindow (w))
00546         return (false);
00547     
00548     if (!windowgetpath (w, bsname)) {
00549         
00550         windowgetfspec (w, &fs);
00551         
00552         copystring (fsname (&fs), bsname);
00553         
00554         //shellgetwindowtitle (hinfo, bsname);
00555         }
00556     
00557     setexternalvalue ((Handle) hv, &val);
00558     
00559     return (hashtableassign (filewindowtable, bsname, val));
00560     } /*langexternalregisterwindow*/
00561 
00562 
00563 boolean langexternalunregisterwindow (hdlwindowinfo hinfo) {
00564     
00565     /*
00566     5.1.5b10 dmb: even if windowgetpath fails, the fspec has the (unsaved) default name
00567     */
00568     
00569     tyfilespec fs;
00570     bigstring bsname;
00571     WindowPtr w;
00572     boolean fl;
00573     
00574     w = (**hinfo).macwindow;
00575     
00576     if (!isfilewindow (w))
00577         return (false);
00578     
00579     if (!windowgetpath (w, bsname)) {
00580         
00581         windowgetfspec (w, &fs);
00582         
00583         copystring (fsname (&fs), bsname);
00584         
00585         //shellgetwindowtitle (hinfo, bsname);
00586         }
00587     
00588     pushhashtable (filewindowtable);
00589     
00590     fl = hashdelete (bsname, false, false);
00591     
00592     pophashtable ();
00593     
00594     return (fl);
00595     } /*langexternalunregisterwindow*/
00596 
00597 
00598 static boolean closeregisteredwindowvisit (hdlhashnode hnode, ptrvoid refcon) {
00599     
00600     boolean flconfirm = (refcon != nil);
00601     hdlwindowinfo hinfo;
00602     
00603     if (langexternalwindowopen ((**hnode).val, &hinfo))
00604         return (shellclose ((**hinfo).macwindow, flconfirm));
00605     
00606     return (true);
00607     } /*closeregisteredwindowvisit*/
00608 
00609 
00610 boolean langexternalcloseregisteredwindows (boolean flconfirm) {
00611     
00612     /*
00613     5.0b12 dmb: the odb is about to close. All guest objects must
00614     be closed, maybe with confirmation
00615     */
00616     
00617     return (hashtablevisit (filewindowtable, &closeregisteredwindowvisit, (ptrvoid) ((long) flconfirm)));
00618     } /*langexternalcloseregisteredwindows*/
00619 
00620 
00621 boolean langexternalisdirty (hdlexternalhandle h) {
00622     
00623     register hdlexternalvariable hv = (hdlexternalvariable) h;
00624     
00625     switch ((**hv).id) {
00626         
00627         case idoutlineprocessor: case idscriptprocessor:
00628             return (opverbisdirty (hv));
00629         
00630         case idwordprocessor:
00631             return (wpverbisdirty (hv));
00632         
00633         case idmenuprocessor:
00634             return (menuverbisdirty (hv));
00635             
00636         case idpictprocessor:
00637             return (pictverbisdirty (hv));
00638         
00639         case idtableprocessor:
00640             return (tableverbisdirty (hv));
00641         
00642         #ifdef fliowa
00643         
00644         case idcardprocessor:
00645             return (cardverbisdirty (hv));
00646         
00647         #endif
00648         
00649         default:
00650             return (false);
00651         } /*switch*/
00652     } /*langexternalisdirty*/
00653 
00654 
00655 boolean langexternalsetdirty (hdlexternalhandle h, boolean fldirty) {
00656     
00657     /*
00658     4/14/92 dmb: new routine.  to encapsulate as much logic as possible, we 
00659     take care of windowinfo here, and only call specific routine if a change 
00660     in state is occuring.  this prevents each external from having to avoid 
00661     loading an object into memory when cleaning it, for instance.
00662     
00663     9/4/92 dmb: return false if it's a new object -- in memory, with no old dbaddress
00664     
00665     5.0d3 dmb: allow cleaning of newly-created objects, in case they're file objects.
00666     it really shouldn't hurt if they're odb objects either; they just won't be saved.
00667     */
00668     
00669     register hdlexternalvariable hv = (hdlexternalvariable) h;
00670     register boolean fl;
00671     boolean flwindowopen;
00672     hdlwindowinfo hinfo;
00673     
00674     if (fldirty == langexternalisdirty (hv))
00675         return (true);
00676     
00677     /*
00678     if ((**hv).flinmemory && ((**hv).oldaddress == nildbaddress)) // can't clean newly-created object
00679         return (false);
00680     */
00681     
00682     flwindowopen = langexternalvariablewindowopen (hv, &hinfo) && (hinfo != nil);
00683     
00684     switch ((**hv).id) {
00685         
00686         case idoutlineprocessor: case idscriptprocessor:
00687             fl = opverbsetdirty (hv, fldirty);
00688             
00689             break;
00690         
00691         case idwordprocessor:
00692             fl = wpverbsetdirty (hv, fldirty);
00693             
00694             break;
00695         
00696         case idmenuprocessor:
00697             fl = menuverbsetdirty (hv, fldirty);
00698             
00699             break;
00700             
00701         case idpictprocessor:
00702             fl = pictverbsetdirty (hv, fldirty);
00703             
00704             break;
00705         
00706         case idtableprocessor:
00707             fl = tableverbsetdirty (hv, fldirty);
00708             
00709             break;
00710         
00711         #ifdef fliowa
00712         
00713         case idcardprocessor:
00714             fl = cardverbsetdirty (hv, fldirty);
00715             
00716             break;
00717         
00718         #endif
00719         
00720         default:
00721             return (false);
00722         } /*switch*/
00723     
00724     if (!fl)
00725         return (false);
00726     
00727     if (flwindowopen)
00728         shellsetwindowchanges (hinfo, fldirty);
00729     
00730     return (true);
00731     } /*langexternalsetdirty*/
00732 
00733 
00734 boolean langexternalpack (hdlexternalhandle h, Handle *hpacked, boolean *flnewdbaddress) {
00735     
00736     tydiskexternalhandle rec;
00737     register hdlexternalvariable hv = (hdlexternalvariable) h;
00738     
00739     rollbeachball ();
00740     
00741     /*
00742     clearbytes (&rec, sizeof (rec));
00743     
00744     rec.flpathlink = (**h).flpathlink;
00745     */
00746     
00747     rec.versionnumber = conditionalshortswap (externaldiskversionnumber);
00748     
00749     rec.id = (byte) (**hv).id;
00750     
00751     if (!newfilledhandle (&rec, sizeof (rec), hpacked))
00752         return (false);
00753         
00754     switch ((**hv).id) {
00755         
00756         case idoutlineprocessor: case idscriptprocessor:
00757             return (opverbpack (hv, hpacked, flnewdbaddress));
00758         
00759         case idwordprocessor:
00760             return (wpverbpack (hv, hpacked, flnewdbaddress));
00761         
00762         case idtableprocessor:
00763             return (tableverbpack (hv, hpacked, flnewdbaddress));
00764             
00765         case idmenuprocessor:
00766             return (menuverbpack (hv, hpacked, flnewdbaddress));
00767         
00768         case idpictprocessor:
00769             return (pictverbpack (hv, hpacked, flnewdbaddress));
00770         
00771         #ifdef fliowa
00772         
00773         case idcardprocessor:
00774             return (cardverbpack (hv, hpacked));
00775         
00776         #endif
00777         
00778         default:
00779             return (false);
00780         } /*switch*/
00781     } /*langexternalpack*/
00782     
00783     
00784 boolean langexternalunpack (Handle hpacked, hdlexternalhandle *h) {
00785     
00786     hdlexternalvariable hdata;
00787     long ixload = 0;
00788     tydiskexternalhandle rec;
00789     tyexternalid id;
00790     
00791     *h = nil;
00792     
00793     if (hpacked == nil)
00794         return (false);
00795     
00796     assert (sizeof (tyexternalvariable) == 16L);
00797     
00798     rollbeachball ();
00799     
00800     if (!loadfromhandle (hpacked, &ixload, sizeof (rec), &rec))
00801         goto cantunpack;
00802     
00803     disktomemshort (rec.versionnumber);
00804 //  disktomemshort (rec.id);
00805 
00806     if (rec.versionnumber != 1)
00807         goto cantunpack;
00808 
00809     id = (tyexternalid) rec.id;
00810 
00811 
00812     switch (id) {
00813         
00814         case idoutlineprocessor:
00815             if (!opverbunpack (hpacked, &ixload, &hdata))
00816                 goto error;
00817                 
00818             break;
00819         
00820         case idscriptprocessor:
00821             if (!opverbscriptunpack (hpacked, &ixload, &hdata))
00822                 goto error;
00823                 
00824             break;
00825             
00826         case idwordprocessor:
00827             if (!wpverbunpack (hpacked, &ixload, &hdata))
00828                 goto error;
00829                 
00830             break;
00831         
00832         case idtableprocessor:
00833             if (!tableverbunpack (hpacked, &ixload, &hdata, false))
00834                 goto error;
00835                 
00836             break;
00837         
00838         case idmenuprocessor:
00839             if (!menuverbunpack (hpacked, &ixload, &hdata))
00840                 goto error;
00841             
00842             break;
00843             
00844         case idpictprocessor:
00845             if (!pictverbunpack (hpacked, &ixload, &hdata))
00846                 goto error;
00847             
00848             break;
00849         
00850         #ifdef fliowa
00851         
00852         case idcardprocessor:
00853             if (!cardverbunpack (hpacked, &ixload, &hdata))
00854                 goto error;
00855             
00856             break;
00857         
00858         #endif
00859         
00860         default:
00861             goto cantunpack;
00862         } /*switch*/
00863     
00864     (**hdata).id = id;
00865     
00866     /*(**hdata).flpathlink = rec.pathlink;*/
00867     
00868     *h = hdata; /*return a handle to the newly allocated external record*/
00869     
00870     return (true);
00871     
00872     cantunpack:
00873         
00874         langerror (cantunpackthisexternalerror);
00875     
00876     error:
00877     
00878         return (false);
00879     } /*langexternalunpack*/
00880     
00881     
00882 boolean langexternalmemorypack (hdlexternalhandle h, Handle *hpacked, hdlhashnode hnode) {
00883     
00884     /*
00885     a special call for the pack and unpack verbs.  we insist that packing result in
00886     a handle of contiguous bytes that represents the external variable.  this is
00887     different from the original packing method which results in a dbaddress being
00888     added to the end of the packed handle.  we need the bytes!
00889     */
00890     
00891     tydiskexternalhandle rec;
00892     register hdlexternalvariable hv = (hdlexternalvariable) h;
00893     
00894 //  rollbeachball ();
00895     
00896     rec.versionnumber = conditionalshortswap (externaldiskversionnumber);
00897     
00898     rec.id = (byte) (**hv).id;
00899     
00900     if (!newfilledhandle (&rec, sizeof (rec), hpacked))
00901         return (false);
00902         
00903     switch ((**hv).id) {
00904         
00905         case idoutlineprocessor: case idscriptprocessor:
00906             return (opverbmemorypack (hv, hpacked));
00907         
00908         case idwordprocessor:
00909             return (wpverbmemorypack (hv, hpacked));
00910         
00911         case idtableprocessor:
00912             return (tableverbmemorypack (hv, hpacked, hnode));
00913         
00914         case idmenuprocessor:
00915             return (menuverbmemorypack (hv, hpacked));
00916         
00917         case idpictprocessor:
00918             return (pictverbmemorypack (hv, hpacked));
00919         
00920         #ifdef fliowa
00921         
00922         case idcardprocessor:
00923             return (cardverbmemorypack (hv, hpacked));
00924         
00925         #endif
00926         
00927         default:
00928             langerror (cantpackthisexternalerror);
00929             
00930             return (false);
00931         } /*switch*/
00932     } /*langexternalmemorypack*/
00933 
00934 
00935 boolean langexternalmemoryunpack (Handle hpacked, hdlexternalhandle *h) {
00936     
00937     /*
00938     see comment at head of langexternalmemorypack.
00939     */
00940     
00941     hdlexternalvariable hdata;
00942     long ixload = 0;
00943     tydiskexternalhandle rec;
00944     tyexternalid id;
00945     
00946     *h = nil;
00947     
00948     if (hpacked == nil)
00949         return (false);
00950     
00951 //  rollbeachball ();
00952     
00953     if (!loadfromhandle (hpacked, &ixload, sizeof (rec), &rec))
00954         goto cantunpack;
00955         
00956 #if 0 // def MACVERSION
00957     if (rec.versionnumber == 1) {
00958         tyOLD42diskexternalhandle oldrec;
00959 
00960         ixload = 0;
00961         if (!loadfromhandle (hpacked, &ixload, sizeof (oldrec), &oldrec))
00962             goto cantunpack;
00963 
00964         id = oldrec.id;
00965 
00966         goto version1ok;
00967         }
00968 #endif
00969 
00970     disktomemshort (rec.versionnumber);
00971 //  disktomemshort (rec.id);
00972 
00973     if (rec.versionnumber != externaldiskversionnumber)
00974         goto cantunpack;
00975 
00976     id = (tyexternalid) rec.id;
00977 
00978 
00979 // version1ok:  
00980     
00981     switch (id) {
00982         
00983         case idoutlineprocessor:
00984             if (!opverbmemoryunpack (hpacked, &ixload, &hdata))
00985                 goto error;
00986             
00987             break;
00988         
00989         case idscriptprocessor:
00990             if (!opverbscriptmemoryunpack (hpacked, &ixload, &hdata))
00991                 goto error;
00992             
00993             break;
00994         
00995         case idwordprocessor:
00996             if (!wpverbmemoryunpack (hpacked, &ixload, &hdata))
00997                 goto error;
00998             
00999             break;
01000         
01001         case idtableprocessor:
01002             if (!tableverbmemoryunpack (hpacked, &ixload, &hdata, false))
01003                 goto error;
01004             
01005             break;
01006         
01007         case idmenuprocessor:
01008             if (!menuverbmemoryunpack (hpacked, &ixload, &hdata))
01009                 goto error;
01010             
01011             break;
01012         
01013         case idpictprocessor:
01014             if (!pictverbmemoryunpack (hpacked, &ixload, &hdata))
01015                 goto error;
01016             
01017             break;
01018         
01019         #ifdef fliowa
01020         
01021         case idcardprocessor:
01022             if (!cardverbmemoryunpack (hpacked, &ixload, &hdata))
01023                 goto error;
01024             
01025             break;
01026         
01027         #endif
01028         
01029         default:
01030             goto cantunpack;
01031         } /*switch*/
01032     
01033     (**hdata).id = id;
01034     
01035     *h = hdata; /*return a handle to the newly allocated external record*/
01036     
01037     return (true);
01038     
01039     cantunpack:
01040     
01041         langerror (cantunpackthisexternalerror);
01042     
01043     error:
01044     
01045         return (false);
01046     } /*langexternalmemoryunpack*/
01047 
01048 
01049 boolean langexternalcopyvalue (const tyvaluerecord *v1, tyvaluerecord *v2) {
01050 
01051     /*
01052     5.0.2b12 dmb: new routine
01053     */
01054     
01055     hdlexternalhandle h = (hdlexternalhandle) (*v1).data.externalvalue;
01056     Handle x;
01057     boolean fl;
01058     
01059     switch ((**h).id) {
01060         
01061         case idoutlineprocessor: 
01062         case idscriptprocessor:
01063             if (!opverbcopyvalue (h, &h))
01064                 return (false);
01065             
01066             setexternalvalue ((Handle) h, v2);
01067             
01068             return (true);
01069             
01070         default:
01071             if (!langpackvalue (*v1, &x, HNoNode))
01072                 return (false);
01073             
01074             fl = langunpackvalue (x, v2);
01075             
01076             disposehandle (x);
01077             
01078             return (fl);
01079         }
01080     } /*langexternalcopyvalue*/
01081 
01082 
01083 /*
01084 boolean langexternalcoercetostring (tyvaluerecord *v) {
01085     
01086     /%
01087     assume the valuerecord is of type externalvaluetype.
01088     
01089     if we return true, the valuerecord is of type string.
01090     %/
01091     
01092     register hdlexternalhandle h = (hdlexternalhandle) (*v).data.externalvalue;
01093     
01094     switch ((**h).id) {
01095         
01096         case idheadrecord: {
01097             bigstring bs;
01098             
01099             opverbgetheadstring (h, bs);
01100             
01101             return (setstringvalue (bs, v));
01102             }
01103             
01104         default:
01105             langerror (cantcoercetostringerror);
01106             
01107             return (false);
01108         
01109         } /%switch%/
01110         
01111     return (false);
01112     } /%langexternalcoercetostring%/
01113 */
01114 
01115 
01116 boolean langexternalgetowningwindow (hdlwindowinfo *hparent) {
01117     
01118     /*
01119     chase through the current symbol table chain until you find one that
01120     has a non-nil owningwindow field, and return that guy.
01121     
01122     if you reach the end of the chain, and all are nil, return false.
01123     
01124     an external guy can use this when he wants to zoom a window to edit
01125     something that came out of a symbol table and wants to know who to
01126     link the window to, child/parent-wise.
01127     
01128     10/22/90 dmb: new implementation.  it turns out that all table windows are 
01129     owned by the root, so there didn't need to be an owningwindow field in 
01130     each hash table.  to achieve the more specific zooming that was intended, 
01131     we traverse the hash table chain calling tablefinddatawindow, which uses the 
01132     hashtableformats field to find the displaying window.  if no window is found 
01133     (which is possible now that the root table isn't always displayed), the 
01134     current root window info is returned
01135     
01136     1/8/91 dmb: can no longer assume that currenthashtable isn't nil
01137     
01138     1/14/91 dmb: ignore most of above.  we actually want all windows containing 
01139     objects in the database to be children of the home window, not of each other 
01140     hierarchically.  the only exception is the menubar script window, which 
01141     doesn't use this routine.
01142     
01143     6.17.97 dmb: new implementation again. the root window can be invisible, and 
01144     the front window may be disk-based, and not owned by the root. so we must 
01145     find the window that owns the root. we must find cancoondata, not roottable. 
01146     the latter may not be open in a window
01147     */
01148     
01149     /*
01150     register hdlhashtable nomad = currenthashtable;
01151     
01152     while (nomad != nil) {
01153         
01154         if (tablefinddatawindow (nomad, hparent))
01155             return (true);
01156         
01157         nomad = (**nomad).prevhashtable;
01158         } /%while%/
01159     
01160     /%ran out of tables to look at%/
01161     */
01162     
01163     if (ccfindrootwindow (hparent))
01164         return (true);
01165     
01166     /*
01167     if (shellwindow != nil)
01168         return (getrootwindow (shellwindow, hparent));
01169     
01170     if (frontrootwindow (hparent))
01171         return (true);
01172     */
01173     
01174     *hparent = nil;
01175     
01176     return (false);
01177     } /*langexternalgetowningwindow*/
01178 
01179 
01180 void langexternalquotename (bigstring bsname) {
01181     
01182     /*
01183     5.0a16 dmb: deparse the string, and always use normal quotes
01184     
01185     5.1.3 dmb: deparse for normal quotes (which we're using), not curly quotes
01186     */
01187 
01188     langdeparsestring (bsname, chdoublequote); /*add needed escape sequences*/
01189 
01190     insertchar ('"', bsname);
01191     
01192     pushchar ('"', bsname);
01193     } /*langexternalquotename*/
01194 
01195 
01196 void langexternalbracketname (bigstring bsname) {
01197     
01198     /*
01199     5.0a16 dmb: this now takes care of deparsing, so caller shouldn't
01200     */
01201 
01202     if (langisidentifier (bsname)) /*doesn't need brackets*/
01203         return;
01204     
01205     langexternalquotename (bsname);
01206     
01207     insertchar ('[', bsname);
01208     
01209     pushchar (']', bsname);
01210     } /*langexternalbracketname*/
01211 
01212 long fullpathloopcount = 0;
01213 
01214 
01215 static boolean istableintable (hdlhashtable hparent, hdlhashtable hchild, hdlhashnode * hnode) {
01216     hdlhashnode x;
01217     hdlexternalvariable hv;
01218 
01219     *hnode = nil;
01220 
01221     if (hparent == nil)
01222         return (false);  //defensive driving
01223 
01224     x = (**hparent).hfirstsort;
01225 
01226     while (x != nil) {
01227         if ((**x).val.valuetype == externalvaluetype) {
01228             
01229             hv = (hdlexternalvariable) (**x).val.data.externalvalue;
01230 
01231             if ((**hv).id == idtableprocessor) {
01232 
01233                 if ((hdlhashtable)(**hv).variabledata == hchild) {
01234                     *hnode = x;
01235                     return (true);
01236                     }
01237                 }
01238             }
01239 
01240         x = (**x).sortedlink;
01241         }
01242 
01243     return (false);
01244     } /* istableintable */
01245 
01246 
01247 static boolean fullpathsearch (hdlhashtable intable, hdlhashtable fortable, bigstring forname, boolean flonlyinmemory, boolean flquote, boolean flincludeself, bigstring bspath, hdlwindowinfo *hroot) {
01248     
01249     /*
01250     1/28/91 dmb: added flquote parameter
01251 
01252     5.0a18 dmb: added hroot parameter, for guest databases.
01253     */
01254     
01255     register hdlhashtable ht = intable;
01256     register boolean fltempload;
01257     hdlhashnode x;
01258     register hdlexternalvariable hv = nil;
01259     bigstring bs;
01260     hdlwindowinfo hinfo;
01261     extern boolean tablesetdebugglobals (hdlhashtable, hdlhashnode);
01262     hdlhashtable pht;
01263     
01264     pht = nil;
01265 
01266     if (ht == nil) //defensive driving
01267         return (false);
01268     
01269     if (ht == fortable) { /* we are at the correct table */
01270         if (isemptystring (forname)) { /*asking for no specific name*/
01271 
01272             setemptystring (bspath);
01273             
01274             return (true);
01275             }
01276 
01277         if (hashtablesymbolexists (ht, forname)) { //Make sure the symbol exists
01278 
01279             copystring (forname, bspath);
01280                     
01281             if (flquote)
01282                 langexternalbracketname (bspath);
01283                     
01284             return (true);
01285             }
01286 
01287         return (false);
01288         }
01289 
01290 
01291     if ((**fortable).parenthashtable != nil) {
01292 
01293         pht = (**fortable).parenthashtable;
01294 
01295         if ((**fortable).thistableshashnode != nil) {
01296 
01297             hv = (hdlexternalvariable)(**((**fortable).thistableshashnode)).val.data.externalvalue;
01298 
01299             if ((hdlhashtable)(**hv).variabledata != fortable) {  /*is this a bad node record*/
01300 
01301                 (**fortable).thistableshashnode = nil; /*clear it and try to redo it below*/
01302                 }
01303             }
01304 
01305         if ((**fortable).thistableshashnode == nil) { /*go fill this in now*/
01306 
01307             if (istableintable (pht, fortable, &x))
01308                 (**fortable).thistableshashnode = x;
01309 
01310             else {
01311                 /*This is bad but be defensive... The parent pointer is wrong */
01312                 (**fortable).parenthashtable = nil;
01313                 pht = nil;
01314                 }
01315             }
01316         }
01317 
01318 
01319     if (pht != nil) { /*Then lets follow the nodes up...*/
01320 
01321         if (fullpathsearch (ht, pht, BIGSTRING (""), flonlyinmemory, flquote, flincludeself, bs, hroot)) {
01322 
01323             if ((ht != pht) || flincludeself) {
01324 
01325                 gethashkey ((**fortable).thistableshashnode, bspath);
01326                     
01327                 if (flquote)
01328                     langexternalbracketname (bspath);
01329                     
01330                 if (stringlength (bs) > 0) {
01331                         
01332                     /*bspath = bs + "." + bspath*/
01333 
01334                     pushchar ('.', bs);
01335                         
01336                     pushstring (bspath, bs);
01337 
01338                     copystring (bs, bspath);
01339                     }
01340                 }
01341             else
01342                 setemptystring (bspath);
01343                 
01344 
01345 
01346             if (! isemptystring (forname)) { /*asking for specific name*/
01347 
01348                 if (hashtablesymbolexists (fortable, forname)) { //Make sure the symbol exists
01349 
01350                     copystring (forname, bs);
01351                     
01352                     if (flquote)
01353                         langexternalbracketname (bs);
01354 
01355                     if (stringlength (bspath) > 0)
01356                         pushchar ('.', bspath);
01357 
01358                     pushstring (bs, bspath);
01359                     }
01360 
01361 //              return (false);
01362                 }
01363 
01364             if (hroot) {
01365                 x = (**fortable).thistableshashnode;
01366 
01367                 hv = (hdlexternalvariable) (**x).val.data.externalvalue;
01368 
01369                 if (langexternalvariablewindowopen (hv, &hinfo) && (hinfo != nil))
01370                     getrootwindow ((**hinfo).macwindow, hroot);
01371                 }
01372 
01373             return (true);
01374             }
01375 
01376         return (false); 
01377         }
01378 
01379 
01380     x = (**ht).hfirstsort;
01381     
01382     while (x != nil) { /*chain through the hash list*/
01383         
01384         fltempload = false;
01385 
01386         ++fullpathloopcount;
01387                 
01388         if ((**x).val.valuetype != externalvaluetype) 
01389             goto nextx;
01390             
01391         hv = (hdlexternalvariable) (**x).val.data.externalvalue;
01392 
01393         if ((**hv).id != idtableprocessor)
01394             goto nextx;
01395         
01396         if (!(**hv).flinmemory) {
01397         
01398             if (flonlyinmemory) /*can't find it if it isn't in memory*/
01399                 goto nextx;
01400             
01401             if (!tableverbinmemory (hv, x))
01402                 return (false);
01403                 
01404             fltempload = true;
01405             }
01406         
01408         
01409         if (fullpathsearch ((hdlhashtable) (**hv).variabledata, fortable, forname, flonlyinmemory, flquote, true, bs, hroot)) {
01410             hdlhashtable cht;
01411             hdlhashnode nn;
01412 
01413             cht = ((hdlhashtable) (**hv).variabledata);
01414 
01415             /*we do not have an if statement here since the straight assignment is faster*/
01416             (**cht).parenthashtable = ht;  /*set the parent pointer for next time*/
01417 
01418             if ((**cht).thistableshashnode == nil)
01419                 if (istableintable (ht, cht, &nn))
01420                     (**cht).thistableshashnode = nn;
01421 
01422             if (flincludeself) {
01423                 
01424                 gethashkey (x, bspath);
01425                 
01426                 if (flquote)
01427                     langexternalbracketname (bspath);
01428                 
01429                 if (stringlength (bs) > 0) {
01430                     
01431                     pushchar ('.', bspath);
01432                     
01433                     pushstring (bs, bspath);
01434                     }
01435                 }
01436             else
01437                 copystring (bs, bspath);
01438             
01439             if (hroot && (*hroot == nil))
01440                 if (langexternalvariablewindowopen (hv, &hinfo) && (hinfo != nil))
01441                     getrootwindow ((**hinfo).macwindow, hroot);
01442             
01443             return (true); /*unwind recursion*/
01444             }
01445             
01446         nextx:
01447         
01448         if (fltempload)
01449             tableverbunload (hv);
01450         
01451         x = (**x).sortedlink; //    hashlink; /*advance to next node in chain*/
01452         } /*while*/
01453         
01454     return (false);
01455     } /*fullpathsearch*/
01456 
01457 
01458 long tableCount = 0;
01459 long maxBucketCount;
01460 long maxdepth;
01461 long currentdepth;
01462 long xxgoodnodelinks;
01463 long xxbadnodelinks;
01464 
01465 typedef struct {
01466     long cttotal;
01467     long ctloaded;
01468     } tyhashstatselement;
01469 
01470 tyhashstatselement hashstats[ctvaluetypes];
01471 
01472 
01473 boolean fullpathstats (hdlhashtable intable, boolean flfirst) {
01474     
01475     /*
01476     1/28/91 dmb: added flquote parameter
01477 
01478     5.0a18 dmb: added hroot parameter, for guest databases.
01479     */
01480     
01481     register hdlhashtable ht = intable;
01482     register hdlhashnode x;
01483     //register hdlexternalhandle xval;
01484     //register hdlhashtable xtable;
01485     register long i;
01486     tyvaluerecord val;
01487     register hdlexternalvariable hv = nil;
01488     extern boolean tablesetdebugglobals (hdlhashtable, hdlhashnode);
01489     long bucketCount;
01490     register tyvaluetype valtype;
01491     boolean flloaded;
01492 
01493     
01494     if (flfirst) {
01495         tableCount = 0;
01496         maxBucketCount = 0;
01497         maxdepth = 0;
01498         currentdepth = 1;
01499         xxgoodnodelinks = 0;
01500         xxbadnodelinks = 0;
01501         clearbytes (hashstats, sizeof (hashstats));
01502         }
01503     else
01504     {
01505 /*      x = (hdlhashnode) (**ht).hashtablerefcon;
01506         xval = (hdlexternalvariable) ((**x).val.data.externalvalue);
01507         xtable = (hdlhashtable) ((**xval).variabledata);
01508 
01509         if (xtable != ht)
01510             ++xxbadnodelinks;
01511         else
01512             ++xxgoodnodelinks;
01513 */  }
01514     
01515     ++tableCount;
01516 
01517     if (ht == nil) //defensive driving
01518         return (true);
01519     
01520     for (i = 0; i < ctbuckets; i++) {
01521         
01522         x = (**ht).hashbucket [i];
01523         
01524         bucketCount = 0;
01525 
01526         while (x != nil) { /*chain through the hash list*/
01527                         
01528             ++bucketCount;
01529 
01530             val = (**x).val;
01531 
01532             valtype = val.valuetype;
01533 
01534             flloaded = !val.fldiskval;
01535 
01536             if (valtype == externalvaluetype) {
01537 
01538                 valtype = (tyvaluetype) (outlinevaluetype + langexternalgettype (val));
01539 
01540                 hv = (hdlexternalvariable) val.data.externalvalue;
01541 
01542                 flloaded = flloaded && (**hv).flinmemory;
01543                 }
01544 
01545             ++hashstats[valtype].cttotal;
01546 
01547             if (flloaded)
01548                 ++hashstats[valtype].ctloaded;
01549 
01550             if (valtype == tablevaluetype && flloaded) {
01551 
01552                 ++currentdepth;
01553 
01554                 if (maxdepth < currentdepth)
01555                     maxdepth = currentdepth;
01556 
01557                 fullpathstats ((hdlhashtable) (**hv).variabledata, false);
01558 
01559                 --currentdepth;
01560                 }
01561 /*
01562             switch (langexternalgettypeid (val)) {
01563 
01564                 case tablevaluetype:
01565 
01566                     hv = (hdlexternalvariable) val.data.externalvalue;
01567             
01568                     if ((**hv).flinmemory) {
01569                     
01570                         ++currentdepth;
01571 
01572                         if (maxdepth < currentdepth)
01573                             maxdepth = currentdepth;
01574 
01575                         fullpathstats ((hdlhashtable) (**hv).variabledata, false);
01576 
01577                         --currentdepth;
01578                         }
01579                     
01580                     break;
01581                     
01582                 case binaryvaluetype:
01583 
01584                     ++ctbinaryobjects;
01585 
01586                     if (!val.fldiskval) { //it's actually loaded
01587                     
01588                         long ctbytes = gethandlesize (val.data.binaryvalue);
01589 
01590                         ++ctloadedbinaryobjects;
01591 
01592                         sizebinaryobjects += ctbytes;
01593 
01594                         if (sizelargestbinaryobject < ctbytes)
01595                             sizelargestbinaryobject = ctbytes;
01596 
01597                         if (ctbytes <= 1000L)
01598                             ++ctbinaryobjects1;
01599                         else if (ctbytes <= 50000L)
01600                             ++ctbinaryobjects2;
01601                         else if (ctbytes <= 100000L)
01602                             ++ctbinaryobjects3;
01603                         else
01604                             ++ctbinaryobjects4;
01605                         }
01606 
01607                     break;
01608                     
01609                 }/%switch*/
01610                             
01611             x = (**x).hashlink; /*advance to next node in chain*/
01612             } /*while*/
01613 
01614         if (bucketCount > maxBucketCount)
01615             maxBucketCount = bucketCount;
01616 
01617         } /*for*/
01618         
01619     return (true);
01620     } /*fullpathstats*/
01621 
01622 #define STR_Comma_Space BIGSTRING ("\x02" ", ")
01623 #define STR_Colon_Space BIGSTRING ("\x02" ": ")
01624 
01625 boolean hashstatsverb (tyvaluerecord *v) {
01626 
01627     handlestream s;
01628     long ix;
01629     bigstring bs;
01630 
01631     fullpathstats (roottable, true);
01632 
01633     openhandlestream (nil, &s);
01634 
01635     if (!writehandlestreamlong (&s, maxBucketCount))
01636         goto error;
01637 
01638     if (!writehandlestreamstring (&s, STR_Comma_Space))
01639         goto error;
01640 
01641     if (!writehandlestreamlong (&s, tableCount))
01642         goto error;
01643 
01644     if (!writehandlestreamstring (&s, STR_Comma_Space))
01645         goto error;
01646 
01647     if (!writehandlestreamlong (&s, maxdepth))
01648         goto error;
01649 
01650     if (!writehandlestreamstring (&s, STR_Comma_Space))
01651         goto error;
01652 
01653     if (!writehandlestreamlong (&s, xxgoodnodelinks))
01654         goto error;
01655 
01656     if (!writehandlestreamstring (&s, STR_Comma_Space))
01657         goto error;
01658 
01659     if (!writehandlestreamlong (&s, xxbadnodelinks))
01660         goto error;
01661 
01662     for (ix = 1; ix < ctvaluetypes; ix++) {
01663 
01664         if (!writehandlestreamchar (&s, '\r'))
01665             goto error;
01666 
01667         if (!writehandlestreamlong (&s, hashstats[ix].ctloaded))
01668             goto error;
01669 
01670         if (!writehandlestreamchar (&s, '\t'))
01671             goto error;
01672 
01673         if (!writehandlestreamlong (&s, hashstats[ix].cttotal))
01674             goto error;
01675 
01676         if (!writehandlestreamchar (&s, '\t'))
01677             goto error;
01678 
01679         if (!langgettypestring (ix, bs))
01680             goto error;
01681 
01682         if (!writehandlestreamstring (&s, bs))
01683             goto error;
01684         }/*for*/
01685 
01686     return (setheapvalue (closehandlestream (&s), stringvaluetype, v));
01687 
01688 error:
01689 
01690     disposehandlestream (&s);
01691 
01692     return (false);
01693     }/*hashstatsverb*/
01694 
01695 
01696 
01697 static boolean getfullpath (hdlhashtable htable, bigstring bsname, boolean flquote, bigstring bspath, hdlwindowinfo *hroot) {
01698     
01699     /*
01700     do a traversal of the root symbol table to get the full path for the indicated
01701     variable.  a full path is something like "agents.secret.007".
01702     
01703     the variable is specified by [htable, bsname].  the path is returned in bspath.
01704     
01705     if bsname is empty, just return a path to the table.
01706     
01707     first we do a search restricted to only those tables that are in memory.  if 
01708     it's found we get off with a very cheap traversal.  otherwise we go slowly
01709     through the whole structure loading everything in from disk to do the search.
01710     
01711     if htable is the root table, and our initial search doesn't find bsname, 
01712     the only possibility is that bsname is the name of a special table.  if so, 
01713     it's name is it's path; otherwise, return false -- no need to look further.
01714     
01715     8/19/91 dmb: if the indicated table is a local table, and it's not found 
01716     in the object db (not being debugged), just return the name
01717     
01718     7.22.97 dmb: do the same for the root table (for standalones)
01719     
01720     5.0d20 dmb: search the files table first, so we get short paths for 
01721     items within standalone tables. shoundn't be too costly, since the table 
01722     is small and we aren't called that often
01723 
01724     5.0a18 dmb: added hroot stuff. kind of ugly. the goal: notice when a path
01725     is below a file-based object, and set it to that parent object, otherwise
01726     the active root.
01727     
01728     5.0.2b21 dmb: don't make the path to the file windows table itself empty.
01729 
01730     5.1.4 dmb: never call fullpathsearch with flonlyinmemory false. an in-memory table
01731     can never be contained by a table that's still on disk
01732     
01733     5.1.5 dmb: added flincludeself parameter to fullpathsearch. We pass false when 
01734     searching the file window table if we're not quoting the path, to avoid file names
01735     in window titles.
01736     */
01737     
01738     boolean fl = true;
01739 
01740     if (hroot)
01741         *hroot = nil;
01742 
01743     if ((htable == roottable) && isemptystring (bsname)) {
01744         
01745         copystring (nameroottable, bspath);
01746         
01747         goto exit;
01748         }
01749     
01750     if (htable && !(**htable).fllocaltable) {
01751 
01752         if ((htable == filewindowtable) || (tablegetdatabase (htable) != tablegetdatabase (roottable)))
01753             if (fullpathsearch (filewindowtable, htable, bsname, true, flquote, flquote, bspath, hroot))
01754                 goto exit;
01755         
01756         if (fullpathsearch (roottable, htable, bsname, true, flquote, true, bspath, hroot))
01757             goto exit;
01758         }
01759     
01760     if ((htable == roottable) || (htable == nil)) {
01761         
01767          if (langgetspecialtable (bsname, &htable)) {
01768             
01769             copystring (bsname, bspath);
01770 
01771             goto exit;
01772             }
01773         }
01774     else {
01775         
01776         if ((**htable).fllocaltable) { /*8/19/91 dmb*/
01777             
01778             hdlhashtable ht;
01779             
01780             if ((**htable).prevhashtable == nil) { // not in the local chain
01781             
01782                 for (ht = currenthashtable; ht != nil; ht = (**ht).prevhashtable) {
01783             
01784                     if (fullpathsearch (ht, htable, bsname, true, flquote, true, bspath, hroot))
01785                         goto exit;
01786                     }
01787                 }
01788             
01789             if (!isemptystring (bsname)) {
01790                 
01791                 copystring (bsname, bspath);
01792                 
01793                 goto exit;
01794                 }
01795             }
01796         
01797         // now try non-inmemory search
01798         //if (fullpathsearch (roottable, htable, bsname, false, flquote, bspath, hroot))
01799         //  goto exit;
01800         }
01801     
01802     fl = false;
01803 
01804     exit:
01805     
01806     if (!fl) {
01807 
01808         langparamerror (nopatherror, bsname);
01809         
01810         return (false);
01811         }
01812     
01813     if (hroot && (*hroot == nil))
01814         ccfindrootwindow (hroot);
01815 
01816     return (true);
01817     } /*getfullpath*/
01818 
01819 
01820 boolean langexternalgetfullpath (hdlhashtable htable, bigstring bsname, bigstring bspath, hdlwindowinfo *hroot) {
01821     
01822     /*
01823     normal version of getfullpath, with concatenates each name in the path, 
01824     creating a string suitable for display purposes.
01825 
01826     added hroot parameter. we set it to the windowinfo of the root containing
01827     the node
01828     */
01829     
01830     return (getfullpath (htable, bsname, false, bspath, hroot));
01831     } /*langexternalgetfullpath*/
01832 
01833 
01834 boolean langexternalgetquotedpath (hdlhashtable htable, bigstring bsname, bigstring bspath) {
01835     
01836     /*
01837     special version of getfullpath which quotes each name in the path.
01838     
01839     this is used for interactive value and type assignment in tables, 
01840     where bspath is used in expressions rather than for display purposes.
01841     */
01842     
01843     return (getfullpath (htable, bsname, true, bspath, nil));
01844     } /*langexternalgetquotedpath*/
01845 
01846 
01847 boolean langexternalgetexternalparam (hdltreenode hfirst, short pnum, short *id, hdlexternalvariable *hv) {
01848     
01849     /*
01850     this code was factored from each EFP's getxxxparam routine.  it ensures that 
01851     the parameter specified by [hfirst, pnum] corresponds to an external value in 
01852     a table.  if so, the EFP id and the variable itself are returned in [id, hv].
01853     
01854     ..in addition, the full path to the variable is calculated and returned in bs.
01855     */
01856     
01857     tyvaluerecord val;
01858     register hdlexternalhandle h;
01859     hdlhashtable htable;
01860     bigstring bs;
01861     hdlhashnode hnode;
01862     
01863     *hv = nil; /*default*/
01864     
01865     if (!getvarparam (hfirst, pnum, &htable, bs)) /*name of variable*/
01866         return (false);
01867     
01868     if (!langsymbolreference (htable, bs, &val, &hnode))
01869         return (false);
01870     
01871     if (val.valuetype != externalvaluetype)
01872         return (false);
01873     
01874     //if (langexternalgetfullpath (htable, bs, bspath, nil))
01875     //  copystring (bspath, bs);
01876     
01877     h = (hdlexternalhandle) val.data.externalvalue;
01878     
01879     *id = (**h).id;
01880     
01881     *hv = (hdlexternalvariable) h;
01882     
01883     return (true);
01884     } /*langexternalgetexternalparam*/
01885 
01886 
01887 static boolean langexternaledit (hdlexternalvariable hv, hdlwindowinfo hparent, tyfilespec *fs, bigstring bstitle, const Rect *rzoom) {
01888     
01889     /*
01890     6.16.97 dmb: the guts of langexternalzoom[from|filewindow]
01891     */
01892     
01893     boolean fl = false;
01894     
01895     switch ((**hv).id) {
01896         
01897         case idtableprocessor:
01898             fl = tableedit (hv, hparent, fs, bstitle, rzoom);
01899             
01900             break;
01901         
01902         case idoutlineprocessor: 
01903         case idscriptprocessor:
01904             fl = opedit (hv, hparent, fs, bstitle, rzoom);
01905             
01906             break;
01907         
01908         case idwordprocessor:
01909             fl = wpedit (hv, hparent, fs, bstitle, rzoom);
01910             
01911             break;
01912             
01913         case idmenuprocessor:
01914             fl = menuedit (hv, hparent, fs, bstitle, rzoom);
01915             
01916             break;
01917             
01918         case idpictprocessor:
01919             fl = pictedit (hv, hparent, fs, bstitle, rzoom);
01920             
01921             break;
01922         
01923         #ifdef fliowa
01924         
01925         case idcardprocessor:
01926             fl = cardedit (hv, hparent, fs, bstitle, rzoom);
01927             
01928             break;
01929         
01930         #endif
01931         
01932         } /*switch*/
01933     
01934     return (fl);
01935     } /*langexternaledit*/
01936 
01937     
01938 boolean langexternalsetreadonly (hdlexternalvariable hv, boolean flreadonly) {
01939     
01940     /*
01941     7.0b6 PBS: set the read-only flag for a window.
01942     Handles various outline types. If it's a wp-text window, it's an error.
01943     */
01944     
01945     hdlhashtable ht;
01946     hdltableformats hf;
01947     hdloutlinerecord ho;
01948     hdlmenurecord hm;
01949     boolean fl = true;
01950     
01951     switch ((**hv).id) {
01952         
01953         case idtableprocessor:
01954         
01955             ht = (hdlhashtable) (**hv).variabledata;
01956             hf = (**ht).hashtableformats;
01957             
01958             (**(**hf).houtline).flreadonly = flreadonly;
01959             
01960             break;
01961             
01962         case idoutlineprocessor:
01963         case idscriptprocessor:
01964             
01965             ho = (hdloutlinerecord) (**hv).variabledata;
01966             
01967             (**ho).flreadonly = flreadonly;
01968             
01969             break;
01970             
01971         case idmenuprocessor:
01972                 
01973             hm = (hdlmenurecord) (**hv).variabledata;
01974             
01975             (**(**hm).menuoutline).flreadonly = flreadonly;
01976             
01977             break;
01978         
01979         case idwordprocessor:
01980             
01981             if (flreadonly) {
01982             
01983                 fl = false;         
01984             
01985                 langerrormessage (BIGSTRING ("\x4b""Can't open as read-only because wp-text windows don't support this feature."));
01986                 } /*if*/
01987                 
01988             break;
01989 
01990         default:
01991         
01992             fl = false;
01993             
01994         } /*switch*/    
01995 
01996     return (fl);
01997     } /*langexternalsetreadonly*/
01998 
01999 
02000 boolean langexternalgetreadonly (hdlexternalvariable hv) {
02001     
02002     /*
02003     7.0b6 PBS: Return the read-only flag for a window.
02004     Handles various outline types. If it's a wp-text window, it's never read-only.
02005     */
02006     
02007     hdlhashtable ht;
02008     hdltableformats hf;
02009     hdloutlinerecord ho;
02010     hdlmenurecord hm;
02011     boolean flreadonly = true;
02012     
02013     switch ((**hv).id) {
02014         
02015         case idtableprocessor:
02016         
02017             ht = (hdlhashtable) (**hv).variabledata;
02018             hf = (**ht).hashtableformats;
02019             
02020             flreadonly = (**(**hf).houtline).flreadonly;
02021             
02022             break;
02023             
02024         case idoutlineprocessor:
02025         case idscriptprocessor:
02026             
02027             ho = (hdloutlinerecord) (**hv).variabledata;
02028             
02029             flreadonly = (**ho).flreadonly;
02030             
02031             break;
02032             
02033         case idmenuprocessor:
02034                 
02035             hm = (hdlmenurecord) (**hv).variabledata;
02036             
02037             flreadonly = (**(**hm).menuoutline).flreadonly;
02038             
02039             break;
02040         
02041         default: /*wp-text*/
02042         
02043             flreadonly = false;
02044             
02045             break;          
02046         } /*switch*/    
02047 
02048     return (flreadonly);
02049     } /*langexternalgetreadonly*/
02050 
02051 
02052 boolean langexternalzoomfrom (tyvaluerecord val, hdlhashtable htable, bigstring bsname, rectparam rzoom) {
02053     
02054     /*
02055     val represents an external variable, or it should.  the caller wants us to 
02056     zoom a window that displays the data linked into the external variable.
02057     
02058     10/3/90 DW: insert wire to editvalue.c.
02059     
02060     10/29/90 dmb: removed wire to editvalue.c (editing now done in tables)
02061     
02062     7/4/91 dmb: now take table parameter, locate the table if it nil, and get 
02063     the full path instead of having caller provide it.
02064     
02065     12/9/91 dmb: if variable is just being loaded into memory, force 
02066     table window to update row, if being displayed.
02067     */
02068     
02069     register hdlexternalvariable hv;
02070     bigstring bstitle;
02071     boolean flwasinmemory;
02072     hdlwindowinfo hparent;
02073     
02074     if (val.valuetype != externalvaluetype)
02075         return (false);
02076     
02077     hv = (hdlexternalvariable) val.data.externalvalue;
02078     
02079     if (htable == nil) { /*no table provided; we'll search for it*/
02080         
02081         if (!langexternalfindvariable (hv, &htable, bsname))
02082             return (false);
02083         }
02084     
02085     if (!langexternalgetfullpath (htable, bsname, bstitle, &hparent))
02086         return (false);
02087     
02088     flwasinmemory = (boolean) (**hv).flinmemory;
02089     
02090     if (!langexternaledit (hv, hparent, nil, bstitle, rzoom))
02091         return (false);
02092     
02093     if (!flwasinmemory) /*make table update row*/
02094         tablewindowclosed (hv);
02095     
02096     return (true);
02097     } /*langexternalzoomfrom*/
02098 
02099 
02100 boolean langexternalzoom (tyvaluerecord val, hdlhashtable htable, bigstring bsname) {
02101     
02102     /*
02103     7/4/91 dmb: we're now just a wrapper for langexternalzoomfrom, which 
02104     takes the zoom rect parameter.  a majority of callers just want the 
02105     default behavior
02106     */
02107     
02108     Rect rzoom;
02109     
02110     rzoom.top = -1; /*use default*/
02111     
02112     return (langexternalzoomfrom (val, htable, bsname, &rzoom));
02113     } /*langexternalzoom*/
02114 
02115 
02116 boolean langexternalzoomfilewindow (const tyvaluerecord *val, tyfilespec *fs, boolean flhidden) {
02117     
02118     /*
02119     create and open a new window containing the file-based external value in val.
02120     val should be in memory
02121     */
02122     
02123     register hdlexternalvariable hv;
02124     bigstring bstitle;
02125     Rect rzoom;
02126     
02127     hv = (hdlexternalvariable) (*val).data.externalvalue;
02128     
02129     assert ((**hv).flinmemory);
02130     
02131     if (flhidden)
02132         rzoom.top = -2; //zoom hidden
02133     else
02134         rzoom.top = -1; //use default
02135     
02136     if (fs != nil)
02137         getfsfile (fs, bstitle); //5.0b9 dmb: new routine
02138     else
02139         getuntitledfilename (bstitle);
02140     
02141     if (!langexternaledit (hv, nil, fs, bstitle, &rzoom))
02142         return (false);
02143     
02144     langexternalregisterwindow (hv);
02145     
02146     return (true);
02147     } /*langexternalzoomfilewindow*/
02148 
02149 
02150 boolean langexternalwindowopen (tyvaluerecord val, hdlwindowinfo *hinfo) {
02151     
02152     /*
02153     3/19/91 DW: add a parameter that returns a handle to the windowinfo record 
02154     if a window is open.  required modification to the routines in each of the
02155     external handlers.
02156     
02157     4/15/92 dmb: moved guts into langexternalvariablewindowopen
02158 
02159     5.0.1 dmb: for this higher-level funtion, don't return true if hinfo is nil
02160     */
02161     
02162     if (val.valuetype != externalvaluetype) /*non-externals can't have open windows*/
02163         return (false);
02164     
02165     if (!langexternalvariablewindowopen ((hdlexternalvariable) val.data.externalvalue, hinfo))
02166         return (false);
02167     
02168     return (*hinfo != nil);
02169     } /*langexternalwindowopen*/
02170 
02171 
02172 boolean langexternalwindowclosed (hdlexternalvariable hvariable) {
02173     
02174     /*
02175     the caller is telling us the the variable's window has just been closed
02176     */
02177     
02178     return (tablewindowclosed (hvariable));
02179     } /*langexternalwindowclosed*/
02180 
02181 
02182 boolean langexternaldisposevariable (hdlexternalvariable hvariable, boolean fldisk, boolean (*disposeroutine) (hdlexternalvariable, boolean)) {
02183     
02184     /*
02185     this code was factored from each EFP's xxxverbdispose routine.  most of the 
02186     routines called from langexternaldisposevalue below simple call this routine 
02187     with the address of a routine that knows how to dispose of the specific type.
02188     the entire variable is passed to the callback, rather than just the variabledata, 
02189     in case there are other flags or fields (like linkedcode in opverbs.c, or flpacked 
02190     in wpverbs.c) that are relevant to disposal
02191     
02192     6/10/92 dmb: inhibitclosedialogs when closing window during disposal
02193     
02194     6.17.97 dmb: with file windows, we can be called from their close routine. so we 
02195     must rely on langexternalwindowopen, not shellfinddatawindow
02196     
02197     5.0.1 dmb: test hinfo before using it to call shellclosewindow
02198     */
02199     
02200     register hdlexternalvariable hv = hvariable;
02201     hdlwindowinfo hinfo;
02202     dbaddress adr;
02203     boolean flwindowopen;
02204     hdldatabaserecord savedatabasedata = databasedata;
02205     
02206     flwindowopen = langexternalvariablewindowopen (hv, &hinfo);
02207     
02208     if (hinfo != nil) {
02209         
02210         langexternalunregisterwindow (hinfo);
02211         
02212         if (flwindowopen) {
02213             
02214             flinhibitclosedialogs = true;
02215             
02216             shellclosewindow ((**hinfo).macwindow);
02217             
02218             flinhibitclosedialogs = false;
02219             }
02220         }
02221     
02222     databasedata = (**hv).hdatabase;
02223 
02224     if ((**hv).flinmemory) {
02225         
02226         (*disposeroutine) (hv, fldisk);
02227 
02228         adr = (**hv).oldaddress;
02229         }
02230     else
02231         adr = (dbaddress) (**hv).variabledata;
02232     
02233     if (fldisk)
02234         dbpushreleasestack (adr, (long) (outlinevaluetype + (**hv).id));
02235     
02236     databasedata = savedatabasedata;
02237     
02238     disposehandle ((Handle) hv);
02239     
02240     return (true);
02241     } /*langexternaldisposevariable*/
02242 
02243 
02244 boolean langexternaldisposevalue (tyvaluerecord val, boolean fldisk) {
02245     
02246     register hdlexternalvariable hv;
02247     register boolean fl;
02248     
02249     if (val.valuetype != externalvaluetype)
02250         return (false);
02251     
02252     hv = (hdlexternalvariable) val.data.externalvalue; /*copy into register*/
02253     
02254     switch ((**hv).id) {
02255     
02256         case idtableprocessor:
02257             fl = tableverbdispose (hv, fldisk);
02258             
02259             break;
02260         
02261         case idoutlineprocessor: case idscriptprocessor:
02262             fl = opverbdispose (hv, fldisk);
02263             
02264             break;
02265         
02266         case idwordprocessor:
02267             fl = wpverbdispose (hv, fldisk);
02268             
02269             break;
02270         
02271         case idmenuprocessor:
02272             fl = menuverbdispose (hv, fldisk);
02273             
02274             break;
02275         
02276         case idpictprocessor:
02277             fl = pictverbdispose (hv, fldisk);
02278             
02279             break;
02280         
02281         #ifdef fliowa
02282         
02283         case idcardprocessor:
02284             fl = cardverbdispose (hv, fldisk);
02285             
02286             break;
02287         
02288         #endif
02289         
02290         default:
02291             fl = false;
02292         } /*switch*/
02293     
02294     return (fl);
02295     } /*langexternaldisposevalue*/
02296 
02297 
02298 static boolean updateconfigsettings (tyvaluetype type, short configid) {
02299     
02300     /*
02301     5.0d14 dmb: update the speicified config record according the the 
02302     user's preference settings in the database
02303     
02304     5.0d17 dmb: push/pop root table for expanding dotparams
02305     */
02306     
02307     bigstring bspref;
02308     byte bstype [16];
02309     bigstring bsfont;
02310     hdlhashtable htable;
02311     bigstring bs;
02312     tyvaluerecord val;
02313     short fontsize = 0;
02314     short ixconfig;
02315     hdlhashnode hnode;
02316     
02317     // build the path to the font pref
02318     getsystemtablescript (iduserfontprefscript, bspref);
02319     
02320     langgettypestring (type, bstype);
02321     
02322     setemptystring (bsfont);
02323     
02324     parsedialogstring (bspref, bstype, nil, nil, nil, bspref);
02325     
02326     disablelangerror ();
02327     
02328     pushhashtable (roottable);
02329     
02330     if (langexpandtodotparams (bspref, &htable, bs) && hashtablelookup (htable, bs, &val, &hnode)) {
02331         
02332         if (val.valuetype == stringvaluetype)
02333             pullstringvalue (&val, bsfont);
02334         }
02335     
02336     // build the path the the font size pref
02337     pushstring (BIGSTRING ("\x04Size"), bspref);
02338     
02339     if (langexpandtodotparams (bspref, &htable, bs) && hashtablelookup (htable, bs, &val, &hnode)) {
02340         
02341         if (val.valuetype == longvaluetype)
02342             fontsize = (short) val.data.longvalue;
02343         else if (val.valuetype == intvaluetype)
02344             fontsize = val.data.intvalue;
02345         }
02346     
02347     pophashtable ();
02348     
02349     enablelangerror ();
02350     
02351     // modify the config according to what we found
02352     if (!shellfindcallbacks (configid, &ixconfig))
02353         return (false);
02354     
02355     if (!isemptystring (bsfont))
02356         fontgetnumber (bsfont, &globalsarray [ixconfig].config.defaultfont);
02357     
02358     if (fontsize > 0)
02359         globalsarray [ixconfig].config.defaultsize = fontsize;
02360     
02361     return (true);
02362     } /*updateconfigsettings*/
02363 
02364 
02365 boolean langexternalgetconfig (tyvaluetype type, short configid, tyconfigrecord *pconfig) {
02366     
02367     /*
02368     5.0b9 dmb: expose functionality so user prefs hold in all contexts,
02369     not just creating new objects
02370     */
02371     
02372     static boolean fltryingtoupdate = false; // ovoid reentrancy, which would be infinite
02373     
02374     if (!fltryingtoupdate && roottable != nil) {
02375         
02376         fltryingtoupdate = true;
02377         
02378         updateconfigsettings (type, configid);
02379         
02380         fltryingtoupdate = false;
02381         }
02382 
02383     return (shellgetconfig (configid, pconfig));
02384     } /*langexternalgetconfig*/
02385 
02386 
02387 boolean langexternalnewvalue (tyexternalid id, Handle hdata, tyvaluerecord *val) {
02388     
02389     /*
02390     9/6/91 dmb: added hdata parameter for type-specific starter data
02391     
02392     5.0d14 dmb: use new updateconfigsettings so we always respect the user's 
02393     font/size preference settings.
02394     */
02395     
02396     hdlexternalvariable hvariable;
02397     register boolean fl;
02398     
02399     switch (id) {
02400     
02401         case idtableprocessor:
02402             updateconfigsettings (tablevaluetype, idtableconfig);
02403             
02404             fl = tableverbnew (&hvariable);
02405             
02406             break;
02407         
02408         case idoutlineprocessor:
02409             updateconfigsettings (outlinevaluetype, idoutlineconfig);
02410             
02411             fl = opverbnew (idoutlineprocessor, hdata, &hvariable);
02412             
02413             break;
02414         
02415         case idscriptprocessor:
02416             updateconfigsettings (scriptvaluetype, idscriptconfig);
02417             
02418             fl = opverbnew (idscriptprocessor, hdata, &hvariable);
02419             
02420             break;
02421         
02422         case idwordprocessor:
02423             updateconfigsettings (wordvaluetype, idwpconfig);
02424             
02425             fl = wpverbnew (hdata, &hvariable);
02426             
02427             break;
02428         
02429         case idmenuprocessor:
02430             updateconfigsettings (menuvaluetype, idmenueditorconfig);
02431             
02432             fl = menuverbnew (hdata, &hvariable);
02433             
02434             break;
02435         
02436         case idpictprocessor:
02437             updateconfigsettings (pictvaluetype, idpictconfig);
02438             
02439             fl = pictverbnew (hdata, &hvariable);
02440             
02441             break;
02442         
02443         #ifdef fliowa
02444         
02445         case idcardprocessor:
02446             updateconfigsettings (cardvaluetype, idiowaconfig);
02447             
02448             fl = cardverbnew (hdata, &hvariable);
02449             
02450             break;
02451         
02452         #endif
02453         
02454         default:
02455             fl = false;
02456         } /*switch*/
02457     
02458     if (!fl)
02459         return (false);
02460     
02461     (**hvariable).id = id;
02462     
02463     setexternalvalue ((Handle) hvariable, val);
02464     
02465     return (true);
02466     } /*langexternalnewvalue*/
02467 
02468 
02469 boolean langexternalvaltocode (tyvaluerecord val, hdltreenode *hcode) {
02470     
02471     register hdlexternalvariable hv;
02472     
02473     if (val.valuetype != externalvaluetype) 
02474         return (false);
02475     
02476     hv = (hdlexternalvariable) val.data.externalvalue;
02477     
02478     if ((**hv).id != idscriptprocessor) 
02479         return (false);
02480     
02481     opverbgetlinkedcode (hv, hcode);
02482     
02483     return (true); /*return true even if *hcode is nil*/
02484     } /*langexternalvaltocode*/
02485 
02486 
02487 boolean langexternalgetvalsize (tyvaluerecord val, long *size) {
02488     
02489     register hdlexternalvariable hv;
02490     
02491     if (val.valuetype != externalvaluetype)
02492         return (false);
02493     
02494     hv = (hdlexternalvariable) val.data.externalvalue; /*copy into register*/
02495     
02496     switch ((**hv).id) {
02497     
02498         case idoutlineprocessor: case idscriptprocessor:
02499             return (opverbgetsize (hv, size));
02500         
02501         case idwordprocessor:
02502             return (wpverbgetsize (hv, size));
02503         
02504         case idtableprocessor:
02505             return (tableverbgetsize (hv, size));
02506         
02507         case idmenuprocessor:
02508             return (menuverbgetsize (hv, size));
02509         
02510         case idpictprocessor:
02511             return (pictverbgetsize (hv, size));
02512         
02513         #ifdef fliowa
02514         
02515         case idcardprocessor:
02516             return (cardverbgetsize (hv, size));
02517         
02518         #endif
02519         
02520         default:
02521             return (false);
02522         } /*switch*/
02523     } /*langexternalgetvalsize*/
02524 
02525 
02526 boolean langnewexternalvariable (boolean flinmemory, long variabledata, hdlexternalvariable *h) {
02527     
02528     tyexternalvariable item;
02529     
02530     clearbytes (&item, sizeof (item));
02531     
02532     item.flinmemory = flinmemory;
02533     
02534     item.variabledata = variabledata;
02535 
02536     item.hdatabase = databasedata; // 5.0a18 dmb
02537     
02538     //item.hexternaltable = nil;
02539     //copystring (emptystring, item.bsexternalname);
02540     
02541     return (newfilledhandle (&item, sizeof (item), (Handle *) h));
02542     } /*langnewexternalvariable*/
02543 
02544 
02545 static short getsortweight (tyexternalid type) {
02546     
02547     /*
02548     the lightest types float to the the top of a sorted list.
02549     */
02550     
02551     register short w = 0;
02552     
02553     switch (type) {
02554     
02555         case idtableprocessor: 
02556             w = 0; break;
02557         
02558         case idscriptprocessor:
02559             w = 1; break;
02560         
02561         case idwordprocessor:
02562             w = 2; break;
02563         
02564         case idpictprocessor:
02565             w = 3; break;
02566         
02567         case idoutlineprocessor:
02568             w = 4; break;
02569         
02570         case idmenuprocessor:
02571             w = 5; break;
02572         
02573         case idheadrecord:
02574             w = 6; break;
02575         
02576         case idcardprocessor:
02577             w = 7; break;
02578         
02579         default:
02580             w = infinity; break;
02581         } /*switch*/
02582     
02583     return (w);
02584     } /*getsortweight*/
02585 
02586 
02587 short langexternalcomparetypes (tyexternalid type1, tyexternalid type2) {
02588     
02589     /*
02590     support for the table editor's view-by-kind sort order.  if type1 is less than
02591     type2 return true.
02592     
02593     3/31/93 dmb: return signed value, not boolean
02594     */
02595     
02596     register short w1, w2;
02597     
02598     w1 = getsortweight (type1);
02599     
02600     w2 = getsortweight (type2);
02601     
02602     return (sgn (w1 - w2));
02603     } /*langexternalcomparetypes*/
02604 
02605 
02606 boolean langexternalsurfacekey (hdlexternalvariable hv) {
02607     
02608     /*
02609     5.0b18 dmb: for win, use cmd-backspace. can't get the mac combo
02610     */
02611 
02612     if (keyboardstatus.chkb == chenter) {
02613         
02614         if (keyboardstatus.flcmdkey && keyboardstatus.flshiftkey) {
02615         
02616             tableclientsurface (hv);
02617             
02618             return (true);
02619             }
02620         }
02621     
02622     #ifdef WIN95VERSION
02623         if (keyboardstatus.chkb == chbackspace) {
02624             
02625             if (keyboardstatus.flshiftkey) {
02626             
02627                 tableclientsurface (hv);
02628                 
02629                 return (true);
02630                 }
02631             }
02632     #endif
02633 
02634     return (false); /*keystroke not handled*/
02635     } /*langexternalsurfacekey*/
02636 
02637 
02638 boolean langexternalpacktotext (hdlexternalhandle h, Handle htext) {
02639     
02640     /*
02641     9/11/92 dmb: call rollbeachball
02642     */
02643     
02644     register hdlexternalvariable hdata = (hdlexternalvariable) h;
02645     
02646     rollbeachball ();
02647     
02648     switch ((**hdata).id) {
02649         
02650         case idoutlineprocessor: case idscriptprocessor:
02651             return (opverbpacktotext (hdata, htext));
02652         
02653         case idwordprocessor:
02654             return (wpverbpacktotext (hdata, htext));
02655         
02656         case idtableprocessor:
02657             return (tableverbpacktotext (hdata, htext));
02658         
02659         case idmenuprocessor:
02660             return (menuverbpacktotext (hdata, htext));
02661         
02662         case idpictprocessor:
02663             return (pictverbpacktotext (hdata, htext));
02664         
02665         #ifdef fliowa
02666         
02667         case idcardprocessor:
02668             return (cardverbpacktotext (hdata, htext));
02669         
02670         #endif
02671         
02672         default:
02673             return (false);
02674         } /*switch*/
02675     } /*langexternalpacktotext*/
02676 
02677 
02678 boolean langexternalsearch (tyvaluerecord val, boolean *flzoom) {
02679     
02680     /*
02681     search the valuerecord according to the current search parameters.  by 
02682     default, we also tell caller to zoom to the value if it contains a 
02683     match, but that can be overridden by each find routine if desired
02684     
02685     4.0.2b1 dmb: give the user a chance to abort by backgroundtasking.
02686     */
02687     
02688     register hdlexternalvariable hv;
02689     boolean fl;
02690     
02691     if (val.valuetype != externalvaluetype) /*non-externals can't be searched*/
02692         return (false);
02693     
02694     if (flscriptrunning)
02695         fl = langbackgroundtask (false);
02696     else
02697         fl = shellbackgroundtask ();
02698     
02699     if (!fl)
02700         return (false);
02701     
02702     *flzoom = true; /*default*/
02703     
02704     hv = (hdlexternalvariable) val.data.externalvalue;
02705     
02706     switch ((**hv).id) {
02707         
02708         case idoutlineprocessor: case idscriptprocessor:
02709             return (opverbfind (hv, flzoom));
02710         
02711         case idwordprocessor:
02712             return (wpverbfind (hv, flzoom));
02713         
02714         case idtableprocessor:
02715             return (tableverbfind (hv, flzoom));
02716         
02717         case idmenuprocessor:
02718             return (menuverbfind (hv, flzoom));
02719         
02720         case idpictprocessor:
02721             return (pictverbfind (hv, flzoom));
02722         
02723         #ifdef fliowa
02724         
02725         case idcardprocessor:
02726             return (cardverbfind (hv, flzoom));
02727         
02728         #endif
02729         
02730         default:
02731             return (false);
02732         } /*switch*/
02733     } /*langexternalsearch*/
02734 
02735 
02736 boolean langexternalcontinuesearch (hdlexternalvariable hvariable) {
02737     
02738     /*
02739     the caller just finished searching hvariable without finding a match.
02740     
02741     we'll call a table routine to continue the search from the variable's
02742     parent table
02743     */
02744     
02745     return (tableverbcontinuesearch (hvariable));
02746     } /*langexternalcontinuesearch*/
02747 
02748 
02749 boolean langexternalgettimes (hdlexternalhandle h, long *timecreated, long *timemodified, hdlhashnode hnode) {
02750     
02751     register hdlexternalvariable hdata = (hdlexternalvariable) h;
02752     
02753     switch ((**hdata).id) {
02754         
02755         case idoutlineprocessor: case idscriptprocessor:
02756             return (opverbgettimes (hdata, timecreated, timemodified));
02757         
02758         case idwordprocessor:
02759             return (wpverbgettimes (hdata, timecreated, timemodified));
02760         
02761         case idtableprocessor:
02762             return (tableverbgettimes (hdata, timecreated, timemodified, hnode));
02763         
02764         case idmenuprocessor:
02765             return (menuverbgettimes (hdata, timecreated, timemodified));
02766         
02767         case idpictprocessor:
02768             return (pictverbgettimes (hdata, timecreated, timemodified));
02769         
02770         #ifdef fliowa
02771         
02772         case idcardprocessor:
02773             return (cardverbgettimes (hdata, timecreated, timemodified));
02774         
02775         #endif
02776         
02777         default:
02778             return (false);
02779         } /*switch*/
02780     } /*langexternalgettimes*/
02781 
02782 
02783 boolean langexternalsettimes (hdlexternalhandle h, long timecreated, long timemodified, hdlhashnode hnode) {
02784     
02785     register hdlexternalvariable hdata = (hdlexternalvariable) h;
02786     
02787     if (!langexternalsetdirty (h, true))
02788         return (false);
02789     
02790     switch ((**hdata).id) {
02791         
02792         case idoutlineprocessor: case idscriptprocessor:
02793             return (opverbsettimes (hdata, timecreated, timemodified));
02794         
02795         case idwordprocessor:
02796             return (wpverbsettimes (hdata, timecreated, timemodified));
02797         
02798         case idtableprocessor:
02799             return (tableverbsettimes (hdata, timecreated, timemodified, hnode));
02800         
02801         case idmenuprocessor:
02802             return (menuverbsettimes (hdata, timecreated, timemodified));
02803         
02804         case idpictprocessor:
02805             return (pictverbsettimes (hdata, timecreated, timemodified));
02806         
02807         #ifdef fliowa
02808         
02809         case idcardprocessor:
02810             return (cardverbsettimes (hdata, timecreated, timemodified));
02811         
02812         #endif
02813         
02814         default:
02815             return (false);
02816         } /*switch*/
02817     } /*langexternalsettimes*/
02818 
02819 
02820 boolean langexternalfindusedblocks (hdlexternalhandle h, bigstring bspath) {
02821     
02822     /*
02823     this being a debuging routine, the implementation isn't as general 
02824     as the verbs.  see dbstats.c
02825     
02826     7/8/91 dmb: roll the beach ball
02827     */
02828     
02829     register hdlexternalvariable hv = (hdlexternalvariable) h;
02830     boolean fl;
02831     
02832     rollbeachball ();
02833     
02834     switch ((**hv).id) {
02835         
02836         case idtableprocessor:
02837             return (tableverbfindusedblocks (hv, bspath));
02838         
02839         case idmenuprocessor:
02840             return (menuverbfindusedblocks (hv, bspath));
02841         
02842         default:
02843             if ((**hv).flinmemory)
02844                 fl = statsblockinuse ((**hv).oldaddress, bspath);
02845             else
02846                 fl = statsblockinuse ((dbaddress) (**hv).variabledata, bspath);
02847             
02848             return (fl);
02849         } /*switch*/
02850     } /*langexternalfindusedblocks*/
02851 
02852 
02853 boolean langexternaltitleclick (Point pt, hdlexternalvariable hv) {
02854     
02855     /*
02856     return true if we consume the click
02857     */
02858     
02859     if (cmdkeydown () || ismouserightclick()) {
02860         
02861         tableclienttitlepopuphit (pt, hv);
02862         
02863         return (true);
02864         }
02865     
02866     if (!mousedoubleclick ())
02867         return (false);
02868     
02869     tableclientsurface (hv);
02870     
02871     return (true); /*consumed*/
02872     } /*langexternaltitleclick*/
02873 
02874 
02875 OSType langexternalgettypeid (tyvaluerecord val) {
02876     
02877     register tyvaluetype type = val.valuetype;
02878     
02879     if (type == externalvaluetype)
02880         type = (tyvaluetype) (outlinevaluetype + langexternalgettype (val));
02881     
02882     return (langgettypeid (type));
02883     } /*langexternalgettypeid*/
02884 
02885 
02886 tyvaluetype langexternalgetvaluetype (OSType typeid) {
02887     
02888     register tyvaluetype type = langgetvaluetype (typeid);
02889     
02890     if (type >= outlinevaluetype)
02891         type = externalvaluetype;
02892     
02893     return (type);
02894     } /*langexternalgetvaluetype*/
02895 
02896 
02897 boolean langexternalrefdata (hdlexternalvariable hv, Handle *hdata) {
02898     
02899     boolean fl;
02900     
02901     assert (!(**hv).flinmemory);
02902     
02903     dbpushdatabase ((**hv).hdatabase);
02904     
02905     fl = dbrefhandle ((dbaddress) (**hv).variabledata, hdata);
02906     
02907     dbpopdatabase ();
02908     
02909     return (fl);
02910     } /*langexternalrefdata*/
02911 
02912 
02913 boolean langexternalsymbolchanged (hdlhashtable htable, const bigstring bsname, hdlhashnode hnode, boolean flvalue) {
02914 #pragma unused(flvalue)
02915 
02916     return langexternalsymbolinserted (htable, bsname, hnode);
02917     } /*langexternalsymbolchanged*/
02918 
02919 
02920 boolean langexternalsymbolinserted (hdlhashtable htable, const bigstring bsname, hdlhashnode hnode) {
02921 #if !langexternalfind_optimization
02922 #   pragma unused (htable, bsname, hnode)
02923 #endif
02924 
02925 #if langexternalfind_optimization
02926     if (    hnode != nil
02927          && hnode != HNoNode
02928          && (**hnode).val.valuetype == externalvaluetype) {
02929         
02930             hdlexternalvariable hv = (hdlexternalvariable) (**hnode).val.data.externalvalue;
02931 
02932             (**hv).hexternaltable = htable;
02933 
02934             (**hv).hexternalnode = hnode;
02935             }
02936     #endif
02937 
02938     return true;
02939     } /*langexternalsymbolinserted*/
02940 
02941 

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