1 /*
2 Hatari - sdlgui.c
3
4 This file is distributed under the GNU General Public License, version 2
5 or at your option any later version. Read the file gpl.txt for details.
6
7 A tiny graphical user interface for Hatari.
8 */
9 const char SDLGui_fileid[] = "Hatari sdlgui.c : " __DATE__ " " __TIME__;
10
11 #include <SDL.h>
12 #include <ctype.h>
13 #include <string.h>
14
15 #include "main.h"
16 #include "sdlgui.h"
17
18 //RETRO DEF
19
20 #include "gui-retro.h"
21
22 extern int touch;
23 int gmx,gmy;
24 int okold=0,boutc=0;
25
26 extern unsigned short int bmp[1024*1024];
27 #define B ((rgba>> 8)&0xff)>>3
28 #define G ((rgba>>16)&0xff)>>3
29 #define R ((rgba>>24)&0xff)>>3
30
31 #define RGB565(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
32
33 extern void Draw_text(unsigned short *buffer,int x,int y,unsigned short fgcol,unsigned short int bgcol ,int scalex,int scaley , int max,char *string,...);
34 extern void DrawFBoxBmp(unsigned short *buffer,int x,int y,int dx,int dy,unsigned short color);
35 extern void input_gui();
36
37 static const char *cross[] = {
38 "X ",
39 "XX ",
40 "X.X ",
41 "X..X ",
42 "X...X ",
43 "X....X ",
44 "X.....X ",
45 "X......X ",
46 "X.......X ",
47 "X........X ",
48 "X.....XXXXX ",
49 "X..X..X ",
50 "X.X X..X ",
51 "XX X..X ",
52 "X X..X ",
53 " X..X ",
54 " X..X ",
55 " X..X ",
56 " XX ",
57 " ",
58 };
59
draw_cross(int x,int y)60 void draw_cross(int x,int y) {
61
62 int i,j,idx;
63 int dx=32,dy=20;
64 unsigned short color;
65
66 for(j=y;j<y+dy;j++){
67 idx=0;
68 for(i=x;i<x+dx;i++){
69 if(cross[j-y][idx]=='.')DrawPointBmp(bmp,i,j,0xffff);
70 else if(cross[j-y][idx]=='X')DrawPointBmp(bmp,i,j,0);
71 idx++;
72 }
73 }
74 }
75
76
77 #if 0
78 #include "font5x8.h"
79 #include "font10x16.h"
80 #endif
81 static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */
82 #if 0
83 static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */
84 static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */
85 static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */
86 #endif
87
88 static int current_object = 0; /* Current selected object */
89
90 int sdlgui_fontwidth; /* Width of the actual font */
91 int sdlgui_fontheight; /* Height of the actual font */
92 #if 0
93 /*-----------------------------------------------------------------------*/
94 /**
95 * Load an 1 plane XBM into a 8 planes SDL_Surface.
96 */
97 static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
98 {
99 SDL_Surface *bitmap;
100 Uint8 *dstbits;
101 const Uint8 *srcbits;
102 int x, y, srcpitch;
103 int mask;
104
105 srcbits = pXbmBits;
106
107 /* Allocate the bitmap */
108 bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
109 if (bitmap == NULL)
110 {
111 fprintf(stderr, "Failed to allocate bitmap: %s", SDL_GetError());
112 return NULL;
113 }
114
115 srcpitch = ((w + 7) / 8);
116 dstbits = (Uint8 *)bitmap->pixels;
117 mask = 1;
118
119 /* Copy the pixels */
120 for (y = 0 ; y < h ; y++)
121 {
122 for (x = 0 ; x < w ; x++)
123 {
124 dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0;
125 mask <<= 1;
126 mask |= (mask >> 8);
127 mask &= 0xFF;
128 }
129 dstbits += bitmap->pitch;
130 srcbits += srcpitch;
131 }
132
133 return bitmap;
134 }
135 #endif
136
137 /*-----------------------------------------------------------------------*/
138 /**
139 * Initialize the GUI.
140 */
SDLGui_Init(void)141 int SDLGui_Init(void)
142 {
143 #if 0
144 SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {0, 0, 0, 0}};
145
146 if (pSmallFontGfx && pBigFontGfx)
147 {
148 /* already initialized */
149 return 0;
150 }
151
152 /* Initialize the font graphics: */
153 pSmallFontGfx = SDLGui_LoadXBM(font5x8_width, font5x8_height, font5x8_bits);
154 pBigFontGfx = SDLGui_LoadXBM(font10x16_width, font10x16_height, font10x16_bits);
155 if (pSmallFontGfx == NULL || pBigFontGfx == NULL)
156 {
157 fprintf(stderr, "Error: Can not init font graphics!\n");
158 return -1;
159 }
160
161 /* Set color palette of the font graphics: */
162 SDL_SetColors(pSmallFontGfx, blackWhiteColors, 0, 2);
163 SDL_SetColors(pBigFontGfx, blackWhiteColors, 0, 2);
164
165 /* Set font color 0 as transparent: */
166 SDL_SetColorKey(pSmallFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
167 SDL_SetColorKey(pBigFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
168 #endif
169 return 0;
170 }
171
172
173 /*-----------------------------------------------------------------------*/
174 /**
175 * Uninitialize the GUI.
176 */
SDLGui_UnInit(void)177 int SDLGui_UnInit(void)
178 {
179 #if 0
180 if (pSmallFontGfx)
181 {
182 SDL_FreeSurface(pSmallFontGfx);
183 pSmallFontGfx = NULL;
184 }
185
186 if (pBigFontGfx)
187 {
188 SDL_FreeSurface(pBigFontGfx);
189 pBigFontGfx = NULL;
190 }
191 #endif
192 return 0;
193 }
194
195
196 /*-----------------------------------------------------------------------*/
197 /**
198 * Inform the SDL-GUI about the actual SDL_Surface screen pointer and
199 * prepare the font to suit the actual resolution.
200 */
SDLGui_SetScreen(SDL_Surface * pScrn)201 int SDLGui_SetScreen(SDL_Surface *pScrn)
202 {
203 #if 0
204 pSdlGuiScrn = pScrn;
205
206 /* Decide which font to use - small or big one: */
207 if (pSdlGuiScrn->w >= 640 && pSdlGuiScrn->h >= 400 && pBigFontGfx != NULL)
208 {
209 pFontGfx = pBigFontGfx;
210 }
211 else
212 {
213 pFontGfx = pSmallFontGfx;
214 }
215
216 if (pFontGfx == NULL)
217 {
218 fprintf(stderr, "Error: A problem with the font occurred!\n");
219 return -1;
220 }
221
222 /* Get the font width and height: */
223 sdlgui_fontwidth = pFontGfx->w/16;
224 sdlgui_fontheight = pFontGfx->h/16;
225
226 return 0;
227 #else
228 pSdlGuiScrn = pScrn;
229 memset(bmp, 0, sizeof(bmp));
230
231 sdlgui_fontwidth = 10;
232 sdlgui_fontheight = 16;
233 return 0;
234 #endif
235 }
236
237 /*-----------------------------------------------------------------------*/
238 /**
239 * Return character size for current font in given arguments.
240 */
SDLGui_GetFontSize(int * width,int * height)241 void SDLGui_GetFontSize(int *width, int *height)
242 {
243 *width = sdlgui_fontwidth;
244 *height = sdlgui_fontheight;
245 }
246
247 /*-----------------------------------------------------------------------*/
248 /**
249 * Center a dialog so that it appears in the middle of the screen.
250 * Note: We only store the coordinates in the root box of the dialog,
251 * all other objects in the dialog are positioned relatively to this one.
252 */
SDLGui_CenterDlg(SGOBJ * dlg)253 void SDLGui_CenterDlg(SGOBJ *dlg)
254 {
255 dlg[0].x = (pSdlGuiScrn->w/sdlgui_fontwidth-dlg[0].w)/2;
256 dlg[0].y = (pSdlGuiScrn->h/sdlgui_fontheight-dlg[0].h)/2;
257 }
258
259
260 /*-----------------------------------------------------------------------*/
261 /**
262 * Draw a text string.
263 */
SDLGui_Text(int x,int y,const char * txt)264 void SDLGui_Text(int x, int y, const char *txt)
265 {
266 /*
267 int i;
268 unsigned char c;
269 SDL_Rect sr, dr;
270
271 for (i=0; txt[i]!=0; i++)
272 {
273 c = txt[i];
274 sr.x=sdlgui_fontwidth*(c%16);
275 sr.y=sdlgui_fontheight*(c/16);
276 sr.w=sdlgui_fontwidth;
277 sr.h=sdlgui_fontheight;
278 dr.x=x+i*sdlgui_fontwidth;
279 dr.y=y;
280 dr.w=sdlgui_fontwidth;
281 dr.h=sdlgui_fontheight;
282 SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr);
283 }
284 */
285 Draw_text(bmp,x,y,1,0,1,2,40,(char *)txt);
286 }
287
288
289 /*-----------------------------------------------------------------------*/
290 /**
291 * Draw a dialog text object.
292 */
SDLGui_DrawText(const SGOBJ * tdlg,int objnum)293 static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
294 {
295 int x, y;
296 x = (tdlg[0].x+tdlg[objnum].x)*sdlgui_fontwidth;
297 y = (tdlg[0].y+tdlg[objnum].y)*sdlgui_fontheight;
298 SDLGui_Text(x, y, tdlg[objnum].txt);
299 }
300
301
302 /*-----------------------------------------------------------------------*/
303 /**
304 * Draw a edit field object.
305 */
SDLGui_DrawEditField(const SGOBJ * edlg,int objnum)306 static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
307 {
308 int x, y;
309 SDL_Rect rect;
310
311 x = (edlg[0].x+edlg[objnum].x)*sdlgui_fontwidth;
312 y = (edlg[0].y+edlg[objnum].y)*sdlgui_fontheight;
313 SDLGui_Text(x, y, edlg[objnum].txt);
314
315 rect.x = x;
316 rect.y = y + edlg[objnum].h * sdlgui_fontheight;
317 rect.w = edlg[objnum].w * sdlgui_fontwidth;
318 rect.h = 1;
319 SDL_FillRect(pSdlGuiScrn, &rect, SDL_MapRGB(pSdlGuiScrn->format,160,160,160));
320 }
321
322
323 /*-----------------------------------------------------------------------*/
324 /**
325 * Draw a dialog box object.
326 */
SDLGui_DrawBox(const SGOBJ * bdlg,int objnum)327 static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
328 {
329 SDL_Rect rect;
330 int x, y, w, h, offset;
331 Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
332 Uint32 upleftc, downrightc;
333
334 x = bdlg[objnum].x*sdlgui_fontwidth;
335 y = bdlg[objnum].y*sdlgui_fontheight;
336 if (objnum > 0) /* Since the root object is a box, too, */
337 {
338 /* we have to look for it now here and only */
339 x += bdlg[0].x*sdlgui_fontwidth; /* add its absolute coordinates if we need to */
340 y += bdlg[0].y*sdlgui_fontheight;
341 }
342 w = bdlg[objnum].w*sdlgui_fontwidth;
343 h = bdlg[objnum].h*sdlgui_fontheight;
344
345 if (bdlg[objnum].state & SG_SELECTED)
346 {
347 upleftc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
348 downrightc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
349 }
350 else
351 {
352 upleftc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
353 downrightc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
354 }
355
356 /* The root box should be bigger than the screen, so we disable the offset there: */
357 if (objnum != 0)
358 offset = 1;
359 else
360 offset = 0;
361
362 /* Draw background: */
363 rect.x = x;
364 rect.y = y;
365 rect.w = w;
366 rect.h = h;
367 SDL_FillRect(pSdlGuiScrn, &rect, grey);
368
369 /* Draw upper border: */
370 rect.x = x;
371 rect.y = y - offset;
372 rect.w = w;
373 rect.h = 1;
374 SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
375
376 /* Draw left border: */
377 rect.x = x - offset;
378 rect.y = y;
379 rect.w = 1;
380 rect.h = h;
381 SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
382
383 /* Draw bottom border: */
384 rect.x = x;
385 rect.y = y + h - 1 + offset;
386 rect.w = w;
387 rect.h = 1;
388 SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
389
390 /* Draw right border: */
391 rect.x = x + w - 1 + offset;
392 rect.y = y;
393 rect.w = 1;
394 rect.h = h;
395 SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
396 }
397
398
399 /*-----------------------------------------------------------------------*/
400 /**
401 * Draw a normal button.
402 */
SDLGui_DrawButton(const SGOBJ * bdlg,int objnum)403 static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
404 {
405 int x,y;
406
407 SDLGui_DrawBox(bdlg, objnum);
408
409 x = (bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w-strlen(bdlg[objnum].txt))/2) * sdlgui_fontwidth;
410 y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * sdlgui_fontheight;
411
412 if (bdlg[objnum].state & SG_SELECTED)
413 {
414 x+=1;
415 y+=1;
416 }
417 SDLGui_Text(x, y, bdlg[objnum].txt);
418 }
419
420
421 /*-----------------------------------------------------------------------*/
422 /**
423 * Draw a dialog radio button object.
424 */
SDLGui_DrawRadioButton(const SGOBJ * rdlg,int objnum)425 static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
426 {
427 char str[80];
428 int x, y;
429
430 x = (rdlg[0].x + rdlg[objnum].x) * sdlgui_fontwidth;
431 y = (rdlg[0].y + rdlg[objnum].y) * sdlgui_fontheight;
432
433 if (rdlg[objnum].state & SG_SELECTED)
434 str[0]=SGRADIOBUTTON_SELECTED;
435 else
436 str[0]=SGRADIOBUTTON_NORMAL;
437 str[1]=' ';
438 strcpy(&str[2], rdlg[objnum].txt);
439
440 SDLGui_Text(x, y, str);
441 }
442
443
444 /*-----------------------------------------------------------------------*/
445 /**
446 * Draw a dialog check box object.
447 */
SDLGui_DrawCheckBox(const SGOBJ * cdlg,int objnum)448 static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
449 {
450 char str[80];
451 int x, y;
452
453 x = (cdlg[0].x + cdlg[objnum].x) * sdlgui_fontwidth;
454 y = (cdlg[0].y + cdlg[objnum].y) * sdlgui_fontheight;
455
456 if ( cdlg[objnum].state&SG_SELECTED )
457 str[0]=SGCHECKBOX_SELECTED;
458 else
459 str[0]=SGCHECKBOX_NORMAL;
460 str[1]=' ';
461 strcpy(&str[2], cdlg[objnum].txt);
462
463 SDLGui_Text(x, y, str);
464 }
465
466
467 /*-----------------------------------------------------------------------*/
468 /**
469 * Draw a scrollbar button.
470 */
SDLGui_DrawScrollbar(const SGOBJ * bdlg,int objnum)471 static void SDLGui_DrawScrollbar(const SGOBJ *bdlg, int objnum)
472 {
473 SDL_Rect rect;
474 int x, y, w, h;
475 Uint32 grey0 = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
476 Uint32 grey1 = SDL_MapRGB(pSdlGuiScrn->format,196,196,196);
477 Uint32 grey2 = SDL_MapRGB(pSdlGuiScrn->format, 64, 64, 64);
478
479 x = bdlg[objnum].x * sdlgui_fontwidth;
480 y = bdlg[objnum].y * sdlgui_fontheight + bdlg[objnum].h;
481
482 x += bdlg[0].x*sdlgui_fontwidth; /* add mainbox absolute coordinates */
483 y += bdlg[0].y*sdlgui_fontheight; /* add mainbox absolute coordinates */
484
485 w = 1 * sdlgui_fontwidth;
486 h = bdlg[objnum].w;
487
488 /* Draw background: */
489 rect.x = x;
490 rect.y = y;
491 rect.w = w;
492 rect.h = h;
493 SDL_FillRect(pSdlGuiScrn, &rect, grey0);
494
495 /* Draw upper border: */
496 rect.x = x;
497 rect.y = y;
498 rect.w = w;
499 rect.h = 1;
500 SDL_FillRect(pSdlGuiScrn, &rect, grey1);
501
502 /* Draw bottom border: */
503 rect.x = x;
504 rect.y = y + h - 1;
505 rect.w = w;
506 rect.h = 1;
507 SDL_FillRect(pSdlGuiScrn, &rect, grey2);
508
509 }
510
511 /*-----------------------------------------------------------------------*/
512 /**
513 * Draw a dialog popup button object.
514 */
SDLGui_DrawPopupButton(const SGOBJ * pdlg,int objnum)515 static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
516 {
517 int x, y, w;
518 const char *downstr = "\x02";
519
520 SDLGui_DrawBox(pdlg, objnum);
521
522 x = (pdlg[0].x + pdlg[objnum].x) * sdlgui_fontwidth;
523 y = (pdlg[0].y + pdlg[objnum].y) * sdlgui_fontheight;
524 w = pdlg[objnum].w * sdlgui_fontwidth;
525
526 SDLGui_Text(x, y, pdlg[objnum].txt);
527 SDLGui_Text(x+w-sdlgui_fontwidth, y, downstr);
528 }
529
530 #if 0
531 /*-----------------------------------------------------------------------*/
532 /**
533 * Let the user insert text into an edit field object.
534 * NOTE: The dlg[objnum].txt must point to an an array that is big enough
535 * for dlg[objnum].w characters!
536 */
537 static void SDLGui_EditField(SGOBJ *dlg, int objnum)
538 {
539 size_t cursorPos; /* Position of the cursor in the edit field */
540 int blinkState = 0; /* Used for cursor blinking */
541 int bStopEditing = false; /* true if user wants to exit the edit field */
542 char *txt; /* Shortcut for dlg[objnum].txt */
543 SDL_Rect rect;
544 Uint32 grey, cursorCol;
545 SDL_Event event;
546 int nOldUnicodeMode;
547
548 /* Enable unicode translation to get proper characters with SDL_PollEvent */
549 nOldUnicodeMode = SDL_EnableUNICODE(true);
550
551 grey = SDL_MapRGB(pSdlGuiScrn->format, 192, 192, 192);
552 cursorCol = SDL_MapRGB(pSdlGuiScrn->format, 128, 128, 128);
553
554 rect.x = (dlg[0].x + dlg[objnum].x) * sdlgui_fontwidth;
555 rect.y = (dlg[0].y + dlg[objnum].y) * sdlgui_fontheight;
556 rect.w = (dlg[objnum].w + 1) * sdlgui_fontwidth - 1;
557 rect.h = dlg[objnum].h * sdlgui_fontheight;
558
559 txt = dlg[objnum].txt;
560 cursorPos = strlen(txt);
561
562 do
563 {
564 /* Look for events */
565 if (SDL_PollEvent(&event) == 0)
566 {
567 /* No event: Wait some time for cursor blinking */
568 SDL_Delay(250);
569 blinkState ^= 1;
570 }
571 else
572 {
573 /* Handle events */
574 do
575 {
576 switch (event.type)
577 {
578 case SDL_QUIT: /* User wants to quit */
579 bQuitProgram = true;
580 bStopEditing = true;
581 break;
582 case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */
583 bStopEditing = true;
584 break;
585 case SDL_KEYDOWN: /* Key pressed */
586 switch (event.key.keysym.sym)
587 {
588 case SDLK_RETURN:
589 case SDLK_KP_ENTER:
590 bStopEditing = true;
591 break;
592 case SDLK_LEFT:
593 if (cursorPos > 0)
594 cursorPos -= 1;
595 break;
596 case SDLK_RIGHT:
597 if (cursorPos < strlen(txt))
598 cursorPos += 1;
599 break;
600 case SDLK_BACKSPACE:
601 if (cursorPos > 0)
602 {
603 memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
604 cursorPos -= 1;
605 }
606 break;
607 case SDLK_DELETE:
608 if (cursorPos < strlen(txt))
609 memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1);
610 break;
611 default:
612 /* If it is a "good" key then insert it into the text field */
613 if (event.key.keysym.unicode >= 32 && event.key.keysym.unicode < 128
614 && event.key.keysym.unicode != PATHSEP)
615 {
616 if (strlen(txt) < (size_t)dlg[objnum].w)
617 {
618 memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
619 txt[cursorPos] = event.key.keysym.unicode;
620 cursorPos += 1;
621 }
622 }
623 break;
624 }
625 break;
626 }
627 }
628 while (SDL_PollEvent(&event));
629
630 blinkState = 1;
631 }
632
633 /* Redraw the text field: */
634 SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw background */
635 /* Draw the cursor: */
636 if (blinkState && !bStopEditing)
637 {
638 SDL_Rect cursorrect;
639 cursorrect.x = rect.x + cursorPos * sdlgui_fontwidth;
640 cursorrect.y = rect.y;
641 cursorrect.w = sdlgui_fontwidth;
642 cursorrect.h = rect.h;
643 SDL_FillRect(pSdlGuiScrn, &cursorrect, cursorCol);
644 }
645 SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */
646 SDL_UpdateRects(pSdlGuiScrn, 1, &rect);
647 }
648 while (!bStopEditing);
649
650 SDL_EnableUNICODE(nOldUnicodeMode);
651 }
652
653 #else
SDLGui_EditField(SGOBJ * dlg,int objnum)654 static void SDLGui_EditField(SGOBJ *dlg, int objnum)
655 {
656 }
657 #endif
658
659 /*-----------------------------------------------------------------------*/
660 /**
661 * Draw a whole dialog.
662 */
SDLGui_DrawDialog(const SGOBJ * dlg)663 void SDLGui_DrawDialog(const SGOBJ *dlg)
664 {
665 int i;
666
667 memset(bmp, 0, sizeof(bmp));
668
669 for (i = 0; dlg[i].type != -1; i++)
670 {
671 switch (dlg[i].type)
672 {
673 case SGBOX:
674 SDLGui_DrawBox(dlg, i);
675 break;
676 case SGTEXT:
677 SDLGui_DrawText(dlg, i);
678 break;
679 case SGEDITFIELD:
680 SDLGui_DrawEditField(dlg, i);
681 break;
682 case SGBUTTON:
683 SDLGui_DrawButton(dlg, i);
684 break;
685 case SGRADIOBUT:
686 SDLGui_DrawRadioButton(dlg, i);
687 break;
688 case SGCHECKBOX:
689 SDLGui_DrawCheckBox(dlg, i);
690 break;
691 case SGPOPUP:
692 SDLGui_DrawPopupButton(dlg, i);
693 break;
694 case SGSCROLLBAR:
695 SDLGui_DrawScrollbar(dlg, i);
696 break;
697 }
698 }
699 SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
700 }
701
702
703 /*-----------------------------------------------------------------------*/
704 /**
705 * Search an object at a certain position.
706 * Return object index or -1 if it wasn't found.
707 */
SDLGui_FindObj(const SGOBJ * dlg,int fx,int fy)708 static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
709 {
710 int len, i;
711 int ob = -1;
712 int xpos, ypos;
713
714 len = 0;
715 while (dlg[len].type != -1) len++;
716
717 xpos = fx / sdlgui_fontwidth;
718 ypos = fy / sdlgui_fontheight;
719 /* Now search for the object: */
720 for (i = len; i >= 0; i--)
721 {
722 /* clicked on a scrollbar ? */
723 if (dlg[i].type == SGSCROLLBAR) {
724 if (xpos >= dlg[0].x+dlg[i].x && xpos < dlg[0].x+dlg[i].x+1) {
725 ypos = dlg[i].y * sdlgui_fontheight + dlg[i].h + dlg[0].y * sdlgui_fontheight;
726 if (fy >= ypos && fy < ypos + dlg[i].w) {
727 ob = i;
728 break;
729 }
730 }
731 }
732 /* clicked on another object ? */
733 else if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y
734 && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h)
735 {
736 ob = i;
737 break;
738 }
739 }
740
741 return ob;
742 }
743
744
745 /*-----------------------------------------------------------------------*/
746 /**
747 * Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL).
748 */
SDLGui_SearchFlaggedButton(const SGOBJ * dlg,int flag)749 static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag)
750 {
751 int i = 0;
752
753 while (dlg[i].type != -1)
754 {
755 if (dlg[i].flags & flag)
756 return i;
757 i++;
758 }
759
760 return 0;
761 }
762
763
764 /*-----------------------------------------------------------------------*/
765 /**
766 * Show and process a dialog. Returns the button number that has been
767 * pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occurred (will be
768 * stored in parameter pEventOut).
769 */
SDLGui_DoDialog(SGOBJ * dlg,SDL_Event * pEventOut)770 int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut)
771 {
772 int obj=0;
773 int oldbutton=0;
774 int retbutton=0;
775 int i, j, b;
776 SDL_Event sdlEvent;
777 SDL_Rect rct;
778 Uint32 grey;
779 SDL_Surface *pBgSurface;
780 SDL_Rect dlgrect, bgrect;
781
782 if (pSdlGuiScrn->h / sdlgui_fontheight < dlg[0].h)
783 {
784 fprintf(stderr, "Screen size too small for dialog!\n");
785 return SDLGUI_ERROR;
786 }
787
788 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
789
790 dlgrect.x = dlg[0].x * sdlgui_fontwidth;
791 dlgrect.y = dlg[0].y * sdlgui_fontheight;
792 dlgrect.w = dlg[0].w * sdlgui_fontwidth;
793 dlgrect.h = dlg[0].h * sdlgui_fontheight;
794
795 bgrect.x = bgrect.y = 0;
796 bgrect.w = dlgrect.w;
797 bgrect.h = dlgrect.h;
798
799 #if 0
800 /* Save background */
801 pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel,
802 pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask);
803 if (pSdlGuiScrn->format->palette != NULL)
804 {
805 SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1);
806 }
807
808 if (pBgSurface != NULL)
809 {
810 SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect);
811 }
812 else
813 {
814 fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError());
815 }
816 #endif
817 /* (Re-)draw the dialog */
818 SDLGui_DrawDialog(dlg);
819
820 /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
821 //SDL_PumpEvents();
822 input_gui();
823 b = SDL_GetMouseState(&i, &j);
824
825 if(touch!=-1){b=1;boutc=1;}
826 else {b=0;boutc=0;}
827
828 /* If current object is the scrollbar, and mouse is still down, we can scroll it */
829 /* also if the mouse pointer has left the scrollbar */
830 if (current_object >= 0 && dlg[current_object].type == SGSCROLLBAR) {
831 if (b ==1 /*& SDL_BUTTON(1)*/) {
832 obj = current_object;
833 dlg[obj].state |= SG_MOUSEDOWN;
834 oldbutton = obj;
835 retbutton = obj;
836 }
837 else {
838 obj = current_object;
839 current_object = 0;
840 dlg[obj].state &= ~SG_MOUSEDOWN;//SG_MOUSEUP;
841 //retbutton = obj;
842 //oldbutton = obj;
843 okold=1;
844 }
845 }
846 else {
847 obj = SDLGui_FindObj(dlg, i, j);
848 current_object = obj;
849 if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) )
850 {
851 oldbutton = obj;
852 if (b ==1/*& SDL_BUTTON(1)*/)
853 {
854 dlg[obj].state |= SG_SELECTED;
855 retbutton = obj;
856 }
857 else{
858 dlg[obj].state &= ~SG_SELECTED;
859 }
860 }
861 }
862
863
864 /* The main loop */
865 while (retbutton == 0 && !bQuitProgram)
866 {
867 #if 0
868 if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */
869
870 switch (sdlEvent.type)
871 {
872 case SDL_QUIT:
873 retbutton = SDLGUI_QUIT;
874 break;
875
876 case SDL_MOUSEBUTTONDOWN:
877 if (sdlEvent.button.button != SDL_BUTTON_LEFT)
878 {
879 /* Not left mouse button -> unsupported event */
880 if (pEventOut)
881 retbutton = SDLGUI_UNKNOWNEVENT;
882 break;
883 }
884 #endif
885
886 input_gui();
887
888 draw_cross(gmx,gmy);
889
890 if(touch!=-1 && okold==0 ){
891
892 okold=1;
893
894 /* It was the left button: Find the object under the mouse cursor */
895 obj = SDLGui_FindObj(dlg, gmx, gmy/*sdlEvent.button.x, sdlEvent.button.y*/);
896 if (obj>0)
897 {
898 if (dlg[obj].type==SGBUTTON)
899 {
900 dlg[obj].state |= SG_SELECTED;
901 SDLGui_DrawButton(dlg, obj);
902 // SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2, dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4);
903 oldbutton=obj;
904 }
905 if (dlg[obj].type==SGSCROLLBAR)
906 {
907 dlg[obj].state |= SG_MOUSEDOWN;
908 oldbutton=obj;
909 }
910 if ( dlg[obj].flags&SG_TOUCHEXIT )
911 {
912 dlg[obj].state |= SG_SELECTED;
913 retbutton = obj;
914 }
915 }
916 //break;
917 #if 0
918 case SDL_MOUSEBUTTONUP:
919 if (sdlEvent.button.button != SDL_BUTTON_LEFT)
920 {
921 /* Not left mouse button -> unsupported event */
922 if (pEventOut)
923 retbutton = SDLGUI_UNKNOWNEVENT;
924 break;
925 }
926 /* It was the left button: Find the object under the mouse cursor */
927 #endif
928 }
929 else if(touch==-1 && okold==1){
930 okold=0;
931 obj = SDLGui_FindObj(dlg, gmx,gmy/*sdlEvent.button.x, sdlEvent.button.y*/);
932 if (obj>0)
933 {
934 switch (dlg[obj].type)
935 {
936 case SGBUTTON:
937 if (oldbutton==obj)
938 retbutton=obj;
939 break;
940 case SGSCROLLBAR:
941 dlg[obj].state &= ~SG_MOUSEDOWN;//SG_MOUSEUP;
942
943 if (oldbutton==obj)
944 retbutton=obj;
945 break;
946 case SGEDITFIELD:
947 SDLGui_EditField(dlg, obj);
948 break;
949 case SGRADIOBUT:
950 for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--)
951 {
952 dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
953 rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
954 rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
955 rct.w = sdlgui_fontwidth;
956 rct.h = sdlgui_fontheight;
957 SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
958 SDLGui_DrawRadioButton(dlg, i);
959 // SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
960 }
961 for (i = obj+1; dlg[i].type == SGRADIOBUT; i++)
962 {
963 dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
964 rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
965 rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
966 rct.w = sdlgui_fontwidth;
967 rct.h = sdlgui_fontheight;
968 SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
969 SDLGui_DrawRadioButton(dlg, i);
970 // SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
971 }
972 dlg[obj].state |= SG_SELECTED; /* Select this radio button */
973 rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
974 rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
975 rct.w = sdlgui_fontwidth;
976 rct.h = sdlgui_fontheight;
977 SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
978 SDLGui_DrawRadioButton(dlg, obj);
979 // SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
980 break;
981 case SGCHECKBOX:
982 dlg[obj].state ^= SG_SELECTED;
983 rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
984 rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
985 rct.w = sdlgui_fontwidth;
986 rct.h = sdlgui_fontheight;
987 SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
988 SDLGui_DrawCheckBox(dlg, obj);
989 // SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
990 break;
991 case SGPOPUP:
992 dlg[obj].state |= SG_SELECTED;
993 SDLGui_DrawPopupButton(dlg, obj);
994 // SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2, dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4);
995 retbutton=obj;
996 break;
997 }
998 }
999 if (oldbutton > 0 /*&& dlg[oldbutton].type == SGBUTTON*/)
1000 {
1001 dlg[oldbutton].state &= ~SG_SELECTED;
1002 SDLGui_DrawButton(dlg, oldbutton);
1003 //SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*sdlgui_fontheight-2, dlg[oldbutton].w*sdlgui_fontwidth+4, dlg[oldbutton].h*sdlgui_fontheight+4);
1004 oldbutton = 0;
1005 }
1006 if (obj >= 0 && (dlg[obj].flags&SG_EXIT))
1007 {
1008 if(dlg[obj].type==SGBUTTON)dlg[obj].state &= ~SG_SELECTED;
1009 retbutton = obj;
1010 }
1011 #if 0
1012 break;
1013
1014 case SDL_JOYAXISMOTION:
1015 case SDL_JOYBALLMOTION:
1016 case SDL_JOYHATMOTION:
1017 case SDL_MOUSEMOTION:
1018 break;
1019
1020 case SDL_KEYDOWN: /* Key pressed */
1021 if (sdlEvent.key.keysym.sym == SDLK_RETURN
1022 || sdlEvent.key.keysym.sym == SDLK_KP_ENTER)
1023 {
1024 retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT);
1025 }
1026 else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE)
1027 {
1028 retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL);
1029 }
1030 else if (pEventOut)
1031 {
1032 retbutton = SDLGUI_UNKNOWNEVENT;
1033 }
1034 break;
1035
1036 default:
1037 if (pEventOut)
1038 retbutton = SDLGUI_UNKNOWNEVENT;
1039 break;
1040 #endif
1041
1042 }
1043
1044 if(retbutton ==0)retbutton = 1;
1045 }
1046
1047 #if 0
1048 /* Restore background */
1049 if (pBgSurface)
1050 {
1051 SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect);
1052 SDL_FreeSurface(pBgSurface);
1053 }
1054
1055 /* Copy event data of unsupported events if caller wants to have it */
1056 if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut)
1057 memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event));
1058 #endif
1059 if (retbutton == SDLGUI_QUIT)
1060 bQuitProgram = true;
1061
1062 return retbutton;
1063 }
1064
1065