oplist.c

Go to the documentation of this file.
00001 
00002 /*  $Id: oplist.c 1236 2006-04-09 11:28:08Z andreradke $    */
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 "strings.h"
00033 #include "resources.h"
00034 #include "op.h"
00035 #include "opinternal.h"
00036 #include "oplist.h"
00037 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00038 
00039 
00040 /*
00041 created 3/20/90 DW:
00042 
00043 you can build a very simple list manager on top of the outline processor
00044 implemented in op.c.  this is such a thing.
00045 
00046 the idea is that any list built on top of op, could someday easily be
00047 displayed in a window, and be interacted with by the user.  both noble
00048 goals.  so here goes!
00049 */
00050 
00051 
00052 #define fldebugging false 
00053 
00054 #define oplistversionnumber 1
00055 
00056 
00057 typedef struct tylistrecord {
00058     
00059     struct tyoutlinerecord ** houtline; /*the list is stored in an outline*/
00060     
00061     long ctitems; /*number of items in the list, can be gotten without traversal*/
00062 
00063     boolean isrecord; /*do items have names?*/
00064     
00065     oplistreleaseitemcallback releaseitemcallback; /*routine that releases one of **your** handles*/
00066     } tylistrecord;
00067 
00068 
00069 typedef struct tydisklistrecord {
00070     
00071     short recordsize; /*number of bytes in this header*/
00072     
00073     short versionnumber; /*this structure is saved on disk*/
00074     
00075     unsigned long ctoutlinebytes; /*size of the packed outline record*/
00076     
00077     short ctitems; /*save this instead of recomputing every time we load*/
00078     
00079     boolean flunused; /*just maintaining the byte alignment we want*/
00080     
00081     boolean isrecord; /*are list items named?*/
00082     
00083     // short ctitems_hiword; // 5.1.3 - support more than 32K items
00084     
00085     /*packed outline record is stored at end of this record*/
00086     } tydisklistrecord;
00087 
00088 
00089 static hdllistrecord hcurrentlist = nil;
00090 
00091 
00092 /*static boolean oplistreleaserefcon (hdlheadrecord hnode, boolean fl) {
00093     
00094     cb = (**hcurrentlist).releaseitemcallback;
00095     
00096     if (cb)
00097         return ((*cb) ((**hnode).hrefcon));
00098     } /%oplistreleaserefcon%/
00099 */
00100 
00101 
00102 boolean opnewlist (hdllistrecord *hlist, boolean isrecord) {
00103     
00104     /*
00105     7.31.97 dmb: expanded implementation to serve as UserTalk's list
00106     and record datatype.
00107     */
00108 
00109     register hdllistrecord h;
00110     hdloutlinerecord houtline;
00111     
00112     if (!newclearhandle (sizeof (tylistrecord), (Handle *) hlist))
00113         return (false);
00114     
00115     h = *hlist; /*copy into register*/
00116 
00117     if (!newoutlinerecord (&houtline)) { 
00118         
00119         disposehandle ((Handle) h);
00120         
00121         return (false);
00122         }
00123         
00124     (**houtline).flbuildundo = false;
00125     
00126     (**houtline).flinhibitdisplay = true;
00127 
00128     (**h).houtline = houtline;
00129     
00130     (**h).ctitems = 0;
00131     
00132     (**h).isrecord = isrecord;
00133     
00134     /*
00135     (**houtline).releaserefconcallback = &oplistreleaserefcon;
00136     */
00137 
00138     return (true);
00139     } /*opnewlist*/
00140     
00141     
00142 void opdisposelist (hdllistrecord hlist) {
00143     
00144     register hdloutlinerecord ho;
00145     
00146     if (hlist == nil) /*defensive driving*/
00147         return;
00148         
00149     hcurrentlist = hlist; /*for our callback routines*/
00150     
00151     ho = (hdloutlinerecord) (**hlist).houtline;
00152     
00153     opdisposeoutline (ho, false);
00154     
00155     hcurrentlist = nil;
00156     
00157     disposehandle ((Handle) hlist);
00158     } /*opdisposelist*/
00159     
00160     
00161 boolean oppushhandle (hdllistrecord hlist, ptrstring pname, Handle hdata) {
00162     
00163     /*
00164     add a new item at the end of the list.  link in the indicated handle in the
00165     refcon field of the allocated headrecord.  return false if there's an allocation
00166     error.
00167 
00168     8.11.97 dmb: dispose hdata on error.
00169     */
00170     
00171     register hdllistrecord h = hlist;
00172     register hdlheadrecord hlast;
00173     register hdloutlinerecord ho;
00174     register long ctitems;
00175     hdlheadrecord hnew;
00176     bigstring bs;
00177     
00178     if ((**h).isrecord && (pname == nil))
00179         goto error;
00180 
00181     ho = (hdloutlinerecord) (**h).houtline;
00182     
00183     if (!oppushoutline (ho))
00184         goto error;
00185     
00186     ctitems = (**h).ctitems;
00187     
00188     copystring (pname, bs); /*checks for nil*/
00189     
00190     if (ctitems == 0) { /*adding to an empty list*/
00191         
00192         hnew = (**ho).hsummit; /*set this guy's refcon handle*/
00193         
00194         opsetheadstring (hnew, bs);
00195         }
00196         
00197     else {
00198         hlast = oprepeatedbump (down, ctitems - 1, (**ho).hsummit, false);
00199         
00200     //  setstringlength (bs, 0);
00201 
00202         if (!opaddheadline (hlast, down, bs, &hnew)) {
00203 
00204             oppopoutline ();
00205 
00206             goto error;
00207             }
00208         
00209         (**ho).ctexpanded++;
00210         
00211         (**hnew).flexpanded = true;
00212         }
00213     
00214     #ifdef fldebug
00215     
00216     if (fldebugging) {
00217         
00218         copystring ((ptrstring) "\x0A" "headline #", bs);
00219         
00220         pushint (ctitems + 1, bs);
00221         
00222         opsetheadstring (hnew, bs);
00223         }
00224     
00225     #endif
00226     
00227     (**hnew).hrefcon = hdata; /*link in the user's data structure*/
00228     
00229     (**h).ctitems++;
00230 
00231     oppopoutline ();
00232 
00233     return (true);
00234 
00235     error:
00236         
00237         disposehandle (hdata);
00238 
00239         return (false);
00240     } /*oppushhandle*/
00241     
00242     
00243 boolean opunshifthandle (hdllistrecord hlist, ptrstring pname, Handle hdata) {
00244     
00245     /*
00246     add a new item at the beginning of the list.  link in the indicated handle in the
00247     refcon field of the allocated headrecord.  return false if there's an allocation
00248     error.
00249     */
00250     
00251     register hdllistrecord h = hlist;
00252     register hdlheadrecord hstart;
00253     register hdloutlinerecord ho;
00254     register long ctitems;
00255     hdlheadrecord hnew;
00256     bigstring bs;
00257     
00258     if ((**h).isrecord && (pname == nil))
00259         goto error;
00260 
00261     ho = (hdloutlinerecord) (**h).houtline;
00262     
00263     if (!oppushoutline (ho))
00264         goto error;
00265     
00266     ctitems = (**h).ctitems;
00267     
00268     copystring (pname, bs); /*checks for nil*/
00269     
00270     if (ctitems == 0) { /*adding to an empty list*/
00271         
00272         hnew = (**ho).hsummit; /*set this guy's refcon handle*/
00273         
00274         opsetheadstring (hnew, bs);
00275         }
00276         
00277     else {
00278         hstart = (**ho).hsummit;
00279 
00280         if (!opaddheadline (hstart, up, bs, &hnew)) {
00281 
00282             oppopoutline ();
00283 
00284             goto error;
00285             }
00286         
00287         (**ho).ctexpanded++;
00288         
00289         (**hnew).flexpanded = true;
00290         }
00291     
00292     #ifdef fldebug
00293     
00294     if (fldebugging) {
00295         
00296         copystring ((ptrstring) "\x0A" "headline #", bs);
00297         
00298         pushint (ctitems + 1, bs);
00299         
00300         opsetheadstring (hnew, bs);
00301         }
00302     
00303     #endif
00304     
00305     (**hnew).hrefcon = hdata; /*link in the user's data structure*/
00306     
00307     (**h).ctitems++;
00308 
00309     oppopoutline ();
00310 
00311     return (true);
00312 
00313     error:
00314         
00315         disposehandle (hdata);
00316 
00317         return (false);
00318     } /*opunshifthandle*/
00319     
00320 
00321 
00322 boolean oppushdata (hdllistrecord hlist, ptrstring pname, ptrvoid pdata, long ctbytes) {
00323     
00324     /*
00325     normally we have a statically allocated thing to link into a new list item.
00326     
00327     if you already have a handle, use oppushhandle to add an item to the list.
00328     */
00329     
00330     Handle h;
00331     
00332     if (!newfilledhandle (pdata, ctbytes, &h))
00333         return (false);
00334     
00335     return (oppushhandle (hlist, pname, h));
00336     } /*oppushdata*/
00337 
00338 
00339 boolean oppushstring (hdllistrecord hlist, ptrstring pname, bigstring bs) {
00340     
00341     /*
00342     add a new item to a list that's just storing strings.
00343     */
00344 
00345     return (oppushdata (hlist, pname, bs, (long) stringsize (bs)));
00346     } /*oppushstring*/
00347     
00348 
00349 static boolean opgetlistnode (hdllistrecord hlist, long ix, ptrstring pname, hdlheadrecord *hnode) {
00350     
00351     /*
00352     should be an internal routine -- this guy returns the outline headrecord for
00353     the indicated index into the list.
00354     */
00355     
00356     hdloutlinerecord ho;
00357     hdlheadrecord nomad;
00358     bigstring bshead;
00359     
00360     *hnode = nil;
00361     
00362     if (hlist == nil) /*defensive driving*/
00363         return (false);
00364     
00365     ho = (hdloutlinerecord) (**hlist).houtline;
00366 
00367     if (ix == -1 && pname != nil) { /*looking up by name*/
00368         
00369         if (!(**hlist).isrecord)
00370             return (false);
00371         
00372         for (nomad = (**ho).hsummit; ; ) {
00373             
00374             opgetheadstring (nomad, bshead);
00375             
00376             if (equalstrings (bshead, pname)) {
00377                 
00378                 *hnode = nomad;
00379 
00380                 return (true);
00381                 }
00382 
00383             if (!opchasedown (&nomad))
00384                 return (false);
00385             }
00386         }
00387     else {
00388         if ((ix < 1) || (ix > (**hlist).ctitems))
00389             return (false);
00390         
00391         *hnode = oprepeatedbump (down, ix - 1, (**ho).hsummit, false);
00392         
00393         return (true);
00394         }
00395     } /*opgetlistnode*/
00396 
00397 
00398 boolean opgetlisthandle (hdllistrecord hlist, long ix, ptrstring pname, Handle *hdata) {
00399     
00400     /*
00401     the user's data is stored in the refcon handle in each headrecord.
00402     
00403     we index through the list, to the ixth item, and return the refcon
00404     handle for that list item.
00405     
00406     ix is 1-based.  the first item is item #1 and so on.
00407     
00408     return false if there aren't ix items in the list.
00409     */
00410     
00411     hdlheadrecord hnode;
00412     
00413     if (!opgetlistnode (hlist, ix, pname, &hnode))
00414         return (false);
00415     
00416     if (pname != nil)
00417         opgetheadstring (hnode, pname);
00418     
00419     *hdata = (**hnode).hrefcon;
00420     
00421     return (true);
00422     } /*opgetlisthandle*/
00423     
00424     
00425 boolean opgetliststring (hdllistrecord hlist, long ix, ptrstring pname, bigstring bs) {
00426     
00427     Handle h;
00428     
00429     if (!opgetlisthandle (hlist, ix, pname, &h)) {
00430         
00431         setstringlength (bs, 0);
00432         
00433         return (false);
00434         }
00435         
00436     copyheapstring ((hdlstring) h, bs);
00437     
00438     return (true);
00439     } /*opgetliststring*/
00440 
00441 
00442 boolean opsetlisthandle (hdllistrecord hlist, long ix, ptrstring pname, Handle hdata) {
00443     
00444     hdlheadrecord hnode;
00445     hdloutlinerecord ho = (hdloutlinerecord) (**hlist).houtline;
00446     boolean flpush;
00447     
00448     if (!opgetlistnode (hlist, ix, pname, &hnode)) {
00449         
00450         if (ix == -1 && pname != nil) //looking up by name*/
00451             flpush = (**hlist).isrecord;
00452         
00453         else
00454             flpush = (ix == (**hlist).ctitems + 1);
00455         
00456         if (flpush)
00457             return (oppushhandle (hlist, pname, hdata));
00458         
00459         disposehandle (hdata);
00460 
00461         return (false);
00462         }
00463     
00464     (*(**ho).releaserefconcallback) (hnode, true);
00465     
00466     disposehandle ((**hnode).hrefcon); /*get rid of the old handle*/
00467     
00468     (**hnode).hrefcon = hdata; /*link in the new one*/
00469     
00470     return (true);
00471     } /*opsetlistdata*/
00472 
00473 
00474 boolean opsetlistdata (hdllistrecord hlist, long ix, ptrstring pname, ptrvoid pdata, long ctbytes) {
00475     
00476     Handle hdata;
00477     
00478     if (!newfilledhandle (pdata, ctbytes, &hdata))
00479         return (false);
00480     
00481     return (opsetlisthandle (hlist, ix, pname, hdata));
00482     } /*opsetlistdata*/
00483 
00484 
00485 long opcountlistitems (hdllistrecord hlist) {
00486     
00487     return ((**hlist).ctitems);
00488     } /*opcountlistitems*/
00489 
00490 
00491 boolean opgetisrecord (hdllistrecord hlist) {
00492     
00493     /*
00494     2004-11-04 aradke: accessor function.
00495     */
00496 
00497     return ((**hlist).isrecord);
00498     } /*oplistisrecord*/
00499 
00500 
00501 void opsetisrecord (hdllistrecord hlist, boolean flisrecord) {
00502     
00503     /*
00504     2004-11-04 aradke: accessor function.
00505     */
00506 
00507     (**hlist).isrecord = flisrecord;
00508     } /*oplistisrecord*/
00509 
00510 
00511 oplistreleaseitemcallback opsetreleaseitemcallback (hdllistrecord hlist, oplistreleaseitemcallback cb) {
00512     
00513     /*
00514     2004-11-04 aradke: accessor function. set the callback and return previous callback.
00515     */
00516     
00517     oplistreleaseitemcallback oldcb = (**hlist).releaseitemcallback;
00518     
00519     (**hlist).releaseitemcallback = cb;
00520     
00521     return (oldcb);
00522     } /*opsetreleaseitemcallback*/
00523 
00524 
00525 static boolean opdeletelistnode (hdloutlinerecord ho, hdlheadrecord hdelete) {
00526     
00527     hdlheadrecord hother;
00528     
00529     hother = hdelete;
00530 
00531     if (!opchasedown (&hother) && !opchaseup (&hother)) // deleting only summit (flat outline)
00532         return (false);
00533     
00534     else {
00535         if ((**ho).hsummit == hdelete)
00536             (**ho).hsummit = hother;
00537         
00538         if ((**ho).hline1 == hdelete)
00539             (**ho).hline1 = hother;
00540         
00541         if ((**ho).hbarcursor == hdelete)
00542             (**ho).hbarcursor = hother;
00543         
00544         opunlink (hdelete);
00545 
00546         (**ho).ctexpanded--;
00547         
00548         if ((**hdelete).flmarked)
00549             (**ho).ctmarked --;
00550         }
00551     
00552     return (true);
00553     } /*opdeletelistnode*/
00554 
00555 
00556 boolean opdeletelistitem (hdllistrecord hlist, long ix, ptrstring pname) {
00557     
00558     hdlheadrecord hnode;
00559     hdloutlinerecord ho = (hdloutlinerecord) (**hlist).houtline;
00560     
00561     if (!opgetlistnode (hlist, ix, pname, &hnode))
00562         return (false);
00563     
00564     oppushoutline (ho);
00565     
00566     if (opdeletelistnode (ho, hnode))
00567         opreleasenode (hnode, false);
00568     else
00569         opemptyrefcon (hnode);
00570     
00571     oppopoutline ();
00572     
00573     (**hlist).ctitems--;
00574     
00575     return (true);
00576     } /*opdeletelistitem*/
00577 
00578 
00579 boolean oppacklist (hdllistrecord hlist, Handle *hpacked) {
00580     
00581     /*
00582     5.0b13 dmb: byteswap info.ctoutlinebytes
00583     */
00584     
00585     tydisklistrecord info;
00586     Handle hpackedoutline = nil;
00587     Handle hpackedlist = nil;
00588     boolean fl;
00589     
00590     if (!oppushoutline ((hdloutlinerecord) (**hlist).houtline))
00591         return (false);
00592         
00593     hpackedoutline = nil; /*allocate a new handle for packing*/
00594     
00595     fl = oppack (&hpackedoutline);
00596     
00597     oppopoutline ();
00598     
00599     if (!fl)
00600         return (false);
00601         
00602     clearbytes (&info, sizeof (info));
00603     
00604     info.recordsize = conditionalshortswap ((short) sizeof (info));
00605 
00606     info.versionnumber = conditionalshortswap (oplistversionnumber);
00607     
00608     info.isrecord = (**hlist).isrecord;
00609     
00610     // memlongtodiskwords ((**hlist).ctitems, info.ctitems, info.ctitems_hiword);
00611     
00612     if ((**hlist).ctitems > 0x7fff) // can't store it
00613         info.ctitems = -1;
00614     else
00615         info.ctitems = (**hlist).ctitems;
00616     
00617     memtodiskshort (info.ctitems);
00618 
00619     info.ctoutlinebytes = conditionallongswap (gethandlesize (hpackedoutline));
00620     
00621     if (!newfilledhandle (&info, sizeof (info), &hpackedlist))
00622         goto error;
00623     
00624     if (!pushhandle (hpackedoutline, hpackedlist))
00625         goto error;
00626         
00627     *hpacked = hpackedlist; /*returned handle*/
00628     
00629     disposehandle (hpackedoutline);
00630     
00631     return (true);
00632         
00633     error:
00634     
00635     oppopoutline ();
00636     
00637     disposehandle (hpackedoutline);
00638     
00639     disposehandle (hpackedlist);
00640     
00641     return (false);
00642     } /*oppacklist*/
00643     
00644     
00645 boolean opunpacklist (Handle hpacked, hdllistrecord *hnewlist) {
00646     
00647     /*
00648     5.0a17 dmb: preserve outlinedata.
00649     
00650     5.0b9 dmb: consume hpacked
00651     
00652     5.0b13 dmb: byteswap info.ctoutlinebytes
00653         
00654     2002-11-11 AR: Added assert to make sure the C compiler chose the
00655     proper byte alignment for the tydisklistrecord struct. If it did not,
00656     we would end up corrupting any database files we saved.
00657     */
00658     
00659     register hdllistrecord hlist = nil;
00660     hdloutlinerecord ho;
00661     long ixload = 0;
00662     tydisklistrecord info;
00663     Handle hpackedoutline = nil;
00664     boolean fl;
00665     
00666     assert (sizeof(tydisklistrecord) == 12L);
00667     
00668     if (!opnewlist (hnewlist, false)) /*create an empty list*/
00669         goto error;
00670     
00671     hlist = *hnewlist; /*copy into register*/
00672     
00673     clearbytes (&info, sizeof (info));
00674     
00675     // load first field - the record size
00676     if (!loadfromhandle (hpacked, &ixload, sizeof (info.recordsize), &info.recordsize))
00677         goto error;
00678     
00679     disktomemshort (info.recordsize);
00680     
00681     // load remaining data in record
00682     if (!loadfromhandle (hpacked, &ixload, min (sizeof (info), info.recordsize) - sizeof (info.recordsize), &info.versionnumber))
00683         goto error;
00684     
00685     disktomemshort (info.versionnumber);
00686     
00687     disktomemshort (info.ctitems);
00688     
00689     // disktomemshort (info.ctitems_hiword);
00690     
00691     disktomemlong (info.ctoutlinebytes);
00692     
00693     if (info.versionnumber == 0x0100) // handle pre-swapped objects (unswap) - 2004-10-31 aradke: was 0x01000000 but that's not a short!
00694         info.versionnumber = 0x01;
00695     
00696     if (info.versionnumber != oplistversionnumber) { /*we only read version 1 format lists*/
00697         
00698         shellinternalerror (idbadopversionnumber, STR_bad_list_version_number);
00699         
00700         goto error;
00701         }
00702     
00703     #if 1 // faster
00704         hpackedoutline = hpacked;
00705         
00706         hpacked = nil;
00707         
00708         if (!pullfromhandle (hpackedoutline, 0, info.recordsize, nil))
00709             goto error;
00710         
00711         if (gethandlesize (hpackedoutline) != (long) info.ctoutlinebytes) { //old, unbyteswapped?
00712             
00713             shortswap (info.ctitems);
00714             
00715             // shortswap (info.ctitems_hiword);
00716             
00717             longswap (info.ctoutlinebytes);
00718             
00719             info.isrecord = info.flunused;
00720             
00721             assert (gethandlesize (hpackedoutline) == (long) info.ctoutlinebytes);
00722             }
00723     
00724     #else // old code
00725         if (!loadfromhandletohandle (hpacked, &ixload, info.ctoutlinebytes, true, &hpackedoutline))
00726             goto error;
00727         
00728         disposehandle (hpacked);
00729         
00730         hpacked = nil;
00731     #endif
00732     
00733     // (**hlist).ctitems = makelong (info.ctitems, info.ctitems_hiword);
00734     (**hlist).ctitems = info.ctitems;
00735     
00736     (**hlist).isrecord = info.isrecord;
00737     
00738     ho = (hdloutlinerecord) (**hlist).houtline;
00739     
00740     opdisposeoutline (ho, false); /*opunpack will create a new one*/
00741     
00742     (**hlist).houtline = nil; /*don't leave it dangling*/
00743     
00744     fl = opunpackoutline (hpackedoutline, &ho);
00745     
00746     disposehandle (hpackedoutline);
00747     
00748     hpackedoutline = nil; /*so it won't get disposed in case of an error*/
00749     
00750     if (!fl)
00751         goto error;
00752         
00753     (**hlist).houtline = ho;
00754         
00755     if (info.ctitems == -1) { // couldn't store it; > 32K
00756         
00757         (**hlist).ctitems = opcountatlevel ((**ho).hsummit);
00758         }
00759     
00760     return (true);
00761     
00762     error:
00763     
00764     disposehandle (hpacked);
00765     
00766     opdisposelist (hlist);
00767     
00768     disposehandle (hpackedoutline);
00769     
00770     return (false);
00771     } /*opunpacklist*/
00772 
00773 
00774 boolean opcopylist (hdllistrecord hsource, hdllistrecord *hcopy) {
00775     
00776     /*
00777     5.0.2b12 dmb: new routine, so we don't have to pack/unpack
00778     */
00779     
00780     hdloutlinerecord ho;
00781     
00782     if (!copyhandle ((Handle) hsource, (Handle *) hcopy))
00783         return (false);
00784     
00785     if (!opcopyoutlinerecord ((**hsource).houtline, &ho)) {
00786         
00787         disposehandle ((Handle) *hcopy);
00788         
00789         return (false);
00790         }
00791     
00792     (***hcopy).houtline = ho;
00793     
00794     return (true);
00795     } /*opcopylist*/
00796 
00797 
00798 boolean oploadstringlist (short resnum, hdllistrecord *hnewlist) {
00799     
00800     register hdllistrecord hlist;
00801     register short ixlist;
00802     bigstring bs;
00803     
00804     if (!opnewlist (hnewlist, false)) /*create an empty list*/
00805         return (false);
00806     
00807     hlist = *hnewlist; /*copy into register*/
00808     
00809     ixlist = 1; /*STR# list indices begin at 1*/
00810     
00811     while (true) {
00812         
00813         if (!getstringlist (resnum, ixlist, bs)) 
00814             return (true);
00815         
00816         if (!oppushstring (hlist, nil, bs)) {
00817             
00818             opdisposelist (hlist);
00819             
00820             *hnewlist = nil;
00821             
00822             return (false);
00823             }
00824         
00825         ixlist++;
00826         } /*while*/
00827     } /*oploadstringlist*/
00828 
00829 
00830 boolean opvisitlist (hdllistrecord hlist, opvisitlistcallback visit, ptrvoid refcon) {
00831     
00832     /*
00833     2004-11-04 aradke: Visit all items in a list without recursion.
00834     The callback should return false to break out of the loop.
00835     */
00836     
00837     hdloutlinerecord ho;
00838     register hdlheadrecord nomad, nextnomad;
00839     bigstring bskey;
00840 
00841     /*
00842     2005-03-30 smd: if the list is empty, we're done.
00843     */
00844     if (opcountlistitems (hlist) == 0)
00845         return (true);
00846     
00847     ho = (hdloutlinerecord) (**hlist).houtline;
00848     
00849     nomad = (**ho).hsummit;
00850     
00851     while (true) {
00852         
00853         nextnomad = (**nomad).headlinkdown;
00854         
00855         opgetheadstring (nomad, bskey);
00856         
00857         if (!(*visit) ((**nomad).hrefcon, bskey, refcon))
00858             return (false);
00859             
00860         if (nextnomad == nomad) 
00861             break;
00862             
00863         nomad = nextnomad;
00864         } /*while*/
00865 
00866     return (true);
00867     } /*opvisitlist*/
00868 

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