1 /*
2 * This file is part of TONG. http://www.nongnu.org/tong
3 * Copyright 2004, 2006 Owen Swerkstrom
4 *
5 * TONG! is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * TONG! is distributed in the hope that it will be useful and fun,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with TONG!; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "text.h"
21
22
Text()23 Text::Text() {
24 LoadGraphics();
25 x=0;
26 y=0;
27 text=NULL;
28 }
29
~Text()30 Text::~Text() {
31 delete[] text;
32 SDL_FreeSurface(textbits);
33 }
34
LoadGraphics()35 void Text::LoadGraphics() {
36 SDL_Surface* ttemp;
37 ttemp=IMG_Load("media/text.png");
38 textbits=SDL_DisplayFormatAlpha(ttemp);
39 SDL_FreeSurface(ttemp);
40 }
41
Init(int xpos,int ypos,const char * msg)42 void Text::Init(int xpos, int ypos, const char* msg) {
43 x=xpos;
44 y=ypos;
45 text=new char[(int)strlen(msg)+1];
46 strcpy(text, msg);
47 return;
48 }
49
SetText(const char * msg)50 void Text::SetText(const char* msg) {
51 delete[] text;
52 text=new char[(int)strlen(msg)+1];
53 strcpy(text, msg);
54 return;
55 }
56
SetX(int newx)57 void Text::SetX(int newx) {
58 x=newx;
59 return;
60 }
61
SetY(int newy)62 void Text::SetY(int newy) {
63 y=newy;
64 return;
65 }
66
GetLines()67 int Text::GetLines() {
68 int i, lines=1;
69 for(i=0; i<(int)strlen(text); i++) {
70 if(text[i]=='\n') {
71 lines++;
72 }
73 }
74 return lines;
75 }
76
Draw(SDL_Surface * surf)77 void Text::Draw(SDL_Surface* surf) {
78 int i;
79 int letterx = x;
80 int lettery = y;
81 SDL_Rect srcrect;
82 srcrect.w = TEXTWIDTH;
83 srcrect.h = TEXTHEIGHT;
84 //draw each letter
85 for(i = 0; text[i]; i++) {
86 if(text[i] == '\n') {
87 letterx = x;
88 lettery += TEXTHEIGHT;
89 } else {
90 srcrect.x = ((int)text[i] % 32) * TEXTWIDTH;
91 if(text[i] < '@') {
92 srcrect.y = 0;
93 } else if(text[i] < '`') {
94 srcrect.y = TEXTHEIGHT;
95 } else {
96 srcrect.y = TEXTHEIGHT * 2;
97 }
98 destrect.x = letterx;
99 destrect.y = lettery;
100 if(SDL_BlitSurface(textbits, &srcrect, surf, &destrect)) {
101 LoadGraphics();
102 SDL_BlitSurface(textbits, &srcrect, surf, &destrect);
103 }
104 letterx += TEXTWIDTH;
105 }
106 }
107 return;
108 }
109
110
Menu()111 Menu::Menu() {
112 LoadGraphics();
113 content=new char[0];
114 x=y=0;
115 boxesw=boxesh=0;
116 choices=0;
117 current=0;
118 active=false;
119 states=new int;
120 }
121
~Menu()122 Menu::~Menu() {
123 delete[] content;
124 SDL_FreeSurface(textbits);
125 delete[] states;
126 }
127
LoadGraphics()128 void Menu::LoadGraphics() {
129 SDL_Surface* ttemp;
130 ttemp=IMG_Load("media/text.png");
131 textbits=SDL_DisplayFormatAlpha(ttemp);
132 SDL_FreeSurface(ttemp);
133 ttemp=IMG_Load("media/textbox.png");
134 menubits=SDL_DisplayFormatAlpha(ttemp);
135 SDL_FreeSurface(ttemp);
136 }
137
138 //set whether the menu is active (cursor'd) or not
SetActive(bool activate)139 void Menu::SetActive(bool activate) {
140 active=activate;
141 return;
142 }
143
IsActive()144 bool Menu::IsActive() {
145 return active;
146 }
147
148 //add a choice labeled text to the menu
AddChoice(const char * text,int state)149 void Menu::AddChoice(const char* text, int state) {
150 char* temp;
151 int i;
152 int* newstates=new int[choices+1];
153
154 for(i=0; i<(int)choices; i++) {
155 newstates[i]=states[i];
156 }
157 newstates[choices]=state;
158 delete[] states;
159 states=newstates;
160 choices++;
161
162 if(choices==1) {
163 //easy to add the first one
164 current=1;
165 temp=new char[(int)strlen(text)+1];
166 strcpy(temp, text);
167 } else {
168 //put newlines between choices, end with null
169 temp=new char[(int)strlen(text)+(int)strlen(content)+2];
170 strncpy(temp, content, strlen(content));
171 temp[strlen(content)]='\n';
172 temp[strlen(content)+1]='\0';
173 strcat(temp, text);
174 }
175 //swap the completed temp in for the menu's content
176 delete[] content;
177 content=temp;
178 CalcArea();
179 return;
180 }
181
182 //replace the menu's which'th choice with text
ModChoice(const char * text,unsigned int which)183 bool Menu::ModChoice(const char* text, unsigned int which) {
184 char* temp;
185 unsigned int newlines=0, keepchars=0;
186 int i, startpos=0, endpos=0;
187 bool success=false;
188
189 if(which>choices || which<1) {
190 // printf("out-of-range ModChoice\n");
191 } else {
192 //easy to replace just one
193 if(choices==1) {
194 current=1;
195 temp=new char[(int)strlen(text)+1];
196 if(temp==NULL) {
197 printf("couldn't allocate %d!\n", (int)strlen(text)+1);
198 return false;
199 }
200 strcpy(temp, text);
201 } else {
202 for(i=0; i<(int)strlen(content)-1; i++) {
203 if(content[i]=='\n') {
204 newlines++;
205 //watch for position of newlines around which'th choice
206 if(newlines+1==which) {
207 startpos=i;
208 } else if(newlines==which) {
209 endpos=i;
210 }
211 }
212 }
213 keepchars=strlen(content)-(endpos-startpos);
214 temp=new char[(int)strlen(text)+keepchars+2];
215 if(temp==NULL) {
216 printf("couldn't allocate %d!\n", (int)(keepchars+2+strlen(text)));
217 return false;
218 }
219 if(endpos==0) {
220 //last option changes
221 strncpy(temp, content, startpos);
222 temp[startpos]='\n';
223 temp[startpos+1]='\0';
224 strcat(temp, text);
225 } else {
226 if(startpos>0) {
227 //some middle option changes
228 strncpy(temp, content, startpos);
229 temp[startpos]='\n';
230 strncpy(temp+startpos+1, text, strlen(text)+1);
231 startpos++; //?! not sure why this and the +1^ are needed
232 } else {
233 //first option changes
234 strncpy(temp, text, strlen(text));
235 }
236 temp[startpos+strlen(text)]='\n';
237 strcpy(temp+startpos+strlen(text)+1, content+endpos+1);
238 }
239 /*this better not be necessary... :^S
240 if(temp[strlen(temp)]!='\0') {
241 temp[strlen(temp)]='\0';
242 }
243 */
244 //swap the completed temp in for the menu's content
245 delete[] content;
246 content=temp;
247 CalcArea();
248 success=true;
249 }
250 }
251 return success;
252 }
253
SetState(int which,int state)254 bool Menu::SetState(int which, int state) {
255 bool success = false;
256 int i = 0;
257 if(which > (int)choices || which < 1) {
258 } else {
259 if(state == HIGHLIGHTED) {
260 for(i = 0; i < (int)choices; i++) {
261 if(states[i] == HIGHLIGHTED) {
262 states[i] = NORMAL;
263 }
264 }
265 }
266 states[which - 1] = state;
267 success = true;
268 }
269 return success;
270 }
271
GetState(int which)272 int Menu::GetState(int which) {
273 if(which > (int)choices || which < 1) {
274 //printf("invalid choice GetState\n");
275 return DISABLED;
276 } else {
277 return states[which - 1];
278 }
279 }
280
MoveCursor(int direction)281 bool Menu::MoveCursor(int direction) {
282 int i;
283 unsigned int oldcurrent = current;
284 switch(direction) {
285 case NORTH:
286 for(i = current; i > 0; i--) {
287 if(GetState(i - 1) != DISABLED) {
288 current = i - 1;
289 break;
290 }
291 }
292 if(oldcurrent == current) {
293 for(i = choices + 1; i > (int)oldcurrent; i--) {
294 if(GetState(i - 1) != DISABLED) {
295 current = i - 1;
296 break;
297 }
298 }
299 }
300 break;
301 case SOUTH:
302 for(i = current; i <= (int)choices; i++) {
303 if(GetState(i+1) != DISABLED) {
304 current = i + 1;
305 break;
306 }
307 }
308 if(oldcurrent == current) {
309 for(i = 0; i < (int)oldcurrent; i++) {
310 if(GetState(i + 1) != DISABLED) {
311 current = i + 1;
312 break;
313 }
314 }
315 }
316 break;
317 default:
318 break;
319 }
320 return current != oldcurrent;
321 }
322
GetChoice()323 int Menu::GetChoice() {
324 return current;
325 }
326
SetChoice(int newchoice)327 void Menu::SetChoice(int newchoice) {
328 current = newchoice;
329 return;
330 }
331
NumChoices()332 int Menu::NumChoices() {
333 return choices;
334 }
335
SetPos(int newx,int newy)336 void Menu::SetPos(int newx, int newy) {
337 x = newx;
338 y = newy;
339 return;
340 }
341
CalcArea()342 void Menu::CalcArea() {
343 int halves=0;
344 int i;
345
346 boxesw=boxesh=0;
347 for(i=0; i<(int)strlen(content); i++) {
348 if(content[i]=='\n') {
349 boxesh++;
350 if(boxesw<(halves/2)) {
351 boxesw=halves/2;
352 if(halves%2==0) {
353 boxesw--;
354 }
355 }
356 halves=0;
357 } else {
358 halves++;
359 }
360 }
361 if(boxesw<(halves/2)) {
362 boxesw=halves/2;
363 if(halves%2==0) {
364 boxesw--;
365 }
366 }
367 return;
368 }
369
Draw(SDL_Surface * surf)370 void Menu::Draw(SDL_Surface* surf) {
371 SDL_Rect srcrect;
372 int i;
373 int j;
374 int mode;
375 int line = 0;
376 int letterx = x;
377 int lettery = y;
378 if(active) {
379 mode = NORMAL;
380 } else {
381 mode = DISABLED;
382 }
383 if(strlen(content) > 0) {
384 //draw the background
385 srcrect.w = srcrect.h = MENUTILE;
386 for(i = 0; i <= boxesw + 1; i++) {
387 for(j = 0; j <= boxesh + 1; j++) {
388 if(i == 0) {
389 srcrect.x = 0;
390 } else if(i == boxesw + 1) {
391 srcrect.x = MENUTILE * 2;
392 } else {
393 srcrect.x = MENUTILE;
394 }
395 if(j == 0) {
396 srcrect.y = 0;
397 } else if(j == boxesh + 1) {
398 srcrect.y = MENUTILE * 2;
399 } else {
400 srcrect.y = MENUTILE;
401 }
402 destrect.x = x - (MENUTILE / 2) + (i * MENUTILE);
403 destrect.y = y - (MENUTILE / 2) + (j * MENUTILE);
404 if(SDL_BlitSurface(menubits, &srcrect, surf, &destrect)) {
405 LoadGraphics();
406 SDL_BlitSurface(menubits, &srcrect, surf, &destrect);
407 }
408 }
409 }
410 //draw each letter
411 mode = active ? states[0] : DISABLED;
412 srcrect.w = TEXTWIDTH;
413 srcrect.h = TEXTHEIGHT;
414 for(i = 0; i < (int)strlen(content); i++) {
415 if(content[i] == '\n') {
416 letterx = x;
417 lettery += TEXTHEIGHT;
418 line++;
419 if((int)choices > line) {
420 mode = active ? states[line] : DISABLED;
421 }
422 } else {
423 srcrect.x = ((int)content[i] % 32) * TEXTWIDTH;
424 if(content[i] < '@') {
425 srcrect.y = 0 + mode;
426 } else if(content[i] < '`') {
427 srcrect.y = TEXTHEIGHT + mode;
428 } else {
429 srcrect.y = (TEXTHEIGHT * 2) + mode;
430 }
431 destrect.x = letterx;
432 destrect.y = lettery;
433 if(SDL_BlitSurface(textbits, &srcrect, surf, &destrect)) {
434 LoadGraphics();
435 SDL_BlitSurface(textbits, &srcrect, surf, &destrect);
436 }
437 letterx += TEXTWIDTH;
438 }
439 }
440 if(active) {
441 //draw the pointer finger thingy
442 srcrect.x = 0;
443 srcrect.y = MENUTILE * 3;
444 srcrect.w = MENUTILE;
445 srcrect.h = MENUTILE / 2;
446 destrect.x = x - MENUTILE;
447 destrect.y = y + (MENUTILE * 2 / 5) + (TEXTHEIGHT * (current-1));
448 if(SDL_BlitSurface(menubits, &srcrect, surf, &destrect)) {
449 LoadGraphics();
450 SDL_BlitSurface(menubits, &srcrect, surf, &destrect);
451 }
452 }
453 } else {
454 //draw a blank menu if the menu is, erm, blank.
455 srcrect.x = srcrect.y = 0;
456 srcrect.w = srcrect.h = MENUTILE * 3;
457 destrect.x = x - (MENUTILE / 2);
458 destrect.y = y - (MENUTILE / 2);
459 if(SDL_BlitSurface(menubits, &srcrect, surf, &destrect)) {
460 LoadGraphics();
461 SDL_BlitSurface(menubits, &srcrect, surf, &destrect);
462 }
463 }
464 return;
465 }
466