1 Star 1 Fork 0

YuYunSong/xbill

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
gtk.c 16.79 KB
一键复制 编辑 原始数据 按行查看 历史
yunsong yu 提交于 2022-04-06 11:13 . comment
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include "util.h"
#include "gtk.h"
#include "Game.h"
#include "UI.h"
//IMAGES (包括SCOREFILE)均在Makefile中以-D的形式预定义,在这里VC工程中不再加该定义,即未定义则指定DEFAULT的值。
#ifndef IMAGES
#define IMAGES "."
#endif
//libgtk-win32-2.0.dll.a
//libgobject-2.0.a
//#if _MSC_VER
//////////////////#pragma comment(lib, "crypt32.lib")
////使用MSYS2+MINGW64安装的GTK2中的库,连接没有问题,但不能运行,不知为何 :(, 反而用以前的老版本可以gtk+-bundle_2.22.1-20101229_win64, gtk+-bundle_2.24.10-20120208_win32
////#pragma comment(linker, "/nodefaultlib:libgtk-win32-2.0.dll.a")
////#pragma comment(linker, "/nodefaultlib:libgdk-win32-2.0.dll.a")
////#pragma comment(linker, "/nodefaultlib:libgobject-2.0.a")
//#pragma comment(linker, "/nodefaultlib:libpangowin32-1.0.a")
//#pragma comment(linker, "/nodefaultlib:libpangocairo-1.0.a")
//#pragma comment(linker, "/nodefaultlib:libpango-1.0.a")
//#pragma comment(linker, "/nodefaultlib:libharfbuzz.a")
//#pragma comment(linker, "/nodefaultlib:libmsimg32.a")
//#pragma comment(linker, "/nodefaultlib:libatk-1.0.a")
//#pragma comment(linker, "/nodefaultlib:libcairo.a")
//#pragma comment(linker, "/nodefaultlib:libgdk_pixbuf-2.0.a")
//#pragma comment(linker, "/nodefaultlib:libgio-2.0.a")
//#pragma comment(linker, "/nodefaultlib:libglib-2.0.a")
//#pragma comment(linker, "/nodefaultlib:libintl.a")
//#endif
struct MCursor {
GdkCursor *cursor;
};
struct Picture {
gint width, height;
GdkPixmap *pix;
GdkBitmap *mask;
GdkGC *gc;
};
static const char *pictdir;
static GtkWidget *toplevel, *base, *menubar, *field;
static GtkWidget *dialogs[DIALOG_MAX + 1];
static GtkWidget *pausebutton;
static guint timer;
static GdkGC *stdgc;
static GdkPixmap *offscreen;
static GdkFont *font;
static GdkColor white, black;
static int screensize;
/*
* Callback functions
*/
static void
gtk_ui_popup_dialog(int index) {
GtkWidget *popup;
int tx, ty, tw, th;
int px, py, pw, ph;
popup = dialogs[index];
gdk_window_get_origin(toplevel->window, &tx, &ty);
gdk_window_get_size(toplevel->window, &tw, &th);
gdk_window_get_size(popup->window, &pw, &ph);
px = tx + (tw - pw) / 2;
py = ty + (th - ph) / 2;
gtk_window_set_position(GTK_WINDOW(popup), GTK_WIN_POS_NONE);
gtk_widget_set_uposition(popup, px, py);
gtk_widget_show_all(popup);
gtk_main();
}
static void
popdown(void) {
gtk_main_quit();
}
static void
new_game(void) {
Game_start(1);
}
static void
quit_game(void) {
Game_quit();
}
static void
warp_apply(GtkWidget *text) {
char *str;
char *endp;
int newlevel;
str =(char*) gtk_entry_get_text(GTK_ENTRY(text));
newlevel = strtol(str, &endp, 10);
if (*endp != '\0')
return;
Game_warp_to_level(newlevel);
}
static void
enter_name(GtkWidget *text) {
char *str;
str =(char*) gtk_entry_get_text(GTK_ENTRY(text));
Game_add_high_score(str);
}
/*
* Event handlers
*/
static gboolean
leave_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
UNUSED(widget);
UNUSED(event);
UNUSED(user_data);
UI_pause_game();
return FALSE;
}
static gboolean
enter_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
UNUSED(widget);
UNUSED(event);
UNUSED(user_data);
UI_resume_game();
return FALSE;
}
static gboolean
redraw_window(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
UNUSED(widget);
UNUSED(event);
UNUSED(user_data);
UI_refresh();
return FALSE;
}
static gboolean
button_press(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
GdkEventButton *buttonevent = (GdkEventButton *) event;
UNUSED(widget);
UNUSED(user_data);
Game_button_press((int)buttonevent->x, (int)buttonevent->y);
return FALSE;
}
static gboolean
button_release(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
GdkEventButton *buttonevent = (GdkEventButton *) event;
UNUSED(widget);
UNUSED(user_data);
Game_button_release((int)buttonevent->x, (int)buttonevent->y);
return FALSE;
}
static int
timer_tick(gpointer arg) {
UNUSED(arg);
UI_restart_timer();
Game_update();
return TRUE;
}
/*
* Cursor handling
*/
#include "bitmaps/apple.xbm"
#include "bitmaps/bsd.xbm"
#include "bitmaps/hurd.xbm"
#include "bitmaps/linux.xbm"
#include "bitmaps/next.xbm"
#include "bitmaps/os2.xbm"
#include "bitmaps/palm.xbm"
#include "bitmaps/redhat.xbm"
#include "bitmaps/sgi.xbm"
#include "bitmaps/sun.xbm"
#include "bitmaps/bucket.xbm"
#include "bitmaps/hand_down.xbm"
#include "bitmaps/hand_down_mask.xbm"
#include "bitmaps/hand_up.xbm"
#include "bitmaps/hand_up_mask.xbm"
typedef struct cursormap {
const char *name;
int width, height;
const char *data, *maskdata;
} cursormap;
#define CURSOR_ADD(x) \
{#x, x ## _width, x ## _height, x ## _bits, NULL}
#define CURSOR_ADD_MASKED(x) \
{#x, x ## _width, x ## _height, x ## _bits, x ## _mask_bits}
static cursormap cursors[] = {
CURSOR_ADD(apple), CURSOR_ADD(bsd), CURSOR_ADD(hurd),
CURSOR_ADD(linux), CURSOR_ADD(next), CURSOR_ADD(os2), CURSOR_ADD(palm),
CURSOR_ADD(redhat), CURSOR_ADD(sgi), CURSOR_ADD(sun),
CURSOR_ADD(bucket),
CURSOR_ADD_MASKED(hand_up), CURSOR_ADD_MASKED(hand_down),
{NULL, 0, 0, NULL, NULL},
};
static void
gtk_ui_set_cursor(MCursor *cursor) {
gdk_window_set_cursor(field->window, cursor->cursor);
}
static void
gtk_ui_load_cursor(const char *name, int masked, MCursor **cursorp) {
MCursor *cursor;
GdkBitmap *bitmap, *mask;
cursormap *c;
cursor = xalloc(sizeof *cursor);
for (c = cursors; c->name != NULL; c++)
if (strcmp(name, c->name) == 0)
break;
if (c->name == NULL)
fatal("couldn't load cursor: %s", name);
bitmap = gdk_bitmap_create_from_data(field->window, c->data,
c->width, c->height);
if (masked == CURSOR_SEP_MASK)
mask = gdk_bitmap_create_from_data(field->window, c->maskdata,
c->width, c->height);
else
mask = bitmap;
cursor->cursor = gdk_cursor_new_from_pixmap(bitmap, mask,
&black, &white,
c->width/2, c->height/2);
*cursorp = cursor;
}
/*
* Pixmap handling
*/
static void
gtk_ui_load_picture(const char *name, int trans, Picture **pictp) {
Picture *pict;
char file[255];
GdkBitmap *mask;
UNUSED(trans);
pict = xalloc(sizeof *pict);
printf("load file %s/pixmaps/%s.xpm\n", pictdir, name);
sprintf(file, "%s/pixmaps/%s.xpm", pictdir, name);
pict->pix = gdk_pixmap_create_from_xpm(toplevel->window, &mask,
NULL, file);
if (pict->pix == NULL)
fatal("error reading %s", file);
pict->mask = mask;
pict->gc = gdk_gc_new(toplevel->window);
gdk_gc_set_exposures(pict->gc, FALSE);
gdk_gc_set_clip_mask(pict->gc, mask);
gdk_window_get_size(pict->pix, &pict->width, &pict->height);
*pictp = pict;
}
static void
gtk_ui_set_icon(Picture *icon) {
gdk_window_set_icon(toplevel->window, NULL, icon->pix, icon->mask);
}
static int
gtk_ui_picture_width(Picture *pict) {
return (pict->width);
}
static int
gtk_ui_picture_height(Picture *pict) {
return (pict->height);
}
/*
* Graphics operations
*/
static void
gtk_ui_clear_window(void) {
gdk_draw_rectangle(offscreen, field->style->white_gc, TRUE, 0, 0,
screensize, screensize);
}
static void
gtk_ui_refresh_window(void) {
gdk_draw_pixmap(field->window, stdgc, offscreen, 0, 0, 0, 0,
screensize, screensize);
}
static void
gtk_ui_draw_image(Picture *pict, int x, int y) {
gdk_gc_set_clip_origin(pict->gc, x, y);
gdk_draw_pixmap(offscreen, pict->gc, pict->pix, 0, 0, x, y,
pict->width, pict->height);
}
static void
gtk_ui_draw_line(int x1, int y1, int x2, int y2) {
gdk_draw_line(offscreen, stdgc, x1, y1, x2, y2);
}
static void
gtk_ui_draw_string(const char *str, int x, int y) {
gdk_draw_string(offscreen, font, stdgc, x, y, str);
}
/*
* Timer operations
*/
static void
gtk_ui_start_timer(int ms) {
if (timer == 0)
timer = gtk_timeout_add(ms, timer_tick, NULL);
}
static void
gtk_ui_stop_timer(void) {
if (timer != 0)
gtk_timeout_remove(timer);
timer = 0;
}
static int
gtk_ui_timer_active(void) {
return (!!timer);
}
/*
* Main Loop
*/
static void
gtk_ui_main_loop(void) {
gtk_main();
}
/*
* Initialization
*/
static void
gtk_ui_initialize(int *argc, char **argv) {
struct stat stats;
gtk_init(argc, &argv);
toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
timer = 0;
gtk_window_set_title(GTK_WINDOW(toplevel), "XBill");
gtk_signal_connect(GTK_OBJECT(toplevel), "delete_event",
GTK_SIGNAL_FUNC(quit_game), NULL);
if (stat(IMAGES, &stats) == 0)
pictdir = IMAGES;
else
pictdir = ".";
}
static GtkWidget *
new_menu_item(GtkWidget *menu, int dialog) {
GtkWidget *menu_item;
menu_item = gtk_menu_item_new_with_label(UI_menu_string(dialog));
gtk_menu_append(GTK_MENU(menu), menu_item);
gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate",
gtk_ui_popup_dialog, (gpointer) dialog);
return (menu_item);
}
static GtkWidget *
CreateMenuBar(void) {
GtkWidget *menubar;
GtkWidget *game_item, *game_menu;
GtkWidget *info_item, *info_menu;
GtkWidget *tearoff;
menubar = gtk_menu_bar_new();
game_item = gtk_menu_item_new_with_label("Game");
game_menu = gtk_menu_new();
tearoff = gtk_tearoff_menu_item_new();
gtk_menu_append(GTK_MENU(game_menu), tearoff);
new_menu_item(game_menu, DIALOG_NEWGAME);
pausebutton = new_menu_item(game_menu, DIALOG_PAUSEGAME);
new_menu_item(game_menu, DIALOG_WARPLEVEL);
new_menu_item(game_menu, DIALOG_HIGHSCORE);
new_menu_item(game_menu, DIALOG_QUITGAME);
gtk_menu_bar_append(GTK_MENU_BAR(menubar), game_item);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(game_item), game_menu);
info_item = gtk_menu_item_new_with_label("Info");
info_menu = gtk_menu_new();
tearoff = gtk_tearoff_menu_item_new();
gtk_menu_append(GTK_MENU(info_menu), tearoff);
new_menu_item(info_menu, DIALOG_STORY);
new_menu_item(info_menu, DIALOG_RULES);
new_menu_item(info_menu, DIALOG_ABOUT);
gtk_menu_bar_append(GTK_MENU_BAR(menubar), info_item);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(info_item), info_menu);
return menubar;
}
static GtkWidget *
CreateDrawingArea(int width, int height) {
GtkWidget *w = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
return w;
}
static void
gtk_ui_make_main_window(int size) {
GdkWindowHints flags;
GdkGeometry geom;
gint winwidth, winheight;
screensize = size;
base = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(toplevel), base);
menubar = CreateMenuBar();
gtk_box_pack_start(GTK_BOX(base), menubar, FALSE, FALSE, 0);
field = CreateDrawingArea(size, size);
gtk_box_pack_start(GTK_BOX(base), field, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(field), "button-press-event",
GTK_SIGNAL_FUNC(button_press), NULL);
gtk_signal_connect(GTK_OBJECT(field), "button-release-event",
GTK_SIGNAL_FUNC(button_release), NULL);
gtk_signal_connect(GTK_OBJECT(field), "enter-notify-event",
GTK_SIGNAL_FUNC(enter_window), NULL);
gtk_signal_connect(GTK_OBJECT(field), "leave-notify-event",
GTK_SIGNAL_FUNC(leave_window), NULL);
gtk_signal_connect(GTK_OBJECT(field), "expose-event",
GTK_SIGNAL_FUNC(redraw_window), NULL);
gtk_widget_set_events(field, GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_EXPOSURE_MASK);
gtk_widget_show_all(toplevel);
gdk_window_get_size(toplevel->window, &winwidth, &winheight);
geom.min_width = geom.max_width = geom.base_width = winwidth;
geom.min_height = geom.max_height = geom.base_height = winheight;
geom.width_inc = geom.height_inc = 0;
flags = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE |
GDK_HINT_RESIZE_INC;
gdk_window_set_geometry_hints(toplevel->window, &geom, flags);
gdk_color_parse("white", &white);
gdk_color_parse("black", &black);
}
static void
gtk_ui_graphics_init(void) {
offscreen = gdk_pixmap_new(field->window, screensize, screensize, -1);
stdgc = gdk_gc_new(offscreen);
gdk_gc_set_exposures(stdgc, FALSE);
gdk_gc_set_line_attributes(stdgc, 2, GDK_LINE_SOLID, GDK_CAP_ROUND,
GDK_JOIN_MITER);
font = gdk_font_load("fixed");
}
static GtkWidget *
new_button(GtkWidget *dialog, const char *text, GtkSignalFunc func,
GtkObject *obj)
{
GtkWidget *button = gtk_button_new_with_label(text);
if (func != NULL)
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
func, obj);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gtk_widget_hide),
GTK_OBJECT(dialog));
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(popdown), NULL);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
button);
gtk_widget_show(button);
return button;
}
static void
CreateDialog(int index, int hascancel, Picture *icon,
const char *buttonlabel, GtkSignalFunc func)
{
GtkWidget *dialog, *pixmap, *label, *hbox;
dialog = gtk_dialog_new();
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
hbox = gtk_hbox_new(FALSE, 0);
if (icon != NULL) {
pixmap = gtk_pixmap_new(icon->pix, icon->mask);
gtk_container_add(GTK_CONTAINER(hbox), pixmap);
}
label = gtk_label_new(UI_dialog_string(index));
gtk_container_add(GTK_CONTAINER(hbox), label);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
gtk_widget_show_all(hbox);
if (buttonlabel == NULL)
buttonlabel = "OK";
new_button(dialog, buttonlabel, func, NULL);
if (hascancel)
new_button(dialog, "Cancel", NULL, NULL);
gtk_widget_realize(dialog);
dialogs[index] = dialog;
}
static void
CreateEnterText(int index, GtkSignalFunc func) {
GtkWidget *dialog, *label, *entry;
dialog = gtk_dialog_new();
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
label = gtk_label_new(UI_dialog_string(index));
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
gtk_widget_show(label);
entry = gtk_entry_new_with_max_length(20);
gtk_signal_connect_object(GTK_OBJECT(entry), "activate",
func, GTK_OBJECT(entry));
gtk_signal_connect_object(GTK_OBJECT(entry), "activate",
GTK_SIGNAL_FUNC(gtk_widget_hide),
GTK_OBJECT(dialog));
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
gtk_widget_show(entry);
new_button(dialog, "OK", func, GTK_OBJECT(entry));
gtk_widget_realize(dialog);
dialogs[index] = dialog;
}
static void
CreatePixmapBox(int index, Picture *logo, Picture *pix) {
GtkWidget *dialog, *pixmap, *label;
const char *text = UI_dialog_string(index);
dialog = gtk_dialog_new();
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
pixmap = gtk_pixmap_new(logo->pix, logo->mask);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), pixmap);
gtk_widget_show(pixmap);
if (pix != NULL) {
pixmap = gtk_pixmap_new(pix->pix, pix->mask);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
pixmap);
gtk_widget_show(pixmap);
}
if (text != NULL) {
label = gtk_label_new(text);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
label);
gtk_widget_show(label);
}
new_button(dialog, "OK", NULL, NULL);
gtk_widget_realize(dialog);
dialogs[index] = dialog;
}
static void
gtk_ui_create_dialogs(Picture *logo, Picture *icon, Picture *about) {
CreateDialog(DIALOG_NEWGAME, 1, NULL, NULL, new_game);
CreateDialog(DIALOG_PAUSEGAME, 0, icon, "Continue", NULL);
CreateEnterText(DIALOG_WARPLEVEL, warp_apply);
CreateDialog(DIALOG_HIGHSCORE, 0, NULL, NULL, NULL);
CreateDialog(DIALOG_QUITGAME, 1, NULL, NULL, quit_game);
CreatePixmapBox(DIALOG_STORY, logo, NULL);
CreatePixmapBox(DIALOG_RULES, logo, NULL);
CreatePixmapBox(DIALOG_ABOUT, logo, about);
CreateDialog(DIALOG_SCORE, 0, NULL, NULL, NULL);
CreateDialog(DIALOG_ENDGAME, 0, NULL, "Nuts!", NULL);
CreateEnterText(DIALOG_ENTERNAME, enter_name);
}
static void
set_label(GtkWidget *dialog, const char *str) {
GList *list;
GtkWidget *hbox = NULL;
list = gtk_container_children(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox));
while (list != NULL) {
GtkWidget *w = (GtkWidget *) list->data;
list = g_list_next(list);
if (GTK_IS_HBOX(w)) {
hbox = w;
break;
}
}
if (hbox == NULL)
return;
list = gtk_container_children(GTK_CONTAINER(hbox));
while (list != NULL) {
GtkWidget *w = (GtkWidget *) list->data;
list = g_list_next(list);
if (GTK_IS_LABEL(w)) {
gtk_label_set_text(GTK_LABEL(w), str);
return;
}
}
}
static void
gtk_ui_update_dialog(int index, const char *str) {
set_label(dialogs[index], str);
}
static void
gtk_ui_set_pausebutton(int active) {
if (pausebutton != NULL)
gtk_widget_set_sensitive(pausebutton, active);
}
static struct UI_methods gtk_methods = {
gtk_ui_set_cursor,
gtk_ui_load_cursor,
gtk_ui_load_picture,
gtk_ui_set_icon,
gtk_ui_picture_width,
gtk_ui_picture_height,
gtk_ui_graphics_init,
gtk_ui_clear_window,
gtk_ui_refresh_window,
gtk_ui_draw_image,
gtk_ui_draw_line,
gtk_ui_draw_string,
gtk_ui_start_timer,
gtk_ui_stop_timer,
gtk_ui_timer_active,
gtk_ui_popup_dialog,
gtk_ui_main_loop,
gtk_ui_initialize,
gtk_ui_make_main_window,
gtk_ui_create_dialogs,
gtk_ui_set_pausebutton,
gtk_ui_update_dialog,
};
void
gtk_ui_setmethods(UI_methods **methodsp) {
*methodsp = &gtk_methods;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yunsongyu/xbill.git
git@gitee.com:yunsongyu/xbill.git
yunsongyu
xbill
xbill
master

搜索帮助