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
35e2f6a01cSJohn Scipione
3602be5353SAxel Dörfler #include "FSClipboard.h"
37e2f6a01cSJohn 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>
43e2f6a01cSJohn 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
5754e2dd72SJohn Scipione #if 0
5802be5353SAxel Dörfler static bool
5902be5353SAxel Dörfler FSClipboardCheckIntegrity()
6002be5353SAxel Dörfler {
6102be5353SAxel Dörfler return true;
6202be5353SAxel Dörfler }
6354e2dd72SJohn Scipione #endif
6402be5353SAxel Dörfler
657befa79aSAxel Dörfler static void
MakeNodeFromName(node_ref * node,char * name)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
MakeRefName(char * refName,const node_ref * node)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
MakeModeName(char * modeName,const node_ref * node)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
MakeModeName(char * name)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
MakeModeNameFromRefName(char * modeName,char * refName)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
CompareModeAndRefName(const char * modeName,const char * refName)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
112e2f6a01cSJohn 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
118e2f6a01cSJohn Scipione
11902be5353SAxel Dörfler bool
FSClipboardHasRefs()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
FSClipboardStartWatch(BMessenger target)15002be5353SAxel Dörfler FSClipboardStartWatch(BMessenger target)
15102be5353SAxel Dörfler {
1529cc03189SJohn Scipione TTracker* tracker = dynamic_cast<TTracker*>(be_app);
1539cc03189SJohn Scipione if (tracker != NULL && tracker->ClipboardRefsWatcher() != NULL)
1549cc03189SJohn Scipione tracker->ClipboardRefsWatcher()->AddToNotifyList(target);
15502be5353SAxel Dörfler else {
156ea001e58SJohn Scipione // this code is used by external apps using objects using FSClipboard
157ea001e58SJohn Scipione // functions, i.e. applications using FilePanel
15802be5353SAxel Dörfler BMessenger messenger(kTrackerSignature);
15902be5353SAxel Dörfler if (messenger.IsValid()) {
16002be5353SAxel Dörfler BMessage message(kStartWatchClipboardRefs);
16102be5353SAxel Dörfler message.AddMessenger("target", target);
16202be5353SAxel Dörfler messenger.SendMessage(&message);
16302be5353SAxel Dörfler }
16402be5353SAxel Dörfler }
16502be5353SAxel Dörfler }
16602be5353SAxel Dörfler
16702be5353SAxel Dörfler
16802be5353SAxel Dörfler void
FSClipboardStopWatch(BMessenger target)16902be5353SAxel Dörfler FSClipboardStopWatch(BMessenger target)
17002be5353SAxel Dörfler {
1719cc03189SJohn Scipione TTracker* tracker = dynamic_cast<TTracker*>(be_app);
1729cc03189SJohn Scipione if (tracker != NULL && tracker->ClipboardRefsWatcher() != NULL)
1739cc03189SJohn Scipione tracker->ClipboardRefsWatcher()->AddToNotifyList(target);
17402be5353SAxel Dörfler else {
175ea001e58SJohn Scipione // this code is used by external apps using objects using FSClipboard
176ea001e58SJohn Scipione // functions, i.e. applications using FilePanel
17702be5353SAxel Dörfler BMessenger messenger(kTrackerSignature);
17802be5353SAxel Dörfler if (messenger.IsValid()) {
17902be5353SAxel Dörfler BMessage message(kStopWatchClipboardRefs);
18002be5353SAxel Dörfler message.AddMessenger("target", target);
18102be5353SAxel Dörfler messenger.SendMessage(&message);
18202be5353SAxel Dörfler }
18302be5353SAxel Dörfler }
18402be5353SAxel Dörfler }
18502be5353SAxel Dörfler
18602be5353SAxel Dörfler
18702be5353SAxel Dörfler void
FSClipboardClear()18802be5353SAxel Dörfler FSClipboardClear()
18902be5353SAxel Dörfler {
19002be5353SAxel Dörfler if (!be_clipboard->Lock())
19102be5353SAxel Dörfler return;
19202be5353SAxel Dörfler
19302be5353SAxel Dörfler be_clipboard->Clear();
19402be5353SAxel Dörfler be_clipboard->Commit();
19502be5353SAxel Dörfler be_clipboard->Unlock();
19602be5353SAxel Dörfler }
19702be5353SAxel Dörfler
19802be5353SAxel Dörfler
19902be5353SAxel Dörfler /** This function adds the given poses list to the clipboard, for both copy
20002be5353SAxel Dörfler * and cut. All poses in the list must have "directory" as parent.
20102be5353SAxel Dörfler * "moveMode" is either kMoveSelection or kCopySelection.
20202be5353SAxel Dörfler * It will check if the entries are already present, so that there can only
20302be5353SAxel Dörfler * be one reference to them in the clipboard.
20402be5353SAxel Dörfler */
20502be5353SAxel Dörfler uint32
FSClipboardAddPoses(const node_ref * directory,PoseList * list,uint32 moveMode,bool clearClipboard)206a51764c5SJohn Scipione FSClipboardAddPoses(const node_ref* directory, PoseList* list,
207a51764c5SJohn Scipione uint32 moveMode, bool clearClipboard)
20802be5353SAxel Dörfler {
20902be5353SAxel Dörfler uint32 refsAdded = 0;
21002be5353SAxel Dörfler int32 listCount = list->CountItems();
21102be5353SAxel Dörfler
21202be5353SAxel Dörfler if (listCount == 0 || !be_clipboard->Lock())
21302be5353SAxel Dörfler return 0;
21402be5353SAxel Dörfler
21502be5353SAxel Dörfler // update message to be send to all listeners
21602be5353SAxel Dörfler BMessage updateMessage(kFSClipboardChanges);
21702be5353SAxel Dörfler updateMessage.AddInt32("device", directory->device);
21802be5353SAxel Dörfler updateMessage.AddInt64("directory", directory->node);
21902be5353SAxel Dörfler updateMessage.AddBool("clearClipboard", clearClipboard);
22002be5353SAxel Dörfler
22102be5353SAxel Dörfler TClipboardNodeRef clipNode;
22202be5353SAxel Dörfler clipNode.moveMode = moveMode;
22302be5353SAxel Dörfler
22402be5353SAxel Dörfler if (clearClipboard)
22502be5353SAxel Dörfler be_clipboard->Clear();
22602be5353SAxel Dörfler
22702be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
22802be5353SAxel Dörfler if (clip != NULL) {
22902be5353SAxel Dörfler for (int32 index = 0; index < listCount; index++) {
23002be5353SAxel Dörfler char refName[64], modeName[64];
23102be5353SAxel Dörfler BPose* pose = (BPose*)list->ItemAt(index);
23202be5353SAxel Dörfler Model* model = pose->TargetModel();
23302be5353SAxel Dörfler const node_ref* node = model->NodeRef();
23402be5353SAxel Dörfler
23502be5353SAxel Dörfler BEntry entry;
23602be5353SAxel Dörfler model->GetEntry(&entry);
23702be5353SAxel Dörfler if (model->IsVolume()
23802be5353SAxel Dörfler || model->IsRoot()
239d9626569SRene Gollent || model->IsTrash()
24089af0548SRene Gollent || model->IsDesktop())
24102be5353SAxel Dörfler continue;
24202be5353SAxel Dörfler
24302be5353SAxel Dörfler MakeRefName(refName, node);
24402be5353SAxel Dörfler MakeModeNameFromRefName(modeName, refName);
24502be5353SAxel Dörfler
24602be5353SAxel Dörfler if (clearClipboard) {
2475422febdSStephan Aßmus if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
24802be5353SAxel Dörfler if (clip->AddRef(refName, model->EntryRef()) == B_OK) {
24902be5353SAxel Dörfler pose->SetClipboardMode(moveMode);
25002be5353SAxel Dörfler
25102be5353SAxel Dörfler clipNode.node = *node;
2525422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2535422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true,
2545422febdSStephan Aßmus listCount);
25502be5353SAxel Dörfler
25602be5353SAxel Dörfler refsAdded++;
25702be5353SAxel Dörfler } else
25802be5353SAxel Dörfler clip->RemoveName(modeName);
2595422febdSStephan Aßmus }
26002be5353SAxel Dörfler } else {
26102be5353SAxel Dörfler if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) {
26202be5353SAxel Dörfler // replace old mode if entry already exists in clipboard
26302be5353SAxel Dörfler if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) {
26402be5353SAxel Dörfler pose->SetClipboardMode(moveMode);
26502be5353SAxel Dörfler
26602be5353SAxel Dörfler clipNode.node = *node;
2675422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2685422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true,
2695422febdSStephan Aßmus listCount);
27002be5353SAxel Dörfler
27102be5353SAxel Dörfler refsAdded++;
27202be5353SAxel Dörfler } else {
27302be5353SAxel Dörfler clip->RemoveName(modeName);
27402be5353SAxel Dörfler
27502be5353SAxel Dörfler clipNode.node = *node;
27602be5353SAxel Dörfler clipNode.moveMode = kDelete; // note removing node
2775422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2785422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true,
2795422febdSStephan Aßmus listCount);
2805422febdSStephan Aßmus clipNode.moveMode = moveMode;
2815422febdSStephan Aßmus // set it back to current value
28202be5353SAxel Dörfler }
28302be5353SAxel Dörfler } else {
2847befa79aSAxel Dörfler // add it if it doesn't exist
28502be5353SAxel Dörfler if (clip->AddRef(refName, model->EntryRef()) == B_OK
28602be5353SAxel Dörfler && clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
28702be5353SAxel Dörfler pose->SetClipboardMode(moveMode);
28802be5353SAxel Dörfler
28902be5353SAxel Dörfler clipNode.node = *node;
2905422febdSStephan Aßmus updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2915422febdSStephan Aßmus &clipNode, sizeof(TClipboardNodeRef), true,
2925422febdSStephan Aßmus listCount);
29302be5353SAxel Dörfler
29402be5353SAxel Dörfler refsAdded++;
29502be5353SAxel Dörfler } else {
29602be5353SAxel Dörfler clip->RemoveName(modeName);
29702be5353SAxel Dörfler clip->RemoveName(refName);
2987befa79aSAxel Dörfler // here notifying delete isn't needed as node didn't
2997befa79aSAxel Dörfler // exist in clipboard
30002be5353SAxel Dörfler }
30102be5353SAxel Dörfler }
30202be5353SAxel Dörfler }
30302be5353SAxel Dörfler }
30402be5353SAxel Dörfler be_clipboard->Commit();
30502be5353SAxel Dörfler }
30602be5353SAxel Dörfler be_clipboard->Unlock();
30702be5353SAxel Dörfler
30802be5353SAxel Dörfler BMessenger(kTrackerSignature).SendMessage(&updateMessage);
30902be5353SAxel Dörfler // Tracker will notify all listeners
31002be5353SAxel Dörfler
31102be5353SAxel Dörfler return refsAdded;
31202be5353SAxel Dörfler }
31302be5353SAxel Dörfler
31402be5353SAxel Dörfler
31502be5353SAxel Dörfler uint32
FSClipboardRemovePoses(const node_ref * directory,PoseList * list)31602be5353SAxel Dörfler FSClipboardRemovePoses(const node_ref* directory, PoseList* list)
31702be5353SAxel Dörfler {
31802be5353SAxel Dörfler if (!be_clipboard->Lock())
31902be5353SAxel Dörfler return 0;
32002be5353SAxel Dörfler
32102be5353SAxel Dörfler // update message to be send to all listeners
32202be5353SAxel Dörfler BMessage updateMessage(kFSClipboardChanges);
32302be5353SAxel Dörfler updateMessage.AddInt32("device", directory->device);
32402be5353SAxel Dörfler updateMessage.AddInt64("directory", directory->node);
32502be5353SAxel Dörfler updateMessage.AddBool("clearClipboard", false);
32602be5353SAxel Dörfler
32702be5353SAxel Dörfler TClipboardNodeRef clipNode;
32802be5353SAxel Dörfler clipNode.moveMode = kDelete;
32902be5353SAxel Dörfler
33002be5353SAxel Dörfler uint32 refsRemoved = 0;
33102be5353SAxel Dörfler
33202be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
33302be5353SAxel Dörfler if (clip != NULL) {
33402be5353SAxel Dörfler int32 listCount = list->CountItems();
33502be5353SAxel Dörfler
33602be5353SAxel Dörfler for (int32 index = 0; index < listCount; index++) {
33702be5353SAxel Dörfler char refName[64], modeName[64];
33802be5353SAxel Dörfler BPose* pose = (BPose*)list->ItemAt(index);
33902be5353SAxel Dörfler
34002be5353SAxel Dörfler clipNode.node = *pose->TargetModel()->NodeRef();
34102be5353SAxel Dörfler MakeRefName(refName, &clipNode.node);
34202be5353SAxel Dörfler MakeModeName(modeName);
34302be5353SAxel Dörfler
344ea001e58SJohn Scipione if (clip->RemoveName(refName) == B_OK
345ea001e58SJohn Scipione && clip->RemoveName(modeName)) {
34602be5353SAxel Dörfler updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode,
34702be5353SAxel Dörfler sizeof(TClipboardNodeRef), true, listCount);
34802be5353SAxel Dörfler refsRemoved++;
34902be5353SAxel Dörfler }
35002be5353SAxel Dörfler }
35102be5353SAxel Dörfler be_clipboard->Commit();
35202be5353SAxel Dörfler }
35302be5353SAxel Dörfler be_clipboard->Unlock();
35402be5353SAxel Dörfler
35502be5353SAxel Dörfler BMessenger(kTrackerSignature).SendMessage(&updateMessage);
35602be5353SAxel Dörfler // Tracker will notify all listeners
35702be5353SAxel Dörfler
35802be5353SAxel Dörfler return refsRemoved;
35902be5353SAxel Dörfler }
36002be5353SAxel Dörfler
36102be5353SAxel Dörfler
36202be5353SAxel Dörfler /** Pastes entries from the clipboard to the target model's directory.
36302be5353SAxel Dörfler * Updates moveModes and notifies listeners if necessary.
36402be5353SAxel Dörfler */
36502be5353SAxel Dörfler bool
FSClipboardPaste(Model * model,uint32 linksMode)36602be5353SAxel Dörfler FSClipboardPaste(Model* model, uint32 linksMode)
36702be5353SAxel Dörfler {
36802be5353SAxel Dörfler if (!FSClipboardHasRefs())
36902be5353SAxel Dörfler return false;
37002be5353SAxel Dörfler
37102be5353SAxel Dörfler BMessenger tracker(kTrackerSignature);
37202be5353SAxel Dörfler
37302be5353SAxel Dörfler node_ref* destNodeRef = (node_ref*)model->NodeRef();
37402be5353SAxel Dörfler
37502be5353SAxel Dörfler // these will be passed to the asynchronous copy/move process
37602be5353SAxel Dörfler BObjectList<entry_ref>* moveList = new BObjectList<entry_ref>(0, true);
37702be5353SAxel Dörfler BObjectList<entry_ref>* copyList = new BObjectList<entry_ref>(0, true);
3785e7114c1SRyan Leavengood BObjectList<entry_ref>* duplicateList = new BObjectList<entry_ref>(0, true);
37902be5353SAxel Dörfler
38002be5353SAxel Dörfler if ((be_clipboard->Lock())) {
38102be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
38202be5353SAxel Dörfler if (clip != NULL) {
38302be5353SAxel Dörfler char modeName[64];
38402be5353SAxel Dörfler uint32 moveMode = 0;
38502be5353SAxel Dörfler
386b93d08f9SJohn Scipione BMessage updateMessage(kFSClipboardChanges);
38702be5353SAxel Dörfler node_ref updateNodeRef;
38802be5353SAxel Dörfler updateNodeRef.device = -1;
38902be5353SAxel Dörfler
39002be5353SAxel Dörfler char* refName;
39102be5353SAxel Dörfler type_code type;
39202be5353SAxel Dörfler int32 count;
39302be5353SAxel Dörfler for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index,
39402be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
39502be5353SAxel Dörfler (const char**)
39602be5353SAxel Dörfler #endif
39702be5353SAxel Dörfler &refName, &type, &count) == B_OK; index++) {
39802be5353SAxel Dörfler entry_ref ref;
39902be5353SAxel Dörfler if (clip->FindRef(refName, &ref) != B_OK)
40002be5353SAxel Dörfler continue;
40102be5353SAxel Dörfler
40202be5353SAxel Dörfler // If the entry_ref's directory has changed, send previous notification
40302be5353SAxel Dörfler // (if any), and start new one for the new directory
404b93d08f9SJohn Scipione if (updateNodeRef.device != ref.device || updateNodeRef.node != ref.directory) {
405b93d08f9SJohn Scipione if (!updateMessage.IsEmpty()) {
406b93d08f9SJohn Scipione tracker.SendMessage(&updateMessage);
407b93d08f9SJohn Scipione updateMessage.MakeEmpty();
40802be5353SAxel Dörfler }
40902be5353SAxel Dörfler
41002be5353SAxel Dörfler updateNodeRef.device = ref.device;
41102be5353SAxel Dörfler updateNodeRef.node = ref.directory;
412b93d08f9SJohn Scipione updateMessage.AddInt32("device", updateNodeRef.device);
413b93d08f9SJohn Scipione 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);
418b93d08f9SJohn Scipione if (!linksMode && clip->FindInt32(modeName, (int32*)&moveMode) != B_OK)
41902be5353SAxel Dörfler continue;
42002be5353SAxel Dörfler
42102be5353SAxel Dörfler BEntry entry(&ref);
42202be5353SAxel Dörfler
42302be5353SAxel Dörfler uint32 newMoveMode = 0;
424a51764c5SJohn Scipione bool sameDirectory = destNodeRef->device == ref.device
425a51764c5SJohn Scipione && destNodeRef->node == ref.directory;
42602be5353SAxel Dörfler
42702be5353SAxel Dörfler if (!entry.Exists()) {
42802be5353SAxel Dörfler // The entry doesn't exist anymore, so we'll remove
42902be5353SAxel Dörfler // that entry from the clipboard as well
43002be5353SAxel Dörfler clip->RemoveName(refName);
43102be5353SAxel Dörfler clip->RemoveName(modeName);
43202be5353SAxel Dörfler
43302be5353SAxel Dörfler newMoveMode = kDelete;
43402be5353SAxel Dörfler } else {
435b93d08f9SJohn Scipione // the entry does exist, so lets see what we will do with it
43602be5353SAxel Dörfler if (!sameDirectory) {
43702be5353SAxel Dörfler if (linksMode || moveMode == kMoveSelectionTo) {
43802be5353SAxel Dörfler // the linksMode uses the moveList as well
43902be5353SAxel Dörfler moveList->AddItem(new entry_ref(ref));
44002be5353SAxel Dörfler } else if (moveMode == kCopySelectionTo)
44102be5353SAxel Dörfler copyList->AddItem(new entry_ref(ref));
442*fe514848SJohn Scipione } else if (moveMode != kMoveSelectionTo) {
443*fe514848SJohn Scipione // we are copying a file into its same directory, do a duplicate
4445e7114c1SRyan Leavengood duplicateList->AddItem(new entry_ref(ref));
4455e7114c1SRyan Leavengood }
446*fe514848SJohn Scipione
447*fe514848SJohn Scipione // Whether the entry changed directories or not we want to copy that entry
448*fe514848SJohn Scipione // next time, even if the items don't have to be moved (source == target).
449*fe514848SJohn Scipione if (moveMode == kMoveSelectionTo)
450*fe514848SJohn Scipione newMoveMode = kCopySelectionTo;
45102be5353SAxel Dörfler }
45202be5353SAxel Dörfler
45302be5353SAxel Dörfler // add the change to the update message (if necessary)
454b93d08f9SJohn Scipione if (newMoveMode != 0) {
45502be5353SAxel Dörfler clip->ReplaceInt32(modeName, kCopySelectionTo);
45602be5353SAxel Dörfler
45702be5353SAxel Dörfler TClipboardNodeRef clipNode;
45802be5353SAxel Dörfler MakeNodeFromName(&clipNode.node, modeName);
45902be5353SAxel Dörfler clipNode.moveMode = kDelete;
460b93d08f9SJohn Scipione updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode,
461b93d08f9SJohn Scipione sizeof(TClipboardNodeRef), true);
46202be5353SAxel Dörfler }
46302be5353SAxel Dörfler }
46402be5353SAxel Dörfler be_clipboard->Commit();
46502be5353SAxel Dörfler
46602be5353SAxel Dörfler // send notification for the last directory
467b93d08f9SJohn Scipione if (!updateMessage.IsEmpty()) {
468b93d08f9SJohn Scipione tracker.SendMessage(&updateMessage);
469b93d08f9SJohn Scipione updateMessage.MakeEmpty();
47002be5353SAxel Dörfler }
47102be5353SAxel Dörfler }
47202be5353SAxel Dörfler be_clipboard->Unlock();
47302be5353SAxel Dörfler }
47402be5353SAxel Dörfler
47502be5353SAxel Dörfler bool okToMove = true;
47602be5353SAxel Dörfler
47702be5353SAxel Dörfler // can't copy/paste to root('/') directory
47802be5353SAxel Dörfler if (model->IsRoot()) {
4794ed28a57SAlexandre Deckner BAlert* alert = new BAlert("",
4804ed28a57SAlexandre Deckner B_TRANSLATE("You must drop items on one of the disk icons "
4814ed28a57SAlexandre Deckner "in the \"Disks\" window."), B_TRANSLATE("Cancel"), NULL, NULL,
4824ed28a57SAlexandre Deckner B_WIDTH_AS_USUAL, B_WARNING_ALERT);
483aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
484019f90e6SJonas Sundström alert->Go();
48502be5353SAxel Dörfler okToMove = false;
48602be5353SAxel Dörfler }
48702be5353SAxel Dörfler
48802be5353SAxel Dörfler BEntry entry;
48902be5353SAxel Dörfler model->GetEntry(&entry);
49002be5353SAxel Dörfler
49102be5353SAxel Dörfler // can't copy items into the trash
492d9626569SRene Gollent if (copyList->CountItems() > 0 && model->IsTrash()) {
4934ed28a57SAlexandre Deckner BAlert* alert = new BAlert("",
4944ed28a57SAlexandre Deckner B_TRANSLATE("Sorry, you can't copy items to the Trash."),
4954ed28a57SAlexandre Deckner B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL,
4964ed28a57SAlexandre Deckner B_WARNING_ALERT);
497aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
498019f90e6SJonas Sundström alert->Go();
49902be5353SAxel Dörfler okToMove = false;
50002be5353SAxel Dörfler }
50102be5353SAxel Dörfler
50202be5353SAxel Dörfler if (!okToMove) {
50302be5353SAxel Dörfler // there was some problem with our target, so we bail out here
50402be5353SAxel Dörfler delete moveList;
50502be5353SAxel Dörfler delete copyList;
5062a49e094SMurai Takashi delete duplicateList;
50702be5353SAxel Dörfler return false;
50802be5353SAxel Dörfler }
50902be5353SAxel Dörfler
51002be5353SAxel Dörfler // asynchronous calls take over ownership of the objects passed to it
511b93d08f9SJohn Scipione if (moveList->CountItems() > 0)
512b93d08f9SJohn Scipione FSMoveToFolder(moveList, new BEntry(entry), linksMode ? linksMode : kMoveSelectionTo);
513b93d08f9SJohn Scipione else
51402be5353SAxel Dörfler delete moveList;
51502be5353SAxel Dörfler
51602be5353SAxel Dörfler if (copyList->CountItems() > 0)
51702be5353SAxel Dörfler FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo);
51802be5353SAxel Dörfler else
51902be5353SAxel Dörfler delete copyList;
52002be5353SAxel Dörfler
5215e7114c1SRyan Leavengood if (duplicateList->CountItems() > 0)
5225e7114c1SRyan Leavengood FSMoveToFolder(duplicateList, new BEntry(entry), kDuplicateSelection);
5235e7114c1SRyan Leavengood else
5245e7114c1SRyan Leavengood delete duplicateList;
5255e7114c1SRyan Leavengood
52602be5353SAxel Dörfler return true;
52702be5353SAxel Dörfler }
52802be5353SAxel Dörfler
52902be5353SAxel Dörfler
530b05aa8b5SJohn Scipione // Seek node in clipboard, if found return it's moveMode
531b05aa8b5SJohn Scipione // else return 0
53202be5353SAxel Dörfler uint32
FSClipboardFindNodeMode(Model * model,bool autoLock,bool updateRefIfNeeded)53395da0645SRene Gollent FSClipboardFindNodeMode(Model* model, bool autoLock, bool updateRefIfNeeded)
53402be5353SAxel Dörfler {
53502be5353SAxel Dörfler int32 moveMode = 0;
53695da0645SRene Gollent if (autoLock) {
53795da0645SRene Gollent if (!be_clipboard->Lock())
53895da0645SRene Gollent return 0;
53995da0645SRene Gollent }
54002be5353SAxel Dörfler bool remove = false;
54102be5353SAxel Dörfler bool change = false;
54202be5353SAxel Dörfler
54302be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
54402be5353SAxel Dörfler if (clip != NULL) {
54502be5353SAxel Dörfler const node_ref* node = model->NodeRef();
54602be5353SAxel Dörfler char modeName[64];
54702be5353SAxel Dörfler MakeModeName(modeName, node);
54802be5353SAxel Dörfler if ((clip->FindInt32(modeName, &moveMode) == B_OK)) {
54902be5353SAxel Dörfler const entry_ref* ref = model->EntryRef();
55002be5353SAxel Dörfler entry_ref clipref;
55102be5353SAxel Dörfler char refName[64];
55202be5353SAxel Dörfler MakeRefName(refName, node);
55302be5353SAxel Dörfler if ((clip->FindRef(refName, &clipref) == B_OK)) {
55402be5353SAxel Dörfler if (clipref != *ref) {
55502be5353SAxel Dörfler if (updateRefIfNeeded) {
55602be5353SAxel Dörfler clip->ReplaceRef(refName, ref);
55702be5353SAxel Dörfler change = true;
55802be5353SAxel Dörfler } else {
55902be5353SAxel Dörfler clip->RemoveName(refName);
56002be5353SAxel Dörfler clip->RemoveName(modeName);
56102be5353SAxel Dörfler change = true;
56202be5353SAxel Dörfler remove = true;
56302be5353SAxel Dörfler moveMode = 0;
56402be5353SAxel Dörfler }
56502be5353SAxel Dörfler }
56602be5353SAxel Dörfler } else {
56702be5353SAxel Dörfler clip->RemoveName(modeName);
56802be5353SAxel Dörfler change = true;
56902be5353SAxel Dörfler remove = true;
57002be5353SAxel Dörfler moveMode = 0;
57102be5353SAxel Dörfler }
57202be5353SAxel Dörfler }
57302be5353SAxel Dörfler }
57402be5353SAxel Dörfler if (change)
57502be5353SAxel Dörfler be_clipboard->Commit();
57602be5353SAxel Dörfler
57795da0645SRene Gollent if (autoLock)
57802be5353SAxel Dörfler be_clipboard->Unlock();
57902be5353SAxel Dörfler
58002be5353SAxel Dörfler if (remove)
58102be5353SAxel Dörfler FSClipboardRemove(model);
58202be5353SAxel Dörfler
58302be5353SAxel Dörfler return (uint32)moveMode;
58402be5353SAxel Dörfler }
58502be5353SAxel Dörfler
58602be5353SAxel Dörfler
58702be5353SAxel Dörfler void
FSClipboardRemove(Model * model)58802be5353SAxel Dörfler FSClipboardRemove(Model* model)
58902be5353SAxel Dörfler {
59002be5353SAxel Dörfler BMessenger messenger(kTrackerSignature);
59102be5353SAxel Dörfler if (messenger.IsValid()) {
59202be5353SAxel Dörfler BMessage* report = new BMessage(kFSClipboardChanges);
59302be5353SAxel Dörfler TClipboardNodeRef tcnode;
59402be5353SAxel Dörfler tcnode.node = *model->NodeRef();
59502be5353SAxel Dörfler tcnode.moveMode = kDelete;
59602be5353SAxel Dörfler const entry_ref* ref = model->EntryRef();
59702be5353SAxel Dörfler report->AddInt32("device", ref->device);
59802be5353SAxel Dörfler report->AddInt64("directory", ref->directory);
59902be5353SAxel Dörfler report->AddBool("clearClipboard", false);
600ea001e58SJohn Scipione report->AddData("tcnode", T_CLIPBOARD_NODE, &tcnode, sizeof(tcnode),
601ea001e58SJohn Scipione true);
60202be5353SAxel Dörfler messenger.SendMessage(report);
60302be5353SAxel Dörfler delete report;
60402be5353SAxel Dörfler }
60502be5353SAxel Dörfler }
60602be5353SAxel Dörfler
60702be5353SAxel Dörfler
60802be5353SAxel Dörfler // #pragma mark -
60902be5353SAxel Dörfler
61002be5353SAxel Dörfler
BClipboardRefsWatcher()61102be5353SAxel Dörfler BClipboardRefsWatcher::BClipboardRefsWatcher()
61202be5353SAxel Dörfler : BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096),
61302be5353SAxel Dörfler fNotifyList(10, false)
61402be5353SAxel Dörfler {
61502be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this);
61602be5353SAxel Dörfler fRefsInClipboard = FSClipboardHasRefs();
61702be5353SAxel Dörfler be_clipboard->StartWatching(this);
61802be5353SAxel Dörfler }
61902be5353SAxel Dörfler
62002be5353SAxel Dörfler
~BClipboardRefsWatcher()62102be5353SAxel Dörfler BClipboardRefsWatcher::~BClipboardRefsWatcher()
62202be5353SAxel Dörfler {
62302be5353SAxel Dörfler stop_watching(this);
62402be5353SAxel Dörfler be_clipboard->StopWatching(this);
62502be5353SAxel Dörfler }
62602be5353SAxel Dörfler
62702be5353SAxel Dörfler
62802be5353SAxel Dörfler void
AddToNotifyList(BMessenger target)62902be5353SAxel Dörfler BClipboardRefsWatcher::AddToNotifyList(BMessenger target)
63002be5353SAxel Dörfler {
63102be5353SAxel Dörfler if (Lock()) {
63202be5353SAxel Dörfler // add the messenger if it's not already in the list
63302be5353SAxel Dörfler // ToDo: why do we have to care about that?
63402be5353SAxel Dörfler BMessenger* messenger;
63502be5353SAxel Dörfler bool found = false;
63602be5353SAxel Dörfler
637ea001e58SJohn Scipione for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL;
638ea001e58SJohn Scipione index++) {
63902be5353SAxel Dörfler if (*messenger == target) {
64002be5353SAxel Dörfler found = true;
64102be5353SAxel Dörfler break;
64202be5353SAxel Dörfler }
64302be5353SAxel Dörfler }
64402be5353SAxel Dörfler if (!found)
64502be5353SAxel Dörfler fNotifyList.AddItem(new BMessenger(target));
64602be5353SAxel Dörfler
64702be5353SAxel Dörfler Unlock();
64802be5353SAxel Dörfler }
64902be5353SAxel Dörfler }
65002be5353SAxel Dörfler
65102be5353SAxel Dörfler
65202be5353SAxel Dörfler void
RemoveFromNotifyList(BMessenger target)65302be5353SAxel Dörfler BClipboardRefsWatcher::RemoveFromNotifyList(BMessenger target)
65402be5353SAxel Dörfler {
65502be5353SAxel Dörfler if (Lock()) {
65602be5353SAxel Dörfler BMessenger* messenger;
65702be5353SAxel Dörfler
658ea001e58SJohn Scipione for (int32 index = 0; (messenger = fNotifyList.ItemAt(index)) != NULL;
659ea001e58SJohn Scipione index++) {
66002be5353SAxel Dörfler if (*messenger == target) {
66102be5353SAxel Dörfler delete fNotifyList.RemoveItemAt(index);
66202be5353SAxel Dörfler break;
66302be5353SAxel Dörfler }
66402be5353SAxel Dörfler }
66502be5353SAxel Dörfler Unlock();
66602be5353SAxel Dörfler }
66702be5353SAxel Dörfler }
66802be5353SAxel Dörfler
66902be5353SAxel Dörfler
67002be5353SAxel Dörfler void
AddNode(const node_ref * node)67102be5353SAxel Dörfler BClipboardRefsWatcher::AddNode(const node_ref* node)
67202be5353SAxel Dörfler {
67302be5353SAxel Dörfler TTracker::WatchNode(node, B_WATCH_NAME, this);
67402be5353SAxel Dörfler fRefsInClipboard = true;
67502be5353SAxel Dörfler }
67602be5353SAxel Dörfler
67702be5353SAxel Dörfler
67802be5353SAxel Dörfler void
RemoveNode(node_ref * node,bool removeFromClipboard)67902be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNode(node_ref* node, bool removeFromClipboard)
68002be5353SAxel Dörfler {
68102be5353SAxel Dörfler watch_node(node, B_STOP_WATCHING, this);
68202be5353SAxel Dörfler
68302be5353SAxel Dörfler if (!removeFromClipboard)
68402be5353SAxel Dörfler return;
68502be5353SAxel Dörfler
68602be5353SAxel Dörfler if (be_clipboard->Lock()) {
68702be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
68802be5353SAxel Dörfler if (clip != NULL) {
68902be5353SAxel Dörfler char name[64];
69002be5353SAxel Dörfler MakeRefName(name, node);
69102be5353SAxel Dörfler clip->RemoveName(name);
69202be5353SAxel Dörfler MakeModeName(name);
69302be5353SAxel Dörfler clip->RemoveName(name);
69402be5353SAxel Dörfler
69502be5353SAxel Dörfler be_clipboard->Commit();
69602be5353SAxel Dörfler }
69702be5353SAxel Dörfler be_clipboard->Unlock();
69802be5353SAxel Dörfler }
69902be5353SAxel Dörfler }
70002be5353SAxel Dörfler
70102be5353SAxel Dörfler
70202be5353SAxel Dörfler void
RemoveNodesByDevice(dev_t device)70302be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device)
70402be5353SAxel Dörfler {
70502be5353SAxel Dörfler if (!be_clipboard->Lock())
70602be5353SAxel Dörfler return;
70702be5353SAxel Dörfler
70802be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
70902be5353SAxel Dörfler if (clip != NULL) {
71002be5353SAxel Dörfler char deviceName[6];
711adf8818eSAlex Smith sprintf(deviceName, "r%" B_PRIdDEV "_", device);
71202be5353SAxel Dörfler
71302be5353SAxel Dörfler int32 index = 0;
71402be5353SAxel Dörfler char* refName;
71502be5353SAxel Dörfler type_code type;
71602be5353SAxel Dörfler int32 count;
71702be5353SAxel Dörfler while (clip->GetInfo(B_REF_TYPE, index,
71802be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
71902be5353SAxel Dörfler (const char**)
72002be5353SAxel Dörfler #endif
72102be5353SAxel Dörfler &refName, &type, &count) == B_OK) {
72202be5353SAxel Dörfler if (!strncmp(deviceName, refName, strlen(deviceName))) {
72302be5353SAxel Dörfler clip->RemoveName(refName);
72402be5353SAxel Dörfler MakeModeName(refName);
72502be5353SAxel Dörfler clip->RemoveName(refName);
72602be5353SAxel Dörfler
72702be5353SAxel Dörfler node_ref node;
72802be5353SAxel Dörfler MakeNodeFromName(&node, refName);
72902be5353SAxel Dörfler watch_node(&node, B_STOP_WATCHING, this);
73002be5353SAxel Dörfler }
73102be5353SAxel Dörfler index++;
73202be5353SAxel Dörfler }
73302be5353SAxel Dörfler be_clipboard->Commit();
73402be5353SAxel Dörfler }
73502be5353SAxel Dörfler be_clipboard->Unlock();
73602be5353SAxel Dörfler }
73702be5353SAxel Dörfler
73802be5353SAxel Dörfler
73902be5353SAxel Dörfler void
UpdateNode(node_ref * node,entry_ref * ref)74002be5353SAxel Dörfler BClipboardRefsWatcher::UpdateNode(node_ref* node, entry_ref* ref)
74102be5353SAxel Dörfler {
74202be5353SAxel Dörfler if (!be_clipboard->Lock())
74302be5353SAxel Dörfler return;
74402be5353SAxel Dörfler
74502be5353SAxel Dörfler BMessage* clip = be_clipboard->Data();
74602be5353SAxel Dörfler if (clip != NULL) {
74702be5353SAxel Dörfler char name[64];
74802be5353SAxel Dörfler MakeRefName(name, node);
74902be5353SAxel Dörfler if ((clip->ReplaceRef(name, ref)) != B_OK) {
75002be5353SAxel Dörfler clip->RemoveName(name);
75102be5353SAxel Dörfler MakeModeName(name);
75202be5353SAxel Dörfler clip->RemoveName(name);
75302be5353SAxel Dörfler
75402be5353SAxel Dörfler RemoveNode(node);
75502be5353SAxel Dörfler }
75602be5353SAxel Dörfler be_clipboard->Commit();
75702be5353SAxel Dörfler }
75802be5353SAxel Dörfler be_clipboard->Unlock();
75902be5353SAxel Dörfler }
76002be5353SAxel Dörfler
76102be5353SAxel Dörfler
76202be5353SAxel Dörfler void
Clear()76302be5353SAxel Dörfler BClipboardRefsWatcher::Clear()
76402be5353SAxel Dörfler {
76502be5353SAxel Dörfler stop_watching(this);
76602be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this);
76702be5353SAxel Dörfler
76802be5353SAxel Dörfler BMessage message(kFSClipboardChanges);
76902be5353SAxel Dörfler message.AddBool("clearClipboard", true);
77002be5353SAxel Dörfler if (Lock()) {
77102be5353SAxel Dörfler int32 items = fNotifyList.CountItems();
77202be5353SAxel Dörfler for (int32 i = 0;i < items;i++) {
77302be5353SAxel Dörfler fNotifyList.ItemAt(i)->SendMessage(&message);
77402be5353SAxel Dörfler }
77502be5353SAxel Dörfler Unlock();
77602be5353SAxel Dörfler }
77702be5353SAxel Dörfler }
77802be5353SAxel Dörfler
77902be5353SAxel Dörfler
780b05aa8b5SJohn Scipione //void
781a51764c5SJohn Scipione //BClipboardRefsWatcher::UpdatePoseViews(bool clearClipboard,
782a51764c5SJohn Scipione // const node_ref* node)
783b05aa8b5SJohn Scipione //{
784b05aa8b5SJohn Scipione // BMessage message(kFSClipboardChanges);
785b05aa8b5SJohn Scipione // message.AddInt32("device", node->device);
786b05aa8b5SJohn Scipione // message.AddInt64("directory", node->node);
787b05aa8b5SJohn Scipione // message.AddBool("clearClipboard", clearClipboard);
788b05aa8b5SJohn Scipione //
789b05aa8b5SJohn Scipione // if (Lock()) {
790b05aa8b5SJohn Scipione // int32 items = fNotifyList.CountItems();
791b05aa8b5SJohn Scipione // for (int32 i = 0;i < items;i++) {
792b05aa8b5SJohn Scipione // fNotifyList.ItemAt(i)->SendMessage(&message);
793b05aa8b5SJohn Scipione // }
794b05aa8b5SJohn Scipione // Unlock();
795b05aa8b5SJohn Scipione // }
796b05aa8b5SJohn Scipione //}
797b05aa8b5SJohn Scipione
79802be5353SAxel Dörfler
79902be5353SAxel Dörfler void
UpdatePoseViews(BMessage * reportMessage)80002be5353SAxel Dörfler BClipboardRefsWatcher::UpdatePoseViews(BMessage* reportMessage)
80102be5353SAxel Dörfler {
80202be5353SAxel Dörfler if (Lock()) {
80302be5353SAxel Dörfler // check if it was cleared, if so clear watching
80402be5353SAxel Dörfler bool clearClipboard = false;
80502be5353SAxel Dörfler if (reportMessage->FindBool("clearClipboard", &clearClipboard) == B_OK
80602be5353SAxel Dörfler && clearClipboard) {
80702be5353SAxel Dörfler stop_watching(this);
80802be5353SAxel Dörfler watch_node(NULL, B_WATCH_MOUNT, this);
80902be5353SAxel Dörfler }
81002be5353SAxel Dörfler
81102be5353SAxel Dörfler // loop through reported node_ref's movemodes:
81202be5353SAxel Dörfler // move or copy: start watching node_ref
81302be5353SAxel Dörfler // remove: stop watching node_ref
81402be5353SAxel Dörfler int32 index = 0;
81502be5353SAxel Dörfler TClipboardNodeRef* tcnode = NULL;
81602be5353SAxel Dörfler ssize_t size;
817ea001e58SJohn Scipione while (reportMessage->FindData("tcnode", T_CLIPBOARD_NODE, index,
818ea001e58SJohn Scipione (const void**)&tcnode, &size) == B_OK) {
81902be5353SAxel Dörfler if (tcnode->moveMode == kDelete) {
82002be5353SAxel Dörfler watch_node(&tcnode->node, B_STOP_WATCHING, this);
82102be5353SAxel Dörfler } else {
82202be5353SAxel Dörfler watch_node(&tcnode->node, B_STOP_WATCHING, this);
82302be5353SAxel Dörfler TTracker::WatchNode(&tcnode->node, B_WATCH_NAME, this);
82402be5353SAxel Dörfler fRefsInClipboard = true;
82502be5353SAxel Dörfler }
82602be5353SAxel Dörfler index++;
82702be5353SAxel Dörfler }
82802be5353SAxel Dörfler
82902be5353SAxel Dörfler // send report
83002be5353SAxel Dörfler int32 items = fNotifyList.CountItems();
83102be5353SAxel Dörfler for (int32 i = 0;i < items;i++) {
83202be5353SAxel Dörfler fNotifyList.ItemAt(i)->SendMessage(reportMessage);
83302be5353SAxel Dörfler }
83402be5353SAxel Dörfler Unlock();
83502be5353SAxel Dörfler }
83602be5353SAxel Dörfler }
83702be5353SAxel Dörfler
83802be5353SAxel Dörfler
83902be5353SAxel Dörfler void
MessageReceived(BMessage * message)84002be5353SAxel Dörfler BClipboardRefsWatcher::MessageReceived(BMessage* message)
84102be5353SAxel Dörfler {
84202be5353SAxel Dörfler if (message->what == B_CLIPBOARD_CHANGED && fRefsInClipboard) {
84302be5353SAxel Dörfler if (!(fRefsInClipboard = FSClipboardHasRefs()))
84402be5353SAxel Dörfler Clear();
84502be5353SAxel Dörfler return;
84602be5353SAxel Dörfler } else if (message->what != B_NODE_MONITOR) {
84702be5353SAxel Dörfler _inherited::MessageReceived(message);
84802be5353SAxel Dörfler return;
84902be5353SAxel Dörfler }
85002be5353SAxel Dörfler
85102be5353SAxel Dörfler switch (message->FindInt32("opcode")) {
85202be5353SAxel Dörfler case B_ENTRY_MOVED:
85302be5353SAxel Dörfler {
85402be5353SAxel Dörfler ino_t toDir;
85502be5353SAxel Dörfler ino_t fromDir;
85602be5353SAxel Dörfler node_ref node;
85702be5353SAxel Dörfler const char* name = NULL;
85802be5353SAxel Dörfler message->FindInt64("from directory", &fromDir);
85902be5353SAxel Dörfler message->FindInt64("to directory", &toDir);
86002be5353SAxel Dörfler message->FindInt64("node", &node.node);
86102be5353SAxel Dörfler message->FindInt32("device", &node.device);
86202be5353SAxel Dörfler message->FindString("name", &name);
86302be5353SAxel Dörfler entry_ref ref(node.device, toDir, name);
86402be5353SAxel Dörfler UpdateNode(&node, &ref);
86502be5353SAxel Dörfler break;
86602be5353SAxel Dörfler }
86702be5353SAxel Dörfler
86802be5353SAxel Dörfler case B_DEVICE_UNMOUNTED:
86902be5353SAxel Dörfler {
87002be5353SAxel Dörfler dev_t device;
87102be5353SAxel Dörfler message->FindInt32("device", &device);
87202be5353SAxel Dörfler RemoveNodesByDevice(device);
87302be5353SAxel Dörfler break;
87402be5353SAxel Dörfler }
87502be5353SAxel Dörfler
87602be5353SAxel Dörfler case B_ENTRY_REMOVED:
87702be5353SAxel Dörfler {
87802be5353SAxel Dörfler node_ref node;
87902be5353SAxel Dörfler message->FindInt64("node", &node.node);
88002be5353SAxel Dörfler message->FindInt32("device", &node.device);
88102be5353SAxel Dörfler RemoveNode(&node, true);
88202be5353SAxel Dörfler break;
88302be5353SAxel Dörfler }
88402be5353SAxel Dörfler }
88502be5353SAxel Dörfler }
886