~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Frontier Kernel
Frontier/Common/source/claybrowserstruc.c

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, &notownrefconvisit, 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, &notownrefconvisit, 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, &notownrefconvisit, 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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.