/* 3270 window widget

   This widget contains the functions needed to handle keyboard
   input and other actions for 3270 windows.  Most of the work
   is done by the client through callback procedures.  The X3270
   widget is a sub-class of this one that is used to define the
   resources needed for a text window.  Ga3270 and Im3270 are 
   other sub-classes that are used for 3277-GA and image windows.  */


#undef BSD_INCLUDES
#define BSD_INCLUDES
#include <memory.h>
#include <X11/IntrinsicP.h>
#include <X11/Xos.h>
#include <X11/StringDefs.h>
#include "Win3270P.h"
#define KEYS_DECLARE
#define KEYS_APL
#include "keys.h"
#define BUFSIZE 50000

static Pixel defColor = ~0; /* Value for color that hasn't been set */

#define offset(field) XtOffset(Win3270Widget, win3270.field)

static XtResource resources[] = {
  {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
     offset(foreground), XtRString, "XtDefaultForeground"},
  {XtNbackColor, XtCBackColor, XtRPixel, sizeof(Pixel),
     offset(backColor), XtRString, "XtDefaultForeground"},
  {XtNforeColor, XtCForeColor, XtRPixel, sizeof(Pixel),
     offset(foreColor), XtRString, "XtDefaultBackground"},
  {XtNmouseColor, XtCMouseColor, XtRPixel, sizeof(Pixel),
     offset(mouseColor), XtRPixel, (caddr_t) &defColor},
  {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
     offset(cursor), XtRString, "left_ptr"},
  {XtNspeckey, XtCBoolean, XtRBoolean, sizeof(Boolean),
     offset(speckey), XtRImmediate, (caddr_t) False},
  {XtNkeyfile, XtCFile, XtRString, sizeof(caddr_t),
     offset(keyfile), XtRString, NULL},
  {XtNkeyProc, XtCCallback, XtRCallback, sizeof(caddr_t),
     offset(keyProc), XtRCallback, NULL},
  {XtNresizeProc, XtCCallback, XtRCallback, sizeof(caddr_t),
     offset(resizeProc), XtRCallback, NULL},
  {XtNexposeProc, XtCCallback, XtRCallback, sizeof(caddr_t),
     offset(exposeProc), XtRCallback, NULL},
  {XtNactionProc, XtCCallback, XtRCallback, sizeof(caddr_t),
     offset(actionProc), XtRCallback, NULL},
  {XtNdestroyProc, XtCCallback, XtRCallback, sizeof(caddr_t),
     offset(destroyProc), XtRCallback, NULL},
  {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
     XtOffset(Win3270Widget, core.border_width), XtRImmediate, (caddr_t) 0},
};


/* Default translation table */
static char defaultTranslations[] =
    "Mod3 Ctrl<Key>q:           q-underbar() \n\
     Mod3 Ctrl<Key>w:           w-underbar() \n\
     Mod3 Ctrl<Key>e:           e-underbar() \n\
     Mod3 Ctrl<Key>r:           r-underbar() \n\
     Mod3 Ctrl<Key>t:           t-underbar() \n\
     Mod3 Ctrl<Key>y:           y-underbar() \n\
     Mod3 Ctrl<Key>u:           u-underbar() \n\
     Mod3 Ctrl<Key>i:           i-underbar() \n\
     Mod3 Ctrl<Key>o:           o-underbar() \n\
     Mod3 Ctrl<Key>p:           p-underbar() \n\
     Mod3 Ctrl<Key>a:           a-underbar() \n\
     Mod3 Ctrl<Key>s:           s-underbar() \n\
     Mod3 Ctrl<Key>d:           d-underbar() \n\
     Mod3 Ctrl<Key>f:           f-underbar() \n\
     Mod3 Ctrl<Key>g:           g-underbar() \n\
     Mod3 Ctrl<Key>h:           h-underbar() \n\
     Mod3 Ctrl<Key>j:           j-underbar() \n\
     Mod3 Ctrl<Key>k:           k-underbar() \n\
     Mod3 Ctrl<Key>l:           l-underbar() \n\
     Mod3 Ctrl<Key>z:           z-underbar() \n\
     Mod3 Ctrl<Key>x:           x-underbar() \n\
     Mod3 Ctrl<Key>c:           c-underbar() \n\
     Mod3 Ctrl<Key>v:           v-underbar() \n\
     Mod3 Ctrl<Key>b:           b-underbar() \n\
     Mod3 Ctrl<Key>n:           n-underbar() \n\
     Mod3 Ctrl<Key>m:           m-underbar() \n\
     Mod3 Alt<Key>quoteleft:    quad-slope() \n\
     Mod3 Alt<Key>1:            i-beam() \n\
     Mod3 Alt<Key>2:            del-tilde() \n\
     Mod3 Alt<Key>3:            del-stile() \n\
     Mod3 Alt<Key>4:            delta-stile() \n\
     Mod3 Alt<Key>5:            circle-stile() \n\
     Mod3 Alt<Key>6:            circle-slope() \n\
     Mod3 Alt<Key>7:            circle-bar() \n\
     Mod3 Alt<Key>8:            circle-star() \n\
     Mod3 Alt<Key>9:            down-carat-tilde() \n\
     Mod3 Alt<Key>0:            up-carat-tilde() \n\
     Mod3 Alt<Key>minus:        quote-dot() \n\
     Mod3 Alt<Key>equal:        quad-divide() \n\
     Mod3 Alt<Key>q:            string(q) \n\
     Mod3 Alt<Key>w:            string(w) \n\
     Mod3 Alt<Key>e:            string(e) \n\
     Mod3 Alt<Key>r:            string(r) \n\
     Mod3 Alt<Key>t:            string(t) \n\
     Mod3 Alt<Key>y:            string(y) \n\
     Mod3 Alt<Key>u:            string(u) \n\
     Mod3 Alt<Key>i:            string(i) \n\
     Mod3 Alt<Key>o:            string(o) \n\
     Mod3 Alt<Key>p:            string(p) \n\
     Mod3 Alt<Key>bracketleft:  quad-quote() \n\
     Mod3 Alt<Key>bracketright: delta-underbar() \n\
     Mod3 Alt<Key>backslash:    dieresis-dot() \n\
     Mod3 Alt<Key>a:            string(a) \n\
     Mod3 Alt<Key>s:            string(s) \n\
     Mod3 Alt<Key>d:            string(d) \n\
     Mod3 Alt<Key>f:            string(f) \n\
     Mod3 Alt<Key>g:            string(g) \n\
     Mod3 Alt<Key>h:            string(h) \n\
     Mod3 Alt<Key>j:            string(j) \n\
     Mod3 Alt<Key>k:            string(k) \n\
     Mod3 Alt<Key>l:            string(l) \n\
     Mod3 Alt<Key>semicolon:    down-tack-jot() \n\
     Mod3 Alt<Key>quoteright:   up-tack-jot() \n\
     Mod3 Alt<Key>z:            string(z) \n\
     Mod3 Alt<Key>x:            string(x) \n\
     Mod3 Alt<Key>c:            string(c) \n\
     Mod3 Alt<Key>v:            string(v) \n\
     Mod3 Alt<Key>b:            string(b) \n\
     Mod3 Alt<Key>n:            string(n) \n\
     Mod3 Alt<Key>m:            string(m) \n\
     Mod3 Alt<Key>comma:        up-shoe-jot() \n\
     Mod3 Alt<Key>period:       slope-bar() \n\
     Mod3 Alt<Key>slash:        slash-bar() \n",
  tab2[] =
    "Mod3 Shift<Key>quoteleft:  quad-jot() \n\
     Mod3 Shift<Key>1:          dieresis() \n\
     Mod3 Shift<Key>2:          overbar() \n\
     Mod3 Shift<Key>3:          string(<) \n\
     Mod3 Shift<Key>4:          not-greater() \n\
     Mod3 Shift<Key>5:          string(=) \n\
     Mod3 Shift<Key>6:          not-less() \n\
     Mod3 Shift<Key>7:          string(>) \n\
     Mod3 Shift<Key>8:          not-equal() \n\
     Mod3 Shift<Key>9:          down-carat() \n\
     Mod3 Shift<Key>0:          up-carat() \n\
     Mod3 Shift<Key>minus:      string(-) \n\
     Mod3 Shift<Key>equal:      divide() \n\
     Mod3 Shift Lock<Key>q:     string(Q) \n\
     Mod3 Lock<Key>q:           string(?) \n\
     Mod3 Shift<Key>q:          string(?) \n\
     Mod3<Key>q:                string(Q) \n\
     Mod3 Shift Lock<Key>w:     string(W) \n\
     Mod3 Lock<Key>w:           omega() \n\
     Mod3 Shift<Key>w:          omega() \n\
     Mod3<Key>w:                string(W) \n\
     Mod3 Shift Lock<Key>e:     string(E) \n\
     Mod3 Lock<Key>e:           epsilon() \n\
     Mod3 Shift<Key>e:          epsilon() \n\
     Mod3<Key>e:                string(E) \n\
     Mod3 Shift Lock<Key>r:     string(R) \n\
     Mod3 Lock<Key>r:           rho() \n\
     Mod3 Shift<Key>r:          rho() \n\
     Mod3<Key>r:                string(R) \n\
     Mod3 Shift Lock<Key>t:     string(T) \n\
     Mod3 Lock<Key>t:           tilde() \n\
     Mod3 Shift<Key>t:          tilde() \n\
     Mod3<Key>t:                string(T) \n\
     Mod3 Shift Lock<Key>y:     string(Y) \n\
     Mod3 Lock<Key>y:           up-arrow() \n\
     Mod3 Shift<Key>y:          up-arrow() \n\
     Mod3<Key>y:                string(Y) \n\
     Mod3 Shift Lock<Key>u:     string(U) \n\
     Mod3 Lock<Key>u:           down-arrow() \n\
     Mod3 Shift<Key>u:          down-arrow() \n\
     Mod3<Key>u:                string(U) \n\
     Mod3 Shift Lock<Key>i:     string(I) \n\
     Mod3 Lock<Key>i:           iota() \n\
     Mod3 Shift<Key>i:          iota() \n\
     Mod3<Key>i:                string(I) \n\
     Mod3 Shift Lock<Key>o:     string(O) \n\
     Mod3 Lock<Key>o:           circle() \n\
     Mod3 Shift<Key>o:          circle() \n\
     Mod3<Key>o:                string(O) \n\
     Mod3 Shift Lock<Key>p:     string(P) \n\
     Mod3 Lock<Key>p:           string(*) \n\
     Mod3 Shift<Key>p:          string(*) \n\
     Mod3<Key>p:                string(P) \n\
     Mod3 Shift<Key>bracketleft: right-arrow() \n\
     Mod3 Shift<Key>bracketright: iota-underbar() \n\
     Mod3 Shift<Key>backslash:  epsilon-underbar() \n\
     Mod3 Shift Lock<Key>a:     string(A) \n\
     Mod3 Lock<Key>a:           alpha() \n\
     Mod3 Shift<Key>a:          alpha() \n\
     Mod3<Key>a:                string(A) \n\
     Mod3 Shift Lock<Key>s:     string(S) \n\
     Mod3 Lock<Key>s:           up-stile() \n\
     Mod3 Shift<Key>s:          up-stile() \n\
     Mod3<Key>s:                string(S) \n\
     Mod3 Shift Lock<Key>d:     string(D) \n\
     Mod3 Lock<Key>d:           down-stile() \n\
     Mod3 Shift<Key>d:          down-stile() \n\
     Mod3<Key>d:                string(D) \n\
     Mod3 Shift Lock<Key>f:     string(F) \n\
     Mod3 Lock<Key>f:           string(_) \n\
     Mod3 Shift<Key>f:          string(_) \n\
     Mod3<Key>f:                string(F) \n\
     Mod3 Shift Lock<Key>g:     string(G) \n\
     Mod3 Lock<Key>g:           del() \n\
     Mod3 Shift<Key>g:          del() \n\
     Mod3<Key>g:                string(G) \n\
     Mod3 Shift Lock<Key>h:     string(H) \n\
     Mod3 Lock<Key>h:           delta() \n\
     Mod3 Shift<Key>h:          delta() \n\
     Mod3<Key>h:                string(H) \n",
  tab3[] =
    "Mod3 Shift Lock<Key>j:     string(J) \n\
     Mod3 Lock<Key>j:           jot() \n\
     Mod3 Shift<Key>j:          jot() \n\
     Mod3<Key>j:                string(J) \n\
     Mod3 Shift Lock<Key>k:     string(K) \n\
     Mod3 Lock<Key>k:           string(') \n\
     Mod3 Shift<Key>k:          string(') \n\
     Mod3<Key>k:                string(K) \n\
     Mod3 Shift Lock<Key>l:     string(L) \n\
     Mod3 Lock<Key>l:           quad() \n\
     Mod3 Shift<Key>l:          quad() \n\
     Mod3<Key>l:                string(L) \n\
     Mod3 Shift<Key>semicolon:  string(\"(\") \n\
     Mod3 Shift<Key>quoteright: string(\")\") \n\
     Mod3 Shift Lock<Key>z:     string(Z) \n\
     Mod3 Lock<Key>z:           left-shoe() \n\
     Mod3 Shift<Key>z:          left-shoe() \n\
     Mod3<Key>z:                string(Z) \n\
     Mod3 Shift Lock<Key>x:     string(X) \n\
     Mod3 Lock<Key>x:           right-shoe() \n\
     Mod3 Shift<Key>x:          right-shoe() \n\
     Mod3<Key>x:                string(X) \n\
     Mod3 Shift Lock<Key>c:     string(C) \n\
     Mod3 Lock<Key>c:           up-shoe() \n\
     Mod3 Shift<Key>c:          up-shoe() \n\
     Mod3<Key>c:                string(C) \n\
     Mod3 Shift Lock<Key>v:     string(V) \n\
     Mod3 Lock<Key>v:           down-shoe() \n\
     Mod3 Shift<Key>v:          down-shoe() \n\
     Mod3<Key>v:                string(V) \n\
     Mod3 Shift Lock<Key>b:     string(B) \n\
     Mod3 Lock<Key>b:           down-tack() \n\
     Mod3 Shift<Key>b:          down-tack() \n\
     Mod3<Key>b:                string(B) \n\
     Mod3 Shift Lock<Key>n:     string(N) \n\
     Mod3 Lock<Key>n:           up-tack() \n\
     Mod3 Shift<Key>n:          up-tack() \n\
     Mod3<Key>n:                string(N) \n\
     Mod3 Shift Lock<Key>m:     string(M) \n\
     Mod3 Lock<Key>m:           stile() \n\
     Mod3 Shift<Key>m:          stile() \n\
     Mod3<Key>m:                string(M) \n\
     Mod3 Shift<Key>comma:      string(;) \n\
     Mod3 Shift<Key>period:     string(:) \n\
     Mod3 Shift<Key>slash:      slope() \n\
     Mod3<Key>minus:            string(+) \n\
     Mod3<Key>equal:            times() \n\
     Mod3<Key>bracketleft:      left-arrow() \n\
     Mod3<Key>bracketright:     squad() \n\
     Mod3<Key>backslash:        equal-underbar() \n\
     Mod3<Key>semicolon:        left-bracket() \n\
     Mod3<Key>quoteright:       right-bracket() \n\
     Shift<Key>KP_1:		lower-left-box-corner() \n\
     Shift<Key>KP_2:		bottom-box-tee() \n\
     Shift<Key>KP_3:		lower-right-box-corner() \n\
     Shift<Key>KP_4:		left-box-tee() \n\
     Shift<Key>KP_5:		box-cross() \n\
     Shift<Key>KP_6:		right-box-tee() \n\
     Shift<Key>KP_7:		upper-left-box-corner() \n\
     Shift<Key>KP_8:		top-box-tee() \n\
     Shift<Key>KP_9:		upper-right-box-corner() \n\
     Shift<Key>KP_0:		vertical-box-bar() \n\
     Shift<Key>KP_Decimal:	horizontal-box-bar() \n\
     <Key>Up:           up() \n\
     Ctrl<Key>P:        up() \n\
     <Key>Down:         down() \n\
     Ctrl<Key>N:        down() \n\
     Ctrl<Key>Right:    forward-word() \n\
     Alt<Key>F:         forward-word() \n\
     Ctrl<Key>Left:     backward-word() \n\
     Alt<Key>B:         backward-word() \n\
     <Key>Left:         left() \n\
     Ctrl<Key>B:        left() \n\
     <Key>Right:        right() \n\
     Ctrl<Key>F:        right() \n\
     <Key>Return:       newline() \n\
     <Key>KP_Enter:     newline() \n\
     <Key>Linefeed:     newline() \n\
     Shift<Key>Home:    field-mark() \n\
     <Key>Home:         home() \n\
     Shift<Key>Tab:     backtab() \n\
     Ctrl<Key>A:        backtab() \n\
     <Key>Tab:          tab() \n\
     Ctrl<Key>End:      erase-eof() \n\
     Ctrl<Key>K:        erase-eof() \n\
     Alt<Key>End:       dup() \n\
     <Key>End:          end() \n\
     Ctrl<Key>E:        end() \n\
     <Key>Insert:       insert() \n\
     Ctrl<Key>Delete:   erase-input() \n\
     <Key>Delete:       delete() \n\
     Ctrl<Key>D:        delete() \n",
  tab4[] =
    "Alt<Key>BackSpace: backward-kill-word() \n\
     Ctrl<Key>BackSpace:aplonoff(3) \n\
     <Key>BackSpace:    backspace() \n\
     Alt<Key>D:         kill-word() \n\
     Alt<Key>Print:     sysreq() \n\
     Ctrl<Key>Print:    sysreq() \n\
     Alt<Key>C:         cent() \n\
     Shift<Key>Print:   print-screen() \n\
     Ctrl<Key>Pause:	attention() \n\
     <Key>Print:        pa1() \n\
     Ctrl<Key>F1:       pa1() \n\
     Ctrl<Key>Z:        pa1() \n\
     Meta<Key>1:        pa1() \n\
     Ctrl<Key>F2:       pa2() \n\
     <Key>Cancel:       pa2() \n\
     Ctrl<Key>L:        pa2() \n\
     Meta<Key>2:        pa2() \n\
     Ctrl<Key>F3:       pa3() \n\
     Meta<Key>3:        pa3() \n\
     <Key>F13:          pf13() \n\
     Shift<Key>F1:      pf13() \n\
     <Key>F14:          pf14() \n\
     Shift<Key>F2:      pf14() \n\
     <Key>F15:          pf15() \n\
     Shift<Key>F3:      pf15() \n\
     <Key>F16:          pf16() \n\
     Shift<Key>F4:      pf16() \n\
     <Key>F17:          pf17() \n\
     Shift<Key>F5:      pf17() \n\
     <Key>F18:          pf18() \n\
     Shift<Key>F6:      pf18() \n\
     <Key>F19:          pf19() \n\
     Shift<Key>F7:      pf19() \n\
     <Key>F20:          pf20() \n\
     Shift<Key>F8:      pf20() \n\
     <Key>F21:          pf21() \n\
     Shift<Key>F9:      pf21() \n\
     <Key>F22:          pf22() \n\
     Shift<Key>F10:     pf22() \n\
     <Key>F23:          pf23() \n\
     Shift<Key>F11:     pf23() \n\
     <Key>F24:          pf24() \n\
     Shift<Key>F12:     pf24() \n\
     <Key>F1:           pf1() \n\
     None<Key>KP_1:     pf1() \n\
     <Key>F2:           pf2() \n\
     None<Key>KP_2:     pf2() \n\
     <Key>F3:           pf3() \n\
     None<Key>KP_3:     pf3() \n\
     Ctrl<Key>C:        pf3() \n\
     <Key>F4:           pf4() \n\
     None<Key>KP_4:     pf4() \n\
     <Key>F5:           pf5() \n\
     None<Key>KP_5:     pf5() \n\
     <Key>F6:           pf6() \n\
     None<Key>KP_6:     pf6() \n\
     <Key>F7:           pf7() \n\
     None<Key>KP_7:     pf7() \n\
     <Key>Prior:        pf7() \n\
     Alt<Key>V:         pf7() \n\
     <Key>F8:           pf8() \n\
     None<Key>KP_8:     pf8() \n\
     <Key>Next:         pf8() \n\
     Ctrl<Key>V:        pf8() \n\
     <Key>F9:           pf9() \n\
     None<Key>KP_9:     pf9() \n\
     <Key>F10:          pf10() \n\
     None<Key>KP_0:     pf10() \n\
     Ctrl<Key>I:        pf10() \n\
     <Key>F11:          pf11() \n\
     <Key>F12:          pf12() \n\
     <Key>Execute:      enter() \n\
     <Key>Meta_R:       enter() \n\
     Alt<Key>Escape:    reset() \n\
     Ctrl<Key>G:        reset() \n\
     Meta<Key>R:        reset() \n\
     <Key>Clear:        clear() \n\
     <Key>Pause:        clear() \n\
     <Key>Escape:       clear() \n\
     Meta<Key>C:        clear() \n\
     Ctrl<Key>U:        unlock() \n\
     Alt<Key>P:         dumpfields() \n\
     <Key>:             string() \n\
     Shift<Key>:        string() \n\
     Shift<Btn1Down>:   select-start() \n\
     Shift<Btn1Motion>: select-adjust() \n\
     Shift<Btn1Up>:     select-end() \n\
     Shift<Btn2Up>:     select-all() \n\
     Shift<Btn3Up>:     insert-selection() \n\
     <Btn1Down>:        special1() \n\
     <Btn2Up>:          special2() \n\
     <Btn3Up>:          special3()";
 

static char specialTranslations[] =
    "Alt<Key>Return:	newline() \n\
     <Key>Execute:	newline() \n\
     <Key>Meta_R:       newline() \n\
     Ctrl<Key>Pause:	attention() \n\
     <Key>Pause:	pa2() \n\
     <Key>Return:	enter() \n\
     <Key>KP_Enter:	enter() \n\
     <Key>Linefeed:     enter()";


static void f_select_start(), f_select_adjust(), f_select_end(),
  f_select_all(), f_insert_selection(), f_zoom(), f_iconify(),
  f_set_cursor(), f_special1(), f_special2(), f_special3(),
  f_ga3277_clear(), f_ga3277_refresh(), f_ga3277_set_cursor(),
  f_image_save(), f_image_destroy(), f_aplonoff(), f_modlock(),
  f_system();


static XtActionsRec actions[] =
{
  {"undefined",		c_undefined},
  {"string",		c_string},
  {"cursor-move",	c_cursor_move},

  {"up",		c_up},
  {"down",		c_down},
  {"left",		c_left},
  {"right",		c_right},
  {"newline",		c_newline},
  {"home",		c_home},
  {"tab",		c_tab},
  {"backtab",		c_backtab},
  {"end",		c_end},
  {"forward-word",	c_forward_word},
  {"backward-word",	c_backward_word},

  {"insert",		c_insert},
  {"delete",		c_delete},
  {"backspace",		c_backspace},
  {"kill-word",		c_kill_word},
  {"backward-kill-word",c_backward_kill_word},

  {"erase-eof",		c_erase_eof},
  {"erase-input",	c_erase_input},
  {"dup",		c_dup},
  {"field-mark",	c_field_mark},
  {"cent",		c_cent},

  {"pf1",		c_pf1},
  {"pf2",		c_pf2},
  {"pf3",		c_pf3},
  {"pf4",		c_pf4},
  {"pf5",		c_pf5},
  {"pf6",		c_pf6},
  {"pf7",		c_pf7},
  {"pf8",		c_pf8},
  {"pf9",		c_pf9},
  {"pf10",		c_pf10},
  {"pf11",		c_pf11},
  {"pf12",		c_pf12},
  {"pf13",		c_pf13},
  {"pf14",		c_pf14},
  {"pf15",		c_pf15},
  {"pf16",		c_pf16},
  {"pf17",		c_pf17},
  {"pf18",		c_pf18},
  {"pf19",		c_pf19},
  {"pf20",		c_pf20},
  {"pf21",		c_pf21},
  {"pf22",		c_pf22},
  {"pf23",		c_pf23},
  {"pf24",		c_pf24},

  {"clear",		c_clear},
  {"enter",		c_enter},
  {"pa1",		c_pa1},
  {"pa2",		c_pa2},
  {"pa3",		c_pa3},
  {"sysreq",		c_sysreq},
  {"attention",		c_attn},

  {"reset",		c_reset},
  {"unlock",		c_unlock},
  {"dumpfields",	c_dumpfields},
  {"print-screen",	c_print_screen},

  {"stringa",		c_stringa},
  {"stringa_",		c_stringa_},
  {"hex",		c_hex},
  {"hex-ge",		c_hex_ge},

  /* The following routines really call stringa or stringa_  */

  {"a-underbar",	c_a_underbar},
  {"alpha",		c_alpha},
  {"b-underbar",	c_b_underbar},
  {"c-underbar",	c_c_underbar},
  {"circle-bar",	c_circle_bar},
  {"circle-slope",	c_circle_slope},
  {"circle-star",	c_circle_star},
  {"circle-stile",	c_circle_stile},
  {"circle",		c_circle},
  {"d-underbar",	c_d_underbar},
  {"del",		c_del},
  {"del-stile",		c_del_stile},
  {"del-tilde",		c_del_tilde},
  {"delta",		c_delta},
  {"delta-stile",	c_delta_stile},
  {"delta-underbar",	c_delta_underbar},
  {"diamond",		c_diamond},
  {"dieresis",		c_dieresis},
  {"dieresis-dot",	c_dieresis_dot},
  {"divide",		c_divide},
  {"down-arrow",	c_down_arrow},
  {"down-carat",	c_down_carat},
  {"down-carat-tilde",	c_down_carat_tilde},
  {"down-shoe",		c_down_shoe},
  {"down-stile",	c_down_stile},
  {"down-tack",		c_down_tack},
  {"down-tack-jot",	c_down_tack_jot},
  {"e-underbar",	c_e_underbar},
  {"epsilon",		c_epsilon},
  {"epsilon-underbar",	c_epsilon_underbar},
  {"equal-underbar",	c_equal_underbar},
  {"f-underbar",	c_f_underbar},
  {"g-underbar",	c_g_underbar},
  {"h-underbar",	c_h_underbar},
  {"i-beam",		c_i_beam},
  {"i-underbar",	c_i_underbar},
  {"iota",		c_iota},
  {"iota-underbar",	c_iota_underbar},
  {"j-underbar",	c_j_underbar},
  {"jot",		c_jot},
  {"k-underbar",	c_k_underbar},
  {"l-underbar",	c_l_underbar},
  {"left-arrow",	c_left_arrow},
  {"left-bracket",	c_left_bracket},
  {"left-shoe",		c_left_shoe},
  {"left-tack",		c_left_tack},
  {"m-underbar",	c_m_underbar},
  {"n-underbar",	c_n_underbar},
  {"not-equal",		c_not_equal},
  {"not-greater",	c_not_greater},
  {"not-less",		c_not_less},
  {"o-underbar",	c_o_underbar},
  {"omega",		c_omega},
  {"overbar",		c_overbar},
  {"p-underbar",	c_p_underbar},
  {"q-underbar",	c_q_underbar},
  {"quad",		c_quad},
  {"quad-divide",	c_quad_divide},
  {"quad-jot",		c_quad_jot},
  {"quad-quote",	c_quad_quote},
  {"quad-slope",	c_quad_slope},
  {"quote-dot",		c_quote_dot},
  {"r-underbar",	c_r_underbar},
  {"rho",		c_rho},
  {"right-arrow",	c_right_arrow},
  {"right-bracket",	c_right_bracket},
  {"right-shoe",	c_right_shoe},
  {"right-tack",	c_right_tack},
  {"s-underbar",	c_s_underbar},
  {"slash-bar",		c_slash_bar},
  {"slope",		c_slope},
  {"slope-bar",		c_slope_bar},
  {"squad",		c_squad},
  {"stile",		c_stile},
  {"t-underbar",	c_t_underbar},
  {"tilde",		c_tilde},
  {"times",		c_times},
  {"u-underbar",	c_u_underbar},
  {"up-arrow",		c_up_arrow},
  {"up-carat",		c_up_carat},
  {"up-carat-tilde",	c_up_carat_tilde},
  {"up-shoe",		c_up_shoe},
  {"up-shoe-jot",	c_up_shoe_jot},
  {"up-stile",		c_up_stile},
  {"up-tack",		c_up_tack},
  {"up-tack-jot",	c_up_tack_jot},
  {"v-underbar",	c_v_underbar},
  {"w-underbar",	c_w_underbar},
  {"x-underbar",	c_x_underbar},
  {"y-underbar",	c_y_underbar},
  {"z-underbar",	c_z_underbar},

  /* Functions for box chars which really use stringa */

  {"upper-left-box-corner",	c_upper_left_box_corner},
  {"upper-right-box-corner",	c_upper_right_box_corner},
  {"lower-left-box-corner",	c_lower_left_box_corner},
  {"lower-right-box-corner",	c_lower_right_box_corner},
  {"top-box-tee",		c_top_box_tee},
  {"bottom-box-tee",		c_bottom_box_tee},
  {"left-box-tee",		c_left_box_tee},
  {"right-box-tee",		c_right_box_tee},
  {"box-cross",			c_box_cross},
  {"horizontal-box-bar",	c_horizontal_box_bar},
  {"vertical-box-bar",		c_vertical_box_bar},

  /* The following routines call actionProc instead of keyProc */

  {"select-start",	f_select_start},
  {"select-adjust",	f_select_adjust},
  {"select-end",	f_select_end},
  {"select-all",	f_select_all},
  {"insert-selection",	f_insert_selection},
  {"zoom",		f_zoom},
  {"iconify",		f_iconify},
  {"set-cursor",	f_set_cursor},
  {"special1",		f_special1},
  {"special2",		f_special2},
  {"special3",		f_special3},
  {"ga3277-clear",	f_ga3277_clear},
  {"ga3277-refresh",	f_ga3277_refresh},
  {"ga3277-set-cursor",	f_ga3277_set_cursor},
  {"image-save",	f_image_save},
  {"image-destroy",	f_image_destroy},
  {"aplonoff",		f_aplonoff},
  {"modlock",		f_modlock},
  {"system",		f_system},
};


static void ClassInitialize(), Initialize(), Realize(), Resize(),
  Redisplay(), Destroy();
static Boolean SetValues();
static int tohex();

Win3270ClassRec win3270ClassRec = {
  /* Core fields */
  { /* superclass		*/	(WidgetClass) &widgetClassRec,
    /* class_name		*/	"Win3270",
    /* widget_size		*/	sizeof(Win3270Rec),
    /* class_initialize		*/	ClassInitialize,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize	  	*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	Realize,
    /* actions			*/	actions,
    /* num_actions		*/	XtNumber(actions),
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	FALSE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	Resize,
    /* expose			*/	Redisplay,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	NULL,
    /* query_geometry		*/	NULL,
    /* display_accelerator      */      XtInheritDisplayAccelerator,
    /* extension                */      NULL,
  },
  /* Win3270 fields */
  { /* empty			*/	0 }
};

WidgetClass win3270WidgetClass = (WidgetClass) &win3270ClassRec;


/* Compilers on some systems can't handle very long character constants,
   so the default translation table string is broken up into pieces.
   This routine puts the pieces together again.  */

static void ClassInitialize()
{
  String table;
  table = (String) XtMalloc(strlen(defaultTranslations) + strlen(tab2) +
			    strlen(tab3) + strlen(tab4) + 1);
  (void) strcpy(table, defaultTranslations);
  strcat(table, tab2);
  strcat(table, tab3);
  strcat(table, tab4);
  win3270ClassRec.core_class.tm_table = table;
}


/*ARGSUSED*/ static void Initialize(request, new)
     Widget request, new;
{
  Win3270Widget xw = (Win3270Widget) new;

  /* On a color display, use a colored background and foreground */
  if (CellsOfScreen(XtScreen(new)) > 2)
    {
      xw->core.background_pixel = xw->win3270.backColor;
      xw->win3270.foreground = xw->win3270.foreColor;
    }

  /* If mouse colors wasn't specified, set to foreground color */
  if (xw->win3270.mouseColor == defColor)
    xw->win3270.mouseColor = xw->win3270.foreground;

  /* Check for special keyboard assignments */
  if (xw->win3270.speckey)
    XtOverrideTranslations(new, XtParseTranslationTable(specialTranslations));

  /* If a key translation file was specified, read it in */
  if (xw->win3270.keyfile) 
    {
      int fd, len;
      char *inbuff, *keybuff, *kptr;

      if ((fd = open(xw->win3270.keyfile, O_RDONLY)) < 0)
	XtWarning("Can't open key translation file");
      else 
	{
	  /* Read the whole file into inbuff */
	  inbuff = XtMalloc(BUFSIZE);
	  len = read(fd, inbuff, BUFSIZE - 1);
	  if (len <= 0) XtError("Error reading from key translation file");
	  close(fd);
	  inbuff[len] = '\0';

	  /* Copy to keybuff, leaving out any comment lines */
	  keybuff = kptr = XtMalloc(BUFSIZE);
	  while (*inbuff)
	    {
	      if (*inbuff == '*' || *inbuff == '#')
		{
		  for (inbuff++; *inbuff && *inbuff != '\n'; inbuff++);
		  if (*inbuff == '\n') inbuff++;
		}
	      else
		{
		  while (*inbuff && *inbuff != '\n') *kptr++ = *inbuff++;
		  if (*inbuff == '\n') *kptr++ = *inbuff++;
		}
	    }
	  *kptr = '\0';

	  /* Load the new translations */
	  XtOverrideTranslations(new, XtParseTranslationTable(keybuff));
	  XtFree(inbuff);
	  XtFree(keybuff);
	}
    }
}


static void Realize(w, value_mask, attributes)
     Widget w;
     Mask *value_mask;
     XSetWindowAttributes *attributes;
{
  Win3270Widget xw = (Win3270Widget) w;
  XColor fcolor, bcolor;

  attributes->cursor = xw->win3270.cursor;
  *value_mask |= CWCursor;

  XtCreateWindow(w, InputOutput, (Visual *) CopyFromParent, *value_mask,
		 attributes);

  /* Set cursor color to the proper value */
  fcolor.pixel = xw->win3270.mouseColor;
  XQueryColor(XtDisplay(w), xw->core.colormap, &fcolor);
  bcolor.pixel = xw->core.background_pixel;
  XQueryColor(XtDisplay(w), xw->core.colormap, &bcolor);
  XRecolorCursor(XtDisplay(w), xw->win3270.cursor, &fcolor, &bcolor);
}


static void Destroy(w)
     Widget w;
{
  XtCallCallbacks(w, XtNdestroyProc, NULL);
  XtRemoveAllCallbacks(w, XtNkeyProc);
  XtRemoveAllCallbacks(w, XtNresizeProc);
  XtRemoveAllCallbacks(w, XtNexposeProc);
  XtRemoveAllCallbacks(w, XtNactionProc);
  XtRemoveAllCallbacks(w, XtNdestroyProc);
}


static void Resize(w)
     Widget w;
{
  XtCallCallbacks(w, XtNresizeProc, NULL);
}


/*ARGSUSED*/ static void Redisplay(w, event, region)
     Widget w;
     XEvent *event;
     Region region;
{
  XtCallCallbacks(w, XtNexposeProc, event);
}


/*ARGSUSED*/ static Boolean SetValues(current, request, new)
     Widget current, request, new;
{
  return False;
}


/*** Action procedures ***/

/* Normal keyboard input */
static void c_string(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  int nbytes;
  char *key, buff[80];

  /* If argument to string() was specified in translation file, then use it */
  if (*n)
    {
      nbytes = strlen(params[0]);
      key = (char *) params[0];
    }

  /* Ignore event if it wasn't a key press */
  else if (event->xany.type != KeyPress) return;

  /* Use the keypress event to get mapping */
  else 
    {
#ifdef LOOKUP_STRING
      KeySym keysym;
      static char keybuff[80];
      key = keybuff;
      nbytes = XLookupString((XKeyPressedEvent *) event, key,
			     sizeof(buff) - 2, &keysym, NULL);

#else
      extern char *XLookupMapping();
      key = XLookupMapping((XKeyPressedEvent *) event, &nbytes);
#endif
      if (!nbytes) return;	/* Ignore dead keys */
    }

  /* Send undefined code for non-printable characters */
  if (key[0] < 32 || key[0] > 126)
    {
      buff[0] = 1;
      buff[1] = k_undefined;
    }

  /* Otherwise send a string */
  else
    {
      if (nbytes > sizeof buff - 2) nbytes = sizeof buff - 2;
      buff[0] = nbytes + 1;
      buff[1] = k_string;
      memcpy(&buff[2], key, nbytes);
    }

  XtCallCallbacks(w, XtNkeyProc, buff);
}


/* APL string functions */
/*ARGSUSED*/ static void c_stringa(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  int nbytes;
  char *key, buff[80];

  /* Argument must be specified in translation file */
  if (!*n) return;
  nbytes = strlen(params[0]);
  key = (char *) params[0];
  if (nbytes > sizeof buff - 2) nbytes = sizeof buff - 2;
  buff[0] = nbytes + 1;
  buff[1] = k_stringa;
  memcpy(&buff[2], key, nbytes);

  XtCallCallbacks(w, XtNkeyProc, buff);
}


/* Underbarred APL alphabet */
/*ARGSUSED*/ static void c_stringa_(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  int nbytes;
  char *key, buff[80];

  /* Argument must be specified in translation file */
  if (!*n) return;
  nbytes = strlen(params[0]);
  key = (char *) params[0];
  if (nbytes > sizeof buff - 2) nbytes = sizeof buff - 2;
  buff[0] = nbytes + 1;
  buff[1] = k_stringa_;
  memcpy(&buff[2], key, nbytes);

  XtCallCallbacks(w, XtNkeyProc, buff);
}

 
/* Raw hex data function */
/*ARGSUSED*/ static void c_hex(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  int j;
  char buff[80];

  if (!*n) return;		/* At least one argument must be specified */
  for (j = 0; j < *n; j++)
    {
      buff[0] = tohex((char *) params[j], &buff[2], sizeof buff - 2) + 1;
      if (buff[0] < 2) return;
      buff[1] = k_hex;
      XtCallCallbacks(w, XtNkeyProc, buff);
    }
}


/* Raw hex data with graphics escape function */
/*ARGSUSED*/ static void c_hex_ge(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  int j;
  char buff[80];

  if (!*n) return;		/* At least one argument must be specified */
  for (j = 0; j < *n; j++)
    {
      buff[0] = tohex((char *) params[j], &buff[2], sizeof buff - 2) + 1;
      if (buff[0] < 2) return;
      buff[1] = k_hex_ge;
      XtCallCallbacks(w, XtNkeyProc, buff);
    }
}


/* Subroutine to convert ASCII hex to binary and return the byte count */
static int tohex(inbuff, outbuff, maxlen)
     char *inbuff, *outbuff;
     int maxlen;
{
  int j, nbytes;
  char *outptr;
  
  nbytes = strlen(inbuff);
  if (nbytes > maxlen) nbytes = maxlen;
  if (!nbytes) return 0;
  
  /* First, translate each nibble from ASCII to binary */
  outptr = outbuff;
  if (nbytes & 1) *outptr++ = 0; /* Assume a leading zero if count is odd */
  for (j = 0; j < nbytes; j++)
    {
      if (inbuff[j] == ' ') continue;
      *outptr = inbuff[j];
      if (*outptr >= '0' && *outptr <= '9') *outptr -= '0';
      else if (*outptr >= 'a' && *outptr <= 'f') *outptr -= 'a' - 10;
      else if (*outptr >= 'A' && *outptr <= 'F') *outptr -= 'A' - 10;
      else return 0;		/* Invalid hex digit */
      outptr++;
    }

  /* Now pack the nibbles */
  nbytes = (outptr - outbuff) / 2;
  for (j = 0; j < nbytes; j++)
    outbuff[j] = (outbuff[j * 2] << 4) + outbuff[j * 2 + 1];
  return nbytes;
}


#define ckey(func, val) \
  /*ARGSUSED*/ static void func(w, event, params, n) \
  Widget w; XEvent *event; String *params; Cardinal *n; \
  { static char buff[] = {1, val}; XtCallCallbacks(w, XtNkeyProc, buff); }

ckey(c_undefined, k_undefined)
ckey(c_cursor_move, k_cursor_move)

ckey(c_up, k_up)
ckey(c_down, k_down)
ckey(c_left, k_left)
ckey(c_right, k_right)
ckey(c_newline, k_newline)
ckey(c_home, k_home)
ckey(c_tab, k_tab)
ckey(c_backtab, k_backtab)
ckey(c_end, k_end)
ckey(c_forward_word, k_forward_word)
ckey(c_backward_word, k_backward_word)

ckey(c_insert, k_insert)
ckey(c_delete, k_delete)
ckey(c_backspace, k_backspace)
ckey(c_kill_word, k_kill_word)
ckey(c_backward_kill_word, k_backward_kill_word)

ckey(c_erase_eof, k_erase_eof)
ckey(c_erase_input, k_erase_input)
ckey(c_dup, k_dup)
ckey(c_field_mark, k_field_mark)
ckey(c_cent, k_cent)

ckey(c_pf1, k_pf1)
ckey(c_pf2, k_pf2)
ckey(c_pf3, k_pf3)
ckey(c_pf4, k_pf4)
ckey(c_pf5, k_pf5)
ckey(c_pf6, k_pf6)
ckey(c_pf7, k_pf7)
ckey(c_pf8, k_pf8)
ckey(c_pf9, k_pf9)
ckey(c_pf10, k_pf10)
ckey(c_pf11, k_pf11)
ckey(c_pf12, k_pf12)
ckey(c_pf13, k_pf13)
ckey(c_pf14, k_pf14)
ckey(c_pf15, k_pf15)
ckey(c_pf16, k_pf16)
ckey(c_pf17, k_pf17)
ckey(c_pf18, k_pf18)
ckey(c_pf19, k_pf19)
ckey(c_pf20, k_pf20)
ckey(c_pf21, k_pf21)
ckey(c_pf22, k_pf22)
ckey(c_pf23, k_pf23)
ckey(c_pf24, k_pf24)

ckey(c_clear, k_clear)
ckey(c_enter, k_enter)
ckey(c_pa1, k_pa1)
ckey(c_pa2, k_pa2)
ckey(c_pa3, k_pa3)
ckey(c_sysreq, k_sysreq)
ckey(c_attn, k_attn)

ckey(c_reset, k_reset)
ckey(c_unlock, k_unlock)
ckey(c_dumpfields, k_dumpfields)
ckey(c_print_screen, k_print_screen)


/*** Functions for assigning APL keys by symbol name in translations ***/

#define akey(func, val) \
  /*ARGSUSED*/ static void func(w, event, params, n) \
  Widget w; XEvent *event; String *params; Cardinal *n; \
  { static char buff[] = {2, k_stringa, val}; \
    XtCallCallbacks(w, XtNkeyProc, buff); }

akey(c_alpha,		0xE0)
akey(c_circle_bar,	0xE9)
akey(c_circle_slope,	0xED)
akey(c_circle_star,	0xB5)
akey(c_circle_stile,	0xE8)
akey(c_circle,		0xEA)
akey(c_del,		0xB7)
akey(c_del_stile,	0xFC)
akey(c_del_tilde,	0xFA)
akey(c_delta,		0xB6)
akey(c_delta_stile,	0xFB)
akey(c_delta_underbar,	0xF7)
akey(c_diamond,		0xD8)
akey(c_dieresis,	0xFE)
akey(c_dieresis_dot,	0xD2)
akey(c_divide,		0xF6)
akey(c_down_arrow,	0xC7)
akey(c_down_carat,	0xEB)
akey(c_down_carat_tilde,0xE7)
akey(c_down_shoe,	0xAC)
akey(c_down_stile,	0xBE)
akey(c_down_tack,	0x9D)
akey(c_down_tack_jot,	0xAF)
akey(c_epsilon,		0xEE)
akey(c_epsilon_underbar,0xD1)
akey(c_equal_underbar,	0xCF)
akey(c_i_beam,		0x9F)
akey(c_iota,		0xEC)
akey(c_iota_underbar,	0xD0)
akey(c_jot,		0xF8)
akey(c_left_arrow,	0xBD)
akey(c_left_bracket,	0x5B)
akey(c_left_shoe,	0xE2)
akey(c_left_tack,	0xD6)
akey(c_not_equal,	0xF4)
akey(c_not_greater,	0xF3)
akey(c_not_less,	0xF2)
akey(c_omega,		0xF9)
akey(c_overbar,		0xFD)
akey(c_quad,		0x90)
akey(c_quad_divide,	0x92)
akey(c_quad_jot,	0xD5)
akey(c_quad_quote,	0x91)
akey(c_quad_slope,	0xD4)
akey(c_quote_dot,	0x21)
akey(c_rho,		0xE6)
akey(c_right_arrow,	0xB8)
akey(c_right_bracket,	0x5D)
akey(c_right_shoe,	0xE3)
akey(c_right_tack,	0xD7)
akey(c_slash_bar,	0xF0)
akey(c_slope,		0x5C)
akey(c_slope_bar,	0xF1)
akey(c_squad,		0xD3)
akey(c_stile,		0x7C)
akey(c_tilde,		0x7E)
akey(c_times,		0xF5)
akey(c_up_arrow,	0xC6)
akey(c_up_carat,	0x5E)
akey(c_up_carat_tilde,	0xE5)
akey(c_up_shoe,		0xEF)
akey(c_up_shoe_jot,	0xE4)
akey(c_up_stile,	0xA9)
akey(c_up_tack,		0x98)
akey(c_up_tack_jot,	0xAE)


/* Underbarred alphabet (now vestigial) */

#define a_key(func, val) \
  static void func(w, event, params, n) \
  Widget w; XEvent *event; String *params; Cardinal *n; \
  { static char buff[] = {2, k_stringa_, val}; \
    XtCallCallbacks(w, XtNkeyProc, buff); }

a_key(c_a_underbar, 0x61)
a_key(c_b_underbar, 0x62)
a_key(c_c_underbar, 0x63)
a_key(c_d_underbar, 0x64)
a_key(c_e_underbar, 0x65)
a_key(c_f_underbar, 0x66)
a_key(c_g_underbar, 0x67)
a_key(c_h_underbar, 0x68)
a_key(c_i_underbar, 0x69)
a_key(c_j_underbar, 0x6A)
a_key(c_k_underbar, 0x6B)
a_key(c_l_underbar, 0x6C)
a_key(c_m_underbar, 0x6D)
a_key(c_n_underbar, 0x6E)
a_key(c_o_underbar, 0x6F)
a_key(c_p_underbar, 0x70)
a_key(c_q_underbar, 0x71)
a_key(c_r_underbar, 0x72)
a_key(c_s_underbar, 0x73)
a_key(c_t_underbar, 0x74)
a_key(c_u_underbar, 0x75)
a_key(c_v_underbar, 0x76)
a_key(c_w_underbar, 0x77)
a_key(c_x_underbar, 0x78)
a_key(c_y_underbar, 0x79)
a_key(c_z_underbar, 0x7A)

/* Box drawing characters */
akey(c_upper_left_box_corner,	0xDA)
akey(c_upper_right_box_corner,	0xBF)
akey(c_lower_left_box_corner,	0xC0)
akey(c_lower_right_box_corner,	0xD9)
akey(c_top_box_tee,		0xC2)
akey(c_bottom_box_tee,		0xC1)
akey(c_left_box_tee,		0xC3)
akey(c_right_box_tee,		0xB4)
akey(c_box_cross,		0xC5)
akey(c_horizontal_box_bar,	0xC4)
akey(c_vertical_box_bar,	0xB3)


/*** Action procedures that aren't keyboard events ***/

#define faction(func, action_type) \
  static void func(w, event, params, n)					\
  Widget w; XEvent *event; String *params; Cardinal *n;			\
  {									\
    XtWin3270Data *data = &((Win3270Widget) w)->win3270.action_data;	\
    data->function = action_type;					\
    if (event->xany.type == ButtonPress ||				\
	event->xany.type == ButtonRelease)				\
      {									\
	data->x = event->xbutton.x;					\
	data->y = event->xbutton.y;					\
      }									\
    else if (event->xany.type == MotionNotify)				\
      {									\
	data->x = event->xmotion.x;					\
	data->y = event->xmotion.y;					\
      }									\
    else								\
      {									\
	data->x = -1;							\
	data->y = -1;							\
      }									\
    XtCallCallbacks(w, XtNactionProc, data);				\
  }

faction(f_select_start,		XtFselectStart)
faction(f_select_adjust,	XtFselectAdjust)
faction(f_select_end,		XtFselectEnd)
faction(f_select_all,		XtFselectAll)
faction(f_insert_selection, 	XtFinsertSelection)
faction(f_zoom,			XtFzoom)
faction(f_iconify,		XtFiconify)
faction(f_set_cursor,		XtFsetCursor)
faction(f_special1,		XtFspecial1)
faction(f_special2,		XtFspecial2)
faction(f_special3,		XtFspecial3)
faction(f_ga3277_clear,		XtFgaClear)
faction(f_ga3277_refresh,	XtFgaRefresh)
faction(f_ga3277_set_cursor,	XtFgaSetCursor)
faction(f_image_save,		XtFimageSave)
faction(f_image_destroy,	XtFimageDestroy)


/* Change APL state */
static void f_aplonoff(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  XtWin3270Data *data = &((Win3270Widget) w)->win3270.action_data;
  data->function = XtFaplonoff;
  data->x = *n ? atoi(params[0]) : 0;
  XtCallCallbacks(w, XtNactionProc, data);
}


/* Change modlock state */
static void f_modlock(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  XtWin3270Data *data = &((Win3270Widget) w)->win3270.action_data;
  if (!*n) return;		/* Argument must be specified */
  data->function = XtFmodlock;
  data->x = atoi(params[0]);
  XtCallCallbacks(w, XtNactionProc, data);
}


/* Run a system command */
static void f_system(w, event, params, n)
     Widget w; XEvent *event; String *params; Cardinal *n;
{
  XtWin3270Data *data = &((Win3270Widget) w)->win3270.action_data;
  if (!*n) return;		/* Argument must be specified */
  data->function = XtFsystem;
  data->params = params[0];
  XtCallCallbacks(w, XtNactionProc, data);
}
