SCI: kDrawControl for list and textedit controls also using gui class

svn-id: r44925
This commit is contained in:
Martin Kiewitz 2009-10-11 14:28:20 +00:00
parent 7b493e9a60
commit efcfae742b
5 changed files with 146 additions and 152 deletions

View file

@ -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
}
}
reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[0];
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;
disableCertainButtons(s->_segMan, s->_gameName, obj);
s->_gui->drawControl(obj, false);
// FULL_REDRAW();
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 controlObject = argv[0];
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;
}

View file

@ -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) {

View file

@ -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);

View file

@ -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;

View file

@ -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);