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