bool Glulxe::init_dispatch() { int ix; /* Set up the game-ID hook. (This is ifdeffed because not all Glk libraries have this call.) */ #ifdef GI_DISPA_GAME_ID_AVAILABLE gidispatch_set_game_id_hook(&get_game_id); #endif /* GI_DISPA_GAME_ID_AVAILABLE */ /* Allocate the class hash tables. */ num_classes = gidispatch_count_classes(); classes = (classtable_t **)glulx_malloc(num_classes * sizeof(classtable_t *)); if (!classes) return false; for (ix = 0; ix < num_classes; ix++) { classes[ix] = new_classtable((glulx_random() % (uint)(101)) + 1); if (!classes[ix]) return false; } /* Set up the two callbacks. */ gidispatch_set_object_registry(&classtable_register, &classtable_unregister); gidispatch_set_retained_registry(&retained_register, &retained_unregister); /* If the library supports autorestore callbacks, set those up too. (These are only used in iosglk, currently.) */ #ifdef GIDISPATCH_AUTORESTORE_REGISTRY gidispatch_set_autorestore_registry(&glulxe_array_locate, &glulxe_array_restore); #endif /* GIDISPATCH_AUTORESTORE_REGISTRY */ return true; }
/* git_init_dispatch(): Set up the class hash tables and other startup-time stuff. */ int git_init_dispatch() { int ix; /* What with one thing and another, this *could* be called more than once. We only need to allocate the tables once. */ if (git_classes) return TRUE; /* Set up the game-ID hook. (This is ifdeffed because not all Glk libraries have this call.) */ #ifdef GI_DISPA_GAME_ID_AVAILABLE gidispatch_set_game_id_hook(&get_game_id); #endif /* GI_DISPA_GAME_ID_AVAILABLE */ /* Allocate the class hash tables. */ num_classes = gidispatch_count_classes(); git_classes = (classtable_t **)glulx_malloc(num_classes * sizeof(classtable_t *)); if (!git_classes) return FALSE; for (ix=0; ix<num_classes; ix++) { git_classes[ix] = new_classtable((glulx_random() % (glui32)(101)) + 1); if (!git_classes[ix]) return FALSE; } /* Set up the two callbacks. */ gidispatch_set_object_registry(&glulxe_classtable_register, &glulxe_classtable_unregister); gidispatch_set_retained_registry(&glulxe_retained_register, &glulxe_retained_unregister); return TRUE; }
static glui32 classes_iter(glk_object_save_t **objs) { classtable_t *ctab; classref_t *cref; glui32 num_classes; glui32 i,j,ct = 0; glk_object_save_t *o = NULL, *cur; window_t *win; stream_t *str_cur = glk_stream_get_current(); if (!objs) return 0; *objs = NULL; num_classes = gidispatch_count_classes(); ct = 0; for (i = 0; i < num_classes; i++) { // iterate everything quickly if ((ctab = classes[i])) { for (j = 0; j < CLASSHASH_SIZE; j++) { cref = ctab->bucket[j]; for ( ; cref; cref = cref->next) { if (i == 0) { window_t *win = (window_t *)cref->obj; win->store = 0; } else if (i == 1) { stream_t *str = (stream_t *)cref->obj; str->store = 0; } ct++; } } } } if (!ct) return 0; // add entries for windows with styles/pair info + the two general styles win = NULL; while ((win = gli_window_iterate_backward(win, NULL))) { if (win->type == wintype_TextBuffer || win->type == wintype_TextGrid || win->type == wintype_Pair || win->type == wintype_Graphics) ct++; } // leave off the last 2 in the event of no styles in use! if (gli_window_has_stylehints()) ct += 2; o = glulx_malloc(sizeof(glk_object_save_t) * ct); if (!o) return 0; ct = 0; win = NULL; while ((win = gli_window_iterate_backward(win, NULL))) { cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = gidisp_Class_Window; cur->id = classes_find_id_for_object(0, win); saveWin(win, &cur->obj.win); //!!!cur->obj.win = *win; win->store = TRUE; cur->iscurrent = FALSE; //(win == win_cur); classes_normalize_pointers(cur); ct++; // get stream for window if ((win->type == wintype_TextBuffer) || (win->type == wintype_TextGrid)) { // write STREAM chunk cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = gidisp_Class_Stream; cur->id = classes_find_id_for_object(1, win->str); //!!!cur->obj.str = *win->str; saveStream(win->str, &cur->obj.str); win->str->store = TRUE; cur->iscurrent = (win->str == str_cur); classes_normalize_pointers(cur); ct++; // write STYLE chunk cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = type_Style; cur->id = classes_find_id_for_object(0, win); GLK_STYLE_HINTS hints[style_NUMSTYLES]; gli_window_get_stylehints(win, hints); memcpy(cur->obj.style, hints, sizeof(GLK_STYLE_HINTS) * style_NUMSTYLES); ct++; } else if (win->type == wintype_Pair) { window_pair_t *pairwin = (window_pair_t*)win->data; // write PAIR chunk cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = type_Pair; cur->id = classes_find_id_for_object(0, win); //!!!cur->obj.pair = *((window_pair_t *)win->data); saveWinPair(pairwin, &cur->obj.pair); // set the children to their ids so we can find the pair on reload cur->obj.pair.child1 = classes_find_id_for_object(gidisp_Class_Window, pairwin->child1); cur->obj.pair.child2 = classes_find_id_for_object(gidisp_Class_Window, pairwin->child2); //!!!classes_normalize_pointers(cur); ct++; } else if (win->type == wintype_Graphics) { // write GRAPHICS chunk cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = type_Graphics; cur->id = classes_find_id_for_object(0, win); saveWinGfx((window_graphics_t *)win->data, &cur->obj.gfx); ct++; } } // now, iterate other classes; window streams should have already been accounted for, but we check this for (i = 0; i < num_classes; i++) { if ((ctab = classes[i])) { for (j = 0; j < CLASSHASH_SIZE; j++) { cref = ctab->bucket[j]; for ( ; cref; cref = cref->next) { if (i == 0) { // windows window_t *win = (window_t *)cref->obj; if (!win->store) { cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = i; cur->id = cref->id; } } else { if (i == 1) { // streams stream_t *str = (stream_t *)cref->obj; if (!str->store) { cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = i; cur->id = cref->id; //!!!cur->obj.str = *str; saveStream(str, &cur->obj.str); cur->iscurrent = (str == str_cur); classes_normalize_pointers(cur); ct++; } } else if (i == 2) { fileref_t *fref = (fileref_t *)cref->obj; cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = i; cur->id = cref->id; //!!!cur->obj.fref = *fref; saveFRef(fref, &cur->obj.fref); classes_normalize_pointers(cur); ct++; } else if (i == 3) { // won't happen here ; } } } } } } // 2 general styles if (gli_window_has_stylehints()) { GLK_STYLE_HINTS hints[style_NUMSTYLES]; cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = type_Style; cur->id = STYLEHINT_TEXT_BUFFER; gli_window_get_stylehints((winid_t)STYLEHINT_TEXT_BUFFER, hints); memcpy(cur->obj.style, hints, sizeof(GLK_STYLE_HINTS) * style_NUMSTYLES); ct++; cur = o + ct; memset(cur, 0, sizeof(glk_object_save_t)); cur->type = type_Style; cur->id = STYLEHINT_TEXT_GRID; gli_window_get_stylehints((winid_t)STYLEHINT_TEXT_GRID, hints); memcpy(cur->obj.style, hints, sizeof(GLK_STYLE_HINTS) * style_NUMSTYLES); ct++; } *objs = o; return ct; }