ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

clipboard.c
Go to the documentation of this file.
00001 /*
00002  * Richedit clipboard handling
00003  *
00004  * Copyright (C) 2006 Kevin Koltzau
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "editor.h"
00022 
00023 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
00024 
00025 static UINT cfRTF = 0;
00026 
00027 typedef struct DataObjectImpl {
00028     IDataObject IDataObject_iface;
00029     LONG ref;
00030 
00031     FORMATETC *fmtetc;
00032     UINT fmtetc_cnt;
00033 
00034     HANDLE unicode;
00035     HANDLE rtf;
00036 } DataObjectImpl;
00037 
00038 typedef struct EnumFormatImpl {
00039     IEnumFORMATETC IEnumFORMATETC_iface;
00040     LONG ref;
00041 
00042     FORMATETC *fmtetc;
00043     UINT fmtetc_cnt;
00044 
00045     UINT cur;
00046 } EnumFormatImpl;
00047 
00048 static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
00049 
00050 static inline DataObjectImpl *impl_from_IDataObject(IDataObject *iface)
00051 {
00052     return CONTAINING_RECORD(iface, DataObjectImpl, IDataObject_iface);
00053 }
00054 
00055 static inline EnumFormatImpl *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
00056 {
00057     return CONTAINING_RECORD(iface, EnumFormatImpl, IEnumFORMATETC_iface);
00058 }
00059 
00060 static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
00061 {
00062     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00063     TRACE("%p %s\n", This, debugstr_guid(riid));
00064 
00065     if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) {
00066         IEnumFORMATETC_AddRef(iface);
00067         *ppvObj = This;
00068         return S_OK;
00069     }
00070     *ppvObj = NULL;
00071     return E_NOINTERFACE;
00072 }
00073 
00074 static ULONG WINAPI EnumFormatImpl_AddRef(IEnumFORMATETC *iface)
00075 {
00076     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00077     LONG ref = InterlockedIncrement(&This->ref);
00078     TRACE("(%p) ref=%d\n", This, ref);
00079     return ref;
00080 }
00081 
00082 static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface)
00083 {
00084     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00085     ULONG ref = InterlockedDecrement(&This->ref);
00086     TRACE("(%p) ref=%d\n", This, ref);
00087 
00088     if(!ref) {
00089         GlobalFree(This->fmtetc);
00090         heap_free(This);
00091     }
00092 
00093     return ref;
00094 }
00095 
00096 static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt,
00097                                           FORMATETC *rgelt, ULONG *pceltFetched)
00098 {
00099     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00100     ULONG count = 0;
00101     TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched);
00102 
00103     if(!rgelt)
00104         return E_INVALIDARG;
00105 
00106     count = min(celt, This->fmtetc_cnt-This->cur);
00107     if(count > 0) {
00108         memcpy(rgelt, This->fmtetc+This->cur, count*sizeof(FORMATETC));
00109         This->cur += count;
00110     }
00111     if(pceltFetched)
00112         *pceltFetched = count;
00113     return count == celt ? S_OK : S_FALSE;
00114 }
00115 
00116 static HRESULT WINAPI EnumFormatImpl_Skip(IEnumFORMATETC *iface, ULONG celt)
00117 {
00118     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00119     ULONG count = 0;
00120     TRACE("(%p)->(%d)\n", This, celt);
00121 
00122     count = min(celt, This->fmtetc_cnt-This->cur);
00123     This->cur += count;
00124     return count == celt ? S_OK : S_FALSE;
00125 }
00126 
00127 static HRESULT WINAPI EnumFormatImpl_Reset(IEnumFORMATETC *iface)
00128 {
00129     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00130     TRACE("(%p)\n", This);
00131 
00132     This->cur = 0;
00133     return S_OK;
00134 }
00135 
00136 static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
00137 {
00138     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
00139     HRESULT hr;
00140     TRACE("(%p)->(%p)\n", This, ppenum);
00141 
00142     if(!ppenum)
00143         return E_INVALIDARG;
00144     hr = EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenum);
00145     if(SUCCEEDED(hr))
00146         hr = IEnumFORMATETC_Skip(*ppenum, This->cur);
00147     return hr;
00148 }
00149 
00150 static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
00151     EnumFormatImpl_QueryInterface,
00152     EnumFormatImpl_AddRef,
00153     EnumFormatImpl_Release,
00154     EnumFormatImpl_Next,
00155     EnumFormatImpl_Skip,
00156     EnumFormatImpl_Reset,
00157     EnumFormatImpl_Clone
00158 };
00159 
00160 static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
00161 {
00162     EnumFormatImpl *ret;
00163     TRACE("\n");
00164 
00165     ret = heap_alloc(sizeof(EnumFormatImpl));
00166     ret->IEnumFORMATETC_iface.lpVtbl = &VT_EnumFormatImpl;
00167     ret->ref = 1;
00168     ret->cur = 0;
00169     ret->fmtetc_cnt = fmtetc_cnt;
00170     ret->fmtetc = GlobalAlloc(GMEM_ZEROINIT, fmtetc_cnt*sizeof(FORMATETC));
00171     memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
00172     *lplpformatetc = (LPENUMFORMATETC)ret;
00173     return S_OK;
00174 }
00175 
00176 static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
00177 {
00178     DataObjectImpl *This = impl_from_IDataObject(iface);
00179     TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
00180 
00181     if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
00182         IDataObject_AddRef(iface);
00183         *ppvObj = This;
00184         return S_OK;
00185     }
00186     *ppvObj = NULL;
00187     return E_NOINTERFACE;
00188 }
00189 
00190 static ULONG WINAPI DataObjectImpl_AddRef(IDataObject* iface)
00191 {
00192     DataObjectImpl *This = impl_from_IDataObject(iface);
00193     ULONG ref = InterlockedIncrement(&This->ref);
00194     TRACE("(%p) ref=%d\n", This, ref);
00195     return ref;
00196 }
00197 
00198 static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface)
00199 {
00200     DataObjectImpl *This = impl_from_IDataObject(iface);
00201     ULONG ref = InterlockedDecrement(&This->ref);
00202     TRACE("(%p) ref=%d\n",This, ref);
00203 
00204     if(!ref) {
00205         if(This->unicode) GlobalFree(This->unicode);
00206         if(This->rtf) GlobalFree(This->rtf);
00207         if(This->fmtetc) GlobalFree(This->fmtetc);
00208         heap_free(This);
00209     }
00210 
00211     return ref;
00212 }
00213 
00214 static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
00215 {
00216     DataObjectImpl *This = impl_from_IDataObject(iface);
00217     TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
00218 
00219     if(pformatetc->lindex != -1)
00220         return DV_E_LINDEX;
00221 
00222     if(!(pformatetc->tymed & TYMED_HGLOBAL))
00223         return DV_E_TYMED;
00224 
00225     if(This->unicode && pformatetc->cfFormat == CF_UNICODETEXT)
00226         pmedium->u.hGlobal = This->unicode;
00227     else if(This->rtf && pformatetc->cfFormat == cfRTF)
00228         pmedium->u.hGlobal = This->rtf;
00229     else
00230         return DV_E_FORMATETC;
00231 
00232     pmedium->tymed = TYMED_HGLOBAL;
00233     pmedium->pUnkForRelease = (LPUNKNOWN)iface;
00234     IUnknown_AddRef(pmedium->pUnkForRelease);
00235     return S_OK;
00236 }
00237 
00238 static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
00239 {
00240     DataObjectImpl *This = impl_from_IDataObject(iface);
00241     FIXME("(%p): stub\n", This);
00242     return E_NOTIMPL;
00243 }
00244 
00245 static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
00246 {
00247     DataObjectImpl *This = impl_from_IDataObject(iface);
00248     UINT i;
00249     BOOL foundFormat = FALSE;
00250     TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
00251 
00252     if(pformatetc->lindex != -1)
00253         return DV_E_LINDEX;
00254 
00255     for(i=0; i<This->fmtetc_cnt; i++) {
00256         if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
00257             foundFormat = TRUE;
00258             if(This->fmtetc[i].tymed == pformatetc->tymed)
00259                 return S_OK;
00260         }
00261     }
00262     return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
00263 }
00264 
00265 static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatetcIn,
00266                                                            FORMATETC *pformatetcOut)
00267 {
00268     DataObjectImpl *This = impl_from_IDataObject(iface);
00269     TRACE("(%p)->(%p,%p)\n", This, pformatetcIn, pformatetcOut);
00270 
00271     if(pformatetcOut) {
00272         *pformatetcOut = *pformatetcIn;
00273         pformatetcOut->ptd = NULL;
00274     }
00275     return DATA_S_SAMEFORMATETC;
00276 }
00277 
00278 static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
00279                                              STGMEDIUM *pmedium, BOOL fRelease)
00280 {
00281     DataObjectImpl *This = impl_from_IDataObject(iface);
00282     FIXME("(%p): stub\n", This);
00283     return E_NOTIMPL;
00284 }
00285 
00286 static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject* iface, DWORD dwDirection,
00287                                                    IEnumFORMATETC **ppenumFormatEtc)
00288 {
00289     DataObjectImpl *This = impl_from_IDataObject(iface);
00290     TRACE("(%p)->(%d)\n", This, dwDirection);
00291 
00292     if(dwDirection != DATADIR_GET) {
00293         FIXME("Unsupported direction: %d\n", dwDirection);
00294         /* WinXP riched20 also returns E_NOTIMPL in this case */
00295         *ppenumFormatEtc = NULL;
00296         return E_NOTIMPL;
00297     }
00298     return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
00299 }
00300 
00301 static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
00302                                              IAdviseSink *pAdvSink, DWORD *pdwConnection)
00303 {
00304     DataObjectImpl *This = impl_from_IDataObject(iface);
00305     FIXME("(%p): stub\n", This);
00306     return E_NOTIMPL;
00307 }
00308 
00309 static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject* iface, DWORD dwConnection)
00310 {
00311     DataObjectImpl *This = impl_from_IDataObject(iface);
00312     FIXME("(%p): stub\n", This);
00313     return E_NOTIMPL;
00314 }
00315 
00316 static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject* iface, IEnumSTATDATA **ppenumAdvise)
00317 {
00318     DataObjectImpl *This = impl_from_IDataObject(iface);
00319     FIXME("(%p): stub\n", This);
00320     return E_NOTIMPL;
00321 }
00322 
00323 static const IDataObjectVtbl VT_DataObjectImpl =
00324 {
00325     DataObjectImpl_QueryInterface,
00326     DataObjectImpl_AddRef,
00327     DataObjectImpl_Release,
00328     DataObjectImpl_GetData,
00329     DataObjectImpl_GetDataHere,
00330     DataObjectImpl_QueryGetData,
00331     DataObjectImpl_GetCanonicalFormatEtc,
00332     DataObjectImpl_SetData,
00333     DataObjectImpl_EnumFormatEtc,
00334     DataObjectImpl_DAdvise,
00335     DataObjectImpl_DUnadvise,
00336     DataObjectImpl_EnumDAdvise
00337 };
00338 
00339 static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, int nChars)
00340 {
00341     int pars = 0;
00342     WCHAR *data;
00343     HANDLE ret;
00344     ME_DisplayItem *para;
00345     int nEnd = ME_GetCursorOfs(start) + nChars;
00346 
00347     /* count paragraphs in range */
00348     para = start->pPara;
00349     while((para = para->member.para.next_para) &&
00350           para->member.para.nCharOfs <= nEnd)
00351         pars++;
00352 
00353     ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1));
00354     data = GlobalLock(ret);
00355     ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE);
00356     GlobalUnlock(ret);
00357     return ret;
00358 }
00359 
00360 typedef struct tagME_GlobalDestStruct
00361 {
00362   HGLOBAL hData;
00363   int nLength;
00364 } ME_GlobalDestStruct;
00365 
00366 static DWORD CALLBACK ME_AppendToHGLOBAL(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
00367 {
00368     ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
00369     int nMaxSize;
00370     BYTE *pDest;
00371 
00372     nMaxSize = GlobalSize(pData->hData);
00373     if (pData->nLength+cb+1 >= cb) {
00374         /* round up to 2^17 */
00375         int nNewSize = (((nMaxSize+cb+1)|0x1FFFF)+1) & 0xFFFE0000;
00376         pData->hData = GlobalReAlloc(pData->hData, nNewSize, 0);
00377     }
00378     pDest = GlobalLock(pData->hData);
00379     memcpy(pDest + pData->nLength, lpBuff, cb);
00380     pData->nLength += cb;
00381     pDest[pData->nLength] = '\0';
00382     GlobalUnlock(pData->hData);
00383     *pcb = cb;
00384 
00385     return 0;
00386 }
00387 
00388 static HGLOBAL get_rtf_text(ME_TextEditor *editor, const ME_Cursor *start, int nChars)
00389 {
00390     EDITSTREAM es;
00391     ME_GlobalDestStruct gds;
00392 
00393     gds.hData = GlobalAlloc(GMEM_MOVEABLE, 0);
00394     gds.nLength = 0;
00395     es.dwCookie = (DWORD_PTR)&gds;
00396     es.pfnCallback = ME_AppendToHGLOBAL;
00397     ME_StreamOutRange(editor, SF_RTF, start, nChars, &es);
00398     GlobalReAlloc(gds.hData, gds.nLength+1, 0);
00399     return gds.hData;
00400 }
00401 
00402 HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start,
00403                          int nChars, LPDATAOBJECT *lplpdataobj)
00404 {
00405     DataObjectImpl *obj;
00406     TRACE("(%p,%d,%d)\n", editor, ME_GetCursorOfs(start), nChars);
00407 
00408     obj = heap_alloc(sizeof(DataObjectImpl));
00409     if(cfRTF == 0)
00410         cfRTF = RegisterClipboardFormatA("Rich Text Format");
00411 
00412     obj->IDataObject_iface.lpVtbl = &VT_DataObjectImpl;
00413     obj->ref = 1;
00414     obj->unicode = get_unicode_text(editor, start, nChars);
00415     obj->rtf = NULL;
00416 
00417     obj->fmtetc_cnt = 1;
00418     if(editor->mode & TM_RICHTEXT)
00419         obj->fmtetc_cnt++;
00420     obj->fmtetc = GlobalAlloc(GMEM_ZEROINIT, obj->fmtetc_cnt*sizeof(FORMATETC));
00421     InitFormatEtc(obj->fmtetc[0], CF_UNICODETEXT, TYMED_HGLOBAL);
00422     if(editor->mode & TM_RICHTEXT) {
00423         obj->rtf = get_rtf_text(editor, start, nChars);
00424         InitFormatEtc(obj->fmtetc[1], cfRTF, TYMED_HGLOBAL);
00425     }
00426 
00427     *lplpdataobj = (LPDATAOBJECT)obj;
00428     return S_OK;
00429 }

Generated on Sat May 26 2012 04:24:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.