1 /*
2 * xutil.c
3 *
4 * Utilities for detailing with X
5 *
6 * (C) 1997 Randall Hopper
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 /* ******************** Include Files ************** */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <assert.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <signal.h>
41 #include <X11/Xlib.h>
42 #include <X11/Intrinsic.h>
43 #include <X11/StringDefs.h>
44 #include <X11/Shell.h>
45 #include <X11/Xaw/Dialog.h>
46 #include <X11/xpm.h>
47 #include "tvdefines.h"
48 #include "xutil.h"
49 #include "app_rsrc.h"
50
51 /* NOTE: Do NOT include Scrollbar.h. This incorrectly defines */
52 /* the arguments of XawScrolbarSetThumb to be doubles, not floats. */
53 /*#include <X11/Xaw/Scrollbar.h>*/
54 void XawScrollbarSetThumb( Widget w, float top, float shown );
55
56 /* ******************** Local defines ************** */
57
58 #ifndef FXTV_LIBDIR
59 # define FXTV_LIBDIR X11BASE "/lib/X11/fxtv/%T/%N"
60 #endif
61
62 #define RUNCMD_CHECK_TIMEOUT_MS 200
63
64 #define WM_BORDER_PAD 40
65
66 typedef struct {
67 pid_t cmd_pid;
68 TVUTIL_PIPE_END end[3];
69 XtAppContext app_context;
70 XUTIL_RUNCMD_CANCELCB *cancel_cb;
71 void *cancel_cb_data;
72 XUTIL_RUNCMD_DONECB *done_cb;
73 void *done_cb_data;
74 } XUTIL_RUNCMD_STATE;
75
76
77 #define XLFD_SIZE_FOUNDRY 128
78 #define XLFD_SIZE_FAMILY 128
79 #define XLFD_SIZE_SMALL 30
80
81 typedef struct {
82 char foundry [ XLFD_SIZE_FOUNDRY ];
83 char family [ XLFD_SIZE_FAMILY ];
84 char weight [ XLFD_SIZE_SMALL ];
85 char slant [ XLFD_SIZE_SMALL ];
86 char set_width [ XLFD_SIZE_SMALL ];
87 char ad_style [ XLFD_SIZE_SMALL ];
88 char pixel_size [ XLFD_SIZE_SMALL ];
89 char point_size [ XLFD_SIZE_SMALL ];
90 char x_dpi [ XLFD_SIZE_SMALL ];
91 char y_dpi [ XLFD_SIZE_SMALL ];
92 char spacing [ XLFD_SIZE_SMALL ];
93 char avg_width [ XLFD_SIZE_SMALL ];
94 char charset_reg[ XLFD_SIZE_SMALL ];
95 char charset_enc[ XLFD_SIZE_SMALL ];
96 } TV_XLFD;
97
98 /* ******************** Private variables ************** */
99
100 static Atom S_wm_delete_window;
101
102 #ifdef THE_ACTUAL_ASCII_TEXT_TRANSLATIONS
103
104 char G_transl_ascii_text[] = "\
105 Ctrl<Key>A: beginning-of-line()\n\
106 Ctrl<Key>B: backward-character() \n\
107 Ctrl<Key>D: delete-next-character() \n\
108 Ctrl<Key>E: end-of-line() \n\
109 Ctrl<Key>F: forward-character() \n\
110 Ctrl<Key>G: multiply(Reset) \n\
111 Ctrl<Key>H: delete-previous-character() \n\
112 Ctrl<Key>J: newline-and-indent() \n\
113 Ctrl<Key>K: kill-to-end-of-line() \n\
114 Ctrl<Key>L: redraw-display() \n\
115 Ctrl<Key>M: newline() \n\
116 Ctrl<Key>N: next-line() \n\
117 Ctrl<Key>O: newline-and-backup() \n\
118 Ctrl<Key>P: previous-line() \n\
119 Ctrl<Key>R: search(backward) \n\
120 Ctrl<Key>S: search(forward) \n\
121 Ctrl<Key>T: transpose-characters() \n\
122 Ctrl<Key>U: multiply(4) \n\
123 Ctrl<Key>V: next-page() \n\
124 Ctrl<Key>W: kill-selection() \n\
125 Ctrl<Key>Y: insert-selection(CUT_BUFFER1) \n\
126 Ctrl<Key>Z: scroll-one-line-up() \n\
127 Ctrl<Key>\\\\: reconnect-im() \n\
128 Meta<Key>B: backward-word() \n\
129 Meta<Key>F: forward-word() \n\
130 Meta<Key>I: insert-file() \n\
131 Meta<Key>K: kill-to-end-of-paragraph() \n\
132 Meta<Key>Q: form-paragraph() \n\
133 Meta<Key>V: previous-page() \n\
134 Meta<Key>Y: insert-selection(PRIMARY, CUT_BUFFER0) \n\
135 Meta<Key>Z: scroll-one-line-down() \n\
136 Meta<Key>d: delete-next-word() \n\
137 Meta<Key>D: kill-word() \n\
138 Meta<Key>h: delete-previous-word() \n\
139 Meta<Key>H: backward-kill-word() \n\
140 Meta<Key>\\<: beginning-of-file() \n\
141 Meta<Key>\\>: end-of-file() \n\
142 Meta<Key>]: forward-paragraph() \n\
143 Meta<Key>[: backward-paragraph() \n\
144 ~Shift Meta<Key>Delete: delete-previous-word() \n\
145 Shift Meta<Key>Delete: backward-kill-word() \n\
146 ~Shift Meta<Key>BackSpace: delete-previous-word() \n\
147 Shift Meta<Key>BackSpace: backward-kill-word() \n\
148 <Key>Right: forward-character() \n\
149 <Key>Left: backward-character() \n\
150 <Key>Down: next-line() \n\
151 <Key>Up: previous-line() \n\
152 <Key>Delete: delete-previous-character() \n\
153 <Key>BackSpace: delete-previous-character() \n\
154 <Key>Linefeed: newline-and-indent() \n\
155 <Key>Return: newline() \n\
156 <Key>: insert-char() \n\
157 <Key>Kanji: reconnect-im() \n\
158 <FocusIn>: focus-in() \n\
159 <FocusOut>: focus-out() \n\
160 <Btn1Down>: select-start() \n\
161 <Btn1Motion>: extend-adjust() \n\
162 <Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0) \n\
163 <Btn2Down>: insert-selection(PRIMARY, CUT_BUFFER0) \n\
164 <Btn3Down>: extend-start() \n\
165 <Btn3Motion>: extend-adjust() \n\
166 <Btn3Up>: extend-end(PRIMARY, CUT_BUFFER0) \n\
167 ";
168
169 #endif
170
171 char G_transl_ovr_ascii_text[] = "\
172 <Enter>: display-caret(on) \n\
173 <Leave>: display-caret(off) \n\
174 ";
175
176 char G_transl_ovr_ascii_text_1line[] = "\
177 <Key>Return: no-op()\n\
178 <Key>KP_Enter: no-op()\n\
179 <Key>Down: no-op()\n\
180 <Key>Up: no-op()\n\
181 <Key>Linefeed: no-op()\n\
182 Ctrl<Key>J: no-op()\n\
183 Ctrl<Key>M: no-op()\n\
184 Ctrl<Key>N: no-op()\n\
185 Ctrl<Key>O: no-op()\n\
186 Ctrl<Key>P: no-op()\n\
187 Ctrl<Key>R: no-op()\n\
188 Ctrl<Key>S: no-op()\n\
189 Ctrl<Key>V: no-op()\n\
190 Ctrl<Key>Z: no-op()\n\
191 Meta<Key>V: no-op()\n\
192 Meta<Key>Z: no-op()\n\
193 ";
194
195 /* ******************** Forward declarations ************** */
196
197 /* ******************** Function Definitions ************** */
198
199
200 /**@BEGINFUNC**************************************************************
201
202 Prototype : TV_BOOL XUTILBitmapLoad(
203 char *bitmap_file,
204 Widget wgt,
205 Pixmap *pixmap )
206
207 Purpose : Loads a bitmap (xbm) of depth 1.
208
209 Programmer : 16-Mar-97 Randall Hopper
210
211 Parameters : bitmap_file - I: filename of bitmap file
212 wgt - I: widget bitmap will be used on
213 pixmap - O: pixmap loaded (depth 1)
214
215 Returns : T = Success; F = Failure
216
217 Globals : None.
218
219 **@ENDFUNC*****************************************************************/
220
XUTILBitmapLoad(char * bitmap_file,Widget wgt,Pixmap * pixmap)221 TV_BOOL XUTILBitmapLoad( char *bitmap_file,
222 Widget wgt,
223 Pixmap *pixmap )
224 {
225 char *pixmap_path = NULL;
226 unsigned width,
227 height;
228 int x_hot,
229 y_hot;
230
231 /********************************************/
232 /* Look for the pixmap file in FXTV_LIBDIR */
233 /********************************************/
234
235 pixmap_path = XtResolvePathname( XtDisplay(wgt), "bitmaps", bitmap_file,
236 NULL, FXTV_LIBDIR, NULL, 0, NULL);
237
238 if ( pixmap_path == NULL ) {
239 fprintf( stderr, "Failed to find bitmap '%s'\n", bitmap_file );
240 return False;
241 }
242
243 if ( XReadBitmapFile( XtDisplay(wgt),
244 RootWindowOfScreen( XtScreen( wgt ) ),
245 pixmap_path, &width, &height, pixmap,
246 &x_hot, &y_hot ) != BitmapSuccess ) {
247 fprintf( stderr, "Failed to load bitmap '%s'\n", pixmap_path );
248 if ( pixmap_path != NULL )
249 XtFree( pixmap_path );
250 return False;
251 }
252
253 XtFree( pixmap_path );
254 return True;
255 }
256
257
258 /**@BEGINFUNC**************************************************************
259
260 Prototype : TV_BOOL XUTILPixmapLoad(
261 char *pixmap_file,
262 Widget wgt,
263 Pixel fg_color,
264 Pixel bg_color,
265 Pixmap *pixmap,
266 Pixmap *pixmap_mask )
267
268 Purpose : Loads the specified pixmap file (.xbm or .xpm) for the
269 purpose of future use with the specified widget.
270
271 For pixmaps, transparency is resolved with the specified
272 background color.
273 For bitmaps, fg_color and bg_color are used directly to
274 determine the colors of the on and off pixels in the
275 pixmap.
276
277 On success, the resulting pixmap (and pixmap mask, if is
278 pixmap file AND mask is present AND pixmap_mask != NULL)
279 is/are returned.
280
281 Free these pixmaps using XFreePixmap.
282
283 NOTE: The default X colormap is used for color matching.
284
285 Programmer : 02-Mar-1997 Randall Hopper
286
287 Parameters : pixmap_file - I: filename base for pixmap file
288 wgt - I: widget pixmap will be associated with
289 fg_color - I: foreground color
290 bg_color - I: background color
291 pixmap - O: returned pixmap (input can't be NULL)
292 pixmap_mask - O: returned pixmap mask (input can be NULL)
293
294 Returns : T = Success; F = Failure
295
296 Globals : None.
297
298 **@ENDFUNC*****************************************************************/
299
XUTILPixmapLoad(char * pixmap_file,Widget wgt,Pixel fg_color,Pixel bg_color,Pixmap * pixmap,Pixmap * pixmap_mask)300 TV_BOOL XUTILPixmapLoad( char *pixmap_file,
301 Widget wgt,
302 Pixel fg_color,
303 Pixel bg_color,
304 Pixmap *pixmap,
305 Pixmap *pixmap_mask )
306 {
307 XpmAttributes xpmatts;
308 XpmColorSymbol XpmTransparentColor[1] = { { NULL, "none", 0 } };
309 int xpm_status,
310 color_depth,
311 x_hot,
312 y_hot;
313 Pixmap pix_returned,
314 pix_mask_returned,
315 pixmap_depth1;
316 Colormap colormap;
317 char *pixmap_path = NULL;
318 unsigned int width,
319 height;
320 XGCValues gcv;
321 GC gc;
322
323 if ( pixmap == NULL )
324 return False;
325
326 /********************************************/
327 /* Look for the pixmap file in FXTV_LIBDIR */
328 /********************************************/
329 pixmap_path = XtResolvePathname( XtDisplay(wgt), "bitmaps", pixmap_file,
330 NULL, FXTV_LIBDIR, NULL, 0, NULL);
331
332 if ( pixmap_path == NULL ) {
333 fprintf( stderr, "Failed to find bitmap/pixmap '%s'\n", pixmap_file );
334 return False;
335 }
336
337 XtVaGetValues( wgt, XtNdepth, &color_depth, NULL );
338
339 /********************************************************************/
340 /* .xbm's aren't handled by Xpm. Do something different for them */
341 /********************************************************************/
342 if (( strlen( pixmap_path ) > 4 ) &&
343 ( strcmp( pixmap_path + strlen( pixmap_path ) - 4, ".xbm" ) == 0 )) {
344
345 /*****************/
346 /* Load bitmap */
347 /*****************/
348 if (( XReadBitmapFile( XtDisplay(wgt),
349 RootWindowOfScreen( XtScreen( wgt ) ),
350 pixmap_path, &width, &height, &pixmap_depth1,
351 &x_hot, &y_hot ) != BitmapSuccess ) ||
352 ( (*pixmap = XCreatePixmap( XtDisplay(wgt),
353 RootWindowOfScreen( XtScreen( wgt ) ),
354 width, height, color_depth )) == None )){
355 fprintf( stderr, "Failed to load bitmap %s\n", pixmap_path );
356 if ( pixmap_path != NULL )
357 XtFree( pixmap_path );
358 return False;
359 }
360
361 gcv.foreground = fg_color;
362 gcv.background = bg_color;
363 gcv.graphics_exposures = False;
364
365 gc = XCreateGC( XtDisplay(wgt), RootWindowOfScreen( XtScreen( wgt ) ),
366 GCForeground | GCBackground | GCGraphicsExposures,
367 &gcv );
368
369 XCopyPlane( XtDisplay(wgt), pixmap_depth1, *pixmap, gc,
370 0, 0, width, height, 0, 0, 0x00000001 );
371 XFreePixmap( XtDisplay( wgt ), pixmap_depth1 );
372 XFreeGC ( XtDisplay( wgt ), gc );
373 if ( pixmap_mask != NULL )
374 *pixmap_mask = NULL;
375 }
376 else {
377
378 /*****************/
379 /* Load pixmap */
380 /*****************/
381 colormap = XDefaultColormap( XtDisplay( wgt ),
382 DefaultScreen( XtDisplay( wgt ) ) );
383
384 XpmTransparentColor[0].pixel = bg_color;
385 xpmatts.colormap = colormap;
386 xpmatts.valuemask = XpmColorSymbols | XpmCloseness | XpmDepth |
387 XpmColormap;
388 xpmatts.colorsymbols = XpmTransparentColor;
389 xpmatts.numsymbols = 1;
390 xpmatts.closeness = 65536;
391 xpmatts.depth = color_depth;
392
393 xpm_status = XpmReadFileToPixmap(
394 XtDisplay( wgt ),
395 DefaultRootWindow( XtDisplay( wgt ) ),
396 pixmap_path,
397 &pix_returned,
398 &pix_mask_returned,
399 &xpmatts);
400
401 if ( xpm_status < 0 ) {
402 fprintf( stderr, "Failed to load pixmap %s\n", pixmap_path );
403 if ( pixmap_path != NULL )
404 XtFree( pixmap_path );
405 return False;
406 }
407
408 *pixmap = pix_returned;
409 if ( pix_mask_returned )
410 if ( pixmap_mask != NULL )
411 *pixmap_mask = pix_mask_returned;
412 else
413 XFreePixmap( XtDisplay( wgt ), pix_mask_returned );
414 }
415
416 if ( pixmap_path != NULL )
417 XtFree( pixmap_path );
418 return True;
419 }
420
421 /**@BEGINFUNC**************************************************************
422
423 Prototype : void XUTILXawScrollbarSetThumb(
424 Widget w,
425 float top,
426 float shown )
427
428 Purpose : Wrapper function for XawScrollbarSetThumb -- in a
429 separate module from that in which its called so we can
430 avoid a Scrollbar.h declaration error which declares
431 XawScrollbarSetThumb taking doubles instead of floats
432 (the library function expects floats).
433
434 Programmer : 29-Mar-97 Randall Hopper
435
436 Parameters : w - I: scrollbar widget
437 top - I: top value
438 shown - I: shown value
439
440 Returns : None.
441
442 Globals : None.
443
444 **@ENDFUNC*****************************************************************/
445
XUTILXawScrollbarSetThumb(Widget w,float top,float shown)446 void XUTILXawScrollbarSetThumb( Widget w, float top, float shown )
447 {
448 /* This rtn is here to avoid a prototyping bug in Scrollbar.h */
449 /* where the args to the following function are incorrectly */
450 /* declared as doubles, not floats. */
451 XawScrollbarSetThumb( w, top, shown );
452 }
453
454
455 /**@BEGINFUNC**************************************************************
456
457 Prototype : void XUTILGetVisualBpp(
458 Display *display,
459 XVisualInfo *vi,
460 TV_INT32 *Bpp_pixmap,
461 TV_INT32 *Bpp_fbuffer )
462
463 Purpose : Returns the number of bytes per pixel for the specified
464 visual.
465
466 NOTE: This is not always (depth+7)/8, which is the reason
467 for the existance of this convenience function. And even
468 then this function will sometimes get it wrong because
469 Pixmap pixel geometry doesn't necessarily equate to Frame
470 buffer pixel geometry.
471
472 BACKGROUND: Some X servers define 4 Bpp 24bpp modes as
473 depth 32 bpp (-bpp 32), while others define them as depth
474 24 bpp (-bpp 24). Others use implement both 24bpp and 32bpp
475 in a 3Bpp mode (e.g. 3.3.1 S3V server). So we can't use
476 visual depth alone as a determining value.
477
478 Alternatively we probe the pixmap formats that are
479 supported by the display to help determine the true Bpp.
480 For both cases, the pixmap bits_per_pixel for the
481 corresponding depth (24 or 32) is 32, usually reflecting
482 the true depth of the frame buffer, but not always.
483
484 Because without probing hardware we can't really tell
485 for sure what the frame buffer Bpp is, we allow the
486 user to tell us (for 24bpp and 32bpp anyway) using the
487 Bpp24bit and Bpp32bit settings
488
489 Programmer : 29-Mar-97 Randall Hopper
490
491 Parameters : display - I: display that visual is on
492 vi - I: info struct for a visual
493 Bpp_pixmap - O: pixmap Bpp
494 Bpp_fbuffer - O: frame buffer Bpp
495
496 Returns : Bytes per pixel for the visual
497
498 Globals : None.
499
500 **@ENDFUNC*****************************************************************/
501
XUTILGetVisualBpp(Display * display,XVisualInfo * vi,TV_INT32 * Bpp_pixmap,TV_INT32 * Bpp_fbuffer)502 void XUTILGetVisualBpp(
503 Display *display,
504 XVisualInfo *vi,
505 TV_INT32 *Bpp_pixmap,
506 TV_INT32 *Bpp_fbuffer )
507 {
508 static struct {
509 VisualID visualid;
510 TV_INT32 Bpp_pixmap;
511 TV_INT32 Bpp_fbuffer;
512 } *Vlist = NULL;
513 static int Vlist_len = 0;
514
515 TV_INT32 i,
516 Bpp = 0;
517
518 /* Look up cached value */
519 for ( i = 0; i < Vlist_len; i++ )
520 if ( Vlist[i].visualid == vi->visualid )
521 break;
522
523 /* Didn't have a cached value? Go figure it out. */
524 if ( i >= Vlist_len ) {
525 XPixmapFormatValues *pf;
526 int num_pf,
527 pfi;
528
529 /* Try to grab Bpp from pixmap formats first */
530 pf = XListPixmapFormats( display, &num_pf );
531 if ( pf != NULL ) {
532 for ( pfi = 0; pfi < num_pf; pfi++ )
533 if ( pf[ pfi ].depth == vi->depth )
534 break;
535 if ( pfi < num_pf )
536 Bpp = ( pf[ pfi ].bits_per_pixel + 7 ) / 8;
537 XFree ( pf );
538 }
539
540 /* Or fallback to using depth */
541 if ( Bpp == 0 )
542 Bpp = ( vi->depth + 7 ) / 8;
543
544 /* And finally, add to Bpp cache */
545 Vlist_len++;
546 Vlist = realloc( Vlist, sizeof( Vlist[0] ) * Vlist_len );
547 if ( Vlist == NULL )
548 TVUTILOutOfMemory();
549 i = Vlist_len-1;
550 Vlist[i].visualid = vi->visualid;
551 Vlist[i].Bpp_pixmap = Bpp;
552 Vlist[i].Bpp_fbuffer = Bpp;
553 }
554
555 /* Even then, this value may not be right for the frame buffer */
556 /* geometry. Allow the user to override settings for 24bpp */
557 /* and 32bpp. */
558 if (( vi->depth == 24 ) && INRANGE( App_res.Bpp_24bit, 3, 4, 0 ))
559 Vlist[i].Bpp_fbuffer = App_res.Bpp_24bit;
560 else if (( vi->depth == 32 ) && INRANGE( App_res.Bpp_32bit, 3, 4, 0 ))
561 Vlist[i].Bpp_fbuffer = App_res.Bpp_32bit;
562
563 if ( Bpp_pixmap )
564 *Bpp_pixmap = Vlist[i].Bpp_pixmap;
565 if ( Bpp_fbuffer )
566 *Bpp_fbuffer = Vlist[i].Bpp_fbuffer;
567 }
568
569
570 /**@BEGINFUNC**************************************************************
571
572 Prototype : void XUTILGetVisualSwaps(
573 Display *display,
574 XVisualInfo *vi,
575 TV_BOOL *swap_bytes,
576 TV_BOOL *swap_shorts )
577
578 Purpose : Based on the visual, determines whether bytes and/or
579 shorts need to be swapped in the process of pixel blasting
580 to display correctly.
581
582 Examples:
583 <--- lower addr higher addr --->
584 2Bpp 15bpp no-swap = xRRRRRGG GGGBBBBB
585 2Bpp 15bpp byte-swap = GGGBBBBB xRRRRRGG
586
587 3Bpp 24bpp no-swap = RGB RGB
588 3Bpp 24bpp byte-swap = BGR BGR
589
590 4Bpp 24bpp no-swap = ARGB ARGB
591 4Bpp 24bpp both-swap = BGRA BGRA
592
593 Programmer : 22-Apr-97 Randall Hopper
594
595 Parameters : display - I: display for visual
596 vi - I: visual info
597 swap_bytes - O: whether byte swap is needed
598 swap_shorts - O: whether short swap is needed
599
600 Returns : None.
601
602 Globals : None.
603
604 **@ENDFUNC*****************************************************************/
605
XUTILGetVisualSwaps(Display * display,XVisualInfo * vi,TV_BOOL * swap_bytes,TV_BOOL * swap_shorts)606 void XUTILGetVisualSwaps( Display *display, XVisualInfo *vi,
607 TV_BOOL *swap_bytes, TV_BOOL *swap_shorts )
608 {
609 TV_INT32 Bpp;
610
611 /* FIXME: probably should make the settings based on bpp rather than */
612 /* Bpp since Bpp is ambiguous. 24bpp could be 3 or 4 Bpp. Ditto */
613 /* for 32bpp. */
614 XUTILGetVisualBpp( display, vi, NULL, &Bpp );
615
616 *swap_bytes = *swap_shorts = FALSE;
617
618 /* FIXME: For now, just let the user override the default swaps. */
619 /* We have defaults, of course. */
620 /* Can't get this from the X server for 2Bpp modes -- assume */
621 /* swapped (makes sense -- more efficient). */
622 /* But consider whether we can determine for 3/4Bpp modes; do */
623 /* all X servers report the visual masks assuming a 4Bpp blast? */
624 /* (i.e. dword already reversed?) -- hard to guess. */
625 switch ( Bpp ) {
626 case 2 : *swap_bytes = App_res.bswap2Bpp;
627 break;
628 case 3 : *swap_bytes = App_res.bswap3Bpp;
629 break;
630 case 4 : *swap_bytes = App_res.bswap4Bpp;
631 *swap_shorts = App_res.wswap4Bpp;
632 break;
633 }
634 }
635
636
637 /**@BEGINFUNC**************************************************************
638
639 Prototype : void XUTILDialogSmartPosition(
640 Widget main_wgt,
641 Widget dialog_wgt )
642
643 Purpose : Smart position a dialog so it lies on the screen.
644
645 Programmer : 21-May-98 Randall Hopper
646
647 Parameters : main_wgt - I: window to place dialog beside
648 dialog_wgt - I: dialog to position
649 Returns : None.
650
651 Globals : None.
652
653 **@ENDFUNC*****************************************************************/
654
XUTILDialogSmartPosition(Widget main_wgt,Widget dialog_wgt)655 void XUTILDialogSmartPosition(
656 Widget main_wgt,
657 Widget dialog_wgt )
658 {
659 Dimension m_width,
660 m_height,
661 d_width,
662 d_height;
663 Position d_x,
664 d_y,
665 m_ul[2],
666 m_lr[2];
667 Screen *screen = XtScreen ( main_wgt );
668
669 XtVaGetValues( dialog_wgt, XtNwidth , &d_width,
670 XtNheight, &d_height,
671 NULL );
672
673 XtVaGetValues( main_wgt, XtNwidth , &m_width,
674 XtNheight, &m_height,
675 NULL);
676
677 XtTranslateCoords( main_wgt, 0, 0, &m_ul[0], &m_ul[1] );
678 m_lr[0] = m_ul[0] + m_width ;
679 m_lr[1] = m_ul[1] + m_height;
680
681 /* Try below, right, above, left, then just slap it on top of main_wgt */
682 if ( m_lr[1]+d_height+WM_BORDER_PAD <= HeightOfScreen(screen) )
683 d_x = m_ul[0],
684 d_y = m_lr[1]+WM_BORDER_PAD;
685 else if ( m_lr[0]+d_width+WM_BORDER_PAD <= WidthOfScreen(screen) )
686 d_x = m_lr[0]+WM_BORDER_PAD,
687 d_y = m_ul[1];
688 else if ( m_ul[1]-d_height-WM_BORDER_PAD >= 0 )
689 d_x = m_ul[0],
690 d_y = m_ul[1]-d_height-WM_BORDER_PAD;
691 else if ( m_ul[0]-d_width-WM_BORDER_PAD >= 0 )
692 d_x = m_ul[0]-d_width-WM_BORDER_PAD,
693 d_y = m_ul[1];
694 else
695 d_x = m_ul[0],
696 d_y = m_ul[1];
697
698 d_x = MAX(0, d_x );
699 d_y = MAX(0, d_y );
700 d_x = MIN( WidthOfScreen (screen), d_x+d_width ) - d_width;
701 d_y = MIN( HeightOfScreen(screen), d_y+d_height ) - d_height;
702
703 XtVaSetValues( dialog_wgt, XtNx, d_x,
704 XtNy, d_y,
705 NULL );
706 }
707
708
709 /**@BEGINFUNC**************************************************************
710
711 Prototype : Widget XUTILDialogBuild(
712 Widget toplevel,
713 char title[],
714 char msg[],
715 TV_DIALOG_TYPE type )
716
717 Prototype : TV_INT32 XUTILDialogPause(
718 Widget toplevel,
719 char title[],
720 char msg[],
721 TV_DIALOG_TYPE type )
722
723 Purpose : Utilities to build a dialog, and to put up a dialog with a
724 user-specified message and sit-n-spin in our own local
725 xevent loop until the user wakes up and answers the question.
726
727 Programmer : 23-May-97 Randall Hopper
728
729 Parameters : toplevel - I: top level shel widget for app
730 title - I: dialog title
731 msg - I: the message to display
732 type - I: type of dialog to display
733
734 Returns : For YES_NO dialogs, { TV_DIALOG_YES TV_DIALOG_NO }
735
736 Globals : None.
737
738 **@ENDFUNC*****************************************************************/
739
740 static TV_INT32 Dialog_answer;
741
742
DialogCB(Widget w,XtPointer client_data,XtPointer cb_data)743 static void DialogCB( Widget w, XtPointer client_data, XtPointer cb_data )
744 {
745 char *name = XtName( w );
746
747 if ( strcmp( name, "yes" ) == 0 )
748 Dialog_answer = TV_DIALOG_YES;
749 else if ( strcmp( name, "no" ) == 0 )
750 Dialog_answer = TV_DIALOG_NO;
751 else
752 Dialog_answer = True;
753
754 XtPopdown ( (Widget) client_data );
755 XtUnrealizeWidget( (Widget) client_data );
756 }
757
758
XUTILDialogBuild(Widget toplevel,char title[],char msg[],TV_DIALOG_TYPE type)759 Widget XUTILDialogBuild( Widget toplevel,
760 char title[], char msg[], TV_DIALOG_TYPE type )
761 {
762 Widget shell,
763 dialog;
764
765 /* Construct dialog */
766 shell = XtCreatePopupShell( "simplePromptShell",
767 transientShellWidgetClass,
768 toplevel, NULL, 0 );
769 XtVaSetValues( shell, XtNtitle , title,
770 XtNallowShellResize, False,
771 NULL );
772
773 dialog = XtVaCreateManagedWidget ( "simplePromptDialog",
774 dialogWidgetClass, shell,
775 XtNlabel, msg,
776 NULL );
777
778 switch ( type ) {
779 case TV_DIALOG_TYPE_OK :
780 XawDialogAddButton( dialog, "ok" , DialogCB, shell );
781 break;
782 case TV_DIALOG_TYPE_CANCEL :
783 XawDialogAddButton( dialog, "cancel", DialogCB, shell );
784 break;
785 case TV_DIALOG_TYPE_YES_NO :
786 XawDialogAddButton( dialog, "yes" , DialogCB, shell );
787 XawDialogAddButton( dialog, "no" , DialogCB, shell );
788 break;
789 case TV_DIALOG_TYPE_NOBUTTONS :
790 break;
791 default:
792 fprintf( stderr, "Unsupported dialog type\n" );
793 exit(1);
794 }
795
796 return shell;
797 }
798
799
XUTILDialogPause(Widget toplevel,char title[],char msg[],TV_DIALOG_TYPE type)800 TV_INT32 XUTILDialogPause( Widget toplevel,
801 char title[], char msg[], TV_DIALOG_TYPE type )
802 {
803 Widget shell;
804
805 /* Sanity check */
806 if ( type == TV_DIALOG_TYPE_NOBUTTONS ) {
807 fprintf( stderr, "XUTILDialogPause: Bad dialog type\n" );
808 exit(1);
809 }
810
811 /* Build dialog */
812 shell = XUTILDialogBuild( toplevel, title, msg, type );
813
814 /* Pop it up */
815 XUTILXtPopup( shell, XtGrabNonexclusive, toplevel );
816
817 /* Wait until user answers the dialog */
818 while ( XtIsRealized(shell) ) {
819 XEvent ev;
820
821 XtAppNextEvent( XtWidgetToApplicationContext(toplevel), &ev );
822 XtDispatchEvent( &ev );
823 }
824
825 /* Close and destroy the dialog */
826 XtUnrealizeWidget( shell );
827 XtDestroyWidget( shell );
828 return Dialog_answer;
829 }
830
831
832 /**@BEGINFUNC**************************************************************
833
834 Prototype : static void XUTILGetPixelGeomInfo(
835 TV_UINT32 rel_mask[3],
836 int bits [3],
837 int shift [3],
838 int mask [3] )
839
840 Purpose : Get Pixel RGB component shifts, masks, and bit counts
841 for the specified visual.
842
843 (mask[0] << shift[0]) | (mask[1] << shift[1]) |
844 (mask[2] << shift[2])
845
846 FIXME: Duplicated in videolib
847
848 Programmer : 07-Mar-97 Randall Hopper
849
850 Parameters : rel_mask- I: R/G/B shifted mask for each compoent
851 bits - O: R/G/B bpp
852 shift - O: R/G/B left shift cnt to align component in pixel
853 mask - O: R/G/B mask to keep only desired bits
854
855 E.g.: INPUT : rel_mask = FF0000,00FF00,0000FF
856 OUTPUT: bits = 8,8,8
857 shift = 16,8,0
858 mask = FF,FF,FF
859
860 Returns : None.
861
862 Globals : None.
863
864 **@ENDFUNC*****************************************************************/
865
XUTILGetPixelGeomInfo(TV_UINT32 rel_mask[3],int bits[3],int shift[3],int mask[3])866 static void XUTILGetPixelGeomInfo(
867 TV_UINT32 rel_mask[3],
868 int bits [3],
869 int shift [3],
870 int mask [3] )
871 {
872 int i;
873 TV_UINT32 rel[3];
874
875 memcpy( rel, rel_mask, sizeof( rel ) );
876
877 for ( i = 0; i < 3; i++ ) {
878 if ( !rel[i] ) {
879 fprintf( stderr, "XUTILGetPixelGeomInfo: Bad X visual mask\n");
880 exit(1);
881 }
882 bits[i] = shift[i] = mask[i] = 0;
883
884 while ( !(rel[i] & 0x01) )
885 rel[i] >>= 1, shift[i]++;
886
887 mask[i] = rel[i];
888
889 while ( (rel[i] & 0x01) )
890 rel[i] >>= 1, bits[i]++;
891 }
892 }
893
894 /**@BEGINFUNC**************************************************************
895
896 Prototype : void XUTILGetPixelConvInfo(
897 TV_UINT32 src_rel_mask[3],
898 TV_UINT32 dst_rel_mask[3],
899 TV_INT32 shift [3],
900 TV_UINT32 mask [3] )
901
902 Purpose : Given a source pixel mask and a destination pixel mask,
903 determines the shifts and masks necessary to map the
904 source pixel geometry to the destination.
905
906 FIXME: Duplicated in videolib
907
908 Programmer : 29-Mar-97 Randall Hopper
909
910 Parameters : src_rel_mask - I: source relative pixel masks
911 dst_rel_mask - I: dest relative pixel masks
912 shift - O: initial pixel shifts
913 mask - O: final pixel masks
914
915 E.g.: INPUT : src_rel_mask = 00FC00, 0003e0, 00001f
916 dst_rel_mask = FF0000, 00FF00, 0000FF
917
918 OUTPUT: shift = 8, 6, 3
919 mask = FC0000, 00F800, 0000F8
920
921 Returns : None.
922
923 Globals : None.
924
925 **@ENDFUNC*****************************************************************/
926
XUTILGetPixelConvInfo(TV_UINT32 src_rel_mask[3],TV_UINT32 dst_rel_mask[3],TV_INT32 shift[3],TV_UINT32 mask[3])927 void XUTILGetPixelConvInfo(
928 TV_UINT32 src_rel_mask[3],
929 TV_UINT32 dst_rel_mask[3],
930 TV_INT32 shift [3],
931 TV_UINT32 mask [3] )
932 {
933 int src_bits[3], src_shf[3], src_msk[3], src_soff[3],
934 dst_bits[3], dst_shf[3], dst_msk[3], dst_soff[3];
935 TV_INT32 i;
936
937 /* Get R/G/B shifts, masks, and bit counts */
938 XUTILGetPixelGeomInfo( src_rel_mask, src_bits, src_shf, src_msk );
939 XUTILGetPixelGeomInfo( dst_rel_mask, dst_bits, dst_shf, dst_msk );
940
941 /* Calculate R/G/B left-most bit offsets */
942 for ( i = 0; i < 3; i++ )
943 src_soff[i] = src_shf[i] + src_bits[i] - 1,
944 dst_soff[i] = dst_shf[i] + dst_bits[i] - 1;
945
946 /* Finally, calculate net shifts and masks */
947 for ( i = 0; i < 3; i++ ) {
948 shift[i] = dst_soff[i] - src_soff[i];
949 if ( shift[i] >= 0 )
950 mask [i] = ( src_rel_mask[i] << shift[i] ) & dst_rel_mask[i];
951 else
952 mask [i] = ( src_rel_mask[i] >> -shift[i] ) & dst_rel_mask[i];
953 }
954 }
955
956
957 /**@BEGINFUNC**************************************************************
958
959 Prototype : static void XUTILRunCmdTimeoutCB(
960 XtPointer cl_data,
961 XtIntervalId *timer )
962
963 Purpose : Timer callback for XUTILRunCmdAllowCancel.
964
965 Called periodically to check on the status of the
966 background command.
967
968 Programmer : 19-Jul-97 Randall Hopper
969
970 Parameters : cl_data - I: state data struct (malloced mem)
971 timer - I: <not used>
972
973 Returns : None.
974
975 Globals : None.
976
977 **@ENDFUNC*****************************************************************/
978
XUTILRunCmdTimeoutCB(XtPointer cl_data,XtIntervalId * timer)979 static void XUTILRunCmdTimeoutCB(
980 XtPointer cl_data,
981 XtIntervalId *timer )
982 {
983 XUTIL_RUNCMD_STATE *state = (XUTIL_RUNCMD_STATE *) cl_data;
984 int ret,
985 status = 0;
986 TV_BOOL aborted,
987 complete;
988
989 /* Ok, is our process still out there crunching? */
990 ret = kill( state->cmd_pid, 0 );
991
992 if (( ret < 0 ) && ( errno != ESRCH )) {
993 TVUTILPipeCleanup( state->cmd_pid, state->end, &status );
994 perror( "kill(,0) failed on conv process" );
995 exit(1);
996 }
997
998 aborted = state->cancel_cb &&
999 state->cancel_cb( state->cancel_cb_data );
1000 complete = ( ret < 0 ) && ( errno == ESRCH );
1001
1002 /* If process is done or user aborted, clean up and get exit status, */
1003 /* and notify client. */
1004 if ( aborted || complete ) {
1005 if ( aborted )
1006 kill( state->cmd_pid, SIGINT );
1007 TVUTILPipeCleanup( state->cmd_pid, state->end, &status );
1008
1009 state->done_cb( aborted, status, state->done_cb_data );
1010
1011 free(state);
1012 }
1013
1014 /* Otherwise, just go back to sleep and check again later */
1015 else
1016 XtAppAddTimeOut( state->app_context, RUNCMD_CHECK_TIMEOUT_MS,
1017 XUTILRunCmdTimeoutCB, state );
1018 }
1019
1020 /**@BEGINFUNC**************************************************************
1021
1022 Prototype : void XUTILRunCmdAllowCancel(
1023 XtAppContext app_context,
1024 char *cmd[],
1025 TVUTIL_PIPE_END end[3],
1026 XUTIL_RUNCMD_CANCELCB *cancel_test,
1027 void *cancel_cb_data,
1028 XUTIL_RUNCMD_DONECB *done_cb,
1029 void *done_cb_data )
1030
1031 Purpose : Run a command (cmd,end) in the background giving the client
1032 the opportunity to cancel the command using its own criteria
1033 (e.g. dialog dismissed, cancel button pressed, etc.).
1034
1035 While the command is executing, its existance is checked and
1036 the cancel_test callback is called (with cancel_cb_data)
1037 periodically.
1038
1039 When the command completes or is cancelled, the user-defined
1040 callback done_cb is called with done_cb_data. The callback
1041 is also passed whether the command was aborted as well as
1042 the exit status of the command.
1043
1044 If the command is called (cancel_test returns TRUE),
1045 the command is killed (SIGINT is issued).
1046
1047 Programmer : 30-May-97 Randall Hopper
1048
1049 Parameters : app-context - I: Xt application context
1050 cmd - I: cmd to execute ( [argv[0],argv[1],...] )
1051 end - I: bindings for stdin/stdout of cmd
1052 cancel_test - I: callback to allow client to abort command
1053 cancel_cb_data - I: client data to pass cancel callback
1054 done_cb - I: callback to call on cmd complete/abort
1055 done_cb_data - I: client data to pass done callback
1056
1057 Returns : None.
1058
1059 Globals : None.
1060
1061 **@ENDFUNC*****************************************************************/
1062
XUTILRunCmdAllowCancel(XtAppContext app_context,char * cmd[],TVUTIL_PIPE_END end[3],XUTIL_RUNCMD_CANCELCB * cancel_test,void * cancel_cb_data,XUTIL_RUNCMD_DONECB * done_cb,void * done_cb_data)1063 void XUTILRunCmdAllowCancel(
1064 XtAppContext app_context,
1065 char *cmd[],
1066 TVUTIL_PIPE_END end[3],
1067 XUTIL_RUNCMD_CANCELCB *cancel_test,
1068 void *cancel_cb_data,
1069 XUTIL_RUNCMD_DONECB *done_cb,
1070 void *done_cb_data )
1071 {
1072 XUTIL_RUNCMD_STATE *state;
1073
1074 /* We'll wake-up every once in a while and check on it. */
1075 /* First, build state data struct. */
1076 if ( (state = malloc( sizeof( *state ) )) == NULL )
1077 TVUTILOutOfMemory();
1078 memset( state, '\0', sizeof( *state ) );
1079
1080 state->cmd_pid = -1;
1081 memcpy( state->end, end, sizeof( state->end ) );
1082 state->app_context = app_context;
1083 state->cancel_cb = cancel_test;
1084 state->cancel_cb_data = cancel_cb_data;
1085 state->done_cb = done_cb;
1086 state->done_cb_data = done_cb_data;
1087
1088 /* Ok, now fire-up the child process */
1089 TVUTILPipeSetup( NULL, cmd, end, &state->cmd_pid );
1090
1091 /* Now go to sleep and wait on 1) user to cancel, or 2) cmd to complete */
1092 XtAppAddTimeOut( state->app_context, RUNCMD_CHECK_TIMEOUT_MS,
1093 XUTILRunCmdTimeoutCB, state );
1094 }
1095
1096
1097 /* XUTILIsWellFormedXLFDFont */
1098 /* This routine returns True if the passed name is a well-formed */
1099 /* XLFD style font name. Adapted from XUtilIsScalableFont (below). */
XUTILIsWellFormedXLFDFont(char * name)1100 Bool XUTILIsWellFormedXLFDFont( char *name )
1101 {
1102 int i, field, field_len;
1103 char *p;
1104
1105 if ( !name || ( name[0] != '-' ))
1106 return False;
1107
1108 for ( i = field = 0; name[i] != '\0'; i++ )
1109 if ( name[i] == '-' ) {
1110 field++;
1111
1112 if ( (p = strchr( &name[i+1], '-' )) != NULL )
1113 field_len = p - &name[i+1];
1114 else
1115 field_len = strlen( &name[i+1] ) - i+1;
1116 if (( field != 6 ) && ( field_len == 0 ))
1117 return False;
1118 switch ( field ) {
1119 case 1 : if ( field_len >= XLFD_SIZE_FOUNDRY )
1120 return False;
1121 break;
1122 case 2 : if ( field_len >= XLFD_SIZE_FAMILY )
1123 return False;
1124 break;
1125 default : if ( field_len >= XLFD_SIZE_SMALL )
1126 return False;
1127 break;
1128 }
1129 }
1130
1131 return ( field == 14 );
1132 }
1133
1134
1135 /* XUTILIsScalableFont - From O'Reilly X11R5 Vol 1 A.3.3 (pg 569). */
1136 /* This routine returns True if the passed name is a well-formed */
1137 /* XLFD style font name with a pixel size, point size, and average */
1138 /* width (fields 7, 8, and 12) of "0". */
1139 /* Modified: component length sanity checking added. */
XUTILIsScalableFont(char * name)1140 Bool XUTILIsScalableFont( char *name )
1141 {
1142 int i, field, field_len;
1143 char *p;
1144
1145 if ( !name || ( name[0] != '-' ))
1146 return False;
1147
1148 for ( i = field = 0; name[i] != '\0'; i++ )
1149 if ( name[i] == '-' ) {
1150 field++;
1151 if (( field == 7 ) || ( field == 8 ) || ( field == 12 ))
1152 if (( name[i+1] != '0' ) || ( name[i+2] != '-' ))
1153 return False;
1154
1155 if ( (p = strchr( &name[i+1], '-' )) != NULL )
1156 field_len = p - &name[i+1];
1157 else
1158 field_len = strlen( &name[i+1] ) - i+1;
1159 switch ( field ) {
1160 case 1 : if ( field_len >= XLFD_SIZE_FOUNDRY )
1161 return False;
1162 break;
1163 case 2 : if ( field_len >= XLFD_SIZE_FAMILY )
1164 return False;
1165 break;
1166 default : if ( field_len >= XLFD_SIZE_SMALL )
1167 return False;
1168 break;
1169 }
1170
1171 }
1172
1173 return ( field == 14 );
1174 }
1175
1176 /* XUTILSplitXLFD - Split an XLFD font name up into components */
XUTILSplitXLFD(char name[],TV_XLFD * xlfd)1177 static void XUTILSplitXLFD( char name[],
1178 TV_XLFD *xlfd )
1179 {
1180 int ret;
1181
1182 if ( !XUTILIsWellFormedXLFDFont( name ) ) {
1183 fprintf( stderr, "XUTILSplitXLFD: Passed non-XLFD font\n" );
1184 exit(1);
1185 }
1186
1187 xlfd->ad_style[0] = '\0';
1188
1189 ret = sscanf( name,
1190 "-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]"
1191 "-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]",
1192 xlfd->foundry, xlfd->family, xlfd->weight, xlfd->slant,
1193 xlfd->set_width, xlfd->ad_style, xlfd->pixel_size, xlfd->point_size,
1194 xlfd->x_dpi, xlfd->y_dpi, xlfd->spacing, xlfd->avg_width,
1195 xlfd->charset_reg, xlfd->charset_enc );
1196
1197 if ( ret != 14 ) {
1198 xlfd->ad_style[0] = '\0';
1199
1200 ret = sscanf( name,
1201 "-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]--%[^-]-%[^-]"
1202 "-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]",
1203 xlfd->foundry, xlfd->family, xlfd->weight, xlfd->slant,
1204 xlfd->set_width, xlfd->pixel_size, xlfd->point_size,
1205 xlfd->x_dpi, xlfd->y_dpi, xlfd->spacing, xlfd->avg_width,
1206 xlfd->charset_reg, xlfd->charset_enc );
1207
1208 if ( ret != 13 ) {
1209 fprintf( stderr, "XUTILSplitXLFD: Unexpected parse failure\n" );
1210 exit(1);
1211 }
1212 }
1213 }
1214
1215 /* XUTILMergeXLFD - Build an XLFD font name string up from its components */
1216 /* It is assumed that name[] is large enough to hold the resulting str. */
XUTILMergeXLFD(TV_XLFD * xlfd,char name[])1217 static void XUTILMergeXLFD( TV_XLFD *xlfd,
1218 char name[] )
1219 {
1220 sprintf( name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1221 xlfd->foundry, xlfd->family, xlfd->weight, xlfd->slant,
1222 xlfd->set_width, xlfd->ad_style, xlfd->pixel_size, xlfd->point_size,
1223 xlfd->x_dpi, xlfd->y_dpi, xlfd->spacing, xlfd->avg_width,
1224 xlfd->charset_reg, xlfd->charset_enc );
1225 }
1226
1227
1228 #define TV_XLFD_SPLIT( str_name, xlfd ) \
1229
1230
1231
1232 /* XUTILLoadQueryScalableFont - From O'Reilly X11R5 Vol 1 A.3.3 (pg 570). */
1233 /* This routine is passed a scalable font name and a point size. It */
1234 /* returns an XFontStruct for the given font scaled to the specified */
1235 /* size and the exact resolution of the screen. The font name is */
1236 /* assumed to be a well-formed XLFD name, and to have pixel size, point */
1237 /* size, and average width fields of "0" and arbitrary x-res and y-res */
1238 /* fields. Size is specified in tenths of points. Returns NULL if */
1239 /* no such font exists. */
1240 /* ADAPTED: new_name, new_name_size args added. */
XUTILLoadQueryScalableFont(Display * dpy,int screen,char * name,int size,char * new_name,int new_name_size)1241 XFontStruct *XUTILLoadQueryScalableFont(
1242 Display *dpy,
1243 int screen,
1244 char *name,
1245 int size,
1246 char *new_name,
1247 int new_name_size )
1248 {
1249 int i,j,field;
1250 char newname[500];
1251 int res_x,res_y;
1252
1253 if ( !XUTILIsScalableFont( name ) ) {
1254 fprintf( stderr,
1255 "XUTILLoadQueryScalableFont: Passed non-scalable font\n" );
1256 exit(1);
1257 }
1258
1259 /* Calculate our screen res in dots-per-inch. 25.4mm = 1in */
1260 res_x = DisplayWidth( dpy, screen ) /
1261 ( DisplayWidthMM( dpy, screen ) / 25.4 );
1262 res_y = DisplayHeight( dpy, screen ) /
1263 ( DisplayHeightMM( dpy, screen ) / 25.4 );
1264
1265 /* Copy the font name, changing the scalable fields as we do so */
1266 for ( i = j = field = 0; name[i] != '\0' && field <= 14; i++ ) {
1267 newname[j++] = name[i];
1268 if ( name[i] == '-' ) {
1269 field++;
1270 switch ( field ) {
1271 case 7: /* pixel size */
1272 case 12: /* average width */
1273 /* change from "-0-" to "-*-" */
1274 newname[j] = '*';
1275 j++;
1276 if ( name[i+1] != '\0' )
1277 i++;
1278 break;
1279
1280 case 8: /* point size */
1281 /* change from "-0-" to "-<size>-" */
1282 sprintf( &newname[j], "%d", size );
1283 while ( newname[j] != '\0' )
1284 j++;
1285 if ( name[i+1] != '\0' )
1286 i++;
1287 break;
1288
1289 case 9: /* x-resolution */
1290 case 10: /* y-resolution */
1291 /* change from an unspecified res to res_x or res_y */
1292 sprintf( &newname[j], "%d", (field == 9 ) ? res_x:res_y );
1293 while ( newname[j] != '\0' )
1294 j++;
1295 while( (name[i+1] != '-') && (name[i+1] != '\0'))
1296 i++;
1297 break;
1298 }
1299 }
1300 }
1301 newname[j] = '\0';
1302
1303 if ( new_name ) {
1304 new_name[0] = '\0';
1305 strncat( new_name, newname, new_name_size-1 );
1306 }
1307
1308 /* if there aren't 14 hyphens, it isn't a well-formed name */
1309 assert( field == 14 );
1310
1311 return XLoadQueryFont( dpy, newname );
1312 }
1313
1314 /* XUTILLoadPixelSizeFont */
1315 /* This routine is passed a well-formed XLFD font name and a pixel size. */
1316 /* It returns an XFontStruct for the given font scaled to the specified */
1317 /* pixel size (if possible). Returns NULL if no such font can be built. */
1318 /* Also, the pixel size is only plugged into the font name if the */
1319 /* pixel size component is wildcarded or 0. */
1320 /* ADAPTED: from the adapted XUTILLoadQueryScalableFont */
XUTILLoadPixelSizeFont(Display * dpy,char * name,int pixel_size,char * new_name,int new_name_size)1321 XFontStruct *XUTILLoadPixelSizeFont(
1322 Display *dpy,
1323 char *name,
1324 int pixel_size,
1325 char *new_name,
1326 int new_name_size )
1327 {
1328 TV_XLFD xlfd;
1329 char newname[500];
1330
1331 XUTILSplitXLFD( name, &xlfd );
1332
1333 if (( strcmp( xlfd.pixel_size, "0" ) == 0 ) ||
1334 ( strcmp( xlfd.pixel_size, "*" ) == 0 ))
1335 sprintf( xlfd.pixel_size, "%d", abs(pixel_size) );
1336
1337 XUTILMergeXLFD( &xlfd, newname );
1338
1339 if ( new_name ) {
1340 new_name[0] = '\0';
1341 strncat( new_name, newname, new_name_size-1 );
1342 }
1343
1344 return XLoadQueryFont( dpy, newname );
1345 }
1346
1347
1348 /* XUTILXMDeleteChildWindow - Called when we receive a window manager */
1349 /* event for a shell window registered with XUTILRegisterWMDelete. */
1350 /* We register for WM_DELETE_WINDOW for WM Close events. When this */
1351 /* occurs, ignore the event. */
XUTILWMDeleteChildWindow(Widget w,XEvent * event,String * params,Cardinal num_params)1352 static void XUTILWMDeleteChildWindow(
1353 Widget w,
1354 XEvent *event,
1355 String *params,
1356 Cardinal num_params )
1357 {
1358 if ( event->type == ClientMessage &&
1359 ( event->xclient.data.l[0] != S_wm_delete_window ) ) {
1360 XBell ( XtDisplay(w), 0 );
1361 return;
1362 }
1363
1364 /* Ignore WM_DELETE */
1365 XBell ( XtDisplay(w), 0 );
1366 }
1367
1368 /* XUTILRegisterWMDelete - Adds translation to shell widgets so that */
1369 /* the app doesn't blow up when the user selects the WM Close function */
1370 /* on out child windows. */
XUTILRegisterWMDelete(Widget shell_wgt)1371 void XUTILRegisterWMDelete(
1372 Widget shell_wgt )
1373 {
1374 static TV_BOOL S_wm_delete_inited = FALSE;
1375 static XtActionsRec S_wm_delete_actions[] = {
1376 { "WMDeleteChildWindow", (XtActionProc) XUTILWMDeleteChildWindow }
1377 };
1378
1379 if ( !XtIsRealized( shell_wgt ) ) {
1380 fprintf( stderr, "XUTILRegisterWMDelete: Called with an unrealized "
1381 "widget: %s\n", XtName( shell_wgt ) );
1382 exit(1);
1383 }
1384
1385 /* One-time init */
1386 if ( !S_wm_delete_inited ) {
1387
1388 /* WM Delete Window (Close) callback for FXTV child windows */
1389 XtAppAddActions ( XtWidgetToApplicationContext( shell_wgt ),
1390 S_wm_delete_actions,
1391 XtNumber( S_wm_delete_actions ) );
1392 S_wm_delete_inited = TRUE;
1393 }
1394
1395 /* Add WM callback translation to shell widget */
1396 XtOverrideTranslations( shell_wgt,
1397 XtParseTranslationTable(
1398 "<Message>WM_PROTOCOLS: WMDeleteChildWindow()" ) );
1399
1400 /* And ask window manager to call us for WM_DELETE_WINDOW events */
1401 S_wm_delete_window = XInternAtom( XtDisplay( shell_wgt ),
1402 "WM_DELETE_WINDOW", False );
1403 XSetWMProtocols( XtDisplay( shell_wgt ), XtWindow( shell_wgt ),
1404 &S_wm_delete_window, 1);
1405 }
1406
1407 /* XUTILXtPopup - XtPopup but additionally register a WM callback */
1408 /* to ignore WM_DELETE_WINDOW, and smart-positions the dialog. */
XUTILXtPopup(Widget popup_shell,XtGrabKind grab_kind,Widget toplevel)1409 void XUTILXtPopup( Widget popup_shell, XtGrabKind grab_kind,
1410 Widget toplevel )
1411 {
1412 Dimension height;
1413 Position x,y;
1414
1415 /* Tentatively position it */
1416 XtVaGetValues( toplevel, XtNheight, &height,
1417 NULL );
1418 XtTranslateCoords( toplevel, 0, 0, &x, &y );
1419 XtVaSetValues( popup_shell, XtNx, x,
1420 XtNy, y+height,
1421 NULL );
1422
1423 XtPopup( popup_shell, grab_kind );
1424
1425 /* Position it for keeps */
1426 XUTILDialogSmartPosition( toplevel, popup_shell );
1427
1428 /* Ignore WM_DELETE */
1429 XUTILRegisterWMDelete( popup_shell );
1430 }
1431
1432
1433 /* XUTILXServerIsLocal - Returns TRUE if the X server we're connecting to */
1434 /* is on the local machine (X via IPC or IP is assigned to an interface */
1435 /* of the local box. */
XUTILXServerIsLocal(Display * display)1436 TV_BOOL XUTILXServerIsLocal( Display *display )
1437 {
1438 char host_str[ 80 ],
1439 *p;
1440
1441 /* Grab the host part of the display string */
1442 host_str[0] = '\0';
1443 strncat( host_str, DisplayString(display), sizeof(host_str)-1 );
1444 if ( (p = strchr( host_str, ':' )) == NULL )
1445 return FALSE;
1446 *p = '\0';
1447 TVUTILstrlwr( host_str );
1448
1449 /* If local IPC, is local */
1450 if (( host_str[0] == '\0' ) || ( strcmp( host_str, "unix" ) == 0 ))
1451 return TRUE;
1452
1453 /* If hostname or IP belongs to one of our network interfaces, its */
1454 /* local. */
1455 /* FIXME: Add this */
1456
1457 return FALSE;
1458 }
1459
1460
1461 /**@BEGINFUNC**************************************************************
1462
1463 Prototype : void XUTILDetermineFrameBufferVisual(
1464 Display *display,
1465 int screen,
1466 XVisualInfo **fb_visual )
1467
1468 Purpose : Determine which visual corresponds the native format
1469 of the frame buffer.
1470
1471 Programmer : 16-Oct-99 Randall Hopper
1472
1473 Parameters : display - I: X display
1474 screen - I: X screen
1475 fb_visual - O: XVisualInfo for frame buffer visual
1476
1477 Returns : None.
1478
1479 Globals : None.
1480
1481 **@ENDFUNC*****************************************************************/
1482
XUTILDetermineFrameBufferVisual(Display * display,int screen,XVisualInfo ** fb_visual)1483 void XUTILDetermineFrameBufferVisual( Display *display,
1484 int screen,
1485 XVisualInfo **fb_visual )
1486 {
1487 XVisualInfo vinfo_pref;
1488 XVisualInfo *visual;
1489 int num_visuals;
1490 TV_INT32 Bpp_pixmap_best = -1,
1491 Bpp_fbuffer_best = -1,
1492 best_i = -1,
1493 i;
1494
1495 /**********************************************************************/
1496 /* FIXME: This algorithm is heuristic and prone to failure. Until */
1497 /* we have an enhanced XFree86 DGA 2.0 to tell us, we simply */
1498 /* assume the frame buffer visual is the one with the most */
1499 /* impressive pixel format. */
1500 /**********************************************************************/
1501
1502 vinfo_pref.screen = screen;
1503 vinfo_pref.depth = DefaultDepth( display, screen );
1504 visual = XGetVisualInfo( display,
1505 VisualScreenMask | VisualDepthMask,
1506 &vinfo_pref, &num_visuals );
1507 if ( num_visuals == 0 ) {
1508 fprintf( stderr, "XGetVisualInfo() says no visuals available!\n" );
1509 exit(1);
1510 }
1511
1512 for ( i = 0; i < num_visuals; i++ ) {
1513 TV_INT32 Bpp_pixmap,
1514 Bpp_fbuffer;
1515
1516 XUTILGetVisualBpp( display, &visual[i], &Bpp_pixmap, &Bpp_fbuffer );
1517 if ( (( visual[i].class == PseudoColor ) ||
1518 ( visual[i].class == TrueColor )) &&
1519 (( Bpp_pixmap > Bpp_pixmap_best ) ||
1520 ( Bpp_fbuffer > Bpp_fbuffer_best )) ) {
1521 Bpp_pixmap_best = Bpp_pixmap;
1522 Bpp_fbuffer_best = Bpp_fbuffer;
1523 best_i = i;
1524 }
1525 }
1526
1527 if ( best_i >= 0 )
1528 *fb_visual = &visual[ best_i ];
1529 else {
1530 Visual *def_vis;
1531
1532 fprintf( stderr, "XUTILDetermineFrameBufferVisual failed. "
1533 "Falling back to default visual.\n" );
1534
1535 def_vis = DefaultVisual( display, screen );
1536 vinfo_pref.screen = screen;
1537 vinfo_pref.visualid = XVisualIDFromVisual( def_vis );
1538
1539 *fb_visual = XGetVisualInfo( display,
1540 VisualScreenMask | VisualIDMask,
1541 &vinfo_pref, &num_visuals );
1542 if ( num_visuals != 1 ) {
1543 fprintf( stderr, "XGetVisualInfo() failed for default visual\n" );
1544 exit(1);
1545 }
1546 }
1547 }
1548