00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "COSXClipboard.h"
00020 #include "CClipboard.h"
00021 #include "COSXClipboardUTF16Converter.h"
00022 #include "COSXClipboardTextConverter.h"
00023 #include "CLog.h"
00024 #include "XArch.h"
00025
00026
00027
00028
00029
00030 COSXClipboard::COSXClipboard() :
00031 m_time(0),
00032 m_pboard(NULL)
00033 {
00034 m_converters.push_back(new COSXClipboardUTF16Converter);
00035 m_converters.push_back(new COSXClipboardTextConverter);
00036
00037 OSStatus createErr = PasteboardCreate(kPasteboardClipboard, &m_pboard);
00038 if (createErr != noErr) {
00039 LOG((CLOG_DEBUG "failed to create clipboard reference: error %i", createErr));
00040 LOG((CLOG_ERR "unable to connect to pasteboard, clipboard sharing disabled", createErr));
00041 m_pboard = NULL;
00042 return;
00043
00044 }
00045
00046 OSStatus syncErr = PasteboardSynchronize(m_pboard);
00047 if (syncErr != noErr) {
00048 LOG((CLOG_DEBUG "failed to syncronize clipboard: error %i", syncErr));
00049 }
00050 }
00051
00052 COSXClipboard::~COSXClipboard()
00053 {
00054 clearConverters();
00055 }
00056
00057 bool
00058 COSXClipboard::empty()
00059 {
00060 LOG((CLOG_DEBUG "emptying clipboard"));
00061 if (m_pboard == NULL)
00062 return false;
00063
00064 OSStatus err = PasteboardClear(m_pboard);
00065 if (err != noErr) {
00066 LOG((CLOG_DEBUG "failed to clear clipboard: error %i", err));
00067 return false;
00068 }
00069
00070 return true;
00071 }
00072
00073 bool
00074 COSXClipboard::synchronize()
00075 {
00076 if (m_pboard == NULL)
00077 return false;
00078
00079 PasteboardSyncFlags flags = PasteboardSynchronize(m_pboard);
00080 LOG((CLOG_DEBUG2 "flags: %x", flags));
00081
00082 if (flags & kPasteboardModified) {
00083 return true;
00084 }
00085 return false;
00086 }
00087
00088 void
00089 COSXClipboard::add(EFormat format, const CString & data)
00090 {
00091 bool emptied = false;
00092 if (m_pboard == NULL)
00093 return;
00094
00095 LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format));
00096
00097 for (ConverterList::const_iterator index = m_converters.begin();
00098 index != m_converters.end(); ++index) {
00099
00100 IOSXClipboardConverter* converter = *index;
00101
00102
00103 if (converter->getFormat() == format) {
00104 CString osXData = converter->fromIClipboard(data);
00105 CFStringRef flavorType = converter->getOSXFormat();
00106 CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, (UInt8 *)osXData.data(), osXData.size());
00107
00108
00109
00110
00111
00112
00113 if (!emptied) {
00114 empty();
00115 emptied = true;
00116 }
00117
00118 PasteboardPutItemFlavor(
00119 m_pboard,
00120 (PasteboardItemID) 0,
00121 flavorType,
00122 dataRef,
00123 kPasteboardFlavorNoFlags);
00124 LOG((CLOG_DEBUG "added %d bytes to clipboard format: %d", data.size(), format));
00125 }
00126 }
00127 }
00128
00129 bool
00130 COSXClipboard::open(Time time) const
00131 {
00132 if (m_pboard == NULL)
00133 return false;
00134
00135 LOG((CLOG_DEBUG "opening clipboard"));
00136 m_time = time;
00137 return true;
00138 }
00139
00140 void
00141 COSXClipboard::close() const
00142 {
00143 LOG((CLOG_DEBUG "closing clipboard"));
00144
00145 }
00146
00147 IClipboard::Time
00148 COSXClipboard::getTime() const
00149 {
00150 return m_time;
00151 }
00152
00153 bool
00154 COSXClipboard::has(EFormat format) const
00155 {
00156 if (m_pboard == NULL)
00157 return false;
00158
00159 PasteboardItemID item;
00160 PasteboardGetItemIdentifier(m_pboard, (CFIndex) 1, &item);
00161
00162 for (ConverterList::const_iterator index = m_converters.begin();
00163 index != m_converters.end(); ++index) {
00164 IOSXClipboardConverter* converter = *index;
00165 if (converter->getFormat() == format) {
00166 PasteboardFlavorFlags flags;
00167 CFStringRef type = converter->getOSXFormat();
00168
00169 OSStatus res;
00170
00171 if ((res = PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags)) == noErr) {
00172 return true;
00173 }
00174 }
00175 }
00176
00177 return false;
00178 }
00179
00180 CString
00181 COSXClipboard::get(EFormat format) const
00182 {
00183 CFStringRef type;
00184 PasteboardItemID item;
00185 CString result;
00186
00187 if (m_pboard == NULL)
00188 return result;
00189
00190 PasteboardGetItemIdentifier(m_pboard, (CFIndex) 1, &item);
00191
00192
00193
00194 IOSXClipboardConverter* converter = NULL;
00195 for (ConverterList::const_iterator index = m_converters.begin();
00196 index != m_converters.end(); ++index) {
00197 converter = *index;
00198
00199 PasteboardFlavorFlags flags;
00200 type = converter->getOSXFormat();
00201
00202 if (converter->getFormat() == format &&
00203 PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags) == noErr) {
00204 break;
00205 }
00206 converter = NULL;
00207 }
00208
00209
00210 if (converter == NULL) {
00211 LOG((CLOG_DEBUG "Unable to find converter for data"));
00212 return result;
00213 }
00214
00215
00216 CFDataRef buffer = NULL;
00217 try {
00218 OSStatus err = PasteboardCopyItemFlavorData(m_pboard, item, type, &buffer);
00219
00220 if (err != noErr) {
00221 throw err;
00222 }
00223
00224 result = CString((char *) CFDataGetBytePtr(buffer), CFDataGetLength(buffer));
00225 }
00226 catch (OSStatus err) {
00227 LOG((CLOG_DEBUG "exception thrown in COSXClipboard::get MacError (%d)", err));
00228 }
00229 catch (...) {
00230 LOG((CLOG_DEBUG "unknown exception in COSXClipboard::get"));
00231 RETHROW_XTHREAD
00232 }
00233
00234 if (buffer != NULL)
00235 CFRelease(buffer);
00236
00237 return converter->toIClipboard(result);
00238 }
00239
00240 void
00241 COSXClipboard::clearConverters()
00242 {
00243 if (m_pboard == NULL)
00244 return;
00245
00246 for (ConverterList::iterator index = m_converters.begin();
00247 index != m_converters.end(); ++index) {
00248 delete *index;
00249 }
00250 m_converters.clear();
00251 }