* GTK front end to puzzles.
*/
+struct font {
+ GdkFont *font;
+ int type;
+ int size;
+};
+
/*
* This structure holds all the data relevant to a single window.
* In principle this would allow us to open multiple independent
midend_data *me;
GdkGC *gc;
int bbox_l, bbox_r, bbox_u, bbox_d;
- int timer_active;
+ int timer_active, timer_id;
+ struct font *fonts;
+ int nfonts, fontsize;
};
void frontend_default_colour(frontend *fe, float *output)
fe->bbox_d = 0;
}
+void clip(frontend *fe, int x, int y, int w, int h)
+{
+ GdkRectangle rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ gdk_gc_set_clip_rectangle(fe->gc, &rect);
+}
+
+void unclip(frontend *fe)
+{
+ GdkRectangle rect;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = fe->w;
+ rect.height = fe->h;
+
+ gdk_gc_set_clip_rectangle(fe->gc, &rect);
+}
+
+void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize,
+ int align, int colour, char *text)
+{
+ int i;
+
+ /*
+ * Find or create the font.
+ */
+ for (i = 0; i < fe->nfonts; i++)
+ if (fe->fonts[i].type == fonttype && fe->fonts[i].size == fontsize)
+ break;
+
+ if (i == fe->nfonts) {
+ if (fe->fontsize <= fe->nfonts) {
+ fe->fontsize = fe->nfonts + 10;
+ fe->fonts = sresize(fe->fonts, fe->fontsize, struct font);
+ }
+
+ fe->nfonts++;
+
+ fe->fonts[i].type = fonttype;
+ fe->fonts[i].size = fontsize;
+
+ /*
+ * FIXME: Really I should make at least _some_ effort to
+ * pick the correct font.
+ */
+ fe->fonts[i].font = gdk_font_load("variable");
+ }
+
+ /*
+ * Find string dimensions and process alignment.
+ */
+ {
+ int lb, rb, wid, asc, desc;
+
+ gdk_string_extents(fe->fonts[i].font, text,
+ &lb, &rb, &wid, &asc, &desc);
+ if (align & ALIGN_VCENTRE)
+ y += asc - (asc+desc)/2;
+
+ if (align & ALIGN_HCENTRE)
+ x -= wid / 2;
+ else if (align & ALIGN_HRIGHT)
+ x -= wid;
+
+ }
+
+ /*
+ * Set colour and actually draw text.
+ */
+ gdk_gc_set_foreground(fe->gc, &fe->colours[colour]);
+ gdk_draw_string(fe->pixmap, fe->fonts[i].font, fe->gc, x, y, text);
+}
+
void draw_rect(frontend *fe, int x, int y, int w, int h, int colour)
{
gdk_gc_set_foreground(fe->gc, &fe->colours[colour]);
if (event->string[0] && !event->string[1])
keyval = (unsigned char)event->string[0];
- else if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
+ else if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
+ event->keyval == GDK_KP_8)
keyval = CURSOR_UP;
- else if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
+ else if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
+ event->keyval == GDK_KP_2)
keyval = CURSOR_DOWN;
- else if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left)
+ else if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left ||
+ event->keyval == GDK_KP_4)
keyval = CURSOR_LEFT;
- else if (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
+ else if (event->keyval == GDK_Right || event->keyval == GDK_KP_Right ||
+ event->keyval == GDK_KP_6)
keyval = CURSOR_RIGHT;
+ else if (event->keyval == GDK_KP_Home || event->keyval == GDK_KP_7)
+ keyval = CURSOR_UP_LEFT;
+ else if (event->keyval == GDK_KP_End || event->keyval == GDK_KP_1)
+ keyval = CURSOR_DOWN_LEFT;
+ else if (event->keyval == GDK_KP_Page_Up || event->keyval == GDK_KP_9)
+ keyval = CURSOR_UP_RIGHT;
+ else if (event->keyval == GDK_KP_Page_Down || event->keyval == GDK_KP_3)
+ keyval = CURSOR_DOWN_RIGHT;
else
keyval = -1;
if (event->type != GDK_BUTTON_PRESS)
return TRUE;
- if (event->button == 1)
- button = LEFT_BUTTON;
- else if (event->button == 2)
+ if (event->button == 2 || (event->state & GDK_SHIFT_MASK))
button = MIDDLE_BUTTON;
+ else if (event->button == 1)
+ button = LEFT_BUTTON;
else if (event->button == 3)
button = RIGHT_BUTTON;
else
void deactivate_timer(frontend *fe)
{
+ if (fe->timer_active)
+ gtk_timeout_remove(fe->timer_id);
fe->timer_active = FALSE;
}
void activate_timer(frontend *fe)
{
- gtk_timeout_add(20, timer_func, fe);
+ if (!fe->timer_active)
+ fe->timer_id = gtk_timeout_add(20, timer_func, fe);
fe->timer_active = TRUE;
}
midend_new_game(fe->me, NULL);
fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(fe->window), game_name);
#if 0
gtk_window_set_resizable(GTK_WINDOW(fe->window), FALSE);
#else
gtk_box_pack_end(vbox, fe->area, FALSE, FALSE, 0);
fe->pixmap = NULL;
+ fe->fonts = NULL;
+ fe->nfonts = fe->fontsize = 0;
+
+ fe->timer_active = FALSE;
gtk_signal_connect(GTK_OBJECT(fe->window), "destroy",
GTK_SIGNAL_FUNC(destroy), fe);