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