From 5fce44d580c24ac4c817ca62614670b04b4cf10b Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Mon, 5 May 2008 22:36:42 +0100 Subject: Scrap plug-able interfaces in preparation for GTK GUI. Signed-off-by: Bradley Smith --- src/userinterface.c | 796 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 665 insertions(+), 131 deletions(-) (limited to 'src/userinterface.c') diff --git a/src/userinterface.c b/src/userinterface.c index f31591f..577cb7a 100644 --- a/src/userinterface.c +++ b/src/userinterface.c @@ -1,7 +1,7 @@ /* Copyright (C) 1998 Jim Hall * Copyright (C) 2008 Bradley Smith * - * GNU Robots game engine. This is the User Interface module + * GNU Robots game engine. * * GNU Robots is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,185 +19,719 @@ */ #include - +#include +#include +#include +#include #include "configs.h" #include "userinterface.h" -/*enum +#include +#include + +G_DEFINE_TYPE(UserInterface, user_interface, G_TYPE_OBJECT) + +enum { ARG_0, ARG_MAP -};*/ +}; + +static GObject * user_interface_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties); + +static void user_interface_finalize (GObject * object); +static void user_interface_dispose (GObject * object); -static void user_interface_base_init (UserInterfaceClass * klass); +static void user_interface_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); -GType -user_interface_get_type (void) +static void user_interface_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void put_tile (UserInterface *ui, XImage *image, gint x, gint y); +static void put_winbuf (UserInterface *ui); +static void setup_winbuf (UserInterface *ui); +void create_image (UserInterface *ui, gchar **data, XImage ** image); + +static GObjectClass *parent_class = NULL; + +static void +user_interface_class_init (UserInterfaceClass * klass) { - static GType _user_interface_type = 0; + GObjectClass *gobject_class; - if (!_user_interface_type) - { - static const GTypeInfo interface_info = { - sizeof (UserInterfaceClass), - (GBaseInitFunc) user_interface_base_init, - NULL, - NULL, - NULL, - NULL, - 0, - 0, - NULL, - NULL - }; + gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_ref (G_TYPE_OBJECT); + + gobject_class->constructor = user_interface_constructor; + gobject_class->set_property = user_interface_set_property; + gobject_class->get_property = user_interface_get_property; + gobject_class->dispose = user_interface_dispose; + gobject_class->finalize = user_interface_finalize; + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAP, + g_param_spec_object ("map", + "Map", + "Reference to the Game Map object", + G_TYPE_MAP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +user_interface_init (UserInterface* ui) +{ + ui->map = NULL; + ui->map_size = NULL; +} + +static GObject * +user_interface_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + /* Initialize ui */ + GObject *object; + UserInterface *ui; +#include "xpm/statusbar.xpm" +#include "xpm/space.xpm" +#include "xpm/food.xpm" +#include "xpm/wall.xpm" +#include "xpm/prize.xpm" +#include "xpm/baddie.xpm" +#include "xpm/robot_north.xpm" +#include "xpm/robot_east.xpm" +#include "xpm/robot_south.xpm" +#include "xpm/robot_west.xpm" +#include "xpm/robot.xpm" + XClassHint classhint; + XWMHints wmhints; + XGCValues values; - _user_interface_type = g_type_register_static (G_TYPE_INTERFACE, - "UserInterface", - &interface_info, 0); + /* Chain up to the parent first */ + object = parent_class->constructor (type, n_construct_properties, + construct_properties); + + ui = USER_INTERFACE (object); + + XInitThreads(); + + if ((ui->dpy = XOpenDisplay ("")) == NULL) { + g_printf ("Couldn't open the X Server Display!\n"); + exit (1); /* Exit nicely isn't needed yet, and causes segfault */ } - return _user_interface_type; + ui->wm_delete_win = XInternAtom (ui->dpy, "WM_DELETE_WINDOW", False); + + ui->win_width = ui->map_size->num_cols * TILE_SIZE; + ui->win_height = ui->map_size->num_rows * TILE_SIZE + 32; + ui->x_win = XCreateSimpleWindow (ui->dpy, DefaultRootWindow (ui->dpy), + 0, 0, ui->win_width, ui->win_height, 0, 0, 0); + + XSetWMProtocols (ui->dpy, ui->x_win, &(ui->wm_delete_win), 1); + + ui->wm_protocols = XInternAtom(ui->dpy, "WM_PROTOCOLS", False); + + XStoreName (ui->dpy, ui->x_win, "GNU Robots"); + + classhint.res_name = "robots"; + classhint.res_class = "Robots"; + XSetClassHint (ui->dpy, ui->x_win, &classhint); + + /* XSetCommand() seems to segfault... */ + + wmhints.input = True; + wmhints.flags = InputHint; + XSetWMHints (ui->dpy, ui->x_win, &wmhints); + + XSelectInput (ui->dpy, ui->x_win, + ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask + | FocusChangeMask); + + XMapWindow (ui->dpy, ui->x_win); + + ui->text = XLoadFont (ui->dpy, + "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*"); + values.font = ui->text; + values.foreground = WhitePixel (ui->dpy, DefaultScreen (ui->dpy)); + + ui->gc = XCreateGC (ui->dpy, ui->x_win, + GCFont | GCForeground, &values); + + create_image (ui, statusbar_xpm, &ui->statusbar); + create_image (ui, space_xpm, &ui->space); + create_image (ui, food_xpm, &ui->food); + create_image (ui, wall_xpm, &ui->wall); + create_image (ui, prize_xpm, &ui->prize); + create_image (ui, baddie_xpm, &ui->baddie); + create_image (ui, robot_north_xpm, &ui->robotDirs[0]); + create_image (ui, robot_east_xpm, &ui->robotDirs[1]); + create_image (ui, robot_south_xpm, &ui->robotDirs[2]); + create_image (ui, robot_west_xpm, &ui->robotDirs[3]); + create_image (ui, robot_xpm, &ui->robotPix); + + setup_winbuf (ui); + + return object; } static void -user_interface_base_init (UserInterfaceClass * klass) +user_interface_dispose (GObject * object) { - static gboolean initialized = FALSE; + UserInterface *ui; + ui = USER_INTERFACE (object); - if (!initialized) - { - /*GObjectClass *gobject_class = - g_type_class_peek (((GTypeInterface *) klass)->g_instance_type); + if (ui->map != NULL) { + g_object_unref (G_OBJECT (ui->map)); - g_object_class_install_property (gobject_class, ARG_MAP, */ - g_object_interface_install_property (klass, - g_param_spec_object ("map", - "Map", - "Reference to the Game Map object", - G_TYPE_MAP, - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT)); - initialized = TRUE; + if (ui->map_size != NULL) { + g_free (ui->map_size); + } } + + parent_class->dispose (object); } -void -user_interface_add_thing (UserInterface * ui, gint x, gint y, gint thing) +/* finalize is called when the object has to free its resources */ +static void +user_interface_finalize (GObject * object) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_add_thing (ui, x, y, thing); + UserInterface *ui = USER_INTERFACE (object); + + /* End ui mode */ +#ifdef USE_MITSHM + if (use_mitshm) { + XShmDetach (ui->dpy, &shm_info); + if (shm_info.shmaddr) + shmdt (shm_info.shmaddr); + if (shm_info.shmid >= 0) + shmctl (shm_info.shmid, IPC_RMID, 0); + } +#endif + XDestroyWindow (ui->dpy, ui->x_win); + XUnloadFont (ui->dpy, ui->text); + + parent_class->finalize (object); } -void user_interface_run(UserInterface* ui) +static void +user_interface_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) { - USER_INTERFACE_GET_CLASS(ui)->user_interface_run(ui); + UserInterface *ui; + GObject *obj; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (G_IS_USER_INTERFACE (object)); + + ui = USER_INTERFACE (object); + + switch (prop_id) { + case ARG_MAP: + obj = g_value_get_object (value); + g_return_if_fail (obj != NULL); + + if (ui->map != NULL) { + g_object_unref (ui->map); + } + + ui->map = MAP (g_object_ref (obj)); + + if (ui->map_size != NULL) { + g_free (ui->map_size); + } + + g_object_get (G_OBJECT (ui->map), + "size", &ui->map_size, + NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } -void -user_interface_draw (UserInterface * ui) +static void +user_interface_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_draw (ui); + UserInterface *ui; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (G_IS_USER_INTERFACE (object)); + + ui = USER_INTERFACE (object); + + switch (prop_id) { + case ARG_MAP: + g_value_set_object (value, g_object_ref (G_OBJECT (ui->map))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } -void -user_interface_move_robot (UserInterface * ui, - gint from_x, - gint from_y, - gint to_x, - gint to_y, - gint cdir, - glong energy, glong score, glong shields) -{ - USER_INTERFACE_GET_CLASS (ui)->user_interface_move_robot (ui, from_x, - from_y, to_x, - to_y, cdir, - energy, score, - shields); -} - -/* user_interfaces to animate the robot */ -void -user_interface_robot_smell (UserInterface * ui, - gint x, - gint y, - gint cdir, - glong energy, glong score, glong shields) +UserInterface * +user_interface_new (Map *map) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_robot_smell (ui, x, y, cdir, - energy, score, - shields); + UserInterface *ui; + + g_return_val_if_fail (map != NULL, NULL); + + ui = USER_INTERFACE (g_object_new (user_interface_get_type (), + "map", map, + NULL)); + + return USER_INTERFACE (ui); } -void -user_interface_robot_zap (UserInterface * ui, - gint x, - gint y, - gint cdir, - gint x_to, - gint y_to, glong energy, glong score, glong shields) +/* note that hook_delete_thing(x,y) is the same as + hook_add_thing(x,y,space) */ +void user_interface_add_thing (UserInterface *ui, + gint x, + gint y, + gint thing) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_robot_zap (ui, x, y, cdir, - x_to, y_to, energy, - score, shields); + gint w_x, w_y; + + w_x = x * TILE_SIZE; + w_y = y * TILE_SIZE; + + switch (thing) { + case SPACE: + put_tile (ui, ui->space, w_x, w_y); + break; + case FOOD: + put_tile (ui, ui->food, w_x, w_y); + break; + case PRIZE: + put_tile (ui, ui->prize, w_x, w_y); + break; + case WALL: + put_tile (ui, ui->wall, w_x, w_y); + break; + case BADDIE: + put_tile (ui, ui->baddie, w_x, w_y); + break; + case ROBOT: + put_tile (ui, ui->robotPix, w_x, w_y); + break; + default: + put_tile (ui, ui->wall, w_x, w_y); + break; + } + + put_winbuf (ui); + XFlush (ui->dpy); } -void -user_interface_robot_feel (UserInterface * ui, - gint x, - gint y, - gint cdir, - gint x_to, - gint y_to, - glong energy, glong score, glong shields) +void user_interface_draw (UserInterface *ui) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_robot_feel (ui, x, y, cdir, - x_to, y_to, - energy, score, - shields); + gint i, j; + + /* Draw the map for the GNU Robots game. */ + for (j = 0; j < ui->map_size->num_rows; j++) { + for (i = 0; i < ui->map_size->num_cols; i++) { + /* Special cases */ + switch (MAP_GET_OBJECT (ui->map, i, j)) { + /* Add something for the ROBOT?? */ + case '\0': + put_tile (ui, ui->wall, i * TILE_SIZE, j * TILE_SIZE); + break; + case SPACE: + put_tile (ui, ui->space, i * TILE_SIZE, j * TILE_SIZE); + break; + case FOOD: + put_tile (ui, ui->food, i * TILE_SIZE, j * TILE_SIZE); + break; + case PRIZE: + put_tile (ui, ui->prize, i * TILE_SIZE, j * TILE_SIZE); + break; + case WALL: + put_tile (ui, ui->wall, i * TILE_SIZE, j * TILE_SIZE); + break; + case BADDIE: + put_tile (ui, ui->baddie, i * TILE_SIZE, j * TILE_SIZE); + break; + case ROBOT: + put_tile (ui, ui->robotPix, i * TILE_SIZE, j * TILE_SIZE); + break; + default: + put_tile (ui, ui->wall, i * TILE_SIZE, j * TILE_SIZE); + break; + } /* switch */ + } /* for i */ + } /* for j */ + + put_winbuf (ui); + XSync (ui->dpy, FALSE); } -void -user_interface_robot_grab (UserInterface * ui, - gint x, - gint y, - gint cdir, - gint x_to, - gint y_to, - glong energy, glong score, glong shields) +void user_interface_move_robot (UserInterface *ui, + gint from_x, + gint from_y, + gint to_x, + gint to_y, + gint cdir, + glong energy, + glong score, + glong shields) +{ + const static gint movement = TILE_SIZE / 16; + guint8 distance = dist (from_x, from_y, to_x, to_y); + guint w_x = to_x * TILE_SIZE, w_y = to_y * TILE_SIZE, tw_x, tw_y; + Bool ok; + + g_assert (distance <= 1); + + user_interface_update_status (ui, "robot moves..", energy, score, shields); + + /* Check if robot is moving withing a single box */ + if (distance == 0) { + put_tile (ui, ui->space, from_x * TILE_SIZE, from_y * TILE_SIZE); + put_tile (ui, ui->robotDirs[cdir], to_x * TILE_SIZE, to_y * TILE_SIZE); + + put_winbuf (ui); + XSync (ui->dpy, False); + g_usleep (USLEEP_TIME / 16); + + return; + } + + from_x *= TILE_SIZE; + from_y *= TILE_SIZE; + tw_y = w_y; + tw_x = w_x; + switch (cdir) { + case NORTH: + tw_y = from_y - movement; + break; + case SOUTH: + tw_y = from_y + movement; + break; + case EAST: + tw_x = from_x + movement; + break; + case WEST: + tw_x = from_x - movement; + break; + default: + g_printf ("Weird unknown robot direction. I'm Confused.\n"); + } + + while (1) { + put_tile (ui, ui->space, from_x, from_y); + put_tile (ui, ui->robotDirs[cdir], tw_x, tw_y); + + ok = False; + if (tw_x < w_x) { + tw_x += movement; + ok = True; + } else if (tw_x > w_x) { + tw_x -= movement; + ok = True; + } + if (tw_y < w_y) { + tw_y += movement; + ok = True; + } else if (tw_y > w_y) { + tw_y -= movement; + ok = True; + } + put_winbuf (ui); + XSync (ui->dpy, False); + g_usleep (USLEEP_TIME / 16); + if (!ok) + break; + } + + g_usleep (USLEEP_TIME); +} + +/* hooks to animate the robot */ +void user_interface_robot_smell (UserInterface *ui, + gint x, + gint y, + gint cdir, + glong energy, + glong score, + glong shields) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_robot_grab (ui, x, y, cdir, - x_to, y_to, - energy, score, - shields); + /* If we want to change the pic, do it here */ + user_interface_update_status (ui, "robot sniffs...", energy, score, shields); + g_usleep (USLEEP_TIME); } -void -user_interface_robot_look (UserInterface * ui, - gint x, - gint y, - gint cdir, - gint x_to, - gint y_to, - glong energy, glong score, glong shields) +void user_interface_robot_zap (UserInterface *ui, + gint x, + gint y, + gint cdir, + gint x_to, + gint y_to, + glong energy, + glong score, + glong shields) { - USER_INTERFACE_GET_CLASS (ui)->user_interface_robot_look (ui, x, y, cdir, - x_to, y_to, - energy, score, - shields); + user_interface_update_status (ui, "robot fires his little gun...", energy, score, shields); + g_usleep (USLEEP_TIME); } -void -user_interface_get_string (UserInterface *ui, gchar *prompt, gchar *buff, - gint len) +void user_interface_robot_feel (UserInterface *ui, + gint x, + gint y, + gint cdir, + gint x_to, + gint y_to, + glong energy, + glong score, + glong shields) +{ + user_interface_update_status (ui, "robot feels for a thing...", energy, score, shields); + g_usleep (USLEEP_TIME); +} + +void user_interface_robot_grab (UserInterface *ui, + gint x, + gint y, + gint cdir, + gint x_to, + gint y_to, + glong energy, + glong score, + glong shields) +{ + user_interface_update_status (ui, "robot grabs thing...", energy, score, shields); + g_usleep (USLEEP_TIME); +} + +void user_interface_robot_look (UserInterface *ui, + gint x, + gint y, + gint cdir, + gint x_to, + gint y_to, + glong energy, + glong score, + glong shields) +{ + user_interface_update_status (ui, "robot looks for a thing...", energy, score, shields); + g_usleep (USLEEP_TIME); +} + +/* hooks to get/display data from/to user */ +void user_interface_get_string (UserInterface *ui, + gchar *prompt, + gchar *buff, + gint len) +{ + char* line = (char*)NULL; + + line = readline(prompt); + + if(line && *line) + { + add_history(line); + + g_strlcpy(buff, line, len); + } + else + buff = ""; + + free(line); +} + +void ui_update_status (UserInterface *ui, + const gchar *s, + glong energy, + glong score, + glong shields) +{ + gchar status[20]; + gint x = 0; + + while (x < ui->win_width) { + XPutImage (ui->dpy, ui->win_buf, ui->buf_gc, ui->statusbar, 0, 0, x, ui->map_size->num_rows * TILE_SIZE, 96, + 32); + x = x + 96; + } + + XDrawString (ui->dpy, ui->win_buf, ui->gc, 3, ui->map_size->num_rows * TILE_SIZE + 16, s, strlen (s)); + + if (energy > -1) { + g_sprintf (status, "Robot Energy: %3ld", energy); + XDrawString (ui->dpy, ui->win_buf, ui->gc, 240, ui->map_size->num_rows * TILE_SIZE + 12, status, + strlen (status)); + } + + if (score > -1) { + g_sprintf (status, "Robot Score: %3ld", score); + XDrawString (ui->dpy, ui->win_buf, ui->gc, 240, ui->map_size->num_rows * TILE_SIZE + 25, status, + strlen (status)); + } + + if (shields > -1) { + g_sprintf (status, "Robot Shields: %3ld", shields); + XDrawString (ui->dpy, ui->win_buf, ui->gc, 480, ui->map_size->num_rows * TILE_SIZE + 12, status, + strlen (status)); + } +} + +void user_interface_update_status (UserInterface *ui, + const gchar *s, + glong energy, + glong score, + glong shields) +{ + ui_update_status (ui, s, energy, score, shields); +} + +void user_interface_run(UserInterface* ui) +{ + XEvent ev; + XClientMessageEvent* evt; + + while (TRUE) + { + XNextEvent (ui->dpy, &ev); + + switch (ev.type) + { + case KeyPress: + case KeyRelease: + switch (XKeycodeToKeysym (ui->dpy, ev.xkey.keycode, 0)) + { + case XK_Escape: + exit (0); + break; + } + case ClientMessage: + evt = (XClientMessageEvent*)&ev; + if (evt->message_type == ui->wm_protocols + && evt->data.l[0] == ui->wm_delete_win) + { + g_printf("Exited\n"); + exit(0); + } + break; + case Expose: + user_interface_draw(ui); + break; + } + } + + put_winbuf (ui); +} + +#ifdef USE_MITSHM +static gint +shm_error_handler (UserInterface *ui, Display * d, XErrorEvent * e) { - USER_INTERFACE_GET_CLASS(ui)->user_interface_get_string(ui, prompt, buff, - len); + ui->use_mitshm = 0; + return 0; +} +#endif + +static void +setup_winbuf (UserInterface *ui) +{ + XVisualInfo *matches; + XVisualInfo plate; + gint count; + guint depth; + XGCValues values; + Visual *vis; + + vis = DefaultVisualOfScreen (DefaultScreenOfDisplay (ui->dpy)); + plate.visualid = XVisualIDFromVisual (vis); + matches = XGetVisualInfo (ui->dpy, VisualIDMask, &plate, &count); + depth = matches[0].depth; + +#ifdef USE_MITSHM + ui->use_mitshm = 1; + ui->shm_info.shmid = shmget (IPC_PRIVATE, win_height * win_width * depth, + IPC_CREAT | 0777); + if (ui->shm_info.shmid < 0) { + g_fprintf (stderr, "shmget failed, looks like I'll have to use XPutImage\n"); + ui->use_mitshm = 0; + } else { + ui->shm_info.shmaddr = (gchar *) shmat (ui->shm_info.shmid, 0, 0); + + if (!ui->shm_info.shmaddr) { + g_fprintf (stderr, "shmat failed, looks like I'll have to use XPutImage\n"); + shmctl (ui->shm_info.shmid, IPC_RMID, 0); + use_mitshm = 0; + } else { + XErrorHandler error_handler = XSetErrorHandler (shm_error_handler); + + ui->win_bufi = XShmCreateImage (ui->dpy, vis, depth, ZPixmap, ui->shm_info.shmaddr, + &ui->shm_info, ui->win_width, ui->win_height); + ui->shm_info.readOnly = False; + XShmAttach (ui->dpy, &ui->shm_info); + win_buf = XShmCreatePixmap (ui->dpy, ui->x_win, ui->shm_info.shmaddr, &ui->shm_info, + ui->win_width, ui->win_height, depth); + XSync (ui->dpy, False); + (void) XSetErrorHandler (error_handler); + if (!use_mitshm) { + p_fprintf (stderr, + "XShmAttach failed, looks like I'll have to use XPutImage\n"); + XFreePixmap (ui->dpy, ui->win_buf); + XDestroyImage (ui->win_bufi); + shmdt (ui->shm_info.shmaddr); + shmctl (ui->shm_info.shmid, IPC_RMID, 0); + } + } + } + + if (!ui->use_mitshm) { +#endif /* USE_MITSHM */ + ui->win_buf = XCreatePixmap (ui->dpy, ui->x_win, ui->win_width, ui->win_height, depth); +#ifdef USE_MITSHM + } else { + g_printf ("Using MIT Shared Memory Pixmaps. Good.\n", major, minor); + } +#endif + + values.font = ui->text; + values.foreground = WhitePixel (ui->dpy, DefaultScreen (ui->dpy)); + + ui->buf_gc = XCreateGC (ui->dpy, ui->win_buf, GCFont | GCForeground, &values); } void -user_interface_update_status (UserInterface * ui, const gchar * s, - glong energy, glong score, glong shields) +create_image (UserInterface *ui, gchar **data, XImage ** image) { - USER_INTERFACE_GET_CLASS(ui)->user_interface_update_status(ui, s, energy, - score, shields); + XpmAttributes a; + gint err; + + a.valuemask = XpmCloseness | XpmAllocCloseColors; + a.closeness = 40000; /* the xpm manual suggests 40000 */ + a.alloc_close_colors = 1; /* allocate the colours chosen */ + err = XpmCreateImageFromData (ui->dpy, data, image, NULL, &a); + if (err != 0) { + g_fprintf (stderr, "Cannot create image from xpm: %s\n", + XpmGetErrorString (err)); + exit (1); + } +} + +static void +put_tile (UserInterface *ui, XImage *image, gint x, gint y) +{ + XPutImage (ui->dpy, ui->win_buf, ui->gc, image, 0, 0, x, y, TILE_SIZE, TILE_SIZE); +} + +static void put_winbuf (UserInterface *ui) +{ +#ifdef USE_MITSHM + if (use_mitshm) + XShmPutImage (ui->dpy, ui->x_win, ui->gc, ui->win_bufi, 0, 0, 0, 0, ui->win_width, ui->win_height, + False); + else +#endif + XCopyArea (ui->dpy, ui->win_buf, ui->x_win, ui->gc, 0, 0, ui->win_width, ui->win_height, 0, 0); + + XSync (ui->dpy, 0); } -- cgit v1.1