/* @(#)tkeys.c 17.1.1.1 (ES0-DMD) 01/25/02 17:40:12 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .IDENTIFICATION tkeys.c .AUTHOR Francois Ochsenbein [ESO-IPG] .LANGUAGE C .KEYWORDS Window Management .ENVIRONMENT TermWindows .COMMENTS This module contains simple application of TermWindows: \begin{TeX} \begin{itemize} \item {\em ta\_yes} which creates a ``yes/no'' window, and prompts for this simple answer. \item {\em ta\_dummy} which creates a ``dummy'' window of $1\times 1$ \end{itemize} \end{TeX} .VERSION 3.0 20-Jun-1988: Creation ----------------------------------------------------------------------------*/ #define DEBUG 0 /* For debugging only */ #define PM_LEVEL LEVEL_TW-1 #include #include #include #include typedef struct { /* Defines Map Keys / Fcts / Help */ short keys[2]; int (*action)(); int name; /* Offset in nam_buf */ } SYMBOL; static struct MAP_KEYS { BUFFER sym_buf ; /* Collects Symbols */ BUFFER nam_buf ; /* Collects Names */ } keys_head = { BUF_Init(SYMBOL, 32), BUF_Init(char, 128) }; #define asym (&keys_head.sym_buf) #define anam (&keys_head.nam_buf) static SYMBOL *find(); static SYMBOL *cfind(); /*========================================================================== * tk_open *==========================================================================*/ int tk_open() /*+++ .PURPOSE Initialise .RETURNS OK .REMARKS Does nothing ... ---*/ { ENTER("*tk_open"); EXIT(OK); } /*========================================================================== * tk_add *==========================================================================*/ int tk_add(key1, key2, action, name) /*+++ .PURPOSE Add a new key .RETURNS OK (key added or replaced) / NOK (error) .REMARKS ---*/ short key1; /* IN: First Key */ short key2; /* IN: 2nd Key */ int (*action)(); /* IN: ACtion to execute */ char *name; /* IN: Name of action */ { SYMBOL *ps; int status; ENTER("tk_add"); if_not (ps = find(key1, key2)) /* A new */ { ps = BUF_AllocateItem(asym, SYMBOL); } if (ps) { ps->keys[0] = key1; ps->keys[1] = key2; if(ps->keys[0] == 0) ps->keys[0] = ps->keys[1], ps->keys[1] = 0; ps->action = action; ps->name = anam->used; BUF_SaveString(anam, name); status = OK; } else status = NOK; EXIT(status); } /*========================================================================== * tk_find *==========================================================================*/ char *tk_find(key1, key2) /*+++ .PURPOSE Find a key's name .RETURNS The associated name. .REMARKS ---*/ short key1; /* IN: First Key */ short key2; /* IN: 2nd Key */ { SYMBOL *ps; char *p; ENTER("*tk_find"); if (ps = find(key1, key2)) { p = anam->buf + ps->name; TRACE(p); } else p = NULL_PTR(char); EXITp(p); } /*========================================================================== * tk_check *==========================================================================*/ int tk_check(key1) /*+++ .PURPOSE Find if a key exists / requires a second one .RETURNS 0 (unknown) / 1 (exists) / 2 (a second key is required) .REMARKS ---*/ short key1; /* IN: First Key */ { SYMBOL *ps; int status; ENTER("tk_check"); if (ps = find(key1, -1)) status = (ps->keys[1] ? 2 : 1); else status = 0; EXIT(status); } /*========================================================================== * tk_cexec *==========================================================================*/ int tk_cexec(action_name) /*+++ .PURPOSE Execute Action .RETURNS The status of Action / -1 if not found .REMARKS ---*/ char *action_name; /* IN: Action to execute */ { SYMBOL *ps; int status; ENTER("tk_cexec"); if (ps = cfind(action_name)) { status = (*(ps->action))(anam->buf + ps->name); } else status = -1; EXIT(status); } /*========================================================================== * tk_exec *==========================================================================*/ int tk_exec(key1, key2) /*+++ .PURPOSE Execute Action .RETURNS The status of Action / NOK if not found .REMARKS ---*/ short key1; /* IN: First Key */ short key2; /* IN: 2nd Key */ { SYMBOL *ps; int status; ENTER("tk_exec"); if (ps = find(key1, key2)) { status = (*(ps->action))(anam->buf + ps->name); } else ERROR("Key has no definition"), status = NOK; EXIT(status); } /*========================================================================== * find *==========================================================================*/ static SYMBOL *find(key1, key2) /*+++ .PURPOSE Find a key's name .RETURNS The associated name. .REMARKS ---*/ short key1; /* IN: First Key */ short key2; /* IN: 2nd Key */ { SYMBOL *ps; short keys[2]; int i; keys[0] = key1, keys[1] = key2; if(keys[0] == 0) keys[0] = keys[1], keys[1] = 0; for (i = SET_Items(asym, SYMBOL), ps = SET_FirstItem(asym, SYMBOL); --i >= 0; ps++) { if (keys[0] == ps->keys[0]) if (keys[1] == ps->keys[1]) break; else if (keys[1] == -1) break; /* First Keys */ } if (i < 0) ps = NULL_PTR(SYMBOL); /* Not Found */ return(ps); } /*========================================================================== * cfind *==========================================================================*/ static SYMBOL *cfind(action_name) /*+++ .PURPOSE Find an action .RETURNS The associated symbol -- NULL if ambiguous .REMARKS ---*/ char *action_name; /* IN: Name of the Action */ { SYMBOL *ps, *matching_symbol; int i, m; char *p; matching_symbol = (SYMBOL *)0; for (i = SET_Items(asym, SYMBOL), ps = SET_FirstItem(asym, SYMBOL); --i >= 0; ps++) { p = anam->buf + ps->name; m = stumatch(action_name, p); if (action_name[m] == EOS) /* Found ... */ { if (p[m] == EOS) return(ps); if (matching_symbol && (ps->action != matching_symbol->action)) return(NULL_PTR(SYMBOL)); matching_symbol = ps; } } return(matching_symbol); } #if DEBUG /*========================================================================== * Test Program *==========================================================================*/ #include #include #include #include #include static char *edkey(key) short key; /* IN: The Key */ { static char ed_key[4]; int i; ed_key[0] = ' ', ed_key[1] = ' ', ed_key[2] = ' '; switch(key>>8) { case _PF_: ed_key[0] = 'P', ed_key[1] = 'F', ed_key[2] = '0' + (key&0x7f); break; case _KEYPAD_: ed_key[0] = 'k', ed_key[1] = 'p'; ed_key[2] = (key&0x7f); break; case _ARROW_: ed_key[0] = 'A'; switch(key&0xf) { case _UP_: ed_key[1] = 'u'; break; case _DOWN_: ed_key[1] = 'd'; break; case _LEFT_: ed_key[1] = 'l'; break; case _RIGHT_: ed_key[1] = 'r'; break; default: ed_key[1] = 'h'; break; } break; case _FK_: ed_key[0] = 'F', i = key&0xff; if (i < 10) ed_key[1] = '0' + i; else ed_key[1] = '0' + i/10, ed_key[2] = '0' + i%10; break; default: ed_key[0] = key; if (iscntrl(ed_key[0])) { if (ed_key[0] > ' ') ed_key[0] &= 077; ed_key[1] = '@' | ed_key[0]; ed_key[0] = '^'; } } return(ed_key); } int list_keys() { static WINDOW *list_window = NULL_WINDOW; SYMBOL *ps; int i; char *edkey(); char ch; if_not(list_window) list_window = OpenWindow("ListKeys", 0,0, 0,0, _REVERSE_, 0, 0); ClearWindow(list_window); for (i = SET_Items(asym, SYMBOL), ps = SET_FirstItem(asym, SYMBOL); --i >= 0; ps++) { if (ps->keys[1]) Put(list_window, edkey(ps->keys[0])), Put(list_window, edkey(ps->keys[1])); else Put(list_window, " "), Put(list_window, edkey(ps->keys[0])); Puts(list_window, anam->buf + ps->name); } RaiseWindow(list_window); GetKey(list_window, &ch); RemoveWindow(list_window); } int find_key() { static WINDOW *list_window = NULL_WINDOW; SYMBOL *ps; char buffer[80]; if_not(list_window) list_window = OpenWindow("FindKeys", -1,0, 1,0, _REVERSE_, 0, 5); ClearWindow(list_window); RaiseWindow(list_window), ActiveWindow(list_window); Gets(list_window, buffer, sizeof(buffer)); if (ps = cfind(buffer)) Put(list_window, " ==> "), Put(list_window, anam->buf + ps->name); else Put(list_window, " ??? "), Bell(); GetKey(list_window, buffer); RemoveWindow(list_window); } int def_key() { static WINDOW *get_window = NULL_WINDOW; short keys[2]; int i, key_group; char *edkey(); char ch; char text[200]; int standard_action(); if_not(get_window) { get_window = OpenWindow("GetKeys", -3,0, 3,0, _REVERSE_, _BORDER_|_BORDER2_, 9); EnableKeypad(get_window); SetStopping(get_window, _FK_, "*"); SetStopping(get_window, _ARROW_, "*"); } ClearWindow(get_window); RaiseWindow(get_window); ActiveWindow(get_window); Put(get_window, "Number of keys (0/1/2): "); for (ch = ' ';(ch < '0') || (ch > '2') ; ) GetKey(get_window, &ch) ; keys[0] = 0; ClearWindow(get_window); Put(get_window, "Enter the "); Write(get_window, &ch, 1); Put(get_window, " keys: "); switch(ch) { case '0': goto FIN; case '2': key_group = GetKey(get_window, &ch); if (key_group < 0) goto FIN; keys[0] = key_group<<8 | ch; case '1': key_group = GetKey(get_window, &ch); if (key_group < 0) goto FIN; keys[1] = key_group<<8 | ch; } ClearWindow(get_window); Put(get_window, "Text for "); if (keys[0]) Put(get_window, edkey(keys[0])), Put(get_window, " "); Put(get_window, edkey(keys[1])); Put(get_window, ": "); SetAttr(get_window, _REVERSE_); Gets(get_window, text, sizeof(text)); SetAttr(get_window, _NORMAL_); tk_add(keys[0], keys[1], standard_action, text); FIN: RemoveWindow(get_window); return(OK); } static WINDOW *w; standard_action(text) char *text; { Put(w, text); TouchWindow(w); return(OK); } PGM(test) { char ch; int key_group; /* int def_keys(), list_keys(); */ short key1, key2; InitWindows((char *)0, (char *)0, TW_cc_VMS); DefineControl('D', 0); DefineControl('L', 0); DefineControl('F', 0); w = OpenWindow("Main", 0,0, 0,0, _NORMAL_, _SCROLL_, 0); SetStopping(w, _STANDARD_, "DLF") ; SetStopping(w, _ARROW_, "*") ; SetStopping(w, _FK_, "*") ; EnableKeypad(w); RaiseWindow(w); DeactiveWindow(w); Puts(w, "Use ^D to define new keys, ^L to list keys, ^F to find keys"); tk_add(Control_('D'), 0, def_key, "Define New Key"); tk_add(Control_('L'), 0, list_keys, "List Known Keys"); tk_add(Control_('F'), 0, find_key , "Find a Key"); while(1) { TouchWindow(w); key_group = GetKey(w, &ch); if (key_group == _EOF_) break; if (key_group == _STANDARD_) { if ((ch == '\r') || (ch == '\0')) { NewLine(w); continue; } key_group = 0; } key1 = key_group<<8 | ch; key2 = 0; switch(tk_check(key1)) { case 0: /* Doesn't map to an action */ if(key_group) Bell(); /* Keypad */ else Write(w, &ch, 1); continue; case 2: key_group = GetKey(w, &ch); if (key_group == _EOF_) key_group = 0; key2 = key_group<<8 | ch; case 1: tk_exec(key1, key2); } } EndWindows() ; } #endif