/*************************************************************************** kmenu.c Copyright (C) 1999 Christoph Reichenbach This program may be modified and copied freely according to the terms of the GNU general public license (GPL), as long as the above copyright notice and the licensing information contained herein are preserved. Please refer to www.gnu.org for licensing details. This work is provided AS IS, without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantibility, noninfringement, and fitness for a specific purpose. The author will not be held liable for any damage caused by this work or derivatives of it. By using this source code, you agree to the licensing terms as stated above. Please contact the maintainer for bug reports or inquiries. Current Maintainer: Christoph Reichenbach (CJR) [jameson@linuxgames.com] ***************************************************************************/ #include "sci/include/sciresource.h" #include "sci/include/engine.h" #include "sci/include/sci_widgets.h" reg_t kAddMenu(state_t *s, int funct_nr, int argc, reg_t *argv) { char *name = kernel_dereference_char_pointer(s, argv[0], 0); char *contents = kernel_dereference_char_pointer(s, argv[1], 0); menubar_add_menu(s->gfx_state, s->menubar, name, contents, s->titlebar_port->font_nr, argv[1]); return s->r_acc; } reg_t kSetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) { int index = UKPV(0); int i = 2; while (i < argc) { menubar_set_attribute(s, (index >> 8) - 1, (index & 0xff) - 1, UKPV(i - 1), argv[i]); i += 2; } return s->r_acc; } reg_t kGetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) { int index = UKPV(0); return menubar_get_attribute(s, (index >> 8) - 1, (index & 0xff) - 1, UKPV(1)); } reg_t kDrawStatus(state_t *s, int funct_nr, int argc, reg_t *argv) { reg_t text = argv[0]; int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground); int bgcolor = SKPV_OR_ALT(2, s->status_bar_background); s->titlebar_port->color.visual = *(get_pic_color(s, fgcolor)); s->titlebar_port->color.mask = GFX_MASK_VISUAL; s->titlebar_port->bgcolor.visual = *(get_pic_color(s, bgcolor)); s->titlebar_port->bgcolor.mask = GFX_MASK_VISUAL; s->status_bar_foreground=fgcolor; s->status_bar_background=bgcolor; if (NULL != s->status_bar_text) { sci_free(s->status_bar_text); s->status_bar_text = NULL; } if (text.segment) s->status_bar_text = sci_strdup(kernel_dereference_char_pointer(s, text, 0)); sciw_set_status_bar(s, s->titlebar_port, s->status_bar_text, fgcolor, bgcolor); gfxop_update(s->gfx_state); return s->r_acc; } reg_t kDrawMenuBar(state_t *s, int funct_nr, int argc, reg_t *argv) { if (SKPV(0)) sciw_set_menubar(s, s->titlebar_port, s->menubar, -1); else sciw_set_status_bar(s, s->titlebar_port, NULL, 0, 0); s->titlebar_port->draw(GFXW(s->titlebar_port), gfx_point(0, 0)); gfxop_update(s->gfx_state); return s->r_acc; } #define ABOUT_FREESCI_PAGES_NR 7 static struct { const char *title; const char *body; int fgcolor, bgcolor; } _about_freesci_pages[ABOUT_FREESCI_PAGES_NR] = { {"FreeSCI hackers and contributors", "Alexander R. Angas\nDirectX 8 driver, Event sound server, Generic memory functions" "\n\n" "Anders Baden Nielsen\nPPC testing" "\n\n" "Bas Zoetekouw\nMan pages, debian package management, CVS maintenance" "\n\n" "Carl Muckenhoupt\nSources to the SCI resource viewer tools that started it all" "\n\n" "Chris Kehler\nMakefile enhancements" "\n\n" "Christoph Reichenbach\nUN*X code, VM/Graphics/Sound/other infrastructure" "\n\n" "Christopher T. Lansdown\nOriginal CVS maintainer, Alpha compatibility fixes" ,0, 15}, {"More FreeSCI hackers and contributors", "Claudio Matsuoka\nCVS snapshots, daily builds, BeOS and cygwin ports" "\n\n" "Dark Minister\nSCI research (bytecode and parser)" "\n\n" "Dmitry Jemerov\nPort to the Win32 platform, numerous bugfixes" "\n\n" "Emmanuel Jeandel\nBugfixes and bug reports" "\n\n" "Francois-R Boyer\nMT-32 information and mapping code" "\n\n" "George Reid\nFreeBSD package management" "\n\n" "Hubert Maier\nAmigaOS 4 port" ,0, 15}, {"Even more FreeSCI hackers & contributors", "Hugues Valois\nGame selection menu" "\n\n" "Johannes Manhave\nDocument format translation" "\n\n" "Jordi Vilalta\nNumerous code and website clean-up patches" "\n\n" "Lars Skovlund\nProject maintenance, most documentation, bugfixes, SCI1 support" "\n\n" "Magnus Reftel\nHeap implementation, Python class viewer, bugfixes" "\n\n" "Matt Hargett\nClean-ups, bugfixes, Hardcore QA, Win32" "\n\n" "Max Horn\nSetJump implementation" ,0, 15}, {"Still more of them", "Paul David Doherty\nGame version information" "\n\n" "Petr Vyhnak\nThe DCL-INFLATE algorithm, many Win32 improvements" "\n\n" "Rainer Canavan\nIRIX MIDI driver and bug fixes" "\n\n" "Rainer De Temple\nSCI research" "\n\n" "Ravi I.\nSCI0 sound resource specification" "\n\n" "Ruediger Hanke\nPort to the MorphOS platform" "\n\n" "Rune Orsval\nConfiguration file editor" ,0, 15}, {"Is there no end to these contributors?", "Rickard Lind\nMT32->GM MIDI mapping magic, sound research" "\n\n" "Rink Springer\nPort to the DOS platform, several bug fixes" "\n\n" "Robey Pointer\nBug tracking system hosting" "\n\n" "Sergey Lapin\nPort of Carl's type 2 decompression code" "\n\n" "Solomon Peachy\nSDL ports and much of the sound subsystem" "\n\n" "Vyacheslav Dikonov\nConfig script improvements" "\n\n" "Walter van Niftrik\nPorts to the Dreamcast and GP32 platforms", 0, 15}, {"The CSCI5573 Team at CU Boulder", "Xiaojun Chen\nSean Terrell\nChristoph Reichenbach\n\n" "Special thanks to Prof. Dr. Gary Nutt\n\nfor allowing the FreeSCI VM extension as a\ncourse project in his Advanced OS course" ,0, 15}, {"Special Thanks", "Special Thanks as well\n\n\nto the linuxgames.com and telefragged.com crew\nfor hosting us\n\n" "To the savannah.gnu.org staff\nfor hosting our mailing list\n\n" "To Bob Heitman and Corey Cole for their support" ,0, 15} }; void about_freesci(state_t *s) { int page; gfxw_port_t *port; int bodyfont, titlefont; resource_t *bodyfont_res = NULL; int i; titlefont = s->titlebar_port->font_nr; i = 999; while (!bodyfont_res && (i > -1)) bodyfont_res = scir_test_resource(s->resmgr, sci_font, i--); if (i == -1) { sciprintf("Sorry, couldn't find a font...\n"); return; } bodyfont = i+1; for (page = 0; page < ABOUT_FREESCI_PAGES_NR; ++page) { sci_event_t event; int cont = 2; int width, height, width2, foo; _about_freesci_pages[page].fgcolor = 0; _about_freesci_pages[page].bgcolor = 15; gfxop_get_text_params(s->gfx_state, bodyfont, _about_freesci_pages[page].body, 300, &width, &height, 0, NULL, NULL, NULL); gfxop_get_text_params(s->gfx_state, titlefont, _about_freesci_pages[page].title, 300, &width2, &foo, 0, NULL, NULL, NULL); width += 4; width2 += 4; height += 12; if (width2 > width) width = width2; port = sciw_new_window(s, gfx_rect(156 - (width >> 1), 100 - (height >> 1), width, height), bodyfont, s->ega_colors[_about_freesci_pages[page].fgcolor], s->ega_colors[_about_freesci_pages[page].bgcolor], titlefont, s->ega_colors[15], s->ega_colors[0], _about_freesci_pages[page].title, WINDOW_FLAG_TITLE); port->add(GFXWC(port), GFXW(gfxw_new_text(s->gfx_state, gfx_rect(0,0,width,height), bodyfont, _about_freesci_pages[page].body, ALIGN_CENTER, ALIGN_CENTER, port->color, port->color, port->bgcolor, 0) )); s->visual->add(GFXWC(s->visual), GFXW(port)); port->add_dirty_abs(GFXWC(port), gfx_rect_fullscreen, 1); s->visual->draw(GFXW(s->visual), gfx_point(0,0)); gfxop_update(s->gfx_state); while (cont) { event = gfxop_get_event(s->gfx_state, SCI_EVT_ANY); if (event.type == SCI_EVT_MOUSE_RELEASE || event.type == SCI_EVT_MOUSE_PRESS) --cont; if (event.type == SCI_EVT_QUIT) { quit_vm(); return; } if (event.type == SCI_EVT_KEYBOARD) cont = 0; gfxop_usleep(s->gfx_state, 25000); } port->widfree(GFXW(port)); s->visual->draw(GFXW(s->visual), gfx_point(0,0)); gfxop_update(s->gfx_state); } } static inline int _menu_go_down(state_t *s, int menu_nr, int item_nr) { int seeker, max = s->menubar->menus[menu_nr].items_nr; seeker = item_nr + 1; while ((seeker < max) && !menubar_item_valid(s, menu_nr, seeker)) ++seeker; if (seeker != max) return seeker; else return item_nr; } #define FULL_REDRAW \ s->visual->draw(GFXW(s->visual), gfx_point(0, 0)); \ gfxop_update(s->gfx_state); reg_t kMenuSelect(state_t *s, int funct_nr, int argc, reg_t *argv) { reg_t event = argv[0]; /*int pause_sound = UKPV_OR_ALT(1, 1);*/ /* FIXME: Do this eventually */ int claimed = 0; int type = GET_SEL32V(event, type); int message = GET_SEL32V(event, message); int modifiers = GET_SEL32V(event, modifiers); int menu_nr = -1, item_nr = 0; menu_item_t *item; int menu_mode = 0; /* Menu is active */ int mouse_down = 0; gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen); /* Check whether we can claim the event directly as a keyboard or said event */ if (type & (SCI_EVT_KEYBOARD | SCI_EVT_SAID)) { int menuc, itemc; if ((type == SCI_EVT_KEYBOARD) && (message == SCI_K_ESC)) menu_mode = 1; else if ((type == SCI_EVT_SAID) || message) { /* Don't claim 0 keyboard event */ SCIkdebug(SCIkMENU,"Menu: Got %s event: %04x/%04x\n", ((type == SCI_EVT_SAID)? "SAID":"KBD"), message, modifiers); for (menuc = 0; menuc < s->menubar->menus_nr; menuc++) for (itemc = 0; itemc < s->menubar->menus[menuc].items_nr; itemc++) { item = s->menubar->menus[menuc].items + itemc; SCIkdebug(SCIkMENU,"Menu: Checking against %s: %04x/%04x (type %d, %s)\n", item->text? item->text : "--bar--", item->key, item->modifiers, item->type, item->enabled? "enabled":"disabled"); if (((item->type == MENU_TYPE_NORMAL) && (item->enabled)) && (((type == SCI_EVT_KEYBOARD) /* keyboard event */ && menubar_match_key(item, message, modifiers)) || ((type == SCI_EVT_SAID) /* Said event */ && (item->flags & MENU_ATTRIBUTE_FLAGS_SAID) && (said(s, item->said, (s->debug_mode & (1 << SCIkPARSER_NR))) != SAID_NO_MATCH) ) ) ) { /* Claim the event */ SCIkdebug(SCIkMENU,"Menu: Event CLAIMED for %d/%d\n", menuc, itemc); claimed = 1; menu_nr = menuc; item_nr = itemc; } } } } if ((type == SCI_EVT_MOUSE_PRESS) && (s->gfx_state->pointer_pos.y < 10)) { menu_mode = 1; mouse_down = 1; } if (menu_mode) { int old_item; int old_menu; gfxw_port_t *port = NULL; item_nr = -1; /* Default to menu 0, unless the mouse was used to generate this effect */ if (mouse_down) menubar_map_pointer(s, &menu_nr, &item_nr, port); else menu_nr = 0; sciw_set_menubar(s, s->titlebar_port, s->menubar, menu_nr); FULL_REDRAW; old_item = -1; old_menu = -1; while (menu_mode) { sci_event_t ev = gfxop_get_event(s->gfx_state, SCI_EVT_ANY); claimed = 0; switch (ev.type) { case SCI_EVT_QUIT: quit_vm(); return NULL_REG; case SCI_EVT_KEYBOARD: switch (ev.data) { case '`': if (ev.buckybits & SCI_EVM_CTRL) s->visual->print(GFXW(s->visual), 0); break; case SCI_K_ESC: menu_mode = 0; break; case SCI_K_ENTER: menu_mode = 0; if ((item_nr >= 0) && (menu_nr >= 0)) claimed = 1; break; case SCI_K_LEFT: if (menu_nr > 0) --menu_nr; else menu_nr = s->menubar->menus_nr - 1; item_nr = _menu_go_down(s, menu_nr, -1); break; case SCI_K_RIGHT: if (menu_nr < (s->menubar->menus_nr - 1)) ++menu_nr; else menu_nr = 0; item_nr = _menu_go_down(s, menu_nr, -1); break; case SCI_K_UP: if (item_nr > -1) { do { --item_nr; } while ((item_nr > -1) && !menubar_item_valid(s, menu_nr, item_nr)); } break; case SCI_K_DOWN: { item_nr = _menu_go_down(s, menu_nr, item_nr); } break; } break; case SCI_EVT_MOUSE_RELEASE: menu_mode = (s->gfx_state->pointer_pos.y < 10); claimed = !menu_mode && !menubar_map_pointer(s, &menu_nr, &item_nr, port); mouse_down = 0; break; case SCI_EVT_MOUSE_PRESS: mouse_down = 1; break; case SCI_EVT_NONE: gfxop_usleep(s->gfx_state, 2500); break; } if (mouse_down) menubar_map_pointer(s, &menu_nr, &item_nr, port); if ((item_nr > -1 && old_item == -1) || (menu_nr != old_menu)) { /* Update menu */ sciw_set_menubar(s, s->titlebar_port, s->menubar, menu_nr); if (port) port->widfree(GFXW(port)); port = sciw_new_menu(s, s->titlebar_port, s->menubar, menu_nr); s->wm_port->add(GFXWC(s->wm_port), GFXW(port)); if (item_nr > -1) old_item = -42; /* Enforce redraw in next step */ else { FULL_REDRAW; } } /* ...if the menu changed. */ /* Remove the active menu item, if neccessary */ if (item_nr != old_item) { port = sciw_unselect_item(s, port, s->menubar->menus + menu_nr, old_item); port = sciw_select_item(s, port, s->menubar->menus + menu_nr, item_nr); FULL_REDRAW; } old_item = item_nr; old_menu = menu_nr; } /* while (menu_mode) */ if (port) { port->widfree(GFXW(port)); port = NULL; sciw_set_status_bar(s, s->titlebar_port, s->status_bar_text, s->status_bar_foreground, s->status_bar_background); gfxop_update(s->gfx_state); } FULL_REDRAW; } if (claimed) { PUT_SEL32(event, claimed, make_reg(0, 1)); if (menu_nr > -1) { s->r_acc = make_reg(0, ((menu_nr + 1) << 8) | (item_nr + 1)); #ifdef MENU_FREESCI_BLATANT_PLUG if (s->menubar->menus[menu_nr].items[item_nr].flags == MENU_FREESCI_BLATANT_PLUG) about_freesci(s); #endif } else s->r_acc = NULL_REG; SCIkdebug(SCIkMENU, "Menu: Claim -> %04x\n", s->r_acc.offset); } else s->r_acc = NULL_REG; /* Not claimed */ return s->r_acc; }