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