1 // This may look like C code, but it is really -*- C++ -*-
2
3 // ------------------------------------------------------------------
4 // The Goldware Library
5 // Copyright (C) 1990-1999 Odinn Sorensen
6 // ------------------------------------------------------------------
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public
18 // License along with this program; if not, write to the Free
19 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 // MA 02111-1307, USA
21 // ------------------------------------------------------------------
22 // $Id: gkbdgetm.cpp,v 1.1 2011/02/18 19:46:01 stas_degteff Exp $
23 // ------------------------------------------------------------------
24 // GCUI: Golded+ Character-oriented User Interface.
25 // Keyboard functions.
26 // ------------------------------------------------------------------
27
28 #include <gkbdcode.h>
29 #include <gkbdbase.h>
30 #include <gmemdbg.h>
31 #include <gwinall.h>
32 #include <gutlmtsk.h>
33 #ifdef GOLD_MOUSE
34 #include <gmoubase.h>
35 #endif
36
37
38 // ------------------------------------------------------------------
39 // Event sources
40
41 const int GEVT_KEYBOARD = 0;
42 const int GEVT_BUFFER = 1;
43 const int GEVT_MOUSE = 2;
44 const int GEVT_TICK = 3;
45
46
47 // ------------------------------------------------------------------
48
gkbdtickpressreset()49 void gkbdtickpressreset() {
50
51 gkbd.tickpress = gclock();
52 }
53
54
55 // ------------------------------------------------------------------
56
gkbdtickvaluereset()57 void gkbdtickvaluereset() {
58
59 gkbd.tickvalue = gclock();
60 }
61
62
63 // ------------------------------------------------------------------
64
kbmhit()65 gkey kbmhit() {
66
67 gkey k;
68
69 // Check for keypress in internal buffer or keyboard
70 if(gkbd.kbuf) {
71 gkbd.source = GEVT_BUFFER;
72 k = gkbd.kbuf->xch;
73 }
74 else {
75 gkbd.source = GEVT_KEYBOARD;
76 k = kbxhit();
77 }
78
79 return k;
80 }
81
82
83 // ------------------------------------------------------------------
84
kbd_call_func(VfvCP func)85 static void kbd_call_func(VfvCP func) {
86
87 int row, col;
88 bool hidden = vcurhidden();
89 vposget(&row,&col);
90 _menu_t* menu = gwin.cmenu;
91 (*func)();
92 gwin.cmenu = menu;
93 vposset(row,col);
94 if(hidden)
95 vcurhide();
96 else
97 vcurshow();
98 }
99
100
101 // ------------------------------------------------------------------
102
find_hotkey(_menu_t * wmenu,gkey xch)103 static _item_t* find_hotkey(_menu_t* wmenu, gkey xch) {
104
105 _item_t* witem;
106 _item_t* item;
107
108 // do while more items in this menu
109 for(witem=wmenu->item; witem!=NULL; witem=witem->prev) {
110
111 // if hot key matches keypress, return its item address
112 if(witem->hotkey==xch and (!(witem->fmask&M_NOSEL)) and witem->select!=NULL)
113 return witem;
114
115 // if current item has a child menu, process it
116 if(witem->child!=NULL) {
117 item = find_hotkey((_menu_t*)witem->child, xch);
118 if(item!=NULL)
119 return item;
120 }
121 }
122
123 // return address of item found
124 return witem;
125 }
126
127
128 // ------------------------------------------------------------------
129
makeextkey(gkey xshift,gkey & xkey)130 static void makeextkey(gkey xshift, gkey& xkey) {
131
132 switch(xkey) {
133 case Key_Home:
134 case Key_C_Home:
135 if(xshift & ALT)
136 xkey = Key_A_HomeG;
137 if(xshift & (LSHIFT | RSHIFT))
138 KCodScn(xkey) |= 0x80;
139 break;
140
141 case Key_End:
142 case Key_C_End:
143 if(xshift & ALT)
144 xkey = Key_A_EndG;
145 if(xshift & (LSHIFT | RSHIFT))
146 KCodScn(xkey) |= 0x80;
147 break;
148
149 case Key_Up:
150 if(xshift & ALT)
151 xkey = Key_A_UpG;
152 else if(xshift & GCTRL)
153 xkey = Key_C_Up;
154 if(xshift & (LSHIFT | RSHIFT))
155 KCodScn(xkey) |= 0x80;
156 break;
157
158 case Key_Dwn:
159 if(xshift & ALT)
160 xkey = Key_A_DwnG;
161 else if(xshift & GCTRL)
162 xkey = Key_C_Dwn;
163 if(xshift & (LSHIFT | RSHIFT))
164 KCodScn(xkey) |= 0x80;
165 break;
166
167 case Key_Lft:
168 if(xshift & ALT)
169 xkey = Key_A_LftG;
170 if(xshift & (LSHIFT | RSHIFT))
171 KCodScn(xkey) |= 0x80;
172 break;
173
174 case Key_Rgt:
175 if(xshift & ALT)
176 xkey = Key_A_RgtG;
177 if(xshift & (LSHIFT | RSHIFT))
178 KCodScn(xkey) |= 0x80;
179 break;
180
181 case Key_PgUp:
182 if(xshift & ALT)
183 xkey = Key_A_PgUpG;
184 if(xshift & (LSHIFT | RSHIFT))
185 KCodScn(xkey) |= 0x80;
186 break;
187
188 case Key_PgDn:
189 if(xshift & ALT)
190 xkey = Key_A_PgDnG;
191 if(xshift & (LSHIFT | RSHIFT))
192 KCodScn(xkey) |= 0x80;
193 break;
194
195 case Key_Ins:
196 if(xshift & ALT)
197 xkey = Key_A_InsG;
198 else if(xshift & GCTRL)
199 xkey = Key_C_Ins;
200 if(xshift & (LSHIFT | RSHIFT))
201 KCodScn(xkey) |= 0x80;
202 break;
203
204 case Key_Del:
205 if(xshift & ALT)
206 xkey = Key_A_DelG;
207 else if(xshift & GCTRL)
208 xkey = Key_C_Del;
209 if(xshift & (LSHIFT | RSHIFT))
210 KCodScn(xkey) |= 0x80;
211 break;
212 }
213 }
214
215
216 // ------------------------------------------------------------------
217
218 extern int blanked;
219
getxch(int __tick)220 gkey getxch(int __tick) {
221
222 gkey k;
223
224 while(1) {
225
226 // Keyboard polling loop
227 if(gkbd.polling) {
228 while(not kbmhit()) {
229 Clock thistick = gclock();
230 long tickdiff = thistick - gkbd.tickvalue;
231 if(tickdiff < 0) {
232 gkbd.tickvalue = thistick;
233 tickdiff = gkbd.tickinterval + 1;
234 }
235 if(tickdiff >= gkbd.tickinterval) {
236 gkbd.tickvalue = thistick;
237 if(gkbd.tickfunc) {
238 gkbd.inidle = true;
239 (*gkbd.tickfunc)();
240 gkbd.inidle = false;
241 }
242 if(__tick)
243 kbput(Key_Tick);
244 }
245 if(gmtsk.detected)
246 gmtsk.timeslice();
247 }
248 }
249
250 // Get key from internal buffer or keyboard
251 if(gkbd.kbuf) {
252 gkbd.source = GEVT_BUFFER;
253 k = gkbd.kbuf->xch;
254 KBuf* _kbuf = gkbd.kbuf->next;
255 throw_free(gkbd.kbuf);
256 gkbd.kbuf = _kbuf;
257 if(gkbd.kbuf)
258 gkbd.kbuf->prev = NULL;
259 }
260 else {
261 gkbd.source = GEVT_KEYBOARD;
262 k = kbxget();
263 gkey s = kbxget(2); // Read shift status
264 if(not gkbd.extkbd) {
265 if(s & (LSHIFT|RSHIFT|GCTRL|ALT))
266 makeextkey(s,k);
267 }
268 }
269
270 // Note time of keypress unless it's a tick
271 if(k != Key_Tick)
272 gkbdtickpressreset();
273
274 // Search through onkey linked list for a
275 // matching defined onkey. If one is found,
276 // then save the current environment, call the
277 // onkey's function, and restore the environment.
278
279 if(not blanked) {
280 KBnd* _onkey = gkbd.onkey;
281 while(_onkey) {
282 if(_onkey->keycode == k) {
283 gkbd.curronkey = _onkey;
284 kbd_call_func(_onkey->func);
285 #ifdef GOLD_MOUSE
286 if(gkbd.inmenu and gmou.FreeCursor())
287 return 0;
288 #endif
289 break;
290 }
291 _onkey = _onkey->prev;
292 }
293 if(_onkey) {
294 if(not _onkey->pass or (_onkey->pass >= 0xFE00))
295 k = 0;
296 else
297 k = _onkey->pass;
298 }
299 else {
300
301 // Search for a menu hot key. If one is found,
302 // then save the current environment, call the
303 // hotkey's function, and restore the environment.
304
305 if(gwin.menu) {
306 _item_t* item = find_hotkey(gwin.menu,k);
307 if(item) {
308 gwin.menu->hotkey = true;
309 kbd_call_func(item->select);
310 #ifdef GOLD_MOUSE
311 if(gkbd.inmenu and gmou.FreeCursor())
312 return 0;
313 #endif
314 k = 0;
315 }
316 }
317 }
318 }
319
320 // If we still have a keycode, exit the loop
321 if(k)
322 break;
323 }
324
325 // Return keycode
326 return k;
327 }
328
329
330 // ------------------------------------------------------------------
331