diff options
Diffstat (limited to 'engines/sci/engine/kmenu.cpp')
-rw-r--r-- | engines/sci/engine/kmenu.cpp | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp new file mode 100644 index 0000000000..bd676213f4 --- /dev/null +++ b/engines/sci/engine/kmenu.cpp @@ -0,0 +1,533 @@ +/*************************************************************************** + 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; + 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 event = gfxop_get_event(s->gfx_state, SCI_EVT_ANY); + + claimed = 0; + + switch (event.type) { + case SCI_EVT_QUIT: + quit_vm(); + return NULL_REG; + + case SCI_EVT_KEYBOARD: + switch (event.data) { + + case '`': + if (event.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; +} |