xref: /haiku/src/servers/registrar/ClipboardHandler.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold, bonefish@users.sf.net
7  *		Gabe Yoder
8  */
9 
10 
11 #include "Clipboard.h"
12 #include "ClipboardHandler.h"
13 
14 #include <Message.h>
15 #include <RegistrarDefs.h>
16 
17 #include <map>
18 #include <string>
19 
20 
21 using std::map;
22 using std::string;
23 using namespace BPrivate;
24 
25 
26 /*!
27 	\class ClipboardHandler
28 	\brief Handles all clipboard related requests.
29 */
30 
31 struct ClipboardHandler::ClipboardMap : map<string, Clipboard*> {};
32 
33 
34 // constructor
35 /*!	\brief Creates and initializes a ClipboardHandler.
36 */
37 ClipboardHandler::ClipboardHandler()
38 				: BHandler(),
39 				  fClipboards(new ClipboardMap)
40 {
41 }
42 
43 
44 // destructor
45 /*!	\brief Frees all resources associate with this object.
46 */
47 ClipboardHandler::~ClipboardHandler()
48 {
49 	for (ClipboardMap::iterator it = fClipboards->begin();
50 		it != fClipboards->end();
51 		++it)
52 		delete it->second;
53 }
54 
55 
56 // MessageReceived
57 /*!	\brief Overrides the super class version to handle the clipboard specific
58 		   messages.
59 	\param message The message to be handled
60 */
61 void
62 ClipboardHandler::MessageReceived(BMessage *message)
63 {
64 	const char *name;
65 	BMessage reply;
66 	switch (message->what) {
67 		case B_REG_ADD_CLIPBOARD:
68 		{
69 			status_t result = B_BAD_VALUE;
70 
71 			if (message->FindString("name", &name) == B_OK) {
72 				if (_GetClipboard(name))
73 					result = B_OK;
74 			}
75 
76 			reply.what = B_REG_RESULT;
77 			reply.AddInt32("result", result);
78 			message->SendReply(&reply);
79 			break;
80 		}
81 
82 		case B_REG_GET_CLIPBOARD_COUNT:
83 		{
84 			status_t result = B_BAD_VALUE;
85 
86 			if (message->FindString("name", &name) == B_OK) {
87 				if (Clipboard *clipboard = _GetClipboard(name)) {
88 					reply.AddInt32("count", clipboard->Count());
89 					result = B_OK;
90 				}
91 			}
92 
93 			reply.AddInt32("result", result);
94 			reply.what = B_REG_RESULT;
95 			message->SendReply(&reply);
96 			break;
97 		}
98 
99 		case B_REG_CLIPBOARD_START_WATCHING:
100 		{
101 			status_t result = B_BAD_VALUE;
102 
103 			BMessenger target;
104 			if (message->FindString("name", &name) == B_OK
105 				&& message->FindMessenger("target", &target) == B_OK) {
106 				Clipboard *clipboard = _GetClipboard(name);
107 				if (clipboard && clipboard->AddWatcher(target))
108 					result = B_OK;
109 			}
110 
111 			reply.what = B_REG_RESULT;
112 			reply.AddInt32("result", result);
113 			message->SendReply(&reply);
114 			break;
115 		}
116 
117 		case B_REG_CLIPBOARD_STOP_WATCHING:
118 		{
119 			status_t result = B_BAD_VALUE;
120 
121 			BMessenger target;
122 			if (message->FindString("name", &name) == B_OK
123 				&& message->FindMessenger("target", &target) == B_OK) {
124 				Clipboard *clipboard = _GetClipboard(name);
125 				if (clipboard && clipboard->RemoveWatcher(target))
126 					result = B_OK;
127 			}
128 
129 			reply.what = B_REG_RESULT;
130 			reply.AddInt32("result", result);
131 			message->SendReply(&reply);
132 			break;
133 		}
134 
135 		case B_REG_DOWNLOAD_CLIPBOARD:
136 		{
137 			status_t result = B_BAD_VALUE;
138 
139 			if (message->FindString("name", &name) == B_OK) {
140 				Clipboard *clipboard = _GetClipboard(name);
141 				if (clipboard) {
142 					reply.AddMessage("data", clipboard->Data());
143 					reply.AddMessenger("data source", clipboard->DataSource());
144 					reply.AddInt32("count", clipboard->Count());
145 					result = B_OK;
146 				}
147 			}
148 
149 			reply.what = B_REG_RESULT;
150 			reply.AddInt32("result", result);
151 			message->SendReply(&reply);
152 			break;
153 		}
154 
155 		case B_REG_UPLOAD_CLIPBOARD:
156 		{
157 			status_t result = B_BAD_VALUE;
158 
159 			BMessage data;
160 			BMessenger source;
161 			if (message->FindString("name", &name) == B_OK
162 				&& message->FindMessenger("data source", &source) == B_OK
163 				&& message->FindMessage("data", &data) == B_OK) {
164 				Clipboard *clipboard = _GetClipboard(name);
165 				if (clipboard) {
166 					int32 localCount;
167 					bool failIfChanged;
168 					if (message->FindInt32("count", &localCount) == B_OK
169 						&& message->FindBool("fail if changed", &failIfChanged)
170 							== B_OK
171 						&& failIfChanged
172 						&& localCount != clipboard->Count()) {
173 						// atomic support
174 						result = B_ERROR;
175 					} else {
176 						clipboard->SetData(&data, source);
177 						result = reply.AddInt32("count", clipboard->Count());
178 						result = B_OK;
179 					}
180 				}
181 			}
182 
183 			reply.what = B_REG_RESULT;
184 			reply.AddInt32("result", result);
185 			message->SendReply(&reply);
186 			break;
187 		}
188 
189 		default:
190 			BHandler::MessageReceived(message);
191 			break;
192 	}
193 }
194 
195 
196 /*!	\brief Gets the clipboard with the specified name, or adds it, if not yet
197 		   existent.
198 
199 	\param name The name of the clipboard to be returned.
200 	\return The clipboard with the respective name.
201 */
202 Clipboard*
203 ClipboardHandler::_GetClipboard(const char *name)
204 {
205 	if (!name)
206 		name = "system";
207 
208 	Clipboard *clipboard = NULL;
209 	ClipboardMap::iterator it = fClipboards->find(name);
210 	if (it != fClipboards->end()) {
211 		clipboard = it->second;
212 	} else {
213 		clipboard = new Clipboard(name);
214 		(*fClipboards)[name] = clipboard;
215 	}
216 
217 	return clipboard;
218 }
219 
220