1 #include "win32\win32guts.h"
2 #ifndef _APRICOT_H_
3 #include "apricot.h"
4 #endif
5 #include "guts.h"
6 #include "Window.h"
7 #include "Application.h"
8 #include "Clipboard.h"
9 #include "Icon.h"
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15
16 #define sys (( PDrawableData)(( PComponent) self)-> sysData)->
17 #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
18 #define var (( PWidget) self)->
19 #define HANDLE sys handle
20 #define DHANDLE(x) dsys(x) handle
21
22 PList
apc_get_standard_clipboards(void)23 apc_get_standard_clipboards( void)
24 {
25 PList l = plist_create( 1, 1);
26 if (!l) return NULL;
27 list_add( l, (Handle)duplicate_string( "Clipboard"));
28 list_add( l, (Handle)duplicate_string( "DragDrop"));
29 return l;
30 }
31
32 Bool
apc_clipboard_create(Handle self)33 apc_clipboard_create( Handle self)
34 {
35 char * c = ((PClipboard)self)-> name;
36 if ( !c ) return false;
37
38 if (strcmp(c, "Clipboard") == 0)
39 guts.clipboards[CLIPBOARD_MAIN] = self;
40 else if (strcmp(c, "DragDrop") == 0) {
41 guts.clipboards[CLIPBOARD_DND] = self;
42 return dnd_clipboard_create();
43 } else
44 return false;
45 return true;
46 }
47
48 Bool
apc_clipboard_destroy(Handle self)49 apc_clipboard_destroy( Handle self)
50 {
51 int i;
52 if (self == guts.clipboards[CLIPBOARD_DND])
53 dnd_clipboard_destroy();
54 for ( i = 0; i < 2; i++)
55 if ( guts.clipboards[i] == self )
56 guts.clipboards[i] = NULL_HANDLE;
57 return true;
58 }
59
60 Bool
apc_clipboard_open(Handle self)61 apc_clipboard_open( Handle self)
62 {
63 if (self == guts.clipboards[CLIPBOARD_DND])
64 return dnd_clipboard_open();
65
66 if ( !OpenClipboard( NULL)) apiErrRet;
67 return true;
68 }
69
70 Bool
apc_clipboard_close(Handle self)71 apc_clipboard_close( Handle self)
72 {
73 if (self == guts.clipboards[CLIPBOARD_DND])
74 return dnd_clipboard_close();
75
76 if ( !CloseClipboard()) apiErrRet;
77 return true;
78 }
79
80 Bool
apc_clipboard_clear(Handle self)81 apc_clipboard_clear( Handle self)
82 {
83 if (self == guts.clipboards[CLIPBOARD_DND])
84 return dnd_clipboard_clear();
85
86 if ( !EmptyClipboard()) apiErrRet;
87 return true;
88 }
89
cf2CF(Handle id)90 static Handle cf2CF( Handle id)
91 {
92 if ( id == cfText) return CF_TEXT;
93 if ( id == cfUTF8) return CF_UNICODETEXT;
94 if ( id == cfBitmap) return CF_BITMAP;
95 return id - cfCustom;
96 }
97
98 static struct {
99 UINT format;
100 char desc[ 20];
101 } formats[] = {
102 {CF_METAFILEPICT , "CF_METAFILEPICT"
103 }, {CF_SYLK , "CF_SYLK"
104 }, {CF_DIF , "CF_DIF"
105 }, {CF_TIFF , "CF_TIFF"
106 }, {CF_OEMTEXT , "CF_OEMTEXT"
107 }, {CF_PENDATA , "CF_PENDATA"
108 }, {CF_RIFF , "CF_RIFF"
109 }, {CF_WAVE , "CF_WAVE"
110 }, {CF_ENHMETAFILE , "CF_ENHMETAFILE"
111 }, {CF_HDROP , "CF_HDROP"
112 }, {CF_LOCALE , "CF_LOCALE"
113 }, {CF_DIBV5 , "CF_DIBV5"
114 }, {CF_MAX , "CF_MAX"
115 }
116 };
117
118 char *
cf2name(UINT f)119 cf2name(UINT f)
120 {
121 switch ( f ) {
122 case CF_TEXT:
123 return duplicate_string("Text");
124 break;
125 case CF_BITMAP:
126 return duplicate_string("Image");
127 break;
128 case CF_UNICODETEXT:
129 return duplicate_string("UTF8");
130 break;
131 case CF_DIB:
132 return duplicate_string("CF_DIB");
133 break;
134 case CF_PALETTE:
135 return duplicate_string("CF_PALETTE");
136 break;
137 default: {
138 int i = 0;
139 char name[256];
140 while ( formats[i]. format != CF_MAX) {
141 if ( formats[i]. format == f)
142 return duplicate_string(formats[i]. desc);
143 i++;
144 }
145 if ( GetClipboardFormatName( f, name, 255))
146 return duplicate_string(name);
147 }}
148 return NULL;
149 }
150
151 PList
apc_clipboard_get_formats(Handle self)152 apc_clipboard_get_formats( Handle self)
153 {
154 UINT f = 0;
155 PList list;
156
157 if (self == guts.clipboards[CLIPBOARD_DND])
158 return dnd_clipboard_get_formats();
159
160 list = plist_create(8, 8);
161 while (( f = EnumClipboardFormats( f))) {
162 char * name = cf2name(f);
163 if ( f )
164 list_add(list, (Handle)name);
165 }
166
167 return list;
168 }
169
170 Bool
apc_clipboard_has_format(Handle self,Handle id)171 apc_clipboard_has_format( Handle self, Handle id)
172 {
173 id = cf2CF( id);
174 if (self == guts.clipboards[CLIPBOARD_DND])
175 return dnd_clipboard_has_format(id);
176
177 return IsClipboardFormatAvailable( id) ||
178 (( id == CF_TEXT) && IsClipboardFormatAvailable( CF_UNICODETEXT));
179 }
180
181 Bool
clipboard_get_data(int cfid,PClipboardDataRec c,void * p1,void * p2)182 clipboard_get_data(int cfid, PClipboardDataRec c, void * p1, void * p2)
183 {
184 switch( cfid)
185 {
186 case CF_DIB: {
187 PIcon i;
188 XBITMAPINFO * bi;
189 if ( !( bi = ( XBITMAPINFO*) GlobalLock( p1)))
190 apiErrRet;
191 if ( bi-> bmiHeader. biCompression != BI_RGB ) {
192 GlobalUnlock( p1);
193 return false;
194 }
195 if ( bi-> bmiHeader. biBitCount == 32 ) {
196 i = (PIcon) create_object("Prima::Icon",
197 "iiiii",
198 "maskType", 8,
199 "width", bi-> bmiHeader. biWidth,
200 "height", bi-> bmiHeader. biHeight,
201 "type", imRGB,
202 "autoMasking", amNone
203 );
204 if ( !i) {
205 GlobalUnlock( p1);
206 return false;
207 }
208 image_argb_query_bits((Handle) i);
209 } else if (
210 bi-> bmiHeader. biBitCount == 1 ||
211 bi-> bmiHeader. biBitCount == 4 ||
212 bi-> bmiHeader. biBitCount == 8
213 ) {
214 Byte * data;
215 int j, colors = bi-> bmiHeader. biClrUsed;
216
217 i = (PIcon) create_object("Prima::Image",
218 "iii",
219 "width", bi-> bmiHeader. biWidth,
220 "height", bi-> bmiHeader. biHeight,
221 "type", bi-> bmiHeader. biBitCount
222 );
223 if ( !i) {
224 GlobalUnlock( p1);
225 return false;
226 }
227 if ( colors > 256 ) colors = 256;
228 i->palSize = colors;
229 for ( j = 0; j < colors; j++) {
230 i-> palette[ j]. r = bi-> bmiColors[ j]. rgbRed ;
231 i-> palette[ j]. g = bi-> bmiColors[ j]. rgbGreen;
232 i-> palette[ j]. b = bi-> bmiColors[ j]. rgbBlue ;
233 }
234
235 data = (Byte*)bi;
236 data += sizeof(BITMAPINFOHEADER) + bi-> bmiHeader.biClrUsed * sizeof(RGBQUAD);
237 memcpy( i->data, data, i->dataSize );
238 } else {
239 GlobalUnlock( p1);
240 return false;
241 }
242 c->image = (Handle) i;
243 GlobalUnlock( p1);
244 return true;
245 }
246 case CF_BITMAP: {
247 Handle self;
248 HBITMAP b = (HBITMAP) p1;
249 HPALETTE op = NULL, p = (HPALETTE) p2;
250 HBITMAP obm;
251 HDC dc, ops;
252
253 self = (Handle) create_object("Prima::Image", "");
254 obm = sys bm;
255 sys bm = b;
256 apcErrClear;
257 if (!( dc = CreateCompatibleDC( dc_alloc()))) {
258 Object_destroy(self);
259 return false;
260 }
261 ops = sys ps;
262 sys ps = dc;
263
264 if ( p) {
265 op = SelectPalette( dc, p, 1);
266 RealizePalette( dc);
267 }
268 image_query_bits(self, true);
269 if ( p)
270 SelectPalette( dc, op, 1);
271 DeleteDC( dc);
272 dc_free();
273 sys ps = ops;
274 sys bm = obm;
275 c->image = self;
276 return true;
277 }
278 case CF_UNICODETEXT: {
279 WCHAR *ptr;
280 Bool ret = false;
281
282 if ( !( ptr = ( WCHAR*) GlobalLock( p1)))
283 apiErrRet;
284 apcErrClear;
285 c->length = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, NULL, 0, NULL, 0);
286 if (( c->data = malloc( c-> length ) )) {
287 WideCharToMultiByte(CP_UTF8, 0, ptr, -1, (LPSTR)c->data, c->length, NULL, 0);
288 if ( c->length > 0) c->length--; // terminating 0
289 ret = true;
290 } else {
291 c->length = 0;
292 }
293 GlobalUnlock( p1);
294 return ret;
295 }
296 case CF_TEXT: {
297 Byte *ptr;
298 int i, len, ret = false;
299
300 if ( !( ptr = ( Byte*) GlobalLock( p1)))
301 apiErrRet;
302 apcErrClear;
303 len = strlen(( char*) ptr);
304 c-> length = 0;
305 if ((c-> data = ( Byte *) malloc( len))) {
306 for ( i = 0; i < len; i++)
307 if ( ptr[i] != '\r' || (( i < len) && (ptr[i+1] != '\n')))
308 c-> data[c-> length++] = ptr[i];
309 ret = true;
310 }
311 GlobalUnlock( p1);
312 return ret;
313 }
314 default: {
315 char *ptr;
316 if (( c-> length = GlobalSize( p1)) == 0)
317 return true; /* not an error */
318 if ( !( ptr = ( char*) GlobalLock( p1)))
319 apiErrRet;
320 if (( c-> data = malloc( c-> length)))
321 memcpy( c-> data, ptr, c-> length);
322 GlobalUnlock( p1);
323 return true;
324 }
325 }
326 return false;
327 }
328
329 Bool
apc_clipboard_get_data(Handle self,Handle id,PClipboardDataRec c)330 apc_clipboard_get_data( Handle self, Handle id, PClipboardDataRec c)
331 {
332 void *ph;
333
334 id = cf2CF( id);
335 if (self == guts.clipboards[CLIPBOARD_DND])
336 return dnd_clipboard_get_data(id, c);
337
338 if ((ph = GetClipboardData(id)) == NULL) {
339 apcErr( errInvClipboardData);
340 return false;
341 }
342
343 return clipboard_get_data(id, c, ph,
344 (id == CF_BITMAP) ? (void*) GetClipboardData( CF_PALETTE) : NULL);
345 }
346
347 Bool
apc_clipboard_set_data(Handle self,Handle id,PClipboardDataRec c)348 apc_clipboard_set_data( Handle self, Handle id, PClipboardDataRec c)
349 {
350 if ( c-> length < 0 ) return false;
351
352 id = cf2CF( id);
353 if (self == guts.clipboards[CLIPBOARD_DND])
354 return dnd_clipboard_set_data(id, c);
355
356 switch ( id)
357 {
358 case CF_BITMAP:
359 {
360 HPALETTE p = palette_create( c-> image);
361 HBITMAP b = image_create_bitmap_by_type( c-> image, p, NULL, BM_AUTO);
362
363 if ( b == NULL) {
364 if ( p) DeleteObject( p);
365 apiErrRet;
366 }
367 if ( !SetClipboardData( CF_BITMAP, b)) apiErr;
368 if ( p)
369 if ( !SetClipboardData( CF_PALETTE, p)) apiErr;
370 }
371 return true;
372 case CF_UNICODETEXT:
373 {
374 int ulen = MultiByteToWideChar(CP_UTF8, 0, (char*) c-> data, c-> length, NULL, 0) + 1;
375 void *ptr = NULL;
376 HGLOBAL glob;
377
378 if (( glob = GlobalAlloc( GMEM_DDESHARE, ( ulen + 0) * sizeof( WCHAR)))) {
379 if (( ptr = GlobalLock( glob))) {
380 MultiByteToWideChar(CP_UTF8, 0, (LPSTR)c-> data, c-> length, ptr, ulen);
381 GlobalUnlock( glob);
382 if ( !SetClipboardData( CF_UNICODETEXT, glob)) apiErr;
383 } else {
384 GlobalFree( glob);
385 apiErr;
386 }
387 } else apiErr;
388 }
389 return true;
390 case CF_TEXT:
391 {
392 int ulen = c-> length;
393 int i, cr = 0;
394 void *ptr = NULL, *oemptr = NULL;
395 char *dst;
396 HGLOBAL glob, oemglob;
397
398 for ( i = 0; i < c-> length; i++)
399 if (c-> data[i] == '\n' && ( i == 0 || c-> data[i-1] != '\r'))
400 cr++;
401
402 glob = GlobalAlloc( GMEM_DDESHARE, ulen + cr + 1);
403 oemglob = GlobalAlloc( GMEM_DDESHARE, ulen + cr + 1);
404 if ( glob) ptr = GlobalLock( glob);
405 if ( oemglob) oemptr = GlobalLock( oemglob);
406
407 if ( ptr && oemptr) {
408 dst = ( char *) ptr;
409 for ( i = 0; i < c-> length; i++) {
410 if ( c-> data[i] == '\n' && ( i == 0 || c-> data[i-1] != '\r'))
411 *(dst++) = '\r';
412 *(dst++) = c-> data[i];
413 }
414 *dst = 0;
415 CharToOemBuff(( LPCTSTR) ptr, ( LPTSTR) oemptr, ulen + cr + 1);
416 GlobalUnlock( oemptr);
417 GlobalUnlock( ptr);
418 if ( !SetClipboardData( CF_TEXT, glob)) apiErr;
419 if ( !SetClipboardData( CF_OEMTEXT, oemglob)) apiErr;
420 } else {
421 apiErr;
422 if ( ptr) GlobalUnlock( ptr);
423 if ( oemptr) GlobalUnlock( oemptr);
424 if ( glob) GlobalFree( glob);
425 if ( oemglob) GlobalFree( oemglob);
426 }
427 }
428 return true;
429 default:
430 {
431 char* ptr;
432 HGLOBAL glob = GlobalAlloc( GMEM_DDESHARE, c-> length);
433 if ( !glob) apiErrRet;
434 if ( !( ptr = ( char *) GlobalLock( glob))) {
435 apiErr;
436 GlobalFree( glob);
437 return false;
438 }
439 memcpy( ptr, c-> data, c-> length);
440 GlobalUnlock( glob);
441 if ( !SetClipboardData( id, glob)) apiErrRet;
442 return true;
443 }
444 }
445 return false;
446 }
447
448 Handle
apc_clipboard_register_format(Handle self,const char * format)449 apc_clipboard_register_format( Handle self, const char * format)
450 {
451 UINT r;
452 int i = 0;
453 while ( formats[i]. format != CF_MAX) {
454 if ( strcmp(formats[i]. desc, format) == 0)
455 return formats[i]. format + cfCustom;
456 i++;
457 }
458 if ( !( r = RegisterClipboardFormat( format))) apiErrRet;
459 return r + cfCustom;
460 }
461
462 Bool
apc_clipboard_deregister_format(Handle self,Handle id)463 apc_clipboard_deregister_format( Handle self, Handle id)
464 {
465 return true;
466 }
467
468 ApiHandle
apc_clipboard_get_handle(Handle self)469 apc_clipboard_get_handle( Handle self)
470 {
471 return NULL_HANDLE;
472 }
473
474 Bool
apc_clipboard_is_dnd(Handle self)475 apc_clipboard_is_dnd( Handle self)
476 {
477 return self == guts.clipboards[CLIPBOARD_DND];
478 }
479
480 #ifdef __cplusplus
481 }
482 #endif
483