1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include "ac/common.h"
18 #include "ac/character.h"
19 #include "ac/display.h"
20 #include "ac/draw.h"
21 #include "ac/game.h"
22 #include "ac/gamesetupstruct.h"
23 #include "ac/gamestate.h"
24 #include "ac/global_character.h"
25 #include "ac/global_display.h"
26 #include "ac/global_screen.h"
27 #include "ac/global_translation.h"
28 #include "ac/roomstruct.h"
29 #include "ac/runtime_defines.h"
30 #include "ac/speech.h"
31 #include "ac/string.h"
32 #include "ac/topbarsettings.h"
33 #include "debug/debug_log.h"
34 #include "main/game_run.h"
35 #include "util/c99_snprintf.h"
36 
37 extern TopBarSettings topBar;
38 extern GameState play;
39 extern roomstruct thisroom;
40 extern int display_message_aschar;
41 extern GameSetupStruct game;
42 extern int screen_is_dirty;
43 
Display(const char * texx,...)44 void Display(const char*texx, ...) {
45     char displbuf[STD_BUFFER_SIZE];
46     va_list ap;
47     va_start(ap,texx);
48     vsprintf(displbuf, get_translation(texx), ap);
49     va_end(ap);
50     DisplayAtY (-1, displbuf);
51 }
52 
DisplaySimple(const char * text)53 void DisplaySimple(const char *text)
54 {
55     DisplayAtY (-1, text);
56 }
57 
DisplayTopBar(int ypos,int ttexcol,int backcol,const char * title,const char * text)58 void DisplayTopBar(int ypos, int ttexcol, int backcol, const char *title, const char *text)
59 {
60     // FIXME: refactor source_text_length and get rid of this ugly hack!
61     const int real_text_sourcelen = source_text_length;
62     snprintf(topBar.text, sizeof(topBar.text), "%s", get_translation(title));
63     source_text_length = real_text_sourcelen;
64 
65     if (ypos > 0)
66         play.top_bar_ypos = ypos;
67     if (ttexcol > 0)
68         play.top_bar_textcolor = ttexcol;
69     if (backcol > 0)
70         play.top_bar_backcolor = backcol;
71 
72     topBar.wantIt = 1;
73     topBar.font = FONT_NORMAL;
74     topBar.height = getfontheight_outlined(topBar.font);
75     topBar.height += multiply_up_coordinate(play.top_bar_borderwidth) * 2 + get_fixed_pixel_size(1);
76 
77     // they want to customize the font
78     if (play.top_bar_font >= 0)
79         topBar.font = play.top_bar_font;
80 
81     // DisplaySpeech normally sets this up, but since we're not going via it...
82     if (play.cant_skip_speech & SKIP_AUTOTIMER)
83         play.messagetime = GetTextDisplayTime(text);
84 
85     DisplayAtY(play.top_bar_ypos, text);
86 }
87 
88 // Display a room/global message in the bar
DisplayMessageBar(int ypos,int ttexcol,int backcol,const char * title,int msgnum)89 void DisplayMessageBar(int ypos, int ttexcol, int backcol, const char *title, int msgnum) {
90     char msgbufr[3001];
91     get_message_text(msgnum, msgbufr);
92     DisplayTopBar(ypos, ttexcol, backcol, title, msgbufr);
93 }
94 
DisplayMessageAtY(int msnum,int ypos)95 void DisplayMessageAtY(int msnum, int ypos) {
96     char msgbufr[3001];
97     if (msnum>=500) { //quit("global message requseted, nto yet supported");
98         get_message_text (msnum, msgbufr);
99         if (display_message_aschar > 0)
100             DisplaySpeech(msgbufr, display_message_aschar);
101         else
102             DisplayAtY(ypos, msgbufr);
103         display_message_aschar=0;
104         return;
105     }
106 
107     if (display_message_aschar > 0) {
108         display_message_aschar=0;
109         quit("!DisplayMessage: data column specified a character for local\n"
110             "message; use the message editor to select the character for room\n"
111             "messages.\n");
112     }
113 
114     int repeatloop=1;
115     while (repeatloop) {
116         get_message_text (msnum, msgbufr);
117 
118         if (thisroom.msgi[msnum].displayas>0) {
119             DisplaySpeech(msgbufr, thisroom.msgi[msnum].displayas - 1);
120         }
121         else {
122             // time out automatically if they have set that
123             int oldGameSkipDisp = play.skip_display;
124             if (thisroom.msgi[msnum].flags & MSG_TIMELIMIT)
125                 play.skip_display = 0;
126 
127             DisplayAtY(ypos, msgbufr);
128 
129             play.skip_display = oldGameSkipDisp;
130         }
131         if (thisroom.msgi[msnum].flags & MSG_DISPLAYNEXT) {
132             msnum++;
133             repeatloop=1;
134         }
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     multiply_up_coordinates(&xxp, &yyp);
147     widd = multiply_up_coordinate(widd);
148 
149     if (widd<1) widd=play.viewport.GetWidth()/2;
150     if (xxp<0) xxp=play.viewport.GetWidth()/2-widd/2;
151     _display_at(xxp,yyp,widd,text,1,0, 0, 0, false);
152 }
153 
DisplayAtY(int ypos,const char * texx)154 void DisplayAtY (int ypos, const char *texx) {
155     if ((ypos < -1) || (ypos >= BASEHEIGHT))
156         quitprintf("!DisplayAtY: invalid Y co-ordinate supplied (used: %d; valid: 0..%d)", ypos, BASEHEIGHT);
157 
158     // Display("") ... a bit of a stupid thing to do, so ignore it
159     if (texx[0] == 0)
160         return;
161 
162     if (ypos > 0)
163         ypos = multiply_up_coordinate(ypos);
164 
165     if (game.options[OPT_ALWAYSSPCH])
166         DisplaySpeechAt(-1, (ypos > 0) ? divide_down_coordinate(ypos) : ypos, -1, game.playercharacter, texx);
167     else {
168         // Normal "Display" in text box
169 
170         if (screen_is_dirty) {
171             // erase any previous DisplaySpeech
172             play.disabled_user_interface ++;
173             UpdateGameOnce();
174             play.disabled_user_interface --;
175         }
176 
177         _display_at(-1,ypos,play.viewport.GetWidth()/2+play.viewport.GetWidth()/4,get_translation(texx),1,0, 0, 0, false);
178     }
179 }
180 
SetSpeechStyle(int newstyle)181 void SetSpeechStyle (int newstyle) {
182     if ((newstyle < 0) || (newstyle > 3))
183         quit("!SetSpeechStyle: must use a SPEECH_* constant as parameter");
184     game.options[OPT_SPEECHTYPE] = newstyle;
185 }
186 
SetSkipSpeech(SkipSpeechStyle newval)187 void SetSkipSpeech (SkipSpeechStyle newval) {
188     if ((newval < kSkipSpeechFirst) || (newval > kSkipSpeechLast))
189         quit("!SetSkipSpeech: invalid skip mode specified");
190 
191     debug_script_log("SkipSpeech style set to %d", newval);
192     play.cant_skip_speech = user_to_internal_skip_speech((SkipSpeechStyle)newval);
193 }
194 
GetSkipSpeech()195 SkipSpeechStyle GetSkipSpeech()
196 {
197     return internal_skip_speech_to_user(play.cant_skip_speech);
198 }
199