opexpand.c

Go to the documentation of this file.
00001 
00002 /*  $Id: opexpand.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 "quickdraw.h"
00032 #include "mouse.h"
00033 #include "op.h"
00034 #include "opinternal.h"
00035 #include "oplineheight.h"
00036 #include "opdisplay.h"
00037 #include "opicons.h"
00038 
00039 #include "tablestructure.h" //7.0d5 AR
00040 
00041 
00042 static boolean flnothingcollapsed;
00043 
00044 static long pixelscollapsed;
00045 
00046 static long pixelsexpanded;
00047 
00048 static long pixelsalreadyexpanded;
00049 
00050 static long ctalreadyexpanded;
00051 
00052 
00053 
00054 static boolean opcollapsevisit (hdlheadrecord hnode, ptrvoid refcon) {
00055 #pragma unused (refcon)
00056 
00057     register hdlheadrecord h = hnode;
00058     
00059     if ((**h).flexpanded) {
00060         
00061         flnothingcollapsed = false; 
00062         
00063         (**outlinedata).ctexpanded -= opgetnodelinecount (h);
00064         
00065         (**h).flexpanded = false;
00066         
00067         pixelscollapsed += opgetlineheight (h);
00068         }
00069     
00070     return (true);
00071     } /*opcollapsevisit*/
00072     
00073 
00074 void opfastcollapse (hdlheadrecord h) {
00075     
00076     /*
00077     clear the expanded bits of all subordinate material, don't do anything
00078     to the display.
00079     */
00080 
00081     oprecursivelyvisit (h, infinity, &opcollapsevisit, nil); 
00082     } /*opfastcollapse*/
00083     
00084 
00085 boolean opcollapse (hdlheadrecord hnode) {
00086     
00087     register hdloutlinerecord ho = outlinedata;
00088     long origct = (**ho).ctexpanded;
00089     long ctscroll;
00090     long lnum;
00091     Rect linerect;
00092     
00093     pixelscollapsed = 0;
00094     
00095     flnothingcollapsed = true;
00096     
00097     oprecursivelyvisit (hnode, infinity, &opcollapsevisit, nil); /*clear expanded bits*/
00098     
00099     if (flnothingcollapsed)
00100         return (false);
00101     
00102     opdirtyview ();
00103     
00104     if (!opdisplayenabled ())
00105         goto exit;
00106     
00107     opgetscreenline (hnode, &lnum);
00108     
00109     opgetlinerect (lnum, &linerect);
00110     
00111 //  opgeticonrect (hnode, &linerect, &iconrect);
00112     
00113 //  invalrect (iconrect); /*the icon changes, avoid flash, don't inval the whole line*/
00114     
00115     opdrawicon (hnode, linerect);
00116 
00117     if (opgetnextexpanded (hnode) == hnode) { /*last expanded node, nothing to scroll up*/
00118         
00119         Rect r = linerect;
00120         
00121         r.top = linerect.bottom; 
00122         
00123         r.bottom = (**ho).outlinerect.bottom;
00124         
00125         smashrect (r); 
00126         
00127         goto exit;
00128         }
00129     
00130     if (linerect.bottom >= (**ho).outlinerect.bottom)
00131         goto exit;
00132     
00133     ctscroll = origct - (**ho).ctexpanded;
00134     
00135     if (ctscroll > 0) {
00136         
00137         Rect r = (**ho).outlinerect;
00138         
00139         if (linerect.bottom > r.top) { /*headline isn't above display*/
00140             
00141             r.top = linerect.bottom;
00142             
00143             opscrollrect (r, 0, -pixelscollapsed);
00144             }
00145         }
00146 
00147     exit:
00148     
00149     opresetscrollbars (); /*number of expanded lines changed*/
00150     
00151     (*(**ho).postcollapsecallback) (hnode);
00152     
00153     opupdatenow (); /*fill in newly revealed stuff immediately*/
00154     
00155     return (true); /*something was collapsed*/
00156     } /*opcollapse*/
00157 
00158 
00159 static boolean opexpandvisit (hdlheadrecord hnode, ptrvoid refcon) {
00160 #pragma unused (refcon)
00161 
00162     short lh = opgetlineheight (hnode);
00163     
00164     if ((**hnode).flexpanded) {
00165     
00166         ++ctalreadyexpanded;
00167         
00168         pixelsalreadyexpanded += lh;
00169         }
00170     else {
00171         (**outlinedata).ctexpanded += opgetnodelinecount (hnode);
00172         
00173         (**hnode).flexpanded = true;
00174         
00175         (**hnode).fldirty = true;
00176         
00177         pixelsexpanded += lh;
00178         }
00179     
00180     return (true);
00181     } /*opexpandvisit*/
00182     
00183 
00184 boolean opexpand (hdlheadrecord hnode, short level, boolean flmaycreatesubs) {
00185     
00186     /*
00187     expand the given node to the indicated level.
00188     
00189     scroll the screen vertically to make the last sub-node visible, if
00190     possible.
00191     
00192     return true if something was expanded, false otherwise.
00193     
00194     10/18/91 dmb: account for already-expanded subheads when no scrolling is required
00195     
00196     6.0b2 dmb: fixed scrollbar handling for large expansions
00197     */
00198     
00199     register hdloutlinerecord ho = outlinedata;
00200     Rect outlinerect = (**ho).outlinerect;
00201     long origct = (**ho).ctexpanded;
00202     long lnum;
00203     Rect linerect, iconrect, r;
00204     long hscroll, vscroll;
00205     
00206     if (!(*(**ho).preexpandcallback) (hnode, level, flmaycreatesubs))
00207         return (false);
00208     
00209     ctalreadyexpanded = 0;
00210     
00211     pixelsexpanded = 0;
00212     
00213     pixelsalreadyexpanded = 0;
00214     
00215     oprecursivelyvisit (hnode, level, &opexpandvisit, nil);
00216     
00217     origct = (**ho).ctexpanded - origct; 
00218     
00219     if (origct == 0) /*nothing expanded*/
00220         return (false); 
00221     
00222     opdirtyview ();
00223     
00224     if (!opdisplayenabled ())
00225         return (true);
00226     
00227     opgetscreenline (hnode, &lnum);
00228     
00229     opgetlinerect (lnum, &linerect); 
00230     
00231     /*handle case where height of the head + subs is > height of win*/ {
00232         
00233         long heightheads = pixelsexpanded + pixelsalreadyexpanded + opgetlineheight (hnode);
00234         long heightwin = outlinerect.bottom - outlinerect.top;
00235         
00236         if (heightheads > heightwin) { /*smash the display, no optimization possible*/
00237         
00238             if (hnode != (**ho).hline1) {
00239                 
00240                 opsetline1 (hnode);
00241                 
00242                 opsetscrollpositiontoline1 ();
00243                 }
00244             
00245             /*
00246             opgetscrollbarinfo (false); 
00247             
00248             (**ho).vertscrollinfo.cur += lnum; //text scrolls up
00249             */
00250             
00251             opresetscrollbars (); 
00252             
00253             opseteditbufferrect (); //in case we're in text mode
00254             
00255             opinvaldisplay ();
00256             
00257             //operaserect ((**ho).outlinerect);
00258             
00259             opupdatenow ();
00260             
00261             return (true);
00262             }
00263         }
00264     
00265     if (false) { /*dmb: it's slower to do just the icon because of the irregular region*/
00266     
00267         opgeticonrect (hnode, &linerect, &iconrect); /*icon might have changed to reflect expansion*/
00268     
00269         invalrect (iconrect); /*the icon changes, avoid flash, don't inval the whole line*/
00270         }
00271     //else
00272     //  opinvalnode (hnode);
00273     
00274     opresetscrollbars (); 
00275     
00276     if (opneedvisiscroll (oplastexpanded (hnode), &hscroll, &vscroll, false)) {
00277     
00278         (**ho).blockvisiupdate = true;
00279         
00280         opdovisiscroll (hscroll, vscroll);
00281         
00282         (**ho).blockvisiupdate = false;
00283         
00284         //opinvalafter ((**hnode).headlinkright);
00285         opinvalafter (hnode);
00286         }
00287     else {
00288         r = linerect; /*get ready to scroll to make room for newly visible text*/
00289         
00290         r.top = r.bottom;
00291         
00292         if (ctalreadyexpanded > 0) { /*account for already-expanded lines*/
00293             
00294             r.bottom = r.top + pixelsalreadyexpanded;
00295             
00296             invalrect (r);
00297             
00298             r.top = r.bottom;
00299             }
00300         
00301         r.bottom = outlinerect.bottom;
00302         
00303         opscrollrect (r, 0, pixelsexpanded); /*scroll text down to make room for new heads*/
00304         
00305         opinvalnode (hnode);
00306         }
00307     
00308     opupdatenow (); 
00309     
00310     return (true);
00311     } /*opexpand*/
00312     
00313 
00314 static void oprecursivelyexpandto (hdlheadrecord hnode) {
00315     
00316     /*
00317     work your way left until you find a node which is expanded.  expand it.
00318    
00319     then retrace your steps, expanding as you go.
00320     */
00321     
00322     hdlheadrecord hparent = (**hnode).headlinkleft;
00323     
00324     if (hparent == hnode) /*at a summit, all summits are expanded*/
00325         return;
00326     
00327     if ((**hnode).flexpanded) 
00328         return;
00329         
00330     oprecursivelyexpandto (hparent); /*recurse*/
00331     
00332     oprecursivelyvisit (hparent, 1, &opexpandvisit, nil); /*set expanded bits on sibs*/
00333     } /*oprecursivelyexpandto*/
00334 
00335 
00336 void opexpandto (hdlheadrecord hnode) {
00337     
00338     /*
00339     make sure that the indicated node is expanded. also moves 
00340     the cursor to the node.
00341     
00342     8/10/92 dmb: pophoists as necessary to make the node accessable
00343     */
00344     
00345     register hdloutlinerecord ho = outlinedata;
00346     
00347     if ((**ho).hbarcursor == hnode) /*cursor is already on the node*/
00348         return;
00349     
00350     while (((**ho).tophoist > 0) && !opcontainsnode ((**ho).hsummit, hnode))
00351         oppophoist ();
00352     
00353     if ((**hnode).flexpanded) { /*just move the cursor to it and return*/
00354         
00355         opmoveto (hnode);
00356     
00357         opdirtyview ();
00358         
00359         return;
00360         }
00361     
00362     /*the node we're looking for isn't expanded*/
00363     
00364     oprecursivelyexpandto (hnode);
00365     
00366     opsetscrollpositiontoline1 ();
00367     
00368     opresetscrollbars ();
00369     
00370     opmoveto (hnode);
00371     
00372     opsmashdisplay ();
00373     
00374     opdirtyview ();
00375     } /*opexpandto*/
00376 
00377 
00378 void opexpandtoggle (void) {
00379     
00380     /*
00381     if expanded, collapse.  if not expanded, expand.
00382     
00383     11/4/92 dmb: always try one or the other, in case subheads appear dynamically
00384     
00385     7.0d5 AR: Run op callback scripts 
00386     */
00387     
00388     register hdlheadrecord hcursor = (**outlinedata).hbarcursor;
00389     register hdlheadrecord hright = (**hcursor).headlinkright;
00390     
00391     if ((hright != hcursor) && (**hright).flexpanded) { /*first subhead is showing, collapse is called for*/
00392 
00393         if (langopruncallbackscripts (idopcollapsescript))
00394             return;  /*fuction consumed the click*/
00395 
00396         opcollapse (hcursor);
00397         }       
00398     else {
00399 
00400         if (langopruncallbackscripts (idopexpandscript))
00401             return;  /*fuction consumed the click*/
00402 
00403         opexpand (hcursor, 1, true);
00404         }
00405     } /*opexpandtoggle*/
00406 
00407 
00408 void opexpandupdate (hdlheadrecord hnewnode) {
00409     
00410     /*
00411     5.0b6 dmb: allow for partially-visible lines
00412     */
00413     
00414     register hdloutlinerecord ho = outlinedata;
00415     long ctlines;
00416     long lnum;
00417     
00418     (**hnewnode).flexpanded = true; 
00419     
00420     ctlines = opgetnodelinecount (hnewnode);
00421     
00422     (**ho).ctexpanded += ctlines;
00423     
00424     if (opdisplayenabled ()) {
00425         
00426         opresetscrollbars ();
00427         
00428         opgetscreenline (hnewnode, &lnum);
00429         
00430         if (lnum < 0)
00431             (**ho).vertscrollinfo.cur += ctlines;
00432         
00433         else if (lnum <= opgetcurrentscreenlines (false)) {/*node is visible*/
00434         
00435             opmakegap (lnum - 1, opgetlineheight (hnewnode));
00436             
00437             opupdatenow ();
00438             }
00439         }
00440     } /*opexpandupdate*/
00441 
00442 
00443 void opcollapseall (void) {
00444     
00445     hdlheadrecord nomad = (**outlinedata).hsummit;
00446     boolean fldisplaywasenabled;
00447     
00448     fldisplaywasenabled = opdisabledisplay ();
00449     
00450     while (true) {
00451         
00452         opjumpto (nomad);
00453     
00454         if (opsubheadsexpanded (nomad)) 
00455             opcollapse (nomad);
00456             
00457         if (!opchasedown (&nomad)) {
00458             
00459             opjumpto ((**outlinedata).hsummit);
00460             
00461             if (fldisplaywasenabled) {
00462                 
00463                 openabledisplay ();
00464                 
00465                 opinvaldisplay ();
00466                 }
00467             
00468             return;
00469             }
00470         } /*while*/
00471     } /*opcollapseall*/
00472     
00473     
00474 boolean opsetlongcursor (long cursor) { 
00475 
00476     hdlheadrecord hcursor = (hdlheadrecord) cursor;
00477 
00478     if (!opnodeinoutline (hcursor)) /*it's been deleted, or something*/
00479         return (false);
00480     
00481     opexpandto (hcursor);
00482     
00483     return (true);
00484     } /*opsetlongcursor*/
00485     
00486 
00487 
00488 
00489 
00490 

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