tableexternal.c

Go to the documentation of this file.
00001 
00002 /*  $Id: tableexternal.c 1254 2006-04-12 20:27:14Z 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 "file.h"
00032 #include "kb.h"
00033 #include "memory.h"
00034 #include "ops.h"
00035 #include "quickdraw.h"
00036 #include "resources.h"
00037 #include "strings.h"
00038 #include "shell.h"
00039 #include "shellprivate.h"
00040 #include "shellundo.h"
00041 #include "langinternal.h"
00042 #include "langexternal.h"
00043 #include "opinternal.h"
00044 #include "tablestructure.h"
00045 #include "tableinternal.h"
00046 #include "tableverbs.h"
00047 #include "wpengine.h"
00048 #include "claybrowser.h"
00049 #include "claybrowserstruc.h"
00050 #include "claycallbacks.h"
00051 #include "cancoon.h"
00052 
00053 
00054 
00055 
00056 boolean tablevaltotable (tyvaluerecord val, hdlhashtable *htable, hdlhashnode hnode) {
00057     
00058     /*
00059     called externally -- you give us a value that holds an external value that's
00060     a tableprocessor variable, we'll return you a handle to the hashtable.
00061     */
00062     
00063     hdltablevariable hvariable;
00064     short errorcode;
00065     
00066     if (!gettablevariable (val, &hvariable, &errorcode))
00067         return (false);
00068     
00069     if (!tableverbinmemory ((hdlexternalvariable) hvariable, hnode))
00070         return (false);
00071     
00072     *htable = (hdlhashtable) (**hvariable).variabledata;
00073     
00074     return (true);
00075     } /*tablevaltotable*/
00076 
00077 
00078 boolean tablewindowopen (hdlexternalvariable hvariable, hdlwindowinfo *hinfo) {
00079     
00080     /*
00081     5.0.1 dmb: if tableformats are nil, don't call shellfinddatawindow
00082     */
00083 
00084     register hdltablevariable hv = (hdltablevariable) hvariable;
00085     register hdlhashtable ht;
00086     hdltableformats hf;
00087 
00088     
00089     if (!(**hv).flinmemory)
00090         return (false);
00091     
00092     ht = (hdlhashtable) (**hv).variabledata;
00093     
00094     hf = (**ht).hashtableformats;
00095     
00096     if (hf != nil)
00097         shellfinddatawindow ((Handle) hf, hinfo); /*3/19/91 DW*/
00098     
00099     return ((**ht).flwindowopen);
00100     } /*tablewindowopen*/
00101 
00102 
00103 boolean tableverbgetdisplaystring (hdlexternalvariable h, bigstring bs) {
00104     
00105     /*
00106     get string for table display.  variable is in memory.
00107     
00108     called from langexternal.c.
00109     */
00110     
00111     register hdltablevariable hv = (hdltablevariable) h;
00112     register hdlhashtable ht;
00113     long ctitems;
00114     
00115     ht = (hdlhashtable) (**hv).variabledata;
00116     
00117     hashcountitems (ht, &ctitems);
00118     
00119     parsenumberstring (tablestringlist, tablesizestring, ctitems, bs);
00120     
00121     return (true);
00122     } /*tableverbgetdisplaystring*/
00123 
00124 
00125 boolean tableverbgettypestring (hdlexternalvariable hvariable, bigstring bs) {
00126     
00127     register hdltablevariable hv = (hdltablevariable) hvariable;
00128     short id;
00129     
00130     if ((**hv).flsystemtable)
00131         id = systemtabletypestring;
00132     else {
00133 
00134         #ifdef xmlfeatures
00135             if ((**hv).flxml)
00136                 id = xmltypestring;
00137             else
00138         #endif
00139 
00140             id = tabletypestring;
00141         }
00142     
00143     tablegetstringlist (id, bs);
00144     
00145     return (true); /*dirty status display wired off, too noisy*/
00146     } /*tableverbgettypestring*/
00147 
00148 
00149 static boolean tabledisposevariable (hdlexternalvariable hvariable, boolean fldisk) {
00150     
00151     register hdltablevariable hv = (hdltablevariable) hvariable;
00152     
00153     tabledisposetable ((hdlhashtable) (**hv).variabledata, fldisk);
00154     
00155     return (true);
00156     } /*tabledisposevariable*/
00157 
00158 
00159 boolean tableverbdispose (hdlexternalvariable hvariable, boolean fldisk) {
00160     
00161     /*
00162     1/25/91 dmb: special-case local tables; they're the only kind of 
00163     system table that can be thrown out.  we might be able to get rid 
00164     of this dirtyness after we support locked tables
00165     
00166     12/22/91 dmb: in order to release all db nodes properly, must force 
00167     table to be loaded into memory when fldisk is true
00168     */
00169     
00170     register hdltablevariable hv = (hdltablevariable) hvariable;
00171     register hdlhashtable ht;
00172     
00173     if (fldisk) { /*load table into memory so that all items can release their db nodes*/
00174         
00175         if (!tableverbinmemory ((hdlexternalvariable) hv, HNoNode))
00176             return (false);
00177         }
00178     
00179     if ((**hv).flinmemory) {
00180         
00181         ht = (hdlhashtable) (**hv).variabledata;
00182         
00183         #if (MEMTRACKER == 1)
00184             if (internaltable != nil) // not tossing everything
00185         #endif
00186 
00187         if ((**hv).flsystemtable && !(**ht).fllocaltable)
00188             return (true);
00189         }
00190     
00191     langexternaldisposevariable ((hdlexternalvariable) hv, fldisk, &tabledisposevariable);
00192     
00193     return (true);
00194     } /*tableverbdispose*/
00195 
00196 
00197 boolean tableverbnew (hdlexternalvariable *hvariable) {
00198     
00199     hdlhashtable hnewtable;
00200     
00201     return (tablenewtable ((hdltablevariable *) hvariable, &hnewtable));
00202     } /*tableverbnew*/
00203 
00204 
00205 boolean tableverbinmemory (hdlexternalvariable hvariable, hdlhashnode hnode) {
00206     
00207     /*
00208     5.0a18 dmb: support database linking
00209     */
00210     
00211     register hdltablevariable hv = (hdltablevariable) hvariable;
00212     Handle hpacked;
00213     hdlhashtable htable = nil;
00214     dbaddress adr;
00215     langerrormessagecallback savecallback;
00216     ptrvoid saverefcon;
00217     hdlhashtable hparent;
00218     bigstring bspath, bsunpackerror;
00219     boolean fl;
00220     
00221     if ((**hv).flinmemory) /*nothing to do, it's already in memory*/
00222         return (true);
00223     
00224     if ((hnode == nil) || (hnode == HNoNode))
00225         hnode = nil;
00226 
00227     dbpushdatabase ((**hv).hdatabase);
00228 
00229     adr = (dbaddress) (**hv).variabledata;
00230     
00231     if (adr == nildbaddress) { /*table has never been allocated*/
00232         
00233         shellinternalerror (idniltableaddress, BIGSTRING ("\x2b" "nil table address.  (Creating empty table.)"));
00234         
00235         fl = false;
00236         }
00237     else {
00238         
00239         fl = dbrefhandle (adr, &hpacked);
00240         
00241         if (fl) {
00242             
00243             langtraperrors (bsunpackerror, &savecallback, &saverefcon);
00244             
00245             fl = tableunpacktable (hpacked, false, &htable); /*always disposes of hpackedtable*/
00246             
00247             languntraperrors (savecallback, saverefcon, !fl);
00248             
00249             if (!fl) {
00250                 
00251                 fllangerror = false;
00252                 
00253                 if (langexternalfindvariable ((hdlexternalvariable) hv, &hparent, bspath) &&
00254                     langexternalgetfullpath (hparent, bspath, bspath, nil)) {
00255                     
00256                     poptrailingchars (bsunpackerror, '.');
00257                     
00258                     lang2paramerror (tableloadingerror, bspath, bsunpackerror);
00259                     }
00260                 else
00261                     langerrormessage (bsunpackerror);
00262                 }
00263             }
00264         }
00265     
00266     dbpopdatabase ();
00267 
00268     if (!fl)
00269         return (false);
00270     
00271     (**hv).flinmemory = true;
00272     
00273     (**hv).variabledata = (long) htable; /*link into variable structure*/
00274     
00275     (**hv).oldaddress = adr; /*last place this table was stored*/
00276     
00277     if ((**hv).flmayaffectdisplay)
00278         (**htable).flmayaffectdisplay = true;
00279     
00280     #ifdef xmlfeatures
00281         (**htable).flxml = (**hv).flxml; //5.0.1
00282     #endif
00283 
00284     (**htable).hashtablerefcon = (long) hv; /*we can get from hashtable to variable rec*/
00285 
00286     (**htable).thistableshashnode = hnode; /*The var rec is contained in the hashnode... RAB 1/3/00 */
00287     
00288     return (true);
00289     } /*tableverbinmemory*/
00290     
00291 
00292 boolean tableverbgetsize (hdlexternalvariable hvariable, long *size) {
00293     
00294     register hdlexternalvariable hv = hvariable;
00295     long ctitems;
00296     
00297     if (!tableverbinmemory (hv, HNoNode))
00298         return (false);
00299         
00300     hashcountitems ((hdlhashtable) (**hv).variabledata, &ctitems);
00301     
00302     *size = (long) ctitems;
00303     
00304     return (true);
00305     } /*tableverbgetsize*/
00306     
00307 
00308 boolean tableverbisdirty (hdlexternalvariable hvariable) {
00309     
00310     /*
00311     8/11/92 dmb: check windowrect now to ensure consistent results
00312     */
00313     
00314     register hdltablevariable hv = (hdltablevariable) hvariable;
00315     register hdlhashtable ht;
00316     
00317     if (!(**hv).flinmemory)
00318         return (false);
00319     
00320     ht = (hdlhashtable) (**hv).variabledata;
00321     
00322     tablecheckwindowrect (ht);
00323     
00324     return ((**ht).fldirty);
00325     } /*tableverbisdirty*/
00326 
00327 
00328 boolean tableverbsetdirty (hdlexternalvariable hvariable, boolean fldirty) {
00329     
00330     /*
00331     4/15/92 dmb: see comments in langexternalsetdirty.  also note that when the table 
00332     is being set as clean, its may still be dirty.
00333     */
00334     
00335     register hdltablevariable hv = (hdltablevariable) hvariable;
00336     
00337     if (!tableverbinmemory ((hdlexternalvariable) hv, HNoNode))
00338         return (false);
00339     
00340     (**(hdlhashtable) (**hv).variabledata).fldirty = fldirty;
00341     
00342     return (true);
00343     } /*tableverbsetdirty*/
00344 
00345 
00346 boolean tableresetformatsrects (void) {
00347     
00348     /*
00349     2/14/97 dmb: rewrite for outline editor
00350 
00351     6.0b3 dmb: need to set display default before calcing tablerect; also
00352     inset based on gray3Dlook
00353     */
00354     
00355     hdloutlinerecord ho = (**tableformatsdata).houtline;
00356     Rect r;
00357     
00358     oppushoutline (ho);
00359     
00360     opsetdisplaydefaults (ho);
00361 
00362     windowresetrects (tableformatswindowinfo);
00363     
00364     tablerecalccolwidths (false); /*re-distribute colwidths*/
00365     
00366     r = (**tableformatsdata).tablerect;
00367     
00368     #ifdef gray3Dlook
00369         insetrect (&r, -2, -2);
00370     #else
00371         insetrect (&r, 1, 1);
00372     #endif
00373 
00374     opresize (r);
00375     
00376     oppopoutline ();
00377     
00378     return (true);
00379     } /*tableresetformatsrects*/
00380 
00381 
00382 boolean tableverbsetupdisplay (hdlhashtable htable, hdlwindowinfo hinfo) {
00383     
00384     /*
00385     6/21/92 dmb: when creating formats for a locals table, use the 
00386     default script font/size instead of the table config's.
00387     */
00388     
00389     register hdlhashtable ht = htable;
00390     hdltableformats hf;
00391     Rect r;
00392     
00393     hf = (**ht).hashtableformats;
00394     
00395     if (hf == nil) { /*this guy has never been edited, create a formats record for him*/
00396         
00397         r = (**hinfo).contentrect;
00398         
00399         if (!tablenewformatsrecord (ht, r, &hf))
00400             return (false);
00401         
00402         if ((**ht).fllocaltable || ht == runtimestacktable) { /*use default script font/size for locals tables*/
00403             
00404             tyconfigrecord lconfig;
00405             
00406             shellgetconfig (idscriptconfig, &lconfig);
00407             
00408             (**hf).fontnum = lconfig.defaultfont;
00409             
00410             (**hf).fontsize = lconfig.defaultsize;
00411             
00412             (**hf).fontstyle = lconfig.defaultstyle;
00413             }
00414         }
00415     
00416     (**hinfo).hdata = (Handle) hf; /*link to windowinfo*/
00417     
00418     if (!tableprepareoutline (hf))
00419         return (false);
00420     
00421     shellpushglobals ((**hinfo).macwindow);
00422     
00423     tableresetformatsrects ();
00424     
00425     shellpopglobals ();
00426     
00427     return (true); 
00428     } /*tableverbsetupdisplay*/
00429 
00430 
00431 boolean tableedit (hdlexternalvariable hvariable, hdlwindowinfo hparent, ptrfilespec fs, bigstring bs, rectparam rzoom) {
00432     
00433     /*
00434     3/30/93 dmb: don't resort the table before zooming. not sure why this 
00435     was ever necessary, but it sure is slow for large tables
00436     */
00437     
00438     register hdltablevariable hv = (hdltablevariable) hvariable;
00439     register hdlhashtable ht;
00440     register hdltableformats hf;
00441     Rect rwindow;
00442     hdlhashtable hparenttable;
00443     bigstring bsname;
00444     WindowPtr w;
00445     hdlwindowinfo hi;
00446     
00447     if (!tableverbinmemory ((hdlexternalvariable) hv, HNoNode)) /*couldn't swap it into memory*/
00448         return (false);
00449     
00450     ht = (hdlhashtable) (**hv).variabledata;
00451     
00452     if (tablefindvariable ((hdlexternalvariable) hv, &hparenttable, bsname))
00453         (**ht).parenthashtable = hparenttable;
00454     
00455     if (tablewindowopen ((hdlexternalvariable) hv, &hi)) { /*bring to front, return true*/
00456         
00457         if ((*rzoom).top > -2)
00458             shellbringtofront (hi);
00459         
00460         return (true);
00461         }
00462     
00463     hf = (**ht).hashtableformats;
00464     
00465     if (hf == nil)
00466         rwindow.top = -1; /*accept default*/
00467     else
00468         rwindow = (**hf).windowrect;
00469     
00470     if (!newchildwindow (idtableconfig, hparent, &rwindow, rzoom, bs, &w))
00471         return (false);
00472     
00473     getwindowinfo (w, &hi);
00474     
00475     if (fs != nil)
00476         (**hi).fspec = *fs;
00477     
00478     if (!tableverbsetupdisplay (ht, hi)) {
00479         
00480         /*xxx -- must get rid of the window!%/
00481         
00482         return (false);
00483         */
00484         }
00485     
00486     hf = (**ht).hashtableformats;
00487     
00488     //if ((**hf).flneedresort)
00489     //  hashresort (ht, nil); /*sort the table before zooming*/
00490     
00491     if ((**ht).fldirty)
00492         shellsetwindowchanges (hi, true);
00493     
00494     (**ht).flwindowopen = true;
00495     
00496     (**(**hf).houtline).flwindowopen = true;
00497     
00498     #if TARGET_API_MAC_CARBON == 1
00499     
00500         SetWindowProxyCreatorAndType (w, 'LAND', 'FTtb', kOnSystemDisk);
00501     
00502     #endif
00503     
00504     windowzoom (w);
00505     
00506     #if TARGET_API_MAC_CARBON == 1
00507     
00508         shellupdatewindow (w);  
00509     
00510     #endif
00511     
00512     return (true);
00513     } /*tableedit*/
00514 
00515 
00516 boolean tablewindowclosed (hdlexternalvariable hvariable) {
00517     
00518     /*
00519     the table manager needs to be informed when a window holding an external is
00520     closed.  this path was created (11/15/90 DW) so that the icon can be updated. in 
00521     the future it may be used for other good things.
00522     
00523     12/9/91 dmb: inval entire row, not just icon, so "on disk" can be updated
00524 
00525     5.0b18 dmb: don't call symbolchanged if a table is being closed,
00526     or it will cause it to be collapsed in other views
00527     */
00528     
00529     hdlhashtable htable;
00530     bigstring bsname;
00531     
00532     if (!tablefindvariable (hvariable, &htable, bsname))
00533         return (false);
00534     
00535     if (htable == nil) // was the hdlrootvariable; not in another table
00536         return (true);
00537     
00538     if (istablevariable (hvariable))
00539         return (true);
00540 
00541     return (tablesymbolchanged (htable, bsname, nil, true));
00542     
00543     /*
00544     if (!tablepushglobals (htable)) // parent table isn't open, no updating needed
00545         return (true);
00546     
00547     fl = hashsortedsearch (htable, bsname, &row);
00548     
00549     if (fl)
00550         tableinvalrow (row);
00551     
00552     shellpopglobals (); // undo the call to tablepushglobals
00553     */
00554     
00555     } /*tablewindowclosed*/
00556     
00557     
00558 boolean tabledive (void) {
00559     
00560     /*
00561     bigstring bs;
00562     tyvaluerecord val;
00563     */
00564     hdlheadrecord hcursor = (**outlinedata).hbarcursor;
00565     
00566     if (opeditingtext (hcursor)) { //((**tableformatsdata).fleditingcell)
00567         
00568         if (opsettextmode (false)) // if (tableexiteditmode ())
00569             opupdatenow ();
00570         else
00571             return (false);
00572         }
00573     
00574     tablezoomfromhead (hcursor);
00575     
00576     return (true);
00577     } /*tabledive*/
00578 
00579 
00580 boolean tableclientsurface (hdlexternalvariable hvariable) {
00581     
00582     /*
00583     surface for one of the clients -- like the pict editor, script editor, etc.
00584     
00585     we do an exhaustive search for a table entry of external type, of no 
00586     specific sub-type, that points to the indicated variable.
00587     
00588     1/9/91 dmb: see comment in tablebringtofront about not setting globals 
00589     without a push and pop.
00590     
00591     5.0.2b21 dmb: don't surface if parent is the file windows table
00592     */
00593     
00594     hdlhashtable htable;
00595     bigstring bsname;
00596     
00597     if (!tablefindvariable (hvariable, &htable, bsname))
00598         return (false);
00599     
00600     if (htable == filewindowtable)
00601         return (false);
00602     
00603     if (!tablezoomtoname (htable, bsname))
00604         return (false);
00605     
00606     if (keyboardstatus.floptionkey)
00607         shellclosewindow (shellwindow);
00608     
00609     return (true);
00610     } /*tableclientsurface*/
00611 
00612 
00613 boolean tablesurface (void) {
00614     
00615     /*
00616     5/10/91 dmb: use generic tools to replace old ccbringtofront routine
00617     
00618     5.0.2b21 dmb: don't surface from a file-based window
00619     */
00620     
00621     register hdlhashtable ht;
00622     hdlhashtable hparenttable;
00623     bigstring bsname;
00624     hdlwindowinfo hrootinfo;
00625     
00626     if (isfilewindow (tableformatswindow))
00627         return (false);
00628     
00629     ht = tablegetlinkedhashtable ();
00630     
00631     if ((**ht).parenthashtable == nil) { /*no parent, must be the root*/
00632         
00633         if (!getrootwindow (tableformatswindow, &hrootinfo))
00634             return (false);
00635         
00636         return (shellbringtofront (hrootinfo)); /*bring the home window to the front*/
00637         }
00638     
00639     if ((ht == roottable) || !findinparenttable (ht, &hparenttable, bsname))
00640         return (false);
00641     
00642     if (!(**hparenttable).flwindowopen && !tablezoomfromtable (hparenttable))
00643         return (false);
00644     
00645     if (!tablebringtofront (hparenttable))
00646         return (false);
00647     
00648     if (!shellpushfrontglobals ())
00649         return (false);
00650     
00651     tablemovetoname (hparenttable, bsname);
00652     
00653     shellpopglobals ();
00654     
00655     if (keyboardstatus.floptionkey)
00656         shellclosewindow (shellwindow);
00657     
00658     return (true);
00659     } /*tablesurface*/
00660 
00661 
00662 boolean tablezoomfromtable (hdlhashtable htable) {
00663     
00664     /*
00665     the caller has a hashtable record that he wants displayed in a window.
00666     */
00667     
00668     register hdlhashtable ht = htable;
00669     register hdltablevariable hv = (hdltablevariable) (**ht).hashtablerefcon;
00670     bigstring bspath;
00671     Rect rzoom;
00672     hdlwindowinfo hparent;
00673 
00674     rzoom.top = -1; /*accept default*/
00675     
00676     if (hv == nil) /*not a zoomable table*/
00677         return (false);
00678     
00679     if (!langexternalgetfullpath (ht, emptystring, bspath, &hparent))
00680         return (false);
00681     
00682     return (tableedit ((hdlexternalvariable) hv, hparent, nil, bspath, &rzoom));
00683     } /*tablezoomfromtable*/
00684 
00685 
00686 boolean tablezoomfromhead (hdlheadrecord hnode) {
00687     
00688     /*
00689     zoom a table item into its own window.  
00690     */
00691     
00692     hdlhashtable htable;
00693     bigstring bs;
00694     tyvaluerecord val;
00695     Rect rzoom;
00696     hdlhashnode hhashnode;
00697     
00698     if (!tablegetiteminfo (hnode, &htable, bs, &val, &hhashnode))
00699         return (false);
00700     
00701     if (val.valuetype == novaluetype) { /*not value type assigned yet*/
00702         
00703         if (!tablepopupkinddialog ())
00704             return (false);
00705         
00706         if (!tablegetiteminfo (hnode, &htable, bs, &val, &hhashnode))
00707             return (false);
00708         }
00709     
00710     opgetnoderect (hnode, &rzoom);
00711     
00712     localtoglobalrect (tableformatswindow, &rzoom);
00713     
00714     if (!langexternalzoomfrom (val, htable, bs, &rzoom))
00715         return (false);
00716     
00717     if (keyboardstatus.floptionkey)
00718         shellclosewindow (tableformatswindow);
00719     
00720     return (true);
00721     } /*tablezoomfromhead*/
00722 
00723 
00724 typedef struct tysymbolchangedinfo {
00725     
00726     hdlhashtable htable;
00727     
00728     ptrstring bsname;
00729     
00730     boolean flvalue;
00731     
00732     boolean flfound;
00733     
00734     boolean flchanged;
00735 
00736     hdldatabaserecord hdatabase;
00737     
00738     opvisitcallback opvisitroutine;
00739     
00740     } tysymbolchangedinfo, *ptrsymbolchangedinfo;
00741 
00742 
00743 typedef struct tyfinddatabaseinfo {
00744     
00745     hdldatabaserecord hdatabase;
00746 
00747     WindowPtr w;
00748     } tyfinddatabaseinfo;
00749 
00750 
00751 static boolean finddatabasevisit (WindowPtr w, ptrvoid refcon) {
00752     
00753     tyfinddatabaseinfo *pinfo = (tyfinddatabaseinfo *) refcon;
00754     
00755     if (ccwindowgetdatabase (w) == (*pinfo).hdatabase) { // got it
00756     
00757         (*pinfo).w = w;
00758         
00759         return (false);
00760         }
00761     
00762     return (true); // keep visiting
00763     } /*finddatabasevisit*/
00764 
00765 
00766 static boolean tablefindrootwindow (hdlhashtable ht, hdlwindowinfo *hinfo) {
00767     
00768     /*
00769     find the root window that contains the given table
00770     */
00771 
00772     tyfinddatabaseinfo findinfo;
00773     
00774     findinfo.hdatabase = tablegetdatabase (ht);
00775 
00776     *hinfo = nil;
00777     
00778     if (shellvisittypedwindows (idcancoonconfig, finddatabasevisit, &findinfo))
00779         return (false);
00780     
00781     return (getwindowinfo (findinfo.w, hinfo));
00782     } /*tablefindrootwindow*/
00783 
00784 
00785 static boolean opnodeistable (hdlheadrecord hnode, hdlhashtable htable) {
00786 
00787     tybrowserspec fs;
00788     hdlhashtable ht;
00789     
00790     return ((**hnode).flnodeisfolder && claygetfilespec (hnode, &fs) && claygetinmemorydirid (&fs, &ht) && (ht == htable));
00791     } /*opnodeistable*/
00792 
00793 
00794 static boolean tableupdatewindowtitles (hdlhashnode hnode, hdlhashtable intable) {
00795     
00796     /*
00797     the indicated table value used to have a different name.  if it's 
00798     an external value, update any window titles that depend on its path
00799 
00800     5.0b16 dmb: don't change the titles of file windows, or they'll become
00801     full paths. later, it would be better to add a fltitlelocked to 
00802     hdlwindowinfo, set after a window.settitle we wouldn't do anything either
00803     */
00804     
00805     hdlhashtable htable;
00806     tyvaluerecord val;
00807     bigstring bspath;
00808     hdlwindowinfo hinfo;
00809     
00810     val = (**hnode).val;
00811     
00812     if (val.valuetype != externalvaluetype) /*can't be in a window -- unwind recursion*/
00813         return (true);
00814     
00815     if (intable == filewindowtable) //5.0b16
00816         return (true);
00817 
00818     if (langexternalwindowopen (val, &hinfo)) {
00819         
00820         gethashkey (hnode, bspath);
00821         
00822         langexternalgetfullpath (intable, bspath, bspath, nil);
00823         
00824         shellsetwindowtitle (hinfo, bspath);
00825         }
00826     
00827     if (langexternalvaltotable (val, &htable, hnode)) {
00828         
00829         hashtablevisit (htable, (langtablevisitcallback) &tableupdatewindowtitles, htable); /*daisy chain recursion*/
00830         }
00831     
00832     return (true);
00833     } /*tableupdatewindowtitles*/
00834 
00835 
00836 static boolean tableupdateoutlinesort (hdlheadrecord hfirst, hdlhashtable htable) {
00837     
00838     /*
00839     5.0d18 dmb: take hfirst instead of hparent; handle all updating here.
00840     */
00841     
00842     hdlheadrecord nomad, hcursor, hmatch;
00843     hdlhashnode h;
00844     bigstring bs;
00845     hdlscreenmap hmap;
00846     
00847     opstartinternalchange ();
00848     
00849     opnewscreenmap (&hmap);
00850     
00851     hcursor = (**outlinedata).hbarcursor;
00852     
00853     nomad = hfirst;
00854     
00855     // loop though table nodes, mirroring order of subheads
00856     
00857     for (h = (**htable).hfirstsort; h != nil; h = (**h).sortedlink) {
00858         
00859         gethashkey (h, bs);
00860         
00861         if (opfindhead (nomad, bs, &hmatch)) { // shouldn't fail
00862             
00863             if (hmatch != nomad) {
00864                 
00865                 opunlink (hmatch);
00866                 
00867                 opdeposit (nomad, up, hmatch);
00868                 }
00869             else {
00870                 opchasedown (&nomad);
00871                 }
00872             }
00873         #if fldebug
00874         else
00875             assert (false);
00876         #endif
00877         }
00878     
00879     (**outlinedata).hbarcursor = hcursor;
00880     
00881     opinvalscreenmap (hmap);
00882     
00883     opvisibarcursor ();
00884     
00885     opendinternalchange ();
00886     
00887     return (true);  
00888     } /*tableupdateoutlinesort*/
00889 
00890 
00891 static boolean opinternaldeletenodewithupdate (hdlheadrecord hnode) {
00892     
00893     hdlscreenmap hmap;
00894     
00895     killundo (); /*must toss undos before they're potentially stranded*/
00896     
00897     opstartinternalchange ();
00898     
00899     opbeforestrucchange (&hmap, false);
00900     
00901     opdeletenode (hnode);
00902     
00903     opafterstrucchange (hmap, false);
00904     
00905     opendinternalchange ();
00906     
00907     return (true);
00908     } /*opinternaldeletenodewithupdate*/
00909     
00910 
00911 static boolean tablesymbolzoomvisit (hdlheadrecord hnode, ptrvoid refcon) {
00912     
00913     /*
00914     5.0d18 dmb: expand tables one level to reveal the item we're looking for
00915     */
00916     
00917     ptrsymbolchangedinfo symbolinfo = (ptrsymbolchangedinfo) refcon;
00918     bigstring bs;
00919     tybrowserinfo info;
00920     tybrowserspec fs;
00921     hdlhashtable htable;
00922     
00923     opgetheadstring (hnode, bs);
00924     
00925     browsergetrefcon (hnode, &info);
00926     
00927     if (info.dirid == (*symbolinfo).htable) { // potentially a match
00928         
00929         if (equalidentifiers (bs, (*symbolinfo).bsname)) { // it is a match
00930             
00931             opsettextmode (false);
00932             
00933             opmoveto (hnode);
00934             
00935             shellbringtofront (shellwindowinfo);
00936             
00937             (*symbolinfo).flfound = true;
00938             
00939             return (false); // we're done
00940             }
00941         }
00942     
00943     if ((**hnode).flnodeisfolder &&     // it's a table
00944         !opsubheadsexpanded (hnode) &&  // ...unexpanded.
00945         claygetfilespec (hnode, &fs) && // which...
00946         claygetinmemorydirid (&fs, &htable) &&  // ...table?
00947         (htable == (*symbolinfo).htable)) {     // the one we want!
00948         
00949         if ((**shellwindowinfo).flhidden) // but the window is hidden
00950             return (false); // we're done, but unsuccessful
00951         
00952         opexpand (hnode, 1, false); // expand it for traversal
00953         }
00954 
00955     return (true);
00956     } /*tablesymbolzoomvisit*/
00957 
00958 
00959 static boolean tablesymbolchangedvisit (hdlheadrecord hnode, ptrvoid refcon) {
00960     
00961     ptrsymbolchangedinfo symbolinfo = (ptrsymbolchangedinfo) refcon;
00962     bigstring bs;
00963     tybrowserinfo info;
00964     boolean fl;
00965     
00966     if (opinternalchange ()) // for symbol changes, no further action needed
00967         return (false);
00968 
00969     opgetheadstring (hnode, bs);
00970     
00971     /*
00972     if (equalidentifiers (bs, (*symbolinfo).bsname)) { // potentially a match
00973         
00974         browsergetrefcon (hnode, &info);
00975         
00976         if (info.dirid == (*symbolinfo).htable) { // it is a match
00977     */
00978     
00979     browsergetrefcon (hnode, &info);
00980     
00981     if (info.dirid == (*symbolinfo).htable) { // potentially a match
00982         
00983         if ((*symbolinfo).flvalue)
00984             fl = equalidentifiers (bs, (*symbolinfo).bsname); // a match
00985         else
00986             fl = !hashtablesymbolexists (info.dirid, bs); // best guess
00987         
00988         if (fl) { // it is a match
00989             
00990             // if we kept more info around, we'd have to reload the refcon here
00991             
00992             opinvalnode (hnode);
00993             
00994             if ((*symbolinfo).flvalue) { // value changed
00995             
00996                 if ((**hnode).flnodeisfolder) //5.0b18
00997                     opcollapse (hnode);
00998 
00999                 browserloadnode (hnode); /*mod date changed*/
01000                 }
01001             else { // name changed
01002             
01003                 opsetactualheadstring (hnode, (*symbolinfo).bsname);
01004                 
01005                 browserinsertagain (hnode);
01006                 }
01007             
01008             if ((**hnode).tmpbit2) {
01009             
01010                 (**hnode).tmpbit2 = false; //user modified item, no longer temp
01011                 
01012                 langexternalpleasesave ((*symbolinfo).htable, (*symbolinfo).bsname); // 5.1.4
01013                 }
01014             
01015             (*symbolinfo).flfound = true;
01016             
01017             return (false); // we're done
01018             }
01019         }
01020     
01021     return (true);
01022     } /*tablesymbolchangedvisit*/
01023 
01024 
01025 static boolean tablesymbolinsertedvisit (hdlheadrecord hnode, ptrvoid refcon) {
01026     
01027     /*
01028     8.8.97 dmb: always check parID of summit, so we'll always catch insertions 
01029     to the parent table
01030 
01031     5.0a25 dmb: we're called for internal change now, must be more selective
01032     about what we do.
01033     
01034     5.1.4 dmb: detect case where we have lone "bogus" summit, not connected to 
01035     window's table.
01036     */
01037     
01038     ptrsymbolchangedinfo symbolinfo = (ptrsymbolchangedinfo) refcon;
01039     tybrowserspec fs;
01040     hdlhashtable htable;
01041     hdlheadrecord hnew;
01042     hdlheadrecord hsummit = (**outlinedata).hsummit;
01043     boolean flsummitisbogus = false;
01044     
01045     if ((**hnode).flnodeisfolder || hnode == hsummit) { // could be the table
01046         
01047         if (!claygetfilespec (hnode, &fs)) { // not connected to a table
01048             
01049             if (hnode == hsummit) { // all nodes were deleted, new summit was auto-created
01050                 
01051                 flsummitisbogus = true;
01052                 
01053                 browsergetparentspec (hnode, &fs); // will set right table, item is ""
01054                 }
01055             }
01056         
01057         if (fs.parID == (*symbolinfo).htable) { // we must be a summit...
01058             
01059             assert ((**hnode).headlinkleft == hnode); // ...otherwise our parent would have caught it below
01060             
01061             if (!opinternalchange ()) {
01062 
01063                 copystring ((*symbolinfo).bsname, fs.name);
01064                 
01065                 if (browserfileadded (nil, &fs, &hnew)) {
01066                     
01067                     if (flsummitisbogus)
01068                         opinternaldeletenodewithupdate (hsummit);
01069                     }
01070                 }
01071             
01072             (*symbolinfo).flfound = true;
01073             
01074             return (false); // we're done
01075             }
01076         
01077         if ((**hnode).flnodeisfolder && claygetinmemorydirid (&fs, &htable) && (htable == (*symbolinfo).htable)) {
01078             
01079             opinvalnode (hnode); // update item count
01080             
01081             if (!opinternalchange () && opsubheadsexpanded (hnode)) {
01082                 
01083                 fs.parID = htable;
01084                 
01085                 copystring ((*symbolinfo).bsname, fs.name);
01086                 
01087                 browserfileadded (hnode, &fs, &hnew);
01088                 }
01089             
01090             (*symbolinfo).flfound = true;
01091             
01092             return (false); // we're done
01093             }
01094         }
01095     
01096     return (true);
01097     } /*tablesymbolinsertedvisit*/
01098 
01099 
01100 static boolean tablesymboldeletedvisit (hdlheadrecord hnode, ptrvoid refcon) {
01101     
01102     /*
01103     5.0a25 dmb: we're called for internal change now, must be more selective
01104     about what we do.
01105     */
01106 
01107     ptrsymbolchangedinfo symbolinfo = (ptrsymbolchangedinfo) refcon;
01108     bigstring bs;
01109     tybrowserinfo info;
01110     hdlheadrecord hparent;
01111     
01112     opgetheadstring (hnode, bs);
01113     
01114     browsergetrefcon (hnode, &info);
01115     
01116     if (opinternalchange ()) { // just look for parent node
01117         
01118         if (opnodeistable (hnode, (*symbolinfo).htable)) {
01119             
01120             opinvalnode (hnode); // update item count
01121             
01122             return (false);
01123             }
01124         
01125         return (true);
01126         }
01127     
01128     if (info.dirid == (*symbolinfo).htable) { // potentially a match
01129     
01130         if (equalidentifiers (bs, (*symbolinfo).bsname)) { // it is a match, or don't care
01131             
01132             // first, inval the parent table node; its item count is changing
01133             
01134             hparent = (**hnode).headlinkleft;
01135             
01136             if (hparent != hnode)
01137                 opinvalnode (hparent);
01138             
01139             opinternaldeletenodewithupdate (hnode);
01140             
01141             (*symbolinfo).flfound = true;
01142             
01143             return (false); // we're done
01144             }
01145         }
01146     else {
01147         
01148         if (!opsubheadsexpanded (hnode)) { // can't rely on subhead to dirty parent
01149             
01150             if (opnodeistable (hnode, (*symbolinfo).htable)) {
01151                 
01152                 opinvalnode (hnode); // update item count
01153                 
01154                 return (false);
01155                 }
01156             }
01157         }
01158     
01159     return (true);
01160     } /*tablesymboldeletedvisit*/
01161 
01162 
01163 static boolean tablesymbolsresortedvisit (hdlheadrecord hnode, ptrvoid refcon) {
01164     
01165     ptrsymbolchangedinfo symbolinfo = (ptrsymbolchangedinfo) refcon;
01166     tybrowserspec fs;
01167     hdlhashtable htable;
01168     
01169     if (hnode == (**outlinedata).hsummit) { // one time check to see of parent table is it
01170         
01171         claygetfilespec (hnode, &fs);
01172         
01173         if (fs.parID == (*symbolinfo).htable) {
01174         
01175             tableupdateoutlinesort (hnode, fs.parID);
01176             
01177             return (false); // we're done
01178             }
01179         }
01180     
01181     if ((**hnode).flnodeisfolder) { // could be the table
01182         
01183         claygetfilespec (hnode, &fs);
01184         
01185         if (claygetinmemorydirid (&fs, &htable) && (htable == (*symbolinfo).htable)) {
01186             
01187             if (opsubheadsexpanded (hnode))
01188                 tableupdateoutlinesort ((**hnode).headlinkright, htable);
01189             
01190             return (false); // we're done
01191             }
01192         }
01193     
01194     return (true);
01195     } /*tablesymbolsresortedvisit*/
01196 
01197 
01198 
01199 static boolean tablesymbolchangedwindowvisit (WindowPtr w, ptrsymbolchangedinfo symbolinfo) {
01200     
01201     /*
01202     5.0d11 dmb: check internalchange here, now that it's outline-specific
01203     
01204     5.0a2 dmb: only visit children of the symbol's root
01205 
01206     5.0a17 dmb: also visit standalone table windows
01207     
01208     5.0a21 dmb: visit all windows. our goal is to not visit windows that 
01209     aren't part of the current context, but with file-based tables and 
01210     guest roots, the logic is getting too messy -- especially since we 
01211     don't expect people to keep two full roots open at the same time.
01212 
01213     5.0a25 dmb: don't even check opinternalchange here; the check needs to 
01214     be more specific, in each visit routine
01215 
01216     5.1.5b15 dmb: rewrote using new ccwindowgetdatabase for specificity
01217     */
01218     
01219     if (ccwindowgetdatabase (w) == (*symbolinfo).hdatabase) {
01220         
01221         shellpushglobals (w);
01222         
01223         if (tableformatsdata && outlinedata) { // && !opinternalchange ())
01224     
01225             opvisiteverything ((*symbolinfo).opvisitroutine, symbolinfo);
01226             
01227             //dirty the root (database) window, in case we don't find the change in any window
01228             if ((*symbolinfo).flchanged && (**shellwindowinfo).parentwindow == nil)
01229                 shellsetwindowchanges (shellwindowinfo, true);
01230             }
01231         
01232         shellpopglobals ();
01233         }
01234     
01235     return (true); // visit all windows, even after finding an instance
01236     } /*tablesymbolchangedwindowvisit*/
01237 
01238 
01239 #ifdef fldebug
01240 //static long   ctlocaltablechecks = 0;
01241 //static long ctglobaltablechecks = 0;
01242 #endif
01243 
01244 static boolean tabledrivesymbolchange (hdlhashtable htable, const bigstring bsname, boolean flchanged, boolean flvalue, opvisitcallback visit) {
01245     
01246     /*
01247     5.0.2b21 dmb: added flchanged parameter to make sure root get dirtied
01248     */
01249     
01250     tysymbolchangedinfo symbolchangedinfo;
01251     hdloutlinerecord saveoutlinedata;
01252     hdlwindowinfo hroot;
01253     boolean fl;
01254     
01255     if (!(**htable).flmayaffectdisplay) {
01256         
01257         if (!(**htable).fldirty) { // first mod to this table, must dirty root window
01258             
01259             if (tablefindrootwindow (htable, &hroot))
01260                 shellsetwindowchanges (hroot, true);
01261             }
01262 
01263         return (false);
01264         }
01265     
01266     symbolchangedinfo.hdatabase = tablegetdatabase (htable);
01267     
01268     symbolchangedinfo.flchanged = flchanged;
01269 
01270 //  #ifdef fldebug
01271 //  if ((**htable).fllocaltable)
01272 //      ++ctlocaltablechecks;
01273 //  else
01274 //      ++ctglobaltablechecks;
01275 //  #endif
01276     
01277     symbolchangedinfo.htable = htable;
01278     
01279     symbolchangedinfo.bsname = (ptrstring) bsname;
01280     
01281     symbolchangedinfo.flvalue = flvalue;
01282     
01283     symbolchangedinfo.opvisitroutine = visit;
01284     
01285     symbolchangedinfo.flfound = false;
01286     
01287     saveoutlinedata = outlinedata; // may not be associated with current shellglobals
01288     
01289     fl = shellvisittypedwindows (idtableconfig, (shellwindowvisitcallback) &tablesymbolchangedwindowvisit, &symbolchangedinfo)
01290         && shellvisittypedwindows (idcancoonconfig, (shellwindowvisitcallback) &tablesymbolchangedwindowvisit, &symbolchangedinfo)
01291         && symbolchangedinfo.flfound;
01292     
01293     opsetoutline (saveoutlinedata);
01294     
01295     return (fl);
01296     } /*tabledrivesymbolchange*/
01297 
01298 
01299 boolean tablesymbolchanged (hdlhashtable htable, const bigstring bsname, hdlhashnode hn, boolean flvalue) {
01300 #pragma unused (hn)
01301 
01302     /*
01303     used as a callback routine.  the value of the indicated variable has changed.
01304     if the cell is being displayed, update the display of it.  if the name changed,
01305     update any window titles containing it.
01306     
01307     11/14/01 dmb: we now take hnode parameter; probably don't need to pushhashtable 
01308     and look it up anymore, but not having the table pushed could change the 
01309     behavior of tableupdatewindowtitles, so I'll leave it.  (it doesn't look like it
01310     would be a problem, but....)
01311     */
01312     
01313     hdlhashnode hnode;
01314     
01315     if (!flvalue) { // the name changed, not the value
01316         
01317         pushhashtable (htable);
01318         
01319         if (hashlookupnode (bsname, &hnode))
01320             tableupdatewindowtitles (hnode, htable);
01321         
01322         pophashtable ();
01323         }
01324     
01325     return (tabledrivesymbolchange (htable, bsname, true, flvalue, &tablesymbolchangedvisit));
01326     } /*tablesymbolchanged*/
01327 
01328 
01329 boolean tablesymbolinserted (hdlhashtable htable, const bigstring bsname) {
01330     
01331     /*
01332     5.0b10 dmb: need to update window titles, in case insertion is 2nd 
01333     half of a move operation. (even table.move can do that.) while it's 
01334     conceivable that we'd need to do this for local table insertions, 
01335     let's not and save cycles
01336     */
01337     
01338     hdlhashnode hnode;
01339     
01340     if (!(**htable).fllocaltable) {
01341 
01342         pushhashtable (htable);
01343         
01344         if (hashlookupnode (bsname, &hnode))
01345             tableupdatewindowtitles (hnode, htable);
01346         
01347         pophashtable ();
01348         }
01349 
01350     return (tabledrivesymbolchange (htable, bsname, true, true, &tablesymbolinsertedvisit));
01351     } /*tablesymbolinserted*/
01352 
01353 
01354 boolean tablesymboldeleted (hdlhashtable htable, const bigstring bsname) {
01355     
01356     /*
01357     5.0d14: it would make sense to close all windows owned by the given value 
01358     record here, but it's already been deleted from the table. we'd need to 
01359     use the symbolunlinked callback, and add a "fldisposing" parameter, so we
01360     could do nothing if the value is indeed being disposed. so, instead, we 
01361     take care of window disposing in browserlinedeleted (browsercommitchanges)
01362     */
01363     
01364     return (tabledrivesymbolchange (htable, bsname, true, true, &tablesymboldeletedvisit));
01365     } /*tablesymboldeleted*/
01366 
01367 
01368 boolean tablesymbolsresorted (hdlhashtable htable) {
01369     
01370     return (tabledrivesymbolchange (htable, nil, false, false, &tablesymbolsresortedvisit));
01371     } /*tablesymbolsresorted*/
01372 
01373 
01374 boolean tablezoomtoname (hdlhashtable htable, bigstring bsname) {
01375     
01376     hdlwindowinfo hinfo;
01377     tysymbolchangedinfo symbolchangedinfo;
01378     
01379     if (tablefinddatawindow (htable, &hinfo)) {
01380         
01381         symbolchangedinfo.htable = htable;
01382         
01383         symbolchangedinfo.bsname = (ptrstring) bsname;
01384         
01385         symbolchangedinfo.flvalue = true;
01386         
01387         symbolchangedinfo.opvisitroutine = tablesymbolzoomvisit;
01388         
01389         symbolchangedinfo.flfound = false;
01390         
01391         tablesymbolchangedwindowvisit ((**hinfo).macwindow, &symbolchangedinfo);
01392         }
01393     else
01394         symbolchangedinfo.flfound = tabledrivesymbolchange (htable, bsname, false, true, &tablesymbolzoomvisit);
01395     
01396     if (symbolchangedinfo.flfound)
01397         return (true);
01398     
01399     if (!tablezoomfromtable (htable))
01400         return (false);
01401     
01402     if (!shellpushfrontglobals ())
01403         return (false);
01404     
01405     opmoveto ((**outlinedata).hsummit);
01406 
01407     tablemovetoname (htable, bsname);
01408     
01409     shellpopglobals ();
01410     
01411     return (true);
01412     } /*tablezoomtoname*/
01413 
01414 

Generated on Wed May 31 18:20:02 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6