1 /** EMULib Emulation Library *********************************/
2 /** **/
3 /** Touch.c **/
4 /** **/
5 /** This file contains functions that simulate joystick and **/
6 /** dialpad with the touch screen. It is normally used from **/
7 /** the platform-dependent functions that know where to get **/
8 /** pen coordinates from and where to draw pen cues to. **/
9 /** **/
10 /** Copyright (C) Marat Fayzullin 2008-2009 **/
11 /** You are not allowed to distribute this software **/
12 /** commercially. Please, notify me, if you make any **/
13 /** changes to this file. **/
14 /*************************************************************/
15 #if !defined(BPP32) && !defined(BPP24) && !defined(BPP16) && !defined(BPP8)
16 #include "TouchMux.h"
17 #else
18
19 #include "EMULib.h"
20 #include "Console.h"
21 #include "Touch.h"
22 #include <string.h>
23
24 #define CLR_NORMALF PIXEL(0,0,0) /* Normal key foreground */
25 #define CLR_NORMALB PIXEL(255,255,255) /* Normal key background */
26 #define CLR_ACTIVEF PIXEL(255,255,255) /* Active key foreground */
27 #define CLR_ACTIVEB PIXEL(255,64,64) /* Active key background */
28
29 #ifndef DEFINE_ONCE
30 #define DEFINE_ONCE
31
32 /* Currently selected virtual keyboard key */
33 static int KBDXPos = 0;
34 static int KBDYPos = 0;
35
36 /* Horizontal offsets of virtual keyboard lines */
37 static const int KBDOffsets[YKEYS] = { 0,0,4,-4,8,4 };
38
39 /* Characters printed on virtual keyboard keys */
40 static const unsigned char *KBDLines[YKEYS+1] =
41 {
42 "\33\20\21\22\23\24\25\26\27\16\17\10",
43 "1234567890-=",
44 "\11QWERTYUIOP",
45 "^ASDFGHJKL;\15",
46 "ZXCVBNM,./",
47 "[] \\'",
48 0
49 };
50
51 /* Characters returned from virtual keyboard */
52 static unsigned char KBDKeys[YKEYS][XKEYS] =
53 {
54 {
55 0x1B,CON_F1,CON_F2,CON_F3,CON_F4,CON_F5,
56 CON_F6,CON_F7,CON_F8,CON_INSERT,CON_DELETE,CON_BS
57 },
58 { '1','2','3','4','5','6','7','8','9','0','-','=' },
59 { CON_TAB,'Q','W','E','R','T','Y','U','I','O','P',0 },
60 { '^','A','S','D','F','G','H','J','K','L',';',CON_ENTER },
61 { 'Z','X','C','V','B','N','M',',','.','/',0,0 },
62 { '[',']',' ',' ',' ',' ',' ','\\','\'',0,0,0 }
63 };
64
65 /** GenericPenJoystick() *************************************/
66 /** Get simulated joystick buttons from touch screen UI. **/
67 /** Result compatible with GetJoystick(). **/
68 /*************************************************************/
GenericPenJoystick(int X,int Y,int W,int H)69 unsigned int GenericPenJoystick(int X,int Y,int W,int H)
70 {
71 unsigned int J;
72
73 /* Simulate joystick when pen touches the screen at X,Y */
74 J = 0;
75
76 /* Don't accept touches outside of the window frame */
77 if((X<0)||(Y<0)||(X>=W)||(Y>=H)) return(0);
78 W/= 3;
79
80 /* Top 1/16 of the widget: FIREL and FIRER */
81 if(Y<(H>>4))
82 { if(X<W) J|=BTN_FIREL; else if(X>=(W<<1)) J|=BTN_FIRER; }
83
84 /* Bottom 1/16 of the widget: SELECT/EXIT and START */
85 if(!J&&(Y>=(H-(H>>4))))
86 { if(X<W) J|=BTN_SELECT|BTN_EXIT; else if(X>=(W<<1)) J|=BTN_START; }
87
88 /* Right 1/3 of the screen is the fire buttons */
89 if(!J&&(X>=(W<<1)))
90 {
91 /* Fire buttons overlap */
92 if(Y<=(H>>1)+(H>>4)) J|=BTN_FIREB;
93 if(Y>=(H>>1)-(H>>4)) J|=BTN_FIREA;
94 }
95
96 /* Left 1/3 of the screen is the directional pad */
97 if(!J&&(X<W))
98 {
99 H/=3;
100 W/=3;
101 if(X<W) J|=BTN_LEFT; else if(X>=(W<<1)) J|=BTN_RIGHT;
102 if(Y<H) J|=BTN_UP; else if(Y>=(H<<1)) J|=BTN_DOWN;
103 }
104
105 /* Done, return simulated "joystick" state */
106 return(J);
107 }
108
109 /** GenericPenDialpad() **************************************/
110 /** Get simulated dialpad buttons from touch screen UI. **/
111 /*************************************************************/
GenericPenDialpad(int X,int Y,int W,int H)112 unsigned char GenericPenDialpad(int X,int Y,int W,int H)
113 {
114 /* Dialpad is the middle 1/3 of the screen */
115 W /= 3;
116 return(
117 (Y>=0)&&(Y<H)&&(X>=W)&&(X<(W<<1))?
118 3*(X-W)/W+3*(Y/(H>>2)) : 0
119 );
120 }
121
122 /** GenericPenKeyboard() *************************************/
123 /** Get virtual on-screen keyboard buttons. **/
124 /*************************************************************/
GenericPenKeyboard(int X,int Y,int W,int H)125 unsigned char GenericPenKeyboard(int X,int Y,int W,int H)
126 {
127 int J;
128
129 /* Pen coordinates relative to keyboard's top left corner */
130 X -= W-KEYSTEP*XKEYS-8;
131 Y -= H-KEYSTEP*YKEYS-8;
132
133 /* Pen must be inside the keyboard */
134 if((X<0)||(Y<0)) return(0);
135
136 /* Keyboard row index */
137 Y/= KEYSTEP;
138 if(Y>=YKEYS) return(0);
139
140 /* Adjust for row position on screen */
141 for(J=0;J<Y;++J) X-=KBDOffsets[J];
142 if(X<0) return(0);
143
144 /* Keyboard column index */
145 X/= KEYSTEP;
146 if(X>=XKEYS) return(0);
147
148 /* Memorize last pressed key */
149 KBDXPos = X;
150 KBDYPos = Y;
151
152 /* Return key */
153 return(KBDKeys[Y][X]);
154 }
155
156 /** GenericDialKeyboard() ************************************/
157 /** Process dialpad input to the virtual keyboard. Returns **/
158 /** virtual keyboard key if selected, or 0 if not. **/
159 /*************************************************************/
GenericDialKeyboard(unsigned char Key)160 unsigned char GenericDialKeyboard(unsigned char Key)
161 {
162 /* Interpret input key */
163 switch(Key)
164 {
165 case CON_LEFT:
166 KBDXPos = (KBDXPos>0? KBDXPos:strlen(KBDLines[KBDYPos]))-1;
167 break;
168 case CON_RIGHT:
169 KBDXPos = KBDXPos<strlen(KBDLines[KBDYPos])-1? KBDXPos+1:0;
170 break;
171 case CON_UP:
172 KBDYPos = KBDYPos>0? KBDYPos-1:YKEYS-1;
173 KBDXPos = KBDXPos<strlen(KBDLines[KBDYPos])? KBDXPos:strlen(KBDLines[KBDYPos])-1;
174 break;
175 case CON_DOWN:
176 KBDYPos = KBDYPos<YKEYS-1? KBDYPos+1:0;
177 KBDXPos = KBDXPos<strlen(KBDLines[KBDYPos])? KBDXPos:strlen(KBDLines[KBDYPos])-1;
178 break;
179 case CON_OK:
180 /* Return ASCII character */
181 return(KBDLines[KBDYPos][KBDXPos]);
182 }
183
184 /* Key has not been interpreted */
185 return(0);
186 }
187
188 #endif /* DEFINE_ONCE */
189
190 /** DrawVLine()/DrawHLine() **********************************/
191 /** Draw dotted lines used to show cues for PenJoystick(). **/
192 /*************************************************************/
DrawVLine(Image * Img,int X,int Y1,int Y2,pixel Color)193 static void DrawVLine(Image *Img,int X,int Y1,int Y2,pixel Color)
194 {
195 pixel *P;
196 int J;
197
198 if(Y1>Y2) { J=Y1;Y1=Y2;Y2=J; }
199 P = (pixel *)Img->Data+Img->L*Y1+X;
200 for(J=Y1;J<=Y2;J+=4) { *P=Color;P+=Img->L<<2; }
201 }
202
DrawHLine(Image * Img,int X1,int X2,int Y,pixel Color)203 static void DrawHLine(Image *Img,int X1,int X2,int Y,pixel Color)
204 {
205 pixel *P;
206 int J;
207
208 if(X1>X2) { J=X1;X1=X2;X2=J; }
209 P = (pixel *)Img->Data+Img->L*Y+X1;
210 for(J=X1;J<=X2;J+=4) { *P=Color;P+=4; }
211 }
212
213 /** DrawPenCues() ********************************************/
214 /** Overlay dotted cue lines for using PenJoystick() onto a **/
215 /** given image. Show dialpad cues if requested. **/
216 /*************************************************************/
DrawPenCues(Image * Img,int ShowDialpad,pixel Color)217 void DrawPenCues(Image *Img,int ShowDialpad,pixel Color)
218 {
219 pixel *P;
220 int W,H,W9,W3,H3;
221
222 P = (pixel *)Img->Data;
223 W = Img->W;
224 H = Img->H;
225 W9 = W/9;
226 W3 = W/3;
227 H3 = H/3;
228
229 /* Vertical edges */
230 DrawVLine(Img,W3,0,H-1,Color);
231 DrawVLine(Img,W-W3,0,H-1,Color);
232
233 /* Corner buttons */
234 DrawHLine(Img,0,W3,H>>4,Color);
235 DrawHLine(Img,W-W3,W-1,H>>4,Color);
236 DrawHLine(Img,0,W3,H-(H>>4),Color);
237 DrawHLine(Img,W-W3,W-1,H-(H>>4),Color);
238
239 /* Fire buttons (with overlap) */
240 DrawHLine(Img,W-W3,W-1,(H>>1)-(H>>4),Color);
241 DrawHLine(Img,W-W3,W-1,(H>>1)+(H>>4),Color);
242
243 /* Directional buttons */
244 DrawVLine(Img,W9,H>>4,H-(H>>4),Color);
245 DrawVLine(Img,W3-W9,H>>4,H-(H>>4),Color);
246 DrawHLine(Img,0,W3,H3,Color);
247 DrawHLine(Img,0,W3,H-H3,Color);
248
249 /* Button labels */
250 PrintXY(Img,"L",2,2,Color,-1);
251 PrintXY(Img,"R",W-W3+2,2,Color,-1);
252 PrintXY(Img,"B",W-W3+2,(H>>4)+2,Color,-1);
253 PrintXY(Img,"A+B",W-W3+2,(H>>1)-(H>>4)+2,Color,-1);
254 PrintXY(Img,"A",W-W3+2,(H>>1)+(H>>4)+2,Color,-1);
255 PrintXY(Img,"SELECT",2,H-(H>>4)+2,Color,-1);
256 PrintXY(Img,"START",W-W3+2,H-(H>>4)+2,Color,-1);
257
258 /* If requested, show on-screen dialpad */
259 if(ShowDialpad)
260 {
261 DrawHLine(Img,W3,W-W3,H>>2,Color);
262 DrawHLine(Img,W3,W-W3,H>>1,Color);
263 DrawHLine(Img,W3,W-W3,H-(H>>2),Color);
264 DrawVLine(Img,W3+W9,0,H-1,Color);
265 DrawVLine(Img,W-W3-W9,0,H-1,Color);
266 PrintXY(Img,"1",W3+2,2,Color,-1);
267 PrintXY(Img,"2",W3+W9+2,2,Color,-1);
268 PrintXY(Img,"3",W-W3-W9+2,2,Color,-1);
269 PrintXY(Img,"4",W3+2,(H>>2)+2,Color,-1);
270 PrintXY(Img,"5",W3+W9+2,(H>>2)+2,Color,-1);
271 PrintXY(Img,"6",W-W3-W9+2,(H>>2)+2,Color,-1);
272 PrintXY(Img,"7",W3+2,(H>>1)+2,Color,-1);
273 PrintXY(Img,"8",W3+W9+2,(H>>1)+2,Color,-1);
274 PrintXY(Img,"9",W-W3-W9+2,(H>>1)+2,Color,-1);
275 PrintXY(Img,"*",W3+2,H-(H>>2)+2,Color,-1);
276 PrintXY(Img,"0",W3+W9+2,H-(H>>2)+2,Color,-1);
277 PrintXY(Img,"#",W-W3-W9+2,H-(H>>2)+2,Color,-1);
278 }
279 }
280
281 /** DrawKeyboard() *******************************************/
282 /** Draw virtual keyboard in a given image. Key modifiers **/
283 /** and the key code passed in CurKey are highlighted. **/
284 /*************************************************************/
DrawKeyboard(Image * Img,unsigned int CurKey)285 void DrawKeyboard(Image *Img,unsigned int CurKey)
286 {
287 unsigned int X,Y,J,I,K,L;
288 char S[2];
289 pixel *P;
290
291 /* Keyboard in the right-bottom corner by default */
292 X=Img->W-KEYSTEP*XKEYS-8;
293 Y=Img->H-KEYSTEP*YKEYS-8;
294
295 /* Draw modifiers */
296 if(CurKey&CON_MODES)
297 {
298 J=X;
299 if(CurKey&CON_SHIFT) { PrintXY(Img,"SHIFT",J,Y-8,CLR_ACTIVEB,-1);J+=48; }
300 if(CurKey&CON_CONTROL) { PrintXY(Img,"CTRL",J,Y-8,CLR_ACTIVEB,-1);J+=40; }
301 if(CurKey&CON_ALT) { PrintXY(Img,"ALT",J,Y-8,CLR_ACTIVEB,-1);J+=32; }
302 }
303
304 /* Draw keys */
305 for(I=J=0,S[1]='\0';KBDLines[I];++I,Y+=KEYSTEP,X+=KBDOffsets[I]-J*KEYSTEP)
306 for(J=0;KBDLines[I][J];++J,X+=KEYSTEP)
307 {
308 /* Draw key frame */
309 P = (pixel *)Img->Data
310 + Img->L*(Y+(KEYSTEP-KEYSIZE)/2)
311 + X+(KEYSTEP-KEYSIZE)/2;
312
313 /* Highlight current key */
314 if(KBDKeys[I][J]==(CurKey&CON_KEYCODE))
315 {
316 for(K=1;K<KEYSIZE-1;++K) P[K]=CLR_ACTIVEB;
317 for(K=1,P+=Img->L;K<KEYSIZE-1;++K,P+=Img->L)
318 for(L=0;L<KEYSIZE;++L) P[L]=CLR_ACTIVEB;
319 for(K=1;K<KEYSIZE-1;++K) P[K]=CLR_ACTIVEB;
320 K=CLR_ACTIVEF;
321 }
322 else
323 {
324 for(K=1;K<KEYSIZE-1;++K) P[K]=CLR_NORMALF;
325 for(K=1,P+=Img->L;K<KEYSIZE-1;++K,P+=Img->L)
326 {
327 for(L=1;L<KEYSIZE-1;++L) P[L]=CLR_NORMALB;
328 P[0]=P[KEYSIZE-1]=CLR_NORMALF;
329 }
330 for(K=1;K<KEYSIZE-1;++K) P[K]=CLR_NORMALF;
331 K=CLR_NORMALF;
332 }
333
334 /* Draw key label */
335 S[0]=KBDLines[I][J];
336 PrintXY(Img,S,X+(KEYSTEP-8)/2,Y+(KEYSTEP-8)/2,K,-1);
337 }
338 }
339
340 #undef CLR_NORMALF
341 #undef CLR_NORMALB
342 #undef CLR_ACTIVEF
343 #undef CLR_ACTIVEB
344
345 #endif /* BPP32||BPP24||BPP16||BPP8 */
346