opops.c

Go to the documentation of this file.
00001 
00002 /*  $Id: opops.c 1199 2006-04-05 22:17:27Z 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 "memory.h"
00032 #include "strings.h"
00033 #include "quickdraw.h"
00034 #include "bitmaps.h"
00035 #include "ops.h"
00036 #include "smallicon.h"
00037 #include "scrap.h"
00038 #include "op.h"
00039 #include "opinternal.h"
00040 #include "font.h"
00041 #include "search.h"
00042 #include "timedate.h"
00043 #include "process.h"
00044 
00045 
00046 
00047 typedef struct tyscanrecord { /*information for contains/find/search recursive scans*/
00048     
00049     hdlheadrecord hnodelookfor;
00050     
00051     hdlheadrecord hnodecurrent;
00052     
00053     long lnumlookfor;
00054     
00055     long lnumcurrent;
00056     
00057     boolean flfoundit;
00058     } tyscanrecord, *ptrscanrecord;
00059 
00060 
00061 
00062 
00063 short topoutlinestack = 0;
00064 
00065 hdloutlinerecord outlinestack [ctoutlinestack];
00066 
00067 
00068 hdloutlinerecord opsetoutline (hdloutlinerecord houtline) {
00069     
00070     /*
00071     5.1.5b7 dmb: carefully manage the setting of outlinedata
00072     
00073     return the value being set for convenience
00074     */
00075     
00076     hdloutlinerecord ho = outlinedata;
00077     
00078     if (houtline != ho) {
00079     
00080         outlinedata = houtline;
00081         
00082         if (houtline)
00083             (**houtline).ctpushes++;
00084         
00085         if (ho) {
00086             
00087             if ((--(**ho).ctpushes == 0) && (**ho).fldisposewhenpopped)
00088                 opdisposeoutline (ho, false);
00089             }
00090         }
00091     
00092     return (houtline);
00093     } /*opsetoutline*/
00094         
00095 
00096 boolean oppushoutline (hdloutlinerecord houtline) {
00097     
00098     /*
00099     when you want to temporarily work with a different outlinerecord, call this
00100     routine, do your stuff and then call oppopoutline.
00101     */
00102     
00103     if (topoutlinestack >= ctoutlinestack) {
00104         
00105         shellinternalerror (idoutlinestackfull, STR_outline_stack_overflow);
00106         
00107         return (false);
00108         }
00109     
00110     outlinestack [topoutlinestack++] = outlinedata;
00111     
00112     outlinedata = houtline;
00113     
00114     if (houtline)
00115         (**houtline).ctpushes++;
00116     
00117     return (true);
00118     } /*oppushoutline*/
00119         
00120 
00121 boolean oppopoutline (void) {
00122     
00123     hdloutlinerecord ho = outlinedata;
00124     
00125     if (topoutlinestack <= 0)
00126         return (false);
00127     
00128     outlinedata = outlinestack [--topoutlinestack];
00129     
00130     if (ho) {
00131         
00132         if ((--(**ho).ctpushes == 0) && (**ho).fldisposewhenpopped)
00133             opdisposeoutline (ho, false);
00134         }
00135     
00136     return (true);
00137     } /*oppopoutline*/
00138 
00139 
00140 boolean oppushglobals (void) {
00141     
00142     /*
00143     5.1.5b11 dmb: we need this layer for globals nesting
00144     */
00145 
00146     if (outlinedata)
00147         ++(**outlinedata).ctpushes;
00148     
00149     return (true);
00150     } /*oppushglobals*/
00151 
00152 
00153 boolean oppopglobals (void) {
00154     
00155     hdloutlinerecord ho = outlinedata;
00156     
00157     if (ho && (**ho).ctpushes > 1) // has been set and pushed
00158         --(**ho).ctpushes;
00159     
00160     return (true);
00161     } /*oppopglobals*/
00162 
00163 
00164 boolean opfirstinlist (hdlheadrecord hnode) {
00165     
00166     return ((**hnode).headlinkup == hnode);
00167     } /*opfirstinlist*/
00168     
00169     
00170 boolean oplastinlist (hdlheadrecord hnode) {
00171     
00172     return ((**hnode).headlinkdown == hnode);
00173     } /*oplastinlist*/
00174     
00175 
00176 boolean opnosubheads (hdlheadrecord hnode) {
00177     
00178     /*
00179     note that we don't acount dynamic subs. we answer the 
00180     question: does it have subheads now?
00181     */
00182     
00183     return ((**hnode).headlinkright == hnode);
00184     } /*opnosubheads*/
00185     
00186 
00187 boolean ophassubheads (hdlheadrecord hnode) {
00188     
00189     /*
00190     unlike opnosubheads, we count dynamic subs has being there, 
00191     event if they're not physically present now.
00192     */
00193     
00194     if ((**hnode).headlinkright != hnode)
00195         return (true);
00196     
00197     return ((*(**outlinedata).hasdynamicsubscallback) (hnode));
00198     } /*ophassubheads*/
00199     
00200 
00201 boolean opislastsubhead (hdlheadrecord hnode) {
00202     
00203     return ((**hnode).headlinkdown == hnode);
00204     } /*opislastsubhead*/
00205     
00206     
00207 boolean opsubheadsexpanded (hdlheadrecord hnode) {
00208     
00209     register hdlheadrecord hkid = (**hnode).headlinkright;
00210     
00211     if (hkid == hnode) /*no subheads*/
00212         return (false);
00213         
00214     return ((**hkid).flexpanded);
00215     } /*opsubheadsexpanded*/
00216     
00217     
00218 boolean opsubordinateto (hdlheadrecord h1, hdlheadrecord h2) {
00219     
00220     /*
00221     return true if h1 is part of h2's suboutline.
00222     
00223     if h2 is in the path back to a summit from h1.
00224     */
00225     
00226     register hdlheadrecord x = h1, y = h2;
00227     
00228     if (x == y) /*a node is not subordinate to itself*/
00229         return (false);
00230     
00231     while (true) {
00232         
00233         if ((**x).headlevel == 0) /*at a summit, h1 is not subordinate to h2*/
00234             return (false);
00235         
00236         x = (**x).headlinkleft; /*move towards a summit*/
00237         
00238         if (x == y) /*x is subordinate to y*/
00239             return (true);
00240         } /*while*/
00241     } /*opsubordinateto*/
00242     
00243     
00244 boolean opnestedincomment (hdlheadrecord hnode) {
00245     
00246     /*
00247     return true if the node is subordinate to a comment line, or if it is
00248     a comment line itself.
00249     */
00250     
00251     register hdlheadrecord x = hnode;
00252     
00253     while (true) {
00254         
00255         if ((**x).flcomment) /*it is nested inside a comment*/
00256             return (true);
00257             
00258         if ((**x).headlevel <= 0) /*can't surface any further*/
00259             return (false);
00260             
00261         x = (**x).headlinkleft;
00262         } /*while*/
00263     } /*opnestedincomment*/
00264     
00265       
00266 hdlheadrecord opgetancestor (hdlheadrecord hnode, short level) {
00267     
00268     /*
00269     surface out from hnode until you reach a node at the indicated level.
00270     
00271     interesting function -- it's used in implementing dragging move.
00272     */
00273     
00274     register hdlheadrecord nomad = hnode;
00275     register short headlevel;
00276     
00277     while (true) {
00278         
00279         headlevel = (**nomad).headlevel;
00280         
00281         if (headlevel <= level) /*surfaced out far enough*/
00282             return (nomad);
00283             
00284         if (headlevel <= 0) /*internal error*/
00285             return (nil);
00286             
00287         nomad = (**nomad).headlinkleft;
00288         } /*while*/
00289     } /*opgetancestor*/
00290     
00291     
00292 hdlheadrecord opgetlastsubhead (hdlheadrecord hnode) {
00293     
00294     /*
00295     return a handle to the last line subordinate to the node.
00296     */
00297     
00298     register hdlheadrecord nomad = (**hnode).headlinkright;
00299     register hdlheadrecord nextnomad;
00300     
00301     if (nomad == hnode)
00302         return (hnode);
00303         
00304     while (true) {
00305         
00306         nextnomad = (**nomad).headlinkdown;
00307         
00308         if (nextnomad == nomad) /*reached the last subhead*/
00309             return (nomad);
00310             
00311         nomad = nextnomad; /*advance to next node*/
00312         } /*while*/
00313     } /*opgetlastsubhead*/
00314     
00315       
00316 hdlheadrecord opnthsubhead (hdlheadrecord hnode, long n) {
00317     
00318     /*
00319     return the nth subhead of the indicated node, nil if he doesn't have
00320     that many subheads.
00321     
00322     the number is 1-based, so the first sub is returned when n == 1.
00323     */
00324     
00325     register hdlheadrecord h = hnode;
00326     register hdlheadrecord nomad = (**h).headlinkright;
00327     register hdlheadrecord nextnomad;
00328     register long i;
00329     
00330     if (n <= 0) /*special case*/
00331         return (h);
00332     
00333     if (nomad == h) /*no subs*/
00334         return (nil);
00335     
00336     for (i = 1; i < n; i++) {
00337         
00338         nextnomad = (**nomad).headlinkdown;
00339         
00340         if (nextnomad == nomad) /*aren't that many subs*/
00341             return (nil);
00342             
00343         nomad = nextnomad; /*advance to next sub*/
00344         } /*for*/
00345         
00346     return (nomad);
00347     } /*opnthsubhead*/
00348     
00349     
00350 boolean opnthsummit (long n, hdlheadrecord *hsummit) {
00351     
00352     /*
00353     return the nth summit of the current structure in *hsummit.
00354     
00355     return true if there are that many summits, false otherwise.
00356     */
00357     
00358     register hdlheadrecord nomad = (**outlinedata).hsummit;
00359     register hdlheadrecord nextnomad;
00360     register long ctloops = n - 1;
00361     register long i;
00362     
00363     for (i = 1; i <= ctloops; i++) {
00364         
00365         nextnomad = (**nomad).headlinkdown;
00366         
00367         if (nextnomad == nomad) { /*reached the end of the list, less than n summits*/
00368             
00369             *hsummit = nomad;
00370             
00371             return (false);
00372             }
00373             
00374         nomad = nextnomad;
00375         } /*for*/
00376         
00377     *hsummit = nomad;
00378     
00379     return (true);
00380     } /*opnthsummit*/
00381 
00382 
00383 static boolean opgetnthnodevisit (hdlheadrecord hnode, ptrvoid refcon) {
00384 
00385     ptrscanrecord scanrecord = (ptrscanrecord) refcon;
00386     
00387     if ((*scanrecord).lnumcurrent == (*scanrecord).lnumlookfor) { /*we're at the node*/
00388         
00389         (*scanrecord).hnodecurrent = hnode;
00390         
00391         return (false); /*terminate the traversal*/
00392         }
00393     
00394     (*scanrecord).lnumcurrent++; 
00395     
00396     return (true); /*continue the traversal*/
00397     } /*opgetnthnodevisit*/
00398 
00399 
00400 boolean opgetnthnode (long lnum, hdlheadrecord *hnode) {
00401     
00402     /*
00403     traverse the outline, counting nodes until we hit the line
00404     numbered "lnum".  return that node.
00405     
00406     if there aren't that many headlines, return false
00407     */
00408     
00409     tyscanrecord scanrecord;
00410     
00411     scanrecord.lnumcurrent = 1; /*counts the lines, start with line 1*/
00412     
00413     scanrecord.lnumlookfor = lnum; /*this is the line we're looking for*/
00414     
00415     if (opsiblingvisiter ((**outlinedata).hsummit, false, &opgetnthnodevisit, &scanrecord)) /*not enough lines*/
00416         return (false);
00417     
00418     *hnode = scanrecord.hnodecurrent;
00419     
00420     return (true);
00421     } /*opgetnthnode*/
00422     
00423 
00424 boolean oparrayreference (long ix, hdlheadrecord *hnode) {
00425     
00426     /*
00427     view the outline as an array.  return the string linked into the ixth summit.
00428     */
00429     
00430     return (opnthsummit (ix, hnode));
00431     } /*oparrayreference*/
00432     
00433       
00434 hdlheadrecord oplastexpanded (hdlheadrecord hnode) {
00435     
00436     /*
00437     return the last expanded subhead under hnode.  if it has no subheads
00438     or it is not expanded, we return hnode itself.
00439     */
00440     
00441     register hdlheadrecord h = hnode;
00442     
00443     while (true) {
00444     
00445         if (!opsubheadsexpanded (h))
00446             return (h);
00447             
00448         h = opgetlastsubhead (h);
00449         } /*while*/
00450     } /*oplastexpanded*/
00451     
00452 
00453 hdlheadrecord oplastexpandedatlevel (hdlheadrecord hnode, short level) {
00454     
00455     /*
00456     return the last expanded subhead under hnode.  if it has no subheads
00457     or it is not expanded, we return hnode itself.
00458     
00459     repeat until you hit a node whose headlevel == level.
00460     
00461     supports the dragging move operation.
00462     */
00463     
00464     register hdlheadrecord h = hnode;
00465     
00466     while (true) {
00467     
00468         if (!opsubheadsexpanded (h))
00469             return (h);
00470             
00471         if ((**h).headlevel == level)
00472             return (h);
00473             
00474         h = opgetlastsubhead (h);
00475         } /*while*/
00476     } /*oplastexpandedatlevel*/
00477     
00478 
00479 boolean opchaseup (hdlheadrecord *hnode) {
00480     
00481     register hdlheadrecord h = *hnode;
00482     register hdlheadrecord hup;
00483     
00484     if (h == nil) /*defensive driving*/
00485         return (false);
00486         
00487     hup = (**h).headlinkup;
00488     
00489     if (hup == h)
00490         return (false);
00491         
00492     *hnode = hup;
00493     
00494     return (true);
00495     } /*opchaseup*/
00496     
00497     
00498 boolean opchasedown (hdlheadrecord *hnode) {
00499     
00500     register hdlheadrecord h = *hnode;
00501     register hdlheadrecord hdown;
00502     
00503     if (h == nil) /*defensive driving*/
00504         return (false);
00505         
00506     hdown = (**h).headlinkdown;
00507     
00508     if (hdown == h)
00509         return (false);
00510         
00511     *hnode = hdown;
00512     
00513     return (true);
00514     } /*opchasedown*/
00515     
00516     
00517 boolean opchaseleft (hdlheadrecord *hnode) {
00518     
00519     register hdlheadrecord h = *hnode;
00520     register hdlheadrecord hleft;
00521     
00522     if (h == nil) /*defensive driving*/
00523         return (false);
00524         
00525     hleft = (**h).headlinkleft;
00526     
00527     if (hleft == h)
00528         return (false);
00529         
00530     *hnode = hleft;
00531     
00532     return (true);
00533     } /*opchaseleft*/
00534     
00535     
00536 boolean opchaseright (hdlheadrecord *hnode) {
00537     
00538     register hdlheadrecord h = *hnode;
00539     register hdlheadrecord hright;
00540     
00541     if (h == nil) /*defensive driving*/
00542         return (false);
00543         
00544     hright = (**h).headlinkright;
00545     
00546     if (hright == h)
00547         return (false);
00548         
00549     *hnode = hright;
00550     
00551     return (true);
00552     } /*opchaseright*/
00553     
00554     
00555 void opsummitof (hdlheadrecord hnode, hdlheadrecord *hsummit) {
00556     
00557     *hsummit = hnode;
00558     
00559     while (opchaseleft (hsummit)) {}
00560     } /*opsummitof*/
00561     
00562     
00563 void opgetsiblingnumber (hdlheadrecord hnode, long *siblingnumber) {
00564     
00565     /*
00566     if hnode is the third head at its level, return 2.  in other words, it's a 
00567     zero-based index into the head's level.
00568     */
00569     
00570     register long ct = 0;
00571     
00572     while (opchaseup (&hnode))
00573         ct++;
00574         
00575     *siblingnumber = ct;
00576     } /*opgetsiblingnumber*/
00577     
00578     
00579 hdlheadrecord opgetnextexpanded (hdlheadrecord hnode) {
00580     
00581     /*
00582     DW 7/13/93: lots of routines want to bump flatdown, only looking at
00583     expanded nodes. this saves a little bit of space and time when 
00584     you have to iterate this way.
00585     */
00586     
00587     hdlheadrecord nomad = hnode;
00588     hdlheadrecord hcheck;
00589     
00590     hcheck = (**nomad).headlinkright;
00591     
00592     if (hcheck != nomad) { 
00593         
00594         if ((**hcheck).flexpanded)
00595             return (hcheck);
00596         }
00597         
00598     hcheck = (**nomad).headlinkdown; 
00599     
00600     if (hcheck != nomad) { 
00601         
00602         if ((**hcheck).flexpanded)
00603             return (hcheck);
00604         }
00605     
00606     while (true) {
00607         
00608         if ((**nomad).headlinkleft == nomad) /*at a summit, return the original node*/
00609             return (hnode); 
00610         
00611         nomad = (**nomad).headlinkleft; /*move out to parent*/
00612         
00613         hcheck = (**nomad).headlinkdown; /*check next sibling*/
00614         
00615         if (hcheck != nomad) { 
00616             
00617             if ((**hcheck).flexpanded)
00618                 return (hcheck);
00619             }
00620         } /*while*/
00621     } /*opgetnextexpanded*/
00622     
00623     
00624 hdlheadrecord opbumpflatdown (hdlheadrecord hnode, boolean flexpanded) {
00625     
00626     /*
00627     return the node that is flatdown from the indicated node.  if the boolean
00628     is true, then only expanded nodes are visited.
00629     
00630     if hnode points to the last node, return the node itself.
00631     */
00632     
00633     hdlheadrecord nomad = hnode;
00634     hdlheadrecord hcheck;
00635     
00636     if (flexpanded)
00637         return (opgetnextexpanded (hnode));
00638         
00639     hcheck = (**nomad).headlinkright;
00640     
00641     if (hcheck != nomad) 
00642         return (hcheck);
00643         
00644     hcheck = (**nomad).headlinkdown; /*check next sibling*/
00645     
00646     if (hcheck != nomad) 
00647         return (hcheck);
00648     
00649     while (true) {
00650         
00651         if ((**nomad).headlinkleft == nomad) /*at a summit*/
00652             return (hnode); 
00653         
00654         nomad = (**nomad).headlinkleft; /*move out to parent*/
00655         
00656         hcheck = (**nomad).headlinkdown; /*check next sibling*/
00657         
00658         if (hcheck != nomad) 
00659             return (hcheck);
00660         } /*while*/
00661     } /*opbumpflatdown*/
00662     
00663     
00664 hdlheadrecord opbumpflatup (hdlheadrecord hnode, boolean flexpanded) {
00665     
00666     /*
00667     12/28/91 dmb: handle flexpanded flag true when original node is collapsed
00668     
00669     5.1.5b9 dmb: recoded to not use opbumpflatdown; avoids infinite looping 
00670     in mis-expanded outlines
00671     */
00672     
00673     hdlheadrecord origh = hnode;
00674     hdlheadrecord lasth;
00675     
00676     if ((**hnode).headlinkup == hnode) { /*no way up*/
00677         
00678         if ((**hnode).headlinkleft != hnode) /*not at summit*/
00679             return ((**hnode).headlinkleft);
00680             
00681         return (origh); /*hnode is on the summit -- no movement*/
00682         }
00683     
00684     hnode = (**hnode).headlinkup; /*go to previous sibling*/
00685     
00686     if (flexpanded && !(**hnode).flexpanded) { /*special case*/
00687         
00688         if (hnode != origh) /*we moved, though still collapsed*/
00689             return (hnode);
00690         
00691         return ((**hnode).headlinkleft); /*bump out a level -- hopefully expanded*/
00692         }
00693     
00694     if (flexpanded)
00695         return (oplastexpanded (hnode));
00696     
00697     while (true) {
00698         
00699         lasth = hnode;
00700         
00701         hnode = opgetlastsubhead (hnode);
00702         
00703         if (hnode == lasth)
00704             return (hnode);
00705         } /*while*/
00706     } /*opbumpflatup*/
00707 
00708 
00709 hdlheadrecord oprepeatedbump (tydirection dir, long ctbumps, hdlheadrecord hstart, boolean flexpanded) {
00710     
00711     /*
00712     navigate from hstart in the indicated tydirection, ctbumps times.
00713     
00714     if flexpanded is true only visit nodes that are expanded.
00715     
00716     return the resulting node.
00717     
00718     this was designed early on, and doesn't return a boolean indicating whether
00719     it was able to move in the desired tydirection.
00720     */
00721     
00722     register hdlheadrecord nomad = hstart;
00723     register long ct = ctbumps;
00724     register boolean fl = flexpanded;
00725     register hdlheadrecord lastnomad;
00726     register long i;
00727     
00728     if (nomad == nil) /*defensive driving*/
00729         return (nil);
00730     
00731     if (ct == 0)
00732         goto L1;
00733     
00734     if (ct < 0) {
00735         
00736         ct = -ct;
00737         
00738         dir = oppositdirection (dir);
00739         }
00740     
00741     switch (dir) {
00742         
00743         case flatup:
00744             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00745                 
00746                 lastnomad = nomad;
00747                 
00748                 nomad = opbumpflatup (nomad, fl);
00749                 
00750                 if (nomad == lastnomad)
00751                     goto L1;
00752                 } /*for*/   
00753                 
00754             break;
00755             
00756         case flatdown:
00757             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00758                 
00759                 lastnomad = nomad;
00760                 
00761                 nomad = opbumpflatdown (nomad, fl);
00762                 
00763                 if (nomad == lastnomad)
00764                     goto L1;
00765                 } /*for*/   
00766                 
00767             break;
00768             
00769         case left:
00770             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00771                 
00772                 lastnomad = nomad;
00773                 
00774                 nomad = (**nomad).headlinkleft;
00775                 
00776                 if (nomad == lastnomad)
00777                     goto L1;
00778                 } /*for*/   
00779                 
00780             break;
00781             
00782         case right:
00783             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00784                 
00785                 lastnomad = nomad;
00786                 
00787                 nomad = (**nomad).headlinkright;
00788                 
00789                 if (nomad == lastnomad)
00790                     goto L1;
00791                 } /*for*/   
00792                 
00793             break;
00794             
00795         case up:
00796             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00797                 
00798                 lastnomad = nomad;
00799                 
00800                 nomad = (**nomad).headlinkup;
00801                 
00802                 if (nomad == lastnomad)
00803                     goto L1;
00804                 } /*for*/   
00805                 
00806             break;
00807             
00808         case down:
00809             for (i = 1; i <= ct; i++) { /*replicated code for speed*/
00810                 
00811                 lastnomad = nomad;
00812                 
00813                 nomad = (**nomad).headlinkdown;
00814                 
00815                 if (nomad == lastnomad)
00816                     goto L1;
00817                 } /*for*/   
00818                 
00819             break;
00820         
00821         default:
00822             /* do nothing */
00823             break;
00824             
00825         } /*switch*/
00826     
00827     L1:
00828             
00829     return (nomad);
00830     } /*oprepeatedbump*/
00831 
00832 
00833 boolean opnavigate (tydirection dir, hdlheadrecord *hnode) {
00834     
00835     /*
00836     yet another way to move through an outline structure.
00837     
00838     return true if you can navigate in the indicated tydirection.  return with
00839     *hnode pointing to the resulting node.
00840     */
00841     
00842     register hdlheadrecord h = *hnode;
00843     register hdlheadrecord hnext;
00844     
00845     hnext = oprepeatedbump (dir, 1, h, false);
00846     
00847     if (hnext == h) /*didn't move anywhere*/
00848         return (false);
00849         
00850     *hnode = hnext;
00851     
00852     return (true);
00853     } /*opnavigate*/
00854     
00855 
00856 boolean opfindhead (hdlheadrecord hfirst, bigstring bs, hdlheadrecord *hnode) {
00857     
00858     /*
00859     search starting with hfirst and step through its siblings looking
00860     for a headline that exactly matches bs.
00861     */
00862     
00863     register hdlheadrecord nomad, nextnomad;
00864     bigstring bsnomad;
00865     bigstring bslook;
00866     
00867     *hnode = nil; /*default returned value*/
00868     
00869     nomad = hfirst;
00870     
00871     copystring (bs, bslook); /*work on a copy*/
00872     
00873     alllower (bslook); /*unicase*/
00874     
00875     while (true) {
00876         
00877         opgetheadstring (nomad, bsnomad);
00878         
00879         alllower (bsnomad);
00880         
00881         if (equalstrings (bslook, bsnomad)) {
00882             
00883             *hnode = nomad;
00884             
00885             return (true);
00886             }
00887         
00888         nextnomad = (**nomad).headlinkdown;
00889         
00890         if (nextnomad == nomad)
00891             return (false);
00892             
00893         nomad = nextnomad;
00894         } /*while*/
00895     } /*opfindhead*/
00896     
00897 
00898 boolean opbestfind (hdlheadrecord hfirst, bigstring bs, hdlheadrecord *hnode) {
00899     
00900     /*
00901     find the best approximation of the string in the siblings of hfirst.
00902     */
00903     
00904     register hdlheadrecord nomad, nextnomad;
00905     bigstring bsnomad;
00906     bigstring bsfind;
00907     bigstring bsbest;
00908     register hdlheadrecord hbest = nil; /*no candidate found*/
00909     
00910     *hnode = nil; /*default returned value*/
00911     
00912     nomad = op1stsibling (hfirst);
00913     
00914     copystring (bs, bsfind); /*work on a copy*/
00915     
00916     alllower (bsfind); /*unicase*/
00917     
00918     while (true) {
00919         
00920         opgetheadstring (nomad, bsnomad);
00921         
00922         alllower (bsnomad);
00923         
00924         switch (comparestrings (bsnomad, bsfind)) {
00925             
00926             case 0: /*string equal*/
00927                 *hnode = nomad;
00928                 
00929                 return (true);
00930             
00931             case -1: /*key less than name*/
00932                 break;
00933             
00934             case +1: /*key greather than name*/
00935                 if ((hbest == nil) || (comparestrings (bsnomad, bsbest) == -1)) {
00936                     
00937                     copystring (bsnomad, bsbest);
00938                     
00939                     hbest = nomad;
00940                     }
00941             } /*switch*/
00942         
00943         nextnomad = (**nomad).headlinkdown;
00944         
00945         if (nextnomad == nomad)
00946             break;
00947             
00948         nomad = nextnomad;
00949         } /*while*/
00950     
00951     if (hbest == nil) /*didn't find any item that would follow bsname*/
00952         hbest = nomad; /*select last name*/
00953     
00954     *hnode = hbest;
00955     
00956     return (false);
00957     } /*opbestfind*/
00958 
00959 
00960 long opcountatlevel (hdlheadrecord hnode) {
00961     
00962     /*
00963     return the number of nodes down from the indicated node plus 1.
00964     
00965     xxx the name is kind of a misnomer, it returns the count at a level if you pass
00966     xxx in a handle to the first guy at the level.
00967     
00968     8/28/92 dmb: recoded to handle arbitrary node in list. slighly less optimal, 
00969     but simple.
00970     */
00971     
00972     register long ct = 0;
00973     hdlheadrecord nomad = hnode;
00974     
00975     if (nomad != nil) { /*defensive driving*/
00976         
00977         ct = 1;
00978         
00979         while (opchaseup (&nomad))
00980             ct++;
00981         
00982         nomad = hnode;
00983         
00984         while (opchasedown (&nomad))
00985             ct++;
00986         }
00987     
00988     return (ct);
00989     } /*opcountatlevel*/
00990     
00991     
00992 hdlheadrecord op1stsibling (hdlheadrecord hnode) {
00993     
00994     while (opchaseup (&hnode)) {}
00995     
00996     return (hnode);
00997     } /*op1stsibling*/
00998 
00999 
01000 long opcountsubs (hdlheadrecord hnode) {
01001     
01002     /*
01003     returns the number of first level subs underneath the indicated headrecord.
01004     */
01005     
01006     register hdlheadrecord hright = (**hnode).headlinkright;
01007     
01008     if (hright == hnode) /*no subs*/
01009         return (0);
01010         
01011     return (opcountatlevel (hright));
01012     } /*opcountsubs*/
01013 
01014 
01015 long opsetctexpanded (hdloutlinerecord ho) {
01016     
01017     /*
01018     when you load an outline, or do something too complex to maintain
01019     arithmetically, call this routine to brute force compute the number
01020     of expanded headlines.
01021     */
01022     
01023     hdlheadrecord nomad = (**ho).hsummit, nextnomad;
01024     long ct = 0;
01025     
01026     oppushoutline (ho);
01027     
01028     while (true) {
01029         
01030         ct += opgetnodelinecount (nomad);
01031         
01032         nextnomad = opgetnextexpanded (nomad);
01033         
01034         if (nextnomad == nomad) { /*could go no further*/
01035             
01036             (**ho).ctexpanded = ct;
01037             
01038             break;
01039             }
01040             
01041         nomad = nextnomad;
01042         } /*while*/
01043     
01044     oppopoutline ();
01045     
01046     return (ct);
01047     } /*opsetctexpanded*/
01048     
01049     
01050 void opsetexpandedbits (hdlheadrecord hsummit, boolean fl) {
01051     
01052     /*
01053     set the expanded bits of the node and all its siblings as indicated
01054     by the boolean.
01055     */
01056 
01057     register boolean bit = bitboolean (fl);
01058     register hdlheadrecord nomad = hsummit;
01059     register hdlheadrecord lastnomad;
01060     
01061     if (nomad == nil) /*defensive driving*/
01062         return;
01063     
01064     while (true) {
01065         
01066         (**nomad).flexpanded = bit;
01067         
01068         lastnomad = nomad;
01069         
01070         nomad = (**nomad).headlinkdown;
01071         
01072         if (nomad == lastnomad) 
01073             return;
01074         } /*while*/
01075     } /*opsetexpandedbits*/
01076 
01077 
01078 static boolean opcontainsvisit (hdlheadrecord hnode, ptrvoid refcon) {
01079     
01080     ptrscanrecord scanrecord = (ptrscanrecord) refcon;
01081     
01082     if (hnode == (*scanrecord).hnodelookfor) {
01083         
01084         (*scanrecord).flfoundit = true;
01085         
01086         return (false); /*halt the search*/
01087         }
01088         
01089     return (true); /*continue searching*/
01090     } /*opcontainsvisit*/
01091     
01092     
01093 boolean opcontainsnode (hdlheadrecord hlookunder, hdlheadrecord hlookfor) {
01094     
01095     /*
01096     traverse the structure indicated by hlookunder, searching for hlookfor.
01097     
01098     if it the node is found, return true, otherwise false.
01099     
01100     5.0.2b20 dmb: we must use opsiblingvisiter, not oprecursivelyvisit, and 
01101     search under all of hlookunder's level
01102     */
01103     
01104     tyscanrecord scanrecord;
01105     
01106     scanrecord.hnodelookfor = hlookfor;
01107     
01108     scanrecord.flfoundit = false;
01109     
01110     opsiblingvisiter (hlookunder, false, &opcontainsvisit, &scanrecord);
01111     
01112     return (scanrecord.flfoundit);
01113     } /*opcontainsnode*/
01114     
01115     
01116 void opgetnodeline (hdlheadrecord hnode, long *lnum) {
01117     
01118     /*
01119     get the node line number for the indicated node.  the first summit is
01120     node 0.  its first sub, if expanded, is node 1.
01121     
01122     we compute the number by bumping our way flatup until we can bump no more,
01123     counting nodes as we go.
01124     */
01125     
01126     register hdlheadrecord nomad = hnode;
01127     register hdlheadrecord lastnomad;
01128     register long ct = 0;
01129     
01130     while (true) {
01131         
01132         lastnomad = nomad;
01133         
01134         nomad = opbumpflatup (nomad, true);
01135         
01136         if (nomad == lastnomad) {
01137             
01138             *lnum = ct;
01139             
01140             return;
01141             }
01142             
01143         ct++;
01144         } /*while*/
01145     } /*opgetnodeline*/
01146 
01147 
01148 boolean opnewheadrecord (Handle hstring, hdlheadrecord *hnewnode) {
01149     
01150     /*
01151     create a new headline, without linking into any structure.
01152     */
01153     
01154     register hdlheadrecord h;
01155     Handle hnew;
01156     
01157     if (!newclearhandle (sizeof (tyheadrecord), &hnew)) {
01158         
01159         disposehandle (hstring);
01160         
01161         return (false);
01162         }
01163     
01164     h = *hnewnode = (hdlheadrecord) hnew; /*copy into register*/
01165     
01166     (**h).headstring = hstring;
01167     
01168     (**h).headlinkup = (**h).headlinkdown = (**h).headlinkleft = (**h).headlinkright = h;
01169     
01170     opnodechanged (h); 
01171     
01172     (**h).fldirty = true;
01173     
01174     return (true);
01175     } /*opnewheadrecord*/
01176  
01177 
01178 boolean opnewstructure (Handle hstring, hdlheadrecord *hsummit) {
01179 
01180     /*
01181     create a new summit for the current outline record.
01182     
01183     7/9/91 dmb: don't assign to hsummit until success
01184     */
01185     
01186     register hdlheadrecord hnode;
01187     
01188     if (!opnewheadrecord (hstring, hsummit))
01189         return (false);
01190     
01191     hnode = *hsummit; /*copy into register*/
01192     
01193     (**hnode).flexpanded = true;
01194     
01195     return (true);
01196     } /*opnewstructure*/
01197 
01198 
01199 boolean opreleasevisit (hdlheadrecord hnode, ptrvoid refcon) {
01200     
01201     register hdlheadrecord h = hnode;
01202     Handle hrefcon = (Handle) (**h).hrefcon;
01203     
01204     if (hrefcon != nil) { /*node has a refcon handle attached*/
01205     
01206         hdloutlinerecord x = outlinedata; /*preserve x over callback*/
01207         
01208         #if !fljustpacking
01209         
01210             (*(**outlinedata).releaserefconcallback) (hnode, (boolean) ((long) refcon));
01211             
01212             #endif
01213         
01214         opsetoutline (x); /*restore*/
01215         
01216         disposehandle (hrefcon); 
01217         }
01218     
01219     disposehandle ((**h).headstring);
01220     
01221     disposehandle ((Handle) h); 
01222     
01223     return (true);
01224     } /*opreleasevisit*/
01225 
01226 
01227 void opreleasenode (hdlheadrecord hnode, boolean fldisk) {
01228     
01229     opreleasevisit (hnode, (ptrvoid) ((long) fldisk));
01230     } /*opreleasenode*/
01231 
01232 
01233 static boolean opreleaserefconvisit (hdlheadrecord hnode, ptrvoid refcon) {
01234 #pragma unused (refcon)
01235 
01236     Handle hrefcon = (Handle) (**hnode).hrefcon;
01237     
01238     if (hrefcon != nil) { /*node has a refcon handle attached*/
01239     
01240         hdloutlinerecord x = outlinedata; /*preserve x over callback*/
01241         
01242         #if !fljustpacking
01243         
01244             (*(**outlinedata).releaserefconcallback) (hnode, true);
01245             
01246             #endif
01247         
01248         opsetoutline (x); /*restore*/
01249         
01250         disposehandle (hrefcon);
01251         
01252         (**hnode).hrefcon = nil;
01253         }
01254     
01255     return (true);
01256     } /*opreleaserefconvisit            */
01257 
01258 
01259 static boolean opresetalllevelsvisit (hdlheadrecord hnode, ptrvoid toplevel) {
01260     
01261     (**hnode).headlevel = (long) toplevel;
01262     
01263     opresetlevels (hnode);
01264     
01265     return (true);
01266     } /*opresetalllevelsvisit*/
01267 
01268 
01269 boolean opsetsummit (hdloutlinerecord houtline, hdlheadrecord hnode) {
01270     
01271     /*
01272     establish hnode as the summit of the indicated outline.  dispose of 
01273     the existing summit, if one exists.  also, make sure that the levels 
01274     of the outline are set correctly, starting at zero.
01275     
01276     5.0.2b15 dmb: set headlevels of all summits -- siblings of hnode
01277     */
01278     
01279     register hdloutlinerecord ho = houtline;
01280     register hdlheadrecord h = hnode;
01281     
01282     if ((**h).headlevel != 0)
01283         opbumpvisit (h, down, opresetalllevelsvisit, (ptrvoid) 0L);
01284     
01285     if ((**ho).hsummit != nil)
01286         opreleasenode ((**ho).hsummit, false);
01287     
01288     (**ho).hsummit = (**ho).hbarcursor = (**ho).hline1 = h;
01289     
01290     (**ho).line1linesabove = 0;
01291     
01292     /*
01293     (**ho).fldirty = true;
01294     */
01295     
01296     return (true);
01297     } /*opsetsummit*/
01298 
01299 
01300 boolean opnewsummit (void) {
01301     
01302     /*
01303     create a new, blank summit for the current outline.  link it into the
01304     structure accordingly.
01305     */
01306     
01307     Handle hstring;
01308     hdlheadrecord hnewsummit;
01309     
01310     if (!newemptyhandle (&hstring))
01311         return (false);
01312     
01313     if (!opnewstructure (hstring, &hnewsummit))
01314         return (false);
01315     
01316     return (opsetsummit (outlinedata, hnewsummit));
01317     } /*opnewsummit*/
01318 
01319 
01320 boolean optexttooutline (hdloutlinerecord houtline, Handle htext, hdlheadrecord *hnode) {
01321     
01322     register hdloutlinerecord ho = houtline;
01323     
01324     return ((*(**ho).texttooutlinecallback) (ho, htext, hnode));
01325     } /*optexttooutline*/
01326 
01327 
01328 boolean newoutlinerecord (hdloutlinerecord *houtline) {
01329     
01330     /*
01331     create a new outline record, returned in houtline.  we assume nothing
01332     about outlinewindowinfo or outlinewindow, and we preserve outlinedata.
01333     
01334     the rectangles and displayinfo are all zero after we're called.
01335     
01336     2.1b5 dmb: always initialize outlinesignature to LAND
01337     
01338     4.0b7 dmb: initialize timelastsave to creation time; it's really a modification date.
01339     */
01340     
01341     #if !fljustpacking
01342     
01343         tyconfigrecord lconfig;
01344     #endif
01345     
01346     register hdloutlinerecord ho;
01347     register boolean fl; 
01348     
01349     if (!newclearhandle (sizeof (tyoutlinerecord), (Handle *) houtline))
01350         return (false);
01351         
01352     ho = *houtline; /*copy into register*/
01353     
01354     oppushoutline (ho);
01355     
01356     fl = opnewsummit ();
01357     
01358     oppopoutline ();
01359         
01360     if (!fl) {  
01361     
01362         disposehandle ((Handle) ho);
01363         
01364         *houtline = nil;
01365         
01366         return (false);
01367         }
01368         
01369     (**ho).ctexpanded = 1; /*the summit line is expanded*/
01370     
01371     (**ho).lineindent = 15;
01372     
01373     (**ho).linespacing = oneandalittlespaced;
01374     
01375     (**ho).defaultlineheight = 12;
01376 
01377     (**ho).maxlinelen = 255;
01378     
01379     (**ho).flbarcursoron = true;
01380     
01381     (**ho).flusebitmaps = true;
01382     
01383     (**ho).flbuildundo = true;
01384     
01385     #if !fljustpacking
01386     
01387         (**ho).caretoffset = -1; /*no saved caret location on activation*/
01388     
01389         (**ho).selpoint.h = -1; /*no established horizontal cursor offset*/
01390     
01391     #endif
01392     
01393     opinitcallbacks (ho);
01394     
01395     (**ho).timecreated = (**ho).timelastsave = timenow ();
01396     
01397     (**ho).iconheight = 16; /*by default, use small icons*/
01398 
01399     (**ho).iconwidth = 16; /*by default, use small icons*/
01400         
01401     (**ho).pixelsaftericon = 3; /*skip this many pixels between icon and text*/
01402     
01403     (**ho).forecolor = blackcolor;
01404     
01405     (**ho).backcolor = whitecolor;
01406     
01407     (**ho).outlinescraptype = opscraptype;
01408     
01409     (**ho).outlinesignature = 'LAND';
01410     
01411     #if !fljustpacking
01412     
01413         shellgetconfig (idoutlineconfig, &lconfig);
01414     
01415         (**ho).windowrect = lconfig.defaultwindowrect; 
01416         
01417         (**ho).fontnum = lconfig.defaultfont;
01418         
01419         (**ho).fontsize = lconfig.defaultsize;
01420         
01421         (**ho).fontstyle = lconfig.defaultstyle;
01422     
01423     #endif
01424     
01425     return (true);
01426     } /*newoutlinerecord*/
01427     
01428     
01429 boolean opnewrecord (Rect r, hdloutlinerecord *hnew) {
01430     
01431     /*
01432     create a new outline record and fit it into outlinewindow.  if you want a new
01433     outlinerecord, but don't have a window around to display it in, call 
01434     newoutlinerecord instead.
01435     
01436     we also set the global outlinedata to point at the newly allocated record.
01437     */
01438 
01439     register hdloutlinerecord ho;
01440     
01441     opinitdisplayvariables ();
01442     
01443     if (!newoutlinerecord (hnew))
01444         return (false);
01445     
01446     ho = (hdloutlinerecord) *hnew;
01447     
01448     (**ho).outlinerect = r;
01449     
01450     #if !fljustpacking
01451 
01452         (**ho).fontnum = (**outlinewindowinfo).defaultfont;
01453     
01454         (**ho).fontsize = (**outlinewindowinfo).defaultsize;
01455     
01456         (**ho).fontstyle = (**outlinewindowinfo).defaultstyle;
01457         
01458         opsetdisplaydefaults (ho);
01459         
01460     #endif
01461     
01462     return (true);
01463     } /*opnewrecord*/
01464     
01465     
01466 void opdisposestructure (hdlheadrecord hnode, boolean fldisk) {
01467     
01468     /*
01469     dispose of the structure pointed to by hnode, including all his
01470     submaterial and all of his siblings' submaterial.
01471     
01472     be sure to unlink the node first, if you don't want all his siblings
01473     to be disposed of too...
01474     
01475     if fldisk, then all disk storage used by the structure is dealloc'd
01476     too.
01477     */
01478     
01479     opsiblingvisiter (hnode, true, &opreleasevisit, (ptrvoid) ((long) fldisk));
01480     } /*opdisposestructure*/
01481 
01482 
01483 static void opdisposerefcons (hdloutlinerecord ho) {
01484     
01485     oppushoutline (ho);
01486     
01487     opdisabledisplay ();
01488     
01489     oppopallhoists ();
01490     
01491     opsiblingvisiter ((**ho).hsummit, true, &opreleaserefconvisit, nil);
01492     
01493     oprestorehoists ();
01494     
01495     oppopoutline ();
01496     } /*opdisposerefcons*/
01497 
01498 
01499 void opdisposeoutline (hdloutlinerecord houtline, boolean fldisk) {
01500     
01501     /*
01502     5.0a10 dmb: if we're disposing outlinedata, nil the global
01503     
01504     5.1.5b7 dmb: ctpushes, fldisposewhenpopped replaces processinvalidoutline
01505     */
01506 
01507     register hdloutlinerecord ho = houtline;
01508     //long ix;
01509     
01510     if (ho == nil) /*defensive driving*/
01511         return;
01512     
01513     //processinvalidoutline (ho);
01514     
01515     if ((**ho).ctpushes > 0) {
01516         
01517         if (fldisk)
01518             opdisposerefcons (ho); //do this in current odb context
01519         
01520         (**ho).fldisposewhenpopped = true;
01521         
01522         return;
01523         }
01524     
01525     (**ho).fldisposewhenpopped = false;
01526     
01527     oppushoutline (ho); /*set the current outline to this one*/
01528     
01529     #if !fljustpacking
01530     
01531         while (oppophoist ()) {} /*pop all the hoists*/
01532         
01533         if ((**ho).hbuffer != nil) /*avoid smashing wp globals*/
01534             opeditdispose ();
01535         
01536         #endif
01537     
01538     opdisposestructure ((**ho).hsummit, fldisk);
01539     
01540     oppopoutline ();
01541         
01542     disposehandle ((Handle) ho);
01543 
01544     if (ho == outlinedata)
01545         outlinedata = nil;
01546     
01547     } /*opdisposeoutline*/
01548     
01549 
01550 hdlheadrecord opfirstatlevel (hdlheadrecord hnode) {
01551     
01552     /*
01553     shoot from hnode up to the first guy at his level, returning with
01554     a handle to the first guy.
01555     */
01556     
01557     register hdlheadrecord h = hnode;
01558     register hdlheadrecord next;
01559     
01560     if (h == nil) /*defensive driving*/
01561         return (nil);
01562         
01563     while (true) {
01564         
01565         next = (**h).headlinkup;
01566         
01567         if (next == h) /*no way to go*/
01568             return (h);
01569             
01570         h = next;
01571         } /*while*/
01572     } /*opfirstatlevel*/
01573     
01574 
01575 static boolean opcountvisit (hdlheadrecord hnode, ptrvoid refcon) {
01576 #pragma unused (hnode)
01577 
01578     (*(long*)refcon)++; /*the simplest visit routine*/
01579     
01580     return (true);
01581     } /*opcountvisit*/
01582     
01583     
01584 long opcountsubheads (hdlheadrecord hnode, short level) {
01585     
01586     long count = 0;
01587     
01588     oprecursivelyvisit (hnode, level, &opcountvisit, &count);
01589     
01590     return (count);
01591     } /*opcountsubheads*/
01592     
01593     
01594 long opcountheads (void) {
01595     
01596     /*
01597     return the number of headlines linked into the current outline record.
01598     */
01599     
01600     hdlheadrecord nomad = (**outlinedata).hsummit;
01601     long ct = 0;
01602     
01603     while (true) {
01604         
01605         ct += opcountsubheads (nomad, infinity) + 1;
01606         
01607         if (!opchasedown (&nomad))
01608             return (ct);
01609         } /*while*/
01610     } /*opcountheads*/
01611     
01612 
01613 static boolean opnotinoutlinevisit (hdlheadrecord hnode, ptrvoid refcon) {
01614     
01615     return (hnode != (*(ptrscanrecord)refcon).hnodelookfor);
01616     } /*opnotinoutlinevisit*/
01617 
01618 
01619 boolean opnodeinoutline (hdlheadrecord hnode) {
01620     
01621     /*
01622     return true if the given node is in the outline somewhere
01623     */
01624     
01625     register hdloutlinerecord ho = outlinedata;
01626     tyscanrecord scanrecord;
01627     
01628     scanrecord.hnodelookfor = hnode;
01629     
01630     if (opsiblingvisiter ((**ho).hsummit, false, &opnotinoutlinevisit, &scanrecord)) /*no match found*/
01631         return (false);
01632     
01633     return (true);
01634     } /*opnodeinoutline*/
01635 
01636 
01637 static boolean opresetlevelsvisit (hdlheadrecord hnode, ptrvoid refcon) {
01638 #pragma unused (refcon)
01639 
01640     register hdlheadrecord h = hnode;
01641     
01642     (**h).headlevel = (**(**h).headlinkleft).headlevel + 1;
01643     
01644     return (true);
01645     } /*opresetlevelsvisit*/
01646     
01647     
01648 void opresetlevels (hdlheadrecord hnode) {
01649 
01650     oprecursivelyvisit (hnode, infinity, &opresetlevelsvisit, nil);
01651     } /*opresetlevels*/
01652 
01653 
01654 void oppushstyle (hdloutlinerecord ho) {
01655     
01656     pushstyle ((**ho).fontnum, (**ho).fontsize, (**ho).fontstyle);
01657     } /*oppushstyle*/
01658 
01659 
01660 void oppushcolors (hdloutlinerecord ho) {
01661     
01662     pushcolors (&(**ho).forecolor, &(**ho).backcolor);
01663     } /*oppushcolors*/
01664 
01665 
01666 boolean opsetactualheadstring (hdlheadrecord hnode, bigstring newstring) {
01667     
01668     return (sethandlecontents (stringbaseaddress (newstring), stringlength (newstring), (**hnode).headstring));
01669     } /*opsetactualheadstring*/
01670 
01671 
01672 boolean opsetheadtext (hdlheadrecord hnode, Handle hstring) {
01673     
01674     /*
01675     4/3/92 dmb: moved call to textchangedcallback into this bottleneck so 
01676     that find/replace and op.setlinetext will update menubar items properly.
01677     call used to be in opwriteeditbuffer
01678     
01679     8/14/93 DW: if the node's tmpbit is set, we display the line before
01680     calling the callback. in clay basket the callback can reorder the 
01681     outline. too much for a human mind to parse while doing a find/replace.
01682     
01683     8/15/93 DW: leave the tmp bit set over call to callback, so that
01684     the browser can avoid re-inserting the node, again for find & replace.
01685     we don't keep the lists sorted, to make things fast, avoid jumpiness,
01686     and also to keep the search order intact (!).
01687     
01688     5.0d14 dmb: do as little as possible when the head string isn't changing.
01689     */
01690     
01691     register hdlheadrecord h = hnode;
01692     Handle horig;
01693     bigstring bsorig;
01694     
01695     opgetheadstring (hnode, bsorig);
01696     
01697     horig = (**hnode).headstring;
01698     
01699     (**hnode).headstring = hstring;
01700     
01701     if (equalhandles (horig, hstring))
01702         disposehandle (horig);
01703     
01704     else {
01705         
01706         opnodechanged (h);
01707         
01708         (**h).fldirty = true;
01709         
01710         opdirtyoutline ();
01711         
01712         if ((**h).tmpbit) { /*special for clay basket, find & replace: update line now*/
01713         
01714             opinvalnode (h);
01715         
01716             opupdatenow ();
01717             }
01718         
01719         if (!(*(**outlinedata).textchangedcallback) (h, bsorig)) {
01720             
01721             /*DW 8/31/93 -- file rename in cb failed*/
01722             
01723             (**hnode).headstring = horig;
01724             
01725             disposehandle (hstring);
01726             }
01727         else
01728             disposehandle (horig);
01729         }
01730             
01731     (**h).tmpbit = false; /*consume the bit*/
01732 
01733     return (true);
01734     } /*opsetheadtext*/
01735 
01736 
01737 boolean opsetheadstring (hdlheadrecord hnode, bigstring bs) {
01738     
01739     /*
01740     6.0a1 dmb: use handles
01741     */
01742     
01743     Handle hstring;
01744     
01745     if (!newtexthandle (bs, &hstring))
01746         return (false);
01747     
01748     return (opsetheadtext (hnode, hstring));
01749     } /*opsetheadstring*/
01750     
01751     
01752 boolean opsetcursorlinetext (bigstring bs) {
01753     
01754     boolean fl;
01755     hdlheadrecord hcursor;
01756     
01757     opsettextmode (false);
01758     
01759     hcursor = (**outlinedata).hbarcursor;
01760     
01761     fl = opsetheadstring (hcursor, bs);
01762     
01763     if (fl) {
01764         
01765         opinvalnode (hcursor);
01766         
01767         opupdatenow ();
01768         }
01769     
01770     return (fl);    
01771     } /*opsetcursorlinetext*/
01772 
01773 
01774 boolean opgetheadstring (hdlheadrecord hnode, bigstring bs) {
01775     
01776     if (hnode == nil) 
01777         setstringlength (bs, 0);
01778     else
01779         texthandletostring ((**hnode).headstring, bs);
01780     
01781     return (true);
01782     } /*opgetheadstring*/
01783 
01784 
01785 void opgetsortstring (hdlheadrecord hnode, bigstring bs) {
01786     
01787     opgetheadstring (hnode, bs);
01788     
01789     if (searchparams.flunicase)
01790         alllower (bs);      
01791     } /*opgetsortstring*/
01792 
01793 
01794 void opcopyformatting (hdloutlinerecord hsource, hdloutlinerecord hdest) {
01795     
01796     /*
01797     5.0.2b12 dmb: copy outlinerect and windowrect too
01798     */
01799     
01800     register hdloutlinerecord ho1 = hsource;
01801     register hdloutlinerecord ho2 = hdest;
01802     
01803     (**ho2).fontnum = (**ho1).fontnum;
01804     
01805     (**ho2).fontsize = (**ho1).fontsize;
01806     
01807     (**ho2).fontstyle = (**ho1).fontstyle;
01808     
01809     (**ho2).lineindent = (**ho1).lineindent;
01810     
01811     (**ho2).linespacing = (**ho1).linespacing;
01812     
01813     (**ho2).outlinerect = (**ho1).outlinerect;
01814     
01815     (**ho2).windowrect = (**ho1).windowrect;
01816     } /*opcopyformatting*/
01817 
01818 
01819 

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