Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: claybrowserexpand.c,v 1.3 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 "file.h"
33 #include "fileloop.h"
34 #include "kb.h"
35 #include "memory.h"
36 #include "strings.h"
37 #include "shellundo.h"
38
39 #include "op.h"
40 #include "opinternal.h"
41 #include "claybrowserstruc.h"
42 #include "claybrowserexpand.h"
43 #include "claycallbacks.h"
44
45
46 static boolean compoundexpand = false;
47
48 static short expandcount; /*for debugging*/
49
50
51 static void browsercalcinsertionpoint (hdlheadrecord hparent, hdlheadrecord *hpre, tydirection *dir) {
52
53 /*
54 using whatever sorting options we have, determine the insertion point for the
55 new line. we return the info that opaddheadline needs, a handle to the "pre"
56 node and the direction relative to that node to create the new headline.
57
58 special case: if hparent == nil, we do it at the summit level.
59
60 possible view settings: name, date, kind, size, label.
61
62 9/22/93 dmb: added cases for remaining possible view settings, treating
63 them all as viewbyname. also viewbyname sort order is unicase.
64 */
65
66 if (hparent == nil) {
67
68 *hpre = oprepeatedbump (down, longinfinity, (**outlinedata).hsummit, true); /*special case*/;
69
70 *dir = down;
71 }
72 else {
73
74 if (opnosubheads (hparent)) {
75
76 *hpre = hparent;
77
78 *dir = right;
79 }
80 else {
81 *hpre = opgetlastsubhead (hparent);
82
83 *dir = down;
84 }
85 }
86 } /*browsercalcinsertionpoint*/
87
88
89 void browserfindinsertionpoint (hdlheadrecord hparent, bigstring bsnewhead, tybrowserinfo *newfileinfo, hdlheadrecord *hpre, tydirection *dir) {
90
91 /*
92 using whatever sorting options we have, determine the insertion point for the
93 new line. we return the info that opaddheadline needs, a handle to the "pre"
94 node and the direction relative to that node to create the new headline.
95
96 special case: if hparent == nil, we do it at the summit level.
97
98 possible view settings: name, date, kind, size, label.
99
100 9/22/93 dmb: added cases for remaining possible view settings, treating
101 them all as viewbyname. also viewbyname sort order is unicase.
102 */
103
104 hdlheadrecord nomad;
105 tyfolderview folderview;
106 #if filebrowser
107 unsigned long time1, time2;
108 unsigned long size1, size2;
109 short label1, label2;
110 bigstring bsnew;
111 #endif
112 #if odbbrowser
113 hdlhashtable ht;
114 hdlhashnode hnode, hnext;
115 bigstring bsnext;
116 hdlheadrecord hmatch;
117 #endif
118
119 if (hparent == nil) {
120
121 folderview = viewbyname;
122
123 nomad = (**outlinedata).hsummit; /*special case*/
124
125 *hpre = nomad;
126
127 *dir = up;
128 }
129 else {
130
131 #if filebrowser
132 tybrowserinfo browserinfo;
133
134 browsergetrefcon (hparent, &browserinfo);
135
136 folderview = browserinfo.folderview;
137 #endif
138
139 nomad = hparent;
140
141 *hpre = nomad;
142
143 *dir = right;
144
145 if (!opchaseright (&nomad)) /*has no expanded subs*/
146 return;
147 }
148
149 #if odbbrowser
150
151 ht = (*newfileinfo).dirid;
152
153 if (hashtablelookupnode (ht, bsnewhead, &hnode)) { // should not fail
154
155 hnext = (**hnode).sortedlink;
156
157 if (hnext != nil) { // we're not last
158
159 gethashkey (hnext, bsnext);
160
161 if (opfindhead (nomad, bsnext, &hmatch)) { // shouldn't fail
162
163 *hpre = hmatch;
164
165 *dir = up;
166
167 return;
168 }
169 }
170 }
171
172 // default: insert at end of list
173
174 *hpre = oprepeatedbump (down, longinfinity, nomad, true);
175
176 *dir = down;
177
178 return;
179
180 #endif
181
182
183 #if filebrowser
184
185 folderview = -1;
186
187 switch (folderview) { /*initialize the things we compare against*/
188
189 case viewbyname:
190 case viewbyicon:
191 case viewbysmallicon:
192 case viewbycomment:
193 case viewbyversion:
194 copystring (bsnewhead, bsnew);
195
196 alllower (bsnew);
197
198 break;
199
200 case viewbykind:
201 setstringlength (bsnew, 4);
202
203 moveleft (&(*newfileinfo).filecreator, &bsnew [1], 4);
204
205 break;
206
207 case viewbydate:
208 time1 = (unsigned long) (*newfileinfo).timemodified;
209
210 break;
211
212 case viewbysize:
213 size1 = (*newfileinfo).filesize;
214
215 break;
216
217 case viewbycolor:
218 label1 = (*newfileinfo).ixlabel;
219
220 break;
221 } /*switch*/
222
223 while (true) {
224
225 switch (folderview) {
226
227 case viewbyname:
228 case viewbyicon:
229 case viewbysmallicon:
230 case viewbycomment:
231 case viewbyversion: {
232 bigstring bs;
233
234 opgetheadstring (nomad, bs);
235
236 alllower (bs);
237
238 if (comparestrings (bsnew, bs) == -1) /*bsnewhead is < bs*/
239 return;
240
241 break;
242 }
243
244 case viewbykind: {
245 tybrowserinfo nomadinfo;
246 bigstring bs;
247
248 browsergetrefcon (nomad, &nomadinfo);
249
250 setstringlength (bs, 4);
251
252 moveleft (&nomadinfo.filecreator, &bs [1], 4);
253
254 if (comparestrings (bsnew, bs) == -1) /*bsnew is < bs*/
255 return;
256
257 break;
258 }
259
260 case viewbydate: {
261 tybrowserinfo nomadinfo;
262
263 browsergetrefcon (nomad, &nomadinfo);
264
265 time2 = (unsigned long) nomadinfo.timemodified;
266
267 if (time1 >= time2)
268 return;
269
270 break;
271 }
272
273 case viewbysize: {
274 tybrowserinfo nomadinfo;
275
276 browsergetrefcon (nomad, &nomadinfo);
277
278 size2 = nomadinfo.filesize;
279
280 if (size1 >= size2)
281 return;
282
283 break;
284 }
285
286 case viewbycolor: {
287 tybrowserinfo nomadinfo;
288
289 browsergetrefcon (nomad, &nomadinfo);
290
291 label2 = nomadinfo.ixlabel;
292
293 if (label1 >= label2)
294 return;
295
296 break;
297 }
298 } /*switch*/
299
300 *hpre = nomad;
301
302 *dir = down;
303
304 if (!opchasedown (&nomad)) /*it's the last guy in the list*/
305 return;
306 } /*while*/
307 #endif
308 } /*browserfindinsertionpoint*/
309
310
311 boolean browserexpandvisit (bigstring bsitem, tybrowserinfo *info, long refcon) {
312
313 /*
314 dmb 9/23/93: call opstart/endinternalchange around opaddheadline. this turns
315 off the lineinsertedcallback and prevents an undo from being built -- which
316 would otherwise delete the file! these calls used to be in browserpreexpand,
317 but that was when this visit routine wasn't directly callable.
318 */
319
320 register tyexpandinfo *expandinfo = (tyexpandinfo *) refcon;
321 hdlheadrecord hnew;
322
323 if (!testheapspace (512)) /*512 bytes should be plenty*/
324 return (false);
325
326 /*debugging code {
327
328 bigstring bs;
329
330 NumToString (expandcount++, bs);
331
332 appsetmessage (app.appwindow, bs);
333 }
334 */
335
336 if (keyboardescape ()) /*user pressed cmd-period*/
337 return (false);
338
339 rollbeachball ();
340
341 /*insert the new line*/ {
342
343 hdlheadrecord hpre;
344 tydirection dir;
345
346 if ((*expandinfo).flsortnodes)
347 browserfindinsertionpoint ((*expandinfo).hparent, bsitem, info, &hpre, &dir);
348 else
349 browsercalcinsertionpoint ((*expandinfo).hparent, &hpre, &dir);
350
351 opstartinternalchange (); /*this operation is not undo-able, and mustn't trigger callbacks*/
352
353 opaddheadline (hpre, dir, bsitem, &hnew);
354
355 opendinternalchange ();
356 }
357
358 browsercopyfileinfo (hnew, info);
359
360 if ((*expandinfo).flsettmpbits)
361 (**hnew).tmpbit = true; /*if expand is cancelled, we nuke all nodes with tmp bit set*/
362
363 if ((*info).flfolder) {
364
365 (**hnew).flnodeisfolder = true;
366
367 if ((*expandinfo).ctlevels > 1) {
368
369 if (!browserexpand (hnew, (*expandinfo).ctlevels - 1))
370 return (false);
371 }
372 }
373
374 (*expandinfo).hnewnode = hnew; /*some callers need this*/
375
376 return (true);
377 } /*browserexpandvisit*/
378
379
380 boolean browserexpand (hdlheadrecord hnode, long ctlevels) {
381
382 tyexpandinfo expandinfo;
383 tybrowserspec fs;
384
385 if (opsubheadsexpanded (hnode)) { /*special case for a node that's already expanded*/
386
387 hdlheadrecord nomad = (**hnode).headlinkright;
388
389 if (ctlevels <= 1) /*we aren't going any deeper*/
390 return (true);
391
392 while (true) { /*loop over all the subheads of the node*/
393
394 if ((**nomad).flnodeisfolder) {
395
396 if (!browserexpand (nomad, ctlevels - 1))
397 return (false);
398 }
399
400 if (!opchasedown (&nomad))
401 return (true);
402 } /*while*/
403 } /*dealing with already-expanded nodes*/
404
405 claygetfilespec (hnode, &fs);
406
407 expandinfo.hparent = hnode;
408
409 expandinfo.ctlevels = ctlevels;
410
411 expandinfo.flsettmpbits = true;
412
413 #if odbbrowser
414 expandinfo.flsortnodes = false;
415 #else
416 expandinfo.flsortnodes = true;
417 #endif
418
419 expandcount = 0; /*for debugging*/
420
421 return (clayfolderloop (&fs, false, &browserexpandvisit, (long) &expandinfo));
422 } /*browserexpand*/
423
424
425 static boolean expandcancelledvisit (hdlheadrecord hnode, ptrvoid refcon) {
426
427 if ((**hnode).tmpbit) {
428
429 opstartinternalchange ();
430
431 opdeletenode (hnode);
432
433 opendinternalchange ();
434 }
435
436 return (true);
437 } /*expandcancelledvisit*/
438
439
440 boolean browserpreexpand (hdlheadrecord hnode, short ctlevels, boolean flmaycreatesubs) {
441
442 /*
443 called by opexpand.c before expanding nodes. we create new nodes under
444 the node by looping over its folder on disk.
445
446 DW 8/18/93: allow the user to press cmd-period to cancel the expand
447 operation. set the tmpbit of every newly created node. if the user
448 hits cmd-period, or if we run out of memory, we delete all nodes with
449 their tmp bit set. important: we don't clear the tmp bits here, we
450 depend on them all being clear before the operation starts. the reason:
451 some operations do several calls to us. we want them all to be
452 cancelled.
453
454 DW 8/30/93: do it right this time. add another piece of baling wire, the
455 compoundexpand flag. if it's not true, we clear the tmpbits. otherwise
456 we assume they've been cleared.
457
458 5.0a25 dmb: auto-create item in empty table to expand, if new flmaycreatesubs
459 parameter is true
460 */
461
462 register hdloutlinerecord ho = outlinedata;
463 boolean fl;
464
465 if (((**hnode).headlinkright != hnode) && (ctlevels <= 1)) /*the nodes are already there*/
466 return (true);
467
468 if (!(**hnode).flnodeisfolder) /*can't expand a file*/
469 return (true);
470
471 initbeachball (right);
472
473 if (!compoundexpand)
474 opcleartmpbits ();
475
476 fl = browserexpand (hnode, ctlevels);
477
478 if (!fl) /*memory error, or user pressed cmd-period or escape*/
479 opsiblingvisiter ((**ho).hsummit, true, &expandcancelledvisit, nil);
480
481 if (!compoundexpand)
482 opcleartmpbits ();
483
484 if ((**hnode).headlinkright == hnode) { // table was empty
485
486 if (flmaycreatesubs) {
487
488 hdlheadrecord hnew;
489
490 opstartinternalchange ();
491
492 opaddheadline (hnode, right, emptystring, &hnew);
493
494 opendinternalchange ();
495
496 if (hnode == nil)
497 return (false);
498
499 browserlineinserted (hnew);
500 }
501 }
502
503 #ifdef xxxfldebug
504 opsetctexpanded (ho);
505
506 opvalidate (ho);
507 #endif
508
509 return (fl);
510 } /*browserpreexpand*/
511
512
513 boolean browserselectfile (ptrfilespec pfs, boolean flexpand, hdlheadrecord *hnode) {
514
515 bigstring filepath;
516 hdlheadrecord nomad;
517 boolean flsomethingexpanded = false;
518 boolean flreturn = false;
519 boolean fldisplaywasenabled;
520
521 *hnode = nil;
522
523 compoundexpand = true; opcleartmpbits ();
524
525 filespectopath (pfs, filepath);
526
527 fldisplaywasenabled = opdisabledisplay ();
528
529 nomad = (**outlinedata).hsummit;
530
531 // addtohistorydisabled = true; /*don't want intermediate expansions added to the history menu*/
532
533 while (true) {
534
535 bigstring headstring;
536
537 if (stringlength (filepath) == 0)
538 break;
539
540 firstword (filepath, ':', headstring);
541
542 if (stringlength (headstring) == 0)
543 copystring (filepath, headstring);
544
545 deletestring (filepath, 1, (short) (stringlength (headstring) + 1));
546
547 if (!opfindhead (nomad, headstring, &nomad))
548 break;
549
550 if (stringlength (filepath) == 0) {
551
552 flreturn = true;
553
554 break;
555 }
556
557 if (flexpand) {
558
559 if (!opsubheadsexpanded (nomad)) {
560
561 if (!opexpand (nomad, 1, false)) { /*user pressed cmd-period, or we ran out of memory*/
562
563 openabledisplay ();
564
565 return (false);
566 }
567
568 flsomethingexpanded = true;
569 }
570 }
571
572 if (!opnavigate (right, &nomad))
573 break;
574 } /*while*/
575
576 // addtohistorydisabled = false;
577
578 if (fldisplaywasenabled)
579 openabledisplay ();
580
581 if (flsomethingexpanded) {
582
583 opresetscrollbars ();
584
585 opinvaldisplay ();
586 }
587
588 compoundexpand = false;
589
590 opcleartmpbits ();
591
592 *hnode = nomad;
593
594 return (flreturn);
595 } /*browserselectfile*/
596
597
598 boolean browserexpandtofile (ptrfilespec pfs) {
599
600 hdlheadrecord hnode;
601
602 opclearallmarks ();
603
604 if (!browserselectfile (pfs, true, &hnode))
605 return (false);
606
607 (**outlinedata).flcursorneedsdisplay = true; /*might need to vertical-scroll*/
608
609 opjumpto (hnode);
610
611 opupdatenow ();
612
613 return (true);
614 } /*browserexpandtofile*/
615
616
617 boolean browsercanexpand (hdlheadrecord hnode) {
618
619 tybrowserinfo info;
620
621 browsergetrefcon (hnode, &info);
622
623 return (info.flfolder && (info.filesize > 0));
624 } /*browsercanexpand*/
625
626
627 boolean browserpostcollapse (hdlheadrecord hnode) {
628
629 /*
630 5.0a25 dmb: auto-delete auto-created node
631
632 5.1.4 dmb: after deleting an auto-created node, we still need to delete subs
633 */
634
635 hdloutlinerecord ho = outlinedata;
636 boolean fldisplaywasenabled;
637
638 killundo ();
639
640 /*toss auto-created nodes, if present*/ {
641 hdlheadrecord hsub = (**hnode).headlinkright;
642
643 browserdeletedummyvalues (hsub);
644
645 /*
646 tybrowserspec fs;
647 tyvaluerecord val;
648
649 if ((**hsub).tmpbit2 && opislastsubhead (hsub)) {
650
651 if (claygetfilespec (hsub, &fs) && claylookupvalue (&fs, &val))
652 if (val.valuetype == novaluetype) {
653
654 hashtabledelete (fs.parID, fs.name);
655
656 //return (true);
657 }
658 }
659 */
660 }
661
662 fldisplaywasenabled = opdisabledisplay (); /*keep the cursor line from flashing*/
663
664 opstartinternalchange ();
665
666 /*make sure the outline is (temporarily) not read-only*/ {
667
668 boolean fltemp = (**ho).flreadonly;
669
670 (**ho).flreadonly = false; /*allow deletion to happen*/
671
672 opdeletesubs (hnode);
673
674 (**ho).flreadonly = fltemp;
675 }
676
677 if (fldisplaywasenabled)
678 openabledisplay ();
679
680 opendinternalchange ();
681
682 return (true);
683 } /*browserpostcollapse*/
684
685
686
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.