1 /* File: main-xaw.c */
3 /* Purpose: Support for X Athena Widget based Angband */
4 /* Most code written by Torbj
\vn Lindgren (tl@cd.chalmers.se) */
11 #ifndef __MAKEDEPEND__
13 #include <X11/StringDefs.h>
14 #include <X11/Xutil.h>
15 #include <X11/Intrinsic.h>
16 #include <X11/Shell.h>
17 #include <X11/keysym.h>
18 #include <X11/keysymdef.h>
19 #include <X11/IntrinsicP.h>
20 #include <X11/CoreP.h>
21 #include <X11/ShellP.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xaw/SimpleP.h>
24 #include <X11/Xaw/Simple.h>
25 #include <X11/Xaw/XawInit.h>
26 #endif /* __MAKEDEPEND__ */
30 /*****************************************************
32 * Resource description
34 *****************************************************/
38 Name Class RepType Default Value
39 ---- ----- ------- -------------
40 background Background Pixel XtDefaultBackground
41 border BorderColor Pixel XtDefaultForeground
42 borderWidth BorderWidth Dimension 1
43 cursor Cursor Cursor None
44 cursorName Cursor String NULL
45 destroyCallback Callback Pointer NULL
46 height Height Dimension 0
47 insensitiveBorder Insensitive Pixmap Gray
48 mappedWhenManaged MappedWhenManaged Boolean True
49 pointerColor Foreground Pixel XtDefaultForeground
50 pointerColorBackground Background Pixel XtDefaultBackground
51 sensitive Sensitive Boolean True
52 width Width Dimension 0
60 My own X Resources look like this (on a 1152x900 screen):
62 angband*angband*font: 12x24
63 angband*angband*geometry: +0+-20
64 angband*recall*font: 7x13
65 angband*recall*geometry: 80x10+0+586
66 angband*choice*font: 7x13
67 angband*choice*geometry: -0-0
69 It's also possible to change the colors using X Resources, the
70 standard colors would look like:
72 angband*color0: #000000
73 angband*color1: #ffffff
74 angband*color2: #a6a6a6
75 angband*color3: #ff6302
76 angband*color4: #ca0808
77 angband*color5: #008e18
78 angband*color6: #0000e3
79 angband*color7: #814007
80 angband*color8: #6b6b6b
81 angband*color9: #d6d6d6
82 angband*color10: #5100c2
83 angband*color11: #fdf105
84 angband*color12: #ff9259
85 angband*color13: #26cf17
86 angband*color14: #02b2f2
87 angband*color15: #b28b48
89 And the newer colors look like:
91 angband*color0: #000000
92 angband*color1: #ffffff
93 angband*color2: #d7d7d7
94 angband*color3: #ff9200
95 angband*color4: #ff0000
96 angband*color5: #00cd00
97 angband*color6: #0000fe
98 angband*color7: #c86400
99 angband*color8: #a3a3a3
100 angband*color9: #ebebeb
101 angband*color10: #a500ff
102 angband*color11: #fffd00
103 angband*color12: #ff00bc
104 angband*color13: #00ff00
105 angband*color14: #00c8ff
106 angband*color15: #ffcc80
108 Some older monochrome monitors have problem with white text on black
109 background. The new code can handle the reverse situation if the user
112 The following X Resources gives black text on white background using
113 Angband/Xaw. The other colors (2-15) isn't changed, since they're not
114 used on a monochrome monitor.
116 angband*color0: #ffffff
117 angband*color1: #000000
121 /* New resource names */
122 #define XtNstartRows "startRows"
123 #define XtNstartColumns "startColumns"
124 #define XtNminRows "minRows"
125 #define XtNminColumns "minColumns"
126 #define XtNmaxRows "maxRows"
127 #define XtNmaxColumns "maxColumns"
128 #define XtNinternalBorder "internalBorder"
129 #define XtNcolor0 "color0"
130 #define XtNcolor1 "color1"
131 #define XtNcolor2 "color2"
132 #define XtNcolor3 "color3"
133 #define XtNcolor4 "color4"
134 #define XtNcolor5 "color5"
135 #define XtNcolor6 "color6"
136 #define XtNcolor7 "color7"
137 #define XtNcolor8 "color8"
138 #define XtNcolor9 "color9"
139 #define XtNcolor10 "color10"
140 #define XtNcolor11 "color11"
141 #define XtNcolor12 "color12"
142 #define XtNcolor13 "color13"
143 #define XtNcolor14 "color14"
144 #define XtNcolor15 "color15"
145 #define XtNredrawCallback "redrawCallback"
147 /* External definitions */
149 #define NUM_COLORS 16
151 /* C Widget type definition */
153 typedef struct AngbandRec *AngbandWidget;
155 /* C Widget class type definition */
157 typedef struct AngbandClassRec *AngbandWidgetClass;
161 * New fields for the Angband widget record
166 /* Settable resources */
175 Pixel color[NUM_COLORS];
176 XtCallbackList redraw_callbacks;
180 Dimension fontheight;
182 Dimension fontascent;
183 GC gc[NUM_COLORS+1]; /* Includes a special 'xor' color */
189 * Full instance record declaration
192 typedef struct AngbandRec AngbandRec;
203 * New fields for the Angband widget class record
206 typedef struct AngbandClassPart AngbandClassPart;
208 struct AngbandClassPart
215 * Full class record declaration
218 typedef struct AngbandClassRec AngbandClassRec;
220 struct AngbandClassRec
222 CoreClassPart core_class;
223 SimpleClassPart simple_class;
224 AngbandClassPart angband_class;
229 /* Angband widget, Created by Torbj
\vn Lindgren (tl@cd.chalmers.se) */
232 * Note that it isn't as self-contained as it really should be,
233 * originally everything was output to a Pixmap which was later copied
234 * to the screen when necessary. I had to abandon that idea since
235 * Pixmaps creates big performance problems for some really old X
236 * terminals (such as 3/50's running Xkernel).
241 * The default colors used is based on the ones used in main-mac.c.
242 * The main difference is that they are gamma corrected for a gamma of
243 * 1.6. MacOS do gamma correction afterwards, but X uses raw
244 * colors. The Gamma of most color screens are about 1.5 - 1.7.
245 * Color 12 was later changed a bit so that it didn't look as similar
249 #define offset(field) XtOffsetOf(AngbandRec, angband.field)
252 * Fallback resources for Angband widget
254 static XtResource resources[] =
256 { XtNstartRows, XtCValue, XtRInt, sizeof(int),
257 offset(start_rows), XtRImmediate, (XtPointer) 24 },
258 { XtNstartColumns, XtCValue, XtRInt, sizeof(int),
259 offset(start_columns), XtRImmediate, (XtPointer) 80 },
260 { XtNminRows, XtCValue, XtRInt, sizeof(int),
261 offset(min_rows), XtRImmediate, (XtPointer) 1 },
262 { XtNminColumns, XtCValue, XtRInt, sizeof(int),
263 offset(min_columns), XtRImmediate, (XtPointer) 1 },
264 { XtNmaxRows, XtCValue, XtRInt, sizeof(int),
265 offset(max_rows), XtRImmediate, (XtPointer) 24 },
266 { XtNmaxColumns, XtCValue, XtRInt, sizeof(int),
267 offset(max_columns), XtRImmediate, (XtPointer) 80 },
268 { XtNinternalBorder, XtCValue, XtRInt, sizeof(int),
269 offset(internal_border), XtRImmediate, (XtPointer) 2 },
270 { XtNfont, XtCFont, XtRString, sizeof(char *),
271 offset(font), XtRString, "9x15" },
272 { XtNcolor0, XtCColor, XtRPixel, sizeof(Pixel),
273 offset(color[0]), XtRString, "black" },
274 { XtNcolor1, XtCColor, XtRPixel, sizeof(Pixel),
275 offset(color[1]), XtRString, "white" },
276 { XtNcolor2, XtCColor, XtRPixel, sizeof(Pixel),
277 offset(color[2]), XtRString, "#d7d7d7" },
278 { XtNcolor3, XtCColor, XtRPixel, sizeof(Pixel),
279 offset(color[3]), XtRString, "#ff9200" },
280 { XtNcolor4, XtCColor, XtRPixel, sizeof(Pixel),
281 offset(color[4]), XtRString, "#ff0000" },
282 { XtNcolor5, XtCColor, XtRPixel, sizeof(Pixel),
283 offset(color[5]), XtRString, "#00cd00" },
284 { XtNcolor6, XtCColor, XtRPixel, sizeof(Pixel),
285 offset(color[6]), XtRString, "#0000fe" },
286 { XtNcolor7, XtCColor, XtRPixel, sizeof(Pixel),
287 offset(color[7]), XtRString, "#c86400" },
288 { XtNcolor8, XtCColor, XtRPixel, sizeof(Pixel),
289 offset(color[8]), XtRString, "#a3a3a3" },
290 { XtNcolor9, XtCColor, XtRPixel, sizeof(Pixel),
291 offset(color[9]), XtRString, "#ebebeb" },
292 { XtNcolor10, XtCColor, XtRPixel, sizeof(Pixel),
293 offset(color[10]), XtRString, "#a500ff" },
294 { XtNcolor11, XtCColor, XtRPixel, sizeof(Pixel),
295 offset(color[11]), XtRString, "#fffd00" },
296 { XtNcolor12, XtCColor, XtRPixel, sizeof(Pixel),
297 offset(color[12]), XtRString, "#ff00bc" },
298 { XtNcolor13, XtCColor, XtRPixel, sizeof(Pixel),
299 offset(color[13]), XtRString, "#00ff00" },
300 { XtNcolor14, XtCColor, XtRPixel, sizeof(Pixel),
301 offset(color[14]), XtRString, "#00c8ff" },
302 { XtNcolor15, XtCColor, XtRPixel, sizeof(Pixel),
303 offset(color[15]), XtRString, "#ffcc80" },
305 { XtNredrawCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
306 offset(redraw_callbacks), XtRCallback, (XtPointer)NULL }
311 /* Forward declarations for Widget functions */
312 static void Initialize(AngbandWidget request, AngbandWidget new);
313 static void Redisplay(AngbandWidget w, XEvent *event, Region region);
314 static Boolean SetValues(AngbandWidget current, AngbandWidget request,
315 AngbandWidget new, ArgList args, Cardinal *num_args);
316 static void Destroy(AngbandWidget widget);
318 /* Forward declaration for internal functions */
319 static void calculateSizeHints(AngbandWidget new);
320 static XFontStruct *getFont(AngbandWidget widget,
321 String font, Boolean fallback);
324 /* Class record constanst */
325 AngbandClassRec angbandClassRec =
328 /* Core class fields initialization */
329 #define superclass (&simpleClassRec)
330 /* superclass */ (WidgetClass) superclass,
331 /* class_name */ "Angband",
332 /* widget_size */ sizeof(AngbandRec),
333 /* class_initialize */ NULL,
334 /* class_part_initialize*/ NULL,
335 /* class_inited */ FALSE,
336 /* initialize */ (XtInitProc) Initialize,
337 /* initialize_hook */ NULL,
338 /* realize */ XtInheritRealize,
341 /* resources */ resources,
342 /* num_resources */ XtNumber(resources),
343 /* xrm_class */ NULLQUARK,
344 /* compress_motion */ TRUE,
345 /* compress_exposure */ XtExposeCompressMultiple,
346 /* compress_enterleave */ TRUE,
347 /* visible_interest */ FALSE,
348 /* destroy */ (XtWidgetProc) Destroy,
350 /* expose */ (XtExposeProc) Redisplay,
351 /* set_values */ (XtSetValuesFunc) SetValues,
352 /* set_values_hook */ NULL,
353 /* set_values_almost */ XtInheritSetValuesAlmost,
354 /* get_values_hook */ NULL,
355 /* accept_focus */ NULL,
356 /* version */ XtVersion,
357 /* callback_private */ NULL,
359 /* query_geometry */ NULL,
360 /* display_accelerator */ XtInheritDisplayAccelerator,
363 /* Simple class fields initialization */
365 /* change_sensitive */ XtInheritChangeSensitive
367 /* Angband class fields initialization */
373 /* Class record pointer */
374 WidgetClass angbandWidgetClass = (WidgetClass) &angbandClassRec;
380 static void AngbandOutputText(AngbandWidget widget, int x, int y,
381 String txt, int len, int color)
383 /* Do nothing if the string is null */
387 /* Check the lenght, and fix it if it's below zero */
391 /* Figure out where to place the text */
392 y = y * widget->angband.fontheight + widget->angband.fontascent +
393 widget->angband.internal_border;
394 x = x * widget->angband.fontwidth + widget->angband.internal_border;
396 /* Place the string */
397 XDrawImageString (XtDisplay(widget), XtWindow(widget),
398 widget->angband.gc[color], x, y, txt, len);
401 static void AngbandClearArea(AngbandWidget widget,
402 int x, int y, int w, int h, int color)
404 /* Figure out which area to clear */
405 y = y * widget->angband.fontheight + widget->angband.internal_border;
406 x = x * widget->angband.fontwidth + widget->angband.internal_border;
409 XFillRectangle(XtDisplay(widget), XtWindow(widget),
410 widget->angband.gc[color],
411 x, y, widget->angband.fontwidth*w,
412 widget->angband.fontheight*h);
420 * Procedure Initialize() is called during the widget creation
421 * process. Initialize() load fonts and calculates window geometry.
422 * The request parameter is filled in by parents to this widget. The
423 * new parameter is the request parameter plus data filled in by this
424 * widget. All changes should be done to the new parameter.
426 static void Initialize(AngbandWidget request, AngbandWidget new)
429 int depth = DefaultDepthOfScreen(XtScreen((Widget) new));
430 TopLevelShellWidget parent =
431 (TopLevelShellWidget)XtParent((Widget) new);
434 /* Fix the background color */
435 new->core.background_pixel = new->angband.color[0];
437 /* Get some information about the font */
438 new->angband.fnt = getFont(new, new->angband.font, TRUE);
439 new->angband.fontheight = new->angband.fnt->ascent +
440 new->angband.fnt->descent;
441 new->angband.fontwidth = new->angband.fnt->max_bounds.width;
442 new->angband.fontascent = new->angband.fnt->ascent;
444 /* Create and initialize the graphics contexts */ /* GXset? */
445 gcv.font = new->angband.fnt->fid;
446 gcv.graphics_exposures = FALSE;
447 gcv.background = new->angband.color[0];
448 for (n = 0; n < NUM_COLORS; n++)
450 if (depth == 1 && n >= 1)
451 gcv.foreground = new->angband.color[1];
453 gcv.foreground = new->angband.color[n];
454 new->angband.gc[n] = XtGetGC((Widget)new, GCFont | GCForeground |
455 GCBackground | GCGraphicsExposures,
459 /* Create a special GC for highlighting */
460 gcv.foreground = BlackPixelOfScreen(XtScreen((Widget)new)) ^
461 WhitePixelOfScreen(XtScreen((Widget)new));
462 gcv.function = GXxor;
463 new->angband.gc[NUM_COLORS] = XtGetGC((Widget)new, GCFunction |
464 GCGraphicsExposures |
467 /* Calculate window geometry */
468 new->core.height = new->angband.start_rows * new->angband.fontheight +
469 2 * new->angband.internal_border;
470 new->core.width = new->angband.start_columns * new->angband.fontwidth +
471 2 * new->angband.internal_border;
473 /* We need to be able to resize the Widget if the user want's to
474 change font on the fly! */
475 parent->shell.allow_shell_resize = TRUE;
477 /* Calculates all the size hints */
478 calculateSizeHints(new);
482 * Procedure Destroy() is called during the destruction of the widget.
483 * Destroy() releases and frees GCs, frees the pixmaps and frees the
486 static void Destroy(AngbandWidget widget)
491 for (n = 0; n < NUM_COLORS+1; n++)
492 XtReleaseGC((Widget)widget, widget->angband.gc[n]);
495 XFreeFont(XtDisplay((Widget)widget), widget->angband.fnt);
499 * Procedure Redisplay() is called as the result of an Expose event.
500 * Use the redraw callback to do a full redraw
502 static void Redisplay(AngbandWidget widget, XEvent *event, Region region)
504 if (XtHasCallbacks((Widget)widget, XtNredrawCallback) == XtCallbackHasSome)
505 XtCallCallbacks((Widget)widget, XtNredrawCallback, NULL);
509 * Font, colors and internal_border can be changed on the fly.
510 * The entire widget is redrawn if any of those parameters change (all
511 * can potentially have effects that spans the whole widget).
513 static Boolean SetValues(AngbandWidget current, AngbandWidget request,
514 AngbandWidget new, ArgList args,
517 int depth = DefaultDepthOfScreen(XtScreen((Widget) new));
518 Boolean font_changed = FALSE;
519 Boolean border_changed = FALSE;
520 Boolean color_changed = FALSE;
526 if (current->angband.font != new->angband.font)
528 /* Check if the font exists */
529 new->angband.fnt = getFont(new, new->angband.font, FALSE);
531 /* The font didn't exist */
532 if (new->angband.fnt == NULL)
534 new->angband.fnt = current->angband.fnt;
535 new->angband.font = current->angband.font;
536 XtWarning("Couldn't find the request font!");
541 /* Free the old font */
542 XFreeFont(XtDisplay((Widget)new), current->angband.fnt);
543 /* Update font information */
544 new->angband.fontheight = new->angband.fnt->ascent +
545 new->angband.fnt->descent;
546 new->angband.fontwidth = new->angband.fnt->max_bounds.width;
547 new->angband.fontascent = new->angband.fnt->ascent;
551 /* Check all colors, if one or more has changed the redo all GC's */
552 for (n = 0; n < NUM_COLORS; n++)
553 if (current->angband.color[n] != new->angband.color[n])
554 color_changed = TRUE;
556 /* Change all GC's if color or font has changed */
557 if (color_changed || font_changed)
559 gcv.font = new->angband.fnt->fid;
560 gcv.graphics_exposures = FALSE;
561 gcv.background = new->angband.color[0];
564 for (n = 0; n < NUM_COLORS; n++)
566 if (depth == 1 && n >= 1)
567 gcv.foreground = new->angband.color[1];
569 gcv.foreground = new->angband.color[n];
570 /* Release the old GC */
571 XtReleaseGC((Widget)current, current->angband.gc[n]);
573 new->angband.gc[n] = XtGetGC((Widget)new, GCFont | GCForeground |
574 GCBackground | GCGraphicsExposures,
578 /* Replace the old XOR/highlighting GC */
579 gcv.foreground = BlackPixelOfScreen(XtScreen((Widget)new)) ^
580 WhitePixelOfScreen(XtScreen((Widget)new));
581 gcv.function = GXxor;
582 XtReleaseGC((Widget)current, current->angband.gc[NUM_COLORS]);
583 new->angband.gc[NUM_COLORS] = XtGetGC((Widget)new, GCFunction |
584 GCGraphicsExposures |
586 /* Fix the background color */
587 new->core.background_pixel = new->angband.color[0];
590 /* Check if internal border width has changed, used later */
591 if (current->angband.internal_border != new->angband.internal_border)
592 border_changed = TRUE;
595 /* If the font or the internal border has changed, all geometry
596 has to be recalculated */
597 if (font_changed || border_changed)
599 /* Change window size */
600 height = (current->core.height - 2 * current->angband.internal_border) /
601 current->angband.fontheight * new->angband.fontheight +
602 2 * current->angband.internal_border;
603 width = (current->core.width - 2 * current->angband.internal_border) /
604 current->angband.fontwidth * new->angband.fontwidth +
605 2 * new->angband.internal_border;
607 /* Get the new width */
608 if (XtMakeResizeRequest((Widget)new, width, height, NULL, NULL) ==
612 XtWarning("Size change denied!");
616 /* Recalculate size hints */
617 calculateSizeHints(new);
621 /* Tell it to redraw the widget if anything has changed */
622 return (font_changed || color_changed || border_changed);
626 * Calculate size hints
628 static void calculateSizeHints(AngbandWidget new)
630 TopLevelShellWidget parent =
631 (TopLevelShellWidget)XtParent((Widget) new);
633 /* Calculate minimum size */
634 parent->wm.size_hints.min_height =
635 new->angband.min_rows * new->angband.fontheight +
636 2 * new->angband.internal_border;
637 parent->wm.size_hints.min_width =
638 new->angband.min_columns * new->angband.fontwidth +
639 2 * new->angband.internal_border;
640 parent->wm.size_hints.flags |= PMinSize;
642 /* Calculate maximum size */
643 parent->wm.size_hints.max_height =
644 new->angband.max_rows * new->angband.fontheight +
645 2 * new->angband.internal_border;
646 parent->wm.size_hints.max_width =
647 new->angband.max_columns * new->angband.fontwidth +
648 2 * new->angband.internal_border;
649 parent->wm.size_hints.flags |= PMaxSize;
651 /* Calculate increment size */
652 parent->wm.size_hints.height_inc = new->angband.fontheight;
653 parent->wm.size_hints.width_inc = new->angband.fontwidth;
654 parent->wm.size_hints.flags |= PResizeInc;
656 /* Calculate base size */
657 parent->wm.base_height = 2 * new->angband.internal_border;
658 parent->wm.base_width = 2 * new->angband.internal_border;
659 parent->wm.size_hints.flags |= PBaseSize;
665 static XFontStruct *getFont(AngbandWidget widget,
666 String font, Boolean fallback)
668 Display *dpy = XtDisplay((Widget) widget);
670 XFontStruct *fnt = NULL;
672 if (!(fnt = XLoadQueryFont(dpy, font)) && fallback)
674 sprintf(buf, "Can't find the font \"%s\", trying fixed\n", font);
676 if (!(fnt = XLoadQueryFont(dpy, "fixed")))
677 XtError("Can't fint the font \"fixed\"!, bailing out\n");
685 /*** The non-widget code ****/
687 #ifndef IsModifierKey
690 * Keysym macros, used on Keysyms to test for classes of symbols
691 * These were stolen from one of the X11 header files
694 #define IsKeypadKey(keysym) \
695 (((unsigned)(keysym) >= XK_KP_Space) && ((unsigned)(keysym) <= XK_KP_Equal))
697 #define IsCursorKey(keysym) \
698 (((unsigned)(keysym) >= XK_Home) && ((unsigned)(keysym) < XK_Select))
700 #define IsPFKey(keysym) \
701 (((unsigned)(keysym) >= XK_KP_F1) && ((unsigned)(keysym) <= XK_KP_F4))
703 #define IsFunctionKey(keysym) \
704 (((unsigned)(keysym) >= XK_F1) && ((unsigned)(keysym) <= XK_F35))
706 #define IsMiscFunctionKey(keysym) \
707 (((unsigned)(keysym) >= XK_Select) && ((unsigned)(keysym) < XK_KP_Space))
709 #define IsModifierKey(keysym) \
710 (((unsigned)(keysym) >= XK_Shift_L) && ((unsigned)(keysym) <= XK_Hyper_R))
716 * Checks if the keysym is a special key or a normal key
717 * Assume that XK_MISCELLANY keysyms are special
719 #define IsSpecialKey(keysym) \
720 ((unsigned)(keysym) >= 0xFF00)
725 * Maximum number of windows XXX XXX XXX XXX
727 #define MAX_TERM_DATA 8
730 * Number of fallback resources per window
732 #define TERM_FALLBACKS 6
735 * Number of windows with special fallback resources
737 #define SPECIAL_FALLBACKS 3
742 typedef struct term_data term_data;
745 * A structure for each "term"
751 AngbandWidget widget;
755 * An array of term_data's
757 static term_data data[MAX_TERM_DATA];
759 char *termNames[MAX_TERM_DATA] =
771 Arg specialArgs[TERM_FALLBACKS][SPECIAL_FALLBACKS] =
773 /* The main screen */
776 { XtNstartColumns, 80},
778 { XtNminColumns, 80},
783 /* The "mirror" window */
786 { XtNstartColumns, 80},
793 /* The "recall" window */
796 { XtNstartColumns, 80},
804 Arg defaultArgs[TERM_FALLBACKS] =
807 { XtNstartColumns, 80},
816 * The application context
821 * User changable information about widgets
823 static String fallback[] =
825 "Angband.angband.iconName: Angband",
826 "Angband.angband.title: Angband",
827 "Angband.mirror.iconName: Mirror",
828 "Angband.mirror.title: Mirror",
829 "Angband.recall.iconName: Recall",
830 "Angband.recall.title: Recall",
831 "Angband.choice.iconName: Choice",
832 "Angband.choice.title: Choice",
833 "Angband.term-4.iconName: Term 4",
834 "Angband.term-4.title: Term 4",
835 "Angband.term-5.iconName: Term 5",
836 "Angband.term-5.title: Term 5",
837 "Angband.term-6.iconName: Term 6",
838 "Angband.term-6.title: Term 6",
839 "Angband.term-7.iconName: Term 7",
840 "Angband.term-7.title: Term 7",
849 static void react_redraw(Widget widget,
850 XtPointer client_data, XtPointer call_data)
852 term_data *old_td = (term_data*)(Term->data);
853 term_data *td = (term_data*)client_data;
855 /* Activate the proper Term */
856 Term_activate(&td->t);
858 /* Request a redraw */
861 /* Activate the old Term */
862 Term_activate(&old_td->t);
866 * Process a keypress event
868 static void react_keypress(XKeyEvent *ev)
870 int i, n, mc, ms, mo, mx;
878 /* Check for "normal" keypresses */
879 n = XLookupString(ev, buf, 125, &ks, NULL);
884 /* Extract four "modifier flags" */
885 mc = (ev->state & ControlMask) ? TRUE : FALSE;
886 ms = (ev->state & ShiftMask) ? TRUE : FALSE;
887 mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
888 mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
890 /* Hack -- Ignore "modifier keys" */
891 if (IsModifierKey(ks)) return;
893 /* Normal keys with no modifiers */
894 if (n && !mo && !mx && !IsSpecialKey(ks))
896 /* Enqueue the normal key(s) */
897 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
903 /* Handle a few standard keys */
907 Term_keypress(ESCAPE); return;
910 Term_keypress('\r'); return;
913 Term_keypress('\t'); return;
917 Term_keypress('\010'); return;
920 /* Hack -- Use the KeySym */
923 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
924 mc ? "N" : "", ms ? "S" : "",
925 mo ? "O" : "", mx ? "M" : "",
926 (unsigned long)(ks), 13);
929 /* Hack -- Use the Keycode */
932 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
933 mc ? "N" : "", ms ? "S" : "",
934 mo ? "O" : "", mx ? "M" : "",
938 /* Enqueue the "fake" string */
939 for (i = 0; msg[i]; i++)
940 Term_keypress(msg[i]);
942 /* Hack -- dump an "extra" string */
945 /* Start the "extra" string */
948 /* Enqueue the "real" string */
949 for (i = 0; buf[i]; i++)
950 Term_keypress(buf[i]);
952 /* End the "extra" string */
958 static void handle_event (Widget widget, XtPointer client_data, XEvent *event,
959 Boolean *continue_to_dispatch)
961 term_data *old_td = (term_data*)(Term->data);
962 term_data *td = (term_data *)client_data;
964 /* Continue to process the event by default */
965 *continue_to_dispatch = TRUE;
967 /* Activate the Term */
968 Term_activate(&td->t);
973 react_keypress(&(event->xkey));
974 *continue_to_dispatch = FALSE; /* We took care of the event */
978 break; /* Huh? Shouldn't happen! */
981 /* Activate the old term */
982 Term_activate(&old_td->t);
989 * Process an event (or just check for one)
991 errr CheckEvent(bool wait)
995 /* No events ready, and told to just check */
996 if (!wait && !XtAppPending(appcon)) return 1;
1001 XtAppNextEvent(appcon, &event);
1002 XtDispatchEvent(&event);
1003 if (!XtAppPending(appcon)) break;
1011 * Handle a "special request"
1013 static errr Term_xtra_xaw(int n, int v)
1017 /* Handle a subset of the legal requests */
1021 case TERM_XTRA_NOISE:
1022 XBell(XtDisplay((Widget)data[0].widget), 100);
1025 /* Flush the output */
1026 case TERM_XTRA_FRESH:
1027 XFlush(XtDisplay((Widget)data[0].widget));
1028 /* Nonblock event-check so the flushed events can be showed */
1032 /* Process random events */
1033 case TERM_XTRA_BORED:
1034 return (CheckEvent(0));
1036 /* Process events */
1037 case TERM_XTRA_EVENT:
1038 return (CheckEvent(v));
1041 case TERM_XTRA_FLUSH:
1042 while (!CheckEvent(FALSE));
1046 case TERM_XTRA_DELAY:
1050 /* Clear the window */
1051 case TERM_XTRA_CLEAR:
1052 for (i=0; i<MAX_TERM_DATA; i++) {
1053 if (Term == &data[i].t)
1054 XClearWindow(XtDisplay((Widget)data[i].widget),
1055 XtWindow((Widget)data[i].widget));
1067 * Erase a number of characters
1069 static errr Term_wipe_xaw(int x, int y, int n)
1071 term_data *td = (term_data*)(Term->data);
1073 /* Erase using color 0 */
1074 AngbandClearArea(td->widget, x, y, n, 1, 0);
1083 * Draw the cursor (XXX by hiliting)
1085 static errr Term_curs_xaw(int x, int y)
1087 term_data *td = (term_data*)(Term->data);
1089 /* Hilite the cursor character */
1090 AngbandClearArea(td->widget, x, y, 1, 1, COLOR_XOR);
1098 * Draw a number of characters
1100 static errr Term_text_xaw(int x, int y, int n, byte a, concptr s)
1102 term_data *td = (term_data*)(Term->data);
1105 AngbandOutputText(td->widget, x, y, (String)s, n, (a & 0x0F));
1115 static void term_raise(term_data win)
1117 Widget widget = (Widget)win.widget;
1119 XRaiseWindow(XtDisplay(XtParent(widget)), XtWindow(XtParent(widget)));
1124 * Initialize a term_data
1126 static errr term_data_init(term_data *td, Widget topLevel,
1127 int key_buf, String name,
1128 ArgList widget_arg, Cardinal widget_arg_no)
1133 /* Create the shell widget */
1134 parent = XtCreatePopupShell(name, topLevelShellWidgetClass, topLevel,
1137 /* Create the interior widget */
1138 td->widget = (AngbandWidget)
1139 XtCreateManagedWidget (name, angbandWidgetClass,
1140 parent, widget_arg, widget_arg_no);
1142 /* Initialize the term (full size) */
1143 term_init(t, 80, 24, key_buf);
1145 /* Use a "soft" cursor */
1146 t->soft_cursor = TRUE;
1148 /* Erase with "white space" */
1149 t->attr_blank = TERM_WHITE;
1150 t->char_blank = ' ';
1153 t->xtra_hook = Term_xtra_xaw;
1154 t->curs_hook = Term_curs_xaw;
1155 t->wipe_hook = Term_wipe_xaw;
1156 t->text_hook = Term_text_xaw;
1161 /* Register the keypress event handler */
1162 XtAddEventHandler((Widget)td->widget, KeyPressMask,
1163 False, (XtEventHandler) handle_event, td);
1165 /* Redraw callback */
1166 XtAddCallback((Widget)td->widget, XtNredrawCallback,
1169 /* Realize the widget */
1170 XtRealizeWidget(parent);
1172 /* Make it visible */
1173 XtPopup(parent, XtGrabNone);
1175 /* Activate (important) */
1183 * Initialization function for an X Athena Widget module to Angband
1185 * Mega-Hack -- we are not given the actual "argc" and "argv" from
1186 * the main program, so we fake one. Thus, we are unable to parse
1187 * any "display" requests for external devices. This is okay, since
1188 * we need to verify the display anyway, to work with "main.c".
1198 /* One fake argument */
1201 /* Save the program name */
1208 /* Attempt to open the local display */
1209 dpy = XOpenDisplay("");
1211 /* Failure -- assume no X11 available */
1212 if (!dpy) return (-1);
1214 /* Close the local display */
1219 /* Support locale processing */
1220 XtSetLanguageProc(NULL, NULL, NULL);
1223 /* Initialize the toolkit */
1224 topLevel = XtAppInitialize (&appcon, "Angband", NULL, 0, &argc, argv,
1227 /* Initialize the windows */
1228 for (i=0; i<MAX_TERM_DATA; i++) {
1229 term_data_init (&data[i], topLevel, 1024, termNames[i],
1230 i<SPECIAL_FALLBACKS ? specialArgs[i] : defaultArgs,
1232 angband_term[i] = Term;
1235 /* Activate the "Angband" window screen */
1236 Term_activate(&data[0].t);
1238 /* Raise the "Angband" window */
1239 term_raise(data[0]);