1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software.. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 #include "FSClipboard.h" 36 #include <Clipboard.h> 37 #include <Alert.h> 38 #include <Catalog.h> 39 #include <Locale.h> 40 #include <NodeMonitor.h> 41 #include "Commands.h" 42 #include "FSUtils.h" 43 #include "Tracker.h" 44 45 46 // prototypes 47 static void MakeNodeFromName(node_ref* node, char* name); 48 static inline void MakeRefName(char* refName, const node_ref* node); 49 static inline void MakeModeName(char* modeName, const node_ref* node); 50 static inline void MakeModeNameFromRefName(char* modeName, char* refName); 51 static inline bool CompareModeAndRefName(const char* modeName, 52 const char* refName); 53 54 /* 55 static bool 56 FSClipboardCheckIntegrity() 57 { 58 return true; 59 } 60 */ 61 62 static void 63 MakeNodeFromName(node_ref* node, char* name) 64 { 65 char* nodeString = strchr(name, '_'); 66 if (nodeString != NULL) { 67 node->node = strtoll(nodeString + 1, (char**)NULL, 10); 68 node->device = atoi(name + 1); 69 } 70 } 71 72 73 static inline void 74 MakeRefName(char* refName, const node_ref* node) 75 { 76 sprintf(refName, "r%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node); 77 } 78 79 80 static inline void 81 MakeModeName(char* modeName, const node_ref* node) 82 { 83 sprintf(modeName, "m%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node); 84 } 85 86 87 static inline void 88 MakeModeName(char* name) 89 { 90 name[0] = 'm'; 91 } 92 93 94 static inline void 95 MakeModeNameFromRefName(char* modeName, char* refName) 96 { 97 strcpy(modeName, refName); 98 modeName[0] = 'm'; 99 } 100 101 102 static inline bool 103 CompareModeAndRefName(const char* modeName, const char* refName) 104 { 105 return !strcmp(refName + 1, modeName + 1); 106 } 107 108 109 // #pragma mark - 110 111 112 #undef B_TRANSLATION_CONTEXT 113 #define B_TRANSLATION_CONTEXT "FSClipBoard" 114 115 bool 116 FSClipboardHasRefs() 117 { 118 bool result = false; 119 120 if (be_clipboard->Lock()) { 121 BMessage* clip = be_clipboard->Data(); 122 if (clip != NULL) { 123 #ifdef B_BEOS_VERSION_DANO 124 const 125 #endif 126 char* refName; 127 #ifdef B_BEOS_VERSION_DANO 128 const 129 #endif 130 char* modeName; 131 uint32 type; 132 int32 count; 133 if (clip->GetInfo(B_REF_TYPE, 0, &refName, &type, &count) == B_OK 134 && clip->GetInfo(B_INT32_TYPE, 0, &modeName, &type, &count) 135 == B_OK) { 136 result = CompareModeAndRefName(modeName, refName); 137 } 138 } 139 be_clipboard->Unlock(); 140 } 141 return result; 142 } 143 144 145 void 146 FSClipboardStartWatch(BMessenger target) 147 { 148 if (dynamic_cast<TTracker*>(be_app) != NULL) 149 ((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target); 150 else { 151 // this code is used by external apps using objects using FSClipboard 152 // functions, i.e. applications using FilePanel 153 BMessenger messenger(kTrackerSignature); 154 if (messenger.IsValid()) { 155 BMessage message(kStartWatchClipboardRefs); 156 message.AddMessenger("target", target); 157 messenger.SendMessage(&message); 158 } 159 } 160 } 161 162 163 void 164 FSClipboardStopWatch(BMessenger target) 165 { 166 if (dynamic_cast<TTracker*>(be_app) != NULL) 167 ((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target); 168 else { 169 // this code is used by external apps using objects using FSClipboard 170 // functions, i.e. applications using FilePanel 171 BMessenger messenger(kTrackerSignature); 172 if (messenger.IsValid()) { 173 BMessage message(kStopWatchClipboardRefs); 174 message.AddMessenger("target", target); 175 messenger.SendMessage(&message); 176 } 177 } 178 } 179 180 181 void 182 FSClipboardClear() 183 { 184 if (!be_clipboard->Lock()) 185 return; 186 187 be_clipboard->Clear(); 188 be_clipboard->Commit(); 189 be_clipboard->Unlock(); 190 } 191 192 193 /** This function adds the given poses list to the clipboard, for both copy 194 * and cut. All poses in the list must have "directory" as parent. 195 * "moveMode" is either kMoveSelection or kCopySelection. 196 * It will check if the entries are already present, so that there can only 197 * be one reference to them in the clipboard. 198 */ 199 200 uint32 201 FSClipboardAddPoses(const node_ref* directory, PoseList* list, 202 uint32 moveMode, bool clearClipboard) 203 { 204 uint32 refsAdded = 0; 205 int32 listCount = list->CountItems(); 206 207 if (listCount == 0 || !be_clipboard->Lock()) 208 return 0; 209 210 // update message to be send to all listeners 211 BMessage updateMessage(kFSClipboardChanges); 212 updateMessage.AddInt32("device", directory->device); 213 updateMessage.AddInt64("directory", directory->node); 214 updateMessage.AddBool("clearClipboard", clearClipboard); 215 216 TClipboardNodeRef clipNode; 217 clipNode.moveMode = moveMode; 218 219 if (clearClipboard) 220 be_clipboard->Clear(); 221 222 BMessage* clip = be_clipboard->Data(); 223 if (clip != NULL) { 224 for (int32 index = 0; index < listCount; index++) { 225 char refName[64], modeName[64]; 226 BPose* pose = (BPose*)list->ItemAt(index); 227 Model* model = pose->TargetModel(); 228 const node_ref* node = model->NodeRef(); 229 230 BEntry entry; 231 model->GetEntry(&entry); 232 if (model->IsVolume() 233 || model->IsRoot() 234 || model->IsTrash() 235 || model->IsDesktop()) 236 continue; 237 238 MakeRefName(refName, node); 239 MakeModeNameFromRefName(modeName, refName); 240 241 if (clearClipboard) { 242 if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) { 243 if (clip->AddRef(refName, model->EntryRef()) == B_OK) { 244 pose->SetClipboardMode(moveMode); 245 246 clipNode.node = *node; 247 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 248 &clipNode, sizeof(TClipboardNodeRef), true, 249 listCount); 250 251 refsAdded++; 252 } else 253 clip->RemoveName(modeName); 254 } 255 } else { 256 if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) { 257 // replace old mode if entry already exists in clipboard 258 if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) { 259 pose->SetClipboardMode(moveMode); 260 261 clipNode.node = *node; 262 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 263 &clipNode, sizeof(TClipboardNodeRef), true, 264 listCount); 265 266 refsAdded++; 267 } else { 268 clip->RemoveName(modeName); 269 270 clipNode.node = *node; 271 clipNode.moveMode = kDelete; // note removing node 272 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 273 &clipNode, sizeof(TClipboardNodeRef), true, 274 listCount); 275 clipNode.moveMode = moveMode; 276 // set it back to current value 277 } 278 } else { 279 // add it if it doesn't exist 280 if (clip->AddRef(refName, model->EntryRef()) == B_OK 281 && clip->AddInt32(modeName, (int32)moveMode) == B_OK) { 282 pose->SetClipboardMode(moveMode); 283 284 clipNode.node = *node; 285 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 286 &clipNode, sizeof(TClipboardNodeRef), true, 287 listCount); 288 289 refsAdded++; 290 } else { 291 clip->RemoveName(modeName); 292 clip->RemoveName(refName); 293 // here notifying delete isn't needed as node didn't 294 // exist in clipboard 295 } 296 } 297 } 298 } 299 be_clipboard->Commit(); 300 } 301 be_clipboard->Unlock(); 302 303 BMessenger(kTrackerSignature).SendMessage(&updateMessage); 304 // Tracker will notify all listeners 305 306 return refsAdded; 307 } 308 309 310 uint32 311 FSClipboardRemovePoses(const node_ref* directory, PoseList* list) 312 { 313 if (!be_clipboard->Lock()) 314 return 0; 315 316 // update message to be send to all listeners 317 BMessage updateMessage(kFSClipboardChanges); 318 updateMessage.AddInt32("device", directory->device); 319 updateMessage.AddInt64("directory", directory->node); 320 updateMessage.AddBool("clearClipboard", false); 321 322 TClipboardNodeRef clipNode; 323 clipNode.moveMode = kDelete; 324 325 uint32 refsRemoved = 0; 326 327 BMessage* clip = be_clipboard->Data(); 328 if (clip != NULL) { 329 int32 listCount = list->CountItems(); 330 331 for (int32 index = 0; index < listCount; index++) { 332 char refName[64], modeName[64]; 333 BPose* pose = (BPose*)list->ItemAt(index); 334 335 clipNode.node = *pose->TargetModel()->NodeRef(); 336 MakeRefName(refName, &clipNode.node); 337 MakeModeName(modeName); 338 339 if (clip->RemoveName(refName) == B_OK 340 && clip->RemoveName(modeName)) { 341 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, 342 sizeof(TClipboardNodeRef), true, listCount); 343 refsRemoved++; 344 } 345 } 346 be_clipboard->Commit(); 347 } 348 be_clipboard->Unlock(); 349 350 BMessenger(kTrackerSignature).SendMessage(&updateMessage); 351 // Tracker will notify all listeners 352 353 return refsRemoved; 354 } 355 356 357 /** Pastes entries from the clipboard to the target model's directory. 358 * Updates moveModes and notifies listeners if necessary. 359 */ 360 bool 361 FSClipboardPaste(Model* model, uint32 linksMode) 362 { 363 if (!FSClipboardHasRefs()) 364 return false; 365 366 BMessenger tracker(kTrackerSignature); 367 368 node_ref* destNodeRef = (node_ref*)model->NodeRef(); 369 370 // these will be passed to the asynchronous copy/move process 371 BObjectList<entry_ref>* moveList = new BObjectList<entry_ref>(0, true); 372 BObjectList<entry_ref>* copyList = new BObjectList<entry_ref>(0, true); 373 374 if ((be_clipboard->Lock())) { 375 BMessage* clip = be_clipboard->Data(); 376 if (clip != NULL) { 377 char modeName[64]; 378 uint32 moveMode = 0; 379 380 BMessage* updateMessage = NULL; 381 node_ref updateNodeRef; 382 updateNodeRef.device = -1; 383 384 char* refName; 385 type_code type; 386 int32 count; 387 for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index, 388 #ifdef B_BEOS_VERSION_DANO 389 (const char**) 390 #endif 391 &refName, &type, &count) == B_OK; index++) { 392 entry_ref ref; 393 if (clip->FindRef(refName, &ref) != B_OK) 394 continue; 395 396 // If the entry_ref's directory has changed, send previous notification 397 // (if any), and start new one for the new directory 398 if (updateNodeRef.device != ref.device 399 || updateNodeRef.node != ref.directory) { 400 if (updateMessage != NULL) { 401 tracker.SendMessage(updateMessage); 402 delete updateMessage; 403 } 404 405 updateNodeRef.device = ref.device; 406 updateNodeRef.node = ref.directory; 407 408 updateMessage = new BMessage(kFSClipboardChanges); 409 updateMessage->AddInt32("device", updateNodeRef.device); 410 updateMessage->AddInt64("directory", updateNodeRef.node); 411 } 412 413 // we need this data later on 414 MakeModeNameFromRefName(modeName, refName); 415 if (!linksMode && clip->FindInt32(modeName, (int32*)&moveMode) 416 != B_OK) { 417 continue; 418 } 419 420 BEntry entry(&ref); 421 422 uint32 newMoveMode = 0; 423 bool sameDirectory = destNodeRef->device == ref.device 424 && destNodeRef->node == ref.directory; 425 426 if (!entry.Exists()) { 427 // The entry doesn't exist anymore, so we'll remove 428 // that entry from the clipboard as well 429 clip->RemoveName(refName); 430 clip->RemoveName(modeName); 431 432 newMoveMode = kDelete; 433 } else { 434 // the entry does exist, so lets see what we will 435 // do with it 436 if (!sameDirectory) { 437 if (linksMode || moveMode == kMoveSelectionTo) { 438 // the linksMode uses the moveList as well 439 moveList->AddItem(new entry_ref(ref)); 440 } else if (moveMode == kCopySelectionTo) 441 copyList->AddItem(new entry_ref(ref)); 442 } 443 444 // if the entry should have been removed from its 445 // directory, we want to copy that entry next time, no 446 // matter if the items don't have to be moved at all 447 // (source == target) 448 if (moveMode == kMoveSelectionTo) 449 newMoveMode = kCopySelectionTo; 450 } 451 452 // add the change to the update message (if necessary) 453 if (newMoveMode) { 454 clip->ReplaceInt32(modeName, kCopySelectionTo); 455 456 TClipboardNodeRef clipNode; 457 MakeNodeFromName(&clipNode.node, modeName); 458 clipNode.moveMode = kDelete; 459 updateMessage->AddData("tcnode", T_CLIPBOARD_NODE, 460 &clipNode, sizeof(TClipboardNodeRef), true); 461 } 462 } 463 be_clipboard->Commit(); 464 465 // send notification for the last directory 466 if (updateMessage != NULL) { 467 tracker.SendMessage(updateMessage); 468 delete updateMessage; 469 } 470 } 471 be_clipboard->Unlock(); 472 } 473 474 bool okToMove = true; 475 476 // can't copy/paste to root('/') directory 477 if (model->IsRoot()) { 478 BAlert* alert = new BAlert("", 479 B_TRANSLATE("You must drop items on one of the disk icons " 480 "in the \"Disks\" window."), B_TRANSLATE("Cancel"), NULL, NULL, 481 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 482 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 483 alert->Go(); 484 okToMove = false; 485 } 486 487 BEntry entry; 488 model->GetEntry(&entry); 489 490 // can't copy items into the trash 491 if (copyList->CountItems() > 0 && model->IsTrash()) { 492 BAlert* alert = new BAlert("", 493 B_TRANSLATE("Sorry, you can't copy items to the Trash."), 494 B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL, 495 B_WARNING_ALERT); 496 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 497 alert->Go(); 498 okToMove = false; 499 } 500 501 if (!okToMove) { 502 // there was some problem with our target, so we bail out here 503 delete moveList; 504 delete copyList; 505 return false; 506 } 507 508 // asynchronous calls take over ownership of the objects passed to it 509 if (moveList->CountItems() > 0) { 510 FSMoveToFolder(moveList, new BEntry(entry), 511 linksMode ? linksMode : kMoveSelectionTo); 512 } else 513 delete moveList; 514 515 if (copyList->CountItems() > 0) 516 FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo); 517 else 518 delete copyList; 519 520 return true; 521 } 522 523 524 // Seek node in clipboard, if found return it's moveMode 525 // else return 0 526 uint32 527 FSClipboardFindNodeMode(Model* model, bool autoLock, bool updateRefIfNeeded) 528 { 529 int32 moveMode = 0; 530 if (autoLock) { 531 if (!be_clipboard->Lock()) 532 return 0; 533 } 534 bool remove = false; 535 bool change = false; 536 537 BMessage* clip = be_clipboard->Data(); 538 if (clip != NULL) { 539 const node_ref* node = model->NodeRef(); 540 char modeName[64]; 541 MakeModeName(modeName, node); 542 if ((clip->FindInt32(modeName, &moveMode) == B_OK)) { 543 const entry_ref* ref = model->EntryRef(); 544 entry_ref clipref; 545 char refName[64]; 546 MakeRefName(refName, node); 547 if ((clip->FindRef(refName, &clipref) == B_OK)) { 548 if (clipref != *ref) { 549 if (updateRefIfNeeded) { 550 clip->ReplaceRef(refName, ref); 551 change = true; 552 } else { 553 clip->RemoveName(refName); 554 clip->RemoveName(modeName); 555 change = true; 556 remove = true; 557 moveMode = 0; 558 } 559 } 560 } else { 561 clip->RemoveName(modeName); 562 change = true; 563 remove = true; 564 moveMode = 0; 565 } 566 } 567 } 568 if (change) 569 be_clipboard->Commit(); 570 571 if (autoLock) 572 be_clipboard->Unlock(); 573 574 if (remove) 575 FSClipboardRemove(model); 576 577 return (uint32)moveMode; 578 } 579 580 581 void 582 FSClipboardRemove(Model* model) 583 { 584 BMessenger messenger(kTrackerSignature); 585 if (messenger.IsValid()) { 586 BMessage* report = new BMessage(kFSClipboardChanges); 587 TClipboardNodeRef tcnode; 588 tcnode.node = *model->NodeRef(); 589 tcnode.moveMode = kDelete; 590 const entry_ref* ref = model->EntryRef(); 591 report->AddInt32("device", ref->device); 592 report->AddInt64("directory", ref->directory); 593 report->AddBool("clearClipboard", false); 594 report->AddData("tcnode", T_CLIPBOARD_NODE, &tcnode, sizeof(tcnode), 595 true); 596 messenger.SendMessage(report); 597 delete report; 598 } 599 } 600 601 602 // #pragma mark - 603 604 605 BClipboardRefsWatcher::BClipboardRefsWatcher() 606 : BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096), 607 fNotifyList(10, false) 608 { 609 watch_node(NULL, B_WATCH_MOUNT, this); 610 fRefsInClipboard = FSClipboardHasRefs(); 611 be_clipboard->StartWatching(this); 612 } 613 614 615 BClipboardRefsWatcher::~BClipboardRefsWatcher() 616 { 617 stop_watching(this); 618 be_clipboard->StopWatching(this); 619 } 620 621 622 void 623 BClipboardRefsWatcher::AddToNotifyList(BMessenger target) 624 { 625 if (Lock()) { 626 // add the messenger if it's not already in the list 627 // ToDo: why do we have to care about that? 628 BMessenger* messenger; 629 bool found = false; 630 631 for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL; 632 index++) { 633 if (*messenger == target) { 634 found = true; 635 break; 636 } 637 } 638 if (!found) 639 fNotifyList.AddItem(new BMessenger(target)); 640 641 Unlock(); 642 } 643 } 644 645 646 void 647 BClipboardRefsWatcher::RemoveFromNotifyList(BMessenger target) 648 { 649 if (Lock()) { 650 BMessenger* messenger; 651 652 for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL; 653 index++) { 654 if (*messenger == target) { 655 delete fNotifyList.RemoveItemAt(index); 656 break; 657 } 658 } 659 Unlock(); 660 } 661 } 662 663 664 void 665 BClipboardRefsWatcher::AddNode(const node_ref* node) 666 { 667 TTracker::WatchNode(node, B_WATCH_NAME, this); 668 fRefsInClipboard = true; 669 } 670 671 672 void 673 BClipboardRefsWatcher::RemoveNode(node_ref* node, bool removeFromClipboard) 674 { 675 watch_node(node, B_STOP_WATCHING, this); 676 677 if (!removeFromClipboard) 678 return; 679 680 if (be_clipboard->Lock()) { 681 BMessage* clip = be_clipboard->Data(); 682 if (clip != NULL) { 683 char name[64]; 684 MakeRefName(name, node); 685 clip->RemoveName(name); 686 MakeModeName(name); 687 clip->RemoveName(name); 688 689 be_clipboard->Commit(); 690 } 691 be_clipboard->Unlock(); 692 } 693 } 694 695 696 void 697 BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device) 698 { 699 if (!be_clipboard->Lock()) 700 return; 701 702 BMessage* clip = be_clipboard->Data(); 703 if (clip != NULL) { 704 char deviceName[6]; 705 sprintf(deviceName, "r%" B_PRIdDEV "_", device); 706 707 int32 index = 0; 708 char* refName; 709 type_code type; 710 int32 count; 711 while (clip->GetInfo(B_REF_TYPE, index, 712 #ifdef B_BEOS_VERSION_DANO 713 (const char**) 714 #endif 715 &refName, &type, &count) == B_OK) { 716 if (!strncmp(deviceName, refName, strlen(deviceName))) { 717 clip->RemoveName(refName); 718 MakeModeName(refName); 719 clip->RemoveName(refName); 720 721 node_ref node; 722 MakeNodeFromName(&node, refName); 723 watch_node(&node, B_STOP_WATCHING, this); 724 } 725 index++; 726 } 727 be_clipboard->Commit(); 728 } 729 be_clipboard->Unlock(); 730 } 731 732 733 void 734 BClipboardRefsWatcher::UpdateNode(node_ref* node, entry_ref* ref) 735 { 736 if (!be_clipboard->Lock()) 737 return; 738 739 BMessage* clip = be_clipboard->Data(); 740 if (clip != NULL) { 741 char name[64]; 742 MakeRefName(name, node); 743 if ((clip->ReplaceRef(name, ref)) != B_OK) { 744 clip->RemoveName(name); 745 MakeModeName(name); 746 clip->RemoveName(name); 747 748 RemoveNode(node); 749 } 750 be_clipboard->Commit(); 751 } 752 be_clipboard->Unlock(); 753 } 754 755 756 void 757 BClipboardRefsWatcher::Clear() 758 { 759 stop_watching(this); 760 watch_node(NULL, B_WATCH_MOUNT, this); 761 762 BMessage message(kFSClipboardChanges); 763 message.AddBool("clearClipboard", true); 764 if (Lock()) { 765 int32 items = fNotifyList.CountItems(); 766 for (int32 i = 0;i < items;i++) { 767 fNotifyList.ItemAt(i)->SendMessage(&message); 768 } 769 Unlock(); 770 } 771 } 772 773 774 //void 775 //BClipboardRefsWatcher::UpdatePoseViews(bool clearClipboard, 776 // const node_ref* node) 777 //{ 778 // BMessage message(kFSClipboardChanges); 779 // message.AddInt32("device", node->device); 780 // message.AddInt64("directory", node->node); 781 // message.AddBool("clearClipboard", clearClipboard); 782 // 783 // if (Lock()) { 784 // int32 items = fNotifyList.CountItems(); 785 // for (int32 i = 0;i < items;i++) { 786 // fNotifyList.ItemAt(i)->SendMessage(&message); 787 // } 788 // Unlock(); 789 // } 790 //} 791 792 793 void 794 BClipboardRefsWatcher::UpdatePoseViews(BMessage* reportMessage) 795 { 796 if (Lock()) { 797 // check if it was cleared, if so clear watching 798 bool clearClipboard = false; 799 if (reportMessage->FindBool("clearClipboard", &clearClipboard) == B_OK 800 && clearClipboard) { 801 stop_watching(this); 802 watch_node(NULL, B_WATCH_MOUNT, this); 803 } 804 805 // loop through reported node_ref's movemodes: 806 // move or copy: start watching node_ref 807 // remove: stop watching node_ref 808 int32 index = 0; 809 TClipboardNodeRef* tcnode = NULL; 810 ssize_t size; 811 while (reportMessage->FindData("tcnode", T_CLIPBOARD_NODE, index, 812 (const void**)&tcnode, &size) == B_OK) { 813 if (tcnode->moveMode == kDelete) { 814 watch_node(&tcnode->node, B_STOP_WATCHING, this); 815 } else { 816 watch_node(&tcnode->node, B_STOP_WATCHING, this); 817 TTracker::WatchNode(&tcnode->node, B_WATCH_NAME, this); 818 fRefsInClipboard = true; 819 } 820 index++; 821 } 822 823 // send report 824 int32 items = fNotifyList.CountItems(); 825 for (int32 i = 0;i < items;i++) { 826 fNotifyList.ItemAt(i)->SendMessage(reportMessage); 827 } 828 Unlock(); 829 } 830 } 831 832 833 void 834 BClipboardRefsWatcher::MessageReceived(BMessage* message) 835 { 836 if (message->what == B_CLIPBOARD_CHANGED && fRefsInClipboard) { 837 if (!(fRefsInClipboard = FSClipboardHasRefs())) 838 Clear(); 839 return; 840 } else if (message->what != B_NODE_MONITOR) { 841 _inherited::MessageReceived(message); 842 return; 843 } 844 845 switch (message->FindInt32("opcode")) { 846 case B_ENTRY_MOVED: 847 { 848 ino_t toDir; 849 ino_t fromDir; 850 node_ref node; 851 const char* name = NULL; 852 message->FindInt64("from directory", &fromDir); 853 message->FindInt64("to directory", &toDir); 854 message->FindInt64("node", &node.node); 855 message->FindInt32("device", &node.device); 856 message->FindString("name", &name); 857 entry_ref ref(node.device, toDir, name); 858 UpdateNode(&node, &ref); 859 break; 860 } 861 862 case B_DEVICE_UNMOUNTED: 863 { 864 dev_t device; 865 message->FindInt32("device", &device); 866 RemoveNodesByDevice(device); 867 break; 868 } 869 870 case B_ENTRY_REMOVED: 871 { 872 node_ref node; 873 message->FindInt64("node", &node.node); 874 message->FindInt32("device", &node.device); 875 RemoveNode(&node, true); 876 break; 877 } 878 } 879 } 880