From efcfae742b63ca01abca64cbbfa5aa71b2dae527 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Oct 2009 14:28:20 +0000 Subject: SCI: kDrawControl for list and textedit controls also using gui class svn-id: r44925 --- engines/sci/engine/kgraphics.cpp | 122 ++++++++++++++++++++++++++--- engines/sci/gui/gui.cpp | 5 +- engines/sci/gui/gui.h | 3 +- engines/sci/gui32/gui32.cpp | 163 ++++++--------------------------------- engines/sci/gui32/gui32.h | 3 +- 5 files changed, 145 insertions(+), 151 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c09e731203..3765835295 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1014,10 +1014,10 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { enum { K_CONTROL_BUTTON = 1, K_CONTROL_TEXT = 2, - K_CONTROL_EDIT = 3, + K_CONTROL_TEXTEDIT = 3, K_CONTROL_ICON = 4, - K_CONTROL_CONTROL = 6, - K_CONTROL_CONTROL_ALIAS = 7, + K_CONTROL_LIST = 6, + K_CONTROL_LIST_ALIAS = 7, K_CONTROL_BOX = 10 }; @@ -1062,20 +1062,122 @@ static void disableCertainButtons(SegManager *segMan, Common::String gameName, r } } +void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { + SegManager *segMan = s->_segMan; + int16 type = GET_SEL32V(controlObject, type); + int16 state = GET_SEL32V(controlObject, state); + int16 x = GET_SEL32V(controlObject, nsLeft); + int16 y = GET_SEL32V(controlObject, nsTop); + GuiResourceId fontId = GET_SEL32V(controlObject, font); + reg_t textReference = GET_SEL32(controlObject, text); + Common::String text; + Common::Rect rect; + int16 mode, maxChars, cursorPos, upperPos, listCount, i; + int16 upperOffset, cursorOffset; + GuiResourceId viewId; + GuiViewLoopNo loopNo; + GuiViewCelNo celNo; + reg_t listSeeker; + Common::String *listStrings = NULL; + const char **listEntries = NULL; + + rect = Common::Rect (x, y, (int16)GET_SEL32V(controlObject, nsRight), (int16)GET_SEL32V(controlObject, nsBottom)); + if (!textReference.isNull()) + text = segMan->getString(textReference); + + switch (type) { + case K_CONTROL_BUTTON: + debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(controlObject), x, y); + s->_gui->drawControlButton(rect, controlObject, s->strSplit(text.c_str(), NULL).c_str(), fontId, state, hilite); + return; + + case K_CONTROL_TEXT: + mode = GET_SEL32V(controlObject, mode); + debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d\n", PRINT_REG(controlObject), text.c_str(), x, y, mode); + s->_gui->drawControlText(rect, controlObject, s->strSplit(text.c_str(), NULL).c_str(), fontId, mode, state, hilite); + return; + + case K_CONTROL_TEXTEDIT: + mode = GET_SEL32V(controlObject, mode); + maxChars = GET_SEL32V(controlObject, max); + cursorPos = GET_SEL32V(controlObject, cursor); + debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d\n", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y); + s->_gui->drawControlTextEdit(rect, controlObject, s->strSplit(text.c_str(), NULL).c_str(), fontId, mode, state, cursorPos, maxChars, hilite); + return; + + case K_CONTROL_ICON: + viewId = GET_SEL32V(controlObject, view); + loopNo = sign_extend_byte(GET_SEL32V(controlObject, loop)); + celNo = sign_extend_byte(GET_SEL32V(controlObject, cel)); + debugC(2, kDebugLevelGraphics, "drawing icon control %04x:%04x to %d,%d\n", PRINT_REG(controlObject), x, y - 1); + s->_gui->drawControlIcon(rect, controlObject, viewId, loopNo, celNo, state, hilite); + return; + + case K_CONTROL_LIST: + case K_CONTROL_LIST_ALIAS: + maxChars = GET_SEL32V(controlObject, x); // max chars per entry + // NOTE: most types of pointer dereferencing don't like odd offsets + if (maxChars & 1) { + warning("List control with odd maxChars %d. This is not yet implemented for all types of segments", maxChars); + } + cursorOffset = GET_SEL32V(controlObject, cursor); + if (s->_kernel->_selectorCache.topString != -1) { + // Games from early SCI1 onwards use topString + upperOffset = GET_SEL32V(controlObject, topString); + } else { + // Earlier games use lsTop + upperOffset = GET_SEL32V(controlObject, lsTop); + } + + // Count string entries in NULL terminated string list + listCount = 0; listSeeker = textReference; + while (s->_segMan->strlen(listSeeker) > 0) { + listCount++; + listSeeker.offset += maxChars; + } + + // TODO: This is rather convoluted... It would be a lot cleaner + // if sciw_new_list_control would take a list of Common::String + cursorPos = 0; upperPos = 0; + if (listCount) { + // We create a pointer-list to the different strings, we also find out whats upper and cursor position + listSeeker = textReference; + listEntries = (const char**)malloc(sizeof(char *) * listCount); + listStrings = new Common::String[listCount]; + for (i = 0; i < listCount; i++) { + listStrings[i] = s->_segMan->getString(listSeeker); + listEntries[i] = listStrings[i].c_str(); + if (listSeeker.offset == upperOffset) + upperPos = i; + if (listSeeker.offset == cursorOffset) + cursorPos = i; + listSeeker.offset += maxChars; + } + } + + debugC(2, kDebugLevelGraphics, "drawing list control %04x:%04x to %d,%d, diff %d\n", PRINT_REG(controlObject), x, y, SCI_MAX_SAVENAME_LENGTH); + s->_gui->drawControlList(rect, controlObject, listCount, listEntries, fontId, upperPos, cursorPos, hilite); + free(listEntries); + delete[] listStrings; + return; + + default: + error("unsupported control type %d", type); + } +} + reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { - reg_t obj = argv[0]; + reg_t controlObject = argv[0]; - disableCertainButtons(s->_segMan, s->_gameName, obj); - s->_gui->drawControl(obj, false); -// FULL_REDRAW(); + disableCertainButtons(s->_segMan, s->_gameName, controlObject); + _k_GenericDrawControl(s, controlObject, false); return NULL_REG; } reg_t kHiliteControl(EngineState *s, int argc, reg_t *argv) { - reg_t obj = argv[0]; - - s->_gui->drawControl(obj, true); + reg_t controlObject = argv[0]; + _k_GenericDrawControl(s, controlObject, true); return s->r_acc; } diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index 8e379cdb6e..22eff9b7fb 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -345,6 +345,9 @@ void SciGui::drawControlText(Common::Rect rect, reg_t obj, const char *text, int _screen->copyToScreen(); } +void SciGui::drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { +} + void SciGui::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, int16 style, bool hilite) { if (!hilite) { _gfx->drawCel(viewId, loopNo, celNo, rect.left, rect.top, 255, 0); @@ -357,7 +360,7 @@ void SciGui::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, _screen->copyToScreen(); } -void SciGui::drawControl(reg_t controlObject, bool highlight) { +void SciGui::drawControlList(Common::Rect rect, reg_t obj, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool hilite) { } void SciGui::editControl(reg_t controlObject, reg_t eventObject) { diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h index ed19ac454c..0a4354e3c3 100644 --- a/engines/sci/gui/gui.h +++ b/engines/sci/gui/gui.h @@ -71,8 +71,9 @@ public: virtual void drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo); virtual void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite); virtual void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool hilite); + virtual void drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite); virtual void drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, int16 style, bool hilite); - virtual void drawControl(reg_t controlObject, bool highlight); + virtual void drawControlList(Common::Rect rect, reg_t obj, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool hilite); virtual void editControl(reg_t controlObject, reg_t eventObject); virtual void graphFillBoxForeground(Common::Rect rect); diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index 87e4cbd33e..a39a73142a 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -613,6 +613,19 @@ void SciGui32::drawControlText(Common::Rect rect, reg_t obj, const char *text, i if (!s->pic_not_valid) FULL_REDRAW(); } +void SciGui32::drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { + rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height()); + int16 textSize = strlen(text); + + if (cursorPos > textSize) + cursorPos = textSize; + +// update_cursor_limits(&s->save_dir_edit_offset, &cursor, max); FIXME: get rid of this? + ADD_TO_CURRENT_PICTURE_PORT(sciw_new_edit_control(s->port, obj, area, text, fontId, (unsigned)cursorPos, (int8)hilite)); + if (!s->pic_not_valid) FULL_REDRAW(); +} + + void SciGui32::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo cellNo, int16 style, bool hilite) { rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height()); @@ -621,6 +634,14 @@ void SciGui32::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewI if (!s->pic_not_valid) FULL_REDRAW(); } +void SciGui32::drawControlList(Common::Rect rect, reg_t obj, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool hilite) { + rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height()); + + ADD_TO_CURRENT_PICTURE_PORT(sciw_new_list_control(s->port, obj, area, fontId, entries, count, upperPos, cursorPos, (int8)hilite)); + if (!s->pic_not_valid) FULL_REDRAW(); +} + + // Control types and flags enum { K_CONTROL_BUTTON = 1, @@ -654,6 +675,8 @@ void update_cursor_limits(int *display_offset, int *cursor, int max_displayed) { *display_offset = 12 + *cursor - max_displayed; } +void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite); + static inline int sign_extend_byte(int value) { if (value & 0x80) return value - 256; @@ -661,142 +684,6 @@ static inline int sign_extend_byte(int value) { return value; } -void _k_draw_control(EngineState *s, reg_t obj, bool hilite) { - SegManager *segMan = s->_segMan; - int x = (int16)GET_SEL32V(obj, nsLeft); - int y = (int16)GET_SEL32V(obj, nsTop); - int xl = (int16)GET_SEL32V(obj, nsRight) - x; - int yl = (int16)GET_SEL32V(obj, nsBottom) - y; - rect_t area = gfx_rect(x, y, xl, yl); - - Common::Rect rect; - rect = Common::Rect (x, y, (int16)GET_SEL32V(obj, nsRight), (int16)GET_SEL32V(obj, nsBottom)); - - int font_nr = GET_SEL32V(obj, font); - reg_t text_pos = GET_SEL32(obj, text); - Common::String text; - if (!text_pos.isNull()) - text = s->_segMan->getString(text_pos); - int view = GET_SEL32V(obj, view); - int cel = sign_extend_byte(GET_SEL32V(obj, cel)); - int loop = sign_extend_byte(GET_SEL32V(obj, loop)); - int mode; - - int type = GET_SEL32V(obj, type); - int state = GET_SEL32V(obj, state); - int cursor; - int max; - - switch (type) { - case K_CONTROL_BUTTON: - debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y); - s->_gui->drawControlButton(rect, obj, s->strSplit(text.c_str(), NULL).c_str(), font_nr, state, hilite); - return; - - case K_CONTROL_TEXT: - mode = (gfx_alignment_t) GET_SEL32V(obj, mode); - debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d\n", PRINT_REG(obj), text.c_str(), x, y, mode); - s->_gui->drawControlText(rect, obj, s->strSplit(text.c_str(), NULL).c_str(), font_nr, mode, state, hilite); - return; - - case K_CONTROL_EDIT: - debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d\n", PRINT_REG(obj), PRINT_REG(text_pos), text.c_str(), x, y); - - max = GET_SEL32V(obj, max); - cursor = GET_SEL32V(obj, cursor); - - if (cursor > (signed)text.size()) - cursor = text.size(); - -// update_cursor_limits(&s->save_dir_edit_offset, &cursor, max); FIXME: get rid of this? - ADD_TO_CURRENT_PICTURE_PORT(sciw_new_edit_control(s->port, obj, area, text.c_str(), font_nr, (unsigned)cursor, (int8)hilite)); - break; - - case K_CONTROL_ICON: - debugC(2, kDebugLevelGraphics, "drawing icon control %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y - 1); - s->_gui->drawControlIcon(rect, obj, view, loop, cel, state, hilite); - return; - - case K_CONTROL_CONTROL: - case K_CONTROL_CONTROL_ALIAS: { - int entries_nr; - int lsTop; - int list_top = 0; - int selection = 0; - int entry_size = GET_SEL32V(obj, x); - int i; - - if (s->_kernel->_selectorCache.topString != -1) { - // Games from early SCI1 onwards use topString - lsTop = GET_SEL32V(obj, topString); - } else { - // Earlier games use lsTop - lsTop = GET_SEL32V(obj, lsTop); - } - lsTop -= text_pos.offset; - - debugC(2, kDebugLevelGraphics, "drawing list control %04x:%04x to %d,%d, diff %d\n", PRINT_REG(obj), x, y, SCI_MAX_SAVENAME_LENGTH); - cursor = GET_SEL32V(obj, cursor) - text_pos.offset; - - entries_nr = 0; - - // NOTE: most types of pointer dereferencing don't like odd offsets - if (entry_size & 1) { - warning("List control with odd entry_size %d. This is not yet implemented for all types of segments", entry_size); - } - - reg_t seeker = text_pos; - // Count string entries in NULL terminated string list - while (s->_segMan->strlen(seeker) > 0) { - ++entries_nr; - seeker.offset += entry_size; - } - - // TODO: This is rather convoluted... It would be a lot cleaner - // if sciw_new_list_control would take a list of Common::String - Common::String *strings = 0; - const char **entries_list = NULL; - - if (entries_nr) { // determine list_top, selection, and the entries_list - seeker = text_pos; - entries_list = (const char**)malloc(sizeof(char *) * entries_nr); - strings = new Common::String[entries_nr]; - for (i = 0; i < entries_nr; i++) { - strings[i] = s->_segMan->getString(seeker); - entries_list[i] = strings[i].c_str(); - seeker.offset += entry_size; - if ((seeker.offset - text_pos.offset) == lsTop) - list_top = i + 1; - if ((seeker.offset - text_pos.offset) == cursor) - selection = i + 1; - } - } - - ADD_TO_CURRENT_PICTURE_PORT(sciw_new_list_control(s->port, obj, area, font_nr, entries_list, entries_nr, - list_top, selection, (int8)hilite)); - free(entries_list); - delete[] strings; - } - break; - - case K_CONTROL_BOX: - break; - - default: - warning("Unknown control type: %d at %04x:%04x, at (%d, %d) size %d x %d", - type, PRINT_REG(obj), x, y, xl, yl); - } - - if (!s->pic_not_valid) { - FULL_REDRAW(); - } -} - - -void SciGui32::drawControl(reg_t controlObject, bool highlight) { - _k_draw_control(s, controlObject, highlight); -} - void SciGui32::editControl(reg_t controlObject, reg_t eventObject) { SegManager *segMan = s->_segMan; uint16 ct_type = GET_SEL32V(controlObject, type); @@ -948,7 +835,7 @@ void SciGui32::editControl(reg_t controlObject, reg_t eventObject) { s->_segMan->strcpy(text_pos, text.c_str()); // Write back string } if (eventObject.segment) PUT_SEL32V(eventObject, claimed, 1); - _k_draw_control(s, controlObject, false); + _k_GenericDrawControl(s, controlObject, false); return; case K_CONTROL_ICON: @@ -959,7 +846,7 @@ void SciGui32::editControl(reg_t controlObject, reg_t eventObject) { case K_CONTROL_TEXT: { int state = GET_SEL32V(controlObject, state); PUT_SEL32V(controlObject, state, state | kControlStateDitherFramed); - _k_draw_control(s, controlObject, false); + _k_GenericDrawControl(s, controlObject, false); PUT_SEL32V(controlObject, state, state); } break; diff --git a/engines/sci/gui32/gui32.h b/engines/sci/gui32/gui32.h index 18679c6228..035b96b8ed 100644 --- a/engines/sci/gui32/gui32.h +++ b/engines/sci/gui32/gui32.h @@ -62,8 +62,9 @@ public: void drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo); void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite); void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool hilite); + void drawControlTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite); void drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo, int16 style, bool hilite); - void drawControl(reg_t controlObject, bool highlight); + void drawControlList(Common::Rect rect, reg_t obj, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool hilite); void editControl(reg_t controlObject, reg_t eventObject); void graphFillBoxForeground(Common::Rect rect); -- cgit v1.2.3