opdisplay.c

Go to the documentation of this file.
00001 
00002 /*  $Id: opdisplay.c 1208 2006-04-05 23:51:45Z 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 "font.h"
00033 #include "quickdraw.h"
00034 #include "bitmaps.h"
00035 #include "kb.h"
00036 #include "smallicon.h"
00037 #include "strings.h"
00038 #include "frontierwindows.h"
00039 #include "ops.h"
00040 #include "textdisplay.h"
00041 #include "op.h"
00042 #include "opinternal.h"
00043 #include "oplineheight.h"
00044 #include "opicons.h"
00045 #include "opdisplay.h"
00046 #include "shellprint.h"
00047 #include "wpengine.h"
00048 
00049 
00050 #define flstructurelines true
00051 
00052 
00053 static RGBColor invertedbackcolor, invertedtextcolor;
00054 
00055 
00056 
00057 
00058 boolean opinitdisplayvariables (void) {
00059     
00060     invertedbackcolor = blackcolor;
00061     
00062     invertedtextcolor = whitecolor;
00063     
00064     return (true);
00065     } /*opinitdisplayvariables*/
00066 
00067 
00068 short opnodeindent (hdlheadrecord hnode) {
00069     
00070     register hdloutlinerecord ho = outlinedata;
00071     
00072     return (((**ho).lineindent * (**hnode).headlevel) - (**ho).horizscrollinfo.cur);
00073     } /*opnodeindent*/
00074     
00075     
00076 boolean opdefaultgettextrect (hdlheadrecord hnode, const Rect *linerect, Rect *textrect) {
00077     
00078     /*
00079     5.0a4 dmb: don't do the vert insetting here. For shaping the cursor, and
00080     deciding of a click is in text, we want to use the full headline height.
00081     so, we need to inset when drawing instead.
00082 
00083     6.0a13 dmb: account for horiz scrolling for fat healines
00084     */
00085     
00086     register hdloutlinerecord ho = outlinedata;
00087     Rect r;
00088     
00089     r = *linerect; 
00090     
00091     /*
00092     r.top += textvertinset;
00093     
00094     r.bottom -= textvertinset;
00095     */
00096     
00097     r.left += 
00098         opnodeindent (hnode) + (**ho).iconwidth + 
00099         
00100         (**ho).pixelsaftericon + 
00101         
00102         texthorizinset;
00103     
00104     r.right -= texthorizinset;
00105     
00106     if (opisfatheadlines (ho))
00107         r.right -= (**ho).horizscrollinfo.cur;
00108 
00109     *textrect = r;
00110     
00111     return (true);
00112     } /*opdefaultgettextrect*/
00113 
00114 
00115 void opgettextrect (hdlheadrecord hnode, const Rect *linerect, Rect *textrect) {
00116     
00117     (*(**outlinedata).gettextrectcallback) (hnode, linerect, textrect);
00118     } /*opgettextrect*/
00119 
00120 
00121 static boolean opmeasuretext (hdlheadrecord hnode) {
00122     
00123     bigstring bs;
00124     short pix;
00125     
00126     // thin headlines are easy to measure
00127     opgetheadstring (hnode, bs);
00128     
00129     oppushheadstyle (hnode);
00130     
00131     pix = stringpixels (bs) + (2 * texthorizinset);
00132     
00133     popstyle ();
00134     
00135     (**hnode).hpixels = pix;
00136     
00137     // height is even easier
00138     (**hnode).vpixels = (**outlinedata).defaultlineheight;
00139     
00140     return (true);
00141     } /*opmeauretext*/
00142 
00143 
00144 boolean opdefaultgetlineheight (hdlheadrecord hnode, short *lh) {
00145     
00146     hdloutlinerecord ho = outlinedata;
00147     
00148     if ((**hnode).vpixels == opdirtymeasurevalue) {
00149         
00150         if (opisfatheadlines (ho))
00151             opeditmeasuretext (hnode);
00152         else
00153             opmeasuretext (hnode);
00154         }
00155     
00156     *lh = (**hnode).vpixels + (2 * textvertinset);
00157     
00158     return (true);
00159     } /*opdefaultgetlineheight*/
00160 
00161 
00162 boolean opdefaultgetlinewidth (hdlheadrecord hnode, short *lw) {
00163     
00164     hdloutlinerecord ho = outlinedata;
00165     
00166     if ((**hnode).hpixels == opdirtymeasurevalue) {
00167         
00168         if (opisfatheadlines (ho))
00169             opeditmeasuretext (hnode);
00170         else
00171             opmeasuretext (hnode);
00172         }
00173     
00174     *lw = (**hnode).hpixels + (texthorizinset); // 6.0a13 dmb: not 2x horizinset
00175     
00176     return (true);
00177     } /*opdefaultgetlinewidth*/
00178 
00179 
00180 short opgetlineheight (hdlheadrecord hnode) {
00181     
00182     short lh;
00183     
00184     (*(**outlinedata).getlineheightcallback) (hnode, &lh);
00185         
00186     return (lh);
00187     } /*opgetlineheight*/
00188 
00189 
00190 short opgetlinewidth (hdlheadrecord hnode) {
00191     
00192     short lw;
00193     
00194     (*(**outlinedata).getlinewidthcallback) (hnode, &lw);
00195         
00196     return (lw);
00197     } /*opgetlinewidth*/
00198 
00199 
00200 long opgetnodelinecount (hdlheadrecord hnode) {
00201     
00202     register hdloutlinerecord ho = outlinedata;
00203     
00204     if (opisfatheadlines (ho))
00205         return (opgetlineheight (hnode) / (**ho).defaultlineheight);
00206     else
00207         return (1);
00208     } /*opgetnodelinecount*/
00209 
00210 
00211 boolean opdefaultgetfullrect (hdlheadrecord hnode, Rect *fullrect) {
00212     
00213     /*
00214     get the sum of the text rect and the icon rect for the indicated
00215     node. set the width of the rectangle to reflect the width of the
00216     text being displayed in the node.
00217     */
00218 
00219     Rect linerect, iconrect, textrect;
00220     
00221     linerect = *fullrect;
00222     
00223     opgeticonrect (hnode, &linerect, &iconrect);
00224     
00225     opgettextrect (hnode, &linerect, &textrect);
00226     
00227     textrect.right = textrect.left + opgetlinewidth (hnode);
00228     
00229     if ((**outlinedata).flneedfulliconheight)
00230         unionrect (iconrect, textrect, fullrect);
00231     
00232     else {
00233         *fullrect = textrect;
00234         
00235         (*fullrect).left = iconrect.left;
00236         }
00237     
00238     return (true);
00239     } /*opdefaultgetfullrect*/
00240     
00241 
00242 static void opgetfullrect (hdlheadrecord hnode, Rect *fullrect) {
00243 
00244     opgetnoderect (hnode, fullrect);
00245 
00246     (*(**outlinedata).getfullrectcallback) (hnode, fullrect);
00247     } /*opgetfullrect*/
00248     
00249 
00250 void oppushheadstyle (hdlheadrecord hnode) {
00251     
00252     (*(**outlinedata).pushstylecallback) (hnode);
00253     } /*oppushheadstyle*/
00254     
00255     
00256 static boolean oprectneedsupdate (Rect r) {
00257 
00258     #ifdef appletinclude
00259     
00260         return (apprectneedsupdate (r));
00261     
00262     #else
00263     
00264         return (shellrectneedsupdate (&r)); 
00265     
00266     #endif
00267     } /*oprectneedsupdate*/
00268 
00269 
00270 boolean opdisabledisplay (void) {
00271     
00272     /*
00273     6.0b2 dmb: return the previous display state
00274     */
00275     
00276     hdloutlinerecord ho = outlinedata;
00277     boolean flwasenabled = !(**ho).flinhibitdisplay;
00278     
00279     (**ho).flinhibitdisplay = true;
00280     
00281     if (opeditsetglobals ())
00282         (**wpdata).flinhibitdisplay = true;
00283     
00284     return (flwasenabled);
00285     } /*opdisabledisplay*/
00286 
00287 
00288 boolean openabledisplay (void) {
00289     
00290     /*
00291     6.0b2 dmb: return true if the state changes
00292     */
00293     
00294     hdloutlinerecord ho = outlinedata;
00295     boolean fldisabled = (**ho).flinhibitdisplay;
00296     
00297     (**ho).flinhibitdisplay = false;
00298     
00299     if (opeditsetglobals ())
00300         (**wpdata).flinhibitdisplay = false;
00301     
00302     return (fldisabled);
00303     } /*openabledisplay*/
00304 
00305 
00306 boolean opdisplayenabled (void) {
00307     
00308     register hdloutlinerecord ho = outlinedata;
00309     
00310     if (ho == NULL)
00311         return (false);
00312 
00313     return ((**ho).flwindowopen && !(**ho).flinhibitdisplay);
00314     } /*opdisplayenabled*/
00315 
00316 
00317 boolean opsetdisplayenabled (boolean fldisplay) {
00318     
00319     /*
00320     enable or disable display according to fl.
00321     
00322     return true if the display state changes
00323     
00324     6.0b2 dmb: don't do any redisplay
00325     */
00326     
00327     hdloutlinerecord ho = outlinedata;
00328     
00329     if ((**ho).flinhibitdisplay != fldisplay) /*nothing to do*/
00330         return (false);
00331     
00332     if (fldisplay)
00333         openabledisplay ();
00334     else
00335         opdisabledisplay ();
00336     
00337     return (true);
00338     } /*opsetdisplayenabled*/
00339 
00340 
00341 void opupdatenow (void) {
00342     
00343     if (!opdisplayenabled ())
00344         return;
00345         
00346     #ifdef appletinclude
00347         
00348         updateappwindow (app.appwindow);
00349         
00350     #else
00351     
00352         shellupdatecontent ((**outlinedata).outlinerect);
00353         
00354     #endif
00355     } /*opupdatenow*/
00356     
00357     
00358 boolean opgetlinerect (long lnum, Rect *r) {
00359 
00360     /*
00361     lnum is a 0-based index into the window. lnum 0 refers to the line 
00362     displayed at the top of the window.
00363     
00364     6.0b2 dmb: always calculate a rect, even if it's above the screen and 
00365     we return false
00366     */
00367     
00368     register hdloutlinerecord ho = outlinedata;
00369     short heightthisline;
00370     
00371     *r = (**ho).outlinerect; /*set left and right*/
00372 
00373     (*r).top += opsumprevlineheights (lnum, &heightthisline);
00374     
00375     (*r).bottom = (*r).top + heightthisline;
00376     
00377     return (lnum >= 0);
00378     } /*opgetlinerect*/
00379     
00380 
00381 hdlheadrecord oppointnode (Point pt) {
00382     
00383     /*
00384     the point is assumed to be pointing at a node.  return that node.   
00385     */
00386     
00387     hdlheadrecord nomad = (**outlinedata).hline1;
00388     long i, ct;
00389     
00390     ct = opgetcurrentscreenlines (false);
00391     
00392     for (i = 0; i < ct; i++) {
00393         
00394         Rect r;
00395         
00396         opgetlinerect (i, &r); 
00397         
00398         if (pointinrect (pt, r)) 
00399             return (nomad);
00400             
00401         nomad = opgetnextexpanded (nomad);
00402         } /*for*/
00403         
00404     return (nil); /*loop terminated, he's not pointing at a real node*/
00405     } /*oppointnode*/
00406     
00407 
00408 boolean opgetscreenline (hdlheadrecord hnode, long *lnum) {
00409 
00410     /*
00411     give me a headrecord handle and I'll return the line it's displayed
00412     on.  it's a virtual line number, ie it can be less than 0 or greater
00413     than the number of lines on the screen.
00414     
00415     the line indicated by (**outlinedata).hline1 is on line 0.
00416     
00417     return false if the node isn't expanded or visible in this window.
00418     */
00419     
00420     long uplnum, downlnum;
00421     hdlheadrecord upnomad, downnomad, lastnomad;
00422     hdloutlinerecord ho = outlinedata;
00423     hdlheadrecord hline1 = (**ho).hline1;
00424     
00425     upnomad = downnomad = hnode;
00426     
00427     uplnum = downlnum = 0;
00428     
00429     while (true) { // check up first
00430     
00431         if (upnomad == hline1) {
00432             
00433             *lnum = uplnum;
00434             
00435             return (true);
00436             }
00437         
00438         uplnum++;
00439         
00440         lastnomad = upnomad;
00441         
00442         upnomad = opbumpflatup (upnomad, true);
00443         
00444         if (lastnomad == upnomad) // didn't find hline1 above
00445             break;
00446         
00447         //uplnum += opgetnodelinecount (upnomad);
00448         }
00449     
00450     while (true) { // check down (we're above the screen)
00451             
00452         if (downnomad == hline1) {
00453             
00454             *lnum = downlnum;
00455             
00456             return (true);
00457             }
00458         
00459         downlnum--;
00460         
00461         lastnomad = downnomad;
00462         
00463         downnomad = opgetnextexpanded (downnomad);
00464         
00465         if (lastnomad == downnomad) // didn't find it below
00466             break;
00467         
00468         //downlnum += opgetnodelinecount (downnomad);
00469         }
00470         
00471     *lnum = 0;
00472     
00473     return (false);
00474     } /*opgetscreenline*/
00475 
00476 
00477 boolean opgetnoderect (hdlheadrecord hnode, Rect *r) {
00478     
00479     /*
00480     6.0b2 dmb: only return false if the node isn't displayed at all, not if
00481     it's above the display -- the rect is now meaningfull.
00482     */
00483     
00484     long lnum;
00485     
00486     if (!opgetscreenline (hnode, &lnum)) 
00487         return (false);
00488     
00489     opgetlinerect (lnum, r);
00490     
00491     return (true);
00492     } /*opgetnoderect*/
00493 
00494 
00495 void opsetdisplaydefaults (hdloutlinerecord ho) {
00496     
00497     short lh;
00498     
00499     oppushstyle (ho);
00500     
00501     lh = globalfontinfo.ascent + globalfontinfo.descent + globalfontinfo.leading;
00502     
00503     if ((**ho).flneedfulliconheight)
00504         lh = max (lh, (**ho).iconheight); 
00505 
00506     (**ho).defaultlineheight = lh;
00507     
00508     if ((**ho).flprinting && iscurrentportprintport()) {
00509         long scaleMult, scaleDiv;
00510 
00511         getprintscale (&scaleMult, &scaleDiv);
00512 
00513         (**ho).lineindent = (15L * scaleMult) / scaleDiv;
00514         
00515         #ifdef WIN95VERSION // can't print icons
00516             (**ho).iconheight = 0;
00517             (**ho).iconwidth = 0;
00518         #else
00519             (**ho).iconheight = (16L * scaleMult) / scaleDiv;
00520             (**ho).iconwidth = (16L * scaleMult) / scaleDiv;
00521         #endif
00522         }
00523     else {
00524         (**ho).lineindent = 15;
00525         (**ho).iconheight = 16;
00526         (**ho).iconwidth = 16;
00527         }
00528 
00529     popstyle ();
00530     } /*opsetdisplaydefaults*/
00531     
00532 
00533 static boolean oppushclip (Rect *rclip) {
00534     
00535     /*
00536     we make sure that the rect doesn't have any territory outside the 
00537     display rectangle, if it does, then we cut it back down to size.
00538     
00539     returns false if the intersection of the two rects is empty.
00540     
00541     to pop, call popclip -- if we return false, don't -- we didn't
00542     push anything.
00543     */
00544     
00545     if (!intersectrect (*rclip, (**outlinedata).outlinerect, rclip))
00546         return (false);
00547         
00548     return (pushclip (*rclip));
00549     } /*oppushclip*/
00550     
00551 
00552 void oplineinval (long lnum) {
00553     
00554     Rect r;
00555     
00556     if (!opdisplayenabled ())
00557         return;
00558     
00559     if (opgetlinerect (lnum, &r))
00560         invalrect (r);
00561     } /*oplineinval*/
00562     
00563 
00564 static void oprangeinval (long firstlnum, long lastlnum) {
00565     
00566     Rect r1, r2;
00567     
00568     opgetlinerect (firstlnum, &r1);
00569     
00570     opgetlinerect (lastlnum, &r2);
00571     
00572     r1.bottom = r2.bottom;
00573     
00574     invalrect (r1);
00575     } /*oprangeinval*/
00576     
00577 
00578 boolean opinvalnode (hdlheadrecord hnode) {
00579     
00580     /*
00581     1/6/97 dmb: don't inval if getting line returns false
00582     
00583     2/19/97 dmb: don't even opgetscreenline if display is disabled
00584     */
00585     
00586     long lnum;
00587     
00588     if (opdisplayenabled ()) {
00589         
00590         if (opgetscreenline (hnode, &lnum))
00591             oplineinval (lnum);
00592         }
00593     
00594     return (true);
00595     } /*opinvalnode*/
00596     
00597 
00598 static boolean opinvalnodevisit (hdlheadrecord hnode, ptrvoid refcon) {
00599 #pragma unused (refcon)
00600 
00601     /*
00602     1/6/97 dmb: don't inval if getting line returns false
00603     */
00604     
00605     opinvalnode (hnode);
00606     
00607     return (true);
00608     } /*opinvalnodevisit*/
00609     
00610     
00611 void opinvalstructure (hdlheadrecord hnode) {
00612     
00613     /*
00614     inval all the nodes subordinate to hnode, and hnode itself.
00615     */
00616     
00617     opinvalnode (hnode);
00618     
00619     oprecursivelyvisit (hnode, infinity, &opinvalnodevisit, nil);
00620     } /*opinvalstructure*/
00621 
00622 
00623 void opinvalafter (hdlheadrecord hnode) {
00624     
00625     long lnum;
00626     
00627     opgetscreenline (hnode, &lnum);
00628     
00629     oprangeinval (lnum, opgetcurrentscreenlines (false));
00630     } /*opinvalafter*/
00631     
00632     
00633 void opinvalbarcursor (void) {
00634     
00635     opinvalnode ((**outlinedata).hbarcursor);
00636     } /*opinvalbarcursor*/
00637     
00638 
00639 void opinvaldisplay (void) {
00640     
00641     if (!opdisplayenabled ())
00642         return;
00643     
00644     invalrect ((**outlinedata).outlinerect);
00645     } /*opinvaldisplay*/
00646     
00647     
00648 void opsmashdisplay (void) {
00649     
00650     opinvaldisplay ();
00651     
00652     opupdatenow ();
00653     } /*opsmashdisplay*/
00654     
00655     
00656 void operaserect (Rect r) {
00657     
00658     pushbackcolor (&(**outlinedata).backcolor);
00659     
00660     eraserect (r);
00661     
00662     popbackcolor ();
00663     } /*operaserect*/
00664 
00665 
00666 void operasedisplay (void) {
00667     
00668     pushbackcolor (&(**outlinedata).backcolor);
00669     
00670     smashrect ((**outlinedata).outlinerect); /*erase and inval*/
00671     
00672     popbackcolor ();
00673     } /*operasedisplay*/
00674 
00675 
00676 static boolean opdirtymeasurementsvisit (hdlheadrecord hnode, ptrvoid refcon) {
00677 #pragma unused (refcon)
00678 
00679     (**hnode).hpixels = (**hnode).vpixels = opdirtymeasurevalue;
00680     
00681     return (true);
00682     } /*opdirtymeasurementsvisit*/
00683 
00684 
00685 boolean opdirtymeasurements (void) {
00686     
00687     return (opvisiteverything (opdirtymeasurementsvisit, nil));
00688     } /*opdirtymeasurements*/
00689 
00690 
00691 static void opupdateafterresize (void) {
00692     
00693     /*
00694     7.0b16 PBS: fix the display glitch when in edit mode, you resize a window,
00695     and the display is incorrect. The outline view should get updated.
00696 
00697     Before calling oppostedit, make sure there is a global outline,
00698     it's in text mode, there's an edit cursor, and there are wp globals.
00699     */
00700 
00701     if (outlinedata == nil) /*Must have an outline global*/
00702         return;
00703 
00704     if (!(**outlinedata).fltextmode) /*Must be in edit mode*/
00705         return;
00706 
00707     if ((**outlinedata).heditcursor == nil) /*Must be an edit cursor*/
00708         return;
00709 
00710     if (wpdata == nil) /*Must have wp globals*/
00711         return;
00712 
00713     oppostedit (); /*Update the outline display*/
00714     } /*opupdateafterresize*/
00715 
00716 
00717 boolean oppostfontchange (void) {
00718     
00719     /*
00720     6.0b3 dmb: must opsetscrollpositiontoline1
00721 
00722     7.0b16: Fix display glitch after resizing an outline when in edit mode.
00723     */
00724     
00725     boolean fl = false;
00726 
00727     opdirtymeasurements ();
00728     
00729     opsetctexpanded (outlinedata); //6.0a12 dmb
00730     
00731     opsetscrollpositiontoline1 ();
00732     
00733     fl = opseteditbufferrect ();
00734 
00735     opupdateafterresize (); /*7.0b16 PBS*/
00736 
00737     return (fl);
00738     } /*oppostfontchange*/
00739 
00740 
00741 short opmaxlevelwidth (hdlheadrecord hnode) {
00742     
00743     /*
00744     visit each of the siblings of hnode, and compute the maximum displaypixels
00745     value for all the nodes.  do not include the node itself in the computation.
00746     
00747     if he's the only node at his level, return 0.
00748     */
00749     
00750     register hdlheadrecord nomad, nextnomad;
00751     register short maxpixels = 0;
00752     Rect fullrect;
00753     short pixels;
00754         
00755     nomad = opfirstatlevel (hnode);
00756     
00757     while (true) {
00758         
00759         if (nomad != hnode) { /*don't include the node itself in the analysis*/
00760             
00761             opgetfullrect (hnode, &fullrect);   
00762             
00763             pixels = (fullrect.right - fullrect.left);
00764             
00765             if (pixels > maxpixels) /*found a new max*/
00766                 maxpixels = pixels;
00767             }
00768         
00769         nextnomad = (**nomad).headlinkdown;
00770         
00771         if (nextnomad == nomad) /*reached the last one*/
00772             return (maxpixels);
00773         
00774         nomad = nextnomad; /*advance to next node at level*/
00775         } /*while*/
00776     } /*opmaxlevelwidth*/
00777 
00778 
00779 boolean opdefaultpredrawline (hdlheadrecord hnode, const Rect *rline, boolean flselected, boolean flinverted) {
00780 #pragma unused(hnode, flselected, flinverted)
00781 
00782     pushbackcolor (&(**outlinedata).backcolor);
00783     
00784     eraserect (*rline); 
00785     
00786     popbackcolor ();
00787     
00788     return (true);
00789     } /*opdefaultpredrawline*/
00790 
00791 
00792 boolean opdefaultdrawtext (hdlheadrecord hnode, const Rect *rtext, boolean flselected, boolean flinverted) {
00793     
00794     /*
00795     the normal text drawing routine, used for script editor and
00796     menu editor in Frontier. 
00797     */
00798     
00799     hdloutlinerecord ho = outlinedata;
00800     bigstring headstring;
00801     Rect r = *rtext;
00802     
00803     if (opeditingtext (hnode)) {
00804     
00805         opeditupdate ();
00806         
00807         return (true);
00808         }
00809     
00810     r.top += textvertinset;
00811     
00812     r.bottom -= textvertinset;
00813     
00814     if (opisfatheadlines (ho)) {
00815         
00816         opeditdrawtext (hnode, &r);
00817         }
00818     
00819     else {
00820         getheadstring (hnode, headstring);
00821         
00822         if ((**hnode).fldrawelipsizes) /*DW 10/9/95 -- hack -- see claylinelayout.c*/
00823             ellipsize (headstring, r.right - r.left);
00824         
00825         movepento (r.left, r.top + globalfontinfo.ascent);
00826         
00827         pendrawstring (headstring);
00828         }
00829     
00830     if (flselected) {
00831         
00832     //  Point pt;
00833         Rect rframe = r;
00834         
00835         rframe.right = rframe.left + (**hnode).hpixels + texthorizinset;
00836         
00837     //  rframe.left -= 2; /*leave 2 extra pixels for prettier bar cursor*/
00838         rframe.left -= (**ho).iconwidth + (**ho).pixelsaftericon + texthorizinset;
00839         
00840         /*
00841         rframe.top += textvertinset;
00842         
00843         rframe.bottom -= textvertinset;
00844         */
00845         
00846         /*
00847         getpenpoint (&pt);
00848         
00849         rframe.right = pt.h + 2; //leave 2 extra pixels for prettier bar cursor
00850         */
00851         
00852         if (flinverted)
00853             invertrect (rframe);
00854         else
00855             grayframerect (rframe);
00856         }
00857     
00858 
00859     return (true);
00860     } /*opdefaultdrawtext*/
00861 
00862 
00863 boolean
00864 opdefaultpostdrawline (
00865         hdlheadrecord    hnode,
00866         const Rect      *linerect,
00867         boolean          flselected,
00868         boolean          flinverted)
00869 {
00870 #pragma unused(hnode, linerect, flselected, flinverted)
00871 
00872     return (true);
00873     } /*opdefaultpostdrawline*/
00874 
00875 
00876 void opgetlineselected (hdlheadrecord hnode, boolean *flinverted, boolean *flselected) {
00877 
00878     /*
00879     analyze the line to determine if it should be drawn selected and/or
00880     inverted.
00881     */
00882 
00883     register hdloutlinerecord ho = outlinedata;
00884 
00885     *flinverted = (**ho).flactive; /*text is inverted when we're the active app & window*/
00886 
00887     if ((**ho).fltextmode) {
00888         
00889         *flselected = false; /*when editing text nothing is selected*/
00890         
00891         return;
00892         }
00893         
00894     if ((**ho).flprinting) { 
00895         
00896         *flselected = false; /*no barcusor in printout*/
00897         
00898         return;
00899         }
00900         
00901     if (!(**ho).flbarcursoron) {
00902         
00903         *flselected = (**hnode).flmarked; /*someone turned the cursor display off*/
00904         
00905         return;
00906         }
00907         
00908     if (opanymarked ()) {
00909     
00910         *flselected = (**hnode).flmarked;
00911         
00912         return;
00913         }
00914     
00915     /*not in textmode, printing, barcursor is on, nothing is marked*/
00916     
00917     *flselected = (**ho).hbarcursor == hnode;
00918     } /*opgetlineselected*/
00919 
00920 
00921 void opdrawicon (hdlheadrecord hnode, Rect linerect) {
00922 
00923     /*
00924     6.0a1 dmb: draw just the headline's icon, accounting for selectedness, 
00925     invertedness
00926     */
00927 
00928     register hdloutlinerecord ho = outlinedata;
00929     Rect rclip = linerect;
00930     Rect iconrect;
00931     boolean flinverted, flselected;
00932     
00933     if (hnode == nil) /*defensive driving, old versions would erase the rect*/
00934         return;
00935     
00936     opgetlineselected (hnode, &flinverted, &flselected);
00937     
00938     opgeticonrect (hnode, &linerect, &iconrect); /*iconrect is derived from the line rect*/
00939 
00940     opgettextrect (hnode, &linerect, &rclip);
00941 
00942     rclip.top += textvertinset;
00943     
00944     rclip.bottom -= textvertinset;
00945 
00946     rclip.right = rclip.left;
00947         
00948     rclip.left -= (**ho).iconwidth + (**ho).pixelsaftericon; // + texthorizinset;
00949     
00950     //intersectrect (rclip, iconrect, &rclip);
00951     
00952     if (!oppushclip (&rclip))
00953         return;
00954     
00955     oppushcolors (ho);
00956     
00957     (*(**ho).predrawlinecallback) (hnode, &linerect, flselected, flinverted);
00958     
00959     (*(**ho).drawiconcallback) (hnode, &iconrect, flselected, flinverted);
00960     
00961     if (flselected && flinverted)
00962         invertrect (rclip);
00963     
00964     (*(**ho).postdrawlinecallback) (hnode, &linerect, flselected, flinverted);
00965 
00966     popcolors ();
00967     
00968     popclip ();
00969     } /*opdrawicon*/
00970 
00971 
00972 void opdrawline (hdlheadrecord hnode, Rect linerect) {
00973     
00974     /*
00975     linerect frames the line which displays the node. left and right
00976     are outlinerect's left and right. top and bottom reflect the 
00977     scrolled position of the line, and the line's height.
00978     
00979     we compute the icon rectangle and text rectangle and whether things
00980     are highlighted or not, and call the callback routines to draw
00981     the icon and text.
00982     
00983     12/11/96 dmb: no bitmaps. it's just a waste of bitcopying when 
00984     responding to an update, and it requires more elaborate update 
00985     calls for paige when text is active
00986     */
00987     
00988     register hdloutlinerecord ho = outlinedata;
00989     Rect iconrect, textrect;
00990     Rect rclip = linerect;
00991     //boolean flbitmap = false;
00992     boolean flinverted, flselected;
00993     
00994     if (hnode == nil) /*defensive driving, old versions would erase the rect*/
00995         return;
00996     
00997     (**hnode).fldirty = false; /*doesn't survive a refresh*/
00998     
00999     if (!oppushclip (&rclip))
01000         return;
01001     
01002     /*
01003     #ifdef fldebug
01004         if (!optionkeydown ())
01005             flbitmap = openbitmap (rclip, outlinewindow);
01006     #else
01007         flbitmap = openbitmap (rclip, outlinewindow);
01008     #endif
01009     */
01010     
01011     opgeticonrect (hnode, &linerect, &iconrect); /*iconrect is derived from the line rect*/
01012         
01013     opgettextrect (hnode, &linerect, &textrect); /*textrect is derived from the line rect*/
01014         
01015     opgetlineselected (hnode, &flinverted, &flselected);
01016     
01017     (*(**ho).predrawlinecallback) (hnode, &linerect, flselected, flinverted);
01018     
01019 //  if (oprectneedsupdate (iconrect))
01020         (*(**ho).drawiconcallback) (hnode, &iconrect, flselected, flinverted);
01021     
01022 //  if (oprectneedsupdate (textrect))
01023         (*(**ho).drawlinecallback) (hnode, &textrect, flselected, flinverted);
01024     
01025     (*(**ho).postdrawlinecallback) (hnode, &linerect, flselected, flinverted);
01026     
01027     /*
01028     if (flbitmap)
01029         closebitmap (outlinewindow);
01030     */
01031     
01032     popclip ();
01033     } /*opdrawline*/
01034     
01035     
01036 void opupdate (void) {
01037 
01038     register hdloutlinerecord ho = outlinedata;
01039     hdlheadrecord nomad;
01040     Rect outlinerect;
01041     Rect r; 
01042     hdlheadrecord nextnomad;
01043     long i;
01044     
01045     if (ho == NULL)
01046         return;
01047 
01048     nomad = (**ho).hline1;
01049     
01050     r = outlinerect = (**ho).outlinerect;
01051     
01052     i = 0;
01053 
01054     oppushstyle (ho);
01055     
01056     oppushcolors (ho);
01057     
01058     #ifdef gray3Dlook
01059         if (!(**ho).fldonterasebackground) {
01060             
01061             insetrect (&outlinerect, -3, -3);
01062             
01063             framerect (outlinerect);
01064             
01065             insetrect (&outlinerect, 1, 1);
01066 
01067             eraserect (outlinerect);
01068 
01069             insetrect (&outlinerect, 2, 2);
01070             }
01071     #endif
01072     
01073     r.top += opgetline1top ();
01074     
01075     while (true) {
01076         
01077         ++i;
01078         
01079         r.bottom = r.top + opgetlineheight (nomad);
01080         
01081         if (r.top >= outlinerect.bottom)
01082             break;
01083         
01084         if (oprectneedsupdate (r))      
01085             opdrawline (nomad, r);
01086         
01087         r.top = r.bottom;
01088         
01089         //if (nomad == (**ho).hbarcursor)
01090         //  (**ho).lnumbarcursor = i;
01091             
01092         nextnomad = opgetnextexpanded (nomad);
01093         
01094         if (nextnomad == nomad) 
01095             break;
01096             
01097         nomad = nextnomad;
01098         } /*while*/
01099     
01100     #ifndef gray3Dlook
01101         if (!(**ho).fldonterasebackground) {
01102 
01103             r.bottom = outlinerect.bottom;
01104             
01105             if (oprectneedsupdate (r))
01106                 operaserect (r);
01107             }
01108     #endif
01109     
01110     popcolors ();
01111     
01112     popstyle ();
01113    } /*opupdate*/
01114 
01115 
01116 void opdocursor (boolean flon) {
01117     
01118     register hdloutlinerecord ho = outlinedata;
01119     long lnumcursor;
01120     Rect r;
01121     
01122     if (!opdisplayenabled ())
01123         return;
01124     
01125     oppushstyle (ho);
01126     
01127     oppushcolors (ho);
01128 
01129     (**ho).flbarcursoron = flon;
01130     
01131     opgetscreenline ((**ho).hbarcursor, &lnumcursor);
01132     
01133     //(**ho).lnumbarcursor = lnumcursor;
01134     
01135     if (opgetlinerect (lnumcursor, &r))
01136         opdrawline ((**ho).hbarcursor, r);
01137     
01138     popcolors ();
01139 
01140     popstyle ();
01141     
01142     (**ho).flbarcursoron = true; 
01143     } /*opdocursor*/
01144     
01145     
01146 void opscrollrect (Rect r, long dh, long dv) {
01147     
01148     pushbackcolor (&(**outlinedata).backcolor); /*so that erasures use the right color*/
01149     
01150     scrollrect (r, dh, dv);
01151     
01152     popbackcolor ();
01153     } /*opscrollrect*/
01154     
01155     
01156 void opmakegap (long lnum, short lineheight) {
01157     
01158     /*
01159     create a gap in the display after the indicated line number.
01160     
01161     5.0d18 dmb: handle lnum < 0 (-1) so opexpandupdate will work when 
01162     new node is first in list
01163     */
01164     
01165     register hdloutlinerecord ho = outlinedata;
01166     Rect r;
01167     
01168     if (lnum < 0)
01169         opgetlinerect (0, &r);
01170     
01171     else {
01172         opgetlinerect (lnum, &r);
01173         
01174         r.top = r.bottom;
01175         }
01176     
01177     r.bottom = (**ho).outlinerect.bottom;
01178     
01179     opscrollrect (r, 0, lineheight);
01180     } /*opmakegap*/
01181     
01182 
01183 static boolean opvertscrollrecord (long *ctscroll, long *ctpixels) {
01184     
01185     /*
01186     only scrolls the record, the data structures, not the pixels on the screen.
01187     
01188     if ctscroll is negative, the text scrolls up; positive ==> down.
01189     
01190     returns true if any scrolling is necessary.
01191     
01192     7/24/91 dmb: protect against integer overflow
01193     
01194     6.0a12 dmb: scrolling is line-wise, not headline-wise; also count pixels here
01195     */
01196     
01197     register hdloutlinerecord ho = outlinedata;
01198     long ct = *ctscroll;
01199     long vc;
01200     hdlheadrecord nomad;
01201     
01202     if (ctpixels != nil)
01203         *ctpixels = 0;
01204     
01205     vc = (**ho).vertscrollinfo.cur - (long) ct;
01206     
01207     vc = min (vc, (**ho).vertscrollinfo.max);
01208     
01209     vc = max (vc, (**ho).vertscrollinfo.min);
01210     
01211     ct = (**ho).vertscrollinfo.cur - (long) vc;
01212     
01213     if (ct == 0) /*nothing to do*/
01214         return (false);
01215         
01216     (**ho).vertscrollinfo.cur = (long) vc;
01217     
01218     *ctscroll = ct;
01219     
01220     ct -= (**ho).line1linesabove; //bring line1 to top before counting
01221     
01222     if (ctpixels != nil)
01223         *ctpixels -= opgetline1top ();
01224     
01225     nomad = (**ho).hline1;
01226     
01227     if (ct > 0) {
01228     
01229         while (ct > 0) {
01230             
01231             nomad = opbumpflatup (nomad, true); 
01232             
01233             ct -= opgetnodelinecount (nomad);
01234             
01235             if (ctpixels != nil)
01236                 *ctpixels += opgetlineheight (nomad);
01237             }
01238         
01239         (**ho).line1linesabove = -ct;
01240         
01241         if (ctpixels != nil)
01242             *ctpixels += opgetline1top ();
01243         }
01244     else {
01245         
01246         ct = -ct;
01247         
01248         while (opgetnodelinecount (nomad) <= ct) {
01249             
01250             ct -= opgetnodelinecount (nomad);
01251             
01252             if (ctpixels != nil)
01253                 *ctpixels -= opgetlineheight (nomad);
01254             
01255             nomad = opbumpflatdown (nomad, true);
01256             }
01257         
01258         (**ho).line1linesabove = ct;
01259         
01260         if (ctpixels != nil)
01261             *ctpixels += opgetline1top ();
01262         }
01263     
01264     (**ho).hline1 = nomad;
01265     
01266     //(**ho).lnumbarcursor -= ct;
01267     
01268     return (true);
01269     } /*opvertscrollrecord*/
01270     
01271 
01272 static boolean ophorizscrollrecord (long *ctscroll) {
01273 
01274     /*
01275     if ctscroll is negative, the text scrolls left; positive ==> right.
01276     
01277     7/24/91 dmb: protect against integer overflow
01278     */
01279     
01280     register hdloutlinerecord ho = outlinedata;
01281     register long ct = *ctscroll;
01282     register long horizcurrent = (**ho).horizscrollinfo.cur;
01283     register long hc;
01284     
01285     hc = horizcurrent - (long) ct;
01286     
01287     hc = min (hc, (**ho).horizscrollinfo.max);
01288     
01289     hc = max (hc, (**ho).horizscrollinfo.min);
01290     
01291     ct = horizcurrent - (long) hc;
01292     
01293     *ctscroll = ct;
01294     
01295     if (ct == 0) /*nothing to do*/
01296         return (false);
01297         
01298     (**ho).horizscrollinfo.cur = (long) hc;
01299     
01300     return (true);
01301     } /*ophorizscrollrecord*/
01302     
01303 
01304 static boolean ophorizscroll (long ctpixels) {
01305     
01306     opupdatenow ();
01307     
01308     if (!ophorizscrollrecord (&ctpixels)) /*only deals with fields of outline record*/
01309         return (false);
01310     
01311     opseteditbufferrect ();
01312     
01313     opscrollrect ((**outlinedata).outlinerect, ctpixels, 0);
01314     
01315     opresetscrollbars ();
01316     
01317     opupdatenow ();
01318     
01319     return (true);
01320     } /*ophorizscroll*/
01321     
01322 
01323 #if 0
01324 
01325 static long opvisiupcountpixels (hdlheadrecord nomad, long vscroll) {
01326     
01327     long i, ct = 0;
01328     
01329     for (i = 1; i <= vscroll; i++) {
01330         
01331         nomad = opbumpflatup (nomad, true);
01332         
01333         ct += opgetlineheight (nomad);  
01334         } /*for*/
01335         
01336     return (ct);
01337     } /*opvisiupcountpixels*/
01338     
01339     
01340 static long opvisidowncountpixels (hdlheadrecord nomad, long vscroll) {
01341     
01342     long i, ct = 0;
01343     
01344     for (i = 1; i <= vscroll; i++) {
01345         
01346         ct += opgetlineheight (nomad);
01347         
01348         nomad = opgetnextexpanded (nomad);
01349         } /*for*/
01350         
01351     return (ct);
01352     } /*opvisidowncountpixels*/
01353 
01354 #endif
01355 
01356 
01357 static boolean opvertscroll (long ctlines) {
01358     
01359     //hdlheadrecord oldline1 = (**outlinedata).hline1;
01360     long ctpixels;
01361     
01362     opupdatenow ();
01363     
01364     if (!opvertscrollrecord (&ctlines, &ctpixels)) /*only deals with fields of outline record*/
01365         return (false);
01366     
01367     opseteditbufferrect ();
01368     
01369     if (opdisplayenabled ()) {
01370         
01371         /*
01372         if (ctlines > 0) 
01373             ctpixels = opvisiupcountpixels (oldline1, ctlines);
01374         else 
01375             ctpixels = -opvisidowncountpixels (oldline1, -ctlines);
01376         */
01377         
01378         opscrollrect ((**outlinedata).outlinerect, 0, ctpixels);
01379         }
01380     
01381     opresetscrollbars ();
01382     
01383     opupdatenow ();
01384     
01385     return (true);
01386     } /*opvertscroll*/
01387 
01388 
01389 void opjumpdisplayto (hdlheadrecord holdcursor, hdlheadrecord hnewcursor) {
01390     
01391     /*
01392     a special way to move the cursor when you know it's going a long 
01393     distance. no point erasing the old cursor. no point trying to scroll
01394     or erase the display. everything is going to be updated. do it all
01395     in one shot for nicer staging.
01396     
01397     DW 8/15/93: try to make it sexier if there is no scrolling required.
01398     
01399     DW 10/17/93: erase the display in addition to inval'ing it. cb can
01400     take a few seconds to redraw the window, this makes for better 
01401     staging.
01402     
01403     6.0a12 dmb: need resetscrollbars here
01404     */
01405     
01406     long hscroll, vscroll;
01407     
01408     opinvalnode (holdcursor);
01409     
01410     if (opneedvisiscroll (hnewcursor, &hscroll, &vscroll, true)) {
01411         
01412         /*DW 10/27/93 -- make sure the head is on the first line in the window*/ {
01413             
01414             if (vscroll < 0)
01415                 vscroll -= opgetcurrentscreenlines (true) - 1;
01416             }
01417             
01418         opvertscrollrecord (&vscroll, nil); 
01419 
01420         ophorizscrollrecord (&hscroll);
01421         
01422         opinvaldisplay (); /*everything will get redrawn*/
01423         
01424         operaserect ((**outlinedata).outlinerect);
01425         }
01426     else
01427         opinvalnode (hnewcursor);
01428     
01429     opresetscrollbars ();
01430     } /*opjumpdisplayto*/
01431 
01432 
01433 boolean opscrollto (long h, long v) {
01434     
01435     /*
01436     DW 10/27/93: new version bends over backwards to avoid 
01437     jerkyness.
01438     */
01439     
01440     long horizpixels, vertlines;
01441     boolean flhoriz, flvert;
01442     
01443     horizpixels = (**outlinedata).horizscrollinfo.cur - h;
01444     
01445     flhoriz = ophorizscrollrecord (&horizpixels);
01446     
01447     vertlines = (**outlinedata).vertscrollinfo.cur - v;
01448     
01449     flvert = opvertscrollrecord (&vertlines, nil);
01450     
01451     if ((!flvert) && (!flhoriz)) 
01452         return (false);
01453     
01454     opseteditbufferrect ();
01455 
01456     opresetscrollbars ();
01457     
01458     operasedisplay ();
01459     
01460     return (true);
01461     } /*opscrollto*/
01462 
01463 
01464 static long scrollquantum (register long hscroll) {
01465     
01466     register long hquantum = (**outlinedata).lineindent;
01467     
01468     return  (quantumize (hscroll, hquantum));
01469     } /*scrollquantum*/
01470 
01471 
01472 static long getuppagescrolllines (void) {
01473     
01474     /*
01475     6.0a12 dmb: this routine was in error. the correct number of lines
01476     to scroll up for a page depends on what is on the screen now, not what's
01477     below it. the number has already been calculated in the vertscrollinfo.
01478     */
01479     
01480     register hdloutlinerecord ho = outlinedata;
01481     
01482     return ((**ho).vertscrollinfo.pag);
01483     
01484     /*
01485     Rect r = (**ho).outlinerect;
01486     long vertpixels = r.bottom - r.top;
01487     long ctpixels = 0, ctlines = 0;
01488     hdlheadrecord h, hnext;
01489     
01490     h = opgetnextexpanded (opgetlastvisiblenode ());
01491     
01492     while (true) {
01493         
01494         ctpixels += opgetlineheight (h);
01495         
01496         if (ctpixels > vertpixels)
01497             return (ctlines);
01498         
01499         ctlines += opgetnodelinecount (h);
01500             
01501         hnext = opgetnextexpanded (h);
01502         
01503         if (hnext == h)
01504             return (ctlines);
01505             
01506         h = hnext;
01507         }
01508     */
01509     } /*getuppagescrolllines*/
01510 
01511 
01512 static long getdownpagescrolllines (void) {
01513     
01514     /*
01515     6.0a12 dmb: subtract one from the number calcuated to create a one-line
01516     overlap between pages. also, handle partial lines and don't count hline1
01517     */
01518     
01519     register hdloutlinerecord ho = outlinedata;
01520     Rect r = (**ho).outlinerect;
01521     long vertpixels = r.bottom - r.top;
01522     long ctpixels = 0, ctlines = 0;
01523     hdlheadrecord h, hnext;
01524     
01525     h = (**ho).hline1;
01526     
01527     ctpixels = -opgetline1top ();
01528     
01529     ctlines = (**ho).line1linesabove;
01530     
01531     while (true) {
01532             
01533         hnext = opbumpflatup (h, true);
01534         
01535         if (hnext == h)
01536             return (ctlines);
01537         
01538         h = hnext;
01539         
01540         ctpixels += opgetlineheight (h);
01541         
01542         if (ctpixels > vertpixels) {
01543             
01544             ctlines += (ctpixels - vertpixels) / (**ho).defaultlineheight;
01545             
01546             return (ctlines - 1);
01547             }
01548         
01549         ctlines += opgetnodelinecount (h);
01550         } /*while*/
01551     } /*getdownpagescrolllines*/
01552 
01553 
01554 boolean opscroll (tydirection dir, boolean flpage, long ctscroll) {
01555     
01556     /*
01557     5.1.5b12 dmb: check for nil outline
01558     */
01559     
01560     register hdloutlinerecord ho = outlinedata;
01561 //  hdlheadrecord hline1;
01562     boolean fl = false;
01563     Rect r;
01564     
01565     if (ho == nil)
01566         return (false);
01567     
01568 //  hline1 = (**ho).hline1;
01569     
01570     switch (dir) {
01571         
01572         case up: { /*text scrolls up, cursor moves down*/
01573             if (flpage) {
01574             
01575                 ctscroll = getuppagescrolllines ();
01576                 
01577                 fl = opvertscroll (-ctscroll);
01578                 }
01579             else {
01580                 fl = opvertscroll (-ctscroll);
01581                 }
01582                 
01583             break;
01584             }
01585             
01586         case down: { /*text scrolls down, cursor moves up*/
01587             if (flpage) {
01588             
01589                 ctscroll = getdownpagescrolllines ();
01590             
01591                 fl = opvertscroll (ctscroll);
01592                 }
01593             else {
01594                 fl = opvertscroll (ctscroll);
01595                 }
01596                 
01597             break;
01598             }
01599         
01600         case left: case right:
01601             if (flpage) {
01602                 
01603                 r = (**ho).outlinerect;
01604                 
01605                 ctscroll *= scrollquantum ((r.right - r.left) / 2);
01606                 }
01607             else
01608                 if (ctscroll == 1)
01609                     ctscroll *= (**ho).lineindent;
01610                     
01611             if (dir == left)
01612                 fl = ophorizscroll (-ctscroll);
01613             else
01614                 fl = ophorizscroll (ctscroll);
01615                     
01616             break;
01617         
01618         default:
01619             /* do nothing */
01620             break;
01621             
01622         } /*switch*/
01623                 
01624     opdirtyview ();
01625     
01626     return (fl);
01627     } /*opscroll*/
01628 
01629 
01630 #if 0
01631 
01632 static void supersmarthorizscrollsmarts (long *hscroll) {
01633     
01634     /*
01635     new idea, DW 10/17/93. after certain very jarring operations, like
01636     jumping a long distance, or switching in a different style in clay
01637     basket, it's really ugly to leave the screen less than optimally
01638     scrolled.
01639     
01640     we travel over all the lines in the window and figure out how much
01641     horizontal scrolling would be necessary to make them all visible.
01642     
01643     we prefer to make everything off to the left visible, if there's 
01644     stuff scrolled off both edges.
01645     
01646     we never scroll enough to make the cursor headline not visible. that
01647     makes it safe to call this after making the cursor horizontally
01648     visible.
01649     
01650     DW 4/10/95: allow for blocking this visi routine.
01651     */
01652     
01653     hdlheadrecord nomad = (**outlinedata).hline1;
01654     Rect outlinerect = (**outlinedata).outlinerect;
01655     long maxoffleft = 0, maxoffright = 0;
01656     long i, ct;
01657     Rect rcursor;
01658     
01659     return; /*10/9/95 -- feature wired off -- it's not optimal*/
01660     
01661     if ((**outlinedata).blocksupersmartvisi) {
01662         
01663         (**outlinedata).blocksupersmartvisi = false;
01664         
01665         return;
01666         }
01667     
01668     ct = opgetcurrentscreenlines ();
01669     
01670     for (i = 0; i < ct; i++) {
01671         
01672         Rect r;
01673         long offleft, offright;
01674         
01675         opgetfullrect (nomad, &r);
01676         
01677         offleft = outlinerect.left - r.left;
01678         
01679         if (offleft > maxoffleft)
01680             maxoffleft = offleft;
01681         
01682         offright = r.right - outlinerect.right;
01683         
01684         if (offright > maxoffright)
01685             maxoffright = offright;
01686             
01687         nomad = opgetnextexpanded (nomad);
01688         } /*for*/
01689         
01690     maxoffleft = scrollquantum (maxoffleft);
01691         
01692     maxoffright = scrollquantum (maxoffright);
01693         
01694     if ((maxoffleft == 0) && (maxoffright == 0)) /*no scrolling needed, everything's visible*/
01695         return;
01696         
01697     opgetfullrect ((**outlinedata).hbarcursor, &rcursor);
01698         
01699     if (maxoffleft > 0) {
01700         
01701         if ((rcursor.right + maxoffleft) <= outlinerect.right) { 
01702 
01703             *hscroll = maxoffleft;
01704         
01705             return;
01706             }
01707         }
01708         
01709     if (maxoffright > 0) {
01710         
01711         if ((rcursor.left - maxoffright) >= outlinerect.left)
01712             *hscroll = -maxoffright;
01713         }
01714     } /*supersmarthorizscrollsmarts*/
01715 
01716 #endif
01717 
01718 boolean opneedvisiscroll (hdlheadrecord hnode, long *hscroll, long *vscroll, boolean flcheckhoriz) {
01719     
01720     /*
01721     return true if one of hscroll or vscroll is non-zero.
01722     
01723     6.0b2 dmb: return false when window isn't open instead of when display is disabled.
01724     this allows script-generated visiing to work, but protects opverbfind from 
01725     screwing the display.
01726     */
01727     
01728     register hdloutlinerecord ho = outlinedata;
01729     register long leftdiff, rightdiff;
01730     Rect r;
01731     long lnum;
01732     
01733     *hscroll = *vscroll = 0;
01734     
01735     if (!ho || !(**ho).flwindowopen) //opdisplayenabled ()
01736         return (false);
01737     
01738     if (!opgetscreenline (hnode, &lnum))
01739         return (false);
01740     
01741     if (lnum <= 0)/*line is scrolled off the top of the window*/
01742         *vscroll = opgetlinestoscrolldownforvisi (hnode);
01743     
01744     else {
01745         long ct = opgetlinestoscrollupforvisi (hnode); 
01746         
01747         if (ct > 0)
01748             *vscroll = -ct;     
01749         }
01750     
01751     if (!flcheckhoriz)
01752         return (*vscroll != 0);
01753     
01754     if (opeditingtext (hnode))
01755         opeditgetselrect (&r);
01756     else 
01757         opgetfullrect (hnode, &r);
01758     
01759     rightdiff = scrollquantum ((**ho).outlinerect.left - r.left);
01760     
01761     leftdiff = scrollquantum (r.right - (**ho).outlinerect.right);
01762     
01763     if (rightdiff > 0) 
01764         *hscroll = rightdiff; /*scroll text to the right*/
01765     else {
01766         leftdiff = minint (leftdiff, -rightdiff);
01767         
01768         if (leftdiff > 0)
01769             *hscroll = -leftdiff; /*scroll text to the left*/
01770         }
01771         
01772 //  supersmarthorizscrollsmarts (hscroll);
01773     
01774     return ((*hscroll != 0) || (*vscroll != 0));
01775     } /*opneedvisiscroll*/
01776 
01777 
01778 void opdovisiscroll (long hscroll, long vscroll) {
01779     
01780 //  hdlheadrecord oldline1 = (**outlinedata).hline1;
01781     long vpixels;
01782     
01783     if (!(**outlinedata).blockvisiupdate)
01784         opupdatenow ();
01785     
01786     opvertscrollrecord (&vscroll, &vpixels); 
01787     
01788     ophorizscrollrecord (&hscroll);
01789     
01790     opseteditbufferrect ();
01791     
01792     if (opdisplayenabled ()) {
01793         
01794         /*
01795         if (vscroll > 0) 
01796             vscroll = opvisiupcountpixels (oldline1, vscroll);
01797         else 
01798             vscroll = -opvisidowncountpixels (oldline1, -vscroll);
01799         */
01800         
01801         opscrollrect ((**outlinedata).outlinerect, hscroll, vpixels);
01802         }
01803     
01804     opresetscrollbars ();
01805     
01806     if (!(**outlinedata).blockvisiupdate)
01807         opupdatenow ();
01808     } /*opdovisiscroll*/
01809 
01810 
01811 boolean opnodevisible (hdlheadrecord hnode) {
01812     
01813     long hscroll, vscroll;
01814     
01815     return (!opneedvisiscroll (hnode, &hscroll, &vscroll, false));
01816     } /*opnodevisible*/
01817 
01818 
01819 boolean opvisinode (hdlheadrecord hnode, boolean flhoriz) {
01820 
01821     /*
01822     make the node vertically visible in the window.  
01823     
01824     return true if scrolling was necessary.
01825     
01826     dmb 9/21/90: take flhoriz parameter to permit vertical-only visiing
01827     */
01828     
01829     long hscroll, vscroll;
01830     
01831     if (!opneedvisiscroll (hnode, &hscroll, &vscroll, flhoriz))
01832         return (false);
01833     
01834     opdovisiscroll (hscroll, vscroll);
01835     
01836     return (true);
01837     } /*opvisinode*/
01838 
01839 
01840 void opvisisubheads (hdlheadrecord hnode) {
01841 
01842     if (ophassubheads (hnode) && opsubheadsexpanded (hnode))
01843         opvisinode (oplastexpanded (hnode), false);
01844     
01845     opvisinode (hnode, true);
01846     } /*opvisisubheads*/
01847 
01848 
01849 static boolean opgetmaxwidthvisit (hdlheadrecord hnode, ptrvoid refcon) {
01850     
01851     short width;
01852     hdloutlinerecord ho = outlinedata;
01853         
01854     if ((**hnode).flexpanded) {
01855         
01856         (*(**ho).getlinewidthcallback) (hnode, &width);
01857         
01858         width += (**ho).lineindent * (**hnode).headlevel + (**ho).iconwidth + (**ho).pixelsaftericon;
01859         
01860         width = scrollquantum (width);
01861         
01862         if (width > *(long*)refcon)
01863             *(long*)refcon = width;
01864         }
01865     
01866     return (true);
01867     } /*opgetmaxwidthvisit*/
01868 
01869 
01870 boolean opgetoutinesize (long *width, long *height) {
01871     
01872     /*
01873     6.0a13 dmb: with wrapping headlines, this gets must more complicated.
01874     we need to see how things would wrap if we were the size of the full 
01875     screen, not the size when wrapped to the current window.
01876     
01877     7.0b17 PBS: On Macs, add a little to the width to prevent wrapping of a headline.
01878     */
01879     
01880     register hdloutlinerecord ho = outlinedata;
01881     Rect rwindow, rscreen;
01882     Rect routline;
01883     long hextra, maxheadwidth;
01884     
01885     //grow outlinerect temporarily as if the window grew to fill the screen
01886 
01887     getglobalwindowrect (shellwindow, &rwindow);
01888 
01889     getwindowscreenbounds (&rwindow, &rscreen);
01890     
01891     insetrect (&rscreen, 3, 3);
01892     
01893     hextra = (rscreen.right - rscreen.left) - (rwindow.right - rwindow.left);
01894     
01895     routline = (**ho).outlinerect;
01896     
01897     (**ho).outlinerect.right += hextra;
01898 
01899     opvisiteverything (opdirtymeasurementsvisit, nil);
01900     
01901     //measure everything
01902     
01903     *height = opsumalllineheights ();
01904     
01905     maxheadwidth = 0; /*set for visit routine*/
01906     
01907     opsiblingvisiter ((**outlinedata).hsummit, false, &opgetmaxwidthvisit, &maxheadwidth);
01908     
01909     *width = maxheadwidth;
01910     
01911     #ifdef MACVERSION
01912     
01913         *width = *width + 5; /*7.0b17 PBS: a little extra needed on Macs to prevent wrapping.*/
01914     
01915     #endif
01916 
01917     //restore outlinerect
01918     
01919     (**ho).outlinerect = routline;
01920     
01921     opvisiteverything (opdirtymeasurementsvisit, nil);
01922 
01923     return (true);
01924     } /*opgetoutinesize*/
01925 
01926 
01927 

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