1 /***************************************************************************
2                           menuitem.cpp  -  description
3                              -------------------
4     begin                : Tue Feb 29 2000
5     copyright            : (C) 2000 by Michael Speck
6     email                :
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "menuitem.h"
19 #include <string.h>
20 #include <stdlib.h>
21 
22 extern Sdl sdl;
23 extern DrawRgn dr_src, dr_dst;
24 
MenuItem()25 MenuItem::MenuItem() //separator
26 {
27 	type = ET_SEPARATOR;
28 	strcpy(name, " ");
29 	Enlight(0);
30 	alpha = 255;
31 	used = 0;
32 }
33 
MenuItem(char * n)34 MenuItem::MenuItem(char *n) //separator
35 {
36 	type = ET_SEPARATOR;
37 	strcpy(name, n);
38 	Enlight(0);
39 	alpha = 255;
40 	used = 0;
41 }
42 
MenuItem(char * n,int * p,char * cap1,char * cap2)43 MenuItem::MenuItem(char *n, int *p, char *cap1, char *cap2) //switch group
44 {
45 	type = ET_SWITCHGRP;
46 	strcpy(name, n);
47 
48 	sw_cap = new char*[2];
49 	sw_cap[0] = cap1;
50 	sw_cap[1] = cap2;
51 	sw_cap_num = 2;
52 
53 	Enlight(0);
54 	pos = p;
55 	alpha = 255;
56 	min = 0;
57 	max = 1;
58 	step = 1;
59 	used = 0;
60 }
61 
MenuItem(char * n,int * p,char ** caps,int num)62 MenuItem::MenuItem(char *n, int *p, char **caps, int num) //switch group
63 {
64 	type = ET_SWITCHGRP;
65 	strcpy(name, n);
66 
67 	sw_cap = new char*[num];
68 	for (int i = 0; i < num; i++)
69 	    sw_cap[i] = caps[i];
70 	sw_cap_num = num;
71 
72 	Enlight(0);
73 	pos = p;
74 	alpha = 255;
75 	min = 0;
76 	max = num-1;
77 	step = 1;
78 	used = 0;
79 }
80 
MenuItem(char * n,int * p,int min,int max,int s)81 MenuItem::MenuItem(char *n, int *p, int min, int max, int s) //range
82 {
83 	type = ET_RANGE;
84 	strcpy(name, n);
85 	Enlight(0);
86 	pos = p;
87 	alpha = 255;
88 	step = s;
89 	MenuItem::min = min;
90 	MenuItem::max = max;
91 	used = 0;
92 }
93 
MenuItem(char * n,int * p,char * k)94 MenuItem::MenuItem(char *n, int *p, char *k) //restr_keys
95 {
96 	type = ET_KEY;
97 	strcpy(name, n);
98 	Enlight(0);
99 	pos = p;
100 	alpha = 255;
101 	used = 0;
102 }
103 
MenuItem(char * n,int a_id)104 MenuItem::MenuItem(char *n, int a_id) //action
105 {
106 	type = ET_ACTION;
107 	strcpy(name, n);
108 	Enlight(0);
109 	alpha = 255;
110 	action = a_id;
111 	used = 0;
112 }
113 
MenuItem(char * n,Menu * m)114 MenuItem::MenuItem(char *n, Menu* m) //submenu
115 {
116 	type = ET_SUBMENU;
117 	strcpy(name, n);
118 	submenu = m;
119 	Enlight(0);
120 	alpha = 255;
121 	used = 0;
122 }
123 
MenuItem(char * n,char * p,int m)124 MenuItem::MenuItem(char *n, char *p, int m) //string
125 {
126 	type = ET_STRING;
127 	strcpy(name, n);
128 	Enlight(0);
129 	alpha = 255;
130 	max = m;
131 	pos = (int*)p;
132 	min = strlen((char*)p);
133 	used = 0;
134 }
135 
~MenuItem()136 MenuItem::~MenuItem()
137 {
138     if (type == ET_SWITCHGRP)
139         delete sw_cap;
140 }
141 
SetXY(int x,int y)142 void MenuItem::SetXY(int x, int y)
143 {
144 	MenuItem::x = x;
145 	MenuItem::y = y;
146 }
147 
SetBackgnd(SDL_Surface * backgnd)148 void MenuItem::SetBackgnd(SDL_Surface *backgnd)
149 {
150 	MenuItem::backgnd = backgnd;
151 }
152 
SetSubmenu(Menu * m)153 void MenuItem::SetSubmenu(Menu* m)
154 {
155 }
156 
SetFont(SFnt * fnt,SFnt * enlgt_fnt)157 void MenuItem::SetFont(SFnt *fnt, SFnt *enlgt_fnt)
158 {
159 	font = fnt;
160 	enlgt_font = enlgt_fnt;
161 }
162 
ComputeStr()163 void MenuItem::ComputeStr()
164 {
165 	switch (type) {
166 		case ET_STRING:
167 			sprintf(string, "%s: %s", name, (char*)pos);
168 			break;
169 		case ET_SWITCHGRP:
170 			sprintf(string, "%s %s", name, sw_cap[*pos]);
171 			break;
172 		case ET_RANGE:
173 			sprintf(string, "%s %i", name, *pos);
174 			break;
175 		case ET_KEY:
176 			if (*pos > 32 && *pos < 127)
177 				sprintf(string, "%s: '%c'", name, (char)*pos);
178 			else
179 				if (*pos == 0)
180 					sprintf(string, "%s: ???", name);
181 				else
182 					switch (*pos){
183 						case SDLK_UP:
184 							sprintf(string, "%s: Up", name);
185 							break;
186 						case SDLK_DOWN:
187 							sprintf(string, "%s: Down", name);
188 							break;
189 						case SDLK_LEFT:
190 							sprintf(string, "%s: Left", name);
191 							break;
192 						case SDLK_RIGHT:
193 							sprintf(string, "%s: Right", name);
194 							break;
195 						case SDLK_SPACE:
196 							sprintf(string, "%s: Space", name);
197 							break;
198 						default:
199 							sprintf(string, "%s: %i", name, *pos);
200 					}
201 			break;
202 		default:
203 			strcpy(string, name);
204 			break;
205 	}
206 	ComputeSize();
207 }
208 
Enlight(int t)209 void MenuItem::Enlight(int t)
210 {
211 	if (t) {
212 		if (!enlighted)
213 			changed = 1;
214 		else
215 			changed = 0;
216 		enlighted = 1;
217 		alpha = 0;
218 	}
219 	else {
220 		if (enlighted)
221 			changed = 1;
222 		else
223 			changed = 0;
224 		enlighted = 0;
225 	}
226 }
227 
Type()228 int MenuItem::Type()
229 {
230 	return type;
231 }
232 
KeyEvent(int code)233 int MenuItem::KeyEvent(int code)
234 {
235 	if (type == ET_SWITCHGRP || type == ET_RANGE) {
236 		int val = *pos;
237 		switch (code) {
238 			case SDLK_LEFT:
239 				val -= step;
240 				if (val < min)
241 			        val = max - ((max - min) % step);
242             	used = 1;
243 				break;
244 			case SDLK_RIGHT:
245 				val += step;
246 				if (val > max) val = min;
247             	used = 1;
248 				break;
249 		}
250 		if (val != *pos) {
251 			*pos = val;
252 			StrUpdate();
253 		}
254 		return MR_CONTINUE;
255 	}
256 	else
257 		if (type == ET_KEY && code == SDLK_RETURN){
258 			*pos = 0;
259 			StrUpdate();
260 		}
261 	return MR_CONTINUE;
262 }
263 
SetKey(int code)264 void MenuItem::SetKey(int code)
265 {
266 	if (*pos == 0) {
267 		*pos = code;
268 		StrUpdate();
269 	}
270 }
271 
Update()272 void MenuItem::Update()
273 {
274 	if (!changed) return;
275 	//redraw in buffer
276 	if (enlighted) {
277 		if (alpha > 0) {
278 		    SFnt_Write(font, sdl.scr, x, y, string, 0);
279 		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, alpha);
280 		}
281 		else
282 		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, 0);
283 	}
284 	else {
285 	    SFnt_Write(font, sdl.scr, x, y, string, 0);
286 		if (alpha < 255)
287 		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, alpha);
288 	}
289 	changed = 0;
290 }
291 
SetChanged(int c)292 void MenuItem::SetChanged(int c)
293 {
294 	changed = c;
295 }
296 
Hide()297 void MenuItem::Hide()
298 {
299 	if (dw != -1) {
300 	    DR_SETDST(sdl.scr, dx, dy, dw, dh);
301 	    DR_SETSRC(backgnd, dx, dy);
302 		SSur_Blit();
303     }
304 }
305 
Refresh()306 void MenuItem::Refresh()
307 {
308 	SDL_UpdateRect(sdl.scr, dx, dy, dw, dh);
309 }
310 
ComputeSize()311 void MenuItem::ComputeSize()
312 {
313 	dw = SFnt_TextWidth(font, string);
314 	dh = font->lh;
315 	dx = x - (dw >> 1);
316 	dy = y - (dh >> 1);
317 }
318 
Compute()319 void MenuItem::Compute()
320 {
321 	if (alpha < 255  && !enlighted) {
322 		alpha += 3;
323 		changed = 1;
324 	}
325 	else
326 		if (alpha >= 5 && enlighted) {
327 			alpha -= 3;
328 			changed = 1;
329 		}
330 }
331 
Submenu()332 Menu* MenuItem::Submenu()
333 {
334 	return submenu;
335 }
336 
ActionId()337 int MenuItem::ActionId()
338 {
339 	return action;
340 }
341 
ClearAlpha()342 void MenuItem::ClearAlpha()
343 {
344 	alpha = 255;
345 }
346 
Pos()347 int MenuItem::Pos()
348 {
349 	return *pos;
350 }
351 
StrUpdate()352 void MenuItem::StrUpdate()
353 {
354 	int x_old = dx;
355 	int y_old = dy;
356 	int w_old = dw;
357 	int h_old = dh;
358 	Hide();
359 	ComputeStr();
360 	changed = 1;
361 	Update();
362 	x_old = (dx < x_old) ? dx : x_old;
363 	y_old = (dy < y_old) ? dy : y_old;
364 	w_old = (dw > w_old) ? dw : w_old;
365 	h_old = (dh > h_old) ? dh : h_old;
366 	SDL_UpdateRect(sdl.scr, x_old, y_old, w_old, h_old);
367 }
368 
EditStr(int code,int unicode)369 void MenuItem::EditStr(int code, int unicode)
370 {
371 	if (code == SDLK_BACKSPACE && min > 0) {
372 		//clear last char
373 		((char*)pos)[--min] = 0;
374 		StrUpdate();
375 	}
376 	else
377 		if (code >= 32 && code < 128 && min < max) {
378 			//letter
379 			((char*)pos)[min++] = unicode;
380 			StrUpdate();
381 		}
382 }
383 
SetRestrKeys(char * rk)384 void MenuItem::SetRestrKeys(char *rk)
385 {
386 	restr_keys = rk;
387 }
388 
NoBackgnd()389 void MenuItem::NoBackgnd()
390 {
391 	dw = -1;
392 }
393 
OnItem(int mx,int my)394 int MenuItem::OnItem(int mx, int my)
395 {
396     return (mx >= dx && mx < dx + dw && my >= dy && my <dy + dh);
397 }
398 
ButtonEvent(SDL_MouseButtonEvent button)399 int MenuItem::ButtonEvent(SDL_MouseButtonEvent button)
400 {
401     if (type == ET_KEY) {
402         *pos = 0;
403         StrUpdate();
404         return MR_CONTINUE;
405     }
406     int val = *pos;
407     if (button.button == 3) {
408 		val -= step;
409     	if (val < min)
410    	        val = max - ((max - min) % step);
411    	    used = 1;
412 	}
413 	else
414 	    if (button.button == 1) {
415 			val += step;
416 			if (val > max) val = min;
417        	    used = 1;
418 		}
419 	if (val != *pos) {
420 		*pos = val;
421 		StrUpdate();
422 	}
423 	return MR_CONTINUE;
424 }
425 
SetString(char * s,int rep)426 void MenuItem::SetString(char *s, int rep)
427 {
428     strcpy(name, s);
429     changed = 1;
430     if (rep)
431         StrUpdate();
432     else
433         ComputeStr();
434 }
435 
SetRange(int ll,int ul,int st,int rep)436 void MenuItem::SetRange(int ll, int ul, int st, int rep)
437 {
438     min = ll;
439     max = ul;
440     step = st;
441     if (*pos > ul)
442         *pos = ll;
443     changed = 1;
444     if (rep)
445         StrUpdate();
446 }
447 
Used()448 int MenuItem::Used()
449 {
450     int ret = used;
451     used = 0;
452     return ret;
453 }
454 
SetUsed(int u)455 void MenuItem::SetUsed(int u)
456 {
457     used = u;
458 }
459