Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: claybrowserstruc.c,v 1.4 2005/01/11 22:48:04 andreradke Exp $ */
3
4 /******************************************************************************
5
6 UserLand Frontier(tm) -- High performance Web content management,
7 object database, system-level and Internet scripting environment,
8 including source code editing and debugging.
9
10 Copyright (C) 1992-2004 UserLand Software, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 ******************************************************************************/
27
28 #include "frontier.h"
29 #include "standard.h"
30
31 #include "cursor.h"
32 #include "dialogs.h"
33 #include "error.h"
34 #include "file.h"
35 #include "fileloop.h"
36 #include "kb.h"
37 #include "memory.h"
38 #include "ops.h"
39 #include "quickdraw.h"
40 #include "process.h"
41 #include "scrap.h"
42 #include "strings.h"
43 #include "opinternal.h"
44 #include "oplineheight.h"
45 #include "claybrowser.h"
46 #include "claycallbacks.h"
47 #include "claybrowserexpand.h"
48 #include "claybrowservalidate.h"
49 #include "claybrowserstruc.h"
50 #if odbbrowser
51 #include "shell.rsrc.h"
52 #include "shellundo.h"
53 #include "tableinternal.h"
54 #include "tableverbs.h"
55 #include "wpengine.h"
56 #endif
57
58
59
60
61 boolean browsergetrefcon (hdlheadrecord hnode, tybrowserinfo *info) {
62
63 return (opgetrefcon (hnode, info, sizeof (tybrowserinfo)));
64 } /*browsergetrefcon*/
65
66
67 boolean browsersetrefcon (hdlheadrecord hnode, tybrowserinfo *info) {
68
69 return (opsetrefcon (hnode, info, sizeof (tybrowserinfo)));
70 } /*browsersetrefcon*/
71
72
73 boolean browsercopyfileinfo (hdlheadrecord hnode, tybrowserinfo *fileinfo) {
74
75 /*
76 set the fields of a browser refcon handle that come from
77 a file's fileinfo record. ignore the other fields.
78 */
79
80 // tybrowserinfo browserinfo;
81
82 // browsergetrefcon (hnode, &browserinfo);
83
84 if (!browsersetrefcon (hnode, fileinfo))
85 return (false);
86
87 return (true);
88 } /*browsercopyfileinfo*/
89
90
91 static void filepushsuffixnumber (short suffixnum, bigstring name) {
92
93 if (suffixnum > 0) {
94
95 pushstring ("\x02" " #", name);
96
97 pushint (suffixnum, name);
98 }
99 } /*filepushsuffixnumber*/
100
101
102 static void filepopsuffixnumber (short suffixnum, bigstring name) {
103
104 byte bssuffix [32];
105 short ixsuffix;
106
107 if (suffixnum > 0) {
108
109 copystring ("\x02" " #", bssuffix);
110
111 pushint (suffixnum, bssuffix);
112
113 ixsuffix = patternmatch (bssuffix, name) - 1;
114
115 if (ixsuffix == stringlength (name) - stringlength (bssuffix))
116 setstringlength (name, ixsuffix);
117 }
118 } /*filepushsuffixnumber*/
119
120
121 boolean claygetfilespec (hdlheadrecord hnode, tybrowserspec *fs) {
122
123 /*
124 turn a headrecord into a filespec.
125
126 6/27/93 DW: per recommendation of Think Reference, if it's a
127 volume, just set the vRefNum field of the filespec.
128
129 8/30/93 DW: rewrite.
130
131 9/21/93 dmb: don't need special case for volumes anymore. Think Ref's
132 recommendation is fine for specifying volumes, but it's event better
133 to specify the root directory of the volume, removing any special cases.
134
135 5.1.4 dmb: on failure, clear fs
136 */
137
138 tybrowserinfo info;
139 bigstring name;
140
141 if (!browsergetrefcon (hnode, &info)) {
142
143 clearbytes (fs, sizeof (tybrowserspec));
144
145 return (false);
146 }
147
148 /*
149 if (info.flvolume) { /%special case%/
150
151 (*fs).vRefNum = info.vnum;
152
153 (*fs).parID = 0;
154
155 setstringlength ((*fs).name, 0);
156
157 return (true);
158 }
159 */
160
161 opgetheadstring (hnode, name);
162
163 // dmb 5.0b9 - was: filepushsuffixnumber (info.suffixnum, name);
164
165 return (claymakespec (info.vnum, info.dirid, name, fs));
166 } /*claygetfilespec*/
167
168
169 boolean browserloadnode (hdlheadrecord hnode) {
170
171 tybrowserspec fs;
172 tybrowserinfo fileinfo;
173
174 (**hnode).fldirty = true; /*force update to reflect new info*/
175
176 claygetfilespec (hnode, &fs);
177
178 if (!claygetfileinfo (&fs, &fileinfo))
179 return (false);
180
181 (**hnode).flnodeisfolder = fileinfo.flfolder;
182
183 return (browsercopyfileinfo (hnode, &fileinfo));
184 } /*browserloadnode*/
185
186
187 boolean browserchecklinelength (short newlen, bigstring bs) {
188
189 bigstring bsalert;
190
191 if (newlen <= (short) (**outlinedata).maxlinelen)
192 return (true);
193
194 copystring ("\x0e" "The file name ", bsalert);
195
196 if (stringlength (bs) > 0) {
197
198 pushstring ("\x01" "Ò", bsalert);
199
200 pushstring (bs, bsalert);
201
202 pushstring ("\x01" "Ó", bsalert);
203 }
204
205 pushstring ("\x2e" " is too long. The maximum file name length is ", bsalert);
206
207 pushlong ((**outlinedata).maxlinelen, bsalert);
208
209 pushstring ("\x0c" " characters.", bsalert);
210
211 alertdialog (bsalert);
212
213 return (false);
214 } /*browserchecklinelength*/
215
216 #if 0
217
218 static boolean browserupdatefileinfo (hdlheadrecord hnode) {
219
220 /*
221 change the in-memory info to reflect what's on disk
222 */
223
224 tybrowserspec fs;
225 tybrowserinfo info;
226
227 if (hnode == nil) /*defensive driving*/
228 return (false);
229
230 claygetfilespec (hnode, &fs);
231
232 claygetfileinfo (&fs, &info);
233
234 browsercopyfileinfo (hnode, &info);
235
236 return (true);
237 } /*browserupdatefileinfo*/
238
239 #endif
240
241
242 boolean browserfileadded (hdlheadrecord hnodeparent, const tybrowserspec *fsnew, hdlheadrecord *hnew) {
243
244 /*
245 a new item has been added to a folder, our job is to add the file
246 to the display.
247
248 dmb 9/23/93: removed setting/clearing of lineinsertedcallbackdisabled.
249 browserexpandvisit now calls opstart/endinternalchange to handle this.
250 */
251
252 tyexpandinfo expandinfo;
253 tybrowserinfo newfileinfo;
254 bigstring fname;
255 boolean fl;
256
257 claygetfileinfo (fsnew, &newfileinfo);
258
259 claygetfilename (fsnew, fname);
260
261 expandinfo.hparent = hnodeparent;
262
263 expandinfo.ctlevels = 1;
264
265 expandinfo.flsortnodes = true;
266
267 expandinfo.flsettmpbits = false;
268
269 /*
270 lineinsertedcallbackdisabled = true;
271 */
272
273 fl = browserexpandvisit (fname, &newfileinfo, (long) &expandinfo);
274
275 /*
276 lineinsertedcallbackdisabled = false;
277 */
278
279 if (!fl)
280 return (false);
281
282 opexpandupdate (expandinfo.hnewnode);
283
284 *hnew = expandinfo.hnewnode;
285
286 return (fl);
287 } /*browserfileadded*/
288
289
290 #if 0
291
292 static boolean browsernodeislocked (hdlheadrecord hnode) {
293
294 tybrowserinfo info;
295
296 browsergetrefcon (hnode, &info);
297
298 #if filebrowser
299 if (info.flnamelocked || info.fllocked)
300 return (false);
301
302 while (opchaseleft (&hnode)) {}; /*get out to volume node*/
303
304 browsergetrefcon (hnode, &info);
305
306 if (info.fllocked || info.flhardwarelock)
307 return (false);
308 #endif
309
310 return (true);
311 } /*browsernodeislocked*/
312
313
314 static boolean browserpostpaste (hdlheadrecord hfirstpasted) {
315
316 browsersortfolder ((**hfirstpasted).headlinkleft);
317
318 return (true);
319 } /*browserpostpaste*/
320
321 #endif
322
323
324 static boolean foldercontainsfile (tybrowserspec *fsfolder, tybrowserspec *fsfile) {
325
326 tybrowserdir dirid;
327
328 if ((*fsfolder).vRefNum != (*fsfile).vRefNum)
329 return (false);
330
331 claygetdirid (fsfolder, &dirid);
332
333 if ((*fsfile).parID == dirid)
334 return (true);
335
336 return (false);
337 } /*foldercontainsfile*/
338
339
340 static boolean claygetuniquefilename (tybrowserspec *fs, short *suffixnum) {
341
342 /*
343 5.0b9 dmb: we now expect suffixnum to have a meaningingful initial value.
344
345 if it's non-zero, and the headstring ends in that suffix, remove the
346 existing suffix before comparing
347 */
348
349 bigstring origname, name;
350 ////Code change by Timothy Paustian Sunday, May 7, 2000 8:42:22 PM
351 //This isn't used
352 //boolean flfolder;
353 boolean flmustsuffixize = false;
354
355 filepopsuffixnumber (*suffixnum, (*fs).name);
356
357 copystring ((*fs).name, origname);
358
359 *suffixnum = 0;
360
361 if (isemptystring (origname)) {
362 #if filebrowser
363 return (false);
364 #else
365 copystring ("\x04" "item", origname);
366 flmustsuffixize = true;
367 #endif
368 }
369
370 while (flmustsuffixize || clayfileexists (fs, &flfolder)) {
371
372 flmustsuffixize = false; // reset
373
374 copystring (origname, name);
375
376 (*suffixnum)++;
377
378 filepushsuffixnumber (*suffixnum, name);
379
380 if (!claymakespec ((*fs).vRefNum, (*fs).parID, name, fs))
381 return (false);
382 } /*while*/
383
384 return (true);
385 } /*claygetuniquefilename*/
386
387
388 static tybrowserspec undofolderspec;
389
390 static tybrowserspec clipfolderspec;
391
392 /*
393 boolean lineinsertedcallbackdisabled = false;
394 */
395
396 static hdlheadrecord hdeletednode = nil; /*last node deleted (unlinked) -- may yet be re-inserted*/
397
398
399 static boolean getundofolderspec (void) {
400
401 static boolean folderfound = false;
402
403 if (folderfound)
404 return (true);
405
406 folderfound = claygetspecialfolder ("\x04" "Undo", true, &undofolderspec);
407
408 return (folderfound);
409 } /*getundofolderspec*/
410
411
412 static boolean getclipfolderspec (void) {
413
414 static boolean folderfound = false;
415
416 if (folderfound)
417 return (true);
418
419 folderfound = claygetspecialfolder ("\x09" "Clipboard", true, &clipfolderspec);
420
421 return (folderfound);
422 } /*getclipfolderspec*/
423
424
425 boolean browserclearundo (void) {
426
427 getundofolderspec ();
428
429 return (clayemptyfilefolder (&undofolderspec));
430 } /*browserclearundo*/
431
432
433 static boolean deletetmpbitvisit (hdlheadrecord hnode, ptrvoid refcon) {
434
435 if ((**hnode).tmpbit) {
436
437 (**hnode).tmpbit = false;
438
439 opdeletenode (hnode);
440
441 browsercommitchanges (); /*moves the file into the undo folder*/
442 }
443
444 return (true); /*keep visiting*/
445 } /*deletetmpbitvisit*/
446
447
448 boolean browserdeletenodeswithtmpbitset (void) {
449
450 /*
451 delete files with their tmp bits turned on
452 */
453
454 return (opsiblingvisiter ((**outlinedata).hsummit, true, &deletetmpbitvisit, nil));
455 } /*browserdeletenodeswithtmpbitset*/
456
457
458 /*
459 static boolean browsercreatefile (hdlheadrecord hnode, tybrowserspec *fsfolder) {
460
461 bigstring bs;
462 tybrowserspec fsdest;
463
464 opgetheadstring (hnode, bs);
465
466 claygetsubitemspec (fsfolder, bs, &fsdest);
467
468 if (claycreatefile (&fsdest)) {
469
470 /%update the node's refcon to reflect the new file's position & attributes%/
471
472 tybrowserinfo browserinfo;
473
474 claygetfileinfo (&fsdest, &browserinfo);
475
476 browsersetrefcon (hnode, &browserinfo);
477 }
478
479 return (true);
480 } /%browsercreatefile%/
481 */
482
483 static boolean browsermoveto (hdlheadrecord hnode, tybrowserspec *fsfolder) {
484
485 /*
486 move or copy the file or folder connected to hnode to the
487 indicated folder.
488
489 if a file with that name already exists, append a suffix
490 to the name.
491
492 the "flnodeonscrap" attribute of a node indicates whether or
493 not it owns the file described by the refcon. it can be false
494 when a node is on the outline scrap, for example.
495
496 dmb 9/20/93: 1) since undo & clip folders are always on sys volume now, we
497 can't assume vRefNum of source & dest are the same; 2) fixed suffixnum
498 updating; was assigning to info instead of browserinfo; 3) fsdest must not
499 take suffixnum into account. suffixnum is essential for determining fssource
500 from the node, but the dest should correspond to the headline name.
501
502 5.0b13 dmb: with the new meaning of suffixnum -- that the node/value name
503 has been modified to be unique in it's new location -- we shouldn't consider
504 and intially-unique name like "item #1" to be suffixized
505
506 5.0.2b20 dmb: don't do copy/delete if source or dest vnum is zero
507
508 5.1.4 dmb: don't ignore return value of claygetsubitemspec
509 */
510
511 tybrowserspec fssource, fsdest;
512 tybrowserinfo info;
513 short suffixnum;
514 bigstring bs;
515 boolean flsourceexists;
516
517 flsourceexists = claygetfilespec (hnode, &fssource);
518
519 if (flsourceexists) { // hnode is associated with a file
520
521 if (foldercontainsfile (fsfolder, &fssource)) // already in the folder*/
522 return (true);
523 }
524
525 opgetheadstring (hnode, bs);
526
527 if (!claygetsubitemspec (fsfolder, bs, &fsdest))
528 return (false);
529
530 if (!browsergetrefcon (hnode, &info)) // 5.0b9 dmb
531 info.suffixnum = 0;
532
533 suffixnum = info.suffixnum;
534
535 claygetuniquefilename (&fsdest, &suffixnum);
536
537 if (!flsourceexists) {
538
539 if (!claycreatefile (&fsdest))
540 return (false);
541 }
542 else {
543 if (!(**hnode).flnodeonscrap) { /*we own this file -- move it*/
544
545 if (((fssource.vRefNum == fsdest.vRefNum) || (fssource.vRefNum == 0) || (fsdest.vRefNum == 0)) && equalidentifiers (fssource.name, fsdest.name)) {
546
547 if (!claymovefile (&fssource, fsfolder))
548 return (false);
549 }
550 else {
551
552 if (!claycopyfile (&fssource, &fsdest))
553 return (false);
554
555 claydeletefile (&fssource);
556 }
557 }
558 else { /*file not owned -- make a copy*/
559
560 if (!claycopyfile (&fssource, &fsdest))
561 return (false);
562 }
563 }
564
565 /*update the node's refcon to reflect the new file's position & attributes*/ {
566
567 tybrowserinfo browserinfo;
568
569 claygetfileinfo (&fsdest, &browserinfo);
570
571 #if filebrowser
572 browserinfo.suffixnum = suffixnum;
573 #else
574 browserinfo.suffixnum = suffixnum; // dmb 5.0b9: new
575
576 if (suffixnum != info.suffixnum) { // suffix was added or removed
577
578 opstartinternalchange ();
579
580 opsetactualheadstring (hnode, fsdest.name);
581
582 opendinternalchange ();
583 }
584 #endif
585 if (!flsourceexists && isemptystring (bs)) { // a new insertion
586
587 (**hnode).tmpbit2 = true;
588
589 langexternaldontsave (fsdest.parID, fsdest.name); // 5.1.4
590
591 browserinfo.suffixnum = 0; // we made up the name, it's real w/whatever suffix
592 }
593
594 browsersetrefcon (hnode, &browserinfo);
595 }
596
597 (**hnode).flnodeonscrap = false;
598
599 return (true);
600 } /*browsermoveto*/
601
602
603 boolean browsergetparentspec (hdlheadrecord hnode, tybrowserspec *fsparent) {
604
605 /*
606 5.13.97 dmb: fixed summit (root table) case
607
608 5.0.2b21 dmb: use new shellgetdatabase to get parent of summit
609 */
610
611 hdlheadrecord hparent = (**hnode).headlinkleft;
612 hdltableformats hformats;
613
614 if (hparent == hnode) { // it's a summit
615
616 hformats = (hdltableformats) (**outlinedata).outlinerefcon;
617
618 shellgetdatabase (shellwindow, &(*fsparent).vRefNum); // was: databasedata; what about GDBs?
619
620 (*fsparent).parID = (**hformats).htable; // 5.0d18 dmb: this is as clean as it gets for now
621
622 setemptystring ((*fsparent).name);
623
624 return (true);
625 }
626
627 return (claygetfilespec (hparent, fsparent));
628 } /*browsergetparentspec*/
629
630
631 static boolean safedragvisit (hdlheadrecord hnode, ptrvoid punsafe) {
632
633 if ((**hnode).tmpbit) {
634
635 opgetheadstring (hnode, punsafe);
636
637 return (false);
638 }
639
640 return (true);
641 } /*safedragvisit*/
642
643
644 boolean browserpredrag (hdlheadrecord *htarget, tydirection *dragdir) {
645
646 /*
647 the user dragged the selection to the indicated destination. it's our
648 job to interpret the move, and return true only if the caller should
649 move (or copy) the selection to the destination.
650
651 if files are being dragged into a folder, we must first delete any name
652 conflicts, with confirmation.
653
654 if files are being dragged into an application, we do the launch and
655 return false; no move it to take place
656
657 9/22/93 dmb: dragging move can give us a dir of up; handle it.
658
659 5.0.2b18 dmb: if a marked headline comes back with its tmpbit set, then
660 the move is trying to replace its ancestor -- don't let it!
661 */
662
663 tybrowserinfo info;
664 hdlheadrecord hpre = *htarget;
665 tydirection dir = *dragdir;
666 bigstring bsunsafe, bsmsg;
667
668 if (dir == right) {
669
670 browsergetrefcon (hpre, &info);
671
672 if (!info.flfolder)
673 return (false);
674 }
675
676 if (!browservalidatemove (hpre, nil, dir))
677 return (false);
678
679 if (!opvisitmarked (down, safedragvisit, bsunsafe)) {
680
681 opcleartmpbits ();
682
683 #ifdef MACVERSION
684 parsedialogstring ("\x3b" "CanÕt move Ò^0Ó here because it would replace its ancestor.", bsunsafe, nil, nil, nil, bsmsg);
685 #else
686 parsedialogstring ("\x3b" "Can't move \"^0\" here because it would replace its ancestor.", bsunsafe, nil, nil, nil, bsmsg);
687 #endif
688
689 alertdialog (bsmsg);
690
691 return (false);
692 }
693
694 if ((**hpre).tmpbit) { //work hard to find a safe target
695
696 assert (dir == down);
697
698 while ((**hpre).tmpbit) { // look above us
699
700 if (!opchaseup (&hpre))
701 break;
702 }
703
704 if ((**hpre).tmpbit) { // reset and look below
705
706 hpre = *htarget;
707
708 *dragdir = up;
709
710 while ((**hpre).tmpbit) {
711
712 if (!opchasedown (&hpre))
713 break;
714 }
715 }
716
717 if ((**hpre).tmpbit) { //go to our parent
718
719 opchaseleft (&hpre);
720
721 *dragdir = right;
722 }
723 }
724
725 *htarget = hpre;
726
727 browserdeletenodeswithtmpbitset ();
728
729 return (true); /*go ahead with the move*/
730
731 #if filebrowser
732
733 if (info.filetype == 'APPL') { /*need to see if app handles file type*/
734
735 tybrowserspec fapp, fdoc;
736
737 claygetfilespec (htarget, &fapp);
738
739 claygetfilespec ((**outlinedata).hbarcursor, &fdoc);
740
741 claylaunchappwithdoc (&fapp, &fdoc, true);
742 }
743
744 #endif
745
746 } /*browserpredrag*/
747
748
749 boolean browserdragcopy (hdlheadrecord hmove, hdlheadrecord hdest) {
750
751 /*
752 we're moving hmove down or to the right of hdest. if they're
753 not both from the same volume, we need to move a copy, not the
754 original.
755 */
756
757 tybrowserspec fs1, fs2;
758
759 claygetfilespec (hmove, &fs1);
760
761 claygetfilespec (hdest, &fs2);
762
763 if (fs1.vRefNum != fs2.vRefNum) /*must copy if it's cross-volumes*/
764 return (true);
765
766 if (keyboardstatus.floptionkey || optionkeydown ()) {
767
768 bigstring bs;
769
770 copystring ("\x20" "Copy or move the selected items?", bs);
771
772 // return (twowaydialog (bs, "\x04" "Copy", "\x04" "Move"));
773 return (msgdialog (bs));
774 }
775
776 return (false);
777 } /*browserdragcopy*/
778
779
780 void browsersortfolder (hdlheadrecord hnode) {
781
782 /*
783 hnode is a folder whose sort order has changed. unlink all its
784 subnodes and reinsert them into the list sorted according to the
785 new order.
786 */
787
788 hdlheadrecord nomad = (**hnode).headlinkright, nextnomad;
789 tybrowserinfo browserinfo;
790 bigstring bs;
791 hdlheadrecord hpre;
792 tydirection dir;
793 hdlscreenmap hmap;
794
795 if (nomad == hnode) /*no subs expanded, nothing to do*/
796 return;
797
798 (**hnode).headlinkright = hnode; /*no longer has any kids*/
799
800 initbeachball (right);
801
802 /*opupdatenow ();*/
803
804 opstartinternalchange (); /*this operation is not undo-able*/
805
806 opnewscreenmap (&hmap);
807
808 while (true) {
809
810 nextnomad = (**nomad).headlinkdown;
811
812 browsergetrefcon (nomad, &browserinfo);
813
814 opgetheadstring (nomad, bs);
815
816 browserfindinsertionpoint (hnode, bs, &browserinfo, &hpre, &dir);
817
818 opdeposit (hpre, dir, nomad);
819
820 if (nextnomad == nomad)
821 break;
822
823 nomad = nextnomad;
824
825 rollbeachball ();
826 } /*while*/
827
828 opinvalscreenmap (hmap);
829
830 opendinternalchange ();
831
832 opsetctexpanded (outlinedata);
833
834 opsetscrollpositiontoline1 ();
835
836 #ifdef fldebug
837 opvalidate (outlinedata);
838 #endif
839 } /*browsersortfolder*/
840
841
842 void browserinsertagain (hdlheadrecord hnode) {
843
844 /*
845 the node's text or other info has been changed, it might sort
846 to a different place in its parent folder's list. we unlink it
847 from the structure, and link it back in where it belongs.
848
849 9/24/93 dmb: don't want an undo built for this operation, since
850 it's a passive reordering going on here.
851
852 5.0d14 dmb: do nothing when hnode is the only node at its level.
853 particularly imporant when hnode is an only summit.
854 */
855
856 hdlheadrecord hparent;
857 bigstring bs;
858 tybrowserinfo browserinfo;
859 hdlheadrecord hpre;
860 tydirection dir;
861 hdlscreenmap hmap;
862
863 if (opcountatlevel (hnode) == 1) /*has no siblings, can't change order*/
864 return;
865
866 hparent = (**hnode).headlinkleft;
867
868 if (hparent == hnode) /*it's a top-level node*/
869 hparent = nil;
870
871 opstartinternalchange (); /*don't want this to trigger callbacks or add to undo stack*/
872
873 opgetheadstring (hnode, bs);
874
875 opnewscreenmap (&hmap);
876
877 opunlink (hnode);
878
879 browsergetrefcon (hnode, &browserinfo);
880
881 browserfindinsertionpoint (hparent, bs, &browserinfo, &hpre, &dir);
882
883 opdeposit (hpre, dir, hnode);
884
885 (**outlinedata).hbarcursor = hnode;
886
887 // 2/20/97 dmb: shouldn't need this: opsetctexpanded ();
888
889 opinvalscreenmap (hmap);
890
891 opendinternalchange ();
892 } /*browserinsertagain*/
893
894
895 boolean browsercopyrefcon (hdlheadrecord hsource, hdlheadrecord hdest) {
896
897 /*
898 called while processing the Edit/Copy command. we copy the refcon
899 handle, but set the flnodeonscrap bit true, making this a reference
900 to the file. if this node gets deleted we don't delete the file.
901 */
902
903 if (!opcopyrefconroutine (hsource, hdest))
904 return (false);
905
906 (**hdest).flnodeonscrap = true; /*we don't own the file*/
907
908 return (true);
909 } /*browsercopyrefcon*/
910
911
912 static boolean browsergetnodevalue (hdlheadrecord hnode, tyvaluerecord *val) {
913
914 tybrowserspec fs;
915 hdlhashnode hhashnode;
916
917 if (!claygetfilespec (hnode, &fs))
918 return (false);
919
920 return (claylookupvalue (&fs, val, &hhashnode));
921 } /*browsergetnodevalue*/
922
923
924 boolean browsertextualizerefcon (hdlheadrecord hnode, Handle htext) {
925
926 tyvaluerecord val;
927
928 if (!browsergetnodevalue (hnode, &val))
929 return (false);
930
931
932 return (true);
933 } /*browsertextualizerefcon*/
934
935
936 boolean browserreleaserefcon (hdlheadrecord hnode, boolean fldisk) {
937
938 /*
939 the node is going away. if we own the file we must delete it. this is how
940 files get deleted from the Undo folder.
941
942 flinternalchange is true, for example, when you collapse a folder. the
943 nodes are deleted, but the files must not be.
944 */
945
946 if (!opinternalchange () && fldisk && (!(**hnode).flnodeonscrap)) {
947
948 tybrowserspec fs;
949
950 claygetfilespec (hnode, &fs);
951
952 claydeletefile (&fs);
953 }
954
955 if (hnode == hdeletednode)
956 hdeletednode = nil;
957
958 return (true);
959 } /*browserreleaserefcon*/
960
961
962 static boolean lineinsertvisit (hdlheadrecord hnode, ptrvoid refcon) {
963
964 /*
965 set the node's refcon info to reflect its current position in
966 the outline hierarchy.
967 */
968
969 tybrowserinfo info;
970 tybrowserspec fsparent;
971
972 browsergetparentspec (hnode, &fsparent);
973
974 if (browsergetrefcon (hnode, &info)) {
975
976 info.vnum = fsparent.vRefNum;
977
978 claygetdirid (&fsparent, &info.dirid);
979
980 browsersetrefcon (hnode, &info);
981 }
982
983 (**hnode).flnodeonscrap = false;
984
985 return (true);
986 } /*lineinsertvisit*/
987
988
989 boolean browserlineinserted (hdlheadrecord hnode) {
990
991 /*
992 dmb 9/23/93: no more lineinsertedcallbackdisabled flag. there's an
993 op mechanism for this, opstart/endinternalchange, that also turns
994 off undo (very important!)
995 */
996
997 tybrowserspec fsparent;
998
999 /*
1000 if (lineinsertedcallbackdisabled)
1001 return (true);
1002 */
1003
1004 if (hnode == hdeletednode) /*finishing a move operation*/
1005 hdeletednode = nil;
1006 else
1007 browsercommitchanges ();
1008
1009 /*
1010 if ((**hnode).flnewlyinsertednode)
1011 browsercreatefile (hnode, &fsparent);
1012
1013 else*/ {
1014
1015 browsergetparentspec (hnode, &fsparent);
1016
1017 if (!browsermoveto (hnode, &fsparent))
1018 return (false);
1019 }
1020
1021 oprecursivelyvisit (hnode, infinity, &lineinsertvisit, nil);
1022
1023 return (true);
1024 } /*browserlineinserted*/
1025
1026
1027 boolean browserlinedeleted (hdlheadrecord hnode) {
1028
1029 browsercommitchanges (); /*flush previous deletion*/
1030
1031 hdeletednode = hnode;
1032
1033 return (true);
1034 } /*browserlinedeleted*/
1035
1036
1037 static boolean notownrefconvisit (hdlheadrecord hnode, ptrvoid refcon) {
1038
1039 (**hnode).flnodeonscrap = true;
1040
1041 return (true);
1042 } /*notownrefconvisit*/
1043
1044
1045 static boolean closeownedwindowsvisit (hdlhashnode hn, ptrvoid refcon) {
1046
1047 tyvaluerecord val = (**hn).val;
1048 hdlexternalvariable hv;
1049 hdlwindowinfo hinfo;
1050
1051 if (val.valuetype != externalvaluetype)
1052 return (true);
1053
1054 if (langexternalwindowopen (val, &hinfo)) {
1055
1056 flinhibitclosedialogs = true;
1057
1058 shellclosewindow ((**hinfo).macwindow);
1059
1060 flinhibitclosedialogs = false;
1061 }
1062
1063 hv = (hdlexternalvariable) val.data.externalvalue;
1064
1065 if (istablevariable (hv) && (**hv).flinmemory) {
1066
1067 return (hashtablevisit ((hdlhashtable) (**hv).variabledata, closeownedwindowsvisit, nil));
1068 }
1069
1070 return (true);
1071 } /*closeownedwindowsvisit*/
1072
1073
1074 static boolean closeownedwindows (hdlheadrecord hnode) {
1075
1076 /*
1077 hnode has been deleted, but with undo. so the external value nodes
1078 aren't being disposed to trigger window closing. tablesymboldeleted
1079 could theoretically take care of this, but traversing the outline is
1080 easier & faster. in fact, tablesymboldeleted can't do it, because the
1081 node is already unlinked. it would have to be the symbolunlinking
1082 callback, with an additional parameter (fldisposing), newly-hooked by
1083 tableexternal.c
1084 */
1085
1086 tybrowserspec fs;
1087 hdlhashnode hn;
1088
1089 if (!claygetfilespec (hnode, &fs))
1090 return (false);
1091
1092 if (!hashtablelookupnode (fs.parID, fs.name, &hn))
1093 return (false);
1094
1095 return (closeownedwindowsvisit (hn, nil));
1096 } /*notownrefconvisit*/
1097
1098
1099 boolean browsercommitchanges (void) {
1100
1101 boolean fl;
1102
1103 if (hdeletednode == nil)
1104 return (true);
1105
1106 getundofolderspec ();
1107
1108 closeownedwindows (hdeletednode);
1109
1110 fl = browsermoveto (hdeletednode, &undofolderspec);
1111
1112 oprecursivelyvisit (hdeletednode, infinity, ¬ownrefconvisit, nil);
1113
1114 hdeletednode = nil;
1115
1116 return (fl);
1117 } /*browsercommitchanges*/
1118
1119
1120 #if 0
1121
1122 static boolean xxxbrowserexportscrap (hdloutlinerecord hscrap) {
1123
1124 hdlheadrecord nomad = (**hscrap).hsummit;
1125
1126 if (!getclipfolderspec ())
1127 return (false);
1128
1129 while (true) {
1130
1131 if (!browsermoveto (nomad, &clipfolderspec))
1132 return (false);
1133
1134 oprecursivelyvisit (nomad, infinity, ¬ownrefconvisit, nil);
1135
1136 if (!opchasedown (&nomad))
1137 return (true);
1138 } /*while*/
1139 } /*browserexportscrap*/
1140
1141 #endif
1142
1143
1144 static void tabledisposescrap (hdloutlinerecord houtline) {
1145
1146 opdisposeoutline (houtline, false);
1147 } /*tabledisposescrap*/
1148
1149
1150 static boolean tableexportscrap (hdloutlinerecord houtline, tyscraptype totype, Handle *hexport, boolean *fltempscrap) {
1151
1152 /*
1153 5.0b9 dmb: for single headline table selection, use 4.x value exporting
1154 */
1155
1156 hdlheadrecord hsummit = (**houtline).hsummit;
1157
1158 *fltempscrap = true; /*usually the case*/
1159
1160 if ((totype != hashscraptype) && opcountatlevel (hsummit) == 1) { // converting single-selection, use 4.x code
1161
1162 tyvaluerecord val;
1163
1164 if (!browsergetnodevalue (hsummit, &val))
1165 return (false);
1166
1167 return (tableexportscrapvalue (&val, totype, hexport, fltempscrap));
1168 }
1169
1170 switch (totype) {
1171
1172 case hashscraptype: /*export flat version for system scrap*/
1173 return (oppackoutline (houtline, hexport));
1174
1175 case opscraptype:
1176 case scriptscraptype:
1177 *hexport = (Handle) houtline; /*op and script scraps are the same*/
1178
1179 *fltempscrap = false; /*it's the original, not a copy*/
1180
1181 return (true);
1182
1183 case textscraptype:
1184 return (opoutlinetonewtextscrap (houtline, hexport));
1185
1186 default:
1187 return (false);
1188 }
1189 } /*tableexportscrap*/
1190
1191
1192 boolean browsersetscrap (hdloutlinerecord houtline) {
1193
1194 /*
1195 5.0d5 dmb: move to scrap folder here, before setting shell scrap
1196 */
1197
1198 hdlheadrecord nomad = (**houtline).hsummit;
1199 hdlhashtable cliptable;
1200
1201 if (!getclipfolderspec ())
1202 return (false);
1203
1204 if (!claygetdirid (&clipfolderspec, &cliptable))
1205 return (false);
1206
1207 emptyhashtable (cliptable, false);
1208
1209 while (true) {
1210
1211 if (!browsermoveto (nomad, &clipfolderspec))
1212 return (false);
1213
1214 oprecursivelyvisit (nomad, infinity, ¬ownrefconvisit, nil);
1215
1216 if (!opchasedown (&nomad))
1217 break;
1218 } /*while*/
1219
1220 return (shellsetscrap ((Handle) houtline, hashscraptype,
1221 (shelldisposescrapcallback) &tabledisposescrap,
1222 (shellexportscrapcallback) &tableexportscrap));
1223 } /*browsersetscrap*/
1224
1225
1226 boolean browsergetscrap (hdloutlinerecord *houtline, boolean *fltempscrap) {
1227
1228 Handle hscrap;
1229 tyscraptype scraptype;
1230
1231 if (!shellgetscrap (&hscrap, &scraptype))
1232 return (false);
1233
1234 if (scraptype == hashscraptype) {
1235
1236 *houtline = (hdloutlinerecord) hscrap;
1237
1238 *fltempscrap = false; /*we're returning a handle to the actual scrap*/
1239
1240 return (true);
1241 }
1242
1243 return (false);
1244 } /*browsergetscrap*/
1245
1246
1247 boolean browserdeletedummyvalues (hdlheadrecord hnode) {
1248
1249 /*
1250 hnode is no longer being displayed in its window.
1251
1252 if it or any of its siblings is an auto-created node, toss the corresponding
1253 table node
1254
1255 return true if no errors occur
1256 */
1257
1258 tybrowserspec fs;
1259 tyvaluerecord val;
1260 hdlhashnode hhashnode;
1261
1262 while (true) {
1263
1264 if ((**hnode).tmpbit2) {
1265
1266 if (claygetfilespec (hnode, &fs) && claylookupvalue (&fs, &val, &hhashnode)) {
1267
1268 if (val.valuetype == novaluetype)
1269 if (!hashtabledelete (fs.parID, fs.name))
1270 return (false);
1271 }
1272 }
1273
1274 if (!opchasedown (&hnode))
1275 return (true);
1276 }
1277 } /*browserdeletedummyvalues*/
1278
1279
1280
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.