This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gcui/gkbdgetm.cpp

331 lines
7.8 KiB
C++

// This may look like C code, but it is really -*- C++ -*-
// ------------------------------------------------------------------
// The Goldware Library
// Copyright (C) 1990-1999 Odinn Sorensen
// ------------------------------------------------------------------
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307, USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// GCUI: Golded+ Character-oriented User Interface.
// Keyboard functions.
// ------------------------------------------------------------------
#include <gkbdcode.h>
#include <gkbdbase.h>
#include <gmemdbg.h>
#include <gwinall.h>
#include <gutlmtsk.h>
#ifdef GOLD_MOUSE
#include <gmoubase.h>
#endif
// ------------------------------------------------------------------
// Event sources
const int GEVT_KEYBOARD = 0;
const int GEVT_BUFFER = 1;
const int GEVT_MOUSE = 2;
const int GEVT_TICK = 3;
// ------------------------------------------------------------------
void gkbdtickpressreset() {
gkbd.tickpress = gclock();
}
// ------------------------------------------------------------------
void gkbdtickvaluereset() {
gkbd.tickvalue = gclock();
}
// ------------------------------------------------------------------
gkey kbmhit() {
gkey k;
// Check for keypress in internal buffer or keyboard
if(gkbd.kbuf) {
gkbd.source = GEVT_BUFFER;
k = gkbd.kbuf->xch;
}
else {
gkbd.source = GEVT_KEYBOARD;
k = kbxhit();
}
return k;
}
// ------------------------------------------------------------------
static void kbd_call_func(VfvCP func) {
int row, col;
bool hidden = vcurhidden();
vposget(&row,&col);
_menu_t* menu = gwin.cmenu;
(*func)();
gwin.cmenu = menu;
vposset(row,col);
if(hidden)
vcurhide();
else
vcurshow();
}
// ------------------------------------------------------------------
static _item_t* find_hotkey(_menu_t* wmenu, gkey xch) {
_item_t* witem;
_item_t* item;
// do while more items in this menu
for(witem=wmenu->item; witem!=NULL; witem=witem->prev) {
// if hot key matches keypress, return its item address
if(witem->hotkey==xch and (!(witem->fmask&M_NOSEL)) and witem->select!=NULL)
return witem;
// if current item has a child menu, process it
if(witem->child!=NULL) {
item = find_hotkey((_menu_t*)witem->child, xch);
if(item!=NULL)
return item;
}
}
// return address of item found
return witem;
}
// ------------------------------------------------------------------
static void makeextkey(gkey xshift, gkey& xkey) {
switch(xkey) {
case Key_Home:
case Key_C_Home:
if(xshift & ALT)
xkey = Key_A_HomeG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_End:
case Key_C_End:
if(xshift & ALT)
xkey = Key_A_EndG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Up:
if(xshift & ALT)
xkey = Key_A_UpG;
else if(xshift & GCTRL)
xkey = Key_C_Up;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Dwn:
if(xshift & ALT)
xkey = Key_A_DwnG;
else if(xshift & GCTRL)
xkey = Key_C_Dwn;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Lft:
if(xshift & ALT)
xkey = Key_A_LftG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Rgt:
if(xshift & ALT)
xkey = Key_A_RgtG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_PgUp:
if(xshift & ALT)
xkey = Key_A_PgUpG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_PgDn:
if(xshift & ALT)
xkey = Key_A_PgDnG;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Ins:
if(xshift & ALT)
xkey = Key_A_InsG;
else if(xshift & GCTRL)
xkey = Key_C_Ins;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
case Key_Del:
if(xshift & ALT)
xkey = Key_A_DelG;
else if(xshift & GCTRL)
xkey = Key_C_Del;
if(xshift & (LSHIFT | RSHIFT))
KCodScn(xkey) |= 0x80;
break;
}
}
// ------------------------------------------------------------------
extern int blanked;
gkey getxch(int __tick) {
gkey k;
while(1) {
// Keyboard polling loop
if(gkbd.polling) {
while(not kbmhit()) {
Clock thistick = gclock();
long tickdiff = thistick - gkbd.tickvalue;
if(tickdiff < 0) {
gkbd.tickvalue = thistick;
tickdiff = gkbd.tickinterval + 1;
}
if(tickdiff >= gkbd.tickinterval) {
gkbd.tickvalue = thistick;
if(gkbd.tickfunc) {
gkbd.inidle = true;
(*gkbd.tickfunc)();
gkbd.inidle = false;
}
if(__tick)
kbput(Key_Tick);
}
if(gmtsk.detected)
gmtsk.timeslice();
}
}
// Get key from internal buffer or keyboard
if(gkbd.kbuf) {
gkbd.source = GEVT_BUFFER;
k = gkbd.kbuf->xch;
KBuf* _kbuf = gkbd.kbuf->next;
throw_free(gkbd.kbuf);
gkbd.kbuf = _kbuf;
if(gkbd.kbuf)
gkbd.kbuf->prev = NULL;
}
else {
gkbd.source = GEVT_KEYBOARD;
k = kbxget();
gkey s = kbxget(2); // Read shift status
if(not gkbd.extkbd) {
if(s & (LSHIFT|RSHIFT|GCTRL|ALT))
makeextkey(s,k);
}
}
// Note time of keypress unless it's a tick
if(k != Key_Tick)
gkbdtickpressreset();
// Search through onkey linked list for a
// matching defined onkey. If one is found,
// then save the current environment, call the
// onkey's function, and restore the environment.
if(not blanked) {
KBnd* _onkey = gkbd.onkey;
while(_onkey) {
if(_onkey->keycode == k) {
gkbd.curronkey = _onkey;
kbd_call_func(_onkey->func);
#ifdef GOLD_MOUSE
if(gkbd.inmenu and gmou.FreeCursor())
return 0;
#endif
break;
}
_onkey = _onkey->prev;
}
if(_onkey) {
if(not _onkey->pass or (_onkey->pass >= 0xFE00))
k = 0;
else
k = _onkey->pass;
}
else {
// Search for a menu hot key. If one is found,
// then save the current environment, call the
// hotkey's function, and restore the environment.
if(gwin.menu) {
_item_t* item = find_hotkey(gwin.menu,k);
if(item) {
gwin.menu->hotkey = true;
kbd_call_func(item->select);
#ifdef GOLD_MOUSE
if(gkbd.inmenu and gmou.FreeCursor())
return 0;
#endif
k = 0;
}
}
}
}
// If we still have a keycode, exit the loop
if(k)
break;
}
// Return keycode
return k;
}
// ------------------------------------------------------------------