claybrowserstruc.c

Go to the documentation of this file.
00001 
00002 /*  $Id: claybrowserstruc.c 1254 2006-04-12 20:27:14Z sethdill $    */
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 "dialogs.h"
00033 #include "error.h"
00034 #include "file.h"
00035 #include "fileloop.h"
00036 #include "kb.h"
00037 #include "memory.h"
00038 #include "ops.h"
00039 #include "quickdraw.h"
00040 #include "process.h"
00041 #include "scrap.h"
00042 #include "strings.h"
00043 #include "opinternal.h"
00044 #include "oplineheight.h"
00045 #include "claybrowser.h"
00046 #include "claycallbacks.h"
00047 #include "claybrowserexpand.h"
00048 #include "claybrowservalidate.h"
00049 #include "claybrowserstruc.h"
00050 #if odbbrowser
00051     #include "shell.rsrc.h"
00052     #include "shellundo.h"
00053     #include "tableinternal.h"
00054     #include "tableverbs.h"
00055     #include "wpengine.h"
00056 #endif
00057 
00058 
00059 
00060 
00061 boolean browsergetrefcon (hdlheadrecord hnode, tybrowserinfo *info) {
00062     
00063     return (opgetrefcon (hnode, info, sizeof (tybrowserinfo)));
00064     } /*browsergetrefcon*/
00065 
00066 
00067 boolean browsersetrefcon (hdlheadrecord hnode, tybrowserinfo *info) {
00068     
00069     return (opsetrefcon (hnode, info, sizeof (tybrowserinfo)));
00070     } /*browsersetrefcon*/
00071 
00072 
00073 boolean browsercopyfileinfo (hdlheadrecord hnode, tybrowserinfo *fileinfo) {
00074     
00075     /*
00076     set the fields of a browser refcon handle that come from 
00077     a file's fileinfo record. ignore the other fields.
00078     */
00079     
00080 //  tybrowserinfo browserinfo;
00081     
00082 //  browsergetrefcon (hnode, &browserinfo);
00083     
00084     if (!browsersetrefcon (hnode, fileinfo))
00085         return (false);
00086     
00087     return (true);
00088     } /*browsercopyfileinfo*/
00089 
00090 
00091 static void filepushsuffixnumber (short suffixnum, bigstring name) {
00092     
00093     if (suffixnum > 0) {
00094     
00095         pushstring (BIGSTRING ("\x02" " #"), name);
00096     
00097         pushint (suffixnum, name);
00098         }
00099     } /*filepushsuffixnumber*/
00100 
00101 
00102 static void filepopsuffixnumber (short suffixnum, bigstring name) {
00103     
00104     byte bssuffix [32];
00105     short ixsuffix;
00106     
00107     if (suffixnum > 0) {
00108     
00109         copystring (BIGSTRING ("\x02" " #"), bssuffix);
00110         
00111         pushint (suffixnum, bssuffix);
00112         
00113         ixsuffix = patternmatch (bssuffix, name) - 1;
00114 
00115         if (ixsuffix == stringlength (name) - stringlength (bssuffix))
00116             setstringlength (name, ixsuffix);
00117         }
00118     } /*filepushsuffixnumber*/
00119         
00120 
00121 boolean claygetfilespec (hdlheadrecord hnode, tybrowserspec *fs) { 
00122     
00123     /*
00124     turn a headrecord into a filespec.
00125     
00126     6/27/93 DW: per recommendation of Think Reference, if it's a
00127     volume, just set the vRefNum field of the filespec.
00128     
00129     8/30/93 DW: rewrite.
00130     
00131     9/21/93 dmb: don't need special case for volumes anymore. Think Ref's 
00132     recommendation is fine for specifying volumes, but it's event better 
00133     to specify the root directory of the volume, removing any special cases.
00134     
00135     5.1.4 dmb: on failure, clear fs
00136     */
00137     
00138     tybrowserinfo info;
00139     bigstring name;
00140     
00141     if (!browsergetrefcon (hnode, &info)) {
00142         
00143         clearbytes (fs, sizeof (tybrowserspec));
00144         
00145         return (false);
00146         }
00147     
00148     /*
00149     if (info.flvolume) { /%special case%/
00150         
00151         (*fs).vRefNum = info.vnum;
00152         
00153         (*fs).parID = 0; 
00154         
00155         setstringlength ((*fs).name, 0);
00156         
00157         return (true);
00158         }
00159     */
00160     
00161     opgetheadstring (hnode, name);
00162     
00163     // dmb 5.0b9 - was: filepushsuffixnumber (info.suffixnum, name);
00164     
00165     return (claymakespec (info.vnum, info.dirid, name, fs));
00166     } /*claygetfilespec*/
00167 
00168 
00169 boolean browserloadnode (hdlheadrecord hnode) {
00170 
00171     tybrowserspec fs;
00172     tybrowserinfo fileinfo;
00173     
00174     (**hnode).fldirty = true; /*force update to reflect new info*/
00175     
00176     claygetfilespec (hnode, &fs);
00177     
00178     if (!claygetfileinfo (&fs, &fileinfo))
00179         return (false);
00180     
00181     (**hnode).flnodeisfolder = fileinfo.flfolder;
00182     
00183     return (browsercopyfileinfo (hnode, &fileinfo));
00184     } /*browserloadnode*/
00185     
00186     
00187 boolean browserchecklinelength (short newlen, bigstring bs) {
00188 
00189     bigstring bsalert;
00190         
00191     if (newlen <= (short) (**outlinedata).maxlinelen) 
00192         return (true);
00193     
00194     copystring (BIGSTRING ("\x0e" "The file name "), bsalert);
00195     
00196     if (stringlength (bs) > 0) {
00197         
00198         pushstring (BIGSTRING ("\x01" "“"), bsalert);
00199         
00200         pushstring (bs, bsalert);
00201         
00202         pushstring (BIGSTRING ("\x01" "”"), bsalert);
00203         }
00204     
00205     pushstring (BIGSTRING ("\x2e" " is too long. The maximum file name length is "), bsalert);
00206     
00207     pushlong ((**outlinedata).maxlinelen, bsalert);
00208     
00209     pushstring (BIGSTRING ("\x0c" " characters."), bsalert);
00210     
00211     alertdialog (bsalert);
00212     
00213     return (false);
00214     } /*browserchecklinelength*/
00215 
00216 #if 0
00217 
00218 static boolean browserupdatefileinfo (hdlheadrecord hnode) {
00219 
00220     /*
00221     change the in-memory info to reflect what's on disk
00222     */ 
00223     
00224     tybrowserspec fs;
00225     tybrowserinfo info;
00226     
00227     if (hnode == nil) /*defensive driving*/
00228         return (false);
00229     
00230     claygetfilespec (hnode, &fs);
00231     
00232     claygetfileinfo (&fs, &info);
00233 
00234     browsercopyfileinfo (hnode, &info);
00235     
00236     return (true);
00237     } /*browserupdatefileinfo*/
00238 
00239 #endif
00240 
00241 
00242 boolean browserfileadded (hdlheadrecord hnodeparent, const tybrowserspec *fsnew, hdlheadrecord *hnew) { 
00243     
00244     /*
00245     a new item has been added to a folder, our job is to add the file
00246     to the display.
00247     
00248     dmb 9/23/93: removed setting/clearing of lineinsertedcallbackdisabled. 
00249     browserexpandvisit now calls opstart/endinternalchange to handle this.
00250     */
00251         
00252     tyexpandinfo expandinfo;
00253     tybrowserinfo newfileinfo;
00254     bigstring fname;
00255     boolean fl;
00256     
00257     claygetfileinfo (fsnew, &newfileinfo);
00258 
00259     claygetfilename (fsnew, fname);
00260     
00261     expandinfo.hparent = hnodeparent;
00262 
00263     expandinfo.ctlevels = 1;
00264     
00265     expandinfo.flsortnodes = true;
00266     
00267     expandinfo.flsettmpbits = false;
00268     
00269     /*
00270     lineinsertedcallbackdisabled = true;
00271     */
00272     
00273     fl = browserexpandvisit (fname, &newfileinfo, (long) &expandinfo);
00274     
00275     /*
00276     lineinsertedcallbackdisabled = false;
00277     */
00278     
00279     if (!fl)
00280         return (false);
00281     
00282     opexpandupdate (expandinfo.hnewnode);
00283         
00284     *hnew = expandinfo.hnewnode;
00285     
00286     return (fl);
00287     } /*browserfileadded*/
00288 
00289 
00290 #if 0
00291 
00292 static boolean browsernodeislocked (hdlheadrecord hnode) {
00293     
00294     tybrowserinfo info;
00295     
00296     browsergetrefcon (hnode, &info);
00297     
00298     #if filebrowser
00299         if (info.flnamelocked || info.fllocked)
00300             return (false);
00301             
00302         while (opchaseleft (&hnode)) {}; /*get out to volume node*/
00303         
00304         browsergetrefcon (hnode, &info);
00305         
00306         if (info.fllocked || info.flhardwarelock)
00307             return (false);
00308     #endif
00309     
00310     return (true);
00311     } /*browsernodeislocked*/
00312 
00313 
00314 static boolean browserpostpaste (hdlheadrecord hfirstpasted) {
00315     
00316     browsersortfolder ((**hfirstpasted).headlinkleft);
00317     
00318     return (true);
00319     } /*browserpostpaste*/
00320 
00321 #endif
00322 
00323 
00324 static boolean foldercontainsfile (tybrowserspec *fsfolder, tybrowserspec *fsfile) {
00325     
00326     tybrowserdir dirid;
00327     
00328     if ((*fsfolder).vRefNum != (*fsfile).vRefNum)
00329         return (false);
00330         
00331     claygetdirid (fsfolder, &dirid);
00332     
00333     if ((*fsfile).parID == dirid)
00334         return (true);
00335         
00336     return (false);
00337     } /*foldercontainsfile*/
00338 
00339 
00340 static boolean claygetuniquefilename (tybrowserspec *fs, short *suffixnum) {
00341     
00342     /*
00343     5.0b9 dmb: we now expect suffixnum to have a meaningingful initial value.
00344     
00345     if it's non-zero, and the headstring ends in that suffix, remove the 
00346     existing suffix before comparing
00347     */
00348 
00349     bigstring origname, name;
00351     //This isn't used
00352     //boolean flfolder;
00353     boolean flmustsuffixize = false;
00354     
00355     filepopsuffixnumber (*suffixnum, (*fs).name);
00356     
00357     copystring ((*fs).name, origname);
00358     
00359     *suffixnum = 0;
00360     
00361     if (isemptystring (origname)) {
00362         #if filebrowser
00363             return (false);
00364         #else
00365             copystring (BIGSTRING ("\x04" "item"), origname);
00366             flmustsuffixize = true;
00367         #endif
00368         }
00369         
00370     while (flmustsuffixize || clayfileexists (fs, &flfolder)) {
00371     
00372         flmustsuffixize = false; // reset
00373         
00374         copystring (origname, name);
00375         
00376         (*suffixnum)++;
00377         
00378         filepushsuffixnumber (*suffixnum, name);
00379         
00380         if (!claymakespec ((*fs).vRefNum, (*fs).parID, name, fs))
00381             return (false);
00382         } /*while*/
00383     
00384     return (true);
00385     } /*claygetuniquefilename*/
00386 
00387 
00388 static tybrowserspec undofolderspec;
00389 
00390 static tybrowserspec clipfolderspec;
00391 
00392 /*
00393 boolean lineinsertedcallbackdisabled = false;
00394 */
00395 
00396 static hdlheadrecord hdeletednode = nil; /*last node deleted (unlinked) -- may yet be re-inserted*/
00397 
00398 
00399 static boolean getundofolderspec (void) {
00400     
00401     static boolean folderfound = false;
00402 
00403     if (folderfound)
00404         return (true);
00405     
00406     folderfound = claygetspecialfolder (BIGSTRING ("\x04" "Undo"), true, &undofolderspec);
00407     
00408     return (folderfound);
00409     } /*getundofolderspec*/
00410     
00411     
00412 static boolean getclipfolderspec (void) {
00413     
00414     static boolean folderfound = false;
00415 
00416     if (folderfound)
00417         return (true);
00418     
00419     folderfound = claygetspecialfolder (BIGSTRING ("\x09" "Clipboard"), true, &clipfolderspec);
00420     
00421     return (folderfound);
00422     } /*getclipfolderspec*/
00423 
00424 
00425 boolean browserclearundo (void) {
00426     
00427     getundofolderspec ();
00428     
00429     return (clayemptyfilefolder (&undofolderspec));
00430     } /*browserclearundo*/
00431 
00432 
00433 static boolean deletetmpbitvisit (hdlheadrecord hnode, ptrvoid refcon) {
00434 #pragma unused (refcon)
00435 
00436     if ((**hnode).tmpbit) {
00437         
00438         (**hnode).tmpbit = false;
00439         
00440         opdeletenode (hnode);
00441         
00442         browsercommitchanges (); /*moves the file into the undo folder*/
00443         }
00444     
00445     return (true); /*keep visiting*/
00446     } /*deletetmpbitvisit*/
00447     
00448     
00449 boolean browserdeletenodeswithtmpbitset (void) {
00450     
00451     /*
00452     delete files with their tmp bits turned on
00453     */
00454 
00455     return (opsiblingvisiter ((**outlinedata).hsummit, true, &deletetmpbitvisit, nil)); 
00456     } /*browserdeletenodeswithtmpbitset*/
00457 
00458 
00459 /*
00460 static boolean browsercreatefile (hdlheadrecord hnode, tybrowserspec *fsfolder) {
00461     
00462     bigstring bs;
00463     tybrowserspec fsdest;
00464     
00465     opgetheadstring (hnode, bs);
00466     
00467     claygetsubitemspec (fsfolder, bs, &fsdest);
00468     
00469     if (claycreatefile (&fsdest)) {
00470     
00471     /%update the node's refcon to reflect the new file's position & attributes%/
00472         
00473         tybrowserinfo browserinfo;
00474         
00475         claygetfileinfo (&fsdest, &browserinfo);
00476         
00477         browsersetrefcon (hnode, &browserinfo);
00478         }
00479     
00480     return (true);
00481     } /%browsercreatefile%/
00482 */
00483 
00484 static boolean browsermoveto (hdlheadrecord hnode, tybrowserspec *fsfolder) {
00485     
00486     /*
00487     move or copy the file or folder connected to hnode to the 
00488     indicated folder.
00489     
00490     if a file with that name already exists, append a suffix
00491     to the name.
00492     
00493     the "flnodeonscrap" attribute of a node indicates whether or
00494     not it owns the file described by the refcon. it can be false
00495     when a node is on the outline scrap, for example.
00496     
00497     dmb 9/20/93: 1) since undo & clip folders are always on sys volume now, we 
00498     can't assume vRefNum of source & dest are the same; 2) fixed suffixnum 
00499     updating; was assigning to info instead of browserinfo; 3) fsdest must not 
00500     take suffixnum into account. suffixnum is essential for determining fssource 
00501     from the node, but the dest should correspond to the headline name.
00502 
00503     5.0b13 dmb: with the new meaning of suffixnum -- that the node/value name 
00504     has been modified to be unique in it's new location -- we shouldn't consider 
00505     and intially-unique name like "item #1" to be suffixized
00506     
00507     5.0.2b20 dmb: don't do copy/delete if source or dest vnum is zero
00508     
00509     5.1.4 dmb: don't ignore return value of claygetsubitemspec
00510     */
00511     
00512     tybrowserspec fssource, fsdest;
00513     tybrowserinfo info;
00514     short suffixnum;
00515     bigstring bs;
00516     boolean flsourceexists;
00517     
00518     flsourceexists = claygetfilespec (hnode, &fssource);
00519     
00520     if (flsourceexists) { // hnode is associated with a file
00521         
00522         if (foldercontainsfile (fsfolder, &fssource)) // already in the folder*/
00523             return (true);
00524         }
00525     
00526     opgetheadstring (hnode, bs);
00527     
00528     if (!claygetsubitemspec (fsfolder, bs, &fsdest))
00529         return (false);
00530     
00531     if (!browsergetrefcon (hnode, &info)) // 5.0b9 dmb
00532         info.suffixnum = 0;
00533     
00534     suffixnum = info.suffixnum;
00535     
00536     claygetuniquefilename (&fsdest, &suffixnum);
00537     
00538     if (!flsourceexists) {
00539         
00540         if (!claycreatefile (&fsdest))
00541             return (false);
00542         }
00543     else {
00544         if (!(**hnode).flnodeonscrap) { /*we own this file -- move it*/
00545             
00546             if (((fssource.vRefNum == fsdest.vRefNum) || (fssource.vRefNum == 0) || (fsdest.vRefNum == 0)) && equalidentifiers (fssource.name, fsdest.name)) {
00547                 
00548                 if (!claymovefile (&fssource, fsfolder))
00549                     return (false);
00550                 }
00551             else { 
00552                 
00553                 if (!claycopyfile (&fssource, &fsdest))
00554                     return (false);
00555                 
00556                 claydeletefile (&fssource);
00557                 }
00558             }
00559         else { /*file not owned -- make a copy*/
00560             
00561             if (!claycopyfile (&fssource, &fsdest))
00562                 return (false);
00563             }
00564         }
00565     
00566     /*update the node's refcon to reflect the new file's position & attributes*/ {
00567         
00568         tybrowserinfo browserinfo;
00569         
00570         claygetfileinfo (&fsdest, &browserinfo);
00571     
00572     #if filebrowser
00573         browserinfo.suffixnum = suffixnum;
00574     #else
00575         browserinfo.suffixnum = suffixnum; // dmb 5.0b9: new
00576 
00577         if (suffixnum != info.suffixnum) { // suffix was added or removed
00578             
00579             opstartinternalchange ();
00580             
00581             opsetactualheadstring (hnode, fsdest.name);
00582             
00583             opendinternalchange ();
00584             }
00585     #endif
00586         if (!flsourceexists && isemptystring (bs)) { // a new insertion
00587             
00588             (**hnode).tmpbit2 = true;
00589             
00590             langexternaldontsave (fsdest.parID, fsdest.name); // 5.1.4
00591             
00592             browserinfo.suffixnum = 0; // we made up the name, it's real w/whatever suffix
00593             }
00594         
00595         browsersetrefcon (hnode, &browserinfo);
00596         }
00597     
00598     (**hnode).flnodeonscrap = false;
00599     
00600     return (true);
00601     } /*browsermoveto*/
00602 
00603 
00604 boolean browsergetparentspec (hdlheadrecord hnode, tybrowserspec *fsparent) {
00605     
00606     /*
00607     5.13.97 dmb: fixed summit (root table) case
00608 
00609     5.0.2b21 dmb: use new shellgetdatabase to get parent of summit
00610     */
00611 
00612     hdlheadrecord hparent = (**hnode).headlinkleft;
00613     hdltableformats hformats;
00614     
00615     if (hparent == hnode) { // it's a summit
00616         
00617         hformats = (hdltableformats) (**outlinedata).outlinerefcon;
00618         
00619         shellgetdatabase (shellwindow, &(*fsparent).vRefNum); // was: databasedata; what about GDBs?
00620 
00621         (*fsparent).parID = (**hformats).htable; // 5.0d18 dmb: this is as clean as it gets for now
00622         
00623         setemptystring ((*fsparent).name);
00624 
00625         return (true);
00626         }
00627     
00628     return (claygetfilespec (hparent, fsparent));
00629     } /*browsergetparentspec*/
00630 
00631 
00632 static boolean safedragvisit (hdlheadrecord hnode, ptrvoid punsafe) {
00633     
00634     if ((**hnode).tmpbit) {
00635         
00636         opgetheadstring (hnode, punsafe);
00637         
00638         return (false);
00639         }
00640     
00641     return (true);
00642     } /*safedragvisit*/
00643 
00644 
00645 boolean browserpredrag (hdlheadrecord *htarget, tydirection *dragdir) {
00646     
00647     /*
00648     the user dragged the selection to the indicated destination. it's our
00649     job to interpret the move, and return true only if the caller should 
00650     move (or copy) the selection to the destination.
00651     
00652     if files are being dragged into a folder, we must first delete any name
00653     conflicts, with confirmation.
00654     
00655     if files are being dragged into an application, we do the launch and 
00656     return false; no move it to take place
00657     
00658     9/22/93 dmb: dragging move can give us a dir of up; handle it.
00659     
00660     5.0.2b18 dmb: if a marked headline comes back with its tmpbit set, then
00661     the move is trying to replace its ancestor -- don't let it!
00662     */
00663     
00664     tybrowserinfo info;
00665     hdlheadrecord hpre = *htarget;
00666     tydirection dir = *dragdir;
00667     bigstring bsunsafe, bsmsg;
00668     
00669     if (dir == right) {
00670         
00671         browsergetrefcon (hpre, &info);
00672         
00673         if (!info.flfolder)
00674             return (false);
00675         }
00676     
00677     if (!browservalidatemove (hpre, nil, dir))
00678         return (false);
00679     
00680     if (!opvisitmarked (down, safedragvisit, bsunsafe)) {
00681         
00682         opcleartmpbits ();
00683         
00684         #ifdef MACVERSION
00685             parsedialogstring (BIGSTRING ("\x3b" "Can’t move “^0” here because it would replace its ancestor."), bsunsafe, nil, nil, nil, bsmsg);
00686         #else
00687             parsedialogstring (BIGSTRING ("\x3b" "Can't move \"^0\" here because it would replace its ancestor."), bsunsafe, nil, nil, nil, bsmsg);
00688         #endif
00689         
00690         alertdialog (bsmsg);
00691         
00692         return (false);
00693         }
00694     
00695     if ((**hpre).tmpbit) { //work hard to find a safe target
00696         
00697         assert (dir == down);
00698         
00699         while ((**hpre).tmpbit) {  // look above us
00700             
00701             if (!opchaseup (&hpre))
00702                 break;
00703             }
00704         
00705         if ((**hpre).tmpbit) { // reset and look below
00706             
00707             hpre = *htarget;
00708             
00709             *dragdir = up;
00710             
00711             while ((**hpre).tmpbit) {
00712                 
00713                 if (!opchasedown (&hpre))
00714                     break;
00715                 }
00716             }
00717         
00718         if ((**hpre).tmpbit) { //go to our parent
00719             
00720             opchaseleft (&hpre);
00721 
00722             *dragdir = right;
00723             }
00724         }
00725     
00726     *htarget = hpre;
00727     
00728     browserdeletenodeswithtmpbitset ();
00729     
00730     return (true); /*go ahead with the move*/
00731     
00732     #if filebrowser
00733     
00734     if (info.filetype == 'APPL') { /*need to see if app handles file type*/
00735         
00736         tybrowserspec fapp, fdoc;
00737         
00738         claygetfilespec (htarget, &fapp);
00739         
00740         claygetfilespec ((**outlinedata).hbarcursor, &fdoc);
00741         
00742         claylaunchappwithdoc (&fapp, &fdoc, true);
00743         }
00744     
00745     #endif
00746     
00747     } /*browserpredrag*/
00748 
00749 
00750 boolean browserdragcopy (hdlheadrecord hmove, hdlheadrecord hdest) {
00751     
00752     /*
00753     we're moving hmove down or to the right of hdest. if they're 
00754     not both from the same volume, we need to move a copy, not the 
00755     original.
00756     */
00757     
00758     tybrowserspec fs1, fs2;
00759     
00760     claygetfilespec (hmove, &fs1);
00761     
00762     claygetfilespec (hdest, &fs2);
00763      
00764     if (fs1.vRefNum != fs2.vRefNum) /*must copy if it's cross-volumes*/
00765         return (true);
00766         
00767     if (keyboardstatus.floptionkey || optionkeydown ()) {
00768         
00769         bigstring bs;
00770         
00771         copystring (BIGSTRING ("\x20" "Copy or move the selected items?"), bs);
00772         
00773     //  return (twowaydialog (bs, "\x04" "Copy", "\x04" "Move"));
00774         return (msgdialog (bs));
00775         }
00776         
00777     return (false);
00778     } /*browserdragcopy*/
00779 
00780 
00781 void browsersortfolder (hdlheadrecord hnode) {
00782     
00783     /*
00784     hnode is a folder whose sort order has changed. unlink all its
00785     subnodes and reinsert them into the list sorted according to the
00786     new order.
00787     */
00788     
00789     hdlheadrecord nomad = (**hnode).headlinkright, nextnomad;
00790     tybrowserinfo browserinfo;
00791     bigstring bs;
00792     hdlheadrecord hpre;
00793     tydirection dir;
00794     hdlscreenmap hmap;
00795     
00796     if (nomad == hnode) /*no subs expanded, nothing to do*/
00797         return;
00798         
00799     (**hnode).headlinkright = hnode; /*no longer has any kids*/
00800     
00801     initbeachball (right);
00802     
00803     /*opupdatenow ();*/
00804     
00805     opstartinternalchange (); /*this operation is not undo-able*/
00806     
00807     opnewscreenmap (&hmap);
00808     
00809     while (true) {
00810         
00811         nextnomad = (**nomad).headlinkdown;
00812         
00813         browsergetrefcon (nomad, &browserinfo);
00814         
00815         opgetheadstring (nomad, bs);
00816         
00817         browserfindinsertionpoint (hnode, bs, &browserinfo, &hpre, &dir);
00818         
00819         opdeposit (hpre, dir, nomad);
00820         
00821         if (nextnomad == nomad)
00822             break;
00823             
00824         nomad = nextnomad;
00825         
00826         rollbeachball ();
00827         } /*while*/
00828         
00829     opinvalscreenmap (hmap);
00830         
00831     opendinternalchange ();
00832     
00833     opsetctexpanded (outlinedata);
00834     
00835     opsetscrollpositiontoline1 ();
00836     
00837     #ifdef fldebug
00838         opvalidate (outlinedata);
00839     #endif
00840     } /*browsersortfolder*/
00841 
00842 
00843 void browserinsertagain (hdlheadrecord hnode) {
00844     
00845     /*
00846     the node's text or other info has been changed, it might sort
00847     to a different place in its parent folder's list. we unlink it
00848     from the structure, and link it back in where it belongs.
00849     
00850     9/24/93 dmb: don't want an undo built for this operation, since 
00851     it's a passive reordering going on here.
00852     
00853     5.0d14 dmb: do nothing when hnode is the only node at its level.
00854     particularly imporant when hnode is an only summit.
00855     */
00856     
00857     hdlheadrecord hparent;
00858     bigstring bs;
00859     tybrowserinfo browserinfo;
00860     hdlheadrecord hpre;
00861     tydirection dir;
00862     hdlscreenmap hmap;
00863     
00864     if (opcountatlevel (hnode) == 1) /*has no siblings, can't change order*/
00865         return;
00866     
00867     hparent = (**hnode).headlinkleft;
00868     
00869     if (hparent == hnode) /*it's a top-level node*/ 
00870         hparent = nil;
00871     
00872     opstartinternalchange (); /*don't want this to trigger callbacks or add to undo stack*/
00873     
00874     opgetheadstring (hnode, bs);
00875     
00876     opnewscreenmap (&hmap);
00877     
00878     opunlink (hnode);
00879     
00880     browsergetrefcon (hnode, &browserinfo);
00881     
00882     browserfindinsertionpoint (hparent, bs, &browserinfo, &hpre, &dir);
00883     
00884     opdeposit (hpre, dir, hnode);
00885     
00886     (**outlinedata).hbarcursor = hnode;
00887     
00888 // 2/20/97 dmb: shouldn't need this:    opsetctexpanded ();
00889     
00890     opinvalscreenmap (hmap);
00891     
00892     opendinternalchange ();
00893     } /*browserinsertagain*/
00894     
00895     
00896 boolean browsercopyrefcon (hdlheadrecord hsource, hdlheadrecord hdest) {
00897     
00898     /*
00899     called while processing the Edit/Copy command. we copy the refcon
00900     handle, but set the flnodeonscrap bit true, making this a reference 
00901     to the file. if this node gets deleted we don't delete the file.
00902     */
00903 
00904     if (!opcopyrefconroutine (hsource, hdest))
00905         return (false);
00906     
00907     (**hdest).flnodeonscrap = true; /*we don't own the file*/
00908     
00909     return (true);
00910     } /*browsercopyrefcon*/
00911 
00912 
00913 static boolean browsergetnodevalue (hdlheadrecord hnode, tyvaluerecord *val) {
00914     
00915     tybrowserspec fs;
00916     hdlhashnode hhashnode;
00917     
00918     if (!claygetfilespec (hnode, &fs))
00919         return (false);
00920 
00921     return (claylookupvalue (&fs, val, &hhashnode));
00922     } /*browsergetnodevalue*/
00923 
00924 
00925 boolean browsertextualizerefcon (hdlheadrecord hnode, Handle htext) {
00926 #pragma unused (htext)
00927 
00928     tyvaluerecord val;
00929 
00930     if (!browsergetnodevalue (hnode, &val))
00931         return (false);
00932     
00933 
00934     return (true);
00935     } /*browsertextualizerefcon*/
00936 
00937 
00938 boolean browserreleaserefcon (hdlheadrecord hnode, boolean fldisk) {
00939     
00940     /*
00941     the node is going away. if we own the file we must delete it. this is how
00942     files get deleted from the Undo folder.
00943     
00944     flinternalchange is true, for example, when you collapse a folder. the
00945     nodes are deleted, but the files must not be.
00946     */
00947     
00948     if (!opinternalchange () && fldisk && (!(**hnode).flnodeonscrap)) { 
00949         
00950         tybrowserspec fs;
00951 
00952         claygetfilespec (hnode, &fs);
00953         
00954         claydeletefile (&fs); 
00955         }
00956     
00957     if (hnode == hdeletednode)
00958         hdeletednode = nil;
00959     
00960     return (true);
00961     } /*browserreleaserefcon*/
00962     
00963     
00964 static boolean lineinsertvisit (hdlheadrecord hnode, ptrvoid refcon) {
00965 #pragma unused (refcon)
00966 
00967     /*
00968     set the node's refcon info to reflect its current position in
00969     the outline hierarchy.
00970     */
00971     
00972     tybrowserinfo info;
00973     tybrowserspec fsparent;
00974     
00975     browsergetparentspec (hnode, &fsparent);
00976     
00977     if (browsergetrefcon (hnode, &info)) {
00978         
00979         info.vnum = fsparent.vRefNum;
00980         
00981         claygetdirid (&fsparent, &info.dirid);
00982         
00983         browsersetrefcon (hnode, &info);
00984         }
00985     
00986     (**hnode).flnodeonscrap = false;
00987     
00988     return (true);
00989     } /*lineinsertvisit*/
00990 
00991 
00992 boolean browserlineinserted (hdlheadrecord hnode) {
00993     
00994     /*
00995     dmb 9/23/93: no more lineinsertedcallbackdisabled flag. there's an 
00996     op mechanism for this, opstart/endinternalchange, that also turns 
00997     off undo (very important!)
00998     */
00999     
01000     tybrowserspec fsparent;
01001     
01002     /*
01003     if (lineinsertedcallbackdisabled)
01004         return (true);
01005     */
01006     
01007     if (hnode == hdeletednode) /*finishing a move operation*/
01008         hdeletednode = nil;
01009     else
01010         browsercommitchanges ();
01011     
01012     /*
01013     if ((**hnode).flnewlyinsertednode)
01014         browsercreatefile (hnode, &fsparent);
01015     
01016     else*/ {
01017         
01018         browsergetparentspec (hnode, &fsparent);
01019         
01020         if (!browsermoveto (hnode, &fsparent))
01021             return (false);
01022         }
01023     
01024     oprecursivelyvisit (hnode, infinity, &lineinsertvisit, nil); 
01025     
01026     return (true);
01027     } /*browserlineinserted*/
01028 
01029 
01030 boolean browserlinedeleted (hdlheadrecord hnode) {
01031     
01032     browsercommitchanges (); /*flush previous deletion*/
01033     
01034     hdeletednode = hnode;
01035     
01036     return (true);
01037     } /*browserlinedeleted*/
01038 
01039 
01040 static boolean notownrefconvisit (hdlheadrecord hnode, ptrvoid refcon) {
01041 #pragma unused (refcon)
01042 
01043     (**hnode).flnodeonscrap = true;
01044     
01045     return (true);
01046     } /*notownrefconvisit*/
01047 
01048 
01049 static boolean closeownedwindowsvisit (hdlhashnode hn, ptrvoid refcon) {
01050 #pragma unused (refcon)
01051 
01052     tyvaluerecord val = (**hn).val;
01053     hdlexternalvariable hv;
01054     hdlwindowinfo hinfo;
01055     
01056     if (val.valuetype != externalvaluetype)
01057         return (true);
01058     
01059     if (langexternalwindowopen (val, &hinfo)) {
01060         
01061         flinhibitclosedialogs = true;
01062         
01063         shellclosewindow ((**hinfo).macwindow);
01064         
01065         flinhibitclosedialogs = false;
01066         }
01067     
01068     hv = (hdlexternalvariable) val.data.externalvalue;
01069     
01070     if (istablevariable (hv) && (**hv).flinmemory) {
01071         
01072         return (hashtablevisit ((hdlhashtable) (**hv).variabledata, closeownedwindowsvisit, nil));
01073         }
01074     
01075     return (true);
01076     } /*closeownedwindowsvisit*/
01077 
01078 
01079 static boolean closeownedwindows (hdlheadrecord hnode) {
01080     
01081     /*
01082     hnode has been deleted, but with undo. so the external value nodes 
01083     aren't being disposed to trigger window closing. tablesymboldeleted 
01084     could theoretically take care of this, but traversing the outline is 
01085     easier & faster. in fact, tablesymboldeleted can't do it, because the
01086     node is already unlinked. it would have to be the symbolunlinking 
01087     callback, with an additional parameter (fldisposing), newly-hooked by
01088     tableexternal.c
01089     */
01090     
01091     tybrowserspec fs;
01092     hdlhashnode hn;
01093     
01094     if (!claygetfilespec (hnode, &fs))
01095         return (false);
01096     
01097     if (!hashtablelookupnode (fs.parID, fs.name, &hn))
01098         return (false);
01099     
01100     return (closeownedwindowsvisit (hn, nil));
01101     } /*notownrefconvisit*/
01102 
01103 
01104 boolean browsercommitchanges (void) {
01105     
01106     boolean fl;
01107     
01108     if (hdeletednode == nil)
01109         return (true);
01110         
01111     getundofolderspec (); 
01112     
01113     closeownedwindows (hdeletednode); 
01114     
01115     fl = browsermoveto (hdeletednode, &undofolderspec);
01116     
01117     oprecursivelyvisit (hdeletednode, infinity, &notownrefconvisit, nil); 
01118     
01119     hdeletednode = nil;
01120     
01121     return (fl);
01122     } /*browsercommitchanges*/
01123 
01124 
01125 #if 0
01126 
01127 static boolean xxxbrowserexportscrap (hdloutlinerecord hscrap) {
01128     
01129     hdlheadrecord nomad = (**hscrap).hsummit;
01130     
01131     if (!getclipfolderspec ())
01132         return (false);
01133         
01134     while (true) {
01135         
01136         if (!browsermoveto (nomad, &clipfolderspec))
01137             return (false);
01138         
01139         oprecursivelyvisit (nomad, infinity, &notownrefconvisit, nil);
01140         
01141         if (!opchasedown (&nomad))
01142             return (true);
01143         } /*while*/
01144     } /*browserexportscrap*/
01145 
01146 #endif
01147 
01148 
01149 static void tabledisposescrap (hdloutlinerecord houtline) {
01150     
01151     opdisposeoutline (houtline, false);
01152     } /*tabledisposescrap*/
01153 
01154 
01155 static boolean tableexportscrap (hdloutlinerecord houtline, tyscraptype totype, Handle *hexport, boolean *fltempscrap) {
01156     
01157     /*
01158     5.0b9 dmb: for single headline table selection, use 4.x value exporting 
01159     */
01160     
01161     hdlheadrecord hsummit = (**houtline).hsummit;
01162 
01163     *fltempscrap = true; /*usually the case*/
01164     
01165     if ((totype != hashscraptype) && opcountatlevel (hsummit) == 1) { // converting single-selection, use 4.x code
01166         
01167         tyvaluerecord val;
01168         
01169         if (!browsergetnodevalue (hsummit, &val))
01170             return (false);
01171 
01172         return (tableexportscrapvalue (&val, totype, hexport, fltempscrap));
01173         }
01174 
01175     switch (totype) {
01176         
01177         case hashscraptype: /*export flat version for system scrap*/
01178             return (oppackoutline (houtline, hexport));
01179         
01180         case opscraptype:
01181         case scriptscraptype:
01182             *hexport = (Handle) houtline; /*op and script scraps are the same*/
01183             
01184             *fltempscrap = false; /*it's the original, not a copy*/
01185             
01186             return (true);
01187         
01188         case textscraptype:
01189             return (opoutlinetonewtextscrap (houtline, hexport));
01190             
01191         default:
01192             return (false);
01193         }
01194     } /*tableexportscrap*/
01195 
01196 
01197 boolean browsersetscrap (hdloutlinerecord houtline) {
01198     
01199     /*
01200     5.0d5 dmb: move to scrap folder here, before setting shell scrap
01201     */
01202     
01203     hdlheadrecord nomad = (**houtline).hsummit;
01204     hdlhashtable cliptable;
01205     
01206     if (!getclipfolderspec ())
01207         return (false);
01208     
01209     if (!claygetdirid (&clipfolderspec, &cliptable))
01210         return (false);
01211     
01212     emptyhashtable (cliptable, false);
01213     
01214     while (true) {
01215         
01216         if (!browsermoveto (nomad, &clipfolderspec))
01217             return (false);
01218         
01219         oprecursivelyvisit (nomad, infinity, &notownrefconvisit, nil);
01220         
01221         if (!opchasedown (&nomad))
01222             break;
01223         } /*while*/
01224     
01225     return (shellsetscrap ((Handle) houtline, hashscraptype,
01226                 (shelldisposescrapcallback) &tabledisposescrap,
01227                 (shellexportscrapcallback) &tableexportscrap));
01228     } /*browsersetscrap*/
01229 
01230 
01231 boolean browsergetscrap (hdloutlinerecord *houtline, boolean *fltempscrap) {
01232     
01233     Handle hscrap;
01234     tyscraptype scraptype;
01235     
01236     if (!shellgetscrap (&hscrap, &scraptype))
01237         return (false);
01238     
01239     if (scraptype == hashscraptype) {
01240         
01241         *houtline = (hdloutlinerecord) hscrap;
01242         
01243         *fltempscrap = false; /*we're returning a handle to the actual scrap*/
01244         
01245         return (true);
01246         }
01247     
01248     return (false);
01249     } /*browsergetscrap*/
01250 
01251 
01252 boolean browserdeletedummyvalues (hdlheadrecord hnode) {
01253 
01254     /*
01255     hnode is no longer being displayed in its window.
01256     
01257     if it or any of its siblings is an auto-created node, toss the corresponding 
01258     table node
01259     
01260     return true if no errors occur
01261     */
01262     
01263     tybrowserspec fs;
01264     tyvaluerecord val;
01265     hdlhashnode hhashnode;
01266     
01267     while (true) {
01268     
01269         if ((**hnode).tmpbit2) {
01270             
01271             if (claygetfilespec (hnode, &fs) && claylookupvalue (&fs, &val, &hhashnode)) {
01272             
01273                 if (val.valuetype == novaluetype)
01274                     if (!hashtabledelete (fs.parID, fs.name))
01275                         return (false);
01276                 }
01277             }
01278         
01279         if (!opchasedown (&hnode))
01280             return (true);
01281         }
01282     } /*browserdeletedummyvalues*/
01283 
01284 

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