From: Carl Worth Date: Thu, 19 Jun 2003 11:40:34 +0000 (+0000) Subject: Fixed messages and scrolling X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=85953690f1a640d11af15017628df86ab6f03e56;p=grrobot Fixed messages and scrolling --- diff --git a/ChangeLog b/ChangeLog index e69de29..84d46ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -0,0 +1,10 @@ +2003-06-19 Carl Worth + + * src/grrobot.c (grr_game_print): Centralized game message + printing. + (grr_game_read_notices): New formatted messages for all notice + types. + (grr_game_read_notices): Fancy incremental updates for move + messages. + (grr_game_print): Fixed (finally) scrolling of messages. + diff --git a/configure.in b/configure.in index 732a07c..d7d827c 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_SUBST(GRROBOT_VERSION) dnl =========================================================================== -AM_INIT_AUTOMAKE(xsvg, $GRROBOT_VERSION) +AM_INIT_AUTOMAKE(grrobot, $GRROBOT_VERSION) AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE @@ -27,4 +27,5 @@ dnl =========================================================================== AC_OUTPUT([ Makefile src/Makefile +src/svg/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index c37b50f..1ec102f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS = . svg + bin_PROGRAMS = grrobot grrobot_SOURCES = \ @@ -5,11 +7,9 @@ grrobot_SOURCES = \ args.h \ grrobot.c \ grr_board_view.c \ - grr_board_view.h + grr_board_view.h \ + grr_util.c \ + grr_util.h -INCLUDES = $(GRROBOT_CFLAGS) +INCLUDES = $(GRROBOT_CFLAGS) -DGRR_ICON_DIR=\"$(pkgdatadir)\" LDFLAGS = $(GRROBOT_LIBS) - - - - diff --git a/src/grr_board_view.c b/src/grr_board_view.c index c4cf316..4a3b733 100644 --- a/src/grr_board_view.c +++ b/src/grr_board_view.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -38,6 +37,7 @@ #include #include "grr_board_view.h" +#include "grr_util.h" #define SCROLL_DELAY_LENGTH 300 #define GRR_BOARD_VIEW_DEFAULT_SIZE 100 @@ -78,13 +78,6 @@ /* Forward declarations */ -static int -grr_sprintf_alloc (char **str, const char *fmt, ...); - -static int -grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap); - - static void grr_board_view_class_init (grr_board_view_class_t *klass); static void grr_board_view_init (grr_board_view_t *view); static void grr_board_view_destroy (GtkObject *object); @@ -761,46 +754,3 @@ grr_board_view_update (grr_board_view_t *view) gtk_widget_queue_draw (GTK_WIDGET (view)); } -static int -grr_sprintf_alloc (char **str, const char *fmt, ...) -{ - int ret; - va_list ap; - - va_start(ap, fmt); - ret = grr_sprintf_alloc_va (str, fmt, ap); - va_end(ap); - - return ret; -} - -/* ripped more or less straight out of PRINTF(3) */ -static int -grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap) -{ - char *new_str; - /* Guess we need no more than 100 bytes. */ - int n, size = 100; - - if ((*str = malloc (size)) == NULL) - return -1; - while (1) { - /* Try to print in the allocated space. */ - n = vsnprintf (*str, size, fmt, ap); - /* If that worked, return the size. */ - if (n > -1 && n < size) - return n; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - size = n+1; /* precisely what is needed */ - else /* glibc 2.0 */ - size *= 2; /* twice the old size */ - new_str = realloc(*str, size); - if (new_str == NULL) { - free(*str); - *str = NULL; - return -1; - } - *str = new_str; - } -} diff --git a/src/grr_icon.c b/src/grr_icon.c new file mode 100644 index 0000000..999f2a6 --- /dev/null +++ b/src/grr_icon.c @@ -0,0 +1,157 @@ +/* grrobot - Ricochet Robot using GTK+ and Xr + * + * Copyright © 2003 Carl Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Carl Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Carl Worth + */ + +#include "grr_icon.h" +#include "grr_icon_svg.h" + +struct { + int type; + char *name; + char *svg; +} icons[] = { + { RR_ROBOT_BLUE, + "robot_blue", GRR_ICON_SVG_ROBOT_BLUE }, + { RR_ROBOT_GREEN, + "robot_green", GRR_ICON_SVG_ROBOT_GREEN }, + { RR_ROBOT_RED, + "robot_red", GRR_ICON_SVG_ROBOT_RED }, + { RR_ROBOT_YELLOW, + "robot_yellow", GRR_ICON_SVG_ROBOT_YELLOW }, + + { RR_TARGET_BLUE_CIRCLE, + "target_blue_circle", GRR_ICON_SVG_TARGET_BLUE_CIRCLE }, + { RR_TARGET_BLUE_OCTAGON, + "target_blue_octagon", GRR_ICON_SVG_TARGET_BLUE_OCTAGON }, + { RR_TARGET_BLUE_SQUARE, + "target_blue_square", GRR_ICON_SVG_TARGET_BLUE_SQUARE }, + { RR_TARGET_BLUE_TRIANGLE, + "target_blue_triangle", GRR_ICON_SVG_TARGET_BLUE_TRIANGLE }, + + { RR_TARGET_GREEN_CIRCLE, + "target_green_circle", GRR_ICON_SVG_TARGET_GREEN_CIRCLE }, + { RR_TARGET_GREEN_OCTAGON, + "target_green_octagon", GRR_ICON_SVG_TARGET_GREEN_OCTAGON }, + { RR_TARGET_GREEN_SQUARE, + "target_green_square", GRR_ICON_SVG_TARGET_GREEN_SQUARE }, + { RR_TARGET_GREEN_TRIANGLE, + "target_green_triangle", GRR_ICON_SVG_TARGET_GREEN_TRIANGLE }, + + { RR_TARGET_RED_CIRCLE, + "target_red_circle", GRR_ICON_SVG_TARGET_RED_CIRCLE }, + { RR_TARGET_RED_OCTAGON, + "target_red_octagon", GRR_ICON_SVG_TARGET_RED_OCTAGON }, + { RR_TARGET_RED_SQUARE, + "target_red_square", GRR_ICON_SVG_TARGET_RED_SQUARE }, + { RR_TARGET_RED_TRIANGLE, + "target_red_triangle", GRR_ICON_SVG_TARGET_RED_TRIANGLE }, + + { RR_TARGET_YELLOW_CIRCLE, + "target_yellow_circle", GRR_ICON_SVG_TARGET_YELLOW_CIRCLE }, + { RR_TARGET_YELLOW_OCTAGON, + "target_yellow_octagon", GRR_ICON_SVG_TARGET_YELLOW_OCTAGON }, + { RR_TARGET_YELLOW_SQUARE, + "target_yellow_square", GRR_ICON_SVG_TARGET_YELLOW_SQUARE }, + { RR_TARGET_YELLOW_TRIANGLE, + "target_yellow_triangle", GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE }, + + { RR_TARGET_WHIRL, + "whirl", GRR_ICON_SVG_TARGET_WHIRL }, + + { RR_WALL_ABOVE, + "wall", GRR_ICON_SVG_WALL }, + + { RR_CELL, + "cell", GRR_ICON_SVG_CELL } +}; + +typedef struct grr_icon { + xsvg_t *xsvg; +} grr_icon_t; + +grr_icon_t * +grr_icon_create (char *name) +{ + grr_icon *icon; + + icon = malloc (sizeof (grr_icon_t)); + if (icon == NULL) + return NULL; + + _grr_icon_init (icon, name); + + return icon; +} + +static rr_status_t +_grr_icon_init (grr_icon_t *icon, char *name) +{ + xsvg_status_t status; + char *file, *buf; + + status = xsvg_create (&icon->xsvg); + if (status) + return RR_STATUS_NO_MEMORY; + + file = grr_icon_find_file (name); + + if (file) { + status = xsvg_parse_file (icon->xsvg, file); + if (status == XSVG_STATUS_SUCCESS) { + free (file); + return RR_STATUS_SUCCESS; + } + fprintf (stderr, "Error parsing SVG icon: %s\n", file); + free (file); + } + + buf = grr_icon_find_buffer (name); + status = xsvg_parse_buffer (icon->xsvg, buf, strlen (buf)); + if (status) { + fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name); + return RR_STATUS_PARSE_ERROR; + } + + return RR_STATUS_SUCCESS; +} + +/* XXX: This could be made more interesting, (eg. search in ~/.grrobot + or something). */ +static char * +_grr_icon_find_file (char *name) +{ + int err; + char *file; + struct stat stat_buf; + + rr_string_sprintf_alloc (&file, "%s/%s", GRR_ICON_DIR, name); + if (file == NULL) + return NULL; + + err = stat (file, &stat_buf); + if (err == 0 && S_ISREG (state.st_mode)) + return (file); + free (file); +} diff --git a/src/grr_icon.h b/src/grr_icon.h new file mode 100644 index 0000000..5a8951c --- /dev/null +++ b/src/grr_icon.h @@ -0,0 +1,126 @@ +/* grrobot - Ricochet Robot using GTK+ and Xr + * + * Copyright © 2003 Carl Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Carl Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Carl Worth + */ + +#ifndef GRR_ICON_H +#define GRR_ICON_H + +typedef struct grr_icon { + xsvg_t *xsvg; +} grr_icon_t; + +grr_icon_t * +grr_icon_create (char *name) +{ + grr_icon *icon; + + icon = malloc (sizeof (grr_icon_t)); + if (icon == NULL) + return NULL; + + _grr_icon_init (icon, name); + + return icon; +} + +static rr_status_t +_grr_icon_init (grr_icon_t *icon, char *name) +{ + xsvg_status_t status; + char *file, *buf; + + status = xsvg_create (&icon->xsvg); + if (status) + return RR_STATUS_NO_MEMORY; + + file = grr_icon_find_file (name); + + if (file) { + status = xsvg_parse_file (icon->xsvg, file); + if (status == XSVG_STATUS_SUCCESS) { + free (file); + return RR_STATUS_SUCCESS; + } + fprintf (stderr, "Error parsing SVG icon: %s\n", file); + free (file); + } + + buf = grr_icon_find_buffer (name); + status = xsvg_parse_buffer (icon->xsvg, buf, strlen (buf)); + if (status) { + fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name); + return RR_STATUS_PARSE_ERROR; + } + + return RR_STATUS_SUCCESS; +} + +/* XXX: This could be made more interesting, (eg. search in ~/.grrobot + or something). */ +static char * +_grr_icon_find_file (char *name) +{ + int err; + char *file; + struct stat stat_buf; + + rr_string_sprintf_alloc (&file, "%s/%s", GRR_ICON_DIR, name); + if (file == NULL) + return NULL; + + err = stat (file, &stat_buf); + if (err == 0 && S_ISREG (state.st_mode)) + return (file); + free (file); +} + +extern char *GRR_ROBOT_BLUE_SVG; +extern char *GRR_ROBOT_GREEN_SVG; +extern char *GRR_ROBOT_RED_SVG; +extern char *GRR_ROBOT_YELLOW_SVG; + +extern char *GRR_TARGET_BLUE_CIRCLE_SVG; +extern char *GRR_TARGET_GREEN_CIRCLE_SVG; +extern char *GRR_TARGET_RED_CIRCLE_SVG; +extern char *GRR_TARGET_YELLOW_CIRCLE_SVG; + +extern char *GRR_TARGET_BLUE_OCTAGON_SVG; +extern char *GRR_TARGET_GREEN_OCTAGON_SVG; +extern char *GRR_TARGET_RED_OCTAGON_SVG; +extern char *GRR_TARGET_YELLOW_OCTAGON_SVG; + +extern char *GRR_TARGET_BLUE_SQUARE_SVG; +extern char *GRR_TARGET_GREEN_SQUARE_SVG; +extern char *GRR_TARGET_RED_SQUARE_SVG; +extern char *GRR_TARGET_YELLOW_SQUARE_SVG; + +extern char *GRR_TARGET_BLUE_TRIANGLE_SVG; +extern char *GRR_TARGET_GREEN_TRIANGLE_SVG; +extern char *GRR_TARGET_RED_TRIANGLE_SVG; +extern char *GRR_TARGET_YELLOW_TRIANGLE_SVG; + +extern char *GRR_TARGET_WHIRL_SVG; + +#endif diff --git a/src/grr_util.c b/src/grr_util.c new file mode 100644 index 0000000..0c1e343 --- /dev/null +++ b/src/grr_util.c @@ -0,0 +1,77 @@ +/* grr_board_view - GTK+ widget for displaying an rr_board + * + * Copyright © 2003 Carl Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Carl Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Carl Worth + */ + +#include +#include +#include + +#include "grr_util.h" + +int +grr_sprintf_alloc (char **str, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = grr_sprintf_alloc_va (str, fmt, ap); + va_end (ap); + + return ret; +} + +/* ripped more or less straight out of PRINTF(3) */ +int +grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap) +{ + char *new_str; + /* Guess we need no more than 100 bytes. */ + int n, size = 100; + + if ((*str = malloc (size)) == NULL) + return -1; + while (1) { + /* Try to print in the allocated space. */ + n = vsnprintf (*str, size, fmt, ap); + /* If that worked, return the size. */ + if (n > -1 && n < size) + return n; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + new_str = realloc(*str, size); + if (new_str == NULL) { + free(*str); + *str = NULL; + return -1; + } + *str = new_str; + } +} + + diff --git a/src/grr_util.h b/src/grr_util.h new file mode 100644 index 0000000..3f6f938 --- /dev/null +++ b/src/grr_util.h @@ -0,0 +1,41 @@ +/* grr_board_view - GTK+ widget for displaying an rr_board + * + * Copyright © 2003 Carl Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Carl Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Carl Worth + */ + +#ifndef GRR_UTIL_H +#define GRR_UTIL_H + +#include +#include + +int +grr_sprintf_alloc (char **str, const char *fmt, ...); + +int +grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap); + +#endif + + diff --git a/src/grrobot.c b/src/grrobot.c index b7433ca..1a8d665 100644 --- a/src/grrobot.c +++ b/src/grrobot.c @@ -30,9 +30,12 @@ #include #include +#include + #include #include "grr_board_view.h" +#include "grr_util.h" #include "args.h" typedef struct grr_game { @@ -41,12 +44,24 @@ typedef struct grr_game { GtkWidget *window; GtkWidget *board_view; + GtkWidget *command_entry; + GtkTextBuffer *message_buffer; GtkWidget *message_view; - GtkWidget *command_entry; - GtkTextIter message_iter; + int msg_id; + int last_move_msg_id; + rr_robot_t last_move_robot; } grr_game_t; +static int +grr_game_printf (grr_game_t *game, const char *fmt, ...); + +static int +grr_game_vprintf (grr_game_t *game, const char *fmt, va_list ap); + +static int +grr_game_print (grr_game_t *game, const char *msg); + static int grr_game_start_gui (grr_game_t *game); @@ -83,6 +98,9 @@ main (int argc, char **argv) } game.board = rr_board_create (16, 16); + game.msg_id = 0; + game.last_move_msg_id = 0; + game.last_move_robot = RR_ROBOT_NONE; source = grr_game_notices_source_new (&game); g_source_set_priority (source, GDK_PRIORITY_EVENTS); @@ -165,63 +183,108 @@ grr_game_read_notices (grr_game_t *game) { rr_board_t *board = game->board; rr_status_t status; - char **notice_s; rr_notice_t *notice; - int i; while (rr_client_notice_pending (game->client)) { - status = rr_client_next_notice (game->client, ¬ice_s); + status = rr_client_next_notice (game->client, ¬ice); if (status) { - fprintf (stderr, "Error during rr_client_notice: %s\n", + fprintf (stderr, "Error during rr_client_next_notice: %s\n", rr_status_str (status)); gtk_exit (1); return; } - for (i=0; notice_s[i]; i++) { - gtk_text_buffer_insert_at_cursor (game->message_buffer, notice_s[i], -1); - gtk_text_buffer_insert_at_cursor (game->message_buffer, " ", -1); - } - gtk_text_buffer_insert_at_cursor (game->message_buffer, "\n", -1); - gtk_text_buffer_get_iter_at_offset (game->message_buffer, - &game->message_iter, - -1); - gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (game->message_view), - &game->message_iter, - 0.0, FALSE, 0.0, 0.0); - - notice = rr_client_parse_notice (game->client, notice_s); - if (notice == NULL) { - int i; - fprintf (stderr, "Failed to parse notice: "); - for (i=0; notice_s[i]; i++) - fprintf (stderr, " %s", notice_s[i]); - fprintf (stderr, "\n"); - return; - } switch (notice->type) { case RR_NOTICE_USER: + grr_game_printf (game, + "\nGLOBAL: %s has connected.", notice->u.string); + break; case RR_NOTICE_QUIT: + grr_game_printf (game, + "\nGLOBAL: %s has disconnected.", notice->u.string); + break; case RR_NOTICE_GAME: + grr_game_printf (game, + "\nGLOBAL: New game available: %s.", notice->u.string); + break; case RR_NOTICE_DISPOSE: + grr_game_printf (game, + "\nGLOBAL: Game %s has been disposed.", notice->u.string); + break; case RR_NOTICE_MESSAGE: + grr_game_printf (game, "\n%s> %s", + notice->u.message.username, + notice->u.message.text); + break; case RR_NOTICE_GAMESTATE: + grr_game_printf (game, "\nGame state changed to: %s.", + rr_gamestate_str (notice->u.gamestate)); + break; case RR_NOTICE_JOIN: + grr_game_printf (game, "\nUser %s has joined the game.", + notice->u.string); + break; case RR_NOTICE_WATCH: + grr_game_printf (game, "\nUser %s has started watching the game.", + notice->u.string); + break; case RR_NOTICE_PART: + grr_game_printf (game, "\nUser %s has left the game.", + notice->u.string); + break; case RR_NOTICE_BID: + grr_game_printf (game, "\nUser %s bids %d.", + notice->u.bid.username, + notice->u.bid.number); + break; case RR_NOTICE_REVOKE: - case RR_NOTICE_TIMER: + grr_game_printf (game, "\nUser %s revokes previous bid.", + notice->u.string); + break; case RR_NOTICE_ABANDON: + grr_game_printf (game, "\nUser %s is willing to abandon this turn.", + notice->u.string); + break; case RR_NOTICE_NOBID: - case RR_NOTICE_ACTIVE: + grr_game_printf (game, "\nUser %s sees no point in bidding further this round", + notice->u.string); + break; case RR_NOTICE_MOVE: + if (game->msg_id == game->last_move_msg_id + && game->last_move_robot == notice->u.move.robot) { + game->last_move_msg_id = grr_game_printf (game, " %s", + rr_direction_str (notice->u.move.direction)); + } else { + game->last_move_msg_id = grr_game_printf (game, "\nMove #%d: %s %s", + notice->u.move.count, + rr_robot_str (notice->u.move.robot), + rr_direction_str (notice->u.move.direction)); + game->last_move_robot = notice->u.move.robot; + } + break; case RR_NOTICE_UNDO: + grr_game_print (game, "\nUNDO"); + break; case RR_NOTICE_RESET: + grr_game_print (game, "\nRESET"); + break; case RR_NOTICE_SCORE: + grr_game_printf (game, "\nScore for %s: %d.", + notice->u.bid.username, + notice->u.bid.number); + break; case RR_NOTICE_ACTIVATE: - /* XXX: Need to actually handle many of these. */ - fprintf (stderr, "Warning: Ignoring notice of type %d\n", notice->type); + grr_game_printf (game, "\nYour turn.", + notice->u.number); + break; + case RR_NOTICE_ACTIVE: + grr_game_printf (game, "\nUser %s now active to demonstrate solution in %d moves.", + notice->u.bid.username, + notice->u.bid.number); + break; + case RR_NOTICE_TIMER: + grr_game_printf (game, "\nTime remaining: %d seconds.", + notice->u.number); break; case RR_NOTICE_POSITION: rr_board_position (board, notice->u.position.robot, @@ -229,6 +292,7 @@ grr_game_read_notices (grr_game_t *game) gtk_widget_queue_draw (GTK_WIDGET (game->window)); break; case RR_NOTICE_TURN: + grr_game_print (game, "\nNew round!"); rr_board_set_goal_target (board, notice->u.target); gtk_widget_queue_draw (GTK_WIDGET (game->window)); break; @@ -250,20 +314,13 @@ grr_game_entry_callback (GtkWidget *widget, status = rr_client_request (game->client, entry_text, &response); if (status) { - gtk_text_buffer_insert_at_cursor (game->message_buffer, - "ERROR: ", -1); - gtk_text_buffer_insert_at_cursor (game->message_buffer, - rr_status_str (status), -1); - gtk_text_buffer_insert_at_cursor (game->message_buffer, - "\n", -1); + grr_game_printf (game, "\nERROR: %s.", rr_status_str (status)); } else { - for (i=0; response[i]; i++) { - gtk_text_buffer_insert_at_cursor (game->message_buffer, - response[i], -1); - gtk_text_buffer_insert_at_cursor (game->message_buffer, - " ", -1); + if (response[0]) { + grr_game_print (game, "\n"); + for (i=0; response[i]; i++) + grr_game_printf (game, "%s ", response[i]); } - gtk_text_buffer_insert_at_cursor (game->message_buffer, "\n", -1); } gtk_entry_set_text (GTK_ENTRY (game->command_entry), ""); @@ -274,6 +331,60 @@ grr_game_entry_callback (GtkWidget *widget, } +static int +grr_game_printf (grr_game_t *game, const char *fmt, ...) +{ + int msg_id; + + va_list ap; + + va_start (ap, fmt); + msg_id = grr_game_vprintf (game, fmt, ap); + va_end (ap); + + return msg_id; +} + +static int +grr_game_vprintf (grr_game_t *game, const char *fmt, va_list ap) +{ + char *msg; + int msg_id; + + grr_sprintf_alloc_va (&msg, fmt, ap); + if (msg == NULL) + return 0; + + msg_id = grr_game_print (game, msg); + + free (msg); + + return msg_id; +} + +static int +grr_game_print (grr_game_t *game, const char *msg) +{ + GtkTextIter iter; + GtkTextMark *mark; + + /* There might be a lighter way to do this, but this seems to + work. */ + + gtk_text_buffer_get_end_iter (game->message_buffer, &iter); + + mark = gtk_text_buffer_get_mark (game->message_buffer, "end"); + + gtk_text_buffer_move_mark (game->message_buffer, mark, &iter); + + gtk_text_buffer_insert (game->message_buffer, &iter, msg, -1); + + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (game->message_view), + mark, 0.0, TRUE, 0.0, 1.0); + + return ++game->msg_id; +} + static int grr_game_start_gui (grr_game_t *game) { @@ -298,9 +409,14 @@ grr_game_start_gui (grr_game_t *game) vbox = gtk_vbox_new (FALSE, 1); gtk_container_add (GTK_CONTAINER (window), vbox); { + GtkTextIter iter; game->board_view = grr_board_view_new (game->board); grr_board_view_set_client (GRR_BOARD_VIEW (game->board_view), game->client); game->message_buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_get_iter_at_offset (game->message_buffer, + &iter, -1); + gtk_text_buffer_create_mark (game->message_buffer, + "end", &iter, FALSE); game->message_view = gtk_text_view_new_with_buffer (game->message_buffer); game->command_entry = gtk_entry_new (); diff --git a/src/svg/.cvsignore b/src/svg/.cvsignore new file mode 100644 index 0000000..aacdc07 --- /dev/null +++ b/src/svg/.cvsignore @@ -0,0 +1,6 @@ +*.svgz +.deps +Makefile +Makefile.in +bin2cstring +grr_icon_svg.h diff --git a/src/svg/Makefile.am b/src/svg/Makefile.am new file mode 100644 index 0000000..b143c9c --- /dev/null +++ b/src/svg/Makefile.am @@ -0,0 +1,66 @@ +noinst_HEADERS=grr_icon_svg.h + +noinst_PROGRAMS = bin2cstring + +bin2cstring_SOURCES = bin2cstring.c + +pkgdata_DATA = \ +cell.svg \ +robot_blue.svg \ +robot_green.svg \ +robot_red.svg \ +robot_yellow.svg \ +target_blue_circle.svg \ +target_blue_octagon.svg \ +target_blue_square.svg \ +target_blue_triangle.svg \ +target_green_circle.svg \ +target_green_octagon.svg \ +target_green_square.svg \ +target_green_triangle.svg \ +target_red_circle.svg \ +target_red_octagon.svg \ +target_red_square.svg \ +target_red_triangle.svg \ +target_whirl.svg \ +target_yellow_circle.svg \ +target_yellow_octagon.svg \ +target_yellow_square.svg \ +target_yellow_triangle.svg \ +wall.svg + +grr_icon_svg.h: \ +cell.svgz \ +robot_blue.svgz \ +robot_green.svgz \ +robot_red.svgz \ +robot_yellow.svgz \ +target_blue_circle.svgz \ +target_blue_octagon.svgz \ +target_blue_square.svgz \ +target_blue_triangle.svgz \ +target_green_circle.svgz \ +target_green_octagon.svgz \ +target_green_square.svgz \ +target_green_triangle.svgz \ +target_red_circle.svgz \ +target_red_octagon.svgz \ +target_red_square.svgz \ +target_red_triangle.svgz \ +target_whirl.svgz \ +target_yellow_circle.svgz \ +target_yellow_octagon.svgz \ +target_yellow_square.svgz \ +target_yellow_triangle.svgz \ +wall.svgz + rm -f $@ + for svgz in $^; do \ + echo -n "char " >> $@; \ + echo -n "grr_icon_svg_$${svgz/.svgz/}[] = " | tr "a-z" "A-Z" >> $@; \ + ./bin2cstring $$svgz >> $@; \ + echo ";" >> $@; \ + done + + +%.svgz: %.svg + gzip -c $< > $@ diff --git a/src/svg/bin2cstring.c b/src/svg/bin2cstring.c new file mode 100644 index 0000000..86ef541 --- /dev/null +++ b/src/svg/bin2cstring.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + int i, c; + FILE *file; + + for (i=1; i < argc; i++) { + file = fopen (argv[i], "r"); + if (file == NULL) { + fprintf (stderr, "Failed to open file %s: %s\n", + argv[i], strerror (errno)); + continue; + } + + putchar ('"'); + while (1) { + c = fgetc (file); + if (c == EOF) + break; + + if (isprint (c) && ! isspace (c)) + printf ("%c", c); + else + printf ("\\%03o", c); + } + putchar ('"'); + } + + return 0; +} diff --git a/src/svg/w.svg b/src/svg/w.svg deleted file mode 100644 index 8a86aa8..0000000 --- a/src/svg/w.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - diff --git a/src/svg/whirl.svg b/src/svg/whirl.svg deleted file mode 100644 index 9b63225..0000000 --- a/src/svg/whirl.svg +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/svg/whirl_non_sodi.svg b/src/svg/whirl_non_sodi.svg deleted file mode 100644 index 479ee36..0000000 --- a/src/svg/whirl_non_sodi.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - diff --git a/src/svg/whirl_sodi.svg b/src/svg/whirl_sodi.svg deleted file mode 100644 index 479ee36..0000000 --- a/src/svg/whirl_sodi.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - -