+static void cb_new(utk_event *ev, void *data)
+{
+ utk_show(uiwin_new);
+ uigrab = uiwin_new;
+}
+
+static void cb_new_ok(utk_event *ev, void *data)
+{
+ static int levsz[] = {16, 24, 32};
+ int sz;
+ struct level newlvl;
+
+ sz = levsz[utk_get_selected(cbox_newsz)];
+
+ if(init_level(&newlvl, sz, sz) == -1) {
+ utk_message_dialog("failed to create new level", UTK_MSG_TYPE_ERROR,
+ UTK_MSG_BN_OK, cb_cancel, 0);
+ return;
+ }
+
+ destroy_level(&lvl);
+ destroy_lview();
+
+ lvl = newlvl;
+ init_lview(&lvl);
+
+ utk_hide(uiwin_new);
+ uigrab = 0;
+}
+
+static void cb_open(utk_event *ev, void *data)
+{
+ uigrab = utk_file_dialog(UTK_FILE_DIALOG_OPEN, 0, "Level file (*.lvl) [.lvl]", 0, cb_open_ok, 0);
+}
+
+static void cb_open_ok(utk_event *ev, void *data)
+{
+ char *errmsg = 0;
+ const char *path;
+
+ utk_widget *dlg = utk_event_widget(ev);
+ path = utk_file_dialog_path(dlg);
+ printf("selected: %s\n", path);
+ if(load_level(&lvl, path) == -1) {
+ errmsg = alloca(strlen(path) + 32);
+ sprintf(errmsg, "Failed to load level: %s", path);
+ }
+ utk_destroy_window(dlg);
+ if(uigrab == dlg) uigrab = 0;
+
+ if(errmsg) {
+ uigrab = utk_message_dialog(errmsg, UTK_MSG_TYPE_ERROR, UTK_MSG_BN_OK, cb_cancel, 0);
+ }
+}
+
+static void cb_save(utk_event *ev, void *data)
+{
+ uigrab = utk_file_dialog(UTK_FILE_DIALOG_SAVE, 0, "Level file (*.lvl) [.lvl]", 0, cb_save_ok, 0);
+}
+
+static void cb_save_ok(utk_event *ev, void *data)
+{
+ char *errmsg = 0;
+ const char *path;
+
+ utk_widget *dlg = utk_event_widget(ev);
+ path = utk_file_dialog_path(dlg);
+ printf("selected: %s\n", path);
+ if(save_level(&lvl, path) == -1) {
+ errmsg = alloca(strlen(path) + 32);
+ sprintf(errmsg, "Failed to save level file: %s", path);
+ }
+ utk_destroy_window(dlg);
+ if(uigrab == dlg) uigrab = 0;
+
+ if(errmsg) {
+ uigrab = utk_message_dialog(errmsg, UTK_MSG_TYPE_ERROR, UTK_MSG_BN_OK, cb_cancel, 0);
+ }
+}
+
+static void cb_cancel(utk_event *ev, void *data)
+{
+ if(!data) data = utk_get_window(utk_event_widget(ev));
+
+ if(utk_is_dialog(data)) {
+ utk_destroy_window(data);
+ } else {
+ utk_hide(data);
+ }
+ uigrab = 0;
+}
+
+static void cb_toolselect(utk_event *ev, void *data)
+{
+ utk_widget *w = utk_event_widget(ev);
+ if(utk_is_checked(w)) {
+ tool = (intptr_t)data;
+ }
+}
+
+static int parse_args(int argc, char **argv)
+{
+ int i;
+
+ for(i=1; i<argc; i++) {
+ if(argv[i][0] == '-') {
+ if(strcmp(argv[i], "-uiscale") == 0) {
+ if(!argv[++i] || !(uiscale = atoi(argv[i]))) {
+ fprintf(stderr, "-uiscale should be followed by a positive number\n");
+ return -1;
+ }
+ } else if(strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) {
+ printf("Usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" -uiscale <scale>: UI scale factor (default: 1)\n");
+ printf(" -h,-help: print usage and exit\n");
+ exit(0);
+ } else {
+ fprintf(stderr, "unknown option: %s\n", argv[i]);
+ return -1;
+ }
+ } else {
+ if(opt_fname) {
+ fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+ return -1;
+ }
+ opt_fname = argv[i];
+ }
+ }
+ return 0;
+}
+
+/* --- ubertk callbacks --- */
+