tablefind.c

Go to the documentation of this file.
00001 
00002 /*  $Id: tablefind.c 1209 2006-04-05 23:59:59Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "cursor.h"
00032 #include "kb.h"
00033 #include "memory.h"
00034 #include "search.h"
00035 #include "strings.h"
00036 #include "langexternal.h"
00037 #include "opinternal.h"
00038 #include "tablestructure.h"
00039 #include "tableinternal.h"
00040 #include "tableverbs.h"
00041 
00042 
00043 
00044 
00045 static hdlhashtable hsearchtable;
00046 
00047 static bigstring bssearchmarker;
00048 
00049 static boolean flsearchundermarker;
00050 
00051 static boolean flsearchwrapped;
00052 
00053 
00054 static boolean tableassigntocell (hdlhashtable htable, bigstring bsname, hdlhashnode hnode, tyvaluerecord val) {
00055     
00056     if (!coercevalue (&val, (**hnode).val.valuetype)) {
00057         
00058         disposevaluerecord (val, false);
00059         
00060         return (false);
00061         }
00062     
00063     hashtableassign (htable, bsname, val);
00064     
00065     exemptfromtmpstack (&val);
00066     
00067     return (true);
00068     } /*tableassigntocell*/
00069 
00070 
00071 static void tablezoomfound (bigstring bsname, short col, long ixfound, short lenfound) {
00072 
00073     if (searchparams.flzoomfound) {
00074         
00075         tablezoomtoname (hsearchtable, bsname);
00076         
00077         if (shellpushfrontglobals ()) {
00078             
00079             if (searchparams.flwindowzoomed)
00080                 (**shellwindowinfo).flopenedforfind = true;
00081             
00082             (**tableformatsdata).focuscol = col;
00083             
00084             if (opsettextmode (true))
00085                 opeditsetselection (ixfound, ixfound + lenfound);
00086             
00087             shellpopglobals ();
00088             }
00089         }
00090     } /*tablezoomfound*/
00091 
00092 
00093 static boolean tablesearchcellname (hdlhashnode hnode, bigstring bscell) {
00094     
00095     /*
00096     4/3/92 dmb: when replacing all, search for multiple occurences in the string, 
00097     and actually assign changed string into values as well as names.
00098     
00099     4.0.2b1 dmb: separate code for names; values may be handles now
00100     */
00101     
00102     short ix = 0;
00103     short len;
00104     boolean fldidreplace = false;
00105     bigstring bs;
00106     
00107     gethashkey (hnode, bs);
00108     
00109     while (true) {
00110         
00111         if (!stringsearch (bs, &ix, &len)) {
00112         
00113             if (fldidreplace)
00114                 hashsetnodekey (hsearchtable, hnode, bs);
00115             
00116             return (false);
00117             }
00118         
00119         if (!searchparams.flreplaceall) {
00120             
00121             tablezoomfound (bscell, namecolumn, ix, len);
00122             
00123             return (true);
00124             }
00125         
00126         replacestring (bs, ix + 1, len, searchparams.bsreplace);
00127         
00128         ++searchparams.ctreplaced;
00129         
00130         fldidreplace = true;
00131         
00132         /*keep looping until we fail*/
00133         ix += stringlength (searchparams.bsreplace);
00134         }
00135     } /*tablesearchcellname*/
00136 
00137 
00138 static boolean tablesearchcellvalue (hdlhashnode hnode, bigstring bscell, tyvaluerecord val) {
00139     
00140     /*
00141     4/3/92 dmb: when replacing all, search for multiple occurences in the string, 
00142     and actually assign changed string into values as well as names.
00143     
00144     4.0.2b1 dmb: separate code for values to handle > 255 characters
00145     
00146     5.0.2b20 dmb: for tokentype, return false, not true.
00147     
00148     7.1b40 PBS: fix off-by-one selection error with addresses.
00149     */
00150     
00151     long ix = 0;
00152     ptrstring bsreplace = searchparams.bsreplace;
00153     Handle hsearch;
00154     long len, lenmatch;
00155     boolean fldidreplace = false;
00156     boolean fladdress = false;
00157     
00158     if (val.valuetype == tokenvaluetype)
00159         return (false);
00160     
00161     if (val.valuetype == addressvaluetype) /*7.1b40 PBS: part off-by-one selection fix.*/
00162         fladdress = true;
00163     
00164     /*copy value unless we're just finding, and it's a string in memory */
00165     if (searchparams.flreplaceall || (val.valuetype != stringvaluetype) || val.fldiskval)
00166         if (!copyvaluerecord (val, &val) || !coercetostring (&val))
00167             return (true);
00168     
00169     hsearch = val.data.stringvalue;
00170     
00171     len = gethandlesize (hsearch);
00172     
00173     while (true) {
00174         
00175         if (!handlesearch (hsearch, &ix, &lenmatch)) {
00176             
00177             if (fldidreplace) {
00178             
00179                 if (!tableassigntocell (hsearchtable, bscell, hnode, val)) /*error; stop search*/
00180                     return (true);
00181                 }
00182             else {
00183                 if (exemptfromtmpstack (&val))
00184                     disposevaluerecord (val, false);
00185                 }
00186             
00187             return (false);
00188             }
00189         
00190         if (!searchparams.flreplaceall) {
00191             
00192             if (fladdress) /*7.1b40 PBS: add one to ix to account for @ symbol -- fix off-by-one selection.*/
00193                 tablezoomfound (bscell, valuecolumn, ix + 1, lenmatch);
00194             
00195             else
00196                 tablezoomfound (bscell, valuecolumn, ix, lenmatch);
00197             
00198             return (true);
00199             }
00200         
00201         if (!mungehandle (hsearch, ix, lenmatch, bsreplace + 1, stringlength (bsreplace)))
00202             return (false);
00203         
00204         ++searchparams.ctreplaced;
00205         
00206         fldidreplace = true;
00207         
00208         /*keep looping until we fail*/
00209         ix += stringlength (bsreplace);
00210         }
00211     } /*tablesearchcellvalue*/
00212 
00213 
00214 static boolean tablefindvisit (bigstring bsname, hdlhashnode hnode, tyvaluerecord val, ptrvoid refcon) {
00215 #pragma unused (refcon)
00216 
00217     /*
00218     7/4/91 dmb: langexternalzoom now takes table/name pair instead 
00219     of full path.
00220     
00221     7/29/91 dmb: handle activate events after zooming so deferred visiing 
00222     takes place
00223     
00224     9/12/91 dmb: new marker logic to handle wraparound search
00225     */
00226     
00227     boolean flzoom;
00228     boolean flsearchcell = true;
00229     boolean flsearchvalue = true;
00230     
00231     if (!isemptystring (bssearchmarker)) { /*we've haven't passed the marked entry*/
00232         
00233         if (!equalstrings (bsname, bssearchmarker)) { /*we haven't reached the marked entry*/
00234             
00235             flsearchcell = false;
00236             
00237             flsearchvalue = false;
00238             }
00239         else { /*we're at the marked cell*/
00240             
00241             setemptystring (bssearchmarker);
00242             
00243             flsearchcell = false;
00244             
00245             flsearchvalue = flsearchundermarker;
00246             }
00247         }
00248     
00249     if (flsearchwrapped) { /*if the search has wrapped, we search *before* the marker, not after*/
00250         
00251         flsearchcell = !flsearchcell;
00252         
00253         flsearchvalue = !flsearchvalue;
00254         }
00255     
00256     if (flsearchcell) {
00257         
00258         rollbeachball ();
00259         
00260         if (tablesearchcellname (hnode, bsname))
00261             return (true);
00262         
00263         if (val.valuetype != externalvaluetype) {
00264             
00265             if (tablesearchcellvalue (hnode, bsname, val))
00266                 return (true);
00267             }
00268         }
00269     
00270     if (searchparams.flonelevel || !flsearchvalue)
00271         return (false);
00272     
00273     if (keyboardescape ()) /*user pressed cmd-period -- stop visiting*/
00274         return (true);
00275     
00276     if (!langexternalsearch (val, &flzoom))
00277         return (false);
00278     
00279     if (searchparams.flreplaceall) /*keep going*/
00280         return (false);
00281     
00282     if (flzoom && searchparams.flzoomfound) {
00283         
00284         hdlwindowinfo hinfo;
00285         
00286         langexternalzoom (val, hsearchtable, bsname);
00287         
00288         if (getfrontwindowinfo (&hinfo))
00289             (**hinfo).flopenedforfind = searchparams.flwindowzoomed;
00290         
00291         shellpartialeventloop (activMask); /*handle pending activate events*/
00292         }
00293     
00294     return (true);
00295     } /*tablefindvisit*/
00296 
00297 
00298 static boolean tablefind (hdlhashtable htable, boolean flwrap, bigstring bsmark, boolean flmarkbeforevalue) {
00299     
00300     /*
00301     9/12/91 dmb: added wrap, marker parameters; now handle wraparound search
00302     
00303     5.1.5 dmb: use tablesortedinversesearch for guest databases
00304     */
00305     
00306     hdlhashtable hsave = hsearchtable;
00307     boolean fl;
00308     
00309     hsearchtable = htable; /*so tablefindvisit can zoom quickly*/
00310     
00311     if (bsmark) { /*a marker is being provided*/
00312         
00313         copystring (bsmark, bssearchmarker); /*so visit routine can see where we are.*/
00314         
00315         flsearchundermarker = flmarkbeforevalue; /*start search with marked cell's submaterial*/
00316         }
00317     
00318     if (flwrap)
00319         flsearchwrapped = false;
00320     
00321     fl = tablesortedinversesearch (htable, &tablefindvisit, htable);
00322     
00323     if (!fl && flwrap) { /*marker will have been cleared; we can try again*/
00324         
00325         copystring (bsmark, bssearchmarker); /*re-establish marker*/
00326         
00327         flsearchwrapped = true;
00328         
00329         fl = tablesortedinversesearch (htable, &tablefindvisit, nil);
00330         }
00331     
00332     hsearchtable = hsave;
00333     
00334     return (fl);
00335     } /*tablefind*/
00336 
00337 
00338 boolean tableverbfind (hdlexternalvariable hvariable, boolean *flzoom) {
00339     
00340     register hdltablevariable hv = (hdltablevariable) hvariable;
00341     register hdlhashtable ht;
00342     register boolean fl;
00343     boolean fltempload;
00344     
00345     fltempload = !(**hv).flinmemory;
00346     
00347     if (!tableverbinmemory ((hdlexternalvariable) hv, HNoNode))
00348         return (false);
00349     
00350     ht = (hdlhashtable) (**hv).variabledata; 
00351     
00352     fl = tablefind (ht, false, nil, false);
00353     
00354     if (fltempload && !fl && tablenosubsdirty (ht))
00355         tableverbunload ((hdlexternalvariable) hv);
00356     
00357     *flzoom = false; /*we take care of our own zooming*/
00358     
00359     return (fl);
00360     } /*tableverbfind*/
00361 
00362 
00363 static boolean continuetablesearch (hdlexternalvariable hvariable) {
00364     
00365     /*
00366     the caller just finished searching hvariable without finding a match.
00367     
00368     our job is to continue the search in the table that contains the variable.
00369     
00370     9/19/91 dmb: don't clear keyboard escape; if we're called from a script, 
00371     we want the script to be aborted as well
00372     */
00373     
00374     hdlhashtable htable;
00375     register long tablerefcon;
00376     bigstring bsname;
00377     boolean fl;
00378     
00379     if (!tablefindvariable (hvariable, &htable, bsname))
00380         return (false);
00381     
00382     if (htable == nil) /*hvariable is rootvariable*/
00383         return (false);
00384     
00385     tablerefcon = (**htable).hashtablerefcon;
00386     
00387     fl = tablefind (htable, searchshouldwrap (tablerefcon), bsname, false);
00388     
00389     if (keyboardescape ()) {
00390         
00391         /*
00392         keyboardclearescape ();
00393         */
00394         
00395         return (false);
00396         }
00397     
00398     if (!fl) { /*not found in our table or subtables; try continuing in parent*/
00399         
00400         if (!searchshouldcontinue (tablerefcon)) /*we're at table that started search*/
00401             return (false);
00402         
00403         fl = continuetablesearch ((hdlexternalvariable) tablerefcon); /*recurse outwards*/
00404         }
00405     
00406     return (fl);
00407     } /*continuetablesearch*/
00408 
00409 
00410 boolean tableverbcontinuesearch (hdlexternalvariable hvariable) {
00411     
00412     /*
00413     a wrapper for continuetablesearch
00414     
00415     12/17/91 dmb: added flopenedforfind support.  he next step would be to 
00416     clear the flag in all open windows when a new search is begun
00417     */
00418     
00419     WindowPtr origwindow = shellwindow;
00420     hdlwindowinfo origwindowinfo = shellwindowinfo;
00421     
00422     /*
00423     if (searchparams.floneobject) /%user has flat search turned off%/
00424         return (false);
00425     */
00426     
00427     if (!continuetablesearch (hvariable))
00428         return (false);
00429     
00430     if (searchparams.flclosebehind) {
00431         
00432         if ((origwindowinfo != nil) && (**origwindowinfo).flopenedforfind)
00433             shellclosewindow (origwindow);
00434         }
00435     
00436     return (true);
00437     } /*tableverbcontinuesearch*/
00438 
00439 
00440 boolean tableverbsearch (void) {
00441     
00442     hdlhashtable htable;
00443     long tablerefcon;
00444     bigstring bsname;
00445     boolean fl;
00446     tyvaluerecord val;
00447     hdlhashnode hnode;
00448     
00449     tablegetcursorinfo (&htable, bsname, &val, &hnode); /*find out where to start*/
00450     
00451     tablerefcon = (**htable).hashtablerefcon;
00452     
00453     startingtosearch (tablerefcon);
00454     
00455     fl = tablefind (htable, searchshouldwrap (tablerefcon), bsname, true);
00456     
00457     if (keyboardescape ()) {
00458         
00459         /*
00460         keyboardclearescape ();
00461         */
00462         
00463         return (false);
00464         }
00465     
00466     if (!fl) { /*not found in our table or subtables; try continuing in parent*/
00467         
00468         if (searchshouldcontinue (tablerefcon))
00469             fl = tableverbcontinuesearch ((hdlexternalvariable) tablerefcon);
00470         }
00471     
00472     return (fl);
00473     } /*tableverbsearch*/
00474 
00475 
00476 

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