/*
 * Win100/Win600 support module
 * 
 * Copyright (c) 1990, 1991 by
 * William S. Hall
 * 3665 Benton Street  #66
 * Santa Clara, CA 95051
 *
 */

#define NOKANJI
#define NOATOM
#define NOMINMAX
#define NOSOUND
#include <windows.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <ascii.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef WIN600
#include "grterm.h"
#endif
#ifdef COLUMBIA
#include "wktsmt.h"
#include "wkt100.h"
#include "wktdlg.h"
#else
#include "smterm.h"
#include "win600.h"
#include "w600dg.h"
#endif
static void NEAR ShowFKeyString(char * keystr);
static void NEAR LoadClipboardData(HWND hWnd);
static void NEAR RecallSavedParams(HWND hWnd);

void FAR MakeCaret(BOOL make)
{
    HWND hWnd;
    unsigned message;
    WORD wparam;
    LONG lparam;

    if (curproto.type == 'A') {
	hWnd = hWndText;
	message = SMT_CARETFUNCTION;
	wparam = make ? SM_CREATECARET : SM_DESTROYCARET;
	lparam = MAKELONG(MWnd.Cursor,MWnd.CursorType);
        if (IsWindow(hWnd))
            SendMessage(hWnd,message, wparam, lparam);
    }
#ifdef WIN600
    else if (curproto.gtype == AG) {
	hWnd = hWndGraph;
	message = GRT_CARETFUNCTION;
	wparam = make ? GR_CREATECARET : GR_DESTROYCARET;
	lparam = 0;
        if (IsWindow(hWnd))
            SendMessage(hWnd,message, wparam, lparam);
    }
#endif
}

/* repaint main window if iconic */
void NEAR MainWndPaint(HWND hWnd, LPPAINTSTRUCT lpps)
{

    SelectObject(lpps->hdc, MWnd.hBrush);
    FillRect(lpps->hdc, (LPRECT)&lpps->rcPaint, MWnd.hBrush);

    if (IsIconic(hWnd)) {
        RECT rIcon;
	int color = (MWnd.Reverse ? MWnd.BGColor : MWnd.TextColor);
	GetClientRect(hWnd, (LPRECT)&rIcon);
	Rectangle(lpps->hdc, 0,0,rIcon.right, rIcon.bottom);
	SetTextColor(lpps->hdc, ColorTable[color]);
	SetBkMode(lpps->hdc, TRANSPARENT);
        TextOut(lpps->hdc,2,rIcon.bottom/3,(LPSTR)szIcon,strlen(szIcon));
    }
}

/* close communications port */
void CloseCommPort(HWND hWnd, int *pCid)
{

    if (*pCid >=0) {
        if (CloseComm(*pCid) >= 0)
            *pCid = INT_MIN;
	else 
	    ShowMessage(hWnd, IDS_CANNOTCLOSECOM, MB_OK | MB_ICONEXCLAMATION);
    }
}

/* show message box */
int ShowMessage(HWND hWnd, int msgnum, WORD style)
{

    char szMessage[MAXRCSTRLEN];
    
    LoadString(hInst, msgnum, (LPSTR)szMessage,sizeof(szMessage));
    return (MessageBox(hWnd,(LPSTR)szMessage, (LPSTR)szAppName, style));

}

void BroadcastWinIniChange()
{

    SendMessage((HWND)(-1), WM_WININICHANGE, 0, (LONG)(LPSTR)szAppName);
        
}

void NEAR WndCommand(HWND hWnd, WORD wParam, LONG lParam)
{
    HMENU hMenu = GetMenu(hWnd);
    char str[80];

    switch(wParam) {

	case IDM_S_UP:
	    SendMessage(hWndText, SMT_COMMAND, SM_CURSORUP, 1);
	    break;

	case IDM_S_DOWN:
	    SendMessage(hWndText, SMT_COMMAND, SM_CURSORDOWN, 1);
	    break;

	case IDM_S_RIGHT:
	    SendMessage(hWndText, SMT_COMMAND, SM_CURSORRIGHT, 1);
	    break;

	case IDM_S_LEFT:
	    SendMessage(hWndText, SMT_COMMAND, SM_CURSORLEFT, 1);
	    break;

	case IDM_S_HOME:
	    SendMessage(hWndText, SMT_COMMAND, SM_CURSORHOME, 0);
	    break;

	case IDM_C_NUM8:
	case IDM_C_UP:
	    SendMessage(hWndText, SMT_COMMAND, SM_SCROLLBACK,
			MAKELONG(1, TRUE));
	    break;
	    
	case IDM_C_NUM2:
	case IDM_C_DOWN:
	    SendMessage(hWndText, SMT_COMMAND, SM_SCROLLBACK,
			MAKELONG(1, FALSE));
	    break;

	case IDM_C_NUM9:
	case IDM_C_PRIOR:
	    SendMessage(hWndText, SMT_COMMAND, SM_PAGEBACK,
			MAKELONG(1, TRUE));
	    break;	    

	case IDM_C_NUM3:
	case IDM_C_NEXT:
	    SendMessage(hWndText, SMT_COMMAND, SM_PAGEBACK,
			MAKELONG(1, FALSE));
	    break;	    

	case IDM_C_HOME:
	case IDM_C_NUM7:
	    SendMessage(hWndText, SMT_COMMAND, SM_HOMEEND,
			MAKELONG(1, TRUE));
	    break;	    

	case IDM_C_END:
	case IDM_C_NUM1:
	    SendMessage(hWndText, SMT_COMMAND, SM_HOMEEND,
			MAKELONG(1, FALSE));
	    break;	    

	case IDM_MINI:
	    OpenDlgBox(hWnd, (FARPROC)MiniBoxProc, DT_MINI);
	    break;

	case IDM_ABOUT:
	    OpenDlgBox(hWnd, (FARPROC)AboutBoxProc, DT_ABOUT);
	    break;

	case IDM_MODEM:
	    OpenDlgBox(hWnd, (FARPROC)ModemBoxProc, DT_MODEM);
	    break;

	case IDM_DISPLAY:
	    OpenDlgBox(hWnd, (FARPROC)DisplayBoxProc, DT_DISPLAY);
	    break;

	case IDM_GENERAL:
	    OpenDlgBox(hWnd, (FARPROC)GeneralBoxProc, DT_GENERAL);
	    break;

	case IDM_KEYBOARD:
	    OpenDlgBox(hWnd, (FARPROC)KeyboardBoxProc, DT_KEYBOARD);
	    break;

	case IDM_COPYLINES:
	    OpenDlgBox(hWnd, (FARPROC)CopyBoxProc, DT_COPYLINES);
	    break;

	case IDM_FONTS:
	    OpenDlgBox(hWnd, (FARPROC)FontsBoxProc, DT_FONTS);
	    break;

	case IDM_PASTE:
	    LoadClipboardData(hWnd);
	    break;

	case IDM_CLEARCOM:
	    FlushComm(cid,0);
	    FlushComm(cid,1);
	    EscapeCommFunction(cid,SETXON);
	    if (LineState & LINE_ON)
		TransmitCommChar(cid, XON);
	    break;

	case IDM_EDITFKEYS:
	    OpenDlgBox(hWnd, (FARPROC)EditFunctionKeys, DT_EDITFKEYS);
	    break;

	case IDM_RECALLSAVED:
	    RecallSavedParams(hWnd);
	    break;

	case IDM_GETFILE:
	    if (OpenDlgBox(hWnd, (FARPROC)LogFileBoxProc, DT_GETFILE)) {
		LoadString(hInst, IDS_CLOSELOG, str, sizeof(str));
	        ChangeMenu(hMenu,wParam,str,IDM_CLOSEFILE,
						MF_BYCOMMAND | MF_CHANGE);
		DrawMenuBar(hWnd);
	    }
	    break;

	case IDM_CLOSEFILE:
	    if (hLogFile > 0)
		CloseLogFile();
	    LoadString(hInst, IDS_LOGSESSION, str, sizeof(str));
	    ChangeMenu(hMenu,wParam,str,IDM_GETFILE,
						MF_BYCOMMAND | MF_CHANGE);
	    DrawMenuBar(hWnd);
	    break;

	case IDM_HELP_HELP:
	    LoadString(hInst, IDS_WINHELPNAME, str, sizeof(str));
	    WinHelp(hWnd, str, HELP_INDEX, 0L);
	    break;

	case IDM_F5:
	    if (MWnd.BreakEnabled) {
	        if (!BreakState) {
		    BreakState = TRUE;
	            SetCommBreak(cid);
	            SetTimer(hWnd, wParam, 230, (FARPROC)NULL);
	        }
	    }
	    break;

	case IDM_F6:
	case IDM_F7:
	case IDM_F8:
	case IDM_F9:
	case IDM_F11:
	case IDM_F12:
	    ShowFKeyString(szFKey[wParam - IDM_F1]);
	    break;

	case IDM_S_F1:
	case IDM_S_F2:
	case IDM_S_F3:
	case IDM_S_F4:
	    ShowFKeyString(szSFKey[wParam - IDM_S_F1]);
	    break;

	case IDM_S_F5:
	    if (!BreakState) {
	        BreakState = TRUE;
		EscapeCommFunction(cid, CLRDTR);
		EscapeCommFunction(cid, CLRRTS);
	        SetCommBreak(cid);
	        SetTimer(hWnd, wParam, 1800, (FARPROC)NULL);
	    }
	    break;

	case IDM_S_F6:
	case IDM_S_F7:
	case IDM_S_F8:
	case IDM_S_F9:
	case IDM_S_F10:
	case IDM_S_F11:
	case IDM_S_F12:
	    ShowFKeyString(szSFKey[wParam - IDM_S_F1]);
	    break;

	case IDM_C_F1:
	case IDM_C_F2:
	case IDM_C_F3:
	case IDM_C_F4:
	    ShowFKeyString(szCFKey[wParam - IDM_C_F1]);
	    break;

	case IDM_C_F5:		// show answerback message
	    ShowAnswerBack();
	    break;

	case IDM_C_F6:
	case IDM_C_F7:
	case IDM_C_F8:
	case IDM_C_F9:
	case IDM_C_F10:
	case IDM_C_F11:
	case IDM_C_F12:
	    ShowFKeyString(szCFKey[wParam - IDM_C_F1]);
	    break;

	case IDM_CS_F1:
	case IDM_CS_F2:
	case IDM_CS_F3:
	case IDM_CS_F4:
	case IDM_CS_F5:
	case IDM_CS_F6:
	case IDM_CS_F7:
	case IDM_CS_F8:
	case IDM_CS_F9:
	case IDM_CS_F10:
	case IDM_CS_F11:
	case IDM_CS_F12:
	    ShowFKeyString(szCSFKey[wParam - IDM_CS_F1]);
	    break;

	default:
	    (*curproto.spkeys)((int)wParam);
	    break;
    }
}

void ShowAnswerBack()
{
    char str[20];

    LoadString(hInst, IDS_ANSWERBACKKEY, str, sizeof(str));
    ShowFKeyString(str);
}

static void NEAR RecallSavedParams(HWND hWnd)
{
    int result;

    MWnd.AutoAnswer = Initdata.AutoAnswer;
    MWnd.BreakEnabled = Initdata.BreakEnabled;
    MWnd.DeleteKey = Initdata.DeleteKey;
    MWnd.CurKeyMode = Initdata.CursorKeys;
    MWnd.ApplMode = Initdata.AltKeypad;
    MWnd.WarningBell = Initdata.WarningBell;
    MWnd.LFCR = Initdata.LFCR;

    if (curproto.type == 'A') {
	curproto.mask = Initdata.EWidth == 7 ? 0x7f : 0xff;
        SetAlphaParams(Initdata.AlphaEmulation);
    }
    MWnd.BGColor = Initdata.BGColor;
    MWnd.TextColor = Initdata.TextColor;
    MWnd.Reverse = Initdata.ReverseVideo;
    InvertScreen(MWnd.Reverse);
    MWnd.CursorType = Initdata.CursorType;
    MWnd.Cursor = Initdata.Cursor;
    if (MWnd.hWnd == GetFocus())
	MakeCaret(TRUE);

    SendMessage(hWndText,SMT_SETATTRIBUTE,SM_MARGINBELL,
		(LONG)Initdata.MarginBell);

    MWnd.Wrap = Initdata.Wrap;
    SendMessage(hWndText, SMT_SETATTRIBUTE, SM_AUTOWRAP, (LONG)Initdata.Wrap);

    MWnd.ControlRep = Initdata.ControlRep;
    if (MWnd.ControlRep) {
	if (curproto.atype == 52)
  	    vt52SetState(-1);
	else
	    vt100SetState(-1);
        SendMessage(hWndActive, SMT_SETATTRIBUTE, SM_AUTOWRAP, (LONG)TRUE);
    }

    SendMessage(hWndText,SMT_SETATTRIBUTE,SM_SMOOTHSCROLL,
		(LONG)Initdata.SmoothScroll);
    SendMessage(hWndText,SMT_SETATTRIBUTE,SM_SCROLLUNITS,
		(LONG)Initdata.ScrollUnits);

    SetCols(Initdata.TermCols);
    LocalEcho = Initdata.LocalEcho;
    if (Initdata.LocalMode) {
	LineState = LOCAL_ON;
	DoMessage = DoGetMessage;
    } else {
	LineState = LINE_ON + LocalEcho;
	DoMessage = DoPeekMessage;
    }
    CommData.BaudRate = Initdata.BaudRate;
    CommData.ByteSize = Initdata.ByteSize;
    CommData.Parity = Initdata.Parity;
    CommData.StopBits = 
		(BYTE)(Initdata.StopBits == 1 ? ONESTOPBIT : TWOSTOPBITS);
    CommData.fParity = Initdata.fParity;
    CommData.fPeChar = Initdata.fParity;
    CommData.fOutX = CommData.fInX = Initdata.XonXoff;
    CommData.XoffLim = DEFRXQUE - Initdata.XoffLim;
    if ((result = SetCommState((DCB FAR *)&CommData)) < 0)
	ShowMessage(hWnd, result, MB_OK | MB_ICONASTERISK);

}

static void NEAR LoadClipboardData(HWND hWnd)
{
    HANDLE hClipData;
    LPSTR lpClip, lpDest;
    register BYTE ch;
    LONG size;
    HMENU hMenu = GetMenu(hWnd);

    if (OpenClipboard(hWnd)) {
	hClipData = GetClipboardData(CF_TEXT);
	if (GB.hBuf == NULL) {
	    size = GlobalSize(hClipData);
    	    GB.hBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
	    if (GB.hBuf != NULL) {
	        if (lpClip = GlobalLock(hClipData)) {
		    if (lpDest = GlobalLock(GB.hBuf)) {
			GB.lBufHead = GB.lBufTail = 0;
			GB.lBufSize = size;
	                while(ch = *lpClip++) {
		            if ((ch != LF) || ((ch == LF) && (MWnd.LFCR))) {
		                *lpDest++ = ch;
		                GB.lBufTail += 1;
		            }
		        }
			EnableMenuItem(hMenu, IDM_PASTE, MF_GRAYED);
			GlobalUnlock(GB.hBuf);
		    }
		    GlobalUnlock(hClipData);
	        }
            }
	}
 	CloseClipboard();
    }
}

static void NEAR ShowFKeyString(char *keystr)
{

    BYTE buf1[80], buf2[80];
    register int i, j;
    BYTE ch;
    int len = GetPrivateProfileString(szAppName, keystr, "", 
				      buf1, sizeof(buf1), szIniName);

    for (i = 0, j = 0; i < len; i++) {
	if ((ch = buf1[i]) == '$') {
	    ch = buf1[++i];
	    ch = (BYTE)toupper(ch);
	    if (('@' <= ch) && (ch <= '_'))
		ch ^= 64;
	}
	buf2[j++] = ch;
     }
     buf2[j] = NUL;

    WriteToComm(buf2, j);
}

void NEAR WndTimer(HWND hWnd, WORD id)
{

    switch(id) {

	case IDM_F5:
            KillTimer(hWnd, id);
	    ClearCommBreak(cid);
	    BreakState = FALSE;
	    break;

	case IDM_S_F5:
            KillTimer(hWnd, id);
	    ClearCommBreak(cid);
	    EscapeCommFunction(cid, SETDTR);
	    EscapeCommFunction(cid, SETRTS);
	    BreakState = FALSE;
	    break;
    }	    
}

void NEAR WriteClipData()
{

    BYTE FAR *tbuf;
    LONG BufBytesRemaining;
    register int count, room;
    COMSTAT comdata;

    GetCommError(cid, &comdata);
    room = DEFTXQUE - comdata.cbOutQue;
    BufBytesRemaining = GB.lBufTail - GB.lBufHead;
    if ((BufBytesRemaining > 0) && (room > 80)) {
        if (tbuf = GlobalLock(GB.hBuf) + GB.lBufHead) {
	    if (BufBytesRemaining > INT_MAX)
	        count = 80;
	    else
	        count = min(80, (int)LOWORD(BufBytesRemaining));
	    WriteComm(cid, tbuf, count);
	    GB.lBufHead += count;
	    BufBytesRemaining = GB.lBufTail - GB.lBufHead;
            GlobalUnlock(GB.hBuf);
	}
    }
    if (BufBytesRemaining <= 0) {
        GB.hBuf = GlobalFree(GB.hBuf);
	EnableMenuItem(GetMenu(MWnd.hWnd), IDM_PASTE, MF_ENABLED);
    }
}

void WriteToComm(BYTE *buf, int len)
{

    if (LineState & LINE_ON)
	WriteComm(cid, (LPSTR)buf, len);
    if (LineState & LOCAL_ON) {
        CharBuf.ptr = buf;
        CharBuf.len = len;
        pBuf = &CharBuf;
	(*curproto.pf)();
    }
}

void InvertScreen(BOOL flag)
{

    LONG Colors[2];
    FARPROC fp;

    if (flag) {
	Colors[0] = ColorTable[MWnd.BGColor];
	Colors[1] = ColorTable[MWnd.TextColor];
    } else {
	Colors[0] = ColorTable[MWnd.TextColor];
	Colors[1] = ColorTable[MWnd.BGColor];
    }
    DeleteObject(MWnd.hBrush);
    MWnd.hBrush = CreateSolidBrush(Colors[1]);
    
    fp = MakeProcInstance((FARPROC)ColorChange,hInst);
    EnumChildWindows(MWnd.hWnd, fp, (LONG)(LONG FAR *)Colors);
    FreeProcInstance(fp);

    InvalidateRect(MWnd.hWnd, (LPRECT)NULL, TRUE);
}

void IdentifyTerm(short id)
{
    switch(id) {
	case 52:
	    WriteToComm("\033/Z", 3);
	    break;
	case 100:
	    WriteToComm("\033[?1;0c", 7);
	    break;
    }
}

void ReportCursorPos(int r, int c)
{
    char buf[40];
    char intbuf[20];

    memset(buf, 0, sizeof(buf));

    buf[0] = ESC;
    buf[1] = '[';
    itoa(r, intbuf, 10);
    strcat(buf, intbuf);
    buf[strlen(buf)] = ';';
    itoa(c, intbuf, 10);
    strcat(buf, intbuf);
    buf[strlen(buf)] = 'R';
    WriteToComm(buf, strlen(buf));

}

void NEAR ProcessChars(BYTE ch, int count)
{
#define KBDBUFSIZE	32

    register BYTE buf[KBDBUFSIZE + 1];
    int lim = 0;
    register int i;

    if (MWnd.DeleteKey) {
	if (ch == BS)
	    ch = DEL;
	else if (ch == DEL)
	    ch = BS;
    }
	
    do {
	i = 0;
	while (i < KBDBUFSIZE) {
	    buf[i++] = ch;
	    if (MWnd.LFCR && (ch == CR))
		buf[i++] = LF;
	    if (++lim >= count)
		break;
	}
	WriteToComm(buf, i);
    } while (lim < count);
}

void SetCols(WORD cols)
{

    LONG lParam = MAKELONG(MWnd.rect.right, MWnd.rect.bottom);
    LONG range;

    SendMessage(hWndText, SMT_COMMAND, SM_SETCOLS, (LONG)cols);
    if (curproto.type == 'A') {
        if (MWnd.hWnd == GetFocus())
	    MakeCaret(TRUE);
        range = SendMessage(hWndText, SMT_SIZEPARENT, (WORD)hWndText, lParam);
        SetScrollPos(MWnd.hWnd, SB_HORZ, 0, FALSE);
        SetScrollRange(MWnd.hWnd, SB_HORZ, 0, LOWORD(range), TRUE);
    }
}

void NEAR CloseLogFile()
{
     long size = lseek(hLogFile, 0L, SEEK_END);
     hLogFile = close(hLogFile);
     if (size == 0)
	unlink(ofLogFile.szPathName);

}

void FAR pushback()
{
    pBuf->len++;
    pBuf->ptr--;

}

void FAR SetAlphaParams(int type)
{

    curproto.atype = type;

    switch(curproto.atype) {
	case 100:
	default:
	    curproto.pf = vt100;
//	    curproto.mask = 0x7f;
	    curproto.spkeys = ANSISpecialKeys;
	    vt100SetState(0);
	    break;
	case 52:
	    curproto.pf = vt52;
//	    curproto.mask = 0x7f;
	    curproto.spkeys = VT52SpecialKeys;
	    vt52SetState(0);
	    break;
    }
}

int FAR yywrap()
{
    return 1;
}

#if defined(WIN3)
/* 
 * This function replaces printf.
 * To use this function you must load the device driver OX.SYS
 * Do NOT run Windows with redirection to AUX.
 * Use dbf just like printf.  There is no function prototype.
 * Example dbf("function foo %d %s, myint, mystring);
 */
void FAR _cdecl dbs(const char *fmt, ...)
{
    char buf[255];

    va_list arg_ptr;

    va_start(arg_ptr, fmt);
    vsprintf(buf, fmt, arg_ptr);
    va_end(arg_ptr);

    OutputDebugString(buf);

}
#endif

#ifdef WIN600
void NEAR XCSpecialKeys(int item)
{
    WORD index;
    int dist;

    switch (item) {
	case IDM_UP:
	    index = 'D';
	    dist = 1;
	    break;
	case IDM_DOWN:
	     index = 'H';
	     dist = 1;
	     break;
	case IDM_RIGHT:
	    index = 'A';
	     dist = 1;
	     break;
	case IDM_LEFT:
	    index = 'B';
	    dist = 1;
	    break;
	case IDM_HOME:
	    index = 'F';
	    dist = 1;
	    break;
	case IDM_END:
	    index = 'J';
	    dist = 1;
	    break;
	case IDM_PRIOR:
	    index = 'E';
	    dist = 1;
	    break;
	case IDM_NEXT:
	    index = 'I';
	    dist = 1;
	    break;

	case IDM_S_UP:
	    index = 'D';
	    dist = 8;
	    break;
	case IDM_S_DOWN:
	     index = 'H';
	     dist = 8;
	     break;
	case IDM_S_RIGHT:
	    index = 'A';
	     dist = 8;
	     break;
	case IDM_S_LEFT:
	    index = 'B';
	    dist = 8;
	    break;
	case IDM_S_HOME:
	    index = 'F';
	    dist = 8;
	    break;
	case IDM_S_END:
	    index = 'J';
	    dist = 8;
	    break;
	case IDM_S_PRIOR:
	    index = 'E';
	    dist = 8;
	    break;
	case IDM_S_NEXT:
	    index = 'I';
	    dist = 8;
	    break;
	default:
	    return;
	    break;
    }
    SendMessage(hWndActive, GRT_MOVEXHAIR, index, (LONG)dist);
}

void NEAR AGSpecialKeys(int item)
{

    int index;
    BOOL internal = FALSE;

    static char *AGKeys[] = {
        "\v",
	"\n",
	"\t",
	"\b",
	"@",
	"A",
	"B",
	"C",
	"D",
	"E",
	"F",
	"G",
	"H",
	"I",
	"L",
	"<",
	"=",
	">",
	"?",
    };
    
    switch(item) {
	case IDM_UP:
	    internal = TRUE;
	    index = 0;
	    break;

	case IDM_DOWN:
	    internal = TRUE;
	    index = 1;
	    break;

	case IDM_RIGHT:
	    internal = TRUE;
	    index = 2;
	    break;

	case IDM_LEFT:
	    internal = TRUE;
	    index = 3;
	    break;

	case IDM_NUM0:
	    index = 4;
	    break;

	case IDM_NUM1:
	    index = 5;
	    break;

	case IDM_NUM2:
	    index = 6;
	    break;

	case IDM_NUM3:
	    index = 7;
	    break;

	case IDM_NUM4:
	    index = 8;
	    break;

	case IDM_NUM5:
	    index = 9;
	    break;

	case IDM_NUM6:
	    index = 10;
	    break;

	case IDM_NUM7:
	    index = 11;
	    break;

	case IDM_NUM8:
	    index = 12;
	    break;

	case IDM_NUM9:
	    index = 13;
	    break;

	case IDM_DECIMAL:
	    index = 14;
	    break;

	case IDM_F1:
	    index = 15;
	    break;

	case IDM_F2:
	    index = 16;
	    break;

	case IDM_F3:
	    index = 17;
	    break;

	case IDM_F4:
	    index = 18;
	    break;

	default:
	    return;
    }
    if (internal)
	goto local;

    if (LineState & LINE_ON)
	WriteComm(cid, (LPSTR)AGKeys[index], 1);
    if (LineState & LOCAL_ON) {
local:
	CharBuf.ptr = AGKeys[index];
	CharBuf.len = 1;
	pBuf = &CharBuf;
	yylex();
    }
}

void NEAR IPPSpecialKeys(int item)
{

    int index;
    static char *IPPKeys[] = {
	" ",
	"J",
	"H",
	"I",
	"B",
	" ",
	"A",
	"F",
	"D",
	"E",
	"L",
	"J",
	"K",
	"M",
	"<",
	"=",
	">",
	"?",
	"i",
	"j",
	"k",
	"l",
	"m",
	"n"
    };

    switch(item) {
	case IDM_NUM0:
	case IDM_C_NUM0:
	case IDM_S_NUM0:
	case IDM_CS_NUM0:
	    index = 0;
	    break;
	case IDM_NUM1:	
	case IDM_S_NUM1:	
	case IDM_C_NUM1:	
	case IDM_CS_NUM1:	
	    index = 1;
	    break;
	case IDM_NUM2:	
	case IDM_S_NUM2:	
	case IDM_C_NUM2:	
	case IDM_CS_NUM2:	
	    index = 2;
	    break;
	case IDM_NUM3:
	case IDM_S_NUM3:	
	case IDM_C_NUM3:	
	case IDM_CS_NUM3:	
	    index = 3;
	    break;
	case IDM_NUM4:
	case IDM_S_NUM4:	
	case IDM_C_NUM4:	
	case IDM_CS_NUM4:	
	    index = 4;
	    break;
	case IDM_NUM5:
	case IDM_S_NUM5:	
	case IDM_C_NUM5:	
	case IDM_CS_NUM5:	
	    index = 5;
	    break;
	case IDM_NUM6:
	case IDM_S_NUM6:	
	case IDM_C_NUM6:	
	case IDM_CS_NUM6:	
	    index = 6;
	    break;
	case IDM_NUM7:	
	case IDM_S_NUM7:	
	case IDM_C_NUM7:	
	case IDM_CS_NUM7:	
	    index = 7;
	    break;
	case IDM_NUM8:
	case IDM_S_NUM8:	
	case IDM_C_NUM8:	
	case IDM_CS_NUM8:	
	    index = 8;
	    break;
	case IDM_NUM9:
	case IDM_S_NUM9:	
	case IDM_C_NUM9:	
	case IDM_CS_NUM9:	
	    index = 9;
	    break;
	case IDM_DECIMAL:
	case IDM_S_DECIMAL:
	case IDM_C_DECIMAL:
	case IDM_CS_DECIMAL:
	    index = 10;
	    break;
	case IDM_SUBTRACT:
	case IDM_S_SUBTRACT:
	case IDM_C_SUBTRACT:
	case IDM_CS_SUBTRACT:
	    index = 11;
	    break;	    	
	case IDM_ADD:
	case IDM_S_ADD:
	case IDM_C_ADD:
	case IDM_CS_ADD:
	    index = 12;
	    break;
	case IDM_MULTIPLY:
	case IDM_S_MULTIPLY:
	case IDM_C_MULTIPLY:
	case IDM_CS_MULTIPLY:
	    index = 13;
	    break;
	case IDM_F1:
	case IDM_C_F1:
	    index = 14;
	    break;
	case IDM_F2:
	case IDM_C_F2:
	    index = 15;
	    break;
	case IDM_F3:
	case IDM_C_F3:
	    index = 16;
	    break;
	case IDM_F4:
	case IDM_C_F4:
	    index = 17;
	    break;
	case IDM_INSERT:
	    index = 18;
	    break;
	case IDM_HOME:
	    index = 19;
	    break;
	case IDM_PRIOR:
	    index = 20;
	    break;
	case IDM_DELETE:
	    index = 21;
	    break;
	case IDM_END:
	    index = 22;
	    break;
	case IDM_NEXT:
	    index = 23;
	    break;
	default:
	    return;
    }
    WriteToComm(IPPKeys[index], 1);
}

void AnswerEnq(BYTE lead, int mode)
{
    BYTE buffer[10];
    long pos;
    WORD x,y;

    buffer[0] = lead;
    pos = SendMessage(hWndActive, GRT_COMMAND, GR_QUERYPOS, (LONG)mode);
    x = LOWORD(pos);
    buffer[2] = (BYTE)(x & 0x1f) + SP;
    buffer[1] = (BYTE)((x >> 5) & 0x1f) + SP;
    y = HIWORD(pos);
    buffer[4] = (BYTE)(y & 0x1f) + SP;
    buffer[3] = (BYTE)((y >> 5) & 0x1f) + SP;

    buffer[5] = CR;
    buffer[6] = EOT;

    if (LineState & LINE_ON)
        WriteToComm(buffer, 7);
}
#endif

