1 /*
2  * dlgAlert.cpp - AES-like AlertBox
3  *
4  * Copyright (c) 2004-2007 Petr Stehlik of ARAnyM dev team (see AUTHORS)
5  *
6  * This file is part of the ARAnyM project which builds a new and powerful
7  * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
8  *
9  * ARAnyM is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * ARAnyM is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with ARAnyM; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "sysdeps.h"
25 #include <string.h>
26 #include <stdlib.h>
27 
28 #include "sdlgui.h"
29 #include "dlgAlert.h"
30 
31 #define DLG_WIDTH 76
32 #define MAX_LINES 20
33 
34 /* The "Alert"-dialog: */
35 SGOBJ alertdlg[1/*BACKGROUND*/ + MAX_LINES/*text*/ + 1/*OK*/ + 1/*Cancel*/ + 1/*NULL*/] =
36 {
37   { SGBOX, SG_BACKGROUND, 0, 0,0, DLG_WIDTH,25, NULL, 0 },
38   { -1, 0, 0, 0,0, 0,0, NULL, 0 }
39 };
40 
41 SGOBJ obj_text = { SGTEXT, 0, 0, 1,1, DLG_WIDTH-2,1, NULL, 0 };
42 SGOBJ obj_but_ok = { SGBUTTON, SG_SELECTABLE|SG_EXIT|SG_DEFAULT, 0, (DLG_WIDTH-8-8)/3,5, 8,1, "OK", 0 };
43 SGOBJ obj_but_cancel = { SGBUTTON, SG_SELECTABLE|SG_EXIT, 0, (DLG_WIDTH-8-8)*2/3+8,5, 8,1, "Cancel", 0 };
44 SGOBJ obj_null = { -1, 0, 0, 0,0, 0,0, NULL, 0 };
45 
46 /*
47    Breaks long string to several strings of max_width, divided by '\0'
48    and returns the number of lines you need to display the strings.
49 */
FormatTextToBox(char * text,int max_width)50 int FormatTextToBox(char *text, int max_width)
51 {
52 	int lines=1;
53 	int delka = strlen(text);
54 	char *p;		/* pointer to begin of actual line */
55 	char *q;		/* pointer to start of next search */
56 	char *rozdel = text-1;	/* pointer to last place suitable for breaking the line */
57 	char *konec;	/* pointer to end of the text */
58 	q = p = text;
59 	konec = text + delka;
60 
61 	while(q < konec) {		/* q was last place suitable for breaking */
62 		char *r = strpbrk(q, " \t/\\\n");	/* find next suitable place for the break */
63 		if (r == NULL)
64 			r = konec;		/* if there's no place then point to the end */
65 
66 		if ((r-p) < max_width && *r != '\n') {		/* '\n' is always used for breaking */
67 			rozdel = r;		/* remember new place suitable for breaking */
68 			q++;
69 			continue;		/* search again */
70 		}
71 
72 		if ((r-p) > max_width) {	/* too long line already? */
73 			if (p > rozdel)				/* bad luck - no place for the delimiter. Let's do it the strong way */
74 				rozdel = p + max_width;		/* we loose one character */
75 		}
76 		else
77 			rozdel = r;			/* break in this place */
78 
79 		*rozdel = '\0';			/* BREAK */
80 		p = q = rozdel+1;		/* next line begins here */
81 		lines++;				/* increment line counter */
82 	}
83 	return lines;					/* return line counter */
84 }
85 
86 
87 
88 /*-----------------------------------------------------------------------*/
89 /*
90   Show the "alert" dialog:
91 */
92 
DlgAlert(SGOBJ * dlg,const char * _text,alert_type _type)93 DlgAlert::DlgAlert(SGOBJ *dlg, const char *_text, alert_type _type)
94 	: Dialog(dlg), text(_text), type(_type), orig_t(NULL), ok_but_idx(-1)
95 {
96 	char *t = (char *)malloc(strlen(text)+1);
97 	orig_t = t;
98 	strcpy(t, text);
99 	int max_linelen = 0;
100 	// break long text into '\0' terminated array of strings
101 	int lines = FormatTextToBox(t, obj_text.w);
102 	if (lines > MAX_LINES)
103 		lines = MAX_LINES;
104 	// build the dialog, find the longest line
105 	int idx = 1;
106 	for(int i=0; i<lines; i++) {
107 		obj_text.y = i+1;
108 		obj_text.txt = t;
109 		alertdlg[idx++] = obj_text;
110 		int str_len = strlen(t);
111 		if (str_len > max_linelen)
112 			max_linelen = str_len;
113 		t += str_len + 1;
114 	}
115 
116 	// compute smallest possible dialog width
117 	int dlg_width = obj_but_ok.w + 2;
118 	if (type == ALERT_OKCANCEL) {
119 		dlg_width += obj_but_cancel.w + 2;
120 	}
121 	if (max_linelen+2 > dlg_width)
122 		dlg_width = max_linelen+2;
123 
124 	// update dialog width
125 	alertdlg[0].w = dlg_width;
126 	for(int i=0; i<lines; i++) {
127 		alertdlg[1+i].w = max_linelen;
128 	}
129 
130 	// update OK/Cancel buttons placement
131 	obj_but_ok.y = lines+2;
132 	obj_but_cancel.y = lines+2;
133 	if (type == ALERT_OKCANCEL) {
134 		int butwidth = obj_but_ok.w + obj_but_cancel.w;
135 		int space = alertdlg[0].w - butwidth;
136 		obj_but_ok.x = space / 3;
137 		obj_but_cancel.x = space * 2/3 + obj_but_ok.w;
138 	}
139 	else {
140 		obj_but_ok.x = (alertdlg[0].w - obj_but_ok.w) / 2;
141 	}
142 
143 	// add OK/Cancel buttons to dialog
144 	ok_but_idx = idx;
145 	alertdlg[idx++] = obj_but_ok;
146 	if (type == ALERT_OKCANCEL) {
147 		alertdlg[idx++] = obj_but_cancel;
148 	}
149 	alertdlg[idx] = obj_null;
150 	alertdlg[0].h = lines+4;
151 }
152 
~DlgAlert()153 DlgAlert::~DlgAlert()
154 {
155 	if (orig_t) {
156 		free(orig_t);
157 		orig_t = NULL;
158 	}
159 }
160 
pressedOk(void)161 bool DlgAlert::pressedOk(void)
162 {
163 	return (return_obj == ok_but_idx);
164 }
165 
processResult(void)166 void DlgAlert::processResult(void)
167 {
168 }
169 
DlgAlertOpen(const char * text,alert_type type)170 Dialog *DlgAlertOpen(const char *text, alert_type type)
171 {
172 	return new DlgAlert(alertdlg, text, type);
173 }
174