1 #include "win32\win32guts.h"
2 #include <stdio.h>
3 #include <stdarg.h>
4 #ifndef _APRICOT_H_
5 #include "apricot.h"
6 #endif
7 #include "guts.h"
8 #include "Component.h"
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 
15 static Handle ctx_mb2MB[] =
16 {
17 	mbError       , MB_ICONHAND,
18 	mbQuestion    , MB_ICONQUESTION,
19 	mbInformation , MB_ICONASTERISK,
20 	mbWarning     , MB_ICONEXCLAMATION,
21 	endCtx
22 };
23 
24 
25 Bool
apc_beep(int style)26 apc_beep( int style)
27 {
28 	if ( !MessageBeep( ctx_remap_def( style, ctx_mb2MB, true, MB_OK))) apiErrRet;
29 	return true;
30 }
31 
32 Bool
apc_beep_tone(int freq,int duration)33 apc_beep_tone( int freq, int duration)
34 {
35 	if ( !Beep( freq, duration)) apiErrRet;
36 	return true;
37 }
38 
39 Bool
apc_query_drives_map(const char * firstDrive,char * map,int len)40 apc_query_drives_map( const char *firstDrive, char *map, int len)
41 {
42 	char *m = map;
43 	int beg;
44 	DWORD driveMap;
45 	int i;
46 
47 #ifdef __CYGWIN__
48 	if ( !map || len <= 0) return true;
49 	*map = 0;
50 	return true;
51 #endif
52 	if ( !map) return false;
53 
54 	beg = toupper( *firstDrive);
55 	if (( beg < 'A') || ( beg > 'Z') || ( firstDrive[1] != ':'))
56 		return false;
57 
58 	beg -= 'A';
59 
60 	if ( !( driveMap = GetLogicalDrives()))
61 		apiErr;
62 	for ( i = beg; i < 26 && m - map + 3 < len; i++)
63 	{
64 		if ((driveMap << ( 31 - i)) >> 31)
65 		{
66 			*m++ = i + 'A';
67 			*m++ = ':';
68 			*m++ = ' ';
69 		}
70 	}
71 
72 	*m = '\0';
73 	return true;
74 }
75 
76 static Handle ctx_dt2DRIVE[] =
77 {
78 	dtUnknown  , 0               ,
79 	dtNone     , 1               ,
80 	dtFloppy   , DRIVE_REMOVABLE ,
81 	dtHDD      , DRIVE_FIXED     ,
82 	dtNetwork  , DRIVE_REMOTE    ,
83 	dtCDROM    , DRIVE_CDROM     ,
84 	dtMemory   , DRIVE_RAMDISK   ,
85 	endCtx
86 };
87 
88 int
apc_query_drive_type(const char * drive)89 apc_query_drive_type( const char *drive)
90 {
91 	char buf[ 256];                        //  Win95 fix
92 #ifdef __CYGWIN__
93 	return false;
94 #endif
95 	strncpy( buf, drive, 255);             //     sometimes D: isn't enough for 95,
96 	if ( buf[1] == ':' && buf[2] == 0) {   //     but ok for D:\.
97 		buf[2] = '\\';                      //
98 		buf[3] = 0;                         //
99 	}                                      //
100 	return ctx_remap_def( GetDriveType( buf), ctx_dt2DRIVE, false, dtNone);
101 }
102 
103 static char userName[ 1024];
104 
105 char *
apc_get_user_name()106 apc_get_user_name()
107 {
108 	DWORD maxSize = 1024;
109 
110 	if ( !GetUserName( userName, &maxSize)) apiErr;
111 	return userName;
112 }
113 
114 Bool
apc_show_message(const char * message,Bool utf8)115 apc_show_message( const char * message, Bool utf8)
116 {
117 	Bool ret;
118 	if ( utf8 && (message = ( char*)alloc_utf8_to_wchar( message, -1, NULL))) {
119 		ret = MessageBoxW( NULL, ( WCHAR*) message, L"Prima", MB_OK | MB_TASKMODAL | MB_SETFOREGROUND) != 0;
120 		free(( void*) message);
121 	} else
122 		ret = MessageBox( NULL, message, "Prima", MB_OK | MB_TASKMODAL | MB_SETFOREGROUND) != 0;
123 	return ret;
124 }
125 
126 Bool
apc_sys_get_insert_mode()127 apc_sys_get_insert_mode()
128 {
129 	return guts. insertMode;
130 }
131 
132 Bool
apc_sys_set_insert_mode(Bool insMode)133 apc_sys_set_insert_mode( Bool insMode)
134 {
135 	guts. insertMode = insMode;
136 	return true;
137 }
138 
139 Point
get_window_borders(int borderStyle)140 get_window_borders( int borderStyle)
141 {
142 	Point ret = { 0, 0};
143 	switch ( borderStyle)
144 	{
145 		case bsSizeable:
146 			ret. x = GetSystemMetrics( SM_CXFRAME);
147 			ret. y = GetSystemMetrics( SM_CYFRAME);
148 			break;
149 		case bsSingle:
150 			ret. x = GetSystemMetrics( SM_CXBORDER);
151 			ret. y = GetSystemMetrics( SM_CYBORDER);
152 			break;
153 		case bsDialog:
154 			ret. x = GetSystemMetrics( SM_CXDLGFRAME);
155 			ret. y = GetSystemMetrics( SM_CYDLGFRAME);
156 			break;
157 	}
158 	return ret;
159 }
160 
161 int
apc_sys_get_value(int sysValue)162 apc_sys_get_value( int sysValue)
163 {
164 	HKEY hKey;
165 	DWORD valSize = 256, valType = REG_SZ;
166 	char buf[ 256] = "";
167 
168 	switch ( sysValue) {
169 	case svYMenu          :
170 		return guts. ncmData. iMenuHeight;
171 	case svYTitleBar      :
172 		return guts. ncmData. iCaptionHeight;
173 	case svMousePresent   :
174 		return GetSystemMetrics( SM_MOUSEPRESENT);
175 	case svMouseButtons   :
176 		return GetSystemMetrics( SM_CMOUSEBUTTONS);
177 	case svSubmenuDelay   :
178 		RegOpenKeyEx( HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &hKey);
179 		RegQueryValueEx( hKey, "MenuShowDelay", NULL, &valType, ( LPBYTE) buf, &valSize);
180 		RegCloseKey( hKey);
181 		return atol( buf);
182 	case svFullDrag       :
183 		RegOpenKeyEx( HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &hKey);
184 		RegQueryValueEx( hKey, "DragFullWindows", NULL, &valType, ( LPBYTE)buf, &valSize);
185 		RegCloseKey( hKey);
186 		return atol( buf);
187 	case svDblClickDelay   :
188 		RegOpenKeyEx( HKEY_CURRENT_USER, "Control Panel\\Mouse", 0, KEY_READ, &hKey);
189 		RegQueryValueEx( hKey, "DoubleClickSpeed", NULL, &valType, ( LPBYTE)buf, &valSize);
190 		RegCloseKey( hKey);
191 		return atol( buf);
192 	case svWheelPresent    : return GetSystemMetrics( SM_MOUSEWHEELPRESENT);
193 	case svXIcon           : return guts. iconSizeLarge. x;
194 	case svYIcon           : return guts. iconSizeLarge. y;
195 	case svXSmallIcon      : return guts. iconSizeSmall. x;
196 	case svYSmallIcon      : return guts. iconSizeSmall. y;
197 	case svXPointer        : return guts. pointerSize. x;
198 	case svYPointer        : return guts. pointerSize. y;
199 	case svXScrollbar      : return GetSystemMetrics( SM_CXHSCROLL);
200 	case svYScrollbar      : return GetSystemMetrics( SM_CYVSCROLL);
201 	case svXCursor         : return GetSystemMetrics( SM_CXBORDER);
202 	case svAutoScrollFirst : return 200;
203 	case svAutoScrollNext  : return 50;
204 	case svInsertMode      : return guts. insertMode;
205 	case svXbsNone         : return 0;
206 	case svYbsNone         : return 0;
207 	case svXbsSizeable     : return GetSystemMetrics( SM_CXFRAME);
208 	case svYbsSizeable     : return GetSystemMetrics( SM_CYFRAME);
209 	case svXbsSingle       : return GetSystemMetrics( SM_CXBORDER);
210 	case svYbsSingle       : return GetSystemMetrics( SM_CYBORDER);
211 	case svXbsDialog       : return GetSystemMetrics( SM_CXDLGFRAME);
212 	case svYbsDialog       : return GetSystemMetrics( SM_CYDLGFRAME);
213 	case svShapeExtension  : return 1;
214 	case svColorPointer    : return guts. displayBMInfo. bmiHeader. biBitCount > 4;
215 	case svCanUTF8_Input   : return 1;
216 	case svCanUTF8_Output  : return 1;
217 	case svCompositeDisplay: return is_dwm_enabled();
218 	case svLayeredWidgets: return guts. displayBMInfo. bmiHeader. biBitCount > 8;
219 	case svFixedPointerSize: return 0;
220 	case svMenuCheckSize   : return GetSystemMetrics( SM_CXMENUCHECK );
221 	case svFriBidi         : return use_fribidi;
222 	case svAntialias       : return 1;
223 	default:
224 		return -1;
225 	}
226 	return 0;
227 }
228 
229 PFont
apc_sys_get_msg_font(PFont copyTo)230 apc_sys_get_msg_font( PFont copyTo)
231 {
232 	*copyTo = guts. msgFont;
233 	copyTo-> pitch = fpDefault;
234 	return copyTo;
235 }
236 
237 PFont
apc_sys_get_caption_font(PFont copyTo)238 apc_sys_get_caption_font( PFont copyTo)
239 {
240 	*copyTo = guts. capFont;
241 	copyTo-> pitch = fpDefault;
242 	return copyTo;
243 }
244 
245 Bool
hwnd_check_limits(int x,int y,Bool uint)246 hwnd_check_limits( int x, int y, Bool uint)
247 {
248 	if ( x > 16383 || y > 16383) return false;
249 	if ( uint && ( x < -16383 || y < -16383)) return false;
250 	return true;
251 }
252 
253 #define rgxExists      1
254 #define rgxNotExists   2
255 #define rgxHasSubkeys  4
256 #define rgxHasValues   8
257 #define rgxInUser      16
258 #define rgxInSys       32
259 
260 static Bool
prf_exists(HKEY hk,char * path,int * info)261 prf_exists( HKEY hk, char * path, int * info)
262 {
263 	HKEY hKey;
264 	Handle cache;
265 	if (( cache = ( Handle) hash_fetch( regnodeMan, path, strlen( path)))) {
266 		if ( info) *info = cache;
267 		return cache & rgxExists;
268 	}
269 
270 	if ( RegOpenKeyEx( hk, path, 0,
271 							KEY_READ, &hKey) != ERROR_SUCCESS) {
272 		hash_store( regnodeMan, path, strlen( path), (void*) rgxNotExists);
273 		return false;
274 	}
275 
276 	cache |= rgxExists;
277 	if ( info) {
278 		char buf[ MAXREGLEN];
279 		DWORD len = MAXREGLEN, subkeys = 0, msk, mc, values, mvn, mvd, sd;
280 		FILETIME ft;
281 		RegQueryInfoKey( hKey, buf, &len, NULL, &subkeys, &msk, &mc, &values,
282 			&mvn, &mvd, &sd, &ft);
283 		if ( subkeys > 0) cache |= rgxHasSubkeys;
284 		if ( values  > 0) cache |= rgxHasValues;
285 		*info = cache;
286 	}
287 	hash_store( regnodeMan, path, strlen( path), (void*) cache);
288 	RegCloseKey( hKey);
289 	return true;
290 }
291 
292 static Bool
prf_find(HKEY hk,char * path,List * ids,int firstName,char * result)293 prf_find( HKEY hk, char * path, List * ids, int firstName, char * result)
294 {
295 	char buf[ MAXREGLEN];
296 	int j = 2, info;
297 
298 	while ( j--) {
299 		snprintf( buf, MAXREGLEN, "%s\\%s", path, ( char*) ids[j].items[ firstName]);
300 		if ( prf_exists( hk, buf, NULL)) {
301 			if ( ids[j].count > firstName + 1) {
302 				if ( prf_find( hk, buf, ids, firstName + 1, result))
303 					return true;
304 			} else {
305 				strcpy( result, buf);
306 				return true;
307 			}
308 		}
309 	}
310 
311 	j = 2;
312 	while ( j--) {
313 		snprintf( buf, MAXREGLEN, "%s\\*", path);
314 		if ( prf_exists( hk, buf, &info)) {
315 			if ( info & rgxHasSubkeys) {
316 				int i;
317 				for ( i = ids[j].count - 1; i >= firstName; i--) {
318 					if ( prf_find( hk, buf, ids, i, result))
319 						return true;
320 				}
321 			}
322 			if (( info & rgxHasValues) == 0)
323 				return false;
324 			strcpy( result, buf);
325 			return true;
326 		}
327 	}
328 	return false;
329 }
330 
331 
332 Bool
apc_fetch_resource(const char * className,const char * name,const char * resClass,const char * resName,Handle owner,int resType,void * val)333 apc_fetch_resource( const char *className, const char *name,
334 						const char *resClass, const char *resName,
335 						Handle owner, int resType,
336 						void *val)
337 {
338 	Bool res = true;
339 	HKEY hKey;
340 	char buf[ MAXREGLEN];
341 	DWORD type, size, i;
342 	List ids[ 2];
343 
344 	i = 2; while( i--) list_create(&ids[i], 8, 8);
345 
346 	list_add(&ids[1], ( Handle) duplicate_string( name));
347 	list_add(&ids[0], ( Handle) duplicate_string( className));
348 
349 	while ( owner) {
350 		list_insert_at(&ids[1],   ( Handle) prima_normalize_resource_string(
351 			duplicate_string( PComponent( owner)-> name), false), 0);
352 		list_insert_at(&ids[0], ( Handle) prima_normalize_resource_string(
353 			duplicate_string(
354 				( owner == application) ? "Prima" : CComponent( owner)-> className
355 			), true), 0);
356 		owner = PComponent( owner)-> owner;
357 	}
358 
359 	if (!( res = prf_find( HKEY_CURRENT_USER, REG_STORAGE, ( List *) &ids, 0, buf)))
360 		goto FINALIZE;
361 
362 	if ( RegOpenKeyEx( HKEY_CURRENT_USER, buf, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
363 		res = false;
364 		goto FINALIZE;
365 	}
366 
367 	switch ( resType) {
368 	case frString:
369 		type = REG_SZ;
370 		size = MAXREGLEN;
371 		if ( RegQueryValueEx( hKey, resName, NULL,
372 			&type, ( LPBYTE) buf, &size) == ERROR_SUCCESS) {
373 			char **x = ( char **) val;
374 			*x = duplicate_string( buf);
375 		} else
376 		if ( RegQueryValueEx( hKey, resClass, NULL,
377 			&type, ( LPBYTE) buf, &size) == ERROR_SUCCESS) {
378 			char **x = ( char **) val;
379 			*x = duplicate_string( buf);
380 		} else
381 			res = false;
382 		break;
383 	case frFont:
384 		type = REG_SZ;
385 		size = MAXREGLEN;
386 		if ( RegQueryValueEx( hKey, resName, NULL,
387 			&type, ( LPBYTE) buf, &size) == ERROR_SUCCESS)
388 			font_pp2font( buf, ( Font *) val);
389 		else
390 		if ( RegQueryValueEx( hKey, resClass, NULL,
391 			&type, ( LPBYTE) buf, &size) == ERROR_SUCCESS)
392 			font_pp2font( buf, ( Font *) val);
393 		else
394 			res = false;
395 		break;
396 	case frColor:
397 		type = REG_DWORD;
398 		size = sizeof( DWORD);
399 		if ( RegQueryValueEx( hKey, resName, NULL,
400 			&type, ( LPBYTE) val, &size) != ERROR_SUCCESS)
401 			res = ( RegQueryValueEx( hKey, resClass, NULL,
402 			&type, ( LPBYTE) val, &size) == ERROR_SUCCESS);
403 		else
404 			res = false;
405 	}
406 
407 	RegCloseKey( hKey);
408 
409 FINALIZE:
410 
411 	i = 2;
412 	while( i--) {
413 		list_delete_all( &ids[i], true);
414 		list_destroy( &ids[i]);
415 	}
416 	return res;
417 }
418 
419 Bool
apc_dl_export(char * path)420 apc_dl_export(char *path)
421 {
422 	return LoadLibrary( path) != NULL;
423 }
424 
425 WCHAR *
alloc_utf8_to_wchar(const char * utf8,int length,int * mb_len)426 alloc_utf8_to_wchar( const char * utf8, int length, int * mb_len)
427 {
428 	WCHAR * ret;
429 	int size;
430 	char * u2 = (char*) utf8;
431 	if ( length > 0) {
432 		while ( length-- > 0 ) u2 = ( char*) utf8_hop(( U8*) u2, 1);
433 		length = u2 - utf8;
434 	}
435 	size = MultiByteToWideChar(CP_UTF8, 0, utf8, length, NULL, 0);
436 	if ( size < 0) {
437 		if ( mb_len ) *mb_len = 0;
438 		return NULL;
439 	}
440 	if ( !( ret = malloc( size * sizeof( WCHAR)))) return NULL;
441 	MultiByteToWideChar(CP_UTF8, 0, utf8, length, ret, size);
442 	if ( mb_len ) *mb_len = size;
443 	return ret;
444 }
445 
446 WCHAR *
alloc_utf8_to_wchar_visual(const char * utf8,int length,int * mb_len)447 alloc_utf8_to_wchar_visual( const char * utf8, int length, int * mb_len)
448 {
449 	WCHAR * ret;
450 	int i, size;
451 	char * u2 = (char*) utf8;
452 	if ( length > 0) {
453 		while ( length-- > 0 ) u2 = ( char*) utf8_hop(( U8*) u2, 1);
454 		length = u2 - utf8;
455 	}
456 	size = MultiByteToWideChar(CP_UTF8, 0, utf8, length, NULL, 0);
457 	if ( size < 0) {
458 		if ( mb_len ) *mb_len = 0;
459 		return NULL;
460 	}
461 	if ( !( ret = malloc((size + 1) * sizeof( WCHAR)))) return NULL;
462 /*
463 U+202A (LRE)	LEFT-TO-RIGHT EMBEDDING	Treats the following text as embedded left-to-right.
464 U+202B (RLE)	RIGHT-TO-LEFT EMBEDDING	Treats the following text as embedded right to left.
465 U+202D (LRO)	LEFT-TO-RIGHT OVERRIDE	Forces the following characters to be treated as strong left-to-right characters.
466 U+202E (RLO)	RIGHT-TO-LEFT OVERRIDE	Forces the following characters to be treated as strong right-to-left characters.
467 U+202C (PDF)	POP DIRECTIONAL FORMATTING CODE	Restores the bidirectional state to what it was before the last LRE, RLE, RLO, or LRO.
468 U+200E (LRM)	LEFT-TO-RIGHT MARK	Left-to-right strong zero-width character.
469 U+200F (RLM)	RIGHT-TO-LEFT MARK	Right-to-left strong zero-width character.
470 */
471 	ret[0] = 0x202D;
472 	MultiByteToWideChar(CP_UTF8, 0, utf8, length, ret + 1, size);
473 	for ( i = 1; i < size + 1; i++) {
474 		if (( ret[i] >= 0x202A && ret[i] <= 0x202E) || ret[i] == 0x200F )
475 			ret[i] = 0x200E;
476 	}
477 	if ( mb_len ) *mb_len = size + 1;
478 	return ret;
479 }
480 
481 void
wchar2char(char * dest,WCHAR * src,int lim)482 wchar2char( char * dest, WCHAR * src, int lim)
483 {
484 	if ( lim < 1) return;
485 	while ( lim-- && *src) *(dest++) = *((char*)src++);
486 	if ( lim < 0) dest--;
487 	*dest = 0;
488 }
489 
490 void
char2wchar(WCHAR * dest,char * src,int lim)491 char2wchar( WCHAR * dest, char * src, int lim)
492 {
493 	int l = strlen( src) + 1;
494 	if ( lim < 0) lim = l;
495 	if ( lim == 0) return;
496 	if ( lim > l) lim = l;
497 	src  += lim - 2;
498 	dest += lim - 1;
499 	*(dest--) = 0;
500 	while ( --lim) *(dest--) = *(src--);
501 }
502 
503 WCHAR *
alloc_ascii_to_wchar(const char * text,int length)504 alloc_ascii_to_wchar( const char * text, int length)
505 {
506 	WCHAR * ret;
507 	if ( text == NULL ) text = "";
508 	if ( length < 0) length = strlen( text) + 1;
509 	if ( !( ret = malloc( length * sizeof( WCHAR)))) return NULL;
510 	MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, text, length, ret, length * 2);
511 	return ret;
512 }
513 
514 #ifdef __cplusplus
515 }
516 #endif
517