1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "sherlock/journal.h"
24 #include "sherlock/sherlock.h"
25 #include "sherlock/scalpel/scalpel_fixed_text.h"
26 #include "sherlock/scalpel/scalpel_journal.h"
27 #include "sherlock/scalpel/scalpel_screen.h"
28 #include "sherlock/scalpel/scalpel.h"
29 #include "sherlock/tattoo/tattoo_journal.h"
30 
31 namespace Sherlock {
32 
33 namespace Scalpel {
34 
35 #define JOURNAL_BUTTONS_Y 178
36 #define JOURNAL_SEARCH_LEFT 15
37 #define JOURNAL_SEARCH_TOP 186
38 #define JOURNAL_SEARCH_RIGHT 296
39 #define JOURNAL_SEACRH_MAX_CHARS 50
40 
41 // Positioning of buttons in the journal view
42 static const int JOURNAL_POINTS[9][3] = {
43 	{ 6, 68, 37 },
44 	{ 69, 131, 100 },
45 	{ 132, 192, 162 },
46 	{ 193, 250, 221 },
47 	{ 251, 313, 281 },
48 	{ 6, 82, 44 },
49 	{ 83, 159, 121 },
50 	{ 160, 236, 198 },
51 	{ 237, 313, 275 }
52 };
53 
54 static const int SEARCH_POINTS[3][3] = {
55 	{ 51, 123, 86 },
56 	{ 124, 196, 159 },
57 	{ 197, 269, 232 }
58 };
59 
60 /*----------------------------------------------------------------*/
61 
ScalpelJournal(SherlockEngine * vm)62 ScalpelJournal::ScalpelJournal(SherlockEngine *vm) : Journal(vm) {
63 	if (_vm->_interactiveFl) {
64 		// Load the journal directory and location names
65 		loadLocations();
66 	}
67 
68 	_fixedTextWatsonsJournal = FIXED(Journal_WatsonsJournal);
69 	_fixedTextExit = FIXED(Journal_Exit);
70 	_fixedTextBack10 = FIXED(Journal_Back10);
71 	_fixedTextUp = FIXED(Journal_Up);
72 	_fixedTextDown = FIXED(Journal_Down);
73 	_fixedTextAhead10 = FIXED(Journal_Ahead10);
74 	_fixedTextSearch = FIXED(Journal_Search);
75 	_fixedTextFirstPage = FIXED(Journal_FirstPage);
76 	_fixedTextLastPage = FIXED(Journal_LastPage);
77 	_fixedTextPrintText = FIXED(Journal_PrintText);
78 
79 	_hotkeyExit = toupper(_fixedTextExit[0]);
80 	_hotkeyBack10 = toupper(_fixedTextBack10[0]);
81 	_hotkeyUp = toupper(_fixedTextUp[0]);
82 	_hotkeyDown = toupper(_fixedTextDown[0]);
83 	_hotkeyAhead10 = toupper(_fixedTextAhead10[0]);
84 	_hotkeySearch = toupper(_fixedTextSearch[0]);
85 	_hotkeyFirstPage = toupper(_fixedTextFirstPage[0]);
86 	_hotkeyLastPage = toupper(_fixedTextLastPage[0]);
87 	_hotkeyPrintText = toupper(_fixedTextPrintText[0]);
88 
89 	_fixedTextSearchExit = FIXED(JournalSearch_Exit);
90 	_fixedTextSearchBackward = FIXED(JournalSearch_Backward);
91 	_fixedTextSearchForward = FIXED(JournalSearch_Forward);
92 	_fixedTextSearchNotFound = FIXED(JournalSearch_NotFound);
93 
94 	_hotkeySearchExit = toupper(_fixedTextSearchExit[0]);
95 	_hotkeySearchBackward = toupper(_fixedTextSearchBackward[0]);
96 	_hotkeySearchForward = toupper(_fixedTextSearchForward[0]);
97 }
98 
loadLocations()99 void ScalpelJournal::loadLocations() {
100 	Resources &res = *_vm->_res;
101 
102 	_directory.clear();
103 	_locations.clear();
104 
105 
106 	Common::SeekableReadStream *dir = res.load("talk.lib");
107 	dir->skip(4);		// Skip header
108 
109 	// Get the numer of entries
110 	_directory.resize(dir->readUint16LE());
111 
112 	// Read in each entry
113 	char buffer[17];
114 	for (uint idx = 0; idx < _directory.size(); ++idx) {
115 		dir->read(buffer, 17);
116 		buffer[16] = '\0';
117 
118 		_directory[idx] = Common::String(buffer);
119 	}
120 
121 	delete dir;
122 
123 	if (IS_3DO) {
124 		// 3DO: storage of locations is currently unknown TODO
125 		return;
126 	}
127 
128 	// Load in the locations stored in journal.txt
129 	Common::SeekableReadStream *loc = res.load("journal.txt");
130 
131 	while (loc->pos() < loc->size()) {
132 		Common::String line;
133 		char c;
134 		while ((c = loc->readByte()) != 0)
135 			line += c;
136 
137 		// WORKAROUND: Special fixes for faulty translations
138 		// Was obviously not done in the original interpreter
139 		if (_vm->getLanguage() == Common::ES_ESP) {
140 			// Spanish version
141 			// We fix all sorts of typos
142 			// see bug #6931
143 			if (line == "En el cajellon destras del teatro Regency") {
144 				line = "En el callejon detras del teatro Regency";
145 			} else if (line == "En el apartamente de Simon Kingsley") {
146 				line = "En el apartamento de Simon Kingsley";
147 			} else if (line == "Bajo la muelle de Savoy Pier") {
148 				line = "Bajo el muelle de Savoy Pier";
149 			} else if (line == "En le viejo Sherman") {
150 				line = "En el viejo Sherman";
151 			} else if (line == "En la entrada de la cada de Anna Carroway") {
152 				line = "En la entrada de la casa de Anna Carroway";
153 			}
154 		}
155 
156 		_locations.push_back(line);
157 	}
158 
159 	delete loc;
160 }
161 
drawFrame()162 void ScalpelJournal::drawFrame() {
163 	Resources &res = *_vm->_res;
164 	ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
165 	byte palette[PALETTE_SIZE];
166 
167 	// Load in the journal background
168 	Common::SeekableReadStream *bg = res.load("journal.lbv");
169 	bg->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
170 	bg->read(palette, PALETTE_SIZE);
171 	delete bg;
172 
173 	// Translate the palette for display
174 	for (int idx = 0; idx < PALETTE_SIZE; ++idx)
175 		palette[idx] = VGA_COLOR_TRANS(palette[idx]);
176 
177 	// Set the palette and print the title
178 	screen.setPalette(palette);
179 	screen.gPrint(Common::Point(111, 18), BUTTON_BOTTOM, "%s", _fixedTextWatsonsJournal.c_str());
180 	screen.gPrint(Common::Point(110, 17), INV_FOREGROUND, "%s", _fixedTextWatsonsJournal.c_str());
181 
182 	// Draw the buttons
183 	screen.makeButton(Common::Rect(JOURNAL_POINTS[0][0], JOURNAL_BUTTONS_Y,
184 		JOURNAL_POINTS[0][1], JOURNAL_BUTTONS_Y + 10),
185 		JOURNAL_POINTS[0][2], _fixedTextExit);
186 	screen.makeButton(Common::Rect(JOURNAL_POINTS[1][0], JOURNAL_BUTTONS_Y,
187 		JOURNAL_POINTS[1][1], JOURNAL_BUTTONS_Y + 10),
188 		JOURNAL_POINTS[1][2], _fixedTextBack10);
189 	screen.makeButton(Common::Rect(JOURNAL_POINTS[2][0], JOURNAL_BUTTONS_Y,
190 		JOURNAL_POINTS[2][1], JOURNAL_BUTTONS_Y + 10),
191 		JOURNAL_POINTS[2][2], _fixedTextUp);
192 	screen.makeButton(Common::Rect(JOURNAL_POINTS[3][0], JOURNAL_BUTTONS_Y,
193 		JOURNAL_POINTS[3][1], JOURNAL_BUTTONS_Y + 10),
194 		JOURNAL_POINTS[3][2], _fixedTextDown);
195 	screen.makeButton(Common::Rect(JOURNAL_POINTS[4][0], JOURNAL_BUTTONS_Y,
196 		JOURNAL_POINTS[4][1], JOURNAL_BUTTONS_Y + 10),
197 		JOURNAL_POINTS[4][2], _fixedTextAhead10);
198 	screen.makeButton(Common::Rect(JOURNAL_POINTS[5][0], JOURNAL_BUTTONS_Y + 11,
199 		JOURNAL_POINTS[5][1], JOURNAL_BUTTONS_Y + 21),
200 		JOURNAL_POINTS[5][2], _fixedTextSearch);
201 	screen.makeButton(Common::Rect(JOURNAL_POINTS[6][0], JOURNAL_BUTTONS_Y + 11,
202 		JOURNAL_POINTS[6][1], JOURNAL_BUTTONS_Y + 21),
203 		JOURNAL_POINTS[6][2], _fixedTextFirstPage);
204 	screen.makeButton(Common::Rect(JOURNAL_POINTS[7][0], JOURNAL_BUTTONS_Y + 11,
205 		JOURNAL_POINTS[7][1], JOURNAL_BUTTONS_Y + 21),
206 		JOURNAL_POINTS[7][2], _fixedTextLastPage);
207 
208 	// WORKAROUND: Draw Print Text button as disabled, since we don't support it in ScummVM
209 	screen.makeButton(Common::Rect(JOURNAL_POINTS[8][0], JOURNAL_BUTTONS_Y + 11,
210 		JOURNAL_POINTS[8][1], JOURNAL_BUTTONS_Y + 21),
211 		JOURNAL_POINTS[8][2], _fixedTextPrintText);
212 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11),
213 		COMMAND_NULL, false, _fixedTextPrintText);
214 }
215 
drawInterface()216 void ScalpelJournal::drawInterface() {
217 	ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
218 
219 	drawFrame();
220 
221 	if (_journal.empty()) {
222 		_up = _down = 0;
223 	} else {
224 		drawJournal(0, 0);
225 	}
226 
227 	doArrows();
228 
229 	// Show the entire screen
230 	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
231 }
232 
doArrows()233 void ScalpelJournal::doArrows() {
234 	ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
235 	byte color;
236 
237 	color = (_page > 1) ? COMMAND_FOREGROUND : COMMAND_NULL;
238 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), color, false, _fixedTextBack10);
239 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), color, false, _fixedTextUp);
240 
241 	color = _down ? COMMAND_FOREGROUND : COMMAND_NULL;
242 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), color, false, _fixedTextDown);
243 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), color, false, _fixedTextAhead10);
244 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[7][2], JOURNAL_BUTTONS_Y + 11), color, false, _fixedTextLastPage);
245 
246 	color = _journal.size() > 0 ? COMMAND_FOREGROUND : COMMAND_NULL;
247 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), color, false, _fixedTextSearch);
248 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11), COMMAND_NULL, false, _fixedTextPrintText);
249 
250 	color = _page > 1 ? COMMAND_FOREGROUND : COMMAND_NULL;
251 	screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, false, _fixedTextFirstPage);
252 }
253 
getHighlightedButton(const Common::Point & pt)254 JournalButton ScalpelJournal::getHighlightedButton(const Common::Point &pt) {
255 	if (pt.x > JOURNAL_POINTS[0][0] && pt.x < JOURNAL_POINTS[0][1] && pt.y >= JOURNAL_BUTTONS_Y &&
256 			pt.y < (JOURNAL_BUTTONS_Y + 10))
257 		return BTN_EXIT;
258 
259 	if (pt.x > JOURNAL_POINTS[1][0] && pt.x < JOURNAL_POINTS[1][1] && pt.y >= JOURNAL_BUTTONS_Y &&
260 			pt.y < (JOURNAL_BUTTONS_Y + 10) && _page > 1)
261 		return BTN_BACK10;
262 
263 	if (pt.x > JOURNAL_POINTS[2][0] && pt.x < JOURNAL_POINTS[2][1] && pt.y >= JOURNAL_BUTTONS_Y &&
264 			pt.y < (JOURNAL_BUTTONS_Y + 10) && _up)
265 		return BTN_UP;
266 
267 	if (pt.x > JOURNAL_POINTS[3][0] && pt.x < JOURNAL_POINTS[3][1] && pt.y >= JOURNAL_BUTTONS_Y &&
268 			pt.y < (JOURNAL_BUTTONS_Y + 10) && _down)
269 		return BTN_DOWN;
270 
271 	if (pt.x > JOURNAL_POINTS[4][0] && pt.x < JOURNAL_POINTS[4][1] && pt.y >= JOURNAL_BUTTONS_Y &&
272 			pt.y < (JOURNAL_BUTTONS_Y + 10) && _down)
273 		return BTN_AHEAD110;
274 
275 	if (pt.x > JOURNAL_POINTS[5][0] && pt.x < JOURNAL_POINTS[5][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
276 			pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty())
277 		return BTN_SEARCH;
278 
279 	if (pt.x > JOURNAL_POINTS[6][0] && pt.x < JOURNAL_POINTS[6][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
280 			pt.y < (JOURNAL_BUTTONS_Y + 20) && _up)
281 		return BTN_FIRST_PAGE;
282 
283 	if (pt.x > JOURNAL_POINTS[7][0] && pt.x < JOURNAL_POINTS[7][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
284 			pt.y < (JOURNAL_BUTTONS_Y + 20) && _down)
285 		return BTN_LAST_PAGE;
286 
287 	if (pt.x > JOURNAL_POINTS[8][0] && pt.x < JOURNAL_POINTS[8][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
288 			pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty())
289 		return BTN_PRINT_TEXT;
290 
291 	return BTN_NONE;
292 }
293 
handleEvents(int key)294 bool ScalpelJournal::handleEvents(int key) {
295 	Events    &events    = *_vm->_events;
296 	ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
297 	bool doneFlag = false;
298 
299 	Common::Point pt = events.mousePos();
300 	JournalButton btn = getHighlightedButton(pt);
301 	byte color;
302 
303 	if (events._pressed || events._released) {
304 		// Exit button
305 		color = (btn == BTN_EXIT) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND;
306 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[0][2], JOURNAL_BUTTONS_Y), color, true, _fixedTextExit);
307 
308 		// Back 10 button
309 		if (btn == BTN_BACK10) {
310 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, _fixedTextBack10);
311 		} else if (_page > 1) {
312 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, _fixedTextBack10);
313 		}
314 
315 		// Up button
316 		if (btn == BTN_UP) {
317 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, _fixedTextUp);
318 		} else if (_up) {
319 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, _fixedTextUp);
320 		}
321 
322 		// Down button
323 		if (btn == BTN_DOWN) {
324 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, _fixedTextDown);
325 		} else if (_down) {
326 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, _fixedTextDown);
327 		}
328 
329 		// Ahead 10 button
330 		if (btn == BTN_AHEAD110) {
331 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, _fixedTextAhead10);
332 		} else if (_down) {
333 			screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, _fixedTextAhead10);
334 		}
335 
336 		// Search button
337 		if (btn == BTN_SEARCH) {
338 			color = COMMAND_HIGHLIGHTED;
339 		} else if (_journal.empty()) {
340 			color = COMMAND_NULL;
341 		} else {
342 			color = COMMAND_FOREGROUND;
343 		}
344 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), color, true, _fixedTextSearch);
345 
346 		// First Page button
347 		if (btn == BTN_FIRST_PAGE) {
348 			color = COMMAND_HIGHLIGHTED;
349 		} else if (_up) {
350 			color = COMMAND_FOREGROUND;
351 		} else {
352 			color = COMMAND_NULL;
353 		}
354 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, true, _fixedTextFirstPage);
355 
356 		// Last Page button
357 		if (btn == BTN_LAST_PAGE) {
358 			color = COMMAND_HIGHLIGHTED;
359 		} else if (_down) {
360 			color = COMMAND_FOREGROUND;
361 		} else {
362 			color = COMMAND_NULL;
363 		}
364 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[7][2], JOURNAL_BUTTONS_Y + 11), color, true, _fixedTextLastPage);
365 
366 		// Print Text button
367 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11), COMMAND_NULL, true, _fixedTextPrintText);
368 	}
369 
370 	if (btn == BTN_EXIT && events._released) {
371 		// Exit button pressed
372 		doneFlag = true;
373 
374 	} else if (((btn == BTN_BACK10 && events._released) || key == _hotkeyBack10) && (_page > 1)) {
375 		// Scrolll up 10 pages
376 		if (_page < 11)
377 			drawJournal(1, (_page - 1) * LINES_PER_PAGE);
378 		else
379 			drawJournal(1, 10 * LINES_PER_PAGE);
380 
381 		doArrows();
382 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
383 
384 	} else if (((btn == BTN_UP && events._released) || key == _hotkeyUp) && _up) {
385 		// Scroll up
386 		drawJournal(1, LINES_PER_PAGE);
387 		doArrows();
388 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
389 
390 	} else if (((btn == BTN_DOWN && events._released) || key == _hotkeyDown) && _down) {
391 		// Scroll down
392 		drawJournal(2, LINES_PER_PAGE);
393 		doArrows();
394 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
395 
396 	} else if (((btn == BTN_AHEAD110 && events._released) || key == _hotkeyAhead10) && _down) {
397 		// Scroll down 10 pages
398 		if ((_page + 10) > _maxPage)
399 			drawJournal(2, (_maxPage - _page) * LINES_PER_PAGE);
400 		else
401 			drawJournal(2, 10 * LINES_PER_PAGE);
402 
403 		doArrows();
404 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
405 
406 	} else if (((btn == BTN_SEARCH && events._released) || key == _hotkeySearch) && !_journal.empty()) {
407 		screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), COMMAND_FOREGROUND, true, _fixedTextSearch);
408 		bool notFound = false;
409 
410 		do {
411 			int dir;
412 			if ((dir = getSearchString(notFound)) != 0) {
413 				int savedIndex = _index;
414 				int savedSub = _sub;
415 				int savedPage = _page;
416 
417 				if (drawJournal(dir + 2, 1000 * LINES_PER_PAGE) == 0) {
418 					_index = savedIndex;
419 					_sub = savedSub;
420 					_page = savedPage;
421 
422 					drawFrame();
423 					drawJournal(0, 0);
424 					notFound = true;
425 				} else {
426 					doneFlag = true;
427 				}
428 
429 				doArrows();
430 				screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
431 			} else {
432 				doneFlag = true;
433 			}
434 		} while (!doneFlag);
435 		doneFlag = false;
436 
437 	} else if (((btn == BTN_FIRST_PAGE && events._released) || key == _hotkeyFirstPage) && _up) {
438 		// First page
439 		_index = _sub = 0;
440 		_up = _down = false;
441 		_page = 1;
442 
443 		drawFrame();
444 		drawJournal(0, 0);
445 		doArrows();
446 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
447 
448 	} else if (((btn == BTN_LAST_PAGE && events._released) || key == _hotkeyLastPage) && _down) {
449 		// Last page
450 		if ((_page + 10) > _maxPage)
451 			drawJournal(2, (_maxPage - _page) * LINES_PER_PAGE);
452 		else
453 			drawJournal(2, 1000 * LINES_PER_PAGE);
454 
455 		doArrows();
456 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
457 	}
458 
459 	events.wait(2);
460 
461 	return doneFlag;
462 }
463 
getSearchString(bool printError)464 int ScalpelJournal::getSearchString(bool printError) {
465 	enum Button { BTN_NONE, BTN_EXIT, BTN_BACKWARD, BTN_FORWARD };
466 
467 	Events    &events    = *_vm->_events;
468 	ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
469 	Talk &talk = *_vm->_talk;
470 	int xp;
471 	int yp = 174;
472 	bool flag = false;
473 	Common::String name;
474 	int done = 0;
475 	byte color;
476 
477 	// Draw search panel
478 	screen.makePanel(Common::Rect(6, 171, 313, 199));
479 	screen.makeButton(Common::Rect(SEARCH_POINTS[0][0], yp, SEARCH_POINTS[0][1], yp + 10),
480 		SEARCH_POINTS[0][2], _fixedTextSearchExit);
481 	screen.makeButton(Common::Rect(SEARCH_POINTS[1][0], yp, SEARCH_POINTS[1][1], yp + 10),
482 		SEARCH_POINTS[1][2], _fixedTextSearchBackward);
483 	screen.makeButton(Common::Rect(SEARCH_POINTS[2][0], yp, SEARCH_POINTS[2][1], yp + 10),
484 		SEARCH_POINTS[2][2], _fixedTextSearchForward);
485 
486 	screen.makeField(Common::Rect(12, 185, 307, 196));
487 
488 	if (printError) {
489 		screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - screen.stringWidth(_fixedTextSearchNotFound)) / 2, 185),
490 			INV_FOREGROUND, "%s", _fixedTextSearchNotFound.c_str());
491 	} else if (!_find.empty()) {
492 		// There's already a search term, display it already
493 		screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, "%s", _find.c_str());
494 		name = _find;
495 	}
496 
497 	screen.slamArea(6, 171, 307, 28);
498 
499 	if (printError) {
500 		// Give time for user to see the message
501 		events.setButtonState();
502 		for (int idx = 0; idx < 40 && !_vm->shouldQuit() && !events.kbHit() && !events._released; ++idx) {
503 			events.pollEvents();
504 			events.setButtonState();
505 			events.wait(2);
506 		}
507 
508 		events.clearKeyboard();
509 		screen._backBuffer1.fillRect(Common::Rect(13, 186, 306, 195), BUTTON_MIDDLE);
510 
511 		if (!_find.empty()) {
512 			screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, "%s", _find.c_str());
513 			name = _find;
514 		}
515 
516 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
517 	}
518 
519 	xp = JOURNAL_SEARCH_LEFT + screen.stringWidth(name);
520 	yp = JOURNAL_SEARCH_TOP;
521 
522 	do {
523 		events._released = false;
524 		Button found = BTN_NONE;
525 
526 		while (!_vm->shouldQuit() && !events.kbHit() && !events._released) {
527 			found = BTN_NONE;
528 			if (talk._talkToAbort)
529 				return 0;
530 
531 			// Check if key or mouse button press has occurred
532 			events.setButtonState();
533 			Common::Point pt = events.mousePos();
534 
535 			flag = !flag;
536 			screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), flag ? INV_FOREGROUND : BUTTON_MIDDLE);
537 
538 			if (events._pressed || events._released) {
539 				if (pt.x > SEARCH_POINTS[0][0] && pt.x < SEARCH_POINTS[0][1] && pt.y > 174 && pt.y < 183) {
540 					found = BTN_EXIT;
541 					color = COMMAND_HIGHLIGHTED;
542 				} else {
543 					color = COMMAND_FOREGROUND;
544 				}
545 				screen.buttonPrint(Common::Point(SEARCH_POINTS[0][0], SEARCH_POINTS[0][2]), color, false, _fixedTextSearchExit);
546 
547 				if (pt.x > SEARCH_POINTS[1][0] && pt.x < SEARCH_POINTS[1][1] && pt.y > 174 && pt.y < 183) {
548 					found = BTN_BACKWARD;
549 					color = COMMAND_HIGHLIGHTED;
550 				} else {
551 					color = COMMAND_FOREGROUND;
552 				}
553 				screen.buttonPrint(Common::Point(SEARCH_POINTS[1][0], SEARCH_POINTS[1][2]), color, false, _fixedTextSearchBackward);
554 
555 				if (pt.x > SEARCH_POINTS[2][0] && pt.x < SEARCH_POINTS[2][1] && pt.y > 174 && pt.y < 183) {
556 					found = BTN_FORWARD;
557 					color = COMMAND_HIGHLIGHTED;
558 				} else {
559 					color = COMMAND_FOREGROUND;
560 				}
561 				screen.buttonPrint(Common::Point(SEARCH_POINTS[2][0], SEARCH_POINTS[2][2]), color, false, _fixedTextSearchForward);
562 			}
563 
564 			events.wait(2);
565 		}
566 
567 		if (events.kbHit()) {
568 			Common::KeyState keyState = events.getKey();
569 
570 			if ((keyState.keycode == Common::KEYCODE_BACKSPACE) && (name.size() > 0)) {
571 				screen.vgaBar(Common::Rect(xp - screen.charWidth(name.lastChar()), yp, xp + 8, yp + 9), BUTTON_MIDDLE);
572 				xp -= screen.charWidth(name.lastChar());
573 				screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), INV_FOREGROUND);
574 				name.deleteLastChar();
575 
576 			} else  if (keyState.keycode == Common::KEYCODE_RETURN) {
577 				done = 1;
578 
579 			}  else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
580 				screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE);
581 				done = -1;
582 
583 			} else if (keyState.ascii >= ' ' && keyState.ascii <= 'z' && keyState.keycode != Common::KEYCODE_AT &&
584 				name.size() < JOURNAL_SEACRH_MAX_CHARS && (xp + screen.charWidth(keyState.ascii)) < JOURNAL_SEARCH_RIGHT) {
585 				char ch = toupper(keyState.ascii);
586 				screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE);
587 				screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", ch);
588 				xp += screen.charWidth(ch);
589 				name += ch;
590 			}
591 		}
592 
593 		if (events._released) {
594 			switch (found) {
595 			case BTN_EXIT:
596 				done = -1; break;
597 			case BTN_BACKWARD:
598 				done = 2; break;
599 			case BTN_FORWARD:
600 				done = 1; break;
601 			default:
602 				break;
603 			}
604 		}
605 	} while (!done && !_vm->shouldQuit());
606 
607 	if (done != -1) {
608 		_find = name;
609 	} else {
610 		done = 0;
611 	}
612 
613 	// Redisplay the journal screen
614 	drawFrame();
615 	drawJournal(0, 0);
616 	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
617 
618 	return done;
619 }
620 
resetPosition()621 void ScalpelJournal::resetPosition() {
622 	_index = _sub = _up = _down = 0;
623 	_page = 1;
624 }
625 
record(int converseNum,int statementNum,bool replyOnly)626 void ScalpelJournal::record(int converseNum, int statementNum, bool replyOnly) {
627 	// there seems to be no journal in the 3DO version
628 	if (!IS_3DO)
629 		Journal::record(converseNum, statementNum, replyOnly);
630 }
631 
632 } // End of namespace Scalpel
633 
634 } // End of namespace Sherlock
635