oledlg: Set the user supplied caption.
[wine] / dlls / oledlg / pastespl.c
1 /*
2  * OleUIPasteSpecial implementation
3  *
4  * Copyright 2006 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COM_NO_WINDOWS_H
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "oledlg.h"
31
32 #include "oledlg_private.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37
38 typedef struct
39 {
40     OLEUIPASTESPECIALW *ps;
41     DWORD flags;
42 } ps_struct_t;
43
44 static const struct ps_flag
45 {
46     DWORD flag;
47     const char *name;
48 } ps_flags[] = {
49 #define PS_FLAG_ENTRY(p) {p, #p}
50     PS_FLAG_ENTRY(PSF_SHOWHELP),
51     PS_FLAG_ENTRY(PSF_SELECTPASTE),
52     PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
53     PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
54     PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
55     PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
56     PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
57     PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
58     {-1, NULL}
59 #undef PS_FLAG_ENTRY
60 };
61
62 static void dump_ps_flags(DWORD flags)
63 {
64     char flagstr[1000] = "";
65
66     const struct ps_flag *flag = ps_flags;
67     for( ; flag->name; flag++) {
68         if(flags & flag->flag) {
69             strcat(flagstr, flag->name);
70             strcat(flagstr, "|");
71         }
72     }
73     TRACE("flags %08x %s\n", flags, flagstr);
74 }
75
76 static void dump_pastespecial(LPOLEUIPASTESPECIALW ps)
77 {
78     UINT i;
79     dump_ps_flags(ps->dwFlags);
80     TRACE("hwnd %p caption %s hook %p custdata %lx\n",
81           ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
82     if(IS_INTRESOURCE(ps->lpszTemplate))
83         TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
84     else
85         TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
86     TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
87           ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
88           ps->arrLinkTypes, ps->cLinkTypes);
89     TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
90           ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
91           ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
92     for(i = 0; i < ps->cPasteEntries; i++)
93     {
94         TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
95               i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
96               ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
97               ps->arrPasteEntries[i].fmtetc.tymed);
98         TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
99               debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
100     }
101     for(i = 0; i < ps->cLinkTypes; i++)
102         TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
103     for(i = 0; i < ps->cClsidExclude; i++)
104         TRACE("lpClsidExclude[%d] %s\n", i, debugstr_guid(&ps->lpClsidExclude[i]));
105
106 }
107
108 static inline WCHAR *strdupAtoW(const char *str)
109 {
110     DWORD len;
111     WCHAR *ret;
112     if(!str) return NULL;
113     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
114     ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
115     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
116     return ret;
117 }
118
119 static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
120 {
121     ps_struct->ps->dwFlags = ps_struct->flags;
122     ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) ? TRUE : FALSE;
123 }
124
125 static void free_structure(ps_struct_t *ps_struct)
126 {
127     HeapFree(GetProcessHeap(), 0, ps_struct);
128 }
129
130 static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
131 {
132     /* native uses prop name "Structure", but we're not compatible
133        with that so we'll prepend "Wine_". */
134     static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
135     ps_struct_t *ps_struct;
136
137     TRACE("(%p, %04x, %08x, %08lx)\n", hdlg, msg, wp, lp);
138
139     ps_struct = GetPropW(hdlg, prop_name);
140
141     if(msg != WM_INITDIALOG)
142     {
143         if(!ps_struct)
144             return 0;
145     }
146
147     switch(msg)
148     {
149     case WM_INITDIALOG:
150     {
151         ps_struct = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct));
152         ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
153         ps_struct->flags = ps_struct->ps->dwFlags;
154
155         SetPropW(hdlg, prop_name, ps_struct);
156
157         if(ps_struct->ps->lpszCaption)
158             SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);
159
160         return TRUE; /* use default focus */
161     }
162     case WM_COMMAND:
163         switch(LOWORD(wp))
164         {
165         case IDOK:
166         case IDCANCEL:
167             if(wp == IDOK)
168                 update_structure(hdlg, ps_struct);
169             EndDialog(hdlg, wp);
170             free_structure(ps_struct);
171             return TRUE;
172         }
173         return FALSE;
174     default:
175         return FALSE;
176     }
177
178 }
179
180 /***********************************************************************
181  *           OleUIPasteSpecialA (OLEDLG.4)
182  */
183 UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
184 {
185     OLEUIPASTESPECIALW ps;
186     UINT ret;
187     TRACE("(%p)\n", psA);
188
189     memcpy(&ps, psA, psA->cbStruct);
190
191     ps.lpszCaption = strdupAtoW(psA->lpszCaption);
192     if(!IS_INTRESOURCE(ps.lpszTemplate))
193         ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);
194
195     if(psA->cPasteEntries > 0)
196     {
197         DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
198         UINT i;
199
200         ps.arrPasteEntries = HeapAlloc(GetProcessHeap(), 0, size);
201         memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
202         for(i = 0; i < psA->cPasteEntries; i++)
203         {
204             ps.arrPasteEntries[i].lpstrFormatName =
205                 strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
206             ps.arrPasteEntries[i].lpstrResultText =
207                 strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
208         }
209     }
210
211     ret = OleUIPasteSpecialW(&ps);
212
213     if(psA->cPasteEntries > 0)
214     {
215         UINT i;
216         for(i = 0; i < psA->cPasteEntries; i++)
217         {
218             HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
219             HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
220         }
221         HeapFree(GetProcessHeap(), 0, ps.arrPasteEntries);
222     }
223     if(!IS_INTRESOURCE(ps.lpszTemplate))
224         HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszTemplate);
225     HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszCaption);
226
227     /* Copy back the output fields */
228     psA->dwFlags = ps.dwFlags;
229     psA->lpSrcDataObj = ps.lpSrcDataObj;
230     psA->nSelectedIndex = ps.nSelectedIndex;
231     psA->fLink = ps.fLink;
232     psA->hMetaPict = ps.hMetaPict;
233     psA->sizel = ps.sizel;
234
235     return ret;
236 }
237
238 /***********************************************************************
239  *           OleUIPasteSpecialW (OLEDLG.22)
240  */
241 UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
242 {
243     LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
244
245     TRACE("(%p)\n", ps);
246
247     if(TRACE_ON(ole)) dump_pastespecial(ps);
248
249     if(!ps->lpSrcDataObj)
250         OleGetClipboard(&ps->lpSrcDataObj);
251
252     if(ps->hInstance || !ps->hResource)
253     {
254         HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
255         const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
256         HRSRC hrsrc;
257
258         if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
259         hrsrc = FindResourceW(hInst, name, MAKEINTRESOURCEW(RT_DIALOG));
260         if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
261         dlg_templ = LoadResource(hInst, hrsrc);
262         if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
263     }
264
265     DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);
266
267     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
268     return OLEUI_FALSE;
269 }