RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / kits / tracker / FSClipboard.cpp
blobd0373180bd856f7105e485e457b48f41263b113f
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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..
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.
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.
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.
36 #include "FSClipboard.h"
38 #include <Clipboard.h>
39 #include <Alert.h>
40 #include <Catalog.h>
41 #include <Locale.h>
42 #include <NodeMonitor.h>
44 #include "Commands.h"
45 #include "FSUtils.h"
46 #include "Tracker.h"
49 // prototypes
50 static void MakeNodeFromName(node_ref* node, char* name);
51 static inline void MakeRefName(char* refName, const node_ref* node);
52 static inline void MakeModeName(char* modeName, const node_ref* node);
53 static inline void MakeModeNameFromRefName(char* modeName, char* refName);
54 static inline bool CompareModeAndRefName(const char* modeName,
55 const char* refName);
57 #if 0
58 static bool
59 FSClipboardCheckIntegrity()
61 return true;
63 #endif
65 static void
66 MakeNodeFromName(node_ref* node, char* name)
68 char* nodeString = strchr(name, '_');
69 if (nodeString != NULL) {
70 node->node = strtoll(nodeString + 1, (char**)NULL, 10);
71 node->device = atoi(name + 1);
76 static inline void
77 MakeRefName(char* refName, const node_ref* node)
79 sprintf(refName, "r%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node);
83 static inline void
84 MakeModeName(char* modeName, const node_ref* node)
86 sprintf(modeName, "m%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node);
90 static inline void
91 MakeModeName(char* name)
93 name[0] = 'm';
97 static inline void
98 MakeModeNameFromRefName(char* modeName, char* refName)
100 strcpy(modeName, refName);
101 modeName[0] = 'm';
105 static inline bool
106 CompareModeAndRefName(const char* modeName, const char* refName)
108 return !strcmp(refName + 1, modeName + 1);
112 // #pragma mark - FSClipBoard
115 #undef B_TRANSLATION_CONTEXT
116 #define B_TRANSLATION_CONTEXT "FSClipBoard"
119 bool
120 FSClipboardHasRefs()
122 bool result = false;
124 if (be_clipboard->Lock()) {
125 BMessage* clip = be_clipboard->Data();
126 if (clip != NULL) {
127 #ifdef B_BEOS_VERSION_DANO
128 const
129 #endif
130 char* refName;
131 #ifdef B_BEOS_VERSION_DANO
132 const
133 #endif
134 char* modeName;
135 uint32 type;
136 int32 count;
137 if (clip->GetInfo(B_REF_TYPE, 0, &refName, &type, &count) == B_OK
138 && clip->GetInfo(B_INT32_TYPE, 0, &modeName, &type, &count)
139 == B_OK) {
140 result = CompareModeAndRefName(modeName, refName);
143 be_clipboard->Unlock();
145 return result;
149 void
150 FSClipboardStartWatch(BMessenger target)
152 TTracker* tracker = dynamic_cast<TTracker*>(be_app);
153 if (tracker != NULL && tracker->ClipboardRefsWatcher() != NULL)
154 tracker->ClipboardRefsWatcher()->AddToNotifyList(target);
155 else {
156 // this code is used by external apps using objects using FSClipboard
157 // functions, i.e. applications using FilePanel
158 BMessenger messenger(kTrackerSignature);
159 if (messenger.IsValid()) {
160 BMessage message(kStartWatchClipboardRefs);
161 message.AddMessenger("target", target);
162 messenger.SendMessage(&message);
168 void
169 FSClipboardStopWatch(BMessenger target)
171 TTracker* tracker = dynamic_cast<TTracker*>(be_app);
172 if (tracker != NULL && tracker->ClipboardRefsWatcher() != NULL)
173 tracker->ClipboardRefsWatcher()->AddToNotifyList(target);
174 else {
175 // this code is used by external apps using objects using FSClipboard
176 // functions, i.e. applications using FilePanel
177 BMessenger messenger(kTrackerSignature);
178 if (messenger.IsValid()) {
179 BMessage message(kStopWatchClipboardRefs);
180 message.AddMessenger("target", target);
181 messenger.SendMessage(&message);
187 void
188 FSClipboardClear()
190 if (!be_clipboard->Lock())
191 return;
193 be_clipboard->Clear();
194 be_clipboard->Commit();
195 be_clipboard->Unlock();
199 /** This function adds the given poses list to the clipboard, for both copy
200 * and cut. All poses in the list must have "directory" as parent.
201 * "moveMode" is either kMoveSelection or kCopySelection.
202 * It will check if the entries are already present, so that there can only
203 * be one reference to them in the clipboard.
205 uint32
206 FSClipboardAddPoses(const node_ref* directory, PoseList* list,
207 uint32 moveMode, bool clearClipboard)
209 uint32 refsAdded = 0;
210 int32 listCount = list->CountItems();
212 if (listCount == 0 || !be_clipboard->Lock())
213 return 0;
215 // update message to be send to all listeners
216 BMessage updateMessage(kFSClipboardChanges);
217 updateMessage.AddInt32("device", directory->device);
218 updateMessage.AddInt64("directory", directory->node);
219 updateMessage.AddBool("clearClipboard", clearClipboard);
221 TClipboardNodeRef clipNode;
222 clipNode.moveMode = moveMode;
224 if (clearClipboard)
225 be_clipboard->Clear();
227 BMessage* clip = be_clipboard->Data();
228 if (clip != NULL) {
229 for (int32 index = 0; index < listCount; index++) {
230 char refName[64], modeName[64];
231 BPose* pose = (BPose*)list->ItemAt(index);
232 Model* model = pose->TargetModel();
233 const node_ref* node = model->NodeRef();
235 BEntry entry;
236 model->GetEntry(&entry);
237 if (model->IsVolume()
238 || model->IsRoot()
239 || model->IsTrash()
240 || model->IsDesktop())
241 continue;
243 MakeRefName(refName, node);
244 MakeModeNameFromRefName(modeName, refName);
246 if (clearClipboard) {
247 if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
248 if (clip->AddRef(refName, model->EntryRef()) == B_OK) {
249 pose->SetClipboardMode(moveMode);
251 clipNode.node = *node;
252 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
253 &clipNode, sizeof(TClipboardNodeRef), true,
254 listCount);
256 refsAdded++;
257 } else
258 clip->RemoveName(modeName);
260 } else {
261 if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) {
262 // replace old mode if entry already exists in clipboard
263 if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) {
264 pose->SetClipboardMode(moveMode);
266 clipNode.node = *node;
267 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
268 &clipNode, sizeof(TClipboardNodeRef), true,
269 listCount);
271 refsAdded++;
272 } else {
273 clip->RemoveName(modeName);
275 clipNode.node = *node;
276 clipNode.moveMode = kDelete; // note removing node
277 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
278 &clipNode, sizeof(TClipboardNodeRef), true,
279 listCount);
280 clipNode.moveMode = moveMode;
281 // set it back to current value
283 } else {
284 // add it if it doesn't exist
285 if (clip->AddRef(refName, model->EntryRef()) == B_OK
286 && clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
287 pose->SetClipboardMode(moveMode);
289 clipNode.node = *node;
290 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
291 &clipNode, sizeof(TClipboardNodeRef), true,
292 listCount);
294 refsAdded++;
295 } else {
296 clip->RemoveName(modeName);
297 clip->RemoveName(refName);
298 // here notifying delete isn't needed as node didn't
299 // exist in clipboard
304 be_clipboard->Commit();
306 be_clipboard->Unlock();
308 BMessenger(kTrackerSignature).SendMessage(&updateMessage);
309 // Tracker will notify all listeners
311 return refsAdded;
315 uint32
316 FSClipboardRemovePoses(const node_ref* directory, PoseList* list)
318 if (!be_clipboard->Lock())
319 return 0;
321 // update message to be send to all listeners
322 BMessage updateMessage(kFSClipboardChanges);
323 updateMessage.AddInt32("device", directory->device);
324 updateMessage.AddInt64("directory", directory->node);
325 updateMessage.AddBool("clearClipboard", false);
327 TClipboardNodeRef clipNode;
328 clipNode.moveMode = kDelete;
330 uint32 refsRemoved = 0;
332 BMessage* clip = be_clipboard->Data();
333 if (clip != NULL) {
334 int32 listCount = list->CountItems();
336 for (int32 index = 0; index < listCount; index++) {
337 char refName[64], modeName[64];
338 BPose* pose = (BPose*)list->ItemAt(index);
340 clipNode.node = *pose->TargetModel()->NodeRef();
341 MakeRefName(refName, &clipNode.node);
342 MakeModeName(modeName);
344 if (clip->RemoveName(refName) == B_OK
345 && clip->RemoveName(modeName)) {
346 updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode,
347 sizeof(TClipboardNodeRef), true, listCount);
348 refsRemoved++;
351 be_clipboard->Commit();
353 be_clipboard->Unlock();
355 BMessenger(kTrackerSignature).SendMessage(&updateMessage);
356 // Tracker will notify all listeners
358 return refsRemoved;
362 /** Pastes entries from the clipboard to the target model's directory.
363 * Updates moveModes and notifies listeners if necessary.
365 bool
366 FSClipboardPaste(Model* model, uint32 linksMode)
368 if (!FSClipboardHasRefs())
369 return false;
371 BMessenger tracker(kTrackerSignature);
373 node_ref* destNodeRef = (node_ref*)model->NodeRef();
375 // these will be passed to the asynchronous copy/move process
376 BObjectList<entry_ref>* moveList = new BObjectList<entry_ref>(0, true);
377 BObjectList<entry_ref>* copyList = new BObjectList<entry_ref>(0, true);
379 if ((be_clipboard->Lock())) {
380 BMessage* clip = be_clipboard->Data();
381 if (clip != NULL) {
382 char modeName[64];
383 uint32 moveMode = 0;
385 BMessage* updateMessage = NULL;
386 node_ref updateNodeRef;
387 updateNodeRef.device = -1;
389 char* refName;
390 type_code type;
391 int32 count;
392 for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index,
393 #ifdef B_BEOS_VERSION_DANO
394 (const char**)
395 #endif
396 &refName, &type, &count) == B_OK; index++) {
397 entry_ref ref;
398 if (clip->FindRef(refName, &ref) != B_OK)
399 continue;
401 // If the entry_ref's directory has changed, send previous notification
402 // (if any), and start new one for the new directory
403 if (updateNodeRef.device != ref.device
404 || updateNodeRef.node != ref.directory) {
405 if (updateMessage != NULL) {
406 tracker.SendMessage(updateMessage);
407 delete updateMessage;
410 updateNodeRef.device = ref.device;
411 updateNodeRef.node = ref.directory;
413 updateMessage = new BMessage(kFSClipboardChanges);
414 updateMessage->AddInt32("device", updateNodeRef.device);
415 updateMessage->AddInt64("directory", updateNodeRef.node);
418 // we need this data later on
419 MakeModeNameFromRefName(modeName, refName);
420 if (!linksMode && clip->FindInt32(modeName, (int32*)&moveMode)
421 != B_OK) {
422 continue;
425 BEntry entry(&ref);
427 uint32 newMoveMode = 0;
428 bool sameDirectory = destNodeRef->device == ref.device
429 && destNodeRef->node == ref.directory;
431 if (!entry.Exists()) {
432 // The entry doesn't exist anymore, so we'll remove
433 // that entry from the clipboard as well
434 clip->RemoveName(refName);
435 clip->RemoveName(modeName);
437 newMoveMode = kDelete;
438 } else {
439 // the entry does exist, so lets see what we will
440 // do with it
441 if (!sameDirectory) {
442 if (linksMode || moveMode == kMoveSelectionTo) {
443 // the linksMode uses the moveList as well
444 moveList->AddItem(new entry_ref(ref));
445 } else if (moveMode == kCopySelectionTo)
446 copyList->AddItem(new entry_ref(ref));
449 // if the entry should have been removed from its
450 // directory, we want to copy that entry next time, no
451 // matter if the items don't have to be moved at all
452 // (source == target)
453 if (moveMode == kMoveSelectionTo)
454 newMoveMode = kCopySelectionTo;
457 // add the change to the update message (if necessary)
458 if (newMoveMode) {
459 clip->ReplaceInt32(modeName, kCopySelectionTo);
461 TClipboardNodeRef clipNode;
462 MakeNodeFromName(&clipNode.node, modeName);
463 clipNode.moveMode = kDelete;
464 updateMessage->AddData("tcnode", T_CLIPBOARD_NODE,
465 &clipNode, sizeof(TClipboardNodeRef), true);
468 be_clipboard->Commit();
470 // send notification for the last directory
471 if (updateMessage != NULL) {
472 tracker.SendMessage(updateMessage);
473 delete updateMessage;
476 be_clipboard->Unlock();
479 bool okToMove = true;
481 // can't copy/paste to root('/') directory
482 if (model->IsRoot()) {
483 BAlert* alert = new BAlert("",
484 B_TRANSLATE("You must drop items on one of the disk icons "
485 "in the \"Disks\" window."), B_TRANSLATE("Cancel"), NULL, NULL,
486 B_WIDTH_AS_USUAL, B_WARNING_ALERT);
487 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
488 alert->Go();
489 okToMove = false;
492 BEntry entry;
493 model->GetEntry(&entry);
495 // can't copy items into the trash
496 if (copyList->CountItems() > 0 && model->IsTrash()) {
497 BAlert* alert = new BAlert("",
498 B_TRANSLATE("Sorry, you can't copy items to the Trash."),
499 B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL,
500 B_WARNING_ALERT);
501 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
502 alert->Go();
503 okToMove = false;
506 if (!okToMove) {
507 // there was some problem with our target, so we bail out here
508 delete moveList;
509 delete copyList;
510 return false;
513 // asynchronous calls take over ownership of the objects passed to it
514 if (moveList->CountItems() > 0) {
515 FSMoveToFolder(moveList, new BEntry(entry),
516 linksMode ? linksMode : kMoveSelectionTo);
517 } else
518 delete moveList;
520 if (copyList->CountItems() > 0)
521 FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo);
522 else
523 delete copyList;
525 return true;
529 // Seek node in clipboard, if found return it's moveMode
530 // else return 0
531 uint32
532 FSClipboardFindNodeMode(Model* model, bool autoLock, bool updateRefIfNeeded)
534 int32 moveMode = 0;
535 if (autoLock) {
536 if (!be_clipboard->Lock())
537 return 0;
539 bool remove = false;
540 bool change = false;
542 BMessage* clip = be_clipboard->Data();
543 if (clip != NULL) {
544 const node_ref* node = model->NodeRef();
545 char modeName[64];
546 MakeModeName(modeName, node);
547 if ((clip->FindInt32(modeName, &moveMode) == B_OK)) {
548 const entry_ref* ref = model->EntryRef();
549 entry_ref clipref;
550 char refName[64];
551 MakeRefName(refName, node);
552 if ((clip->FindRef(refName, &clipref) == B_OK)) {
553 if (clipref != *ref) {
554 if (updateRefIfNeeded) {
555 clip->ReplaceRef(refName, ref);
556 change = true;
557 } else {
558 clip->RemoveName(refName);
559 clip->RemoveName(modeName);
560 change = true;
561 remove = true;
562 moveMode = 0;
565 } else {
566 clip->RemoveName(modeName);
567 change = true;
568 remove = true;
569 moveMode = 0;
573 if (change)
574 be_clipboard->Commit();
576 if (autoLock)
577 be_clipboard->Unlock();
579 if (remove)
580 FSClipboardRemove(model);
582 return (uint32)moveMode;
586 void
587 FSClipboardRemove(Model* model)
589 BMessenger messenger(kTrackerSignature);
590 if (messenger.IsValid()) {
591 BMessage* report = new BMessage(kFSClipboardChanges);
592 TClipboardNodeRef tcnode;
593 tcnode.node = *model->NodeRef();
594 tcnode.moveMode = kDelete;
595 const entry_ref* ref = model->EntryRef();
596 report->AddInt32("device", ref->device);
597 report->AddInt64("directory", ref->directory);
598 report->AddBool("clearClipboard", false);
599 report->AddData("tcnode", T_CLIPBOARD_NODE, &tcnode, sizeof(tcnode),
600 true);
601 messenger.SendMessage(report);
602 delete report;
607 // #pragma mark -
610 BClipboardRefsWatcher::BClipboardRefsWatcher()
611 : BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096),
612 fNotifyList(10, false)
614 watch_node(NULL, B_WATCH_MOUNT, this);
615 fRefsInClipboard = FSClipboardHasRefs();
616 be_clipboard->StartWatching(this);
620 BClipboardRefsWatcher::~BClipboardRefsWatcher()
622 stop_watching(this);
623 be_clipboard->StopWatching(this);
627 void
628 BClipboardRefsWatcher::AddToNotifyList(BMessenger target)
630 if (Lock()) {
631 // add the messenger if it's not already in the list
632 // ToDo: why do we have to care about that?
633 BMessenger* messenger;
634 bool found = false;
636 for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL;
637 index++) {
638 if (*messenger == target) {
639 found = true;
640 break;
643 if (!found)
644 fNotifyList.AddItem(new BMessenger(target));
646 Unlock();
651 void
652 BClipboardRefsWatcher::RemoveFromNotifyList(BMessenger target)
654 if (Lock()) {
655 BMessenger* messenger;
657 for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL;
658 index++) {
659 if (*messenger == target) {
660 delete fNotifyList.RemoveItemAt(index);
661 break;
664 Unlock();
669 void
670 BClipboardRefsWatcher::AddNode(const node_ref* node)
672 TTracker::WatchNode(node, B_WATCH_NAME, this);
673 fRefsInClipboard = true;
677 void
678 BClipboardRefsWatcher::RemoveNode(node_ref* node, bool removeFromClipboard)
680 watch_node(node, B_STOP_WATCHING, this);
682 if (!removeFromClipboard)
683 return;
685 if (be_clipboard->Lock()) {
686 BMessage* clip = be_clipboard->Data();
687 if (clip != NULL) {
688 char name[64];
689 MakeRefName(name, node);
690 clip->RemoveName(name);
691 MakeModeName(name);
692 clip->RemoveName(name);
694 be_clipboard->Commit();
696 be_clipboard->Unlock();
701 void
702 BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device)
704 if (!be_clipboard->Lock())
705 return;
707 BMessage* clip = be_clipboard->Data();
708 if (clip != NULL) {
709 char deviceName[6];
710 sprintf(deviceName, "r%" B_PRIdDEV "_", device);
712 int32 index = 0;
713 char* refName;
714 type_code type;
715 int32 count;
716 while (clip->GetInfo(B_REF_TYPE, index,
717 #ifdef B_BEOS_VERSION_DANO
718 (const char**)
719 #endif
720 &refName, &type, &count) == B_OK) {
721 if (!strncmp(deviceName, refName, strlen(deviceName))) {
722 clip->RemoveName(refName);
723 MakeModeName(refName);
724 clip->RemoveName(refName);
726 node_ref node;
727 MakeNodeFromName(&node, refName);
728 watch_node(&node, B_STOP_WATCHING, this);
730 index++;
732 be_clipboard->Commit();
734 be_clipboard->Unlock();
738 void
739 BClipboardRefsWatcher::UpdateNode(node_ref* node, entry_ref* ref)
741 if (!be_clipboard->Lock())
742 return;
744 BMessage* clip = be_clipboard->Data();
745 if (clip != NULL) {
746 char name[64];
747 MakeRefName(name, node);
748 if ((clip->ReplaceRef(name, ref)) != B_OK) {
749 clip->RemoveName(name);
750 MakeModeName(name);
751 clip->RemoveName(name);
753 RemoveNode(node);
755 be_clipboard->Commit();
757 be_clipboard->Unlock();
761 void
762 BClipboardRefsWatcher::Clear()
764 stop_watching(this);
765 watch_node(NULL, B_WATCH_MOUNT, this);
767 BMessage message(kFSClipboardChanges);
768 message.AddBool("clearClipboard", true);
769 if (Lock()) {
770 int32 items = fNotifyList.CountItems();
771 for (int32 i = 0;i < items;i++) {
772 fNotifyList.ItemAt(i)->SendMessage(&message);
774 Unlock();
779 //void
780 //BClipboardRefsWatcher::UpdatePoseViews(bool clearClipboard,
781 // const node_ref* node)
783 // BMessage message(kFSClipboardChanges);
784 // message.AddInt32("device", node->device);
785 // message.AddInt64("directory", node->node);
786 // message.AddBool("clearClipboard", clearClipboard);
788 // if (Lock()) {
789 // int32 items = fNotifyList.CountItems();
790 // for (int32 i = 0;i < items;i++) {
791 // fNotifyList.ItemAt(i)->SendMessage(&message);
792 // }
793 // Unlock();
794 // }
798 void
799 BClipboardRefsWatcher::UpdatePoseViews(BMessage* reportMessage)
801 if (Lock()) {
802 // check if it was cleared, if so clear watching
803 bool clearClipboard = false;
804 if (reportMessage->FindBool("clearClipboard", &clearClipboard) == B_OK
805 && clearClipboard) {
806 stop_watching(this);
807 watch_node(NULL, B_WATCH_MOUNT, this);
810 // loop through reported node_ref's movemodes:
811 // move or copy: start watching node_ref
812 // remove: stop watching node_ref
813 int32 index = 0;
814 TClipboardNodeRef* tcnode = NULL;
815 ssize_t size;
816 while (reportMessage->FindData("tcnode", T_CLIPBOARD_NODE, index,
817 (const void**)&tcnode, &size) == B_OK) {
818 if (tcnode->moveMode == kDelete) {
819 watch_node(&tcnode->node, B_STOP_WATCHING, this);
820 } else {
821 watch_node(&tcnode->node, B_STOP_WATCHING, this);
822 TTracker::WatchNode(&tcnode->node, B_WATCH_NAME, this);
823 fRefsInClipboard = true;
825 index++;
828 // send report
829 int32 items = fNotifyList.CountItems();
830 for (int32 i = 0;i < items;i++) {
831 fNotifyList.ItemAt(i)->SendMessage(reportMessage);
833 Unlock();
838 void
839 BClipboardRefsWatcher::MessageReceived(BMessage* message)
841 if (message->what == B_CLIPBOARD_CHANGED && fRefsInClipboard) {
842 if (!(fRefsInClipboard = FSClipboardHasRefs()))
843 Clear();
844 return;
845 } else if (message->what != B_NODE_MONITOR) {
846 _inherited::MessageReceived(message);
847 return;
850 switch (message->FindInt32("opcode")) {
851 case B_ENTRY_MOVED:
853 ino_t toDir;
854 ino_t fromDir;
855 node_ref node;
856 const char* name = NULL;
857 message->FindInt64("from directory", &fromDir);
858 message->FindInt64("to directory", &toDir);
859 message->FindInt64("node", &node.node);
860 message->FindInt32("device", &node.device);
861 message->FindString("name", &name);
862 entry_ref ref(node.device, toDir, name);
863 UpdateNode(&node, &ref);
864 break;
867 case B_DEVICE_UNMOUNTED:
869 dev_t device;
870 message->FindInt32("device", &device);
871 RemoveNodesByDevice(device);
872 break;
875 case B_ENTRY_REMOVED:
877 node_ref node;
878 message->FindInt64("node", &node.node);
879 message->FindInt32("device", &node.device);
880 RemoveNode(&node, true);
881 break;