xref: /haiku/src/kits/tracker/FSClipboard.cpp (revision b05aa8b5b16e5b4f420a35c37805c6387df98737)
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 
3502be5353SAxel Dörfler #include "FSClipboard.h"
3602be5353SAxel Dörfler #include <Clipboard.h>
3702be5353SAxel Dörfler #include <Alert.h>
384ed28a57SAlexandre Deckner #include <Catalog.h>
394ed28a57SAlexandre Deckner #include <Locale.h>
4002be5353SAxel Dörfler #include <NodeMonitor.h>
4102be5353SAxel Dörfler #include "Commands.h"
4202be5353SAxel Dörfler #include "FSUtils.h"
4302be5353SAxel Dörfler #include "Tracker.h"
4402be5353SAxel Dörfler 
454ed28a57SAlexandre Deckner 
4602be5353SAxel Dörfler // prototypes
4702be5353SAxel Dörfler static void MakeNodeFromName(node_ref* node, char* name);
4802be5353SAxel Dörfler static inline void MakeRefName(char* refName, const node_ref* node);
4902be5353SAxel Dörfler static inline void MakeModeName(char* modeName, const node_ref* node);
5002be5353SAxel Dörfler static inline void MakeModeNameFromRefName(char* modeName, char* refName);
5102be5353SAxel Dörfler static inline bool CompareModeAndRefName(const char* modeName, const char* refName);
5202be5353SAxel Dörfler 
5302be5353SAxel Dörfler /*
5402be5353SAxel Dörfler static bool
5502be5353SAxel Dörfler FSClipboardCheckIntegrity()
5602be5353SAxel Dörfler {
5702be5353SAxel Dörfler 	return true;
5802be5353SAxel Dörfler }
5902be5353SAxel Dörfler */
6002be5353SAxel Dörfler 
617befa79aSAxel Dörfler static void
627befa79aSAxel Dörfler MakeNodeFromName(node_ref* node, char* name)
637befa79aSAxel Dörfler {
647befa79aSAxel Dörfler 	char* nodeString = strchr(name, '_');
657befa79aSAxel Dörfler 	if (nodeString != NULL) {
667befa79aSAxel Dörfler 		node->node = strtoll(nodeString + 1, (char**)NULL, 10);
677befa79aSAxel Dörfler 		node->device = atoi(name + 1);
687befa79aSAxel Dörfler 	}
697befa79aSAxel Dörfler }
707befa79aSAxel Dörfler 
717befa79aSAxel Dörfler 
727befa79aSAxel Dörfler static inline void
737befa79aSAxel Dörfler MakeRefName(char* refName, const node_ref* node)
747befa79aSAxel Dörfler {
757befa79aSAxel Dörfler 	sprintf(refName, "r%ld_%Ld", node->device, node->node);
767befa79aSAxel Dörfler }
777befa79aSAxel Dörfler 
787befa79aSAxel Dörfler 
797befa79aSAxel Dörfler static inline void
807befa79aSAxel Dörfler MakeModeName(char* modeName, const node_ref* node)
817befa79aSAxel Dörfler {
827befa79aSAxel Dörfler 	sprintf(modeName, "m%ld_%Ld", node->device, node->node);
837befa79aSAxel Dörfler }
847befa79aSAxel Dörfler 
857befa79aSAxel Dörfler 
867befa79aSAxel Dörfler static inline void
877befa79aSAxel Dörfler MakeModeName(char* name)
887befa79aSAxel Dörfler {
897befa79aSAxel Dörfler 	name[0] = 'm';
907befa79aSAxel Dörfler }
917befa79aSAxel Dörfler 
927befa79aSAxel Dörfler 
937befa79aSAxel Dörfler static inline void
947befa79aSAxel Dörfler MakeModeNameFromRefName(char* modeName, char* refName)
957befa79aSAxel Dörfler {
967befa79aSAxel Dörfler 	strcpy(modeName, refName);
977befa79aSAxel Dörfler 	modeName[0] = 'm';
987befa79aSAxel Dörfler }
997befa79aSAxel Dörfler 
1007befa79aSAxel Dörfler 
1017befa79aSAxel Dörfler static inline bool
1027befa79aSAxel Dörfler CompareModeAndRefName(const char* modeName, const char* refName)
1037befa79aSAxel Dörfler {
1047befa79aSAxel Dörfler 	return !strcmp(refName + 1, modeName + 1);
1057befa79aSAxel Dörfler }
1067befa79aSAxel Dörfler 
1077befa79aSAxel Dörfler 
1087befa79aSAxel Dörfler //	#pragma mark -
1097befa79aSAxel Dörfler 
1107befa79aSAxel Dörfler 
111546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
112546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "FSClipBoard"
1134ed28a57SAlexandre Deckner 
11402be5353SAxel Dörfler bool
11502be5353SAxel Dörfler FSClipboardHasRefs()
11602be5353SAxel Dörfler {
11702be5353SAxel Dörfler 	bool result = false;
11802be5353SAxel Dörfler 
11902be5353SAxel Dörfler 	if (be_clipboard->Lock()) {
12002be5353SAxel Dörfler 		BMessage* clip = be_clipboard->Data();
12102be5353SAxel Dörfler 		if (clip != NULL) {
12202be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
12302be5353SAxel Dörfler 			const
12402be5353SAxel Dörfler #endif
12502be5353SAxel Dörfler 			char* refName;
12602be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
12702be5353SAxel Dörfler 			const
12802be5353SAxel Dörfler #endif
12902be5353SAxel Dörfler 			char* modeName;
13002be5353SAxel Dörfler 			uint32 type;
13102be5353SAxel Dörfler 			int32 count;
13202be5353SAxel Dörfler 			if (clip->GetInfo(B_REF_TYPE, 0, &refName, &type, &count) == B_OK
13302be5353SAxel Dörfler 				&& clip->GetInfo(B_INT32_TYPE, 0, &modeName, &type, &count) == B_OK)
13402be5353SAxel Dörfler 				result = CompareModeAndRefName(modeName, refName);
13502be5353SAxel Dörfler 		}
13602be5353SAxel Dörfler 		be_clipboard->Unlock();
13702be5353SAxel Dörfler 	}
13802be5353SAxel Dörfler 	return result;
13902be5353SAxel Dörfler }
14002be5353SAxel Dörfler 
14102be5353SAxel Dörfler 
14202be5353SAxel Dörfler void
14302be5353SAxel Dörfler FSClipboardStartWatch(BMessenger target)
14402be5353SAxel Dörfler {
14502be5353SAxel Dörfler 	if (dynamic_cast<TTracker*>(be_app) != NULL)
14602be5353SAxel Dörfler 		((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target);
14702be5353SAxel Dörfler 	else {
14802be5353SAxel Dörfler 		// this code is used by external apps using objects using FSClipboard functions
14902be5353SAxel Dörfler 		// i.e: applications using FilePanel
15002be5353SAxel Dörfler 		BMessenger messenger(kTrackerSignature);
15102be5353SAxel Dörfler 		if (messenger.IsValid()) {
15202be5353SAxel Dörfler 			BMessage message(kStartWatchClipboardRefs);
15302be5353SAxel Dörfler 			message.AddMessenger("target", target);
15402be5353SAxel Dörfler 			messenger.SendMessage(&message);
15502be5353SAxel Dörfler 		}
15602be5353SAxel Dörfler 	}
15702be5353SAxel Dörfler }
15802be5353SAxel Dörfler 
15902be5353SAxel Dörfler 
16002be5353SAxel Dörfler void
16102be5353SAxel Dörfler FSClipboardStopWatch(BMessenger target)
16202be5353SAxel Dörfler {
16302be5353SAxel Dörfler 	if (dynamic_cast<TTracker*>(be_app) != NULL)
16402be5353SAxel Dörfler 		((TTracker*)be_app)->ClipboardRefsWatcher()->AddToNotifyList(target);
16502be5353SAxel Dörfler 	else {
16602be5353SAxel Dörfler 		// this code is used by external apps using objects using FSClipboard functions
16702be5353SAxel Dörfler 		// i.e: applications using FilePanel
16802be5353SAxel Dörfler 		BMessenger messenger(kTrackerSignature);
16902be5353SAxel Dörfler 		if (messenger.IsValid()) {
17002be5353SAxel Dörfler 			BMessage message(kStopWatchClipboardRefs);
17102be5353SAxel Dörfler 			message.AddMessenger("target", target);
17202be5353SAxel Dörfler 			messenger.SendMessage(&message);
17302be5353SAxel Dörfler 		}
17402be5353SAxel Dörfler 	}
17502be5353SAxel Dörfler }
17602be5353SAxel Dörfler 
17702be5353SAxel Dörfler 
17802be5353SAxel Dörfler void
17902be5353SAxel Dörfler FSClipboardClear()
18002be5353SAxel Dörfler {
18102be5353SAxel Dörfler 	if (!be_clipboard->Lock())
18202be5353SAxel Dörfler 		return;
18302be5353SAxel Dörfler 
18402be5353SAxel Dörfler 	be_clipboard->Clear();
18502be5353SAxel Dörfler 	be_clipboard->Commit();
18602be5353SAxel Dörfler 	be_clipboard->Unlock();
18702be5353SAxel Dörfler }
18802be5353SAxel Dörfler 
18902be5353SAxel Dörfler 
19002be5353SAxel Dörfler /** This function adds the given poses list to the clipboard, for both copy
19102be5353SAxel Dörfler  *	and cut. All poses in the list must have "directory" as parent.
19202be5353SAxel Dörfler  *	"moveMode" is either kMoveSelection or kCopySelection.
19302be5353SAxel Dörfler  *	It will check if the entries are already present, so that there can only
19402be5353SAxel Dörfler  *	be one reference to them in the clipboard.
19502be5353SAxel Dörfler  */
19602be5353SAxel Dörfler 
19702be5353SAxel Dörfler uint32
19802be5353SAxel Dörfler FSClipboardAddPoses(const node_ref* directory, PoseList* list, uint32 moveMode,
19902be5353SAxel Dörfler 	bool clearClipboard)
20002be5353SAxel Dörfler {
20102be5353SAxel Dörfler 	uint32 refsAdded = 0;
20202be5353SAxel Dörfler 	int32 listCount = list->CountItems();
20302be5353SAxel Dörfler 
20402be5353SAxel Dörfler 	if (listCount == 0 || !be_clipboard->Lock())
20502be5353SAxel Dörfler 		return 0;
20602be5353SAxel Dörfler 
20702be5353SAxel Dörfler 	// update message to be send to all listeners
20802be5353SAxel Dörfler 	BMessage updateMessage(kFSClipboardChanges);
20902be5353SAxel Dörfler 	updateMessage.AddInt32("device", directory->device);
21002be5353SAxel Dörfler 	updateMessage.AddInt64("directory", directory->node);
21102be5353SAxel Dörfler 	updateMessage.AddBool("clearClipboard", clearClipboard);
21202be5353SAxel Dörfler 
21302be5353SAxel Dörfler 	TClipboardNodeRef clipNode;
21402be5353SAxel Dörfler 	clipNode.moveMode = moveMode;
21502be5353SAxel Dörfler 
21602be5353SAxel Dörfler 	if (clearClipboard)
21702be5353SAxel Dörfler 		be_clipboard->Clear();
21802be5353SAxel Dörfler 
21902be5353SAxel Dörfler 	BMessage* clip = be_clipboard->Data();
22002be5353SAxel Dörfler 	if (clip != NULL) {
22102be5353SAxel Dörfler 		for (int32 index = 0; index < listCount; index++) {
22202be5353SAxel Dörfler 			char refName[64], modeName[64];
22302be5353SAxel Dörfler 			BPose* pose = (BPose*)list->ItemAt(index);
22402be5353SAxel Dörfler 			Model* model = pose->TargetModel();
22502be5353SAxel Dörfler 			const node_ref* node = model->NodeRef();
22602be5353SAxel Dörfler 
22702be5353SAxel Dörfler 			BEntry entry;
22802be5353SAxel Dörfler 			model->GetEntry(&entry);
22902be5353SAxel Dörfler 			if (model->IsVolume()
23002be5353SAxel Dörfler 				|| model->IsRoot()
231d9626569SRene Gollent 				|| model->IsTrash()
23289af0548SRene Gollent 				|| model->IsDesktop())
23302be5353SAxel Dörfler 				continue;
23402be5353SAxel Dörfler 
23502be5353SAxel Dörfler 			MakeRefName(refName, node);
23602be5353SAxel Dörfler 			MakeModeNameFromRefName(modeName, refName);
23702be5353SAxel Dörfler 
23802be5353SAxel Dörfler 			if (clearClipboard) {
2395422febdSStephan Aßmus 				if (clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
24002be5353SAxel Dörfler 					if (clip->AddRef(refName, model->EntryRef()) == B_OK) {
24102be5353SAxel Dörfler 						pose->SetClipboardMode(moveMode);
24202be5353SAxel Dörfler 
24302be5353SAxel Dörfler 						clipNode.node = *node;
2445422febdSStephan Aßmus 						updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2455422febdSStephan Aßmus 							&clipNode, sizeof(TClipboardNodeRef), true,
2465422febdSStephan Aßmus 							listCount);
24702be5353SAxel Dörfler 
24802be5353SAxel Dörfler 						refsAdded++;
24902be5353SAxel Dörfler 					} else
25002be5353SAxel Dörfler 						clip->RemoveName(modeName);
2515422febdSStephan Aßmus 				}
25202be5353SAxel Dörfler 			} else {
25302be5353SAxel Dörfler 				if (clip->ReplaceInt32(modeName, (int32)moveMode) == B_OK) {
25402be5353SAxel Dörfler 					// replace old mode if entry already exists in clipboard
25502be5353SAxel Dörfler 					if (clip->ReplaceRef(refName, model->EntryRef()) == B_OK) {
25602be5353SAxel Dörfler 						pose->SetClipboardMode(moveMode);
25702be5353SAxel Dörfler 
25802be5353SAxel Dörfler 						clipNode.node = *node;
2595422febdSStephan Aßmus 						updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2605422febdSStephan Aßmus 							&clipNode, sizeof(TClipboardNodeRef), true,
2615422febdSStephan Aßmus 							listCount);
26202be5353SAxel Dörfler 
26302be5353SAxel Dörfler 						refsAdded++;
26402be5353SAxel Dörfler 					} else {
26502be5353SAxel Dörfler 						clip->RemoveName(modeName);
26602be5353SAxel Dörfler 
26702be5353SAxel Dörfler 						clipNode.node = *node;
26802be5353SAxel Dörfler 						clipNode.moveMode = kDelete;	// note removing node
2695422febdSStephan Aßmus 						updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2705422febdSStephan Aßmus 							&clipNode, sizeof(TClipboardNodeRef), true,
2715422febdSStephan Aßmus 							listCount);
2725422febdSStephan Aßmus 						clipNode.moveMode = moveMode;
2735422febdSStephan Aßmus 							// set it back to current value
27402be5353SAxel Dörfler 					}
27502be5353SAxel Dörfler 				} else {
2767befa79aSAxel Dörfler 					// add it if it doesn't exist
27702be5353SAxel Dörfler 					if (clip->AddRef(refName, model->EntryRef()) == B_OK
27802be5353SAxel Dörfler 						&& clip->AddInt32(modeName, (int32)moveMode) == B_OK) {
27902be5353SAxel Dörfler 						pose->SetClipboardMode(moveMode);
28002be5353SAxel Dörfler 
28102be5353SAxel Dörfler 						clipNode.node = *node;
2825422febdSStephan Aßmus 						updateMessage.AddData("tcnode", T_CLIPBOARD_NODE,
2835422febdSStephan Aßmus 							&clipNode, sizeof(TClipboardNodeRef), true,
2845422febdSStephan Aßmus 							listCount);
28502be5353SAxel Dörfler 
28602be5353SAxel Dörfler 						refsAdded++;
28702be5353SAxel Dörfler 					} else {
28802be5353SAxel Dörfler 						clip->RemoveName(modeName);
28902be5353SAxel Dörfler 						clip->RemoveName(refName);
2907befa79aSAxel Dörfler 						// here notifying delete isn't needed as node didn't
2917befa79aSAxel Dörfler 						// exist in clipboard
29202be5353SAxel Dörfler 					}
29302be5353SAxel Dörfler 				}
29402be5353SAxel Dörfler 			}
29502be5353SAxel Dörfler 		}
29602be5353SAxel Dörfler 		be_clipboard->Commit();
29702be5353SAxel Dörfler 	}
29802be5353SAxel Dörfler 	be_clipboard->Unlock();
29902be5353SAxel Dörfler 
30002be5353SAxel Dörfler 	BMessenger(kTrackerSignature).SendMessage(&updateMessage);
30102be5353SAxel Dörfler 		// Tracker will notify all listeners
30202be5353SAxel Dörfler 
30302be5353SAxel Dörfler 	return refsAdded;
30402be5353SAxel Dörfler }
30502be5353SAxel Dörfler 
30602be5353SAxel Dörfler 
30702be5353SAxel Dörfler uint32
30802be5353SAxel Dörfler FSClipboardRemovePoses(const node_ref* directory, PoseList* list)
30902be5353SAxel Dörfler {
31002be5353SAxel Dörfler 	if (!be_clipboard->Lock())
31102be5353SAxel Dörfler 		return 0;
31202be5353SAxel Dörfler 
31302be5353SAxel Dörfler 	// update message to be send to all listeners
31402be5353SAxel Dörfler 	BMessage updateMessage(kFSClipboardChanges);
31502be5353SAxel Dörfler 	updateMessage.AddInt32("device", directory->device);
31602be5353SAxel Dörfler 	updateMessage.AddInt64("directory", directory->node);
31702be5353SAxel Dörfler 	updateMessage.AddBool("clearClipboard", false);
31802be5353SAxel Dörfler 
31902be5353SAxel Dörfler 	TClipboardNodeRef clipNode;
32002be5353SAxel Dörfler 	clipNode.moveMode = kDelete;
32102be5353SAxel Dörfler 
32202be5353SAxel Dörfler 	uint32 refsRemoved = 0;
32302be5353SAxel Dörfler 
32402be5353SAxel Dörfler 	BMessage* clip = be_clipboard->Data();
32502be5353SAxel Dörfler 	if (clip != NULL) {
32602be5353SAxel Dörfler 		int32 listCount = list->CountItems();
32702be5353SAxel Dörfler 
32802be5353SAxel Dörfler 		for (int32 index = 0; index < listCount; index++) {
32902be5353SAxel Dörfler 			char refName[64], modeName[64];
33002be5353SAxel Dörfler 			BPose* pose = (BPose*)list->ItemAt(index);
33102be5353SAxel Dörfler 
33202be5353SAxel Dörfler 			clipNode.node = *pose->TargetModel()->NodeRef();
33302be5353SAxel Dörfler 			MakeRefName(refName, &clipNode.node);
33402be5353SAxel Dörfler 			MakeModeName(modeName);
33502be5353SAxel Dörfler 
33602be5353SAxel Dörfler 			if (clip->RemoveName(refName) == B_OK && clip->RemoveName(modeName)) {
33702be5353SAxel Dörfler 				updateMessage.AddData("tcnode", T_CLIPBOARD_NODE, &clipNode,
33802be5353SAxel Dörfler 					sizeof(TClipboardNodeRef), true, listCount);
33902be5353SAxel Dörfler 				refsRemoved++;
34002be5353SAxel Dörfler 			}
34102be5353SAxel Dörfler 		}
34202be5353SAxel Dörfler 		be_clipboard->Commit();
34302be5353SAxel Dörfler 	}
34402be5353SAxel Dörfler 	be_clipboard->Unlock();
34502be5353SAxel Dörfler 
34602be5353SAxel Dörfler 	BMessenger(kTrackerSignature).SendMessage(&updateMessage);
34702be5353SAxel Dörfler 		// Tracker will notify all listeners
34802be5353SAxel Dörfler 
34902be5353SAxel Dörfler 	return refsRemoved;
35002be5353SAxel Dörfler }
35102be5353SAxel Dörfler 
35202be5353SAxel Dörfler 
35302be5353SAxel Dörfler /** Pastes entries from the clipboard to the target model's directory.
35402be5353SAxel Dörfler  *	Updates moveModes and notifies listeners if necessary.
35502be5353SAxel Dörfler  */
35602be5353SAxel Dörfler 
35702be5353SAxel Dörfler bool
35802be5353SAxel Dörfler FSClipboardPaste(Model* model, uint32 linksMode)
35902be5353SAxel Dörfler {
36002be5353SAxel Dörfler 	if (!FSClipboardHasRefs())
36102be5353SAxel Dörfler 		return false;
36202be5353SAxel Dörfler 
36302be5353SAxel Dörfler 	BMessenger tracker(kTrackerSignature);
36402be5353SAxel Dörfler 
36502be5353SAxel Dörfler 	node_ref* destNodeRef = (node_ref*)model->NodeRef();
36602be5353SAxel Dörfler 
36702be5353SAxel Dörfler 	// these will be passed to the asynchronous copy/move process
36802be5353SAxel Dörfler 	BObjectList<entry_ref>* moveList = new BObjectList<entry_ref>(0, true);
36902be5353SAxel Dörfler 	BObjectList<entry_ref>* copyList = new BObjectList<entry_ref>(0, true);
37002be5353SAxel Dörfler 
37102be5353SAxel Dörfler 	if ((be_clipboard->Lock())) {
37202be5353SAxel Dörfler 		BMessage* clip = be_clipboard->Data();
37302be5353SAxel Dörfler 		if (clip != NULL) {
37402be5353SAxel Dörfler 			char modeName[64];
37502be5353SAxel Dörfler 			uint32 moveMode = 0;
37602be5353SAxel Dörfler 
37702be5353SAxel Dörfler 			BMessage* updateMessage = NULL;
37802be5353SAxel Dörfler 			node_ref updateNodeRef;
37902be5353SAxel Dörfler 			updateNodeRef.device = -1;
38002be5353SAxel Dörfler 
38102be5353SAxel Dörfler 			char* refName;
38202be5353SAxel Dörfler 			type_code type;
38302be5353SAxel Dörfler 			int32 count;
38402be5353SAxel Dörfler 			for (int32 index = 0; clip->GetInfo(B_REF_TYPE, index,
38502be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
38602be5353SAxel Dörfler 				(const char**)
38702be5353SAxel Dörfler #endif
38802be5353SAxel Dörfler 				&refName, &type, &count) == B_OK; index++) {
38902be5353SAxel Dörfler 				entry_ref ref;
39002be5353SAxel Dörfler 				if (clip->FindRef(refName, &ref) != B_OK)
39102be5353SAxel Dörfler 					continue;
39202be5353SAxel Dörfler 
39302be5353SAxel Dörfler 				// If the entry_ref's directory has changed, send previous notification
39402be5353SAxel Dörfler 				// (if any), and start new one for the new directory
39502be5353SAxel Dörfler 				if (updateNodeRef.device != ref.device
39602be5353SAxel Dörfler 					|| updateNodeRef.node != ref.directory) {
39702be5353SAxel Dörfler 					if (updateMessage != NULL) {
39802be5353SAxel Dörfler 						tracker.SendMessage(updateMessage);
39902be5353SAxel Dörfler 						delete updateMessage;
40002be5353SAxel Dörfler 					}
40102be5353SAxel Dörfler 
40202be5353SAxel Dörfler 					updateNodeRef.device = ref.device;
40302be5353SAxel Dörfler 					updateNodeRef.node = ref.directory;
40402be5353SAxel Dörfler 
40502be5353SAxel Dörfler 					updateMessage = new BMessage(kFSClipboardChanges);
40602be5353SAxel Dörfler 					updateMessage->AddInt32("device", updateNodeRef.device);
40702be5353SAxel Dörfler 					updateMessage->AddInt64("directory", updateNodeRef.node);
40802be5353SAxel Dörfler 				}
40902be5353SAxel Dörfler 
41002be5353SAxel Dörfler 				// we need this data later on
41102be5353SAxel Dörfler 				MakeModeNameFromRefName(modeName, refName);
41202be5353SAxel Dörfler 				if (!linksMode && clip->FindInt32(modeName, (int32*)&moveMode) != B_OK)
41302be5353SAxel Dörfler 					continue;
41402be5353SAxel Dörfler 
41502be5353SAxel Dörfler 				BEntry entry(&ref);
41602be5353SAxel Dörfler 
41702be5353SAxel Dörfler 				uint32 newMoveMode = 0;
41802be5353SAxel Dörfler 				bool sameDirectory = destNodeRef->device == ref.device && destNodeRef->node == ref.directory;
41902be5353SAxel Dörfler 
42002be5353SAxel Dörfler 				if (!entry.Exists()) {
42102be5353SAxel Dörfler 					// The entry doesn't exist anymore, so we'll remove
42202be5353SAxel Dörfler 					// that entry from the clipboard as well
42302be5353SAxel Dörfler 					clip->RemoveName(refName);
42402be5353SAxel Dörfler 					clip->RemoveName(modeName);
42502be5353SAxel Dörfler 
42602be5353SAxel Dörfler 					newMoveMode = kDelete;
42702be5353SAxel Dörfler 				} else {
42802be5353SAxel Dörfler 					// the entry does exist, so lets see what we will
42902be5353SAxel Dörfler 					// do with it
43002be5353SAxel Dörfler 					if (!sameDirectory) {
43102be5353SAxel Dörfler 						if (linksMode || moveMode == kMoveSelectionTo) {
43202be5353SAxel Dörfler 							// the linksMode uses the moveList as well
43302be5353SAxel Dörfler 							moveList->AddItem(new entry_ref(ref));
43402be5353SAxel Dörfler 						} else if (moveMode == kCopySelectionTo)
43502be5353SAxel Dörfler 							copyList->AddItem(new entry_ref(ref));
43602be5353SAxel Dörfler 					}
43702be5353SAxel Dörfler 
43802be5353SAxel Dörfler 					// if the entry should have been removed from its directory,
43902be5353SAxel Dörfler 					// we want to copy that entry next time, no matter if the
44002be5353SAxel Dörfler 					// items don't have to be moved at all (source == target)
44102be5353SAxel Dörfler 					if (moveMode == kMoveSelectionTo)
44202be5353SAxel Dörfler 						newMoveMode = kCopySelectionTo;
44302be5353SAxel Dörfler 				}
44402be5353SAxel Dörfler 
44502be5353SAxel Dörfler 				// add the change to the update message (if necessary)
44602be5353SAxel Dörfler 				if (newMoveMode) {
44702be5353SAxel Dörfler 					clip->ReplaceInt32(modeName, kCopySelectionTo);
44802be5353SAxel Dörfler 
44902be5353SAxel Dörfler 					TClipboardNodeRef clipNode;
45002be5353SAxel Dörfler 					MakeNodeFromName(&clipNode.node, modeName);
45102be5353SAxel Dörfler 					clipNode.moveMode = kDelete;
45202be5353SAxel Dörfler 					updateMessage->AddData("tcnode", T_CLIPBOARD_NODE, &clipNode,
45302be5353SAxel Dörfler 						sizeof(TClipboardNodeRef), true);
45402be5353SAxel Dörfler 				}
45502be5353SAxel Dörfler 			}
45602be5353SAxel Dörfler 			be_clipboard->Commit();
45702be5353SAxel Dörfler 
45802be5353SAxel Dörfler 			// send notification for the last directory
45902be5353SAxel Dörfler 			if (updateMessage != NULL) {
46002be5353SAxel Dörfler 				tracker.SendMessage(updateMessage);
46102be5353SAxel Dörfler 				delete updateMessage;
46202be5353SAxel Dörfler 			}
46302be5353SAxel Dörfler 		}
46402be5353SAxel Dörfler 		be_clipboard->Unlock();
46502be5353SAxel Dörfler 	}
46602be5353SAxel Dörfler 
46702be5353SAxel Dörfler 	bool okToMove = true;
46802be5353SAxel Dörfler 
46902be5353SAxel Dörfler 	// can't copy/paste to root('/') directory
47002be5353SAxel Dörfler 	if (model->IsRoot()) {
4714ed28a57SAlexandre Deckner 		BAlert* alert = new BAlert("",
4724ed28a57SAlexandre Deckner 			B_TRANSLATE("You must drop items on one of the disk icons "
4734ed28a57SAlexandre Deckner 			"in the \"Disks\" window."), B_TRANSLATE("Cancel"),	NULL, NULL,
4744ed28a57SAlexandre Deckner 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
475019f90e6SJonas Sundström 		alert->SetShortcut(0, B_ESCAPE);
476019f90e6SJonas Sundström 		alert->Go();
47702be5353SAxel Dörfler 		okToMove = false;
47802be5353SAxel Dörfler 	}
47902be5353SAxel Dörfler 
48002be5353SAxel Dörfler 	BEntry entry;
48102be5353SAxel Dörfler 	model->GetEntry(&entry);
48202be5353SAxel Dörfler 
48302be5353SAxel Dörfler 	// can't copy items into the trash
484d9626569SRene Gollent 	if (copyList->CountItems() > 0 && model->IsTrash()) {
4854ed28a57SAlexandre Deckner 		BAlert* alert = new BAlert("",
4864ed28a57SAlexandre Deckner 			B_TRANSLATE("Sorry, you can't copy items to the Trash."),
4874ed28a57SAlexandre Deckner 			B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL,
4884ed28a57SAlexandre Deckner 			B_WARNING_ALERT);
489019f90e6SJonas Sundström 		alert->SetShortcut(0, B_ESCAPE);
490019f90e6SJonas Sundström 		alert->Go();
49102be5353SAxel Dörfler 		okToMove = false;
49202be5353SAxel Dörfler 	}
49302be5353SAxel Dörfler 
49402be5353SAxel Dörfler 	if (!okToMove) {
49502be5353SAxel Dörfler 		// there was some problem with our target, so we bail out here
49602be5353SAxel Dörfler 		delete moveList;
49702be5353SAxel Dörfler 		delete copyList;
49802be5353SAxel Dörfler 		return false;
49902be5353SAxel Dörfler 	}
50002be5353SAxel Dörfler 
50102be5353SAxel Dörfler 	// asynchronous calls take over ownership of the objects passed to it
50202be5353SAxel Dörfler 	if (moveList->CountItems() > 0)
50302be5353SAxel Dörfler 		FSMoveToFolder(moveList, new BEntry(entry), linksMode ? linksMode : kMoveSelectionTo);
50402be5353SAxel Dörfler 	else
50502be5353SAxel Dörfler 		delete moveList;
50602be5353SAxel Dörfler 
50702be5353SAxel Dörfler 	if (copyList->CountItems() > 0)
50802be5353SAxel Dörfler 		FSMoveToFolder(copyList, new BEntry(entry), kCopySelectionTo);
50902be5353SAxel Dörfler 	else
51002be5353SAxel Dörfler 		delete copyList;
51102be5353SAxel Dörfler 
51202be5353SAxel Dörfler 	return true;
51302be5353SAxel Dörfler }
51402be5353SAxel Dörfler 
51502be5353SAxel Dörfler 
516*b05aa8b5SJohn Scipione // Seek node in clipboard, if found return it's moveMode
517*b05aa8b5SJohn Scipione // else return 0
51802be5353SAxel Dörfler uint32
51995da0645SRene Gollent FSClipboardFindNodeMode(Model* model, bool autoLock, bool updateRefIfNeeded)
52002be5353SAxel Dörfler {
52102be5353SAxel Dörfler 	int32 moveMode = 0;
52295da0645SRene Gollent 	if (autoLock) {
52395da0645SRene Gollent 		if (!be_clipboard->Lock())
52495da0645SRene Gollent 			return 0;
52595da0645SRene Gollent 	}
52602be5353SAxel Dörfler 	bool remove = false;
52702be5353SAxel Dörfler 	bool change = false;
52802be5353SAxel Dörfler 
52902be5353SAxel Dörfler 	BMessage* clip = be_clipboard->Data();
53002be5353SAxel Dörfler 	if (clip != NULL) {
53102be5353SAxel Dörfler 		const node_ref* node = model->NodeRef();
53202be5353SAxel Dörfler 		char modeName[64];
53302be5353SAxel Dörfler 		MakeModeName(modeName, node);
53402be5353SAxel Dörfler 		if ((clip->FindInt32(modeName, &moveMode) == B_OK)) {
53502be5353SAxel Dörfler 			const entry_ref* ref = model->EntryRef();
53602be5353SAxel Dörfler 			entry_ref clipref;
53702be5353SAxel Dörfler 			char refName[64];
53802be5353SAxel Dörfler 			MakeRefName(refName, node);
53902be5353SAxel Dörfler 			if ((clip->FindRef(refName, &clipref) == B_OK)) {
54002be5353SAxel Dörfler 				if (clipref != *ref) {
54102be5353SAxel Dörfler 					if (updateRefIfNeeded) {
54202be5353SAxel Dörfler 						clip->ReplaceRef(refName, ref);
54302be5353SAxel Dörfler 						change = true;
54402be5353SAxel Dörfler 					} else {
54502be5353SAxel Dörfler 						clip->RemoveName(refName);
54602be5353SAxel Dörfler 						clip->RemoveName(modeName);
54702be5353SAxel Dörfler 						change = true;
54802be5353SAxel Dörfler 						remove = true;
54902be5353SAxel Dörfler 						moveMode = 0;
55002be5353SAxel Dörfler 					}
55102be5353SAxel Dörfler 				}
55202be5353SAxel Dörfler 			} else {
55302be5353SAxel Dörfler 				clip->RemoveName(modeName);
55402be5353SAxel Dörfler 				change = true;
55502be5353SAxel Dörfler 				remove = true;
55602be5353SAxel Dörfler 				moveMode = 0;
55702be5353SAxel Dörfler 			}
55802be5353SAxel Dörfler 		}
55902be5353SAxel Dörfler 	}
56002be5353SAxel Dörfler 	if (change)
56102be5353SAxel Dörfler 		be_clipboard->Commit();
56202be5353SAxel Dörfler 
56395da0645SRene Gollent 	if (autoLock)
56402be5353SAxel Dörfler 		be_clipboard->Unlock();
56502be5353SAxel Dörfler 
56602be5353SAxel Dörfler 	if (remove)
56702be5353SAxel Dörfler 		FSClipboardRemove(model);
56802be5353SAxel Dörfler 
56902be5353SAxel Dörfler 	return (uint32)moveMode;
57002be5353SAxel Dörfler }
57102be5353SAxel Dörfler 
57202be5353SAxel Dörfler 
57302be5353SAxel Dörfler void
57402be5353SAxel Dörfler FSClipboardRemove(Model* model)
57502be5353SAxel Dörfler {
57602be5353SAxel Dörfler 	BMessenger messenger(kTrackerSignature);
57702be5353SAxel Dörfler 	if (messenger.IsValid()) {
57802be5353SAxel Dörfler 		BMessage* report = new BMessage(kFSClipboardChanges);
57902be5353SAxel Dörfler 		TClipboardNodeRef tcnode;
58002be5353SAxel Dörfler 		tcnode.node = *model->NodeRef();
58102be5353SAxel Dörfler 		tcnode.moveMode = kDelete;
58202be5353SAxel Dörfler 		const entry_ref* ref = model->EntryRef();
58302be5353SAxel Dörfler 		report->AddInt32("device", ref->device);
58402be5353SAxel Dörfler 		report->AddInt64("directory", ref->directory);
58502be5353SAxel Dörfler 		report->AddBool("clearClipboard", false);
58602be5353SAxel Dörfler 		report->AddData("tcnode", T_CLIPBOARD_NODE, &tcnode, sizeof(tcnode), true);
58702be5353SAxel Dörfler 		messenger.SendMessage(report);
58802be5353SAxel Dörfler 		delete report;
58902be5353SAxel Dörfler 	}
59002be5353SAxel Dörfler }
59102be5353SAxel Dörfler 
59202be5353SAxel Dörfler 
59302be5353SAxel Dörfler //	#pragma mark -
59402be5353SAxel Dörfler 
59502be5353SAxel Dörfler 
59602be5353SAxel Dörfler BClipboardRefsWatcher::BClipboardRefsWatcher()
59702be5353SAxel Dörfler 	:	BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096),
59802be5353SAxel Dörfler 	fNotifyList(10, false)
59902be5353SAxel Dörfler {
60002be5353SAxel Dörfler 	watch_node(NULL, B_WATCH_MOUNT, this);
60102be5353SAxel Dörfler 	fRefsInClipboard = FSClipboardHasRefs();
60202be5353SAxel Dörfler 	be_clipboard->StartWatching(this);
60302be5353SAxel Dörfler }
60402be5353SAxel Dörfler 
60502be5353SAxel Dörfler 
60602be5353SAxel Dörfler BClipboardRefsWatcher::~BClipboardRefsWatcher()
60702be5353SAxel Dörfler {
60802be5353SAxel Dörfler 	stop_watching(this);
60902be5353SAxel Dörfler 	be_clipboard->StopWatching(this);
61002be5353SAxel Dörfler }
61102be5353SAxel Dörfler 
61202be5353SAxel Dörfler 
61302be5353SAxel Dörfler void
61402be5353SAxel Dörfler BClipboardRefsWatcher::AddToNotifyList(BMessenger target)
61502be5353SAxel Dörfler {
61602be5353SAxel Dörfler 	if (Lock()) {
61702be5353SAxel Dörfler 		// add the messenger if it's not already in the list
61802be5353SAxel Dörfler 		// ToDo: why do we have to care about that?
61902be5353SAxel Dörfler 		BMessenger* messenger;
62002be5353SAxel Dörfler 		bool found = false;
62102be5353SAxel Dörfler 
62202be5353SAxel Dörfler 		for (int32 index = 0;(messenger = fNotifyList.ItemAt(index)) != NULL; index++) {
62302be5353SAxel Dörfler 			if (*messenger == target) {
62402be5353SAxel Dörfler 				found = true;
62502be5353SAxel Dörfler 				break;
62602be5353SAxel Dörfler 			}
62702be5353SAxel Dörfler 		}
62802be5353SAxel Dörfler 		if (!found)
62902be5353SAxel Dörfler 			fNotifyList.AddItem(new BMessenger(target));
63002be5353SAxel Dörfler 
63102be5353SAxel Dörfler 		Unlock();
63202be5353SAxel Dörfler 	}
63302be5353SAxel Dörfler }
63402be5353SAxel Dörfler 
63502be5353SAxel Dörfler 
63602be5353SAxel Dörfler void
63702be5353SAxel Dörfler BClipboardRefsWatcher::RemoveFromNotifyList(BMessenger target)
63802be5353SAxel Dörfler {
63902be5353SAxel Dörfler 	if (Lock()) {
64002be5353SAxel Dörfler 		BMessenger* messenger;
64102be5353SAxel Dörfler 
64202be5353SAxel Dörfler 		for (int32 index = 0;(messenger = fNotifyList.ItemAt(index)) != NULL; index++) {
64302be5353SAxel Dörfler 			if (*messenger == target) {
64402be5353SAxel Dörfler 				delete fNotifyList.RemoveItemAt(index);
64502be5353SAxel Dörfler 				break;
64602be5353SAxel Dörfler 			}
64702be5353SAxel Dörfler 		}
64802be5353SAxel Dörfler 		Unlock();
64902be5353SAxel Dörfler 	}
65002be5353SAxel Dörfler }
65102be5353SAxel Dörfler 
65202be5353SAxel Dörfler 
65302be5353SAxel Dörfler void
65402be5353SAxel Dörfler BClipboardRefsWatcher::AddNode(const node_ref* node)
65502be5353SAxel Dörfler {
65602be5353SAxel Dörfler 	TTracker::WatchNode(node, B_WATCH_NAME, this);
65702be5353SAxel Dörfler 	fRefsInClipboard = true;
65802be5353SAxel Dörfler }
65902be5353SAxel Dörfler 
66002be5353SAxel Dörfler 
66102be5353SAxel Dörfler void
66202be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNode(node_ref* node, bool removeFromClipboard)
66302be5353SAxel Dörfler {
66402be5353SAxel Dörfler 	watch_node(node, B_STOP_WATCHING, this);
66502be5353SAxel Dörfler 
66602be5353SAxel Dörfler 	if (!removeFromClipboard)
66702be5353SAxel Dörfler 		return;
66802be5353SAxel Dörfler 
66902be5353SAxel Dörfler 	if (be_clipboard->Lock()) {
67002be5353SAxel Dörfler 		BMessage* clip = be_clipboard->Data();
67102be5353SAxel Dörfler 		if (clip != NULL) {
67202be5353SAxel Dörfler 			char name[64];
67302be5353SAxel Dörfler 			MakeRefName(name, node);
67402be5353SAxel Dörfler 			clip->RemoveName(name);
67502be5353SAxel Dörfler 			MakeModeName(name);
67602be5353SAxel Dörfler 			clip->RemoveName(name);
67702be5353SAxel Dörfler 
67802be5353SAxel Dörfler 			be_clipboard->Commit();
67902be5353SAxel Dörfler 		}
68002be5353SAxel Dörfler 		be_clipboard->Unlock();
68102be5353SAxel Dörfler 	}
68202be5353SAxel Dörfler }
68302be5353SAxel Dörfler 
68402be5353SAxel Dörfler 
68502be5353SAxel Dörfler void
68602be5353SAxel Dörfler BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device)
68702be5353SAxel Dörfler {
68802be5353SAxel Dörfler 	if (!be_clipboard->Lock())
68902be5353SAxel Dörfler 		return;
69002be5353SAxel Dörfler 
69102be5353SAxel Dörfler 	BMessage* clip = be_clipboard->Data();
69202be5353SAxel Dörfler 	if (clip != NULL) {
69302be5353SAxel Dörfler 		char deviceName[6];
69402be5353SAxel Dörfler 		sprintf(deviceName, "r%ld_", device);
69502be5353SAxel Dörfler 
69602be5353SAxel Dörfler 		int32 index = 0;
69702be5353SAxel Dörfler 		char* refName;
69802be5353SAxel Dörfler 		type_code type;
69902be5353SAxel Dörfler 		int32 count;
70002be5353SAxel Dörfler 		while (clip->GetInfo(B_REF_TYPE, index,
70102be5353SAxel Dörfler #ifdef B_BEOS_VERSION_DANO
70202be5353SAxel Dörfler 			(const char**)
70302be5353SAxel Dörfler #endif
70402be5353SAxel Dörfler 			&refName, &type, &count) == B_OK) {
70502be5353SAxel Dörfler 			if (!strncmp(deviceName, refName, strlen(deviceName))) {
70602be5353SAxel Dörfler 				clip->RemoveName(refName);
70702be5353SAxel Dörfler 				MakeModeName(refName);
70802be5353SAxel Dörfler 				clip->RemoveName(refName);
70902be5353SAxel Dörfler 
71002be5353SAxel Dörfler 				node_ref node;
71102be5353SAxel Dörfler 				MakeNodeFromName(&node, refName);
71202be5353SAxel Dörfler 				watch_node(&node, B_STOP_WATCHING, this);
71302be5353SAxel Dörfler 			}
71402be5353SAxel Dörfler 			index++;
71502be5353SAxel Dörfler 		}
71602be5353SAxel Dörfler 		be_clipboard->Commit();
71702be5353SAxel Dörfler 	}
71802be5353SAxel Dörfler 	be_clipboard->Unlock();
71902be5353SAxel Dörfler }
72002be5353SAxel Dörfler 
72102be5353SAxel Dörfler 
72202be5353SAxel Dörfler void
72302be5353SAxel Dörfler BClipboardRefsWatcher::UpdateNode(node_ref* node, entry_ref* ref)
72402be5353SAxel Dörfler {
72502be5353SAxel Dörfler 	if (!be_clipboard->Lock())
72602be5353SAxel Dörfler 		return;
72702be5353SAxel Dörfler 
72802be5353SAxel Dörfler 	BMessage* clip = be_clipboard->Data();
72902be5353SAxel Dörfler 	if (clip != NULL) {
73002be5353SAxel Dörfler 		char name[64];
73102be5353SAxel Dörfler 		MakeRefName(name, node);
73202be5353SAxel Dörfler 		if ((clip->ReplaceRef(name, ref)) != B_OK) {
73302be5353SAxel Dörfler 			clip->RemoveName(name);
73402be5353SAxel Dörfler 			MakeModeName(name);
73502be5353SAxel Dörfler 			clip->RemoveName(name);
73602be5353SAxel Dörfler 
73702be5353SAxel Dörfler 			RemoveNode(node);
73802be5353SAxel Dörfler 		}
73902be5353SAxel Dörfler 		be_clipboard->Commit();
74002be5353SAxel Dörfler 	}
74102be5353SAxel Dörfler 	be_clipboard->Unlock();
74202be5353SAxel Dörfler }
74302be5353SAxel Dörfler 
74402be5353SAxel Dörfler 
74502be5353SAxel Dörfler void
74602be5353SAxel Dörfler BClipboardRefsWatcher::Clear()
74702be5353SAxel Dörfler {
74802be5353SAxel Dörfler 	stop_watching(this);
74902be5353SAxel Dörfler 	watch_node(NULL, B_WATCH_MOUNT, this);
75002be5353SAxel Dörfler 
75102be5353SAxel Dörfler 	BMessage message(kFSClipboardChanges);
75202be5353SAxel Dörfler 	message.AddBool("clearClipboard", true);
75302be5353SAxel Dörfler 	if (Lock()) {
75402be5353SAxel Dörfler 		int32 items = fNotifyList.CountItems();
75502be5353SAxel Dörfler 		for (int32 i = 0;i < items;i++) {
75602be5353SAxel Dörfler 			fNotifyList.ItemAt(i)->SendMessage(&message);
75702be5353SAxel Dörfler 		}
75802be5353SAxel Dörfler 		Unlock();
75902be5353SAxel Dörfler 	}
76002be5353SAxel Dörfler }
76102be5353SAxel Dörfler 
76202be5353SAxel Dörfler 
763*b05aa8b5SJohn Scipione //void
764*b05aa8b5SJohn Scipione //BClipboardRefsWatcher::UpdatePoseViews(bool clearClipboard, const node_ref* node)
765*b05aa8b5SJohn Scipione //{
766*b05aa8b5SJohn Scipione //	BMessage message(kFSClipboardChanges);
767*b05aa8b5SJohn Scipione //	message.AddInt32("device", node->device);
768*b05aa8b5SJohn Scipione //	message.AddInt64("directory", node->node);
769*b05aa8b5SJohn Scipione //	message.AddBool("clearClipboard", clearClipboard);
770*b05aa8b5SJohn Scipione //
771*b05aa8b5SJohn Scipione //	if (Lock()) {
772*b05aa8b5SJohn Scipione //		int32 items = fNotifyList.CountItems();
773*b05aa8b5SJohn Scipione //		for (int32 i = 0;i < items;i++) {
774*b05aa8b5SJohn Scipione //			fNotifyList.ItemAt(i)->SendMessage(&message);
775*b05aa8b5SJohn Scipione //		}
776*b05aa8b5SJohn Scipione //		Unlock();
777*b05aa8b5SJohn Scipione //	}
778*b05aa8b5SJohn Scipione //}
779*b05aa8b5SJohn Scipione 
78002be5353SAxel Dörfler 
78102be5353SAxel Dörfler void
78202be5353SAxel Dörfler BClipboardRefsWatcher::UpdatePoseViews(BMessage* reportMessage)
78302be5353SAxel Dörfler {
78402be5353SAxel Dörfler 	if (Lock()) {
78502be5353SAxel Dörfler 		// check if it was cleared, if so clear watching
78602be5353SAxel Dörfler 		bool clearClipboard = false;
78702be5353SAxel Dörfler 		if (reportMessage->FindBool("clearClipboard", &clearClipboard) == B_OK
78802be5353SAxel Dörfler 			&& clearClipboard) {
78902be5353SAxel Dörfler 			stop_watching(this);
79002be5353SAxel Dörfler 			watch_node(NULL, B_WATCH_MOUNT, this);
79102be5353SAxel Dörfler 		}
79202be5353SAxel Dörfler 
79302be5353SAxel Dörfler 		// loop through reported node_ref's movemodes:
79402be5353SAxel Dörfler 		// move or copy: start watching node_ref
79502be5353SAxel Dörfler 		// remove: stop watching node_ref
79602be5353SAxel Dörfler 		int32 index = 0;
79702be5353SAxel Dörfler 		TClipboardNodeRef* tcnode = NULL;
79802be5353SAxel Dörfler 		ssize_t size;
79902be5353SAxel Dörfler 		while (reportMessage->FindData("tcnode", T_CLIPBOARD_NODE, index, (const void**)&tcnode, &size) == B_OK) {
80002be5353SAxel Dörfler 			if (tcnode->moveMode == kDelete) {
80102be5353SAxel Dörfler 				watch_node(&tcnode->node, B_STOP_WATCHING, this);
80202be5353SAxel Dörfler 			} else {
80302be5353SAxel Dörfler 				watch_node(&tcnode->node, B_STOP_WATCHING, this);
80402be5353SAxel Dörfler 				TTracker::WatchNode(&tcnode->node, B_WATCH_NAME, this);
80502be5353SAxel Dörfler 				fRefsInClipboard = true;
80602be5353SAxel Dörfler 			}
80702be5353SAxel Dörfler 			index++;
80802be5353SAxel Dörfler 		}
80902be5353SAxel Dörfler 
81002be5353SAxel Dörfler 		// send report
81102be5353SAxel Dörfler 		int32 items = fNotifyList.CountItems();
81202be5353SAxel Dörfler 		for (int32 i = 0;i < items;i++) {
81302be5353SAxel Dörfler 			fNotifyList.ItemAt(i)->SendMessage(reportMessage);
81402be5353SAxel Dörfler 		}
81502be5353SAxel Dörfler 		Unlock();
81602be5353SAxel Dörfler 	}
81702be5353SAxel Dörfler }
81802be5353SAxel Dörfler 
81902be5353SAxel Dörfler 
82002be5353SAxel Dörfler void
82102be5353SAxel Dörfler BClipboardRefsWatcher::MessageReceived(BMessage* message)
82202be5353SAxel Dörfler {
82302be5353SAxel Dörfler 	if (message->what == B_CLIPBOARD_CHANGED && fRefsInClipboard) {
82402be5353SAxel Dörfler 		if (!(fRefsInClipboard = FSClipboardHasRefs()))
82502be5353SAxel Dörfler 			Clear();
82602be5353SAxel Dörfler 		return;
82702be5353SAxel Dörfler 	} else if (message->what != B_NODE_MONITOR) {
82802be5353SAxel Dörfler 		_inherited::MessageReceived(message);
82902be5353SAxel Dörfler 		return;
83002be5353SAxel Dörfler 	}
83102be5353SAxel Dörfler 
83202be5353SAxel Dörfler 	switch (message->FindInt32("opcode")) {
83302be5353SAxel Dörfler 		case B_ENTRY_MOVED:
83402be5353SAxel Dörfler 		{
83502be5353SAxel Dörfler 			ino_t toDir;
83602be5353SAxel Dörfler 			ino_t fromDir;
83702be5353SAxel Dörfler 			node_ref node;
83802be5353SAxel Dörfler 			const char* name = NULL;
83902be5353SAxel Dörfler 			message->FindInt64("from directory", &fromDir);
84002be5353SAxel Dörfler 			message->FindInt64("to directory", &toDir);
84102be5353SAxel Dörfler 			message->FindInt64("node", &node.node);
84202be5353SAxel Dörfler 			message->FindInt32("device", &node.device);
84302be5353SAxel Dörfler 			message->FindString("name", &name);
84402be5353SAxel Dörfler 			entry_ref ref(node.device, toDir, name);
84502be5353SAxel Dörfler 			UpdateNode(&node, &ref);
84602be5353SAxel Dörfler 			break;
84702be5353SAxel Dörfler 		}
84802be5353SAxel Dörfler 
84902be5353SAxel Dörfler 		case B_DEVICE_UNMOUNTED:
85002be5353SAxel Dörfler 		{
85102be5353SAxel Dörfler 			dev_t device;
85202be5353SAxel Dörfler 			message->FindInt32("device", &device);
85302be5353SAxel Dörfler 			RemoveNodesByDevice(device);
85402be5353SAxel Dörfler 			break;
85502be5353SAxel Dörfler 		}
85602be5353SAxel Dörfler 
85702be5353SAxel Dörfler 		case B_ENTRY_REMOVED:
85802be5353SAxel Dörfler 		{
85902be5353SAxel Dörfler 			node_ref node;
86002be5353SAxel Dörfler 			message->FindInt64("node", &node.node);
86102be5353SAxel Dörfler 			message->FindInt32("device", &node.device);
86202be5353SAxel Dörfler 			RemoveNode(&node, true);
86302be5353SAxel Dörfler 			break;
86402be5353SAxel Dörfler 		}
86502be5353SAxel Dörfler 	}
86602be5353SAxel Dörfler }
867