aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kgraphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kgraphics.cpp')
-rw-r--r--engines/sci/engine/kgraphics.cpp130
1 files changed, 78 insertions, 52 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index fc72e6e3f1..b57fc32dcf 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -445,7 +445,7 @@ void _k_graph_rebuild_port_with_color(EngineState *s, gfx_color_t newbgcolor) {
newport = sciw_new_window(s, port->zone, port->_font, port->_color, newbgcolor,
s->titlebar_port->_font, s->ega_colors[15], s->ega_colors[8],
- port->title_text, port->port_flags & ~kWindowTransparent);
+ port->_title_text.c_str(), port->port_flags & ~kWindowTransparent);
if (s->dyn_views) {
int found = 0;
@@ -602,29 +602,32 @@ reg_t kGraph(EngineState *s, int, int argc, reg_t *argv) {
reg_t kTextSize(EngineState *s, int, int argc, reg_t *argv) {
int width, height;
- char *text = argv[1].segment ? s->segMan->derefString(argv[1]) : NULL;
- const char *sep = NULL;
+ Common::String text = s->segMan->getString(argv[1]);
reg_t *dest = s->segMan->derefRegPtr(argv[0], 4);
int maxwidth = (argc > 3) ? argv[3].toUint16() : 0;
int font_nr = argv[2].toUint16();
- if ((argc > 4) && (argv[4].segment))
- sep = s->segMan->derefString(argv[4]);
+ Common::String sep_str;
+ const char *sep = NULL;
+ if ((argc > 4) && (argv[4].segment)) {
+ sep_str = s->segMan->getString(argv[4]);
+ sep = sep_str.c_str();
+ }
if (maxwidth < 0)
maxwidth = 0;
dest[0] = dest[1] = NULL_REG;
- if (!text || !*text || !dest) { // Empty text
+ if (text.empty() || !dest) { // Empty text
dest[2] = dest[3] = make_reg(0, 0);
debugC(2, kDebugLevelStrings, "GetTextSize: Empty string\n");
return s->r_acc;
}
- gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text, sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
+ gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text.c_str(), sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
&width, &height, 0, NULL, NULL, NULL);
- debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text, width, height);
+ debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text.c_str(), width, height);
dest[2] = make_reg(0, height);
// dest[3] = make_reg(0, maxwidth? maxwidth : width);
@@ -1303,7 +1306,9 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse);
static void disableCertainButtons(SegManager *segMan, Common::String gameName, reg_t obj) {
reg_t text_pos = GET_SEL32(obj, text);
- char *text = text_pos.isNull() ? NULL : segMan->derefString(text_pos);
+ Common::String text;
+ if (!text_pos.isNull())
+ text = segMan->getString(text_pos);
int type = GET_SEL32V(obj, type);
int state = GET_SEL32V(obj, state);
@@ -1327,15 +1332,15 @@ static void disableCertainButtons(SegManager *segMan, Common::String gameName, r
* that game - bringing the save/load dialog on a par with SCI0.
*/
// NOTE: This _only_ works with the English version
- if (type == K_CONTROL_BUTTON && text && (gameName == "sq4") &&
- getSciVersion() < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) {
+ if (type == K_CONTROL_BUTTON && (gameName == "sq4") &&
+ getSciVersion() < SCI_VERSION_1_1 && text == " Delete ") {
PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled);
}
// Disable the "Change Directory" button, as we don't allow the game engine to
// change the directory where saved games are placed
// NOTE: This _only_ works with the English version
- if (type == K_CONTROL_BUTTON && text && !strcmp(text, "Change\r\nDirectory")) {
+ if (type == K_CONTROL_BUTTON && text == "Change\r\nDirectory") {
PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled);
}
}
@@ -1369,13 +1374,13 @@ void update_cursor_limits(int *display_offset, int *cursor, int max_displayed) {
#define _K_EDIT_DELETE \
if (cursor < textlen) { \
- memmove(text + cursor, text + cursor + 1, textlen - cursor +1); \
+ text.deleteChar(cursor); \
}
#define _K_EDIT_BACKSPACE \
if (cursor) { \
--cursor; \
- memmove(text + cursor, text + cursor + 1, textlen - cursor +1); \
+ text.deleteChar(cursor); \
--textlen; \
}
@@ -1401,15 +1406,17 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
reg_t text_pos = GET_SEL32(obj, text);
int display_offset = 0;
- char *text = s->segMan->derefString(text_pos);
+ Common::String text = s->segMan->getString(text_pos);
int textlen;
+#if 0
if (!text) {
warning("Could not draw control: %04x:%04x does not reference text", PRINT_REG(text_pos));
return s->r_acc;
}
+#endif
- textlen = strlen(text);
+ textlen = text.size();
cursor += display_offset;
@@ -1432,7 +1439,7 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
if (cursor > 0) --cursor;
break;
case 'k':
- text[cursor] = 0;
+ text = Common::String(text.c_str(), cursor);
break; // Terminate string
case 'h':
_K_EDIT_BACKSPACE;
@@ -1503,20 +1510,20 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
if (cursor == textlen) {
if (textlen < max) {
- text[cursor++] = key;
- text[cursor] = 0; // Terminate string
+ text += key;
+ cursor++;
}
} else if (inserting) {
if (textlen < max) {
int i;
for (i = textlen + 2; i >= cursor; i--)
- text[i] = text[i - 1];
- text[cursor++] = key;
+ text.setChar(text[i - 1], i);
+ text.setChar(key, cursor++);
}
} else { // Overwriting
- text[cursor++] = key;
+ text.setChar(key, cursor++);
}
if (max_displayed < max)
@@ -1528,6 +1535,7 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
}
PUT_SEL32V(obj, cursor, cursor); // Write back cursor position
+ s->segMan->strcpy(text_pos, text.c_str()); // Write back string
}
case K_CONTROL_ICON:
@@ -1564,7 +1572,9 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
int font_nr = GET_SEL32V(obj, font);
reg_t text_pos = GET_SEL32(obj, text);
- const char *text = text_pos.isNull() ? NULL : s->segMan->derefString(text_pos);
+ 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));
@@ -1578,7 +1588,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
switch (type) {
case K_CONTROL_BUTTON:
debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text, NULL).c_str(), font_nr,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text.c_str(), NULL).c_str(), font_nr,
(int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled)));
break;
@@ -1587,7 +1597,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text).c_str(), font_nr, mode,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text.c_str()).c_str(), font_nr, mode,
(int8)(!!(state & kControlStateDitherFramed)), (int8)inverse));
break;
@@ -1597,11 +1607,11 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
max = GET_SEL32V(obj, max);
cursor = GET_SEL32V(obj, cursor);
- if (cursor > (signed)strlen(text))
- cursor = strlen(text);
+ 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, font_nr, (unsigned)cursor, (int8)inverse));
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_edit_control(s->port, obj, area, text.c_str(), font_nr, (unsigned)cursor, (int8)inverse));
break;
case K_CONTROL_ICON:
@@ -1614,8 +1624,6 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
case K_CONTROL_CONTROL:
case K_CONTROL_CONTROL_ALIAS: {
- const char **entries_list = NULL;
- const char *seeker;
int entries_nr;
int lsTop = GET_SEL32V(obj, lsTop) - text_pos.offset;
int list_top = 0;
@@ -1627,29 +1635,41 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
cursor = GET_SEL32V(obj, cursor) - text_pos.offset;
entries_nr = 0;
- seeker = text;
- while (seeker[0]) { // Count string entries in NULL terminated string list
+
+ // NOTE: most types of pointer dereferencing don't like odd offsets
+ assert((entry_size & 1) == 0);
+
+ reg_t seeker = text_pos;
+ // Count string entries in NULL terminated string list
+ while (s->segMan->strlen(seeker) > 0) {
++entries_nr;
- seeker += entry_size;
+ 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;
+ 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++) {
- entries_list[i] = seeker;
- seeker += entry_size ;
- if ((seeker - text) == lsTop)
+ 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 - text) == cursor)
+ 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)inverse));
- if (entries_nr)
- free(entries_list);
+
+ free(entries_list);
+ delete[] strings;
}
break;
@@ -2511,10 +2531,14 @@ reg_t kNewWindow(EngineState *s, int, int argc, reg_t *argv) {
lWhite.alpha = 0;
lWhite.priority = -1;
lWhite.control = -1;
- const char *title = argv[4 + argextra].segment ? s->segMan->derefString(argv[4 + argextra]) : NULL;
+ Common::String title;
+ if (argv[4 + argextra].segment) {
+ title = s->segMan->getString(argv[4 + argextra]);
+ title = s->strSplit(title.c_str(), NULL);
+ }
window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
- s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, flags);
+ s->titlebar_port->_font, lWhite, black, title.c_str(), flags);
// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
if (argextra)
@@ -3113,7 +3137,7 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
int temp;
bool save_under = false;
gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
- char *text;
+ Common::String text;
GfxPort *port = (s->port) ? s->port : s->picture_port;
bool update_immediately = true;
@@ -3139,16 +3163,18 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
if (textp.segment) {
argpt = 1;
- text = s->segMan->derefString(textp);
+ text = s->segMan->getString(textp);
} else {
argpt = 2;
text = kernel_lookup_text(s, textp, index);
}
+#if 0
if (!text) {
error("Display with invalid reference %04x:%04x", PRINT_REG(textp));
return NULL_REG;
}
+#endif
while (argpt < argc) {
switch (argv[argpt++].toUint16()) {
@@ -3251,7 +3277,7 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
if (halign == ALIGN_LEFT) {
// If the text does not fit on the screen, move it to the left and upwards until it does
- gfxop_get_text_params(s->gfx_state, font_nr, text, area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
+ gfxop_get_text_params(s->gfx_state, font_nr, text.c_str(), area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
// Make the text fit on the screen
if (area.x + area.width > 320)
@@ -3275,7 +3301,7 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
assert_primary_widget_lists(s);
- text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
+ text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text.c_str()).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
if (!text_handle) {
error("Display: Failed to create text widget");
@@ -3293,7 +3319,7 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
debugC(2, kDebugLevelGraphics, "Saving (%d, %d) size (%d, %d) as %04x:%04x\n", save_area.x, save_area.y, save_area.width, save_area.height, PRINT_REG(s->r_acc));
}
- debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text);
+ debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text.c_str());
//ADD_TO_CURRENT_PICTURE_PORT(text_handle);
@@ -3307,12 +3333,12 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
}
static reg_t kShowMovie_Windows(EngineState *s, int argc, reg_t *argv) {
- const char *filename = s->segMan->derefString(argv[1]);
+ Common::String filename = s->segMan->getString(argv[1]);
Graphics::AVIPlayer *player = new Graphics::AVIPlayer(g_system);
if (!player->open(filename)) {
- warning("Failed to open movie file %s", filename);
+ warning("Failed to open movie file %s", filename.c_str());
return s->r_acc;
}
@@ -3386,13 +3412,13 @@ static reg_t kShowMovie_Windows(EngineState *s, int argc, reg_t *argv) {
}
static reg_t kShowMovie_DOS(EngineState *s, int argc, reg_t *argv) {
- const char *filename = s->segMan->derefString(argv[0]);
+ Common::String filename = s->segMan->getString(argv[0]);
int delay = argv[1].toUint16(); // Time between frames in ticks
int frameNr = 0;
SeqDecoder seq;
if (!seq.loadFile(filename) && !seq.loadFile(Common::String("SEQ/") + filename)) {
- warning("Failed to open movie file %s", filename);
+ warning("Failed to open movie file %s", filename.c_str());
return s->r_acc;
}