102be5353SAxel Dörfler /* 202be5353SAxel Dörfler Open Tracker License 302be5353SAxel Dörfler 402be5353SAxel Dörfler Terms and Conditions 502be5353SAxel Dörfler 602be5353SAxel Dörfler Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 702be5353SAxel Dörfler 802be5353SAxel Dörfler Permission is hereby granted, free of charge, to any person obtaining a copy of 902be5353SAxel Dörfler this software and associated documentation files (the "Software"), to deal in 1002be5353SAxel Dörfler the Software without restriction, including without limitation the rights to 1102be5353SAxel Dörfler use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 1202be5353SAxel Dörfler of the Software, and to permit persons to whom the Software is furnished to do 1302be5353SAxel Dörfler so, subject to the following conditions: 1402be5353SAxel Dörfler 1502be5353SAxel Dörfler The above copyright notice and this permission notice applies to all licensees 1602be5353SAxel Dörfler and shall be included in all copies or substantial portions of the Software.. 1702be5353SAxel Dörfler 1802be5353SAxel Dörfler THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1902be5353SAxel Dörfler IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 2002be5353SAxel Dörfler FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2102be5353SAxel Dörfler BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2202be5353SAxel Dörfler AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 2302be5353SAxel Dörfler WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2402be5353SAxel Dörfler 2502be5353SAxel Dörfler Except as contained in this notice, the name of Be Incorporated shall not be 2602be5353SAxel Dörfler used in advertising or otherwise to promote the sale, use or other dealings in 2702be5353SAxel Dörfler this Software without prior written authorization from Be Incorporated. 2802be5353SAxel Dörfler 2902be5353SAxel Dörfler Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 3002be5353SAxel Dörfler of Be Incorporated in the United States and other countries. Other brand product 3102be5353SAxel Dörfler names are registered trademarks or trademarks of their respective holders. 3202be5353SAxel Dörfler All rights reserved. 3302be5353SAxel Dörfler */ 3402be5353SAxel Dörfler 35*e2f6a01cSJohn Scipione 3602be5353SAxel Dörfler #include "FSClipboard.h" 37*e2f6a01cSJohn Scipione 3802be5353SAxel Dörfler #include <Clipboard.h> 3902be5353SAxel Dörfler #include <Alert.h> 404ed28a57SAlexandre Deckner #include <Catalog.h> 414ed28a57SAlexandre Deckner #include <Locale.h> 4202be5353SAxel Dörfler #include <NodeMonitor.h> 43*e2f6a01cSJohn Scipione 4402be5353SAxel Dörfler #include "Commands.h" 4502be5353SAxel Dörfler #include "FSUtils.h" 4602be5353SAxel Dörfler #include "Tracker.h" 4702be5353SAxel Dörfler 484ed28a57SAlexandre Deckner 4902be5353SAxel Dörfler // prototypes 5002be5353SAxel Dörfler static void MakeNodeFromName(node_ref* node, char* name); 5102be5353SAxel Dörfler static inline void MakeRefName(char* refName, const node_ref* node); 5202be5353SAxel Dörfler static inline void MakeModeName(char* modeName, const node_ref* node); 5302be5353SAxel Dörfler static inline void MakeModeNameFromRefName(char* modeName, char* refName); 54ea001e58SJohn Scipione static inline bool CompareModeAndRefName(const char* modeName, 55ea001e58SJohn Scipione const char* refName); 5602be5353SAxel Dörfler 5702be5353SAxel Dörfler /* 5802be5353SAxel Dörfler static bool 5902be5353SAxel Dörfler FSClipboardCheckIntegrity() 6002be5353SAxel Dörfler { 6102be5353SAxel Dörfler return true; 6202be5353SAxel Dörfler } 6302be5353SAxel Dörfler */ 6402be5353SAxel Dörfler 657befa79aSAxel Dörfler static void 667befa79aSAxel Dörfler MakeNodeFromName(node_ref* node, char* name) 677befa79aSAxel Dörfler { 687befa79aSAxel Dörfler char* nodeString = strchr(name, '_'); 697befa79aSAxel Dörfler if (nodeString != NULL) { 707befa79aSAxel Dörfler node->node = strtoll(nodeString + 1, (char**)NULL, 10); 717befa79aSAxel Dörfler node->device = atoi(name + 1); 727befa79aSAxel Dörfler } 737befa79aSAxel Dörfler } 747befa79aSAxel Dörfler 757befa79aSAxel Dörfler 767befa79aSAxel Dörfler static inline void 777befa79aSAxel Dörfler MakeRefName(char* refName, const node_ref* node) 787befa79aSAxel Dörfler { 79adf8818eSAlex Smith sprintf(refName, "r%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node); 807befa79aSAxel Dörfler } 817befa79aSAxel Dörfler 827befa79aSAxel Dörfler 837befa79aSAxel Dörfler static inline void 847befa79aSAxel Dörfler MakeModeName(char* modeName, const node_ref* node) 857befa79aSAxel Dörfler { 86adf8818eSAlex Smith sprintf(modeName, "m%" B_PRIdDEV "_%" B_PRIdINO, node->device, node->node); 877befa79aSAxel Dörfler } 887befa79aSAxel Dörfler 897befa79aSAxel Dörfler 907befa79aSAxel Dörfler static inline void 917befa79aSAxel Dörfler MakeModeName(char* name) 927befa79aSAxel Dörfler { 937befa79aSAxel Dörfler name[0] = 'm'; 947befa79aSAxel Dörfler } 957befa79aSAxel Dörfler 967befa79aSAxel Dörfler 977befa79aSAxel Dörfler static inline void 987befa79aSAxel Dörfler MakeModeNameFromRefName(char* modeName, char* refName) 997befa79aSAxel Dörfler { 1007befa79aSAxel Dörfler strcpy(modeName, refName); 1017befa79aSAxel Dörfler modeName[0] = 'm'; 1027befa79aSAxel Dörfler } 1037befa79aSAxel Dörfler 1047befa79aSAxel Dörfler 1057befa79aSAxel Dörfler static inline bool 1067befa79aSAxel Dörfler CompareModeAndRefName(const char* modeName, const char* refName) 1077befa79aSAxel Dörfler { 1087befa79aSAxel Dörfler return !strcmp(refName + 1, modeName + 1); 1097befa79aSAxel Dörfler } 1107befa79aSAxel Dörfler 1117befa79aSAxel Dörfler 112*e2f6a01cSJohn Scipione // #pragma mark - FSClipBoard 1137befa79aSAxel Dörfler 1147befa79aSAxel Dörfler 115546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 116546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "FSClipBoard" 1174ed28a57SAlexandre Deckner 118*e2f6a01cSJohn Scipione 11902be5353SAxel Dörfler bool 12002be5353SAxel Dörfler FSClipboardHasRefs() 12102be5353SAxel Dörfler { 12202be5353SAxel Dörfler bool result = false; 12302be5353SAxel Dörfler 12402be5353SAxel Dörfler if (be_clipboard->Lock()) { 12502be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 12602be5353SAxel Dörfler if (clip != NULL) { 12702be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO 12802be5353SAxel Dörfler const 12902be5353SAxel Dörfler #endif 13002be5353SAxel Dörfler char* refName; 13102be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO 13202be5353SAxel Dörfler const 13302be5353SAxel Dörfler #endif 13402be5353SAxel Dörfler char* modeName; 13502be5353SAxel Dörfler uint32 type; 13602be5353SAxel Dörfler int32 count; 13702be5353SAxel Dörfler if (clip->GetInfo(B_REF_TYPE, 0, &refName, &type, &count) == B_OK 138ea001e58SJohn Scipione && clip->GetInfo(B_INT32_TYPE, 0, &modeName, &type, &count) 139ea001e58SJohn Scipione == B_OK) { 14002be5353SAxel Dörfler result = CompareModeAndRefName(modeName, refName); 14102be5353SAxel Dörfler } 142ea001e58SJohn Scipione } 14302be5353SAxel Dörfler be_clipboard->Unlock(); 14402be5353SAxel Dörfler } 14502be5353SAxel Dörfler return result; 14602be5353SAxel Dörfler } 14702be5353SAxel Dörfler 14802be5353SAxel Dörfler 14902be5353SAxel Dörfler void 15002be5353SAxel Dörfler FSClipboardStartWatch(BMessenger target) 15102be5353SAxel Dörfler { 15202be5353SAxel Dörfler if (dynamic_cast<TTracker*>(be_app) != NULL) 15302be5353SAxel Dörfler ((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target); 15402be5353SAxel Dörfler else { 155ea001e58SJohn Scipione // this code is used by external apps using objects using FSClipboard 156ea001e58SJohn Scipione // functions, i.e. applications using FilePanel 15702be5353SAxel Dörfler BMessenger messenger(kTrackerSignature); 15802be5353SAxel Dörfler if (messenger.IsValid()) { 15902be5353SAxel Dörfler BMessage message(kStartWatchClipboardRefs); 16002be5353SAxel Dörfler message.AddMessenger("target", target); 16102be5353SAxel Dörfler messenger.SendMessage(&message); 16202be5353SAxel Dörfler } 16302be5353SAxel Dörfler } 16402be5353SAxel Dörfler } 16502be5353SAxel Dörfler 16602be5353SAxel Dörfler 16702be5353SAxel Dörfler void 16802be5353SAxel Dörfler FSClipboardStopWatch(BMessenger target) 16902be5353SAxel Dörfler { 17002be5353SAxel Dörfler if (dynamic_cast<TTracker*>(be_app) != NULL) 17102be5353SAxel Dörfler ((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target); 17202be5353SAxel Dörfler else { 173ea001e58SJohn Scipione // this code is used by external apps using objects using FSClipboard 174ea001e58SJohn Scipione // functions, i.e. applications using FilePanel 17502be5353SAxel Dörfler BMessenger messenger(kTrackerSignature); 17602be5353SAxel Dörfler if (messenger.IsValid()) { 17702be5353SAxel Dörfler BMessage message(kStopWatchClipboardRefs); 17802be5353SAxel Dörfler message.AddMessenger("target", target); 17902be5353SAxel Dörfler messenger.SendMessage(&message); 18002be5353SAxel Dörfler } 18102be5353SAxel Dörfler } 18202be5353SAxel Dörfler } 18302be5353SAxel Dörfler 18402be5353SAxel Dörfler 18502be5353SAxel Dörfler void 18602be5353SAxel Dörfler FSClipboardClear() 18702be5353SAxel Dörfler { 18802be5353SAxel Dörfler if (!be_clipboard->Lock()) 18902be5353SAxel Dörfler return; 19002be5353SAxel Dörfler 19102be5353SAxel Dörfler be_clipboard->Clear(); 19202be5353SAxel Dörfler be_clipboard->Commit(); 19302be5353SAxel Dörfler be_clipboard->Unlock(); 19402be5353SAxel Dörfler } 19502be5353SAxel Dörfler 19602be5353SAxel Dörfler 19702be5353SAxel Dörfler /** This function adds the given poses list to the clipboard, for both copy 19802be5353SAxel Dörfler * and cut. All poses in the list must have "directory" as parent. 19902be5353SAxel Dörfler * "moveMode" is either kMoveSelection or kCopySelection. 20002be5353SAxel Dörfler * It will check if the entries are already present, so that there can only 20102be5353SAxel Dörfler * be one reference to them in the clipboard. 20202be5353SAxel Dörfler */ 20302be5353SAxel Dörfler uint32 204a51764c5SJohn Scipione FSClipboardAddPoses(const node_ref* directory, PoseList* list, 205a51764c5SJohn Scipione uint32 moveMode, bool clearClipboard) 20602be5353SAxel Dörfler { 20702be5353SAxel Dörfler uint32 refsAdded = 0; 20802be5353SAxel Dörfler int32 listCount = list->CountItems(); 20902be5353SAxel Dörfler 21002be5353SAxel Dörfler if (listCount == 0 || !be_clipboard->Lock()) 21102be5353SAxel Dörfler return 0; 21202be5353SAxel Dörfler 21302be5353SAxel Dörfler // update message to be send to all listeners 21402be5353SAxel Dörfler BMessage updateMessage(kFSClipboardChanges); 21502be5353SAxel Dörfler updateMessage.AddInt32("device", directory->device); 21602be5353SAxel Dörfler updateMessage.AddInt64("directory", directory->node); 21702be5353SAxel Dörfler updateMessage.AddBool("clearClipboard", clearClipboard); 21802be5353SAxel Dörfler 21902be5353SAxel Dörfler TClipboardNodeRef clipNode; 22002be5353SAxel Dörfler clipNode.moveMode = moveMode; 22102be5353SAxel Dörfler 22202be5353SAxel Dörfler if (clearClipboard) 22302be5353SAxel Dörfler be_clipboard->Clear(); 22402be5353SAxel Dörfler 22502be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 22602be5353SAxel Dörfler if (clip != NULL) { 22702be5353SAxel Dörfler for (int32 index = 0; index < listCount; index++) { 22802be5353SAxel Dörfler char refName[64], modeName[64]; 22902be5353SAxel Dörfler BPose* pose = (BPose*)list->ItemAt(index); 23002be5353SAxel Dörfler Model* model = pose->TargetModel(); 23102be5353SAxel Dörfler const node_ref* node = model->NodeRef(); 23202be5353SAxel Dörfler 23302be5353SAxel Dörfler BEntry entry; 23402be5353SAxel Dörfler model->GetEntry(&entry); 23502be5353SAxel Dörfler if (model->IsVolume() 23602be5353SAxel Dörfler || model->IsRoot() 237d9626569SRene Gollent || model->IsTrash() 23889af0548SRene Gollent || model->IsDesktop()) 23902be5353SAxel Dörfler continue; 24002be5353SAxel Dörfler 24102be5353SAxel Dörfler MakeRefName(refName, node); 24202be5353SAxel Dörfler MakeModeNameFromRefName(modeName, refName); 24302be5353SAxel Dörfler 24402be5353SAxel Dörfler if (clearClipboard) { 2455422febdSStephan Aßmus if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) { 24602be5353SAxel Dörfler if (clip->AddRef(refName, model->EntryRef()) == B_OK) { 24702be5353SAxel Dörfler pose->SetClipboardMode(moveMode); 24802be5353SAxel Dörfler 24902be5353SAxel Dörfler clipNode.node = *node; 2505422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 2515422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true, 2525422febdSStephan Aßmus listCount); 25302be5353SAxel Dörfler 25402be5353SAxel Dörfler refsAdded++; 25502be5353SAxel Dörfler } else 25602be5353SAxel Dörfler clip->RemoveName(modeName); 2575422febdSStephan Aßmus } 25802be5353SAxel Dörfler } else { 25902be5353SAxel Dörfler if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) { 26002be5353SAxel Dörfler // replace old mode if entry already exists in clipboard 26102be5353SAxel Dörfler if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) { 26202be5353SAxel Dörfler pose->SetClipboardMode(moveMode); 26302be5353SAxel Dörfler 26402be5353SAxel Dörfler clipNode.node = *node; 2655422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 2665422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true, 2675422febdSStephan Aßmus listCount); 26802be5353SAxel Dörfler 26902be5353SAxel Dörfler refsAdded++; 27002be5353SAxel Dörfler } else { 27102be5353SAxel Dörfler clip->RemoveName(modeName); 27202be5353SAxel Dörfler 27302be5353SAxel Dörfler clipNode.node = *node; 27402be5353SAxel Dörfler clipNode.moveMode = kDelete; // note removing node 2755422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 2765422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true, 2775422febdSStephan Aßmus listCount); 2785422febdSStephan Aßmus clipNode.moveMode = moveMode; 2795422febdSStephan Aßmus // set it back to current value 28002be5353SAxel Dörfler } 28102be5353SAxel Dörfler } else { 2827befa79aSAxel Dörfler // add it if it doesn't exist 28302be5353SAxel Dörfler if (clip->AddRef(refName, model->EntryRef()) == B_OK 28402be5353SAxel Dörfler && clip->AddInt32(modeName, (int32)moveMode) == B_OK) { 28502be5353SAxel Dörfler pose->SetClipboardMode(moveMode); 28602be5353SAxel Dörfler 28702be5353SAxel Dörfler clipNode.node = *node; 2885422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, 2895422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true, 2905422febdSStephan Aßmus listCount); 29102be5353SAxel Dörfler 29202be5353SAxel Dörfler refsAdded++; 29302be5353SAxel Dörfler } else { 29402be5353SAxel Dörfler clip->RemoveName(modeName); 29502be5353SAxel Dörfler clip->RemoveName(refName); 2967befa79aSAxel Dörfler // here notifying delete isn't needed as node didn't 2977befa79aSAxel Dörfler // exist in clipboard 29802be5353SAxel Dörfler } 29902be5353SAxel Dörfler } 30002be5353SAxel Dörfler } 30102be5353SAxel Dörfler } 30202be5353SAxel Dörfler be_clipboard->Commit(); 30302be5353SAxel Dörfler } 30402be5353SAxel Dörfler be_clipboard->Unlock(); 30502be5353SAxel Dörfler 30602be5353SAxel Dörfler BMessenger(kTrackerSignature).SendMessage(&updateMessage); 30702be5353SAxel Dörfler // Tracker will notify all listeners 30802be5353SAxel Dörfler 30902be5353SAxel Dörfler return refsAdded; 31002be5353SAxel Dörfler } 31102be5353SAxel Dörfler 31202be5353SAxel Dörfler 31302be5353SAxel Dörfler uint32 31402be5353SAxel Dörfler FSClipboardRemovePoses(const node_ref* directory, PoseList* list) 31502be5353SAxel Dörfler { 31602be5353SAxel Dörfler if (!be_clipboard->Lock()) 31702be5353SAxel Dörfler return 0; 31802be5353SAxel Dörfler 31902be5353SAxel Dörfler // update message to be send to all listeners 32002be5353SAxel Dörfler BMessage updateMessage(kFSClipboardChanges); 32102be5353SAxel Dörfler updateMessage.AddInt32("device", directory->device); 32202be5353SAxel Dörfler updateMessage.AddInt64("directory", directory->node); 32302be5353SAxel Dörfler updateMessage.AddBool("clearClipboard", false); 32402be5353SAxel Dörfler 32502be5353SAxel Dörfler TClipboardNodeRef clipNode; 32602be5353SAxel Dörfler clipNode.moveMode = kDelete; 32702be5353SAxel Dörfler 32802be5353SAxel Dörfler uint32 refsRemoved = 0; 32902be5353SAxel Dörfler 33002be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 33102be5353SAxel Dörfler if (clip != NULL) { 33202be5353SAxel Dörfler int32 listCount = list->CountItems(); 33302be5353SAxel Dörfler 33402be5353SAxel Dörfler for (int32 index = 0; index < listCount; index++) { 33502be5353SAxel Dörfler char refName[64], modeName[64]; 33602be5353SAxel Dörfler BPose* pose = (BPose*)list->ItemAt(index); 33702be5353SAxel Dörfler 33802be5353SAxel Dörfler clipNode.node = *pose->TargetModel()->NodeRef(); 33902be5353SAxel Dörfler MakeRefName(refName, &clipNode.node); 34002be5353SAxel Dörfler MakeModeName(modeName); 34102be5353SAxel Dörfler 342ea001e58SJohn Scipione if (clip->RemoveName(refName) == B_OK 343ea001e58SJohn Scipione && clip->RemoveName(modeName)) { 34402be5353SAxel Dörfler updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode, 34502be5353SAxel Dörfler sizeof(TClipboardNodeRef), true, listCount); 34602be5353SAxel Dörfler refsRemoved++; 34702be5353SAxel Dörfler } 34802be5353SAxel Dörfler } 34902be5353SAxel Dörfler be_clipboard->Commit(); 35002be5353SAxel Dörfler } 35102be5353SAxel Dörfler be_clipboard->Unlock(); 35202be5353SAxel Dörfler 35302be5353SAxel Dörfler BMessenger(kTrackerSignature).SendMessage(&updateMessage); 35402be5353SAxel Dörfler // Tracker will notify all listeners 35502be5353SAxel Dörfler 35602be5353SAxel Dörfler return refsRemoved; 35702be5353SAxel Dörfler } 35802be5353SAxel Dörfler 35902be5353SAxel Dörfler 36002be5353SAxel Dörfler /** Pastes entries from the clipboard to the target model's directory. 36102be5353SAxel Dörfler * Updates moveModes and notifies listeners if necessary. 36202be5353SAxel Dörfler */ 36302be5353SAxel Dörfler bool 36402be5353SAxel Dörfler FSClipboardPaste(Model* model, uint32 linksMode) 36502be5353SAxel Dörfler { 36602be5353SAxel Dörfler if (!FSClipboardHasRefs()) 36702be5353SAxel Dörfler return false; 36802be5353SAxel Dörfler 36902be5353SAxel Dörfler BMessenger tracker(kTrackerSignature); 37002be5353SAxel Dörfler 37102be5353SAxel Dörfler node_ref* destNodeRef = (node_ref*)model->NodeRef(); 37202be5353SAxel Dörfler 37302be5353SAxel Dörfler // these will be passed to the asynchronous copy/move process 37402be5353SAxel Dörfler BObjectList<entry_ref>* moveList = new BObjectList<entry_ref>(0, true); 37502be5353SAxel Dörfler BObjectList<entry_ref>* copyList = new BObjectList<entry_ref>(0, true); 37602be5353SAxel Dörfler 37702be5353SAxel Dörfler if ((be_clipboard->Lock())) { 37802be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 37902be5353SAxel Dörfler if (clip != NULL) { 38002be5353SAxel Dörfler char modeName[64]; 38102be5353SAxel Dörfler uint32 moveMode = 0; 38202be5353SAxel Dörfler 38302be5353SAxel Dörfler BMessage* updateMessage = NULL; 38402be5353SAxel Dörfler node_ref updateNodeRef; 38502be5353SAxel Dörfler updateNodeRef.device = -1; 38602be5353SAxel Dörfler 38702be5353SAxel Dörfler char* refName; 38802be5353SAxel Dörfler type_code type; 38902be5353SAxel Dörfler int32 count; 39002be5353SAxel Dörfler for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index, 39102be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO 39202be5353SAxel Dörfler (const char**) 39302be5353SAxel Dörfler #endif 39402be5353SAxel Dörfler &refName, &type, &count) == B_OK; index++) { 39502be5353SAxel Dörfler entry_ref ref; 39602be5353SAxel Dörfler if (clip->FindRef(refName, &ref) != B_OK) 39702be5353SAxel Dörfler continue; 39802be5353SAxel Dörfler 39902be5353SAxel Dörfler // If the entry_ref's directory has changed, send previous notification 40002be5353SAxel Dörfler // (if any), and start new one for the new directory 40102be5353SAxel Dörfler if (updateNodeRef.device != ref.device 40202be5353SAxel Dörfler || updateNodeRef.node != ref.directory) { 40302be5353SAxel Dörfler if (updateMessage != NULL) { 40402be5353SAxel Dörfler tracker.SendMessage(updateMessage); 40502be5353SAxel Dörfler delete updateMessage; 40602be5353SAxel Dörfler } 40702be5353SAxel Dörfler 40802be5353SAxel Dörfler updateNodeRef.device = ref.device; 40902be5353SAxel Dörfler updateNodeRef.node = ref.directory; 41002be5353SAxel Dörfler 41102be5353SAxel Dörfler updateMessage = new BMessage(kFSClipboardChanges); 41202be5353SAxel Dörfler updateMessage->AddInt32("device", updateNodeRef.device); 41302be5353SAxel Dörfler updateMessage->AddInt64("directory", updateNodeRef.node); 41402be5353SAxel Dörfler } 41502be5353SAxel Dörfler 41602be5353SAxel Dörfler // we need this data later on 41702be5353SAxel Dörfler MakeModeNameFromRefName(modeName, refName); 418a51764c5SJohn Scipione if (!linksMode && clip->FindInt32(modeName, (int32*)&moveMode) 419a51764c5SJohn Scipione != B_OK) { 42002be5353SAxel Dörfler continue; 421a51764c5SJohn Scipione } 42202be5353SAxel Dörfler 42302be5353SAxel Dörfler BEntry entry(&ref); 42402be5353SAxel Dörfler 42502be5353SAxel Dörfler uint32 newMoveMode = 0; 426a51764c5SJohn Scipione bool sameDirectory = destNodeRef->device == ref.device 427a51764c5SJohn Scipione && destNodeRef->node == ref.directory; 42802be5353SAxel Dörfler 42902be5353SAxel Dörfler if (!entry.Exists()) { 43002be5353SAxel Dörfler // The entry doesn't exist anymore, so we'll remove 43102be5353SAxel Dörfler // that entry from the clipboard as well 43202be5353SAxel Dörfler clip->RemoveName(refName); 43302be5353SAxel Dörfler clip->RemoveName(modeName); 43402be5353SAxel Dörfler 43502be5353SAxel Dörfler newMoveMode = kDelete; 43602be5353SAxel Dörfler } else { 43702be5353SAxel Dörfler // the entry does exist, so lets see what we will 43802be5353SAxel Dörfler // do with it 43902be5353SAxel Dörfler if (!sameDirectory) { 44002be5353SAxel Dörfler if (linksMode || moveMode == kMoveSelectionTo) { 44102be5353SAxel Dörfler // the linksMode uses the moveList as well 44202be5353SAxel Dörfler moveList->AddItem(new entry_ref(ref)); 44302be5353SAxel Dörfler } else if (moveMode == kCopySelectionTo) 44402be5353SAxel Dörfler copyList->AddItem(new entry_ref(ref)); 44502be5353SAxel Dörfler } 44602be5353SAxel Dörfler 447a51764c5SJohn Scipione // if the entry should have been removed from its 448a51764c5SJohn Scipione // directory, we want to copy that entry next time, no 449a51764c5SJohn Scipione // matter if the items don't have to be moved at all 450a51764c5SJohn Scipione // (source == target) 45102be5353SAxel Dörfler if (moveMode == kMoveSelectionTo) 45202be5353SAxel Dörfler newMoveMode = kCopySelectionTo; 45302be5353SAxel Dörfler } 45402be5353SAxel Dörfler 45502be5353SAxel Dörfler // add the change to the update message (if necessary) 45602be5353SAxel Dörfler if (newMoveMode) { 45702be5353SAxel Dörfler clip->ReplaceInt32(modeName, kCopySelectionTo); 45802be5353SAxel Dörfler 45902be5353SAxel Dörfler TClipboardNodeRef clipNode; 46002be5353SAxel Dörfler MakeNodeFromName(&clipNode.node, modeName); 46102be5353SAxel Dörfler clipNode.moveMode = kDelete; 462a51764c5SJohn Scipione updateMessage->AddData("tcnode", T_CLIPBOARD_NODE, 463a51764c5SJohn Scipione &clipNode, sizeof(TClipboardNodeRef), true); 46402be5353SAxel Dörfler } 46502be5353SAxel Dörfler } 46602be5353SAxel Dörfler be_clipboard->Commit(); 46702be5353SAxel Dörfler 46802be5353SAxel Dörfler // send notification for the last directory 46902be5353SAxel Dörfler if (updateMessage != NULL) { 47002be5353SAxel Dörfler tracker.SendMessage(updateMessage); 47102be5353SAxel Dörfler delete updateMessage; 47202be5353SAxel Dörfler } 47302be5353SAxel Dörfler } 47402be5353SAxel Dörfler be_clipboard->Unlock(); 47502be5353SAxel Dörfler } 47602be5353SAxel Dörfler 47702be5353SAxel Dörfler bool okToMove = true; 47802be5353SAxel Dörfler 47902be5353SAxel Dörfler // can't copy/paste to root('/') directory 48002be5353SAxel Dörfler if (model->IsRoot()) { 4814ed28a57SAlexandre Deckner BAlert* alert = new BAlert("", 4824ed28a57SAlexandre Deckner B_TRANSLATE("You must drop items on one of the disk icons " 4834ed28a57SAlexandre Deckner "in the \"Disks\" window."), B_TRANSLATE("Cancel"), NULL, NULL, 4844ed28a57SAlexandre Deckner B_WIDTH_AS_USUAL, B_WARNING_ALERT); 485aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 486019f90e6SJonas Sundström alert->Go(); 48702be5353SAxel Dörfler okToMove = false; 48802be5353SAxel Dörfler } 48902be5353SAxel Dörfler 49002be5353SAxel Dörfler BEntry entry; 49102be5353SAxel Dörfler model->GetEntry(&entry); 49202be5353SAxel Dörfler 49302be5353SAxel Dörfler // can't copy items into the trash 494d9626569SRene Gollent if (copyList->CountItems() > 0 && model->IsTrash()) { 4954ed28a57SAlexandre Deckner BAlert* alert = new BAlert("", 4964ed28a57SAlexandre Deckner B_TRANSLATE("Sorry, you can't copy items to the Trash."), 4974ed28a57SAlexandre Deckner B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL, 4984ed28a57SAlexandre Deckner B_WARNING_ALERT); 499aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 500019f90e6SJonas Sundström alert->Go(); 50102be5353SAxel Dörfler okToMove = false; 50202be5353SAxel Dörfler } 50302be5353SAxel Dörfler 50402be5353SAxel Dörfler if (!okToMove) { 50502be5353SAxel Dörfler // there was some problem with our target, so we bail out here 50602be5353SAxel Dörfler delete moveList; 50702be5353SAxel Dörfler delete copyList; 50802be5353SAxel Dörfler return false; 50902be5353SAxel Dörfler } 51002be5353SAxel Dörfler 51102be5353SAxel Dörfler // asynchronous calls take over ownership of the objects passed to it 512a51764c5SJohn Scipione if (moveList->CountItems() > 0) { 513a51764c5SJohn Scipione FSMoveToFolder(moveList, new BEntry(entry), 514a51764c5SJohn Scipione linksMode ? linksMode : kMoveSelectionTo); 515a51764c5SJohn Scipione } else 51602be5353SAxel Dörfler delete moveList; 51702be5353SAxel Dörfler 51802be5353SAxel Dörfler if (copyList->CountItems() > 0) 51902be5353SAxel Dörfler FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo); 52002be5353SAxel Dörfler else 52102be5353SAxel Dörfler delete copyList; 52202be5353SAxel Dörfler 52302be5353SAxel Dörfler return true; 52402be5353SAxel Dörfler } 52502be5353SAxel Dörfler 52602be5353SAxel Dörfler 527b05aa8b5SJohn Scipione // Seek node in clipboard, if found return it's moveMode 528b05aa8b5SJohn Scipione // else return 0 52902be5353SAxel Dörfler uint32 53095da0645SRene Gollent FSClipboardFindNodeMode(Model* model, bool autoLock, bool updateRefIfNeeded) 53102be5353SAxel Dörfler { 53202be5353SAxel Dörfler int32 moveMode = 0; 53395da0645SRene Gollent if (autoLock) { 53495da0645SRene Gollent if (!be_clipboard->Lock()) 53595da0645SRene Gollent return 0; 53695da0645SRene Gollent } 53702be5353SAxel Dörfler bool remove = false; 53802be5353SAxel Dörfler bool change = false; 53902be5353SAxel Dörfler 54002be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 54102be5353SAxel Dörfler if (clip != NULL) { 54202be5353SAxel Dörfler const node_ref* node = model->NodeRef(); 54302be5353SAxel Dörfler char modeName[64]; 54402be5353SAxel Dörfler MakeModeName(modeName, node); 54502be5353SAxel Dörfler if ((clip->FindInt32(modeName, &moveMode) == B_OK)) { 54602be5353SAxel Dörfler const entry_ref* ref = model->EntryRef(); 54702be5353SAxel Dörfler entry_ref clipref; 54802be5353SAxel Dörfler char refName[64]; 54902be5353SAxel Dörfler MakeRefName(refName, node); 55002be5353SAxel Dörfler if ((clip->FindRef(refName, &clipref) == B_OK)) { 55102be5353SAxel Dörfler if (clipref != *ref) { 55202be5353SAxel Dörfler if (updateRefIfNeeded) { 55302be5353SAxel Dörfler clip->ReplaceRef(refName, ref); 55402be5353SAxel Dörfler change = true; 55502be5353SAxel Dörfler } else { 55602be5353SAxel Dörfler clip->RemoveName(refName); 55702be5353SAxel Dörfler clip->RemoveName(modeName); 55802be5353SAxel Dörfler change = true; 55902be5353SAxel Dörfler remove = true; 56002be5353SAxel Dörfler moveMode = 0; 56102be5353SAxel Dörfler } 56202be5353SAxel Dörfler } 56302be5353SAxel Dörfler } else { 56402be5353SAxel Dörfler clip->RemoveName(modeName); 56502be5353SAxel Dörfler change = true; 56602be5353SAxel Dörfler remove = true; 56702be5353SAxel Dörfler moveMode = 0; 56802be5353SAxel Dörfler } 56902be5353SAxel Dörfler } 57002be5353SAxel Dörfler } 57102be5353SAxel Dörfler if (change) 57202be5353SAxel Dörfler be_clipboard->Commit(); 57302be5353SAxel Dörfler 57495da0645SRene Gollent if (autoLock) 57502be5353SAxel Dörfler be_clipboard->Unlock(); 57602be5353SAxel Dörfler 57702be5353SAxel Dörfler if (remove) 57802be5353SAxel Dörfler FSClipboardRemove(model); 57902be5353SAxel Dörfler 58002be5353SAxel Dörfler return (uint32)moveMode; 58102be5353SAxel Dörfler } 58202be5353SAxel Dörfler 58302be5353SAxel Dörfler 58402be5353SAxel Dörfler void 58502be5353SAxel Dörfler FSClipboardRemove(Model* model) 58602be5353SAxel Dörfler { 58702be5353SAxel Dörfler BMessenger messenger(kTrackerSignature); 58802be5353SAxel Dörfler if (messenger.IsValid()) { 58902be5353SAxel Dörfler BMessage* report = new BMessage(kFSClipboardChanges); 59002be5353SAxel Dörfler TClipboardNodeRef tcnode; 59102be5353SAxel Dörfler tcnode.node = *model->NodeRef(); 59202be5353SAxel Dörfler tcnode.moveMode = kDelete; 59302be5353SAxel Dörfler const entry_ref* ref = model->EntryRef(); 59402be5353SAxel Dörfler report->AddInt32("device", ref->device); 59502be5353SAxel Dörfler report->AddInt64("directory", ref->directory); 59602be5353SAxel Dörfler report->AddBool("clearClipboard", false); 597ea001e58SJohn Scipione report->AddData("tcnode", T_CLIPBOARD_NODE, &tcnode, sizeof(tcnode), 598ea001e58SJohn Scipione true); 59902be5353SAxel Dörfler messenger.SendMessage(report); 60002be5353SAxel Dörfler delete report; 60102be5353SAxel Dörfler } 60202be5353SAxel Dörfler } 60302be5353SAxel Dörfler 60402be5353SAxel Dörfler 60502be5353SAxel Dörfler // #pragma mark - 60602be5353SAxel Dörfler 60702be5353SAxel Dörfler 60802be5353SAxel Dörfler BClipboardRefsWatcher::BClipboardRefsWatcher() 60902be5353SAxel Dörfler : BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096), 61002be5353SAxel Dörfler fNotifyList(10, false) 61102be5353SAxel Dörfler { 61202be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this); 61302be5353SAxel Dörfler fRefsInClipboard = FSClipboardHasRefs(); 61402be5353SAxel Dörfler be_clipboard->StartWatching(this); 61502be5353SAxel Dörfler } 61602be5353SAxel Dörfler 61702be5353SAxel Dörfler 61802be5353SAxel Dörfler BClipboardRefsWatcher::~BClipboardRefsWatcher() 61902be5353SAxel Dörfler { 62002be5353SAxel Dörfler stop_watching(this); 62102be5353SAxel Dörfler be_clipboard->StopWatching(this); 62202be5353SAxel Dörfler } 62302be5353SAxel Dörfler 62402be5353SAxel Dörfler 62502be5353SAxel Dörfler void 62602be5353SAxel Dörfler BClipboardRefsWatcher::AddToNotifyList(BMessenger target) 62702be5353SAxel Dörfler { 62802be5353SAxel Dörfler if (Lock()) { 62902be5353SAxel Dörfler // add the messenger if it's not already in the list 63002be5353SAxel Dörfler // ToDo: why do we have to care about that? 63102be5353SAxel Dörfler BMessenger* messenger; 63202be5353SAxel Dörfler bool found = false; 63302be5353SAxel Dörfler 634ea001e58SJohn Scipione for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL; 635ea001e58SJohn Scipione index++) { 63602be5353SAxel Dörfler if (*messenger == target) { 63702be5353SAxel Dörfler found = true; 63802be5353SAxel Dörfler break; 63902be5353SAxel Dörfler } 64002be5353SAxel Dörfler } 64102be5353SAxel Dörfler if (!found) 64202be5353SAxel Dörfler fNotifyList.AddItem(new BMessenger(target)); 64302be5353SAxel Dörfler 64402be5353SAxel Dörfler Unlock(); 64502be5353SAxel Dörfler } 64602be5353SAxel Dörfler } 64702be5353SAxel Dörfler 64802be5353SAxel Dörfler 64902be5353SAxel Dörfler void 65002be5353SAxel Dörfler BClipboardRefsWatcher::RemoveFromNotifyList(BMessenger target) 65102be5353SAxel Dörfler { 65202be5353SAxel Dörfler if (Lock()) { 65302be5353SAxel Dörfler BMessenger* messenger; 65402be5353SAxel Dörfler 655ea001e58SJohn Scipione for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL; 656ea001e58SJohn Scipione index++) { 65702be5353SAxel Dörfler if (*messenger == target) { 65802be5353SAxel Dörfler delete fNotifyList.RemoveItemAt(index); 65902be5353SAxel Dörfler break; 66002be5353SAxel Dörfler } 66102be5353SAxel Dörfler } 66202be5353SAxel Dörfler Unlock(); 66302be5353SAxel Dörfler } 66402be5353SAxel Dörfler } 66502be5353SAxel Dörfler 66602be5353SAxel Dörfler 66702be5353SAxel Dörfler void 66802be5353SAxel Dörfler BClipboardRefsWatcher::AddNode(const node_ref* node) 66902be5353SAxel Dörfler { 67002be5353SAxel Dörfler TTracker::WatchNode(node, B_WATCH_NAME, this); 67102be5353SAxel Dörfler fRefsInClipboard = true; 67202be5353SAxel Dörfler } 67302be5353SAxel Dörfler 67402be5353SAxel Dörfler 67502be5353SAxel Dörfler void 67602be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNode(node_ref* node, bool removeFromClipboard) 67702be5353SAxel Dörfler { 67802be5353SAxel Dörfler watch_node(node, B_STOP_WATCHING, this); 67902be5353SAxel Dörfler 68002be5353SAxel Dörfler if (!removeFromClipboard) 68102be5353SAxel Dörfler return; 68202be5353SAxel Dörfler 68302be5353SAxel Dörfler if (be_clipboard->Lock()) { 68402be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 68502be5353SAxel Dörfler if (clip != NULL) { 68602be5353SAxel Dörfler char name[64]; 68702be5353SAxel Dörfler MakeRefName(name, node); 68802be5353SAxel Dörfler clip->RemoveName(name); 68902be5353SAxel Dörfler MakeModeName(name); 69002be5353SAxel Dörfler clip->RemoveName(name); 69102be5353SAxel Dörfler 69202be5353SAxel Dörfler be_clipboard->Commit(); 69302be5353SAxel Dörfler } 69402be5353SAxel Dörfler be_clipboard->Unlock(); 69502be5353SAxel Dörfler } 69602be5353SAxel Dörfler } 69702be5353SAxel Dörfler 69802be5353SAxel Dörfler 69902be5353SAxel Dörfler void 70002be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device) 70102be5353SAxel Dörfler { 70202be5353SAxel Dörfler if (!be_clipboard->Lock()) 70302be5353SAxel Dörfler return; 70402be5353SAxel Dörfler 70502be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 70602be5353SAxel Dörfler if (clip != NULL) { 70702be5353SAxel Dörfler char deviceName[6]; 708adf8818eSAlex Smith sprintf(deviceName, "r%" B_PRIdDEV "_", device); 70902be5353SAxel Dörfler 71002be5353SAxel Dörfler int32 index = 0; 71102be5353SAxel Dörfler char* refName; 71202be5353SAxel Dörfler type_code type; 71302be5353SAxel Dörfler int32 count; 71402be5353SAxel Dörfler while (clip->GetInfo(B_REF_TYPE, index, 71502be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO 71602be5353SAxel Dörfler (const char**) 71702be5353SAxel Dörfler #endif 71802be5353SAxel Dörfler &refName, &type, &count) == B_OK) { 71902be5353SAxel Dörfler if (!strncmp(deviceName, refName, strlen(deviceName))) { 72002be5353SAxel Dörfler clip->RemoveName(refName); 72102be5353SAxel Dörfler MakeModeName(refName); 72202be5353SAxel Dörfler clip->RemoveName(refName); 72302be5353SAxel Dörfler 72402be5353SAxel Dörfler node_ref node; 72502be5353SAxel Dörfler MakeNodeFromName(&node, refName); 72602be5353SAxel Dörfler watch_node(&node, B_STOP_WATCHING, this); 72702be5353SAxel Dörfler } 72802be5353SAxel Dörfler index++; 72902be5353SAxel Dörfler } 73002be5353SAxel Dörfler be_clipboard->Commit(); 73102be5353SAxel Dörfler } 73202be5353SAxel Dörfler be_clipboard->Unlock(); 73302be5353SAxel Dörfler } 73402be5353SAxel Dörfler 73502be5353SAxel Dörfler 73602be5353SAxel Dörfler void 73702be5353SAxel Dörfler BClipboardRefsWatcher::UpdateNode(node_ref* node, entry_ref* ref) 73802be5353SAxel Dörfler { 73902be5353SAxel Dörfler if (!be_clipboard->Lock()) 74002be5353SAxel Dörfler return; 74102be5353SAxel Dörfler 74202be5353SAxel Dörfler BMessage* clip = be_clipboard->Data(); 74302be5353SAxel Dörfler if (clip != NULL) { 74402be5353SAxel Dörfler char name[64]; 74502be5353SAxel Dörfler MakeRefName(name, node); 74602be5353SAxel Dörfler if ((clip->ReplaceRef(name, ref)) != B_OK) { 74702be5353SAxel Dörfler clip->RemoveName(name); 74802be5353SAxel Dörfler MakeModeName(name); 74902be5353SAxel Dörfler clip->RemoveName(name); 75002be5353SAxel Dörfler 75102be5353SAxel Dörfler RemoveNode(node); 75202be5353SAxel Dörfler } 75302be5353SAxel Dörfler be_clipboard->Commit(); 75402be5353SAxel Dörfler } 75502be5353SAxel Dörfler be_clipboard->Unlock(); 75602be5353SAxel Dörfler } 75702be5353SAxel Dörfler 75802be5353SAxel Dörfler 75902be5353SAxel Dörfler void 76002be5353SAxel Dörfler BClipboardRefsWatcher::Clear() 76102be5353SAxel Dörfler { 76202be5353SAxel Dörfler stop_watching(this); 76302be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this); 76402be5353SAxel Dörfler 76502be5353SAxel Dörfler BMessage message(kFSClipboardChanges); 76602be5353SAxel Dörfler message.AddBool("clearClipboard", true); 76702be5353SAxel Dörfler if (Lock()) { 76802be5353SAxel Dörfler int32 items = fNotifyList.CountItems(); 76902be5353SAxel Dörfler for (int32 i = 0;i < items;i++) { 77002be5353SAxel Dörfler fNotifyList.ItemAt(i)->SendMessage(&message); 77102be5353SAxel Dörfler } 77202be5353SAxel Dörfler Unlock(); 77302be5353SAxel Dörfler } 77402be5353SAxel Dörfler } 77502be5353SAxel Dörfler 77602be5353SAxel Dörfler 777b05aa8b5SJohn Scipione //void 778a51764c5SJohn Scipione //BClipboardRefsWatcher::UpdatePoseViews(bool clearClipboard, 779a51764c5SJohn Scipione // const node_ref* node) 780b05aa8b5SJohn Scipione //{ 781b05aa8b5SJohn Scipione // BMessage message(kFSClipboardChanges); 782b05aa8b5SJohn Scipione // message.AddInt32("device", node->device); 783b05aa8b5SJohn Scipione // message.AddInt64("directory", node->node); 784b05aa8b5SJohn Scipione // message.AddBool("clearClipboard", clearClipboard); 785b05aa8b5SJohn Scipione // 786b05aa8b5SJohn Scipione // if (Lock()) { 787b05aa8b5SJohn Scipione // int32 items = fNotifyList.CountItems(); 788b05aa8b5SJohn Scipione // for (int32 i = 0;i < items;i++) { 789b05aa8b5SJohn Scipione // fNotifyList.ItemAt(i)->SendMessage(&message); 790b05aa8b5SJohn Scipione // } 791b05aa8b5SJohn Scipione // Unlock(); 792b05aa8b5SJohn Scipione // } 793b05aa8b5SJohn Scipione //} 794b05aa8b5SJohn Scipione 79502be5353SAxel Dörfler 79602be5353SAxel Dörfler void 79702be5353SAxel Dörfler BClipboardRefsWatcher::UpdatePoseViews(BMessage* reportMessage) 79802be5353SAxel Dörfler { 79902be5353SAxel Dörfler if (Lock()) { 80002be5353SAxel Dörfler // check if it was cleared, if so clear watching 80102be5353SAxel Dörfler bool clearClipboard = false; 80202be5353SAxel Dörfler if (reportMessage->FindBool("clearClipboard", &clearClipboard) == B_OK 80302be5353SAxel Dörfler && clearClipboard) { 80402be5353SAxel Dörfler stop_watching(this); 80502be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this); 80602be5353SAxel Dörfler } 80702be5353SAxel Dörfler 80802be5353SAxel Dörfler // loop through reported node_ref's movemodes: 80902be5353SAxel Dörfler // move or copy: start watching node_ref 81002be5353SAxel Dörfler // remove: stop watching node_ref 81102be5353SAxel Dörfler int32 index = 0; 81202be5353SAxel Dörfler TClipboardNodeRef* tcnode = NULL; 81302be5353SAxel Dörfler ssize_t size; 814ea001e58SJohn Scipione while (reportMessage->FindData("tcnode", T_CLIPBOARD_NODE, index, 815ea001e58SJohn Scipione (const void**)&tcnode, &size) == B_OK) { 81602be5353SAxel Dörfler if (tcnode->moveMode == kDelete) { 81702be5353SAxel Dörfler watch_node(&tcnode->node, B_STOP_WATCHING, this); 81802be5353SAxel Dörfler } else { 81902be5353SAxel Dörfler watch_node(&tcnode->node, B_STOP_WATCHING, this); 82002be5353SAxel Dörfler TTracker::WatchNode(&tcnode->node, B_WATCH_NAME, this); 82102be5353SAxel Dörfler fRefsInClipboard = true; 82202be5353SAxel Dörfler } 82302be5353SAxel Dörfler index++; 82402be5353SAxel Dörfler } 82502be5353SAxel Dörfler 82602be5353SAxel Dörfler // send report 82702be5353SAxel Dörfler int32 items = fNotifyList.CountItems(); 82802be5353SAxel Dörfler for (int32 i = 0;i < items;i++) { 82902be5353SAxel Dörfler fNotifyList.ItemAt(i)->SendMessage(reportMessage); 83002be5353SAxel Dörfler } 83102be5353SAxel Dörfler Unlock(); 83202be5353SAxel Dörfler } 83302be5353SAxel Dörfler } 83402be5353SAxel Dörfler 83502be5353SAxel Dörfler 83602be5353SAxel Dörfler void 83702be5353SAxel Dörfler BClipboardRefsWatcher::MessageReceived(BMessage* message) 83802be5353SAxel Dörfler { 83902be5353SAxel Dörfler if (message->what == B_CLIPBOARD_CHANGED && fRefsInClipboard) { 84002be5353SAxel Dörfler if (!(fRefsInClipboard = FSClipboardHasRefs())) 84102be5353SAxel Dörfler Clear(); 84202be5353SAxel Dörfler return; 84302be5353SAxel Dörfler } else if (message->what != B_NODE_MONITOR) { 84402be5353SAxel Dörfler _inherited::MessageReceived(message); 84502be5353SAxel Dörfler return; 84602be5353SAxel Dörfler } 84702be5353SAxel Dörfler 84802be5353SAxel Dörfler switch (message->FindInt32("opcode")) { 84902be5353SAxel Dörfler case B_ENTRY_MOVED: 85002be5353SAxel Dörfler { 85102be5353SAxel Dörfler ino_t toDir; 85202be5353SAxel Dörfler ino_t fromDir; 85302be5353SAxel Dörfler node_ref node; 85402be5353SAxel Dörfler const char* name = NULL; 85502be5353SAxel Dörfler message->FindInt64("from directory", &fromDir); 85602be5353SAxel Dörfler message->FindInt64("to directory", &toDir); 85702be5353SAxel Dörfler message->FindInt64("node", &node.node); 85802be5353SAxel Dörfler message->FindInt32("device", &node.device); 85902be5353SAxel Dörfler message->FindString("name", &name); 86002be5353SAxel Dörfler entry_ref ref(node.device, toDir, name); 86102be5353SAxel Dörfler UpdateNode(&node, &ref); 86202be5353SAxel Dörfler break; 86302be5353SAxel Dörfler } 86402be5353SAxel Dörfler 86502be5353SAxel Dörfler case B_DEVICE_UNMOUNTED: 86602be5353SAxel Dörfler { 86702be5353SAxel Dörfler dev_t device; 86802be5353SAxel Dörfler message->FindInt32("device", &device); 86902be5353SAxel Dörfler RemoveNodesByDevice(device); 87002be5353SAxel Dörfler break; 87102be5353SAxel Dörfler } 87202be5353SAxel Dörfler 87302be5353SAxel Dörfler case B_ENTRY_REMOVED: 87402be5353SAxel Dörfler { 87502be5353SAxel Dörfler node_ref node; 87602be5353SAxel Dörfler message->FindInt64("node", &node.node); 87702be5353SAxel Dörfler message->FindInt32("device", &node.device); 87802be5353SAxel Dörfler RemoveNode(&node, true); 87902be5353SAxel Dörfler break; 88002be5353SAxel Dörfler } 88102be5353SAxel Dörfler } 88202be5353SAxel Dörfler } 883