Re: [AD] allegro_message under X |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Ok, here is a patch that implements what I have proposed. Basically,
allegro_message under X now tries to use kdialog, gdialog and xmessage, in
that order. If none is available, it falls back to stdout.
This was more complicated than I expected, because the message to display must
be put in a form that won't confuse the shell (think metacharacters). Right
now, I put the message between double quotes, and escape with a backslash the
characters (&) (!) (") and (\). I don't know if this is enough.
All in all, the patch seems to work, but it's not perfect:
1. the demo's ending message looks like crap with kdialog :-). This is
because lines are broken twice (explicitly by the demo, and then
automatically by kdialog). Not much can be done here.
2. fullscreen does matter after all. When leaving graphics mode with
set_gfx_mode(GFX_TEXT), the old window is not hidden (a black rectangle
remains). When the graphic mode was fullscreen, the rectangle obscures the
message box...
I suppose the window is needed for keyboard input, but maybe it could be
hidden by set_gfx_mode(GFX_TEXT), or made very small... ?
--
Julien Cugnière
--- src/x/xsystem.c.old 2004-10-23 17:42:29.965884952 +0200
+++ src/x/xsystem.c 2004-10-23 18:21:54.074485816 +0200
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
+#include <sys/wait.h>
#include <unistd.h>
@@ -37,6 +38,7 @@
static void _xwin_sysdrv_exit(void);
static void _xwin_sysdrv_set_window_title(AL_CONST char *name);
static int _xwin_sysdrv_set_close_button_callback(void (*proc)(void));
+static void _xwin_sysdrv_message(AL_CONST char *msg);
static int _xwin_sysdrv_display_switch_mode(int mode);
static int _xwin_sysdrv_desktop_color_depth(void);
static int _xwin_sysdrv_get_desktop_resolution(int *width, int *height);
@@ -65,7 +67,7 @@
_unix_find_resource,
_xwin_sysdrv_set_window_title,
_xwin_sysdrv_set_close_button_callback,
- NULL, /* message */
+ _xwin_sysdrv_message,
NULL, /* assert */
NULL, /* save_console_state */
NULL, /* restore_console_state */
@@ -274,6 +276,77 @@
+/* _xwin_sysdrv_message:
+ * Displays a message. There is no universal MessageBox() function in X11,
+ * so this function tries to use the common command line tools that do the
+ * same. Failling that, it falls back to stdout.
+ */
+static void _xwin_sysdrv_message(AL_CONST char *msg)
+{
+ /* The /dev/null redirection prevents sh from displaying error messages as
+ * we look for a command that works. */
+ AL_CONST char *commands[] =
+ {
+ "kdialog --msgbox \"%s\" 2> /dev/null",
+ "gdialog --msgbox \"%s\" 0 0 2> /dev/null",
+ "xmessage -center \"%s\" 2> /dev/null",
+ NULL
+ };
+
+ char *command;
+ char *text, *in, *out, *msg2;
+ int i;
+ int text_length = 0;
+
+ /* convert the command to ascii, and escape some characters needing it */
+ msg2 = malloc(ALLEGRO_MESSAGE_SIZE);
+ uconvert(msg, U_CURRENT, msg2, U_ASCII_CP, ALLEGRO_MESSAGE_SIZE);
+
+ text = malloc(ALLEGRO_MESSAGE_SIZE);
+ in = msg2;
+ out = text;
+ for (in = msg2; *in != 0; in++) {
+ if (out - text >= ALLEGRO_MESSAGE_SIZE - 3)
+ break;
+
+ switch (*in) {
+ case '&':
+ case '!':
+ case '"':
+ case '\\':
+ *out++ = '\\';
+ *out++ = *in;
+ break;
+
+ default:
+ *out++ = *in;
+ }
+ }
+ *out = 0;
+ text_length = out - text;
+
+ /* try to find a working command */
+ for (i = 0; commands[i] != NULL; i++) {
+ int ret;
+ command = malloc(strlen(commands[i]) + text_length + 1);
+ sprintf(command, commands[i], text);
+ ret = system(command);
+ free(command);
+ if (WEXITSTATUS(ret) == 0)
+ break;
+ }
+
+ if (commands[i] == NULL) {
+ /* no command worked, so fall back to stdout */
+ fputs(msg, stdout);
+ }
+
+ free(msg2);
+ free(text);
+}
+
+
+
/* _xwin_sysdrv_gfx_drivers:
* Get the list of graphics drivers.
*/