opscreenmap.c

Go to the documentation of this file.
00001 
00002 /*  $Id: opscreenmap.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "quickdraw.h"
00033 #include "opinternal.h"
00034 #include "oplineheight.h"
00035 #include "opdisplay.h"
00036 
00037 
00038 
00039 boolean opnewscreenmap (hdlscreenmap *hmap) {
00040     
00041     /*
00042     take a snapshot of what headrecord is displayed on what screen line.
00043     */
00044     
00045     tymapelement *pe;
00046     short ctelements;
00047     hdloutlinerecord ho = outlinedata;
00048     hdlheadrecord nomad = (**ho).hline1;
00049     hdlheadrecord hcursor = (**ho).hbarcursor;
00050     hdlscreenmap h;
00051     hdlheadrecord orignomad;
00052     long sizemap;
00053     Handle hnew;
00054     
00055     ctelements = opgetcurrentscreenlines (false) + 1; /*allow for partially visible line*/
00056     
00057     sizemap = sizeof (tyscreenmap) + (ctelements * sizeof (tymapelement));
00058     
00059     if (!newclearhandle (sizemap, &hnew)) {
00060         
00061         *hmap = nil;
00062         
00063         return (false);
00064         }
00065     
00066     h = *hmap = (hdlscreenmap) hnew; /*copy into returned value, register*/
00067     
00068     (**h).ctelements = ctelements;
00069 
00070     for (pe = (**h).map;  ctelements;  --ctelements, ++pe) {
00071         
00072         (*pe).hnode = nomad;
00073         
00074         (*pe).level = (**nomad).headlevel;
00075         
00076         (*pe).vpixels = (**nomad).vpixels;
00077         
00078         (*pe).flcursorhere = (nomad == hcursor);
00079         
00080         (*pe).flmarked = (**nomad).flmarked;
00081         
00082         orignomad = nomad;
00083         
00084         nomad = opgetnextexpanded (nomad);
00085     
00086         if (nomad == orignomad) /*rest of the items are already 0'd*/
00087             break;
00088         } /*for*/
00089     
00090     return (true);
00091     } /*opnewscreenmap*/
00092     
00093     
00094 void opinvalscreenmap (hdlscreenmap hmap) {
00095     
00096     /*
00097     inval those lines in the current display that differ from
00098     the elements of the screenmap.  we're willing to do a lot
00099     of analysis to avoid displaying a line that does not need
00100     to be displayed.
00101     
00102     things that make a line dirty: 
00103     
00104     1. if its fldirty bit is set, 
00105     
00106     2. if it is now blank, but wasn't blank before, 
00107     
00108     3. if a different node is displayed on the line,
00109     
00110     4. if the level of the node changed,
00111     
00112     5. if the cursor is on the line, but wasn't before,
00113     
00114     6. if the cursor was on the line before, but isn't now.
00115     
00116     7. 5.0a25 dmb: if the node's marked status changed (and it's not the barcursor)
00117     
00118     when we're done we dispose of the map, since every caller
00119     seems to want to do that as the next thing.
00120 
00121     5.0b18 dmb: handle having more display lines than in the map
00122     */
00123     
00124     hdlheadrecord nomad;
00125     short i;
00126     boolean fldirty;
00127     hdlscreenmap h = hmap;
00128     hdloutlinerecord ho = outlinedata;
00129     hdlheadrecord hnode;
00130     hdlheadrecord hcursor = (**ho).hbarcursor;
00131     short ctelements;
00132     tymapelement element;
00133     long ctlines;
00134     Rect r, rscroll;
00135     long scrollpixels = 0;
00136     
00137     if (!opdisplayenabled ()) {
00138     
00139         disposehandle ((Handle) h); 
00140         
00141         return;
00142         }
00143     
00144     if (h == nil) { /*no screenmap*/
00145     
00146         opinvaldisplay ();
00147         
00148         return;
00149         }
00150     
00151     nomad = (**ho).hline1;
00152     
00153     ctelements = (**h).ctelements;
00154     
00155     for (i = 0; i < ctelements; i++) {
00156         
00157         element = (**h).map [i];
00158         
00159         fldirty = false;
00160         
00161         if (nomad == nil) {
00162             
00163             if (element.hnode != nil)
00164                 fldirty = true;
00165                 
00166             goto L1;
00167             }
00168         
00169         opgetlineheight (nomad); //force calculation
00170         
00171         if (element.vpixels != (**nomad).vpixels) { /*level changed*/
00172             
00173             fldirty = true;
00174             
00175             if (scrollpixels == 0) { //don't already have a scroll
00176                 
00177                 fldirty = false; //we're going to set up special invals
00178                 
00179                 opgetlinerect (i, &rscroll);
00180                 
00181                 scrollpixels = (**nomad).vpixels - element.vpixels;
00182                 
00183                 if (scrollpixels < 0) //getting shorter
00184                     rscroll.bottom = rscroll.top + element.vpixels; //original height
00185                 }
00186             
00187             (**nomad).fldirty = false; //make sure we're clean
00188             
00189             goto L1;
00190             }
00191         
00192         if ((**nomad).fldirty) {
00193             
00194             fldirty = true;
00195             
00196             (**nomad).fldirty = false; /*consume it*/
00197             
00198             goto L1;
00199             }
00200             
00201         if (element.level != (**nomad).headlevel) { /*level changed*/
00202             
00203             fldirty = true;
00204             
00205             goto L1;
00206             }
00207         
00208         hnode = element.hnode; /*copy into register*/
00209         
00210         if (hnode != nomad) { /*different node on this line*/
00211             
00212             fldirty = true;
00213             
00214             goto L1;
00215             }
00216         
00217         if ((hnode == hcursor) != element.flcursorhere) { /*bar cursor is/was on this line*/
00218         
00219             fldirty = true;
00220             
00221             goto L1;
00222             }
00223         
00224         if ((**hnode).flmarked != element.flmarked) {
00225             
00226             fldirty = true;
00227             
00228             goto L1;
00229             }
00230         
00231         L1:
00232         
00233         if (fldirty) {
00234         
00235             if (scrollpixels) { // dirty node after a scroll node
00236                 
00237                 rscroll.bottom = (**ho).outlinerect.bottom;
00238                 
00239                 invalrect (rscroll);
00240                 
00241                 scrollpixels = 0; //consumed
00242                 
00243                 break;
00244                 }
00245             
00246             if (nomad != nil)
00247                 oplineinval (i);
00248             else {
00249                 
00250                 opgetlinerect (i - 1, &r);
00251 
00252                 r.top = r.bottom;
00253 
00254                 r.bottom = (**ho).outlinerect.bottom;
00255 
00256                 invalrect (r);
00257                 }
00258             }
00259             
00260         if (nomad != nil) {
00261             
00262             hdlheadrecord orignomad = nomad;
00263             
00264             nomad = opgetnextexpanded (nomad);
00265             
00266             if (nomad == orignomad)
00267                 nomad = nil;
00268             }
00269         } /*for*/
00270     
00271     if (scrollpixels) { //an element changed height, no dirty lines after
00272         
00273         invalrect (rscroll);
00274         
00275         rscroll.top = rscroll.bottom;
00276         
00277         if (scrollpixels < 0)
00278             rscroll.top += scrollpixels;
00279         
00280         rscroll.bottom = (**ho).outlinerect.bottom;
00281         
00282         opscrollrect (rscroll, 0, scrollpixels);
00283         }
00284     
00285     ctlines = opgetcurrentscreenlines (false) + 1;
00286     
00287     if ((ctelements < ctlines) && (nomad != nil)) //more lines now than in the map
00288         opinvalafter (nomad);
00289     
00290     disposehandle ((Handle) h); /*no longer needed*/
00291     } /*opinvalscreenmap*/
00292 
00293 
00294 void opinvaldirtynodes (void) {
00295     
00296     /*
00297     high-level guys can set the dirty bits on the nodes whose attributes they've
00298     changed. we take care of inval'ing all the nodes.
00299     
00300     this can save having to push and pop the port a lot. just dirty the bits and
00301     set the port and call us.
00302     */
00303     
00304     hdlscreenmap hmap;
00305     
00306     opnewscreenmap (&hmap);
00307     
00308     opinvalscreenmap (hmap);
00309     } /*opinvaldirtynodes*/
00310     
00311     
00312     
00313     

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