Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: claybrowservalidate.c,v 1.5 2005/09/30 15:29:18 icreedon 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 "dialogs.h"
32 #include "error.h"
33 #include "strings.h"
34 #include "opinternal.h"
35 #include "claybrowserstruc.h"
36 #include "claybrowservalidate.h"
37 #include "langinternal.h" /* 2005-09-26 creedon */
38 #include "tablestructure.h" /* 2005-09-26 creedon */
39
40 #define collidewithequal 0x0001
41 #define collidewitholder 0x0002
42 #define collidewithnewer 0x0004
43
44 #define nocollisions 0
45
46 #define bilateralcollision (collidewitholder + collidewithnewer)
47
48 static long dragmodified;
49
50 //static char *pastefname;
51
52 typedef enum tyaction {
53
54 validatemove,
55
56 validatepaste
57 } tyaction;
58
59
60 byte * actionstrings [] = {
61
62 "\x06" "moving",
63 "\x07" "pasting"
64 };
65
66
67 enum {
68 ixsomeitems,
69 ixan,
70 ixanewer,
71 ixanolder,
72 ixitemnamed,
73 ixalreadyexists
74 };
75
76
77 byte * dialogstrings [] = {
78 "\x40" "Some items in this location have the same names as items you're ",
79 "\x02" "An",
80 "\x07" "A newer",
81 "\x08" "An older",
82 #ifdef MACVERSION
83 "\x0d" " item named Ň",
84 "\x22" "Ó already exists in this location."
85 #else
86 "\x0d" " item named \"",
87 "\x22" "\" already exists in this location."
88 #endif
89 };
90
91 typedef struct tydraginfo {
92
93 long ctcollisions;
94
95 short collisiontype;
96
97 tyaction action;
98
99 hdlheadrecord hdrag;
100
101 hdlheadrecord hdest;
102
103 tydirection dir;
104
105 hdlheadrecord hcollided;
106
107 hdlheadrecord hcompare;
108 } tydraginfo, *ptrdraginfo;
109
110
111 boolean browservalidatedrag (hdlheadrecord hsource, hdlheadrecord hdest, tydirection dir) {
112
113 /*
114 5.0a5 dmb: same level, resort check is bogus; headlink lefts can be the same for a
115 summit and its child, and two summits have different headlinklefts. but we don't
116 want to enforce this anyway, so I just commented it out
117
118 5.0b15 dmb: removed vestigal sourceinfo code
119 */
120
121 tybrowserinfo destinfo;
122
123 browsergetrefcon (hdest, &destinfo);
124
125 if (destinfo.flvolume) {
126
127 if (dir == down)
128 return (false);
129
130 #if filebrowser
131 if (destinfo.fllocked || destinfo.flhardwarelock)
132 return (false);
133 #endif
134 }
135
136 if ((!destinfo.flfolder) && (dir == right)) /*can't move to the right of a file*/
137 return (false);
138
139 /*
140 if ((**hsource).headlinkleft == (**hdest).headlinkleft) { //they're at the same level
141
142 if ((dir == up) || (dir == down)) //can't re-sort the list with dragging move
143 return (false);
144 }
145
146 browsergetrefcon (hsource, &sourceinfo);
147 */
148
149 return (true);
150 } /*browservalidatedrag*/
151
152
153 static boolean browsercompareforcollision (hdlheadrecord hnode, long dragmodified, bigstring bs1, bigstring bs2, ptrdraginfo draginfo) {
154
155 /*
156 5.0.2b18 dmb: set tmpbit of subs too, so we can detect illegal moves
157 */
158
159 tybrowserinfo info;
160
161 if (equalidentifiers (bs1, bs2)) {
162
163 opsettmpbitvisit (hnode, (ptrvoid) true);
164
165 oprecursivelyvisit (hnode, infinity, &opsettmpbitvisit, (ptrvoid) true); // set subs too
166
167 ++(*draginfo).ctcollisions;
168
169 (*draginfo).hcollided = hnode; /*last collision*/
170
171 if ((*draginfo).collisiontype < bilateralcollision) { /*still useful to check dates*/
172
173 browsergetrefcon (hnode, &info);
174
175 switch (sgn (dragmodified - info.timemodified)) {
176
177 case +1:
178 (*draginfo).collisiontype |= collidewitholder; break;
179
180 case 0:
181 (*draginfo).collisiontype |= collidewithequal; break;
182
183 case -1:
184 (*draginfo).collisiontype |= collidewithnewer; break;
185 } /*switch*/
186 }
187 }
188
189 return (true);
190 } /*browsercompareforcollision*/
191
192
193 static boolean collisionvisit (hdlheadrecord hnode, ptrvoid refcon) {
194
195 /*
196 5.0b9 dmb: don't conflict with ourself
197 */
198
199 bigstring bsnode, bsdrag;
200 ptrdraginfo draginfo = (ptrdraginfo) refcon;
201
202 if (hnode == (*draginfo).hdrag)
203 return (true);
204
205 opgetheadstring (hnode, bsnode);
206
207 opgetheadstring ((*draginfo).hdrag, bsdrag);
208
209 return (browsercompareforcollision (hnode, dragmodified, bsnode, bsdrag, draginfo));
210 } /*collisionvisit*/
211
212
213 static boolean browsercollisiondialog (hdlheadrecord hdest, ptrdraginfo draginfo) {
214
215 /*
216 2005-09-26 creedon: changed default order of buttons, default is Duplicate which is the safe option, checks user.prefs.flReplaceDialogExpertMode and if true Replace is the default option
217 */
218
219 bigstring bs, bscollided, prompt;
220 bigstring nobutton, yesbutton;
221 short itemhit;
222 boolean fl, flExpertMode = false;
223
224 if ((*draginfo).collisiontype == nocollisions) /*no confirmation or deletions needed*/
225 return (true);
226
227 if ((*draginfo).ctcollisions > 1) {
228
229 copystring (dialogstrings [ixsomeitems], prompt);
230
231 pushstring (actionstrings [(*draginfo).action], prompt);
232
233 pushchar ('.', prompt);
234 }
235 else {
236 copystring (dialogstrings [ixan], prompt);
237
238 switch ((*draginfo).collisiontype) {
239
240 case collidewithnewer:
241 copystring (dialogstrings [ixanewer], prompt);
242
243 break;
244
245 case collidewitholder:
246 copystring (dialogstrings [ixanolder], prompt);
247
248 break;
249 } /*switch*/
250
251 pushstring (dialogstrings [ixitemnamed], prompt);
252
253 opgetheadstring ((*draginfo).hcollided, bscollided);
254
255 pushstring (bscollided, prompt);
256
257 pushstring (dialogstrings [ixalreadyexists], prompt);
258 }
259
260 getsystemtablescript (idreplacedialogexpertmode, bs); // "user.prefs.flReplaceDialogExpertMode"
261
262 disablelangerror ();
263
264 fl = langrunstring (bs, bs);
265
266 enablelangerror ();
267
268 if (fl)
269 stringisboolean (bs, &flExpertMode);
270
271 if (flExpertMode) {
272 copystring (duplicatebuttontext, nobutton);
273 copystring (replacebuttontext, yesbutton);
274 }
275 else {
276 copystring (duplicatebuttontext, yesbutton);
277 copystring (replacebuttontext, nobutton);
278 }
279
280 itemhit = threewaydialog (prompt, yesbutton, nobutton, cancelbuttontext);
281
282 if (flExpertMode)
283 switch (itemhit) {
284
285 case 1:
286 itemhit = 2;
287
288 break;
289
290 case 2:
291 itemhit = 1;
292 break;
293
294 }
295
296 switch (itemhit) {
297
298 case 1:
299 opcleartmpbits ();
300
301 /*caller should rename items where conflicts occur*/
302
303 return (true);
304
305 case 2:
306 /*caller should delete all files with their tmpbit set*/
307
308 return (true);
309
310 default:
311 opcleartmpbits ();
312
313 return (false);
314 } /* switch */
315
316 } /*browsercollisiondialog*/
317
318
319 static boolean validatemovevisit (hdlheadrecord hnode, ptrvoid refcon) {
320
321 tybrowserinfo info;
322 ptrdraginfo draginfo = (ptrdraginfo) refcon;
323 hdlheadrecord hdest = (*draginfo).hdest;
324
325 (*draginfo).hdrag = hnode;
326
327 browsergetrefcon (hnode, &info);
328
329 dragmodified = info.timemodified;
330
331 if ((*draginfo).dir == right)
332 return (oprecursivelyvisit (hdest, 1, &collisionvisit, draginfo));
333 else
334 return (oplistvisit (opfirstatlevel (hdest), &collisionvisit, draginfo));
335 } /*validatemovevisit*/
336
337
338 static boolean browservalidateinsertion (hdlheadrecord hdest, hdlheadrecord hscrap, tydirection dir, tyaction action) {
339
340 /*
341 confirm that the user wants to overwrite existing files,
342 we return false to cancel the operation.
343 */
344
345 tydraginfo draginfo;
346
347 draginfo.hdest = hdest;
348
349 draginfo.dir = dir;
350
351 draginfo.ctcollisions = draginfo.collisiontype = 0;
352
353 draginfo.action = action;
354
355 opcleartmpbits ();
356
357 if (hscrap == nil)
358 opvisitmarked (down, &validatemovevisit, &draginfo);
359 else
360 oplistvisit (hscrap, &validatemovevisit, &draginfo);
361
362 return (browsercollisiondialog (hdest, &draginfo));
363 } /*browservalidateinsertion*/
364
365
366 boolean browservalidatemove (hdlheadrecord hdest, hdlheadrecord hscrap, tydirection dir) {
367
368 return (browservalidateinsertion (hdest, hscrap, dir, validatemove));
369 } /*browservalidatemove*/
370
371
372 boolean browservalidatepaste (hdlheadrecord hscrap, hdlheadrecord hdest, tydirection dir) {
373
374 /*
375 return false to cancel the paste.
376
377 assume that paste always happens in the list of the cursor's parent.
378 */
379
380 #if filebrowser
381
382 hdlheadrecord hfolder = (**hdest).headlinkleft;
383
384 if (hfolder == hdest) {
385
386 alertdialog ("\x32" "CanŐt paste at the top level of a browser outline.");
387
388 return (false);
389 }
390
391 #endif
392
393 if (!browservalidateinsertion (hdest, hscrap, dir, validatepaste)) /*user declined to replace already-existing files*/
394 return (false);
395
396 browserdeletenodeswithtmpbitset ();
397
398 return (true);
399 } /*browservalidatepaste*/
400
401
402 #if 0 /*we're not doing a folder-based clipboard, but if we did, this is how you would validate a paste*/
403
404 static boolean pastecollisionvisit (hdlheadrecord hnode, ptrdraginfo draginfo) {
405
406 bigstring fname;
407 bigstring bsnode;
408
409 copystring (pastefname, fname);
410
411 opgetheadstring (hnode, bsnode);
412
413 return (browsercompareforcollision (hnode, dragmodified, bsnode, fname));
414 } /*pastecollisionvisit*/
415
416
417 static boolean validatepastecallback (bigstring fname, tyfileinfo *info, ptrdraginfo draginfo) {
418
419 dragmodified = (*info).timemodified;
420
421 pastefname = (char *) fname;
422
423 return (oprecursivelyvisit ((*draginfo).hdest, 1, &pastecollisionvisit, draginfo));
424 } /*validatepastecallback*/
425
426
427 static boolean browservalidatefolderpaste (hdlheadrecord hfolder, FSSpec *clipfolderspec) {
428
429 /*
430 check for collisions -- if there already is a file in the target folder
431 with the same name as one of the items we're pasting, a dialog appears
432 confirming the replacement. all files that need to be deleted have their
433 tmpbits set. the caller should delete them. we don't do the deletion
434 here so that the deletions can be undoable.
435 */
436
437 tydraginfo;
438
439 if ((**hfolder).headlinkleft == hfolder) {
440
441 alertdialog ("\x32" "CanŐt paste at the top level of a browser outline.");
442
443 return (false);
444 }
445
446 draginfo.hdest = hfolder;
447
448 draginfo.ctcollisions = draginfo.collisiontype = 0;
449
450 opcleartmpbits ();
451
452 folderloop (clipfolderspec, false, &validatepastecallback, &draginfo);
453
454 return (browsercollisiondialog (hfolder, "\x07" "pasting"));
455 } /*browservalidatefolderpaste*/
456
457 #endif
458
459
460 static ptrstring pcommand;
461
462
463 static boolean compareforcopyvisit (hdlheadrecord hnode, ptrvoid refcon) {
464
465 bigstring bs, bsnode;
466 ptrdraginfo draginfo = (ptrdraginfo) refcon;
467
468 if (hnode == (*draginfo).hcompare)
469 return (true);
470
471 opgetheadstring (hnode, bsnode);
472
473 opgetheadstring ((*draginfo).hcompare, bs);
474
475 if (!equalidentifiers (bsnode, bs))
476 return (true);
477
478 copystring ("\x06" "CanŐt ", bs);
479
480 pushstring (pcommand, bs);
481
482 pushstring ("\x35" " because there are two or more selected items named Ň", bs);
483
484 pushstring (bsnode, bs);
485
486 pushstring ("\x02" "Ó.", bs);
487
488 alertdialog (bs);
489
490 return (false); /*stop both traversals*/
491 } /*compareforcopyvisit*/
492
493
494 static boolean validatecopyvisit (hdlheadrecord hnode, ptrvoid refcon) {
495
496 tydraginfo draginfo;
497
498 draginfo.hcompare = hnode;
499
500 return (opvisitmarked (down, &compareforcopyvisit, &draginfo));
501 } /*validatecopyvisit*/
502
503
504 boolean browservalidatecopy (bigstring bscommand) {
505
506 /*
507 don't allow a copy if there's a node selected that has the
508 same name as another node that's selected. we do the dialog
509 here, the caller should just exit if we return false.
510 */
511
512 pcommand = bscommand; /*set static to point to string*/
513
514 return (opvisitmarked (down, &validatecopyvisit, nil));
515 } /*browservalidatecopy*/
516
517
518
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.