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