1
2 /* This is a set of C functions wrapping C++ classes for popup text output */
3
4 #include <stdarg.h>
5 #include <string.h>
6 #include <math.h>
7
8 #include "GUI.h"
9 #include "GUI_widgets.h"
10 #include "GUI_loadimage.h"
11 #include "GUI_output.h"
12
13 /************************************************************************/
14 /* C functions for GUI output window support */
15 /* */
16 /************************************************************************/
17
OK_ButtonProc(void * statusp)18 static GUI_status OK_ButtonProc(void *statusp)
19 {
20 *((int *)statusp) = 1;
21 return(GUI_QUIT);
22 }
Cancel_ButtonProc(void * statusp)23 static GUI_status Cancel_ButtonProc(void *statusp)
24 {
25 *((int *)statusp) = 0;
26 return(GUI_QUIT);
27 }
28
29 extern "C" {
30
31 /* The (really C++) structure holding information for popup text output */
32 struct GUI_Output {
33 int visible;
34 SDL_Surface *screen;
35 GUI_TermWin *window;
36 GUI_Area *frame_inner;
37 GUI_Area *frame_outer;
38 SDL_Surface *behind;
39 };
40
41 /* Function to create a hidden output window 'width' by 'height' characters.
42 The 'font' argument should either be a pointer to a 16x16 character font
43 image (with an extra pixel row under each row of characters), or NULL to
44 use a default internal 8x8-pixel font.
45 */
GUI_CreateOutput(SDL_Surface * screen,int width,int height,SDL_Surface * font)46 GUI_Output *GUI_CreateOutput(SDL_Surface *screen,
47 int width, int height, SDL_Surface *font)
48 {
49 GUI_Output *output;
50 int w, h, x, y;
51
52 /* Create a new output window */
53 output = new GUI_Output;
54 output->visible = 0;
55 output->screen = screen;
56 if ( font == NULL ) {
57 font = GUI_DefaultFont();
58 }
59
60 /* Allocate the text window */
61 w = width * (font->w/16);
62 h = height * ((font->h/16)-1);
63 x = (screen->w - w)/2;
64 y = (screen->h - h)/2;
65 output->window = new GUI_TermWin(x, y, w, h, font);
66
67 /* Allocate the frame areas */
68 w += 2; h += 2;
69 x -= 1; y -= 1;
70 output->frame_inner = new GUI_Area(x, y, w, h, 255, 255, 255);
71 w += 2; h += 2;
72 x -= 1; y -= 1;
73 output->frame_outer = new GUI_Area(x, y, w, h, 0, 0, 0);
74
75 /* Allocate a save buffer for the area behind it */
76 output->behind = SDL_AllocSurface(SDL_SWSURFACE, w, h,
77 screen->format->BitsPerPixel,
78 screen->format->Rmask,
79 screen->format->Gmask,
80 screen->format->Bmask, 0);
81
82 /* Return the output window */
83 return(output);
84 }
85
86 /* Add output to an output window. If the window is visible, the output
87 will appear immediately. Note that the output windows are not overlays,
88 and any normal SDL drawing will overwrite the output window display.
89 If output causes the window to scroll, previous text will be lost.
90 */
GUI_AddOutput(GUI_Output * output,const char * fmt,...)91 void GUI_AddOutput(GUI_Output *output, const char *fmt, ...)
92 {
93 va_list ap;
94 char text[4096];
95
96 /* Get the text string */
97 va_start(ap, fmt);
98 vsprintf(text, fmt, ap); /* CAUTION: possible buffer overflow */
99 va_end(ap);
100
101 /* Add it to the window */
102 output->window->AddText(text, strlen(text));
103 }
104
105 /* Clear the contents of an output window */
GUI_ClearOutput(GUI_Output * output)106 void GUI_ClearOutput(GUI_Output *output)
107 {
108 output->window->Clear();
109 }
110
111 /* Show an output window, saving the area behind the window, and wait for
112 keyboard or mouse press input if 'wait' is non-zero.
113 */
GUI_ShowOutput(GUI_Output * output,int wait)114 void GUI_ShowOutput(GUI_Output *output, int wait)
115 {
116 /* Display the text output window */
117 output->frame_outer->SetDisplay(output->screen);
118 output->frame_inner->SetDisplay(output->screen);
119 output->window->SetDisplay(output->screen);
120 if ( output->behind ) {
121 SDL_Rect src;
122
123 src.x = output->frame_outer->X();
124 src.y = output->frame_outer->Y();
125 src.w = output->frame_outer->W();
126 src.h = output->frame_outer->H();
127 SDL_BlitSurface(output->screen, &src, output->behind, NULL);
128 }
129 output->frame_outer->Display();
130 output->frame_inner->Display();
131 output->window->Display();
132 SDL_UpdateRect(output->screen, 0, 0, 0, 0);
133 output->visible = 1;
134
135 /* Pump the event queue, waiting for key and mouse press events */
136 if ( wait ) {
137 SDL_Event event;
138
139 while ( ! SDL_PeepEvents(&event, 1, SDL_GETEVENT,
140 (SDL_KEYDOWNMASK|SDL_MOUSEBUTTONDOWNMASK)) ) {
141 SDL_Delay(20);
142 SDL_PumpEvents();
143 }
144 }
145 }
146
147 /* Hide an output window, restoring the previous contents of the display */
GUI_HideOutput(GUI_Output * output)148 void GUI_HideOutput(GUI_Output *output)
149 {
150 if ( output->behind ) {
151 SDL_Rect dst;
152
153 dst.x = output->frame_outer->X();
154 dst.y = output->frame_outer->Y();
155 dst.w = output->frame_outer->W();
156 dst.h = output->frame_outer->H();
157 SDL_BlitSurface(output->behind, NULL, output->screen, &dst);
158 SDL_UpdateRects(output->screen, 1, &dst);
159 }
160 output->visible = 0;
161 }
162
163 /* Delete an output window */
GUI_DeleteOutput(GUI_Output * output)164 void GUI_DeleteOutput(GUI_Output *output)
165 {
166 if ( output ) {
167 if ( output->visible ) {
168 GUI_HideOutput(output);
169 }
170 if ( output->window ) {
171 delete output->window;
172 output->window = NULL;
173 }
174 if ( output->behind ) {
175 SDL_FreeSurface(output->behind);
176 output->behind = NULL;
177 }
178 delete output;
179 }
180 }
181
182
183 /************************************************************************/
184 /* Simple C message-box functions for quick popup output */
185 /* */
186 /************************************************************************/
187
188 #include "okay_img.h"
189 #include "cancel_img.h"
190
191
192 /* Create a popup message box of the given style, and wait for user input.
193 If 'title' is NULL, then no title-text will be used.
194
195 Returns the index of the button pressed, which is style dependent:
196 */
GUI_MessageBox(SDL_Surface * screen,const char * title,const char * text,Uint32 style)197 int GUI_MessageBox(SDL_Surface *screen,
198 const char *title, const char *text, Uint32 style)
199 {
200 int status;
201 const int gui_w = 320, gui_h = 200;
202 GUI *gui;
203 GUI_Widget *widget;
204 GUI_TermWin *textout;
205 GUI_Button *button;
206 int w, h, x, y;
207 unsigned int i;
208 SDL_Surface *font;
209 SDL_Surface *images[2];
210 SDL_Surface *background;
211 SDL_Rect srcrect;
212 SDL_Rect dstrect;
213
214 /* Initialize status */
215 status = -1;
216
217 /* Create the GUI holder */
218 gui = new GUI(screen);
219 font = GUI_DefaultFont();
220
221 /* Create the GUI elements */
222 w = gui_w;
223 h = gui_h;
224 x = (screen->w - w)/2;
225 y = (screen->h - h)/2;
226
227 /* Save the message box background to a private surface */
228 srcrect.x = x;
229 srcrect.y = y;
230 srcrect.w = w;
231 srcrect.h = h;
232 dstrect = srcrect;
233 background = SDL_AllocSurface(SDL_SWSURFACE, w, h,
234 screen->format->BitsPerPixel,
235 screen->format->Rmask,
236 screen->format->Gmask,
237 screen->format->Bmask, 0);
238 SDL_BlitSurface(screen, &srcrect, background, NULL);
239
240 /* Adjust for the height of buttons */
241 if ( style != GUI_MBNONE ) {
242 h -= 1+32+1;
243 }
244
245 /* Create the title, if any */
246 if ( title ) {
247 char titletext[1024];
248 int title_x, title_y;
249 int title_w, title_h;
250
251 /* Set up the title coordinates */
252 title_x = x;
253 title_y = x;
254 title_w = w;
255 title_h = ((font->h/16)-1) + 4;
256 y += title_h;
257 h -= title_h;
258
259 /* Add the outer frame */
260 widget = new GUI_Area(title_x, title_y, title_w, title_h,
261 0, 0, 0);
262 gui->AddWidget(widget);
263
264 /* Add the inner frame */
265 title_x += 1; title_y += 1;
266 title_h -= 1; title_w -= 2;
267 widget = new GUI_Area(title_x, title_y, title_w, title_h,
268 255, 255, 255);
269 gui->AddWidget(widget);
270
271 /* Add the centered title text */
272 title_x += 1; title_y += 1;
273 title_h -= 2; title_w -= 2;
274 textout = new GUI_TermWin(title_x, title_y, title_w, title_h,
275 font);
276 for ( i=0; i<((title_w/(font->w/16))-strlen(title))/2; ++i ) {
277 titletext[i] = ' ';
278 }
279 titletext[i] = '\0';
280 strcat(titletext, title);
281 textout->AddText(titletext, strlen(titletext));
282 gui->AddWidget(textout);
283 }
284
285 /* Create outer frame */
286 widget = new GUI_Area(x, y, w, h, 0, 0, 0);
287 gui->AddWidget(widget);
288
289 /* Create inner frame */
290 x += 1; y += 1;
291 w -= 2; h -= 2;
292 widget = new GUI_Area(x, y, w, h, 255, 255, 255);
293 gui->AddWidget(widget);
294
295 /* Create text output area */
296 x += 1; y += 1;
297 h -= 2; w -= 2;
298 textout = new GUI_TermWin(x, y, w, h, font);
299 textout->AddText(text, strlen(text));
300 gui->AddWidget(textout);
301
302 /* Create any buttons */
303 y += h+2;
304 for ( i=0; i<2; ++i ) {
305 images[i] = NULL;
306 }
307 if ( style == GUI_MBNONE ) {
308 y += 1;
309 } else {
310 /* Create button frame */
311 x = (screen->w - gui_w)/2;
312 w = gui_w;
313 h = 1+32+1;
314 widget = new GUI_Area(x, y, w, h, 0, 0, 0);
315 gui->AddWidget(widget);
316 x += 1; y += 1;
317 w -= 2; h -= 2;
318 widget = new GUI_Area(x, y, w, h, 0xAA, 0xAA, 0xAA);
319 gui->AddWidget(widget);
320 }
321 switch (style) {
322 case GUI_MBNONE: /* Create a single large button */
323 x = (screen->w - gui_w)/2;
324 y = (screen->h - gui_h)/2;
325 button = new GUI_Button(NULL, x, y, gui_w, gui_h);
326 gui->AddWidget(button);
327 break;
328 case GUI_MBOK: /* Create a single "OK" button */
329 images[0] = GUI_LoadImage(okay_w, okay_h, okay_pal,
330 okay_data);
331 x = (screen->w - images[0]->w)/2;
332 button = new GUI_Button(&status, x, y,images[0],NULL,
333 OK_ButtonProc);
334 gui->AddWidget(button);
335 break;
336 case GUI_MBOKCANCEL: /* Create "OK" and "Cancel" buttons */
337 images[0] = GUI_LoadImage(cancel_w, cancel_h,
338 cancel_pal, cancel_data);
339 x = (screen->w - gui_w)/2 + 1;
340 button = new GUI_Button(&status, x, y,images[0],NULL,
341 Cancel_ButtonProc);
342 gui->AddWidget(button);
343 images[1] = GUI_LoadImage(okay_w, okay_h, okay_pal,
344 okay_data);
345 x = screen->w - ((screen->w - gui_w)/2 + 1) -
346 images[0]->w;
347 button = new GUI_Button(&status, x, y,images[1],NULL,
348 OK_ButtonProc);
349 gui->AddWidget(button);
350 break;
351 }
352
353 /* Run the GUI */
354 gui->Run();
355
356 /* Clean up, restore background, and return the status */
357 delete gui;
358 for ( i=0; i<2; ++i ) {
359 if ( images[i] ) {
360 SDL_FreeSurface(images[i]);
361 }
362 }
363 SDL_BlitSurface(background, NULL, screen, &dstrect);
364 SDL_UpdateRects(screen, 1, &dstrect);
365 return(status);
366 }
367
368 }; /* Extern C */
369