COSXClipboard.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2004 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "CClipboard.h"
00016 #include "COSXClipboard.h"
00017 #include "COSXClipboardUTF16Converter.h"
00018 #include "COSXClipboardTextConverter.h"
00019 #include "CLog.h"
00020 #include "XArch.h"
00021 
00022 //
00023 // COSXClipboard
00024 //
00025 
00026 COSXClipboard::COSXClipboard() :
00027     m_time(0),
00028     m_pboard(NULL)
00029 {
00030     m_converters.push_back(new COSXClipboardUTF16Converter);
00031     m_converters.push_back(new COSXClipboardTextConverter);
00032     PasteboardCreate( kPasteboardClipboard, &m_pboard);
00033     PasteboardSynchronize(m_pboard);
00034 }
00035 
00036 COSXClipboard::~COSXClipboard()
00037 {
00038     clearConverters();
00039 }
00040 
00041 bool
00042 COSXClipboard::empty()
00043 {
00044     LOG((CLOG_DEBUG "empty clipboard"));
00045     assert(m_pboard != NULL);
00046 
00047     OSStatus err = PasteboardClear(m_pboard);
00048     if (err != noErr) {
00049         LOG((CLOG_DEBUG "failed to grab clipboard"));
00050         return false;
00051     }
00052 
00053 
00054     return true;
00055 }
00056 
00057 bool
00058 COSXClipboard::synchronize()
00059 {
00060     PasteboardSyncFlags flags = PasteboardSynchronize(m_pboard);
00061     LOG((CLOG_DEBUG "flags: %x", flags));
00062 
00063     if (flags & kPasteboardModified) {
00064         return true;
00065     }
00066     return false;
00067 }    
00068 
00069 void
00070 COSXClipboard::add(EFormat format, const CString & data)
00071 {
00072     LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format));
00073 
00074     for (ConverterList::const_iterator index = m_converters.begin();
00075             index != m_converters.end(); ++index) {
00076 
00077         IOSXClipboardConverter* converter = *index;
00078 
00079         // skip converters for other formats
00080         if (converter->getFormat() == format) {
00081             CString osXData = converter->fromIClipboard(data);
00082             CFStringRef flavorType = converter->getOSXFormat();
00083             CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, (UInt8 *)osXData.data(), osXData.size());
00084 
00085             PasteboardPutItemFlavor(
00086                     m_pboard,
00087                     (PasteboardItemID) 0,
00088                     flavorType,
00089                     dataRef, 
00090                     kPasteboardFlavorNoFlags);
00091             LOG((CLOG_DEBUG "added %d bytes to clipboard format: %d", data.size(), format));
00092         }
00093     }
00094 }
00095 
00096 bool
00097 COSXClipboard::open(Time time) const 
00098 {
00099     LOG((CLOG_DEBUG "opening clipboard"));
00100     m_time = time;
00101     return true;
00102 }
00103 
00104 void
00105 COSXClipboard::close() const
00106 {
00107     LOG((CLOG_DEBUG "closing clipboard"));
00108     /* not needed */
00109 }
00110 
00111 IClipboard::Time
00112 COSXClipboard::getTime() const
00113 {
00114     return m_time;
00115 }
00116 
00117 bool
00118 COSXClipboard::has(EFormat format) const
00119 {
00120     assert(m_pboard != NULL);
00121 
00122     PasteboardItemID item;
00123     PasteboardGetItemIdentifier(m_pboard, (CFIndex) 1, &item);
00124 
00125     for (ConverterList::const_iterator index = m_converters.begin();
00126             index != m_converters.end(); ++index) {
00127         IOSXClipboardConverter* converter = *index;
00128         if (converter->getFormat() == format) {
00129             PasteboardFlavorFlags flags;
00130             CFStringRef type = converter->getOSXFormat();
00131 
00132             OSStatus res;
00133 
00134             if ((res = PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags)) == noErr) {
00135                 return true;
00136             }
00137         }
00138     }
00139 
00140     return false;
00141 }
00142 
00143 CString
00144 COSXClipboard::get(EFormat format) const
00145 {
00146     CString result;
00147     CFStringRef type;
00148 
00149     PasteboardItemID item;
00150     PasteboardGetItemIdentifier(m_pboard, (CFIndex) 1, &item);
00151 
00152 
00153     // find the converter for the first clipboard format we can handle
00154     IOSXClipboardConverter* converter = NULL;
00155     for (ConverterList::const_iterator index = m_converters.begin();
00156             index != m_converters.end(); ++index) {
00157         converter = *index;
00158 
00159         PasteboardFlavorFlags flags;
00160         type = converter->getOSXFormat();
00161 
00162         if (converter->getFormat() == format &&
00163                 PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags) == noErr) {
00164             break;
00165         }
00166         converter = NULL;
00167     }
00168 
00169     // if no converter then we don't recognize any formats
00170     if (converter == NULL) {
00171         LOG((CLOG_DEBUG "Unable to find converter for data"));
00172         return result;
00173     }
00174 
00175     // get the clipboard data.
00176     CFDataRef buffer = NULL;
00177     try {
00178         OSStatus err = PasteboardCopyItemFlavorData(m_pboard, item, type, &buffer);
00179 
00180         if (err != noErr) {
00181             throw err;
00182         }
00183 
00184         result = CString((char *) CFDataGetBytePtr(buffer), CFDataGetLength(buffer));
00185     }
00186     catch (OSStatus err) {
00187         LOG((CLOG_DEBUG "exception thrown in COSXClipboard::get MacError (%d)", err));
00188     }
00189     catch (...) {
00190         LOG((CLOG_DEBUG "unknown exception in COSXClipboard::get"));
00191         RETHROW_XTHREAD
00192     }
00193 
00194     if (buffer != NULL)
00195         CFRelease(buffer);
00196 
00197     return converter->toIClipboard(result);
00198 }
00199 
00200 void
00201 COSXClipboard::clearConverters()
00202 {
00203     for (ConverterList::iterator index = m_converters.begin();
00204             index != m_converters.end(); ++index) {
00205         delete *index;
00206     }
00207     m_converters.clear();
00208 }

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7