root/trunk/txlib/txwutil.c

Revision 14, 70.5 kB (checked in by jvw, 2 years ago)

HEX/ASCII (sector) editor control added

Line 
1//
2//                     TxWin, Textmode Windowing Library
3//
4//   Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk
5//
6// ==========================================================================
7//
8// This file contains Original Code and/or Modifications of Original Code as
9// defined in and that are subject to the GNU Lesser General Public License.
10// You may not use this file except in compliance with the License.
11// BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE.
12// A copy of the License is provided with the Original Code and Modifications,
13// and is also available at http://www.dfsee.com/txwin/lgpl.htm
14//
15// This library is free software; you can redistribute it and/or modify
16// it under the terms of the GNU Lesser General Public License as published
17// by the Free Software Foundation; either version 2.1 of the License,
18// or (at your option) any later version.
19//
20// This library is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23// See the GNU Lesser General Public License for more details.
24//
25// You should have received a copy of the GNU Lesser General Public License
26// along with this library; (lgpl.htm) if not, write to the Free Software
27// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28//
29// Questions on TxWin licensing can be directed to: txwin@fsys.nl
30//
31// ==========================================================================
32//
33// TX Windowed text utility functions
34//
35// Author: J. van Wijk
36//
37// JvW  01-09-2001 Added Begin/EndEnumWindows and GetNextWindow
38// JvW  02-01-2000 Fixed qsort callback bug in history sort (DOS 16bit only)
39// JvW  31-12-1999 Updated current-position after find existing cmd in history
40// JvW  10-07-1998 Initial version
41
42#include <txlib.h>                              // public interface
43#include <txwpriv.h>                            // private interface
44
45#include <time.h>                               // time functions
46
47
48#define TXWE_SIGNATURE   0xFEEDBEEF             // valid magic signature value
49
50typedef struct txwe_element                     // window enumeration element
51{
52   ULONG               signature;               // signature value
53   TXWINBASE          *parent;                  // parent window for enum
54   TXWINBASE          *nextstart;               // start for next search
55} TXWE_ELEMENT;                                 // end of struct "txa_element"
56
57
58
59// Compare History order for descending sort
60static int txwHistoryDescend
61(
62   const void         *h1,
63   const void         *h2
64);
65
66// Compare History order for ascending sort
67static int txwHistoryAscend
68(
69   const void         *h1,
70   const void         *h2
71);
72
73static char         ascii[32];
74
75
76/*****************************************************************************/
77// Validate window-handle and return corresponding TXWBASE pointer
78/*****************************************************************************/
79TXWINBASE *txwValidateHandle                    // RET   window base pointer
80(
81   TXWHANDLE           hwnd,                    // IN    handle to validate
82   TXWINDOW          **win                      // OUT   attached window
83)
84{
85   TXWINBASE          *wnd = NULL;
86   TXWINBASE          *chk = NULL;
87
88   switch (hwnd)
89   {
90      case TXHWND_NULL:                         // invalid by definition
91         break;
92
93      case TXHWND_DESKTOP:
94      case TXHWND_BOTTOM:
95         wnd = txwa->desktop;
96         break;
97
98      case TXHWND_TOP:
99         wnd = txwa->last;
100         break;
101
102      case TXHWND_OBJECT:                       // not supported yet
103         break;
104
105      default:
106         for (chk = txwa->desktop; chk != NULL; chk = chk->next)
107         {
108            if ((TXWHANDLE) chk == hwnd)
109            {
110               wnd = chk;                       // found valid wnd for hwnd
111               break;
112            }
113         }
114         break;
115   }
116   if (win != NULL)                             // window pointer requested
117   {
118      if (wnd != NULL)                          // valid window base
119      {
120         if ((*win = wnd->window) == NULL)      // no attached window, invalid
121         {
122            wnd = NULL;
123         }
124      }
125      else                                      // make returned window invalid
126      {
127         *win = NULL;
128      }
129   }
130   return( wnd);
131}                                               // end 'txwValidateHandle'
132/*---------------------------------------------------------------------------*/
133
134
135/*****************************************************************************/
136// Validate handle and calculate clip rectangle from all (parent) client areas
137/*****************************************************************************/
138TXWINBASE *txwValidateAndClip                   // RET   window base pointer
139(
140   TXWHANDLE           hwnd,                    // IN    handle to validate
141   TXWINDOW          **window,                  // OUT   attached window
142   BOOL                border,                  // IN    start clip with border
143   TXRECT             *pclip                    // OUT   combined clip rect
144)
145{
146   TXWINBASE          *wnd;
147   TXWINDOW           *win;
148   TXRECT              clip;                    // parent Clip rectangle
149
150
151   if ((wnd = txwValidateHandle( hwnd, window)) != NULL)
152   {
153      TXWINBASE       *ancestor = wnd->parent;  // first ancestor level
154
155      //- to be refined, use IsWindowVisible() and return empty clip rectangle ?
156      //- to be refined, or  IsWindowShowing()  ?
157
158      if (border)                               // clip including border area ?
159      {
160         clip = (border) ? wnd->window->border : wnd->window->client;
161         if (wnd->window->style & TXWS_CAST_SHADOW)
162         {
163            clip.bottom += 1;                   // adjust for a shadow area
164            clip.right  += 2;                   // below and at right side
165         }
166      }
167      else                                      // use plain client area
168      {
169         clip = wnd->window->client;
170      }
171      while (txwValidateHandle((TXWHANDLE) ancestor, &win) != NULL)
172      {
173         txwIntersectRect( &clip, &win->client, &clip);
174         ancestor = ancestor->parent;           // next ancestor level
175      }
176
177      //- finally, clip to whole screen, to avoid line-wrapping :-)
178      txwIntersectRect( &clip, &txwa->screen, &clip);
179      *pclip = clip;
180   }
181   return( wnd);
182}                                               // end 'txwValidateAndClip'
183/*---------------------------------------------------------------------------*/
184
185
186/*****************************************************************************/
187// Start enumeration of child windows
188/*****************************************************************************/
189TXWHENUM txwBeginEnumWindows
190(
191   TXWHANDLE           parent                   // IN    Parent window handle
192)
193{
194   TXWE_ELEMENT       *rc = NULL;               // function return
195   TXWINBASE          *wnd;
196
197   ENTER();
198
199   if ((wnd = txwValidateHandle( parent, NULL)) != NULL)
200   {
201      if ((rc = TxAlloc( 1, sizeof(TXWE_ELEMENT))) != NULL)
202      {
203         rc->signature = TXWE_SIGNATURE;
204         rc->parent    = wnd;
205         rc->nextstart = txwa->last;            // highest Z-order window
206      }
207   }
208   RETURN ((TXWHENUM) rc);
209}                                               // end 'txwBeginEnumWindows'
210/*---------------------------------------------------------------------------*/
211
212/*****************************************************************************/
213// End an enumeration of child-windows (free resources)
214/*****************************************************************************/
215BOOL txwEndEnumWindows
216(
217   TXWHENUM            henum                    // IN    Enumeration handle
218)
219{
220   BOOL                rc = FALSE;              // function return
221   TXWE_ELEMENT       *el = (TXWE_ELEMENT *) henum;
222
223   ENTER();
224
225   if ((el) && (el->signature == TXWE_SIGNATURE))
226   {
227      el->signature = 0;                        // make memory content invalid
228      TxFreeMem( el);
229      rc = TRUE;
230   }
231   BRETURN (rc);
232}                                               // end 'txwEndEnumWindows'
233/*---------------------------------------------------------------------------*/
234
235
236/*****************************************************************************/
237// Retrieve next child's handle in enumeration
238/*****************************************************************************/
239TXWHANDLE txwGetNextWindow
240(
241   TXWHENUM            henum                    // IN    Enumeration handle
242)
243{
244   TXWHANDLE           rc = 0;                  // function return
245   TXWE_ELEMENT       *el = (TXWE_ELEMENT *) henum;
246   TXWINBASE          *wnd;
247
248   ENTER();
249
250   if ((el) && (el->signature == TXWE_SIGNATURE))
251   {
252      for (wnd = el->nextstart; rc == 0; wnd = wnd->prev)
253      {
254         if (wnd == NULL)                       // at lowest Z-order
255         {
256            el->nextstart = txwa->last;         // prepare wrap-arround
257            break;                              // and stop the search
258         }
259         else if (wnd == el->parent)
260         {
261            continue;                           // skip parent itself
262         }
263         else if (txwIsChild( (TXWHANDLE) wnd, (TXWHANDLE) el->parent))
264         {
265            rc = (TXWHANDLE) wnd;               // result found
266            el->nextstart = wnd->prev;          // next itteration
267            break;                              // and stop the search
268         }
269      }
270   }
271   RETURN (rc);
272}                                               // end 'txwGetNextWindow'
273/*---------------------------------------------------------------------------*/
274
275
276/*****************************************************************************/
277// Determine if window is a direct descendant of parent (or parent itself)
278/*****************************************************************************/
279BOOL txwIsChild                                 // RET   window is a child
280(
281   TXWHANDLE           hwnd,                    // IN    window to test
282   TXWHANDLE           parent                   // IN    Parent window handle
283)
284{
285   TXWINBASE          *wnd = txwValidateHandle( hwnd,   NULL);
286   TXWINBASE          *par = txwValidateHandle( parent, NULL);
287
288   if ((wnd != par) && (txwValidateHandle((TXWHANDLE) wnd, NULL) != NULL))
289   {
290      wnd = wnd->parent;                        // next ancestor level
291   }
292   return((wnd == par));
293}                                               // end 'txwIsChild'
294/*---------------------------------------------------------------------------*/
295
296
297/*****************************************************************************/
298// Determine if window is a descendant of given parent  (or parent itself)
299/*****************************************************************************/
300BOOL txwIsDescendant                            // RET   window is descendant
301(
302   TXWHANDLE           hwnd,                    // IN    window to test
303   TXWHANDLE           parent                   // IN    Parent window handle
304)
305{
306   TXWINBASE          *wnd = txwValidateHandle( hwnd,   NULL);
307   TXWINBASE          *par = txwValidateHandle( parent, NULL);
308
309   while ((wnd != par) && (txwValidateHandle((TXWHANDLE) wnd, NULL) != NULL))
310   {
311      wnd = wnd->parent;                        // next ancestor level
312   }
313   return((wnd == par));
314}                                               // end 'txwIsDescendant'
315/*---------------------------------------------------------------------------*/
316
317
318/*****************************************************************************/
319// Determine if either this window OR a parent is currently MINIMIZED
320/*****************************************************************************/
321BOOL txwIsMinimized                             // RET   window is descendant
322(
323   TXWHANDLE           hwnd,                    // IN    window to test
324   BOOL                parent                   // IN    check parents only
325)                                               //       or check THIS only
326{
327   BOOL                rc = FALSE;
328   TXWINBASE          *wnd = txwValidateHandle( hwnd,   NULL);
329
330   ENTER();
331
332   if (wnd)
333   {
334      if (parent == FALSE)                      // check only THIS window
335      {
336         rc = ((wnd->us[TXQWS_FLAGS] & TXFF_MINIMIZED) != 0);
337      }
338      else
339      {
340         for ( wnd = txwValidateHandle((TXWHANDLE) wnd->parent, NULL);
341              (wnd) && (rc == FALSE);
342               wnd = txwValidateHandle((TXWHANDLE) wnd->parent, NULL))
343         {
344            rc = ((wnd->us[TXQWS_FLAGS] & TXFF_MINIMIZED) != 0);
345         }
346      }
347   }
348   BRETURN( rc);
349}                                               // end 'txwIsMinimized'
350/*---------------------------------------------------------------------------*/
351
352
353/*****************************************************************************/
354// Reset all AutoRadioButtons in a group to the 'unset' condition
355/*****************************************************************************/
356void txwResetAutoRadioGroup
357(
358   TXWHANDLE           hwnd,                    // IN    dialog handle or 0
359   USHORT              group                    // IN    Group ID or 0
360)
361{
362   TXWHENUM      henum;
363   TXWHANDLE     child;
364   TXWINDOW     *cwin;
365
366   ENTER();
367   TRACES(( "dialog:%8.8lx  group-nr: %hu\n", hwnd, group));
368
369   if ((henum = txwBeginEnumWindows( hwnd)) != 0)
370   {
371      while ((child = txwGetNextWindow( henum)) != 0)
372      {
373         cwin = txwWindowData( child);
374
375         if (cwin->class == TXW_BUTTON)
376         {
377            TXWINBASE *wnd = (TXWINBASE *) child;
378
379            TRACES(( "Button %8.8lx: group:%hu '%s'\n",
380                      child, wnd->us[TXQWS_GROUP], cwin->bu.text));
381
382            if ((cwin->style & TXBS_PRIMARYSTYLES) == TXBS_AUTORADIO)
383            {
384               TRACES(("AutoRadio: %s\n", (*(cwin->bu.checked)) ? "ON" : "OFF"));
385               if ((*(cwin->bu.checked)) &&     // only reset the set one(s)
386                   (wnd->us[TXQWS_GROUP] == group))
387               {
388                  TRACES(( "Reset autoradio button %8.8lx: '%s'\n",
389                                                   child, cwin->bu.text));
390                  *(cwin->bu.checked) = FALSE;
391                  txwInvalidateWindow( child, FALSE, FALSE);
392               }
393            }
394         }
395      }
396      txwEndEnumWindows( henum);
397   }
398   VRETURN();
399}                                               // end 'txwResetAutoRadioGroup'
400/*---------------------------------------------------------------------------*/
401
402
403/*****************************************************************************/
404// Determine if keyvalue is a possible ACCELERATOR key
405/*****************************************************************************/
406BOOL txwIsAccelCandidate                        // RET   key could be ACCEL
407(
408   ULONG               key                      // IN    key value
409)
410{
411   BOOL                rc = TRUE;               // function return
412
413   ENTER();
414
415   if (((key <  0x0ff) && (key > TXc_Z) &&
416        (key != '<')   && (key != '>'))   ||
417       ((key <  0x1b0) && (key > 0x18a))  ||
418        (key == TXs_TAB)                  ||
419        (key == TXk_BACKSPACE)            ||
420        (key == TXk_TAB      )            ||
421        (key == TXc_ENTER    )            ||
422        (key == TXk_ENTER    )            ||
423        (key == TXa_BACKQUOTE)            ||
424        (key == TXa_SLASH)                ||
425        (key == TXc_PGUP)                 ||
426        (key == TXk_F11)                  ||    // History popup
427        (key == TXk_F12)                  ||
428        (key == TXa_F5)                   ||
429        (key == TXa_F8)                   ||
430        (key == TXa_F9)                   ||
431        (key == TXa_F10)                  ||
432        (key == TXc_D)                    ||    // History delete
433        (key == TXc_E)                    ||    // Clear to end of line
434        (key == TXc_K)                    ||    // History add
435        (key == TXc_L)                    ||    // Refresh screen (Linux)
436        (key == TXc_R)                    ||    // Refresh screen
437       ((key >= 0x147) && (key <= 0x153)) ||
438       ((key >= 0x173) && (key <= 0x177))
439      )
440   {
441      rc = FALSE;
442   }
443   BRETURN (rc);
444}                                               // end 'txwIsAccelCandidate'
445/*---------------------------------------------------------------------------*/
446
447
448/*****************************************************************************/
449// Return short description for msg-id
450/*****************************************************************************/
451char *txwMsgDescription
452(
453   ULONG               msg                      // IN    message-id
454)
455{
456   switch (msg)
457   {
458      case TXWM_CREATE:        return( "WM_CREATE");
459      case TXWM_DESTROY:       return( "WM_DESTROY");
460      case TXWM_CHAR:          return( "WM_CHAR");
461      case TXWM_COMMAND:       return( "WM_COMMAND");
462      case TXWM_CLOSE:         return( "WM_CLOSE");
463      case TXWM_QUIT:          return( "WM_QUIT");
464      case TXWM_HELP:          return( "WM_HELP");
465      case TXWM_BORDER:        return( "WM_BORDER");
466      case TXWM_STATUS:        return( "WM_STATUS");
467      case TXWM_PAINT:         return( "WM_PAINT");
468      case TXWM_SETFOCUS:      return( "WM_SETFOCUS");
469      case TXWM_ENABLE:        return( "WM_ENABLE");
470      case TXWM_SHOW:          return( "WM_SHOW");
471      case TXWM_ACTIVATE:      return( "WM_ACTIVATE");
472      case TXWM_SELECTED:      return( "WM_SELECTED");
473      case TXWM_CURSORVISIBLE: return( "WM_CURSORVIS");
474      case TXWM_MOVE:          return( "WM_MOVE");
475      case TXWM_SIZE:          return( "WM_SIZE");
476      case TXWM_CONTROL:       return( "WM_CONTROL");
477      case TXWM_INITDLG:       return( "WM_INITDLG");
478      case TXWM_MENUSELECT:    return( "WM_MENUSELECT");
479      case TXWM_MENUEND:       return( "WM_MENUEND");
480      case TXWM_SETFOOTER:     return( "WM_SETFOOTER");
481      case TXWM_BUTTONDOWN:    return( "WM_BUTTONDOWN");
482      case TXWM_BUTTONUP:      return( "WM_BUTTONUP");
483      case TXWM_BUTTONDBLCLK:  return( "WM_BUTTONDBLCLK");
484      case TXWM_MOUSEMOVE:     return( "WM_MOUSEMOVE");
485      case TXWM_HOOKEVENT:     return( "WM_HOOKEVENT");
486      case TXWM_FD_FILTER:     return( "WM_FD_FILTER");
487      case TXWM_FD_VALIDATE:   return( "WM_FD_VALIDATE");
488      case TXWM_FD_ERROR:      return( "WM_FD_ERROR");
489      case TXWM_FD_NEWSPEC:    return( "WM_FD_NEWSPEC");
490      case TXWM_FD_NEWPATH:    return( "WM_FD_NEWPATH");
491      case TXWM_FD_WILDCARD:   return( "TXWM_FD_WILDCARD");
492      case TXWM_FD_POPULATED:  return( "TXWM_FD_POPULATED");
493      default:
494         if (msg < TXWM_USER)
495         {
496            return( "UNKNOWN txw msg");
497         }
498         else
499         {
500            return( "USER MESSAGE");
501         }
502   }
503}                                               // end 'txwMsgDescription'
504/*---------------------------------------------------------------------------*/
505
506
507/*****************************************************************************/
508// Return short description for WM_CHAR key code (mp2)
509/*****************************************************************************/
510char *txwKeyDescription
511(
512   ULONG               key                      // IN    message-id
513)
514{
515   switch (key)
516   {
517      case TXk_F1:                 return( "k_F1");
518      case TXk_F2:                 return( "k_F2");
519      case TXk_F3:                 return( "k_F3");
520      case TXk_F4:                 return( "k_F4");
521      case TXk_F5:                 return( "k_F5");
522      case TXk_F6:                 return( "k_F6");
523      case TXk_F7:                 return( "k_F7");
524      case TXk_F8:                 return( "k_F8");
525      case TXk_F9:                 return( "k_F9");
526      case TXk_F10:                return( "k_F10");
527      case TXk_F11:                return( "k_F11");
528      case TXk_F12:                return( "k_F12");
529      case TXk_ENTER:              return( "k_ENTER");
530      case TXk_BACKSPACE:          return( "k_BACKSPACE");
531      case TXk_TAB:                return( "k_TAB");
532      case TXk_ESCAPE:             return( "k_ESCAPE");
533      case TXk_BACKQUOTE:          return( "k_BACKQUOTE");
534      case TXk_INSERT:             return( "k_INSERT");
535      case TXk_DELETE:             return( "k_DELETE");
536      case TXk_UP:                 return( "k_UP");
537      case TXk_DOWN:               return( "k_DOWN");
538      case TXk_LEFT:               return( "k_LEFT");
539      case TXk_RIGHT:              return( "k_RIGHT");
540      case TXk_PGUP:               return( "k_PGUP");
541      case TXk_PGDN:               return( "k_PGDN");
542      case TXk_HOME:               return( "k_HOME");
543      case TXk_END:                return( "k_END");
544      case TXs_F1:                 return( "s_F1");
545      case TXs_F2:                 return( "s_F2");
546      case TXs_F3:                 return( "s_F3");
547      case TXs_F4:                 return( "s_F4");
548      case TXs_F5:                 return( "s_F5");
549      case TXs_F6:                 return( "s_F6");
550      case TXs_F7:                 return( "s_F7");
551      case TXs_F8:                 return( "s_F8");
552      case TXs_F9:                 return( "s_F9");
553      case TXs_F10:                return( "s_F10");
554      case TXs_F11:                return( "s_F11");
555      case TXs_F12:                return( "s_F12");
556      case TXs_TAB:                return( "s_TAB");
557      case TXc_F1:                 return( "c_F1");
558      case TXc_F2:                 return( "c_F2");
559      case TXc_F3:                 return( "c_F3");
560      case TXc_F4:                 return( "c_F4");
561      case TXc_F5:                 return( "c_F5");
562      case TXc_F6:                 return( "c_F6");
563      case TXc_F7:                 return( "c_F7");
564      case TXc_F8:                 return( "c_F8");
565      case TXc_F9:                 return( "c_F9");
566      case TXc_F10:                return( "c_F10");
567      case TXc_F11:                return( "c_F11");
568      case TXc_F12:                return( "c_F12");
569      case TXc_ENTER:              return( "c_ENTER");
570      case TXc_BACKSP:             return( "c_BACKSP");
571      case TXc_TAB:                return( "c_TAB");
572      case TXc_2:                  return( "c_2");
573      case TXc_6:                  return( "c_6");
574      case TXc_MINUS:              return( "c_MINUS");
575      case TXc_RBRACKET:           return( "c_RBRACKET");
576      case TXc_BACKSLASH:          return( "c_BACKSLASH");
577      case TXc_INSERT:             return( "c_INSERT");
578      case TXc_DELETE:             return( "c_DELETE");
579      case TXc_UP:                 return( "c_UP");
580      case TXc_DOWN:               return( "c_DOWN");
581      case TXc_LEFT:               return( "c_LEFT");
582      case TXc_RIGHT:              return( "c_RIGHT");
583      case TXc_PGUP:               return( "c_PGUP");
584      case TXc_PGDN:               return( "c_PGDN");
585      case TXc_HOME:               return( "c_HOME");
586      case TXc_END:                return( "c_END");
587      case TXc_A:                  return( "c_A");
588      case TXc_B:                  return( "c_B");
589      case TXc_C:                  return( "c_C");
590      case TXc_D:                  return( "c_D");
591      case TXc_E:                  return( "c_E");
592      case TXc_F:                  return( "c_F");
593      case TXc_G:                  return( "c_G");
594      case TXc_K:                  return( "c_K");
595      case TXc_L:                  return( "c_L");
596      case TXc_N:                  return( "c_N");
597      case TXc_O:                  return( "c_O");
598      case TXc_P:                  return( "c_P");
599      case TXc_Q:                  return( "c_Q");
600      case TXc_R:                  return( "c_R");
601      case TXc_S:                  return( "c_S");
602      case TXc_T:                  return( "c_T");
603      case TXc_U:                  return( "c_U");
604      case TXc_V:                  return( "c_V");
605      case TXc_W:                  return( "c_W");
606      case TXc_X:                  return( "c_X");
607      case TXc_Y:                  return( "c_Y");
608      case TXc_Z:                  return( "c_Z");
609      case TXa_F1:                 return( "a_F1");
610      case TXa_F2:                 return( "a_F2");
611      case TXa_F3:                 return( "a_F3");
612      case TXa_F4:                 return( "a_F4");
613      case TXa_F5:                 return( "a_F5");
614      case TXa_F6:                 return( "a_F6");
615      case TXa_F7:                 return( "a_F7");
616      case TXa_F8:                 return( "a_F8");
617      case TXa_F9:                 return( "a_F9");
618      case TXa_F10:                return( "a_F10");
619      case TXa_F11:                return( "a_F11");
620      case TXa_F12:                return( "a_F12");
621      case TXa_ENTER:              return( "a_ENTER");
622      case TXa_BACKSP:             return( "a_BACKSP");
623      case TXa_1:                  return( "a_1");
624      case TXa_2:                  return( "a_2");
625      case TXa_3:                  return( "a_3");
626      case TXa_4:                  return( "a_4");
627      case TXa_5:                  return( "a_5");
628      case TXa_6:                  return( "a_6");
629      case TXa_7:                  return( "a_7");
630      case TXa_8:                  return( "a_8");
631      case TXa_9:                  return( "a_9");
632      case TXa_0:                  return( "a_0");
633      case TXa_MINUS:              return( "a_MINUS");
634      case TXa_EQUAL:              return( "a_EQUAL");
635      case TXa_LBRACKET:           return( "a_LBRACKET");
636      case TXa_RBRACKET:           return( "a_RBRACKET");
637      case TXa_SEMICOLON:          return( "a_SEMICOLON");
638      case TXa_QUOTE:              return( "a_QUOTE");
639      case TXa_BACKQUOTE:          return( "a_BACKQUOTE");
640      case TXa_BACKSLASH:          return( "a_BACKSLASH");
641      case TXa_COMMA:              return( "a_COMMA");
642      case TXa_DOT:                return( "a_DOT");
643      case TXa_SLASH:              return( "a_SLASH");
644      case TXa_INSERT:             return( "a_INSERT");
645      case TXa_DELETE:             return( "a_DELETE");
646      case TXa_UP:                 return( "a_UP");
647      case TXa_DOWN:               return( "a_DOWN");
648      case TXa_LEFT:               return( "a_LEFT");
649      case TXa_RIGHT:              return( "a_RIGHT");
650      case TXa_PGUP:               return( "a_PGUP");
651      case TXa_PGDN:               return( "a_PGDN");
652      case TXa_HOME:               return( "a_HOME");
653      case TXa_END:                return( "a_END");
654      case TXa_A:                  return( "a_A");
655      case TXa_B:                  return( "a_B");
656      case TXa_C:                  return( "a_C");
657      case TXa_D:                  return( "a_D");
658      case TXa_E:                  return( "a_E");
659      case TXa_F:                  return( "a_F");
660      case TXa_G:                  return( "a_G");
661      case TXa_H:                  return( "a_H");
662      case TXa_I:                  return( "a_I");
663      case TXa_J:                  return( "a_J");
664      case TXa_K:                  return( "a_K");
665      case TXa_L:                  return( "a_L");
666      case TXa_M:                  return( "a_M");
667      case TXa_N:                  return( "a_N");
668      case TXa_O:                  return( "a_O");
669      case TXa_P:                  return( "a_P");
670      case TXa_Q:                  return( "a_Q");
671      case TXa_R:                  return( "a_R");
672      case TXa_S:                  return( "a_S");
673      case TXa_T:                  return( "a_T");
674      case TXa_U:                  return( "a_U");
675      case TXa_V:                  return( "a_V");
676      case TXa_W:                  return( "a_W");
677      case TXa_X:                  return( "a_X");
678      case TXa_Y:                  return( "a_Y");
679      case TXa_Z:                  return( "a_Z");
680      case TXk_LWIN:               return( "L-Win");
681      case TXk_RWIN:               return( "R-Win");
682      case TXk_MENU:               return( "Menu");
683      case TXk_FIND:               return( "Find");
684      default:
685         if (isprint(key))
686         {
687            sprintf( ascii, "ascii: '%c'", key);
688         }
689         else
690         {
691            strcpy( ascii, "unknown key");
692</