claybrowserexpand.c

Go to the documentation of this file.
00001 
00002 /*  $Id: claybrowserexpand.c 1211 2006-04-06 00:20:14Z 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 "cursor.h"
00032 #include "file.h"
00033 #include "fileloop.h"
00034 #include "kb.h"
00035 #include "memory.h"
00036 #include "strings.h"
00037 #include "shellundo.h"
00038 
00039 #include "op.h"
00040 #include "opinternal.h"
00041 #include "claybrowserstruc.h"
00042 #include "claybrowserexpand.h"
00043 #include "claycallbacks.h"
00044 
00045 
00046 static boolean compoundexpand = false;
00047 
00048 static short expandcount; /*for debugging*/
00049 
00050 
00051 static void browsercalcinsertionpoint (hdlheadrecord hparent, hdlheadrecord *hpre, tydirection *dir) {
00052     
00053     /*
00054     using whatever sorting options we have, determine the insertion point for the
00055     new line. we return the info that opaddheadline needs, a handle to the "pre"
00056     node and the direction relative to that node to create the new headline.
00057     
00058     special case: if hparent == nil, we do it at the summit level.
00059     
00060     possible view settings: name, date, kind, size, label.
00061     
00062     9/22/93 dmb: added cases for remaining possible view settings, treating 
00063     them all as viewbyname. also viewbyname sort order is unicase.
00064     */
00065     
00066     if (hparent == nil) {
00067         
00068         *hpre = oprepeatedbump (down, longinfinity, (**outlinedata).hsummit, true); /*special case*/;
00069         
00070         *dir = down;
00071         }
00072     else {
00073         
00074         if (opnosubheads (hparent)) {
00075             
00076             *hpre = hparent;
00077             
00078             *dir = right;
00079             }
00080         else {
00081             *hpre = opgetlastsubhead (hparent);
00082         
00083             *dir = down;
00084             }
00085         }
00086     } /*browsercalcinsertionpoint*/
00087     
00088     
00089 void browserfindinsertionpoint (hdlheadrecord hparent, bigstring bsnewhead, tybrowserinfo *newfileinfo, hdlheadrecord *hpre, tydirection *dir) {
00090     
00091     /*
00092     using whatever sorting options we have, determine the insertion point for the
00093     new line. we return the info that opaddheadline needs, a handle to the "pre"
00094     node and the direction relative to that node to create the new headline.
00095     
00096     special case: if hparent == nil, we do it at the summit level.
00097     
00098     possible view settings: name, date, kind, size, label.
00099     
00100     9/22/93 dmb: added cases for remaining possible view settings, treating 
00101     them all as viewbyname. also viewbyname sort order is unicase.
00102     */
00103     
00104     hdlheadrecord nomad;
00105     tyfolderview folderview;
00106 #if filebrowser
00107     unsigned long time1, time2;
00108     unsigned long size1, size2;
00109     short label1, label2;
00110     bigstring bsnew;
00111 #endif
00112 #if odbbrowser
00113     hdlhashtable ht;
00114     hdlhashnode hnode, hnext;
00115     bigstring bsnext;
00116     hdlheadrecord hmatch;
00117 #endif      
00118     
00119     if (hparent == nil) {
00120         
00121         folderview = viewbyname;
00122         
00123         nomad = (**outlinedata).hsummit; /*special case*/
00124         
00125         *hpre = nomad;
00126         
00127         *dir = up;
00128         }
00129     else {
00130         
00131     #if filebrowser
00132         tybrowserinfo browserinfo;
00133         
00134         browsergetrefcon (hparent, &browserinfo);
00135         
00136         folderview = browserinfo.folderview;
00137     #endif
00138     
00139         nomad = hparent;
00140         
00141         *hpre = nomad;
00142         
00143         *dir = right;
00144     
00145         if (!opchaseright (&nomad)) /*has no expanded subs*/
00146             return;
00147         }
00148     
00149     #if odbbrowser
00150         
00151         ht = (*newfileinfo).dirid;
00152         
00153         if (hashtablelookupnode (ht, bsnewhead, &hnode)) { // should not fail
00154             
00155             hnext = (**hnode).sortedlink;
00156             
00157             if (hnext != nil) { // we're not last
00158                 
00159                 gethashkey (hnext, bsnext);
00160                 
00161                 if (opfindhead (nomad, bsnext, &hmatch)) { // shouldn't fail
00162                     
00163                     *hpre = hmatch;
00164                     
00165                     *dir = up;
00166                     
00167                     return;
00168                     }
00169                 }
00170             }
00171         
00172         // default: insert at end of list
00173         
00174         *hpre = oprepeatedbump (down, longinfinity, nomad, true);
00175         
00176         *dir = down;
00177         
00178         return;
00179         
00180     #endif
00181     
00182     
00183     #if filebrowser
00184     
00185     folderview = -1;
00186     
00187     switch (folderview) { /*initialize the things we compare against*/ 
00188         
00189         case viewbyname:
00190         case viewbyicon:
00191         case viewbysmallicon:
00192         case viewbycomment:
00193         case viewbyversion:
00194             copystring (bsnewhead, bsnew);
00195             
00196             alllower (bsnew);
00197             
00198             break;
00199             
00200         case viewbykind:
00201             setstringlength (bsnew, 4);
00202             
00203             moveleft (&(*newfileinfo).filecreator, &bsnew [1], 4);
00204     
00205             break;
00206             
00207         case viewbydate:
00208             time1 = (unsigned long) (*newfileinfo).timemodified;
00209     
00210             break;
00211             
00212         case viewbysize:
00213             size1 = (*newfileinfo).filesize;
00214             
00215             break;
00216             
00217         case viewbycolor:
00218             label1 = (*newfileinfo).ixlabel;
00219             
00220             break;
00221         } /*switch*/
00222         
00223     while (true) {
00224         
00225         switch (folderview) {
00226         
00227             case viewbyname:
00228             case viewbyicon:
00229             case viewbysmallicon:
00230             case viewbycomment:
00231             case viewbyversion: {
00232                 bigstring bs;
00233                 
00234                 opgetheadstring (nomad, bs);
00235                 
00236                 alllower (bs);
00237                 
00238                 if (comparestrings (bsnew, bs) == -1) /*bsnewhead is < bs*/
00239                     return;
00240                 
00241                 break;
00242                 }
00243             
00244             case viewbykind: {
00245                 tybrowserinfo nomadinfo;
00246                 bigstring bs;
00247             
00248                 browsergetrefcon (nomad, &nomadinfo);
00249             
00250                 setstringlength (bs, 4);
00251             
00252                 moveleft (&nomadinfo.filecreator, &bs [1], 4);
00253                 
00254                 if (comparestrings (bsnew, bs) == -1) /*bsnew is < bs*/
00255                     return;
00256                     
00257                 break;
00258                 }
00259                 
00260             case viewbydate: {
00261                 tybrowserinfo nomadinfo;
00262             
00263                 browsergetrefcon (nomad, &nomadinfo);
00264             
00265                 time2 = (unsigned long) nomadinfo.timemodified;
00266             
00267                 if (time1 >= time2)
00268                     return;
00269                     
00270                 break;
00271                 }
00272                 
00273             case viewbysize: {
00274                 tybrowserinfo nomadinfo;
00275             
00276                 browsergetrefcon (nomad, &nomadinfo);
00277             
00278                 size2 = nomadinfo.filesize;
00279             
00280                 if (size1 >= size2)
00281                     return;
00282                     
00283                 break;
00284                 }
00285                 
00286             case viewbycolor: {
00287                 tybrowserinfo nomadinfo;
00288             
00289                 browsergetrefcon (nomad, &nomadinfo);
00290             
00291                 label2 = nomadinfo.ixlabel;
00292             
00293                 if (label1 >= label2)
00294                     return;
00295                     
00296                 break;
00297                 }
00298             } /*switch*/
00299         
00300         *hpre = nomad;
00301         
00302         *dir = down;
00303         
00304         if (!opchasedown (&nomad)) /*it's the last guy in the list*/
00305             return;
00306         } /*while*/
00307     #endif
00308     } /*browserfindinsertionpoint*/
00309     
00310 
00311 boolean browserexpandvisit (bigstring bsitem, tybrowserinfo *info, long refcon) {
00312     
00313     /*
00314     dmb 9/23/93: call opstart/endinternalchange around opaddheadline. this turns 
00315     off the lineinsertedcallback and prevents an undo from being built -- which 
00316     would otherwise delete the file!  these calls used to be in browserpreexpand, 
00317     but that was when this visit routine wasn't directly callable.
00318     */
00319     
00320     register tyexpandinfo *expandinfo = (tyexpandinfo *) refcon;
00321     hdlheadrecord hnew;
00322     
00323     if (!testheapspace (512)) /*512 bytes should be plenty*/ 
00324         return (false);
00325         
00326     /*debugging code {
00327         
00328         bigstring bs;
00329         
00330         NumToString (expandcount++, bs);
00331         
00332         appsetmessage (app.appwindow, bs);
00333         }
00334     */
00335         
00336     if (keyboardescape ()) /*user pressed cmd-period*/
00337         return (false);
00338     
00339     rollbeachball ();
00340     
00341     /*insert the new line*/ {
00342         
00343         hdlheadrecord hpre;
00344         tydirection dir;
00345         
00346         if ((*expandinfo).flsortnodes)
00347             browserfindinsertionpoint ((*expandinfo).hparent, bsitem, info, &hpre, &dir);
00348         else
00349             browsercalcinsertionpoint ((*expandinfo).hparent, &hpre, &dir);
00350         
00351         opstartinternalchange (); /*this operation is not undo-able, and mustn't trigger callbacks*/
00352         
00353         opaddheadline (hpre, dir, bsitem, &hnew);
00354         
00355         opendinternalchange ();
00356         }
00357     
00358     browsercopyfileinfo (hnew, info);
00359     
00360     if ((*expandinfo).flsettmpbits)
00361         (**hnew).tmpbit = true; /*if expand is cancelled, we nuke all nodes with tmp bit set*/
00362     
00363     if ((*info).flfolder) {
00364         
00365         (**hnew).flnodeisfolder = true;
00366         
00367         if ((*expandinfo).ctlevels > 1) {
00368         
00369             if (!browserexpand (hnew, (*expandinfo).ctlevels - 1))
00370                 return (false);
00371             }
00372         }
00373     
00374     (*expandinfo).hnewnode = hnew; /*some callers need this*/
00375     
00376     return (true);
00377     } /*browserexpandvisit*/
00378 
00379 
00380 boolean browserexpand (hdlheadrecord hnode, long ctlevels) {
00381     
00382     tyexpandinfo expandinfo;
00383     tybrowserspec fs;
00384     
00385     if (opsubheadsexpanded (hnode)) { /*special case for a node that's already expanded*/
00386         
00387         hdlheadrecord nomad = (**hnode).headlinkright;
00388         
00389         if (ctlevels <= 1) /*we aren't going any deeper*/
00390             return (true);
00391         
00392         while (true) { /*loop over all the subheads of the node*/
00393             
00394             if ((**nomad).flnodeisfolder) {
00395             
00396                 if (!browserexpand (nomad, ctlevels - 1))
00397                     return (false);
00398                 }
00399                 
00400             if (!opchasedown (&nomad))
00401                 return (true);
00402             } /*while*/
00403         } /*dealing with already-expanded nodes*/
00404     
00405     claygetfilespec (hnode, &fs);
00406     
00407     expandinfo.hparent = hnode;
00408     
00409     expandinfo.ctlevels = ctlevels;
00410     
00411     expandinfo.flsettmpbits = true;
00412     
00413 #if odbbrowser
00414     expandinfo.flsortnodes = false;
00415 #else
00416     expandinfo.flsortnodes = true;
00417 #endif
00418 
00419     expandcount = 0; /*for debugging*/
00420     
00421     return (clayfolderloop (&fs, false, &browserexpandvisit, (long) &expandinfo));
00422     } /*browserexpand*/
00423     
00424     
00425 static boolean expandcancelledvisit (hdlheadrecord hnode, ptrvoid refcon) {
00426 #pragma unused (refcon)
00427 
00428     if ((**hnode).tmpbit) {
00429         
00430         opstartinternalchange ();
00431         
00432         opdeletenode (hnode);
00433         
00434         opendinternalchange ();
00435         }
00436         
00437     return (true);
00438     } /*expandcancelledvisit*/
00439     
00440 
00441 boolean browserpreexpand (hdlheadrecord hnode, short ctlevels, boolean flmaycreatesubs) {
00442     
00443     /*
00444     called by opexpand.c before expanding nodes. we create new nodes under
00445     the node by looping over its folder on disk.
00446     
00447     DW 8/18/93: allow the user to press cmd-period to cancel the expand
00448     operation. set the tmpbit of every newly created node. if the user
00449     hits cmd-period, or if we run out of memory, we delete all nodes with
00450     their tmp bit set. important: we don't clear the tmp bits here, we
00451     depend on them all being clear before the operation starts. the reason:
00452     some operations do several calls to us. we want them all to be 
00453     cancelled.
00454     
00455     DW 8/30/93: do it right this time. add another piece of baling wire, the
00456     compoundexpand flag. if it's not true, we clear the tmpbits. otherwise
00457     we assume they've been cleared.
00458 
00459     5.0a25 dmb: auto-create item in empty table to expand, if new flmaycreatesubs
00460     parameter is true
00461     */
00462     
00463     register hdloutlinerecord ho = outlinedata;
00464     boolean fl;
00465     
00466     if (((**hnode).headlinkright != hnode) && (ctlevels <= 1)) /*the nodes are already there*/
00467         return (true);
00468         
00469     if (!(**hnode).flnodeisfolder) /*can't expand a file*/
00470         return (true);
00471     
00472     initbeachball (right);
00473     
00474     if (!compoundexpand)
00475         opcleartmpbits ();
00476     
00477     fl = browserexpand (hnode, ctlevels);
00478     
00479     if (!fl) /*memory error, or user pressed cmd-period or escape*/
00480         opsiblingvisiter ((**ho).hsummit, true, &expandcancelledvisit, nil);
00481     
00482     if (!compoundexpand)
00483         opcleartmpbits ();
00484     
00485     if ((**hnode).headlinkright == hnode) { // table was empty
00486         
00487         if (flmaycreatesubs) {
00488 
00489             hdlheadrecord hnew;
00490             
00491             opstartinternalchange ();
00492             
00493             opaddheadline (hnode, right, emptystring, &hnew);
00494             
00495             opendinternalchange ();
00496             
00497             if (hnode == nil)
00498                 return (false);
00499 
00500             browserlineinserted (hnew);
00501             }
00502         }
00503     
00504     #ifdef xxxfldebug
00505         opsetctexpanded (ho);
00506     
00507         opvalidate (ho);
00508     #endif
00509         
00510     return (fl);
00511     } /*browserpreexpand*/
00512 
00513 
00514 boolean browserselectfile (ptrfilespec pfs, boolean flexpand, hdlheadrecord *hnode) {
00515 
00516     bigstring filepath;
00517     hdlheadrecord nomad;
00518     boolean flsomethingexpanded = false;
00519     boolean flreturn = false;
00520     boolean fldisplaywasenabled;
00521     
00522     *hnode = nil;
00523     
00524     compoundexpand = true; opcleartmpbits ();
00525     
00526     filespectopath (pfs, filepath);
00527     
00528     fldisplaywasenabled = opdisabledisplay ();
00529     
00530     nomad = (**outlinedata).hsummit;
00531     
00532 //  addtohistorydisabled = true; /*don't want intermediate expansions added to the history menu*/
00533     
00534     while (true) {
00535         
00536         bigstring headstring;
00537         
00538         if (stringlength (filepath) == 0) 
00539             break;
00540         
00541         firstword (filepath, ':', headstring);
00542         
00543         if (stringlength (headstring) == 0)
00544             copystring (filepath, headstring);
00545             
00546         deletestring (filepath, 1, (short) (stringlength (headstring) + 1));
00547         
00548         if (!opfindhead (nomad, headstring, &nomad))
00549             break;
00550         
00551         if (stringlength (filepath) == 0) {
00552             
00553             flreturn = true; 
00554             
00555             break;
00556             }
00557             
00558         if (flexpand) {
00559         
00560             if (!opsubheadsexpanded (nomad)) {
00561                 
00562                 if (!opexpand (nomad, 1, false)) { /*user pressed cmd-period, or we ran out of memory*/
00563                     
00564                     openabledisplay ();
00565                     
00566                     return (false);
00567                     }
00568                     
00569                 flsomethingexpanded = true;
00570                 }
00571             }
00572             
00573         if (!opnavigate (right, &nomad))
00574             break;
00575         } /*while*/
00576     
00577 //  addtohistorydisabled = false;
00578     
00579     if (fldisplaywasenabled)
00580         openabledisplay ();
00581     
00582     if (flsomethingexpanded) {
00583     
00584         opresetscrollbars ();
00585     
00586         opinvaldisplay ();
00587         }
00588     
00589     compoundexpand = false;
00590     
00591     opcleartmpbits ();
00592     
00593     *hnode = nomad;
00594     
00595     return (flreturn);
00596     } /*browserselectfile*/
00597     
00598     
00599 boolean browserexpandtofile (ptrfilespec pfs) {
00600     
00601     hdlheadrecord hnode;
00602     
00603     opclearallmarks ();
00604     
00605     if (!browserselectfile (pfs, true, &hnode))
00606         return (false);
00607         
00608     (**outlinedata).flcursorneedsdisplay = true; /*might need to vertical-scroll*/
00609     
00610     opjumpto (hnode);
00611     
00612     opupdatenow ();
00613         
00614     return (true);
00615     } /*browserexpandtofile*/
00616     
00617     
00618 boolean browsercanexpand (hdlheadrecord hnode) {
00619 
00620     tybrowserinfo info;
00621     
00622     browsergetrefcon (hnode, &info);
00623     
00624     return (info.flfolder && (info.filesize > 0));
00625     } /*browsercanexpand*/
00626 
00627 
00628 boolean browserpostcollapse (hdlheadrecord hnode) {
00629     
00630     /*
00631     5.0a25 dmb: auto-delete auto-created node
00632     
00633     5.1.4 dmb: after deleting an auto-created node, we still need to delete subs
00634     */
00635 
00636     hdloutlinerecord ho = outlinedata;
00637     boolean fldisplaywasenabled;
00638     
00639     killundo ();
00640     
00641     /*toss auto-created nodes, if present*/ {
00642         hdlheadrecord hsub = (**hnode).headlinkright;
00643         
00644         browserdeletedummyvalues (hsub);
00645         
00646         /*
00647         tybrowserspec fs;
00648         tyvaluerecord val;
00649         
00650         if ((**hsub).tmpbit2 && opislastsubhead (hsub)) {
00651             
00652             if (claygetfilespec (hsub, &fs) && claylookupvalue (&fs, &val))
00653                 if (val.valuetype == novaluetype) {
00654                     
00655                     hashtabledelete (fs.parID, fs.name);
00656                     
00657                     //return (true);
00658                     }
00659             }
00660         */
00661         }
00662      
00663     fldisplaywasenabled = opdisabledisplay (); /*keep the cursor line from flashing*/
00664     
00665     opstartinternalchange ();
00666     
00667     /*make sure the outline is (temporarily) not read-only*/ {
00668     
00669         boolean fltemp = (**ho).flreadonly;
00670         
00671         (**ho).flreadonly = false; /*allow deletion to happen*/
00672         
00673         opdeletesubs (hnode);
00674         
00675         (**ho).flreadonly = fltemp;
00676         }
00677     
00678     if (fldisplaywasenabled)
00679         openabledisplay ();
00680     
00681     opendinternalchange ();
00682     
00683     return (true);
00684     } /*browserpostcollapse*/
00685 
00686 

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