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 result = message->SendReply(&reply); 152 if (result != B_OK) { 153 reply.MakeEmpty(); 154 reply.what = B_REG_RESULT; 155 reply.AddInt32("result", result); 156 message->SendReply(&reply); 157 } 158 break; 159 } 160 161 case B_REG_UPLOAD_CLIPBOARD: 162 { 163 status_t result = B_BAD_VALUE; 164 165 BMessage data; 166 BMessenger source; 167 if (message->FindString("name", &name) == B_OK 168 && message->FindMessenger("data source", &source) == B_OK 169 && message->FindMessage("data", &data) == B_OK) { 170 Clipboard *clipboard = _GetClipboard(name); 171 if (clipboard) { 172 int32 localCount; 173 bool failIfChanged; 174 if (message->FindInt32("count", &localCount) == B_OK 175 && message->FindBool("fail if changed", &failIfChanged) 176 == B_OK 177 && failIfChanged 178 && localCount != clipboard->Count()) { 179 // atomic support 180 result = B_ERROR; 181 } else { 182 clipboard->SetData(&data, source); 183 result = reply.AddInt32("count", clipboard->Count()); 184 result = B_OK; 185 } 186 } 187 } 188 189 reply.what = B_REG_RESULT; 190 reply.AddInt32("result", result); 191 message->SendReply(&reply); 192 break; 193 } 194 195 default: 196 BHandler::MessageReceived(message); 197 break; 198 } 199 } 200 201 202 /*! \brief Gets the clipboard with the specified name, or adds it, if not yet 203 existent. 204 205 \param name The name of the clipboard to be returned. 206 \return The clipboard with the respective name. 207 */ 208 Clipboard* 209 ClipboardHandler::_GetClipboard(const char *name) 210 { 211 if (!name) 212 name = "system"; 213 214 Clipboard *clipboard = NULL; 215 ClipboardMap::iterator it = fClipboards->find(name); 216 if (it != fClipboards->end()) { 217 clipboard = it->second; 218 } else { 219 clipboard = new Clipboard(name); 220 (*fClipboards)[name] = clipboard; 221 } 222 223 return clipboard; 224 } 225 226