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 <cstdio>
24 //include <stdarg.h>
25 #include "ags/shared/ac/common.h"
26 #include "ags/engine/ac/character.h"
27 #include "ags/engine/ac/display.h"
28 #include "ags/engine/ac/draw.h"
29 #include "ags/engine/ac/game.h"
30 #include "ags/shared/ac/game_setup_struct.h"
31 #include "ags/engine/ac/game_state.h"
32 #include "ags/engine/ac/global_character.h"
33 #include "ags/engine/ac/global_display.h"
34 #include "ags/engine/ac/global_screen.h"
35 #include "ags/engine/ac/global_translation.h"
36 #include "ags/engine/ac/runtime_defines.h"
37 #include "ags/engine/ac/speech.h"
38 #include "ags/engine/ac/string.h"
39 #include "ags/engine/ac/top_bar_settings.h"
40 #include "ags/engine/debugging/debug_log.h"
41 #include "ags/shared/game/room_struct.h"
42 #include "ags/engine/main/game_run.h"
43 
44 namespace AGS3 {
45 
46 using namespace AGS::Shared;
47 
Display(const char * texx,...)48 void Display(const char *texx, ...) {
49 	char displbuf[STD_BUFFER_SIZE];
50 	va_list ap;
51 	va_start(ap, texx);
52 	vsprintf(displbuf, get_translation(texx), ap);
53 	va_end(ap);
54 	DisplayAtY(-1, displbuf);
55 }
56 
DisplaySimple(const char * text)57 void DisplaySimple(const char *text) {
58 	DisplayAtY(-1, text);
59 }
60 
DisplayTopBar(int ypos,int ttexcol,int backcol,const char * title,const char * text)61 void DisplayTopBar(int ypos, int ttexcol, int backcol, const char *title, const char *text) {
62 	// FIXME: refactor source_text_length and get rid of this ugly hack!
63 	const int real_text_sourcelen = _G(source_text_length);
64 	snprintf(_GP(topBar).text, sizeof(_GP(topBar).text), "%s", get_translation(title));
65 	_G(source_text_length) = real_text_sourcelen;
66 
67 	if (ypos > 0)
68 		_GP(play).top_bar_ypos = ypos;
69 	if (ttexcol > 0)
70 		_GP(play).top_bar_textcolor = ttexcol;
71 	if (backcol > 0)
72 		_GP(play).top_bar_backcolor = backcol;
73 
74 	_GP(topBar).wantIt = 1;
75 	_GP(topBar).font = FONT_NORMAL;
76 	_GP(topBar).height = getfontheight_outlined(_GP(topBar).font);
77 	_GP(topBar).height += data_to_game_coord(_GP(play).top_bar_borderwidth) * 2 + get_fixed_pixel_size(1);
78 
79 	// they want to customize the font
80 	if (_GP(play).top_bar_font >= 0)
81 		_GP(topBar).font = _GP(play).top_bar_font;
82 
83 	// DisplaySpeech normally sets this up, but since we're not going via it...
84 	if (_GP(play).cant_skip_speech & SKIP_AUTOTIMER)
85 		_GP(play).messagetime = GetTextDisplayTime(text);
86 
87 	DisplayAtY(_GP(play).top_bar_ypos, text);
88 }
89 
90 // Display a room/global message in the bar
DisplayMessageBar(int ypos,int ttexcol,int backcol,const char * title,int msgnum)91 void DisplayMessageBar(int ypos, int ttexcol, int backcol, const char *title, int msgnum) {
92 	char msgbufr[3001];
93 	get_message_text(msgnum, msgbufr);
94 	DisplayTopBar(ypos, ttexcol, backcol, title, msgbufr);
95 }
96 
DisplayMessageAtY(int msnum,int ypos)97 void DisplayMessageAtY(int msnum, int ypos) {
98 	char msgbufr[3001];
99 	if (msnum >= 500) {
100 		get_message_text(msnum, msgbufr);
101 		if (_G(display_message_aschar) > 0)
102 			DisplaySpeech(msgbufr, _G(display_message_aschar));
103 		else
104 			DisplayAtY(ypos, msgbufr);
105 		_G(display_message_aschar) = 0;
106 		return;
107 	}
108 
109 	if (_G(display_message_aschar) > 0) {
110 		_G(display_message_aschar) = 0;
111 		quit("!DisplayMessage: data column specified a character for local\n"
112 		     "message; use the message editor to select the character for room\n"
113 		     "messages.\n");
114 	}
115 
116 	int repeatloop = 1;
117 	while (repeatloop) {
118 		get_message_text(msnum, msgbufr);
119 
120 		if (_GP(thisroom).MessageInfos[msnum].DisplayAs > 0) {
121 			DisplaySpeech(msgbufr, _GP(thisroom).MessageInfos[msnum].DisplayAs - 1);
122 		} else {
123 			// time out automatically if they have set that
124 			int oldGameSkipDisp = _GP(play).skip_display;
125 			if (_GP(thisroom).MessageInfos[msnum].Flags & MSG_TIMELIMIT)
126 				_GP(play).skip_display = 0;
127 
128 			DisplayAtY(ypos, msgbufr);
129 
130 			_GP(play).skip_display = oldGameSkipDisp;
131 		}
132 		if (_GP(thisroom).MessageInfos[msnum].Flags & MSG_DISPLAYNEXT) {
133 			msnum++;
134 			repeatloop = 1;
135 		} else
136 			repeatloop = 0;
137 	}
138 
139 }
140 
DisplayMessage(int msnum)141 void DisplayMessage(int msnum) {
142 	DisplayMessageAtY(msnum, -1);
143 }
144 
DisplayAt(int xxp,int yyp,int widd,const char * text)145 void DisplayAt(int xxp, int yyp, int widd, const char *text) {
146 	data_to_game_coords(&xxp, &yyp);
147 	widd = data_to_game_coord(widd);
148 
149 	if (widd < 1) widd = _GP(play).GetUIViewport().GetWidth() / 2;
150 	if (xxp < 0) xxp = _GP(play).GetUIViewport().GetWidth() / 2 - widd / 2;
151 	_display_at(xxp, yyp, widd, text, DISPLAYTEXT_MESSAGEBOX, 0, 0, 0, false);
152 }
153 
DisplayAtY(int ypos,const char * texx)154 void DisplayAtY(int ypos, const char *texx) {
155 	const Rect &ui_view = _GP(play).GetUIViewport();
156 	if ((ypos < -1) || (ypos >= ui_view.GetHeight()))
157 		quitprintf("!DisplayAtY: invalid Y co-ordinate supplied (used: %d; valid: 0..%d)", ypos, ui_view.GetHeight());
158 
159 	// Display("") ... a bit of a stupid thing to do, so ignore it
160 	if (texx[0] == 0)
161 		return;
162 
163 	if (ypos > 0)
164 		ypos = data_to_game_coord(ypos);
165 
166 	if (_GP(game).options[OPT_ALWAYSSPCH])
167 		DisplaySpeechAt(-1, (ypos > 0) ? game_to_data_coord(ypos) : ypos, -1, _GP(game).playercharacter, texx);
168 	else {
169 		// Normal "Display" in text box
170 
171 		if (is_screen_dirty()) {
172 			// erase any previous DisplaySpeech
173 			_GP(play).disabled_user_interface++;
174 			UpdateGameOnce();
175 			_GP(play).disabled_user_interface--;
176 		}
177 
178 		_display_at(-1, ypos, ui_view.GetWidth() / 2 + ui_view.GetWidth() / 4,
179 		            get_translation(texx), DISPLAYTEXT_MESSAGEBOX, 0, 0, 0, false);
180 	}
181 }
182 
SetSpeechStyle(int newstyle)183 void SetSpeechStyle(int newstyle) {
184 	if ((newstyle < 0) || (newstyle > 3))
185 		quit("!SetSpeechStyle: must use a SPEECH_* constant as parameter");
186 	_GP(game).options[OPT_SPEECHTYPE] = newstyle;
187 }
188 
SetSkipSpeech(SkipSpeechStyle newval)189 void SetSkipSpeech(SkipSpeechStyle newval) {
190 	if ((newval < kSkipSpeechFirst) || (newval > kSkipSpeechLast))
191 		quit("!SetSkipSpeech: invalid skip mode specified");
192 
193 	debug_script_log("SkipSpeech style set to %d", newval);
194 	_GP(play).cant_skip_speech = user_to_internal_skip_speech((SkipSpeechStyle)newval);
195 }
196 
GetSkipSpeech()197 SkipSpeechStyle GetSkipSpeech() {
198 	return internal_skip_speech_to_user(_GP(play).cant_skip_speech);
199 }
200 
201 } // namespace AGS3
202