1 /***********************************************************/
2 /* */
3 /* System dependent miscellaneous routines (unix, x11) */
4 /* */
5 /***********************************************************/
6
7 #include <apricot.h>
8 #include <sys/stat.h>
9 #include "unix/guts.h"
10 #include "Application.h"
11 #include "File.h"
12 #include "Icon.h"
13 #define XK_MISCELLANY
14 #include <X11/keysymdef.h>
15
16 /* Miscellaneous system-dependent functions */
17
18 #define X_COLOR_TO_RGB(xc) (ARGB(((xc).red>>8),((xc).green>>8),((xc).blue>>8)))
19 #define RANGE(a) { if ((a) < -16383) (a) = -16383; else if ((a) > 16383) a = 16383; }
20 #define RANGE2(a,b) RANGE(a) RANGE(b)
21
22 static XrmQuark
get_class_quark(const char * name)23 get_class_quark( const char *name)
24 {
25 XrmQuark quark;
26 char *s, *t;
27
28 t = s = prima_normalize_resource_string( duplicate_string( name), true);
29 if ( t && *t == 'P' && strncmp( t, "Prima__", 7) == 0)
30 s = t + 7;
31 if ( s && *s == 'A' && strcmp( s, "Application") == 0)
32 strcpy( s, "Prima"); /* we have enough space */
33 quark = XrmStringToQuark( s);
34 free( t);
35 return quark;
36 }
37
38 static XrmQuark
get_instance_quark(const char * name)39 get_instance_quark( const char *name)
40 {
41 XrmQuark quark;
42 char *s;
43
44 s = duplicate_string( name);
45 quark = XrmStringToQuark( prima_normalize_resource_string( s, false));
46 free( s);
47 return quark;
48 }
49
50 static Bool
update_quarks_cache(Handle self)51 update_quarks_cache( Handle self)
52 {
53 PComponent me = PComponent( self);
54 XrmQuark qClass, qInstance;
55 int n;
56 DEFXX;
57 PDrawableSysData UU;
58
59 if (!XX)
60 return false;
61
62 qClass = get_class_quark( self == application ? "Prima" : me-> self-> className);
63 qInstance = get_instance_quark( me-> name ? me-> name : "noname");
64
65 free( XX-> q_class_name); XX-> q_class_name = NULL;
66 free( XX-> q_instance_name); XX-> q_instance_name = NULL;
67
68 if ( me-> owner && me-> owner != self && PComponent(me-> owner)-> sysData && X(PComponent( me-> owner))-> q_class_name) {
69 UU = X(PComponent( me-> owner));
70 XX-> n_class_name = n = UU-> n_class_name + 1;
71 if (( XX-> q_class_name = malloc( sizeof( XrmQuark) * (n + 3))))
72 memcpy( XX-> q_class_name, UU-> q_class_name, sizeof( XrmQuark) * n);
73 XX-> q_class_name[n-1] = qClass;
74 XX-> n_instance_name = n = UU-> n_instance_name + 1;
75 if (( XX-> q_instance_name = malloc( sizeof( XrmQuark) * (n + 3))))
76 memcpy( XX-> q_instance_name, UU-> q_instance_name, sizeof( XrmQuark) * n);
77 XX-> q_instance_name[n-1] = qInstance;
78 } else {
79 XX-> n_class_name = n = 1;
80 if (( XX-> q_class_name = malloc( sizeof( XrmQuark) * (n + 3))))
81 XX-> q_class_name[n-1] = qClass;
82 XX-> n_instance_name = n = 1;
83 if (( XX-> q_instance_name = malloc( sizeof( XrmQuark) * (n + 3))))
84 XX-> q_instance_name[n-1] = qInstance;
85 }
86 return true;
87 }
88
89 int
unix_rm_get_int(Handle self,XrmQuark class_detail,XrmQuark name_detail,int default_value)90 unix_rm_get_int( Handle self, XrmQuark class_detail, XrmQuark name_detail, int default_value)
91 {
92 DEFXX;
93 XrmRepresentation type;
94 XrmValue value;
95 long int r;
96 char *end;
97
98 if ( XX && guts.db && XX-> q_class_name && XX-> q_instance_name) {
99 XX-> q_class_name[XX-> n_class_name] = class_detail;
100 XX-> q_class_name[XX-> n_class_name + 1] = 0;
101 XX-> q_instance_name[XX-> n_instance_name] = name_detail;
102 XX-> q_instance_name[XX-> n_instance_name + 1] = 0;
103 if ( XrmQGetResource( guts.db,
104 XX-> q_instance_name,
105 XX-> q_class_name,
106 &type, &value)) {
107 if ( type == guts.qString) {
108 r = strtol((char *)value. addr, &end, 0);
109 if (*(value. addr) && !*end)
110 return (int)r;
111 }
112 }
113 }
114 return default_value;
115 }
116
117 Bool
apc_fetch_resource(const char * className,const char * name,const char * resClass,const char * res,Handle owner,int resType,void * result)118 apc_fetch_resource( const char *className, const char *name,
119 const char *resClass, const char *res,
120 Handle owner, int resType,
121 void *result)
122 {
123 PDrawableSysData XX;
124 XrmQuark *classes, *instances, backup_classes[3], backup_instances[3];
125 XrmRepresentation type;
126 XrmValue value;
127 int nc, ni;
128 char *s;
129 XColor clr;
130
131 if ( owner == NULL_HANDLE) {
132 classes = backup_classes;
133 instances = backup_instances;
134 nc = ni = 0;
135 } else {
136 if (!update_quarks_cache( owner)) return false;
137 XX = X(owner);
138 if (!XX) return false;
139 classes = XX-> q_class_name;
140 instances = XX-> q_instance_name;
141 if ( classes == NULL || instances == NULL) return false;
142 nc = XX-> n_class_name;
143 ni = XX-> n_instance_name;
144 }
145 classes[nc++] = get_class_quark( className);
146 instances[ni++] = get_instance_quark( name);
147 classes[nc++] = get_class_quark( resClass);
148 instances[ni++] = get_instance_quark( res);
149 classes[nc] = 0;
150 instances[ni] = 0;
151
152 if (guts. debug & DEBUG_XRDB) {
153 int i;
154 _debug( "misc: inst: ");
155 for ( i = 0; i < ni; i++) {
156 _debug( "%s ", XrmQuarkToString( instances[i]));
157 }
158 _debug( "\nmisc: class: ");
159 for ( i = 0; i < nc; i++) {
160 _debug( "%s ", XrmQuarkToString( classes[i]));
161 }
162 _debug( "\n");
163 }
164
165 if ( XrmQGetResource( guts.db,
166 instances,
167 classes,
168 &type, &value)) {
169 if ( type == guts.qString) {
170 s = (char *)value.addr;
171 Xdebug("found %s\n", s);
172 switch ( resType) {
173 case frString:
174 *((char**)result) = duplicate_string( s);
175 break;
176 case frColor:
177 if (!XParseColor( DISP, DefaultColormap( DISP, SCREEN), s, &clr))
178 return false;
179 *((Color*)result) = X_COLOR_TO_RGB(clr);
180 Xdebug("color: %06x\n", *((Color*)result));
181 break;
182 case frFont:
183 prima_font_pp2font( s, ( Font *) result);
184 #define DEBUG_FONT(font) font.height,font.width,font.size,font.name,font.encoding
185 Xdebug("font: %d.[w=%d,s=%d].%s.%s\n", DEBUG_FONT((*(( Font *) result))));
186 break;
187 case frUnix_int:
188 *((int*)result) = atoi( s);
189 Xdebug("int: %d\n", *((int*)result));
190 break;
191 default:
192 return false;
193 }
194 return true;
195 }
196 }
197
198 return false;
199 }
200
201 Color
apc_lookup_color(const char * colorName)202 apc_lookup_color( const char * colorName)
203 {
204 char buf[ 256];
205 char *b;
206 int len;
207 XColor clr;
208
209 if ( DISP && XParseColor( DISP, DefaultColormap( DISP, SCREEN), colorName, &clr))
210 return X_COLOR_TO_RGB(clr);
211
212 #define xcmp( name, stlen, retval) if (( len == stlen) && ( strcmp( name, buf) == 0)) return retval
213
214 strncpy( buf, colorName, 255);
215 len = strlen( buf);
216 for ( b = buf; *b; b++) *b = tolower(*b);
217
218 switch( buf[0]) {
219 case 'a':
220 xcmp( "aqua", 4, 0x00FFFF);
221 xcmp( "azure", 5, ARGB(240,255,255));
222 break;
223 case 'b':
224 xcmp( "black", 5, 0x000000);
225 xcmp( "blanchedalmond", 14, ARGB( 255,235,205));
226 xcmp( "blue", 4, 0x000080);
227 xcmp( "brown", 5, 0x808000);
228 xcmp( "beige", 5, ARGB(245,245,220));
229 break;
230 case 'c':
231 xcmp( "cyan", 4, 0x008080);
232 xcmp( "chocolate", 9, ARGB(210,105,30));
233 break;
234 case 'd':
235 xcmp( "darkgray", 8, 0x404040);
236 break;
237 case 'e':
238 break;
239 case 'f':
240 xcmp( "fuchsia", 7, 0xFF00FF);
241 break;
242 case 'g':
243 xcmp( "green", 5, 0x008000);
244 xcmp( "gray", 4, 0x808080);
245 xcmp( "gray80", 6, ARGB(204,204,204));
246 xcmp( "gold", 4, ARGB(255,215,0));
247 break;
248 case 'h':
249 xcmp( "hotpink", 7, ARGB(255,105,180));
250 break;
251 case 'i':
252 xcmp( "ivory", 5, ARGB(255,255,240));
253 break;
254 case 'j':
255 break;
256 case 'k':
257 xcmp( "khaki", 5, ARGB(240,230,140));
258 break;
259 case 'l':
260 xcmp( "lime", 4, 0x00FF00);
261 xcmp( "lightgray", 9, 0xC0C0C0);
262 xcmp( "lightblue", 9, 0x0000FF);
263 xcmp( "lightgreen", 10, 0x00FF00);
264 xcmp( "lightcyan", 9, 0x00FFFF);
265 xcmp( "lightmagenta", 12, 0xFF00FF);
266 xcmp( "lightred", 8, 0xFF0000);
267 xcmp( "lemon", 5, ARGB(255,250,205));
268 break;
269 case 'm':
270 xcmp( "maroon", 6, 0x800000);
271 xcmp( "magenta", 7, 0x800080);
272 break;
273 case 'n':
274 xcmp( "navy", 4, 0x000080);
275 break;
276 case 'o':
277 xcmp( "olive", 5, 0x808000);
278 xcmp( "orange", 6, ARGB(255,165,0));
279 break;
280 case 'p':
281 xcmp( "purple", 6, 0x800080);
282 xcmp( "peach", 5, ARGB(255,218,185));
283 xcmp( "peru", 4, ARGB(205,133,63));
284 xcmp( "pink", 4, ARGB(255,192,203));
285 xcmp( "plum", 4, ARGB(221,160,221));
286 break;
287 case 'q':
288 break;
289 case 'r':
290 xcmp( "red", 3, 0x800000);
291 xcmp( "royalblue", 9, ARGB(65,105,225));
292 break;
293 case 's':
294 xcmp( "silver", 6, 0xC0C0C0);
295 xcmp( "sienna", 6, ARGB(160,82,45));
296 break;
297 case 't':
298 xcmp( "teal", 4, 0x008080);
299 xcmp( "turquoise", 9, ARGB(64,224,208));
300 xcmp( "tan", 3, ARGB(210,180,140));
301 xcmp( "tomato", 6, ARGB(255,99,71));
302 break;
303 case 'u':
304 break;
305 case 'w':
306 xcmp( "white", 5, 0xFFFFFF);
307 xcmp( "wheat", 5, ARGB(245,222,179));
308 break;
309 case 'v':
310 xcmp( "violet", 6, ARGB(238,130,238));
311 break;
312 case 'x':
313 break;
314 case 'y':
315 xcmp( "yellow", 6, 0xFFFF00);
316 break;
317 case 'z':
318 break;
319 }
320
321 #undef xcmp
322
323 return clInvalid;
324 }
325
326 /* Component-related functions */
327
328 Bool
apc_component_create(Handle self)329 apc_component_create( Handle self)
330 {
331 if ( !PComponent( self)-> sysData) {
332 if ( !( PComponent( self)-> sysData = malloc( sizeof( UnixSysData))))
333 return false;
334 bzero( PComponent( self)-> sysData, sizeof( UnixSysData));
335 ((PUnixSysData)(PComponent(self)->sysData))->component. self = self;
336 }
337 return true;
338 }
339
340 Bool
apc_component_destroy(Handle self)341 apc_component_destroy( Handle self)
342 {
343 DEFXX;
344 if ( XX-> q_instance_name) {
345 free( XX-> q_instance_name);
346 XX-> q_instance_name = NULL;
347 }
348 if ( XX-> q_class_name) {
349 free( XX-> q_class_name);
350 XX-> q_class_name = NULL;
351 }
352
353 free( PComponent( self)-> sysData);
354 PComponent( self)-> sysData = NULL;
355 X_WINDOW = NULL_HANDLE;
356 return true;
357 }
358
359 Bool
apc_component_fullname_changed_notify(Handle self)360 apc_component_fullname_changed_notify( Handle self)
361 {
362 Handle *list;
363 PComponent me = PComponent( self);
364 int i, n;
365
366 if ( self == NULL_HANDLE) return false;
367 if (!update_quarks_cache( self)) return false;
368
369 if ( me-> components && (n = me-> components-> count) > 0) {
370 if ( !( list = allocn( Handle, n))) return false;
371 memcpy( list, me-> components-> items, sizeof( Handle) * n);
372
373 for ( i = 0; i < n; i++) {
374 apc_component_fullname_changed_notify( list[i]);
375 }
376 free( list);
377 }
378
379 return true;
380 }
381
382 /* Cursor support */
383
384 void
prima_no_cursor(Handle self)385 prima_no_cursor( Handle self)
386 {
387 if ( self && guts.focused == self && X(self)
388 && !(XF_IN_PAINT(X(self)))
389 && X(self)-> flags. cursor_visible
390 && guts. cursor_save
391 && guts. cursor_shown)
392 {
393 DEFXX;
394 int x, y, w, h;
395
396 h = XX-> cursor_size. y;
397 y = XX-> size. y - (h + XX-> cursor_pos. y);
398 x = XX-> cursor_pos. x;
399 w = XX-> cursor_size. x;
400
401 prima_get_gc( XX);
402 XChangeGC( DISP, XX-> gc, VIRGIN_GC_MASK, &guts. cursor_gcv);
403 XCHECKPOINT;
404 XCopyArea( DISP, guts. cursor_save, XX-> udrawable, XX-> gc,
405 0, 0, w, h, x, y);
406 XFlush(DISP);
407 XCHECKPOINT;
408 prima_release_gc( XX);
409 guts. cursor_shown = false;
410 }
411 }
412
413 void
prima_update_cursor(Handle self)414 prima_update_cursor( Handle self)
415 {
416 if (
417 guts.focused == self
418 && !(XF_IN_PAINT(X(self)))
419 ) {
420 DEFXX;
421 int x, y, w, h;
422
423 h = XX-> cursor_size. y;
424 y = XX-> size. y - (h + XX-> cursor_pos. y);
425 x = XX-> cursor_pos. x;
426 w = XX-> cursor_size. x;
427
428 if ( !guts. cursor_save || !guts. cursor_xor
429 || w > guts. cursor_pixmap_size. x
430 || h > guts. cursor_pixmap_size. y ||
431 XX-> flags. layered != guts. cursor_layered
432 )
433 {
434 if ( !guts. cursor_save) {
435 guts. cursor_gcv. background = 0;
436 guts. cursor_gcv. foreground = 0xffffffff;
437 }
438 if ( guts. cursor_save) {
439 XFreePixmap( DISP, guts. cursor_save);
440 guts. cursor_save = 0;
441 }
442 if ( guts. cursor_xor) {
443 XFreePixmap( DISP, guts. cursor_xor);
444 guts. cursor_xor = 0;
445 }
446 if ( guts. cursor_pixmap_size. x < w)
447 guts. cursor_pixmap_size. x = w;
448 if ( guts. cursor_pixmap_size. y < h)
449 guts. cursor_pixmap_size. y = h;
450 if ( guts. cursor_pixmap_size. x < 16)
451 guts. cursor_pixmap_size. x = 16;
452 if ( guts. cursor_pixmap_size. y < 64)
453 guts. cursor_pixmap_size. y = 64;
454 guts. cursor_save = XCreatePixmap( DISP, XX-> udrawable,
455 guts. cursor_pixmap_size. x,
456 guts. cursor_pixmap_size. y,
457 XX-> visual-> depth);
458 guts. cursor_xor = XCreatePixmap( DISP, XX-> udrawable,
459 guts. cursor_pixmap_size. x,
460 guts. cursor_pixmap_size. y,
461 XX-> visual-> depth);
462 guts. cursor_layered = XX-> flags. layered;
463 }
464
465 prima_get_gc( XX);
466 XChangeGC( DISP, XX-> gc, VIRGIN_GC_MASK, &guts. cursor_gcv);
467 XCopyArea( DISP, XX-> udrawable, guts. cursor_save, XX-> gc,
468 x, y, w, h, 0, 0);
469 XCopyArea( DISP, guts. cursor_save, guts. cursor_xor, XX-> gc,
470 0, 0, w, h, 0, 0);
471 XSetFunction( DISP, XX-> gc, GXxor);
472 XFillRectangle( DISP, guts. cursor_xor, XX-> gc, 0, 0, w, h);
473 prima_release_gc( XX);
474 XCHECKPOINT;
475
476 if ( XX-> flags. cursor_visible) {
477 guts. cursor_shown = false;
478 prima_cursor_tick();
479 } else {
480 apc_timer_stop( CURSOR_TIMER);
481 }
482 }
483 }
484
485 void
prima_cursor_tick(void)486 prima_cursor_tick( void)
487 {
488 if (
489 guts. focused &&
490 X(guts. focused)-> flags. cursor_visible &&
491 !(XF_IN_PAINT(X(guts. focused)))
492 ) {
493 PDrawableSysData selfxx = X(guts. focused);
494 Pixmap pixmap;
495 int x, y, w, h;
496
497 if ( guts. cursor_shown) {
498 guts. cursor_shown = false;
499 apc_timer_set_timeout( CURSOR_TIMER, guts. invisible_timeout);
500 pixmap = guts. cursor_save;
501 } else {
502 guts. cursor_shown = true;
503 apc_timer_set_timeout( CURSOR_TIMER, guts. visible_timeout);
504 pixmap = guts. cursor_xor;
505 }
506
507 h = XX-> cursor_size. y;
508 y = XX-> size. y - (h + XX-> cursor_pos. y);
509 x = XX-> cursor_pos. x;
510 w = XX-> cursor_size. x;
511
512 prima_get_gc( XX);
513 XChangeGC( DISP, XX-> gc, VIRGIN_GC_MASK, &guts. cursor_gcv);
514 XCHECKPOINT;
515 XCopyArea( DISP, pixmap, XX-> udrawable, XX-> gc, 0, 0, w, h, x, y);
516 XCHECKPOINT;
517 prima_release_gc( XX);
518 XFlush( DISP);
519 XCHECKPOINT;
520 } else {
521 apc_timer_stop( CURSOR_TIMER);
522 guts. cursor_shown = !guts. cursor_shown;
523 }
524 }
525
526 Bool
apc_cursor_set_pos(Handle self,int x,int y)527 apc_cursor_set_pos( Handle self, int x, int y)
528 {
529 DEFXX;
530 prima_no_cursor( self);
531 RANGE2(x,y);
532 XX-> cursor_pos. x = x;
533 XX-> cursor_pos. y = y;
534 prima_update_cursor( self);
535 return true;
536 }
537
538 Bool
apc_cursor_set_size(Handle self,int x,int y)539 apc_cursor_set_size( Handle self, int x, int y)
540 {
541 DEFXX;
542 prima_no_cursor( self);
543 if ( x < 0) x = 1;
544 if ( y < 0) y = 1;
545 if ( x > 16383) x = 16383;
546 if ( y > 16383) y = 16383;
547 XX-> cursor_size. x = x;
548 XX-> cursor_size. y = y;
549 prima_update_cursor( self);
550 return true;
551 }
552
553 Bool
apc_cursor_set_visible(Handle self,Bool visible)554 apc_cursor_set_visible( Handle self, Bool visible)
555 {
556 DEFXX;
557 if ( XX-> flags. cursor_visible != visible) {
558 prima_no_cursor( self);
559 XX-> flags. cursor_visible = visible;
560 prima_update_cursor( self);
561 }
562 return true;
563 }
564
565 Point
apc_cursor_get_pos(Handle self)566 apc_cursor_get_pos( Handle self)
567 {
568 return X(self)-> cursor_pos;
569 }
570
571 Point
apc_cursor_get_size(Handle self)572 apc_cursor_get_size( Handle self)
573 {
574 return X(self)-> cursor_size;
575 }
576
577 Bool
apc_cursor_get_visible(Handle self)578 apc_cursor_get_visible( Handle self)
579 {
580 return X(self)-> flags. cursor_visible;
581 }
582
583 int
apc_pointer_get_state(Handle self)584 apc_pointer_get_state( Handle self)
585 {
586 XWindow foo;
587 int bar;
588 unsigned mask;
589 XQueryPointer( DISP, guts.root, &foo, &foo, &bar, &bar, &bar, &bar, &mask);
590 return
591 (( mask & Button1Mask) ? mb1 : 0) |
592 (( mask & Button2Mask) ? mb2 : 0) |
593 (( mask & Button3Mask) ? mb3 : 0) |
594 (( mask & Button4Mask) ? mb4 : 0) |
595 (( mask & Button5Mask) ? mb5 : 0) |
596 (( mask & Button6Mask) ? mb6 : 0) |
597 (( mask & Button7Mask) ? mb7 : 0);
598 }
599
600 int
apc_kbd_get_state(Handle self)601 apc_kbd_get_state( Handle self)
602 {
603 XWindow foo;
604 int bar;
605 unsigned int mask;
606 XQueryPointer( DISP, guts.root, &foo, &foo, &bar, &bar, &bar, &bar, &mask);
607 return
608 (( mask & ShiftMask) ? kmShift : 0) |
609 (( mask & ControlMask) ? kmCtrl : 0) |
610 (( mask & Mod1Mask) ? kmAlt : 0);
611 }
612
613 static void
close_msgdlg(struct MsgDlg * md)614 close_msgdlg( struct MsgDlg * md)
615 {
616 md-> active = false;
617 md-> pressed = false;
618 if ( md-> grab)
619 XUngrabPointer( DISP, CurrentTime);
620 md-> grab = false;
621 XUnmapWindow( DISP, md-> w);
622 XFlush( DISP);
623 if ( md-> next == NULL) {
624 XSetInputFocus( DISP, md-> focus, md-> focus_revertTo, CurrentTime);
625 XCHECKPOINT;
626 }
627 }
628
629 void
prima_msgdlg_event(XEvent * ev,struct MsgDlg * md)630 prima_msgdlg_event( XEvent * ev, struct MsgDlg * md)
631 {
632 XWindow w = ev-> xany. window;
633 switch ( ev-> type) {
634 case ConfigureNotify:
635 md-> winSz. x = ev-> xconfigure. width;
636 md-> winSz. y = ev-> xconfigure. height;
637 break;
638 case Expose:
639 {
640 int i, y = md-> textPos. y;
641 int d = md-> pressed ? 2 : 0;
642 XSetForeground( DISP, md-> gc, md-> bg. primary);
643 if ( md-> bg. balance > 0) {
644 Pixmap p = prima_get_hatch( &guts. ditherPatterns[ md-> bg. balance]);
645 if ( p) {
646 XSetStipple( DISP, md-> gc, p);
647 XSetFillStyle( DISP, md-> gc, FillOpaqueStippled);
648 XSetBackground( DISP, md-> gc, md-> bg. secondary);
649 }
650 }
651 XFillRectangle( DISP, w, md-> gc, 0, 0, md-> winSz.x, md-> winSz.y);
652 if ( md-> bg. balance > 0)
653 XSetFillStyle( DISP, md-> gc, FillSolid);
654 XSetForeground( DISP, md-> gc, md-> fg);
655 for ( i = 0; i < md-> wrappedCount; i++) {
656 if ( md-> wide)
657 XDrawString16( DISP, w, md-> gc,
658 ( md-> winSz.x - md-> widths[i]) / 2, y,
659 ( XChar2b*) md-> wrapped[i], md-> lengths[i]);
660 else
661 XDrawString( DISP, w, md-> gc,
662 ( md-> winSz.x - md-> widths[i]) / 2, y,
663 md-> wrapped[i], md-> lengths[i]);
664 y += md-> font-> height + md-> font-> externalLeading;
665 }
666 XDrawRectangle( DISP, w, md-> gc,
667 md-> btnPos.x-1, md-> btnPos.y-1, md-> btnSz.x+2, md-> btnSz.y+2);
668 XDrawString( DISP, w, md-> gc,
669 md-> btnPos.x + ( md-> btnSz.x - md-> OKwidth) / 2 + d,
670 md-> btnPos.y + md-> font-> height + md-> font-> externalLeading +
671 ( md-> btnSz.y - md-> font-> height - md-> font-> externalLeading) / 2 - 2 + d,
672 "OK", 2);
673 XSetForeground( DISP, md-> gc,
674 md-> pressed ? md-> d3d : md-> l3d);
675 XDrawLine( DISP, w, md-> gc,
676 md-> btnPos.x, md-> btnPos.y + md-> btnSz.y - 1,
677 md-> btnPos.x, md-> btnPos. y);
678 XDrawLine( DISP, w, md-> gc,
679 md-> btnPos.x + 1, md-> btnPos. y,
680 md-> btnPos.x + md-> btnSz.x - 1, md-> btnPos. y);
681 XSetForeground( DISP, md-> gc,
682 md-> pressed ? md-> l3d : md-> d3d);
683 XDrawLine( DISP, w, md-> gc,
684 md-> btnPos.x, md-> btnPos.y + md-> btnSz.y,
685 md-> btnPos.x + md-> btnSz.x, md-> btnPos.y + md-> btnSz.y);
686 XDrawLine( DISP, w, md-> gc,
687 md-> btnPos.x + md-> btnSz.x, md-> btnPos.y + md-> btnSz.y - 1,
688 md-> btnPos.x + md-> btnSz.x, md-> btnPos.y + 1);
689 }
690 break;
691 case ButtonPress:
692 if ( !md-> grab &&
693 ( ev-> xbutton. button == Button1) &&
694 ( ev-> xbutton. x >= md-> btnPos. x ) &&
695 ( ev-> xbutton. x < md-> btnPos. x + md-> btnSz.x) &&
696 ( ev-> xbutton. y >= md-> btnPos. y ) &&
697 ( ev-> xbutton. y < md-> btnPos. y + md-> btnSz.y)) {
698 md-> pressed = true;
699 md-> grab = true;
700 XClearArea( DISP, w, md-> btnPos.x, md-> btnPos.y,
701 md-> btnSz.x, md-> btnSz.y, true);
702 XGrabPointer( DISP, w, false,
703 ButtonReleaseMask | PointerMotionMask | ButtonMotionMask,
704 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
705 }
706 break;
707 case MotionNotify:
708 if ( md-> grab) {
709 Bool np =
710 (( ev-> xmotion. x >= md-> btnPos. x ) &&
711 ( ev-> xmotion. x < md-> btnPos. x + md-> btnSz.x) &&
712 ( ev-> xmotion. y >= md-> btnPos. y ) &&
713 ( ev-> xmotion. y < md-> btnPos. y + md-> btnSz.y));
714 if ( np != md-> pressed) {
715 md-> pressed = np;
716 XClearArea( DISP, w, md-> btnPos.x, md-> btnPos.y,
717 md-> btnSz.x, md-> btnSz.y, true);
718 }
719 }
720 break;
721 case KeyPress:
722 {
723 char str_buf[256];
724 KeySym keysym;
725 int str_len = XLookupString( &ev-> xkey, str_buf, 256, &keysym, NULL);
726 if (
727 ( keysym == XK_Return) ||
728 ( keysym == XK_Escape) ||
729 ( keysym == XK_KP_Enter) ||
730 ( keysym == XK_KP_Space) ||
731 (( str_len == 1) && ( str_buf[0] == ' '))
732 )
733 close_msgdlg( md);
734 }
735 break;
736 case ButtonRelease:
737 if ( md-> grab &&
738 ( ev-> xbutton. button == Button1)) {
739 md-> grab = false;
740 XUngrabPointer( DISP, CurrentTime);
741 if ( md-> pressed) close_msgdlg( md);
742 }
743 break;
744 case ClientMessage:
745 if (( ev-> xclient. message_type == WM_PROTOCOLS) &&
746 (( Atom) ev-> xclient. data. l[0] == WM_DELETE_WINDOW))
747 close_msgdlg( md);
748 break;
749 }
750 }
751
752 Bool
apc_show_message(const char * message,Bool utf8)753 apc_show_message( const char * message, Bool utf8)
754 {
755 int * wrapped;
756 Font f;
757 Point appSz, appPos;
758 Point textSz;
759 Point winSz;
760 TextWrapRec twr;
761 int i;
762 struct MsgDlg md, **storage;
763 Bool ret = false;
764 PList font_abc_unicode = NULL;
765 PFontABC font_abc_ascii = NULL;
766 XFontStruct *fs = NULL;
767
768 if ( !DISP) {
769 warn( "%s", message);
770 return true;
771 }
772
773 if ( guts. grab_widget)
774 apc_widget_set_capture( guts. grab_widget, 0, 0);
775
776 appSz = apc_application_get_size( NULL_HANDLE);
777 appPos.x = 0;
778 appPos.y = 0;
779
780 /* multi-monitor centering */
781 {
782 int i, nrects = 0;
783 Box *best = NULL, *rects = apc_application_get_monitor_rects( application, &nrects);
784 for ( i = 0; i < nrects; i++) {
785 Box * curr = rects + i;
786 if ( best == NULL || best-> x > curr->x || best->y > curr->y)
787 best = curr;
788 }
789 if ( best ) {
790 appPos.x = best->x;
791 appPos.y = best->y;
792 appSz.x = best->width;
793 appSz.y = best->height;
794 }
795 }
796
797 /* acquiring message font and wrapping message text */
798 {
799 PCachedFont cf;
800 int max;
801
802 apc_sys_get_msg_font( &f);
803 f. pitch = fpDefault;
804 #define DEBUG_FONT(font) font.height,font.width,font.size,font.name,font.encoding
805 prima_core_font_pick( NULL_HANDLE, &f, &f);
806 cf = prima_find_known_font( &f, false, false);
807 if ( !cf || !cf-> id) {
808 warn( "%s", message);
809 return false;
810 }
811 fs = XQueryFont( DISP, cf-> id);
812 if (!fs) {
813 warn( "%s", message);
814 return false;
815 }
816
817 twr. text = ( char *) message;
818 twr. utf8_text = utf8;
819 twr. textLen = strlen( message);
820 twr. utf8_textLen = utf8 ? prima_utf8_length( message, -1) : twr. textLen;
821 twr. width = appSz. x * 2 / 3;
822 twr. tabIndent = 3;
823 twr. options = twNewLineBreak | twWordBreak | twReturnLines;
824 twr. ascii = &font_abc_ascii;
825 twr. unicode = &font_abc_unicode;
826 twr. count = 0;
827 guts. font_abc_nil_hack = fs;
828 wrapped = CDrawable->do_text_wrap( NULL_HANDLE, &twr, NULL, NULL);
829
830 if ( font_abc_ascii) free( font_abc_ascii);
831 if ( font_abc_unicode) {
832 int i;
833 for ( i = 0; i < font_abc_unicode-> count; i += 2)
834 free(( void*) font_abc_unicode-> items[ i + 1]);
835 plist_destroy( font_abc_unicode);
836 }
837
838 md.wrappedCount = md.count = twr.count / 4;
839 if ( !( md.widths = malloc( md.count * sizeof(int))))
840 goto EXIT;
841 if ( !( md.lengths = malloc( md.count * sizeof(int))))
842 goto EXIT;
843 if ( !( md.wrapped = malloc( md.count * sizeof(char*))))
844 goto EXIT;
845 bzero(md.wrapped, md.count * sizeof(char*));
846
847 /* find text extensions */
848 max = 0;
849 for ( i = 0; i < md.count; i+=4) {
850 md.lengths[i] = wrapped[i+3];
851 if (utf8) {
852 if (!(md.wrapped[i] = (char*)prima_alloc_utf8_to_wchar( message + wrapped[i], md.lengths[i])))
853 goto EXIT;
854 md.widths[i] = XTextWidth16( fs, (XChar2b*) md.wrapped[i], md.lengths[i]);
855 } else {
856 if (!(md.wrapped[i] = malloc( md.lengths[i] + 1)))
857 goto EXIT;
858 memcpy(md.wrapped[i], message + wrapped[i], md.lengths[i]);
859 md.wrapped[i][md.lengths[i]] = 0;
860 md. widths[i] = XTextWidth( fs, md.wrapped[i], md.lengths[i]);
861 }
862 if ( md. widths[i] > max) max = md. widths[i];
863 }
864 textSz. x = max;
865 textSz. y = md.count * ( f. height + f. externalLeading);
866
867 md. font = &f;
868 md. fontId = cf-> id;
869 md. OKwidth = XTextWidth( fs, "OK", 2);
870 md. btnSz.x = md. OKwidth + 2 + 10;
871 if ( md. btnSz. x < 56) md. btnSz. x = 56;
872 md. btnSz.y = f. height + f. externalLeading + 2 + 12;
873
874 winSz. x = textSz. x + 4;
875 if ( winSz. x < md. btnSz. x + 2) winSz. x = md. btnSz.x + 2;
876 winSz. x += f. width * 4;
877 winSz. y = textSz. y + 2 + 12 + md. btnSz. y + f. height;
878 while ( winSz. y + 12 >= appSz.y) {
879 winSz. y -= f. height + f. externalLeading;
880 md. wrappedCount--;
881 }
882 md. btnPos. x = ( winSz. x - md. btnSz. x) / 2;
883 md. btnPos. y = winSz. y - 2 - md. btnSz. y - f. height / 2;
884 md. textPos. x = 2;
885 md. textPos. y = f. height * 3 / 2 + 2;
886 md. winSz = winSz;
887 }
888
889 md. wide = utf8;
890 md. active = true;
891 md. next = NULL;
892 md. pressed = false;
893 md. grab = false;
894 XGetInputFocus( DISP, &md. focus, &md. focus_revertTo);
895 XCHECKPOINT;
896 {
897 char * prima = "Prima";
898 XTextProperty p;
899 XSizeHints xs;
900 XSetWindowAttributes attrs;
901 Atom net_data[2];
902 attrs. event_mask = 0
903 | KeyPressMask
904 | ButtonPressMask
905 | ButtonReleaseMask
906 | ButtonMotionMask
907 | PointerMotionMask
908 | StructureNotifyMask
909 | ExposureMask;
910 attrs. override_redirect = false;
911 attrs. do_not_propagate_mask = attrs. event_mask;
912
913 md. w = XCreateWindow( DISP, guts. root,
914 appPos.x + ( appSz.x - winSz.x) / 2, appPos.y + ( appSz.y - winSz.y) / 2,
915 winSz.x, winSz.y, 0, CopyFromParent, InputOutput,
916 CopyFromParent, CWEventMask | CWOverrideRedirect, &attrs);
917 XCHECKPOINT;
918 if ( !md. w) goto EXIT;
919 XSetWMProtocols( DISP, md. w, &WM_DELETE_WINDOW, 1);
920 XCHECKPOINT;
921 xs. flags = PMinSize | PMaxSize | USPosition;
922 xs. min_width = xs. max_width = winSz.x;
923 xs. min_height = xs. max_height = winSz. y;
924 xs. x = appPos.x + ( appSz.x - winSz.x) / 2;
925 xs. y = appPos.y + ( appSz.y - winSz.y) / 2;
926 XSetWMNormalHints( DISP, md. w, &xs);
927 if ( XStringListToTextProperty( &prima, 1, &p) != 0) {
928 XSetWMIconName( DISP, md. w, &p);
929 XSetWMName( DISP, md. w, &p);
930 XFree( p. value);
931 }
932 net_data[0] = NET_WM_STATE_SKIP_TASKBAR;
933 net_data[1] = NET_WM_STATE_MODAL;
934 XChangeProperty( DISP, md. w, NET_WM_STATE, XA_ATOM, 32,
935 PropModeReplace, ( unsigned char *) net_data, 2);
936 }
937
938 storage = &guts. message_boxes;
939 while ( *storage) storage = &((*storage)-> next);
940 *storage = &md;
941
942 {
943 #define CLR(x) prima_allocate_color( NULL_HANDLE,prima_map_color(x,NULL),NULL)
944 XGCValues gcv;
945 gcv. font = md. fontId;
946 md. gc = XCreateGC( DISP, md. w, GCFont, &gcv);
947 md. fg = CLR(clFore | wcDialog);
948 prima_allocate_color( NULL_HANDLE, prima_map_color(clBack | wcDialog,NULL), &md. bg);
949 md. l3d = CLR(clLight3DColor | wcDialog);
950 md. d3d = CLR(clDark3DColor | wcDialog);
951 #undef CLR
952 }
953
954
955 XMapWindow( DISP, md. w);
956 XMoveResizeWindow( DISP, md. w,
957 appPos.x + ( appSz.x - winSz.x) / 2, appPos.y + ( appSz.y - winSz.y) / 2, winSz.x, winSz.y);
958 XNoOp( DISP);
959 while ( md. active && !guts. applicationClose) {
960 XFlush( DISP);
961 prima_one_loop_round( WAIT_ALWAYS, false);
962 }
963
964 XFreeGC( DISP, md. gc);
965 XDestroyWindow( DISP, md. w);
966 *storage = md. next;
967 ret = true;
968 EXIT:
969 XFreeFontInfo( NULL, fs, 1);
970 if ( md.widths ) free( md.widths);
971 if ( md.lengths) free( md.lengths);
972 if ( md.wrapped ) {
973 for ( i = 0; i < md.count; i++)
974 free(md.wrapped[i]);
975 free(md.wrapped);
976 }
977
978 return ret;
979 }
980
981 /* system metrics */
982
983 Bool
apc_sys_get_insert_mode(void)984 apc_sys_get_insert_mode( void)
985 {
986 return guts. insert;
987 }
988
989 PFont
apc_sys_get_msg_font(PFont f)990 apc_sys_get_msg_font( PFont f)
991 {
992 memcpy( f, &guts. default_msg_font, sizeof( Font));
993 return f;
994 }
995
996 PFont
apc_sys_get_caption_font(PFont f)997 apc_sys_get_caption_font( PFont f)
998 {
999 memcpy( f, &guts. default_caption_font, sizeof( Font));
1000 return f;
1001 }
1002
1003 static int
is_composite_display(void)1004 is_composite_display(void)
1005 {
1006 if ( guts. argb_visual. visual == NULL ) return false;
1007
1008 #ifndef HAVE_X11_EXTENSIONS_XCOMPOSITE_H
1009 return -1;
1010 #else
1011 /* try to become a compmgr */
1012 XCHECKPOINT;
1013 guts. composite_error_triggered = false;
1014 XCompositeRedirectSubwindows( DISP, guts.root, CompositeRedirectManual);
1015 XCHECKPOINT;
1016 XSync(DISP, false);
1017 if ( guts. composite_error_triggered )
1018 return true;
1019 XCompositeUnredirectSubwindows( DISP, guts.root, CompositeRedirectManual);
1020 XCHECKPOINT;
1021 XSync(DISP, false);
1022 if ( guts. composite_error_triggered )
1023 return true;
1024
1025 return false;
1026 #endif
1027 }
1028
1029 int
apc_sys_get_value(int v)1030 apc_sys_get_value( int v) /* XXX one big XXX */
1031 {
1032 switch ( v) {
1033 case svYMenu: {
1034 Font f;
1035 apc_menu_default_font( &f);
1036 return f. height + MENU_ITEM_GAP * 2;
1037 }
1038 case svYTitleBar: /* XXX */ return 20;
1039 case svMousePresent: return guts. mouse_buttons > 0;
1040 case svMouseButtons: return guts. mouse_buttons;
1041 case svSubmenuDelay: /* XXX ? */ return guts. menu_timeout;
1042 case svFullDrag: /* XXX ? */ return false;
1043 case svWheelPresent: return guts.mouse_wheel_up || guts.mouse_wheel_down;
1044 case svXIcon:
1045 case svYIcon:
1046 case svXSmallIcon:
1047 case svYSmallIcon:
1048 {
1049 int ret[4], n;
1050 XIconSize * sz = NULL;
1051 if ( XGetIconSizes( DISP, guts.root, &sz, &n) && ( n > 0) && (sz != NULL)) {
1052 ret[0] = sz-> max_width;
1053 ret[1] = sz-> max_height;
1054 ret[2] = sz-> min_width;
1055 ret[3] = sz-> min_height;
1056 } else {
1057 ret[0] = ret[1] = 64;
1058 ret[2] = ret[3] = 20;
1059 }
1060 if ( sz) XFree( sz);
1061 return ret[v - svXIcon];
1062 }
1063 break;
1064 case svXPointer: return guts. cursor_width;
1065 case svYPointer: return guts. cursor_height;
1066 case svXScrollbar: return 19;
1067 case svYScrollbar: return 19;
1068 case svXCursor: return 1;
1069 case svAutoScrollFirst: return guts. scroll_first;
1070 case svAutoScrollNext: return guts. scroll_next;
1071 case svXbsNone: return 0;
1072 case svYbsNone: return 0;
1073 case svXbsSizeable: return 3; /* XXX */
1074 case svYbsSizeable: return 3; /* XXX */
1075 case svXbsSingle: return 1; /* XXX */
1076 case svYbsSingle: return 1; /* XXX */
1077 case svXbsDialog: return 2; /* XXX */
1078 case svYbsDialog: return 2; /* XXX */
1079 case svShapeExtension: return guts. shape_extension;
1080 case svDblClickDelay: return guts. double_click_time_frame;
1081 case svColorPointer: return
1082 #ifdef HAVE_X11_XCURSOR_XCURSOR_H
1083 1
1084 #else
1085 0
1086 #endif
1087 ;
1088 case svCanUTF8_Input: return 1;
1089 case svCanUTF8_Output: return 1;
1090 case svCompositeDisplay: return is_composite_display();
1091 case svLayeredWidgets: return guts. argb_visual. visual != NULL;
1092 case svFixedPointerSize: return
1093 #ifdef HAVE_X11_XCURSOR_XCURSOR_H
1094 0
1095 #else
1096 1
1097 #endif
1098 ;
1099 case svMenuCheckSize : return MENU_CHECK_XOFFSET;
1100 case svFriBidi : return use_fribidi;
1101 case svAntialias : return guts. argb_visual. visual != NULL;
1102 default:
1103 return -1;
1104 }
1105 }
1106
1107 Bool
apc_sys_set_insert_mode(Bool insMode)1108 apc_sys_set_insert_mode( Bool insMode)
1109 {
1110 guts. insert = !!insMode;
1111 return true;
1112 }
1113
1114 /* etc */
1115
1116 Bool
apc_beep(int style)1117 apc_beep( int style)
1118 {
1119 /* XXX - mbError, mbQuestion, mbInformation, mbWarning */
1120 if ( DISP)
1121 XBell( DISP, 0);
1122 return true;
1123 }
1124
1125 Bool
apc_beep_tone(int freq,int duration)1126 apc_beep_tone( int freq, int duration)
1127 {
1128 XKeyboardControl xkc;
1129 XKeyboardState xks;
1130 struct timeval timeout;
1131
1132 if ( !DISP) return false;
1133
1134 XGetKeyboardControl( DISP, &xks);
1135 xkc. bell_pitch = freq;
1136 xkc. bell_duration = duration;
1137 XChangeKeyboardControl( DISP, KBBellPitch | KBBellDuration, &xkc);
1138
1139 XBell( DISP, 100);
1140 XFlush( DISP);
1141
1142 xkc. bell_pitch = xks. bell_pitch;
1143 xkc. bell_duration = xks. bell_duration;
1144 XChangeKeyboardControl( DISP, KBBellPitch | KBBellDuration, &xkc);
1145
1146 timeout. tv_sec = duration / 1000;
1147 timeout. tv_usec = 1000 * (duration % 1000);
1148 select( 0, NULL, NULL, NULL, &timeout);
1149
1150 return true;
1151 }
1152
1153 char *
apc_system_action(const char * s)1154 apc_system_action( const char *s)
1155 {
1156 int l = strlen( s);
1157 switch (*s) {
1158 case 'b':
1159 if ( l == 7 && strcmp( s, "browser") == 0)
1160 return duplicate_string("netscape");
1161 break;
1162 case 'c':
1163 if ( l == 19 && strcmp( s, "can.shape.extension") == 0 && guts.shape_extension)
1164 return duplicate_string( "yes");
1165 else if ( l == 26 && strcmp( s, "can.shared.image.extension") == 0 && guts.shared_image_extension)
1166 return duplicate_string( "yes");
1167 break;
1168 case 'D':
1169 if ( l == 7 && ( strcmp( s, "Display") == 0)) {
1170 char * c = malloc(19);
1171 if ( c) snprintf( c, 18, "0x%p", DISP);
1172 return c;
1173 }
1174 break;
1175 case 'g':
1176 if ( l > 15 && strncmp( "get.frame.info ", s, 15) == 0) {
1177 char *end;
1178 XWindow w = strtoul( s + 15, &end, 0);
1179 Handle self;
1180 Rect r;
1181 char buf[ 80];
1182
1183 if (*end == '\0' &&
1184 ( self = prima_xw2h( w)) &&
1185 prima_get_frame_info( self, &r) &&
1186 snprintf( buf, sizeof(buf), "%d %d %d %d", r.left, r.bottom, r.right, r.top) < sizeof(buf))
1187 return duplicate_string( buf);
1188 return duplicate_string("");
1189 } else if ( strncmp( s, "gtk.OpenFile.", 13) == 0) {
1190 s += 13;
1191 #ifdef WITH_GTK
1192 if ( guts. use_gtk )
1193 return prima_gtk_openfile(( char*) s);
1194 #endif
1195 return NULL;
1196 }
1197 break;
1198 case 'r':
1199 if ( strncmp( s, "resolution", 10) == 0) {
1200 int dx, dy;
1201 int i = sscanf( s + 10, "%u %u", &dx, &dy);
1202 if ( i != 2 || (dx < 1 || dy < 1)) {
1203 warn("Bad resolution\n");
1204 return 0;
1205 }
1206 guts. resolution. x = dx;
1207 guts. resolution. y = dy;
1208 return NULL;
1209 }
1210 break;
1211 case 's':
1212 if ( strcmp( "synchronize", s) == 0) {
1213 XSynchronize( DISP, true);
1214 return NULL;
1215 }
1216 if ( strncmp( "setfont ", s, 8) == 0) {
1217 Handle self = NULL_HANDLE;
1218 char font[1024];
1219 XWindow win;
1220 int i = sscanf( s + 8, "%lu %s", &win, font);
1221 if ( i != 2 || !(self = prima_xw2h( win))) {
1222 warn( "Bad parameters to sysaction setfont");
1223 return 0;
1224 }
1225 if ( !opt_InPaint) return 0;
1226 XSetFont( DISP, X(self)-> gc, XLoadFont( DISP, font));
1227 return NULL;
1228 }
1229 if ( strcmp( "shaper", s) == 0) {
1230 char shaper[64] = "";
1231 #ifdef USE_XFT
1232 if ( guts. use_xft ) strcat(shaper, "xft ");
1233 #endif
1234 #ifdef WITH_HARFBUZZ
1235 if ( guts. use_harfbuzz ) strcat(shaper, "harfbuzz ");
1236 #endif
1237 shaper[strlen(shaper)-1] = 0;
1238 return duplicate_string(shaper);
1239 }
1240 break;
1241 case 't':
1242 if ( strncmp( "textout16 ", s, 10) == 0) {
1243 Handle self = NULL_HANDLE;
1244 unsigned char text[1024];
1245 XWindow win;
1246 int x, y, len;
1247 int i = sscanf( s + 10, "%lu %d %d %s", &win, &x, &y, text);
1248 if ( i != 4 || !(self = prima_xw2h( win))) {
1249 warn( "Bad parameters to sysaction textout16");
1250 return 0;
1251 }
1252 if ( !opt_InPaint) return 0;
1253 len = strlen((char*) text);
1254 for ( i = 0; i < len; i++) if ( text[i]==255) text[i] = 0;
1255 XDrawString16( DISP, win, X(self)-> gc, x, y, ( XChar2b *) text, len / 2);
1256 return NULL;
1257 }
1258 break;
1259 case 'u':
1260 if ( strcmp( s, "unix_guts") == 0)
1261 return (char*) &guts;
1262 break;
1263 case 'x':
1264 if ( strncmp(s, "xquartz.", 8) == 0) {
1265 s += 8;
1266 #ifdef WITH_COCOA
1267 if ( guts. use_quartz )
1268 return prima_cocoa_system_action(( char*) s);
1269 #endif
1270 return NULL;
1271 }
1272 break;
1273 case 'X':
1274 if ( strcmp( s, "XOpenDisplay") == 0) {
1275 char err_buf[512];
1276 if ( DISP)
1277 return duplicate_string( "X display already opened");
1278 window_subsystem_set_option( "yes-x11", NULL);
1279 if ( !window_subsystem_init( err_buf))
1280 return duplicate_string( err_buf);
1281 return NULL;
1282 }
1283 break;
1284 }
1285 warn("Unknown sysaction:%s", s);
1286 return NULL;
1287 }
1288
1289 Bool
apc_query_drives_map(const char * firstDrive,char * result,int len)1290 apc_query_drives_map( const char* firstDrive, char *result, int len)
1291 {
1292 if ( !result || len <= 0) return true;
1293 *result = 0;
1294 return true;
1295 }
1296
1297 int
apc_query_drive_type(const char * drive)1298 apc_query_drive_type( const char *drive)
1299 {
1300 return dtNone;
1301 }
1302
1303 char *
apc_get_user_name(void)1304 apc_get_user_name( void)
1305 {
1306 char * c = getlogin();
1307 return c ? c : "";
1308 }
1309
1310 Bool
apc_dl_export(char * path)1311 apc_dl_export(char *path)
1312 {
1313 /* XXX */
1314 return true;
1315 }
1316
1317 void
prima_rect_union(XRectangle * t,const XRectangle * s)1318 prima_rect_union( XRectangle *t, const XRectangle *s)
1319 {
1320 XRectangle r;
1321
1322 if ( t-> x < s-> x) r. x = t-> x; else r. x = s-> x;
1323 if ( t-> y < s-> y) r. y = t-> y; else r. y = s-> y;
1324 if ( t-> x + t-> width > s-> x + s-> width)
1325 r. width = t-> x + t-> width - r. x;
1326 else
1327 r. width = s-> x + s-> width - r. x;
1328 if ( t-> y + t-> height > s-> y + s-> height)
1329 r. height = t-> y + t-> height - r. y;
1330 else
1331 r. height = s-> y + s-> height - r. y;
1332 *t = r;
1333 }
1334
1335 void
prima_rect_intersect(XRectangle * t,const XRectangle * s)1336 prima_rect_intersect( XRectangle *t, const XRectangle *s)
1337 {
1338 XRectangle r;
1339 int w, h;
1340
1341 if ( t-> x > s-> x) r. x = t-> x; else r. x = s-> x;
1342 if ( t-> y > s-> y) r. y = t-> y; else r. y = s-> y;
1343 if ( t-> x + t-> width < s-> x + s-> width)
1344 w = t-> x + (int)t-> width - r. x;
1345 else
1346 w = s-> x + (int)s-> width - r. x;
1347 if ( t-> y + t-> height < s-> y + s-> height)
1348 h = t-> y + (int)t-> height - r. y;
1349 else
1350 h = s-> y + (int)s-> height - r. y;
1351 if ( w < 0 || h < 0) {
1352 r. x = 0; r. y = 0; r. width = 0; r. height = 0;
1353 } else {
1354 r. width = w; r. height = h;
1355 }
1356 *t = r;
1357 }
1358
1359
1360 void
prima_utf8_to_wchar(const char * utf8,XChar2b * u16,int src_len_bytes,int target_len_xchars)1361 prima_utf8_to_wchar( const char * utf8, XChar2b * u16, int src_len_bytes, int target_len_xchars )
1362 {
1363 STRLEN charlen;
1364 while ( target_len_xchars--) {
1365 register UV u = prima_utf8_uvchr(utf8, src_len_bytes, &charlen);
1366 if ( u < 0x10000) {
1367 u16-> byte1 = u >> 8;
1368 u16-> byte2 = u & 0xff;
1369 } else
1370 u16-> byte1 = u16-> byte2 = 0xff;
1371 u16++;
1372 utf8 += charlen;
1373 src_len_bytes -= charlen;
1374 if ( src_len_bytes <= 0 || charlen == 0) break;
1375 }
1376 }
1377
1378 XChar2b *
prima_alloc_utf8_to_wchar(const char * utf8,int length_chars)1379 prima_alloc_utf8_to_wchar( const char * utf8, int length_chars)
1380 {
1381 XChar2b * ret;
1382 if ( length_chars < 0) length_chars = prima_utf8_length( utf8, -1) + 1;
1383 if ( !( ret = malloc( length_chars * sizeof( XChar2b)))) return NULL;
1384 prima_utf8_to_wchar( utf8, ret, strlen(utf8), length_chars);
1385 return ret;
1386 }
1387
1388 void
prima_wchar2char(char * dest,XChar2b * src,int lim)1389 prima_wchar2char( char * dest, XChar2b * src, int lim)
1390 {
1391 if ( lim < 1) return;
1392 while ( lim-- && src-> byte1 && src-> byte2) *(dest++) = (src++)-> byte2;
1393 if ( lim < 0) dest--;
1394 *dest = 0;
1395 }
1396
1397 void
prima_char2wchar(XChar2b * dest,char * src,int lim)1398 prima_char2wchar( XChar2b * dest, char * src, int lim)
1399 {
1400 int l = strlen( src) + 1;
1401 if ( lim < 1) return;
1402 if ( lim > l) lim = l;
1403 src += lim - 2;
1404 dest += lim - 1;
1405 dest-> byte1 = dest-> byte2 = 0;
1406 dest--;
1407 while ( lim--) {
1408 dest-> byte2 = *(src--);
1409 dest-> byte1 = 0;
1410 dest--;
1411 }
1412 }
1413
1414 /* printer stubs */
1415
apc_prn_create(Handle self)1416 Bool apc_prn_create( Handle self) { return false; }
apc_prn_destroy(Handle self)1417 Bool apc_prn_destroy( Handle self) { return true; }
apc_prn_select(Handle self,const char * printer)1418 Bool apc_prn_select( Handle self, const char* printer) { return false; }
apc_prn_get_selected(Handle self)1419 char * apc_prn_get_selected( Handle self) { return NULL; }
apc_prn_get_size(Handle self)1420 Point apc_prn_get_size( Handle self) { Point r = {0,0}; return r; }
apc_prn_get_resolution(Handle self)1421 Point apc_prn_get_resolution( Handle self) { Point r = {0,0}; return r; }
apc_prn_get_default(Handle self)1422 char * apc_prn_get_default( Handle self) { return NULL; }
apc_prn_setup(Handle self)1423 Bool apc_prn_setup( Handle self) { return false; }
apc_prn_begin_doc(Handle self,const char * docName)1424 Bool apc_prn_begin_doc( Handle self, const char* docName) { return false; }
apc_prn_begin_paint_info(Handle self)1425 Bool apc_prn_begin_paint_info( Handle self) { return false; }
apc_prn_end_doc(Handle self)1426 Bool apc_prn_end_doc( Handle self) { return true; }
apc_prn_end_paint_info(Handle self)1427 Bool apc_prn_end_paint_info( Handle self) { return true; }
apc_prn_new_page(Handle self)1428 Bool apc_prn_new_page( Handle self) { return true; }
apc_prn_abort_doc(Handle self)1429 Bool apc_prn_abort_doc( Handle self) { return true; }
apc_prn_get_handle(Handle self)1430 ApiHandle apc_prn_get_handle( Handle self) { return ( ApiHandle) 0; }
apc_prn_set_option(Handle self,char * option,char * value)1431 Bool apc_prn_set_option( Handle self, char * option, char * value) { return false; }
1432
apc_prn_get_option(Handle self,char * option,char ** value)1433 Bool apc_prn_get_option( Handle self, char * option, char ** value)
1434 {
1435 *value = NULL;
1436 return false;
1437 }
1438
apc_prn_enum_options(Handle self,int * count,char *** options)1439 Bool apc_prn_enum_options( Handle self, int * count, char *** options)
1440 {
1441 *count = 0;
1442 return false;
1443 }
1444
1445 PrinterInfo *
apc_prn_enumerate(Handle self,int * count)1446 apc_prn_enumerate( Handle self, int * count)
1447 {
1448 *count = 0;
1449 return NULL;
1450 }
1451
1452 char *
apc_last_error(void)1453 apc_last_error( void )
1454 {
1455 return NULL;
1456 }
1457
1458