From: Keith Vetter Date: Tue, 28 Mar 1995 04:51:52 +0000 (+0000) Subject: Added windows/wintel directory for the windows telnet program X-Git-Tag: krb5-1.0-beta5~439 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b947261e618d7519f97e06fe95fd7fb2cc796d52;p=krb5.git Added windows/wintel directory for the windows telnet program git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5278 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/windows/wintel/auth.c b/src/windows/wintel/auth.c new file mode 100644 index 000000000..f3956ac11 --- /dev/null +++ b/src/windows/wintel/auth.c @@ -0,0 +1,626 @@ +/* + * Implements Kerberos 4 authentication + */ + +#include +#include +#ifdef KRB4 + #include "kerberos.h" +#endif +#include "telnet.h" +#include "telopts.h" + +#ifdef KRB5 + #include "krb5.h" + #include "des_int.h" + #include "com_err.h" + #include "los-proto.h" +#endif + +/* + * Contants + */ + #define IS 0 + #define SEND 1 + #define REPLY 2 + #define NAME 3 + + #define AUTH_NULL 0 + #define KERBEROS_V4 1 + #define KERBEROS_V5 2 + #define SPX 3 + #define RSA 6 + #define LOKI 10 + + #define AUTH 0 + #define K4_REJECT 1 + #define K4_ACCEPT 2 + #define K4_CHALLENGE 3 + #define K4_RESPONSE 4 + + #define K5_REJECT 1 + #define K5_ACCEPT 2 + #define K5_RESPONSE 3 + + #define AUTH_WHO_MASK 1 + #define AUTH_CLIENT_TO_SERVER 0 + #define AUTH_SERVER_TO_CLIENT 1 + + #define AUTH_HOW_MASK 2 + #define AUTH_HOW_ONE_WAY 0 + #define AUTH_HOW_MUTUAL 2 + + #ifndef KSUCCESS + #define KSUCCESS 0 + #define KFAILURE 255 + #endif +/* + * Globals + */ + #ifdef KRB4 + static CREDENTIALS cred; + #define KRB_SERVICE_NAME "rcmd" + #define KERBEROS_VERSION KERBEROS_V4 + #endif + #ifdef KRB5 + static krb5_data auth; + static int auth_how; + #define KRB_SERVICE_NAME "host" + #define KERBEROS_VERSION KERBEROS_V5 + #endif + + BOOL encrypt_enable; + +/*+ + * Function: Enable or disable the encryption process. + * + * Parameters: + * enable - TRUE to enable, FALSE to disable. + */ +static void auth_encrypt_enable( + BOOL enable) +{ + encrypt_enable = enable; + +} /* auth_encrypt_enable */ + + +/*+ + * Function: Abort the authentication process + * + * Parameters: + * ks - kstream to send abort message to. + */ +static void auth_abort( + kstream ks, + char *errmsg, + long r) +{ + char buf[9]; + + wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, AUTH_NULL, AUTH_NULL, IAC, SE); + TelnetSend(ks, (LPSTR)buf, 8, 0); + + if (errmsg != NULL) { + strcpy(strTmp, errmsg); + + if (r != KSUCCESS) { + strcat(strTmp, "\n"); + #ifdef KRB4 + lstrcat(strTmp, krb_get_err_text(r)); + #endif + #ifdef KRB5 + lstrcat (strTmp, error_message(r)); + #endif + } + + MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!", MB_OK | MB_ICONEXCLAMATION); + } + +} /* auth_abort */ + + +/*+ + * Function: Copy data to buffer, doubling IAC character if present. + * + * Parameters: + * kstream - kstream to send abort message to. + */ +static int copy_for_net( + unsigned char *to, + unsigned char *from, + int c) +{ + int n; + + n = c; + + while (c-- > 0) { + if ((*to++ = *from++) == IAC) { + n++; + *to++ = IAC; + } + } + + return n; + +} /* copy_for_net */ + + +/*+ + * Function: Parse authentication send command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +static int auth_send( + kstream ks, + unsigned char *parsedat, + int end_sub) +{ + char buf[512]; + char *pname; + int plen; + int r; + int i; + #ifdef KRB4 + KTEXT_ST auth; + char instance[INST_SZ]; + char *realm; + #endif /* KRB4 */ + #ifdef KRB5 + extern int kerberos5_send (int how); + #endif /* KRB5 */ + + auth_how = -1; + + for (i = 2; i+1 <= end_sub; i += 2) { + if (parsedat[i] == KERBEROS_VERSION) + if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER) { + auth_how = parsedat[i+1] & AUTH_HOW_MASK; + break; + } + } + + if (auth_how == -1) { + auth_abort(ks, NULL, 0); + return KFAILURE; + } + + #ifdef KRB4 + memset(instance, 0, sizeof(instance)); + + if (realm = krb_get_phost(szHostName)) + lstrcpy(instance, realm); + + realm = krb_realmofhost(szHostName); + + if (!realm) { + strcpy(buf, "Can't find realm for host \""); + strcat(buf, szHostName); + strcat(buf, "\""); + auth_abort(ks, buf, 0); + return KFAILURE; + } + + r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0); + + if (r == 0) + r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); + + if (r) { + strcpy(buf, "Can't get \""); + strcat(buf, KRB_SERVICE_NAME); + if (instance[0] != 0) { + strcat(buf, "."); + lstrcat(buf, instance); + } + strcat(buf, "@"); + lstrcat(buf, realm); + strcat(buf, "\" ticket"); + auth_abort(ks, buf, r); + return r; + } + + if (szUserName[0]) + pname = szUserName; + else + pname = cred.pname; + plen = strlen (szUserName); + + #endif /* KRB4 */ + + #ifdef KRB5 + r = kerberos5_send (auth_how); + if (! r) + return KFAILURE; + + plen = strlen (szUserName); /* Set in kerberos_5 if needed */ + pname = szUserName; + + #endif /* KRB5 */ + + wsprintf(buf, "%c%c%c%c", IAC, SB, AUTHENTICATION, NAME); + memcpy (&buf[4], pname, plen); + wsprintf(&buf[plen + 4], "%c%c", IAC, SE); + TelnetSend(ks, (LPSTR)buf, lstrlen(pname)+6, 0); + + wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, + KERBEROS_VERSION, auth_how | AUTH_CLIENT_TO_SERVER, AUTH); + + #if KRB4 + auth.length = copy_for_net(&buf[7], auth.dat, auth.length); + #endif /* KRB4 */ + #if KRB5 + auth.length = copy_for_net(&buf[7], auth.data, auth.length); + #endif /* KRB5 */ + + wsprintf(&buf[auth.length+7], "%c%c", IAC, SE); + + TelnetSend(ks, (LPSTR)buf, auth.length+9, 0); + + return KSUCCESS; + +} /* auth_send */ + +/*+ + * Function: Parse authentication reply command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +#ifdef KRB5 +static int auth_reply( + kstream ks, + unsigned char *parsedat, + int end_sub) +{ + extern int kerberos5_reply (int how, unsigned char *data, int cnt); + int n; + + n = kerberos5_reply (0, parsedat, end_sub); + + return n; +} +#endif /* KRB5 */ +#ifdef KRB4 +static int auth_reply( + kstream ks, + unsigned char *parsedat, + int end_sub) +{ + time_t t; + int x; + char buf[512]; + int i; + des_cblock session_key; + des_key_schedule sched; + static des_cblock challenge; + + if (end_sub < 4) + return KFAILURE; + + if (parsedat[2] != KERBEROS_V4) + return KFAILURE; + + if (parsedat[4] == K4_REJECT) { + buf[0] = 0; + + for (i = 5; i <= end_sub; i++) { + if (parsedat[i] == IAC) + break; + buf[i-5] = parsedat[i]; + buf[i-4] = 0; + } + + if (!buf[0]) + strcpy(buf, "Authentication rejected by remote machine!"); + MessageBox(HWND_DESKTOP, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + if (parsedat[4] == K4_ACCEPT) { + if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) + return KSUCCESS; + + if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) + return KFAILURE; + + des_key_sched(cred.session, sched); + + t = time(NULL); + memcpy(challenge, &t, 4); + memcpy(&challenge[4], &t, 4); + des_ecb_encrypt(&challenge, &session_key, sched, 1); + + /* + * Increment the challenge by 1, and encrypt it for + * later comparison. + */ + for (i = 7; i >= 0; --i) { + x = (unsigned int)challenge[i] + 1; + challenge[i] = x; /* ignore overflow */ + if (x < 256) /* if no overflow, all done */ + break; + } + + des_ecb_encrypt(&challenge, &challenge, sched, 1); + + wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, AUTHENTICATION, IS, + KERBEROS_V4, AUTH_CLIENT_TO_SERVER|AUTH_HOW_MUTUAL, K4_CHALLENGE); + memcpy(&buf[7], session_key, 8); + wsprintf(&buf[15], "%c%c", IAC, SE); + TelnetSend(ks, (LPSTR)buf, 17, 0); + + return KSUCCESS; + } + + if (parsedat[4] == K4_RESPONSE) { + if (end_sub < 12) + return KFAILURE; + + if (memcmp(&parsedat[5], challenge, sizeof(challenge)) != 0) { + MessageBox(HWND_DESKTOP, "Remote machine is being impersonated!", + NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + return KSUCCESS; + } + + return KFAILURE; + +} /* auth_reply */ + +#endif /* KRB4 */ +/*+ + * Function: Parse the athorization sub-options and reply. + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - sub-option string to parse. + * + * end_sub - last charcter position in parsedat. + */ +void auth_parse( + kstream ks, + unsigned char *parsedat, + int end_sub) +{ + if (parsedat[1] == SEND) + auth_send(ks, parsedat, end_sub); + + if (parsedat[1] == REPLY) + auth_reply(ks, parsedat, end_sub); + +} /* auth_parse */ + + +/*+ + * Function: Initialization routine called kstream encryption system. + * + * Parameters: + * str - kstream to send abort message to. + * + * data - user data. + */ +int INTERFACE auth_init( + kstream str, + kstream_ptr data) +{ + return 0; + +} /* auth_init */ + + +/*+ + * Function: Destroy routine called kstream encryption system. + * + * Parameters: + * str - kstream to send abort message to. + * + * data - user data. + */ +void INTERFACE auth_destroy( + kstream str) +{ +} /* auth_destroy */ + + +/*+ + * Function: Callback to encrypt a block of characters + * + * Parameters: + * out - return as pointer to converted buffer. + * + * in - the buffer to convert + * + * str - the stream being encrypted + * + * Returns: number of characters converted. + */ +int INTERFACE auth_encrypt( + struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str) +{ + out->ptr = in->ptr; + + out->length = in->length; + + return(out->length); + +} /* auth_encrypt */ + + +/*+ + * Function: Callback to decrypt a block of characters + * + * Parameters: + * out - return as pointer to converted buffer. + * + * in - the buffer to convert + * + * str - the stream being encrypted + * + * Returns: number of characters converted. + */ +int INTERFACE auth_decrypt( + struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str) +{ + out->ptr = in->ptr; + + out->length = in->length; + + return(out->length); + +} /* auth_decrypt */ + +/*+*/ +#ifdef KRB5 + +/* +** +** Code lifted from telnet sample code in the appl directory. +** +*/ + +krb5_auth_context *auth_context; +krb5_flags krb5_kdc_default_options = KDC_OPT_RENEWABLE_OK; + +/* 0 on failure, 1 on success */ +int +kerberos5_send (int how) +{ + krb5_error_code r; + krb5_ccache ccache; + krb5_creds cred; + krb5_creds * new_cred; + extern krb5_flags krb5_kdc_default_options; + krb5_flags ap_opts; + int len; + + if (r = krb5_cc_default(k5_context, &ccache)) { + com_err (NULL, r, "while authorizing."); + return(0); + } + + memset((char *)&cred, 0, sizeof(cred)); + if (r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME, + KRB5_NT_SRV_HST, &cred.server)) { + com_err (NULL, r, "while authorizing."); + return(0); + } + + if (r = krb5_cc_get_principal(k5_context, ccache, &cred.client)) { + com_err (NULL, r, "while authorizing."); + krb5_free_cred_contents(k5_context, &cred); + return(0); + } + if (szUserName[0] == '\0') { /* Get user name now */ + len = krb5_princ_component(k5_context, cred.client, 0)->length; + memcpy (szUserName, + krb5_princ_component(k5_context, cred.client, 0)->data, + len); + szUserName[len] = '\0'; + } + + + if (r = krb5_get_credentials(k5_context, krb5_kdc_default_options, + ccache, &cred, &new_cred)) { + com_err (NULL, r, "while authorizing."); + krb5_free_cred_contents(k5_context, &cred); + return(0); + } + + ap_opts = 0; + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + + r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts, + NULL, new_cred, &auth); + + krb5_free_cred_contents(k5_context, &cred); + krb5_free_creds(k5_context, new_cred); + + if (r) { + com_err (NULL, r, "while authorizing."); + return(0); + } + + return(1); +} +/*+*/ +int +kerberos5_reply (int how, unsigned char *data, int cnt) { + static int mutual_complete = 0; + + data += 4; /* Point to status byte */ + + switch (*data++) { + case K5_REJECT: + if (cnt > 0) + wsprintf (strTmp, + "Kerberos V5 refuses authentication because %.*s", + cnt, data); + else + wsprintf (strTmp, "Kerberos V5 refuses authentication"); + MessageBox (HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + + case K5_ACCEPT: + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) { + wsprintf(strTmp, "Kerberos V5 accepted you, " + "but didn't provide mutual authentication"); + MessageBox (HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION); + return KSUCCESS; + } + + return KSUCCESS; + break; + + case K5_RESPONSE: + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* the rest of the reply should contain a krb_ap_rep */ + krb5_ap_rep_enc_part *reply; + krb5_data inbuf; + krb5_error_code r; + + inbuf.length = cnt; + inbuf.data = (char *)data; + + if (r = krb5_rd_rep (k5_context, auth_context, &inbuf, &reply)) { + com_err (NULL, r, "while authorizing."); + return KFAILURE; + } + krb5_free_ap_rep_enc_part(k5_context, reply); + + mutual_complete = 1; + } + return KSUCCESS; + + default: + return KSUCCESS; // Unknown code + } +} +#endif /* KRB5 */ diff --git a/src/windows/wintel/auth.h b/src/windows/wintel/auth.h new file mode 100644 index 000000000..ddc8b2169 --- /dev/null +++ b/src/windows/wintel/auth.h @@ -0,0 +1,25 @@ +/* + * Implements Kerberos 4 authentication and ecryption + */ + +void auth_parse( + kstream ks, + unsigned char *parsedat, + int end_sub); + +int INTERFACE auth_init( + kstream str, + kstream_ptr data); + +void INTERFACE auth_destroy( + kstream str); + +int INTERFACE auth_encrypt( + struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str); + +int INTERFACE auth_decrypt( + struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str); diff --git a/src/windows/wintel/changelo b/src/windows/wintel/changelo new file mode 100644 index 000000000..9364c5f3e --- /dev/null +++ b/src/windows/wintel/changelo @@ -0,0 +1,8 @@ +Mon Mar 27 20:18:41 1995 Keith Vetter (keithv@fusion.com) + + * Initial release based upon the K4 version. + * K4 streams layer is replaced with no-ops in k5stream.c + * only one-way authentication tested since a telnet daemon which + does mutual is not available. + * connect port is hard-wired to 13131 for now since that is the + port of the only available K5 telnet daemon (tsx-11.mit.edu) diff --git a/src/windows/wintel/dialog.h b/src/windows/wintel/dialog.h new file mode 100644 index 000000000..da4790f74 --- /dev/null +++ b/src/windows/wintel/dialog.h @@ -0,0 +1,31 @@ +#define IDM_ABOUT 100 +#define IDM_SHOWCONSOLE 700 + +#define IDM_OPENTELNETDLG 200 +#define TEL_CONNECT_NAME 201 +#define TEL_USEDEFAULTS 202 +#define TEL_MANUALCONFIGURE 203 +#define TEL_OK 204 +#define TEL_CANCEL 206 +#define CON_SESSIONNAME 302 +#define CON_WINDOWTITLE 304 +#define CON_COLUMNS132 305 +#define CON_COLUMNS80 306 +#define CON_BACKSPACE 307 +#define CON_DELETE 308 +#define CON_CRLF 309 +#define CON_CRNUL 310 +#define CON_BUFFERS 311 +#define CON_SENDS 312 +#define CON_OK 320 +#define CON_USEDEFAULTS 321 +#define CONFIGDLG 300 +#define CON_SCRLBCK 317 +#define CON_NUMLINES 318 +#define PRINTQUEUE 400 +#define IDM_PRINTQUEUE 500 +#define TEL_PUSH1 601 +#define TEL_PUSH2 602 +#define TEL_PUSH3 603 +#define TEL_PUSH4 604 +#define TEL_PUSH5 605 diff --git a/src/windows/wintel/edit.c b/src/windows/wintel/edit.c new file mode 100644 index 000000000..16ac28c24 --- /dev/null +++ b/src/windows/wintel/edit.c @@ -0,0 +1,419 @@ +#include +#include +#include +#include "screen.h" + +char *cInvertedArray; +int bMouseDown=FALSE; +int iLocStart,iLocEnd,bSelection; + +void Edit_LbuttonDown(HWND hWnd,LPARAM lParam) { + SCREEN *fpScr; + HGLOBAL hgScr; + HMENU hMenu; + int iTmp,iXlocStart,iYlocStart; + HDC hDC; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + hDC=GetDC(hWnd); + for (iTmp=0; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + bSelection=FALSE; + hMenu=GetMenu(hWnd); + EnableMenuItem(hMenu,IDM_COPY,MF_GRAYED); + ReleaseDC(hWnd,hDC); + iXlocStart=(int)LOWORD(lParam)/fpScr->cxChar; + if (iXlocStart >= fpScr->width) + iXlocStart = fpScr->width - 1; + iYlocStart=(int)HIWORD(lParam)/fpScr->cyChar; + if (iYlocStart >= fpScr->height) + iYlocStart = fpScr->height - 1; + iLocStart=iXlocStart+(iYlocStart*fpScr->width); + bMouseDown=TRUE; + GlobalUnlock(hgScr); +} + +void Edit_LbuttonUp(HWND hWnd, LPARAM lParam) { + SCREEN *fpScr; + HGLOBAL hgScr; + int iTmp,iTmp2; + HMENU hMenu; + + bMouseDown=FALSE; + if (bSelection) return; + bSelection=TRUE; + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + iTmp=(int)LOWORD(lParam)/fpScr->cxChar; + if (iTmp >= fpScr->width) + iTmp = fpScr->width - 1; + iTmp2=(int)HIWORD(lParam)/fpScr->cyChar; + if (iTmp2 >= fpScr->height) + iTmp2 = fpScr->height - 1; + GlobalUnlock(hgScr); + iLocEnd=iTmp+(iTmp2*fpScr->width); + if (iLocEnd==iLocStart) { + bSelection=FALSE; + } else { + hMenu=GetMenu(hWnd); + EnableMenuItem(hMenu,IDM_COPY,MF_ENABLED); + } +} + +void Edit_MouseMove(HWND hWnd, LPARAM lParam){ + SCREEN *fpScr; + HGLOBAL hgScr; + int iTmp,iTmp2,iXlocCurr,iYlocCurr,iLocCurr,iX,iX2,iY,iY2; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + HDC hDC; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + hDC = GetDC(hWnd); + iXlocCurr=(int)LOWORD(lParam)/fpScr->cxChar; + if (iXlocCurr >= fpScr->width) + iXlocCurr = fpScr->width - 1; + iYlocCurr=(int)HIWORD(lParam)/fpScr->cyChar; + if (iYlocCurr >= fpScr->height) + iYlocCurr = fpScr->height - 1; + iLocCurr=iXlocCurr+(iYlocCurr*fpScr->width); + if (iLocCurr > iLocStart) { + for (iTmp=0; iTmp < iLocStart; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + iX=(iLocStart%fpScr->width); + iY=(int)(iLocStart/fpScr->width); + iX2=(iLocCurr%fpScr->width); + iY2=(int)(iLocCurr/fpScr->width); + if (iY==iY2) { + hgScrLine=GetScreenLineFromY(fpScr,iY); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= iX; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + else { + hgScrLine=GetScreenLineFromY(fpScr,iY); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= iX; iTmp2 < fpScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY)]=fpScrLine->text[iTmp2]; + } + } + for (iTmp=iY+1; iTmp < iY2; iTmp++) { + hgScrLine=GetScreenLineFromY(fpScr,iTmp); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= 0; iTmp2 < fpScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iTmp)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iTmp*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iTmp)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + if (!(iY2==iY)) { + hgScrLine=GetScreenLineFromY(fpScr,iY2); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= 0; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY2)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY2*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY2)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + + } + for (iTmp=iLocCurr; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + } else { /* going backwards */ + for (iTmp=0; iTmp < iLocCurr; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + iX=(iLocCurr%fpScr->width); + iY=(int)(iLocCurr/fpScr->width); + iX2=(iLocStart%fpScr->width); + iY2=(int)(iLocStart/fpScr->width); + if (iY==iY2) { + hgScrLine=GetScreenLineFromY(fpScr,iY); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= iX; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + else { + hgScrLine=GetScreenLineFromY(fpScr,iY); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= iX; iTmp2 < fpScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY)]=fpScrLine->text[iTmp2]; + } + } + for (iTmp=iY+1; iTmp < iY2; iTmp++) { + hgScrLine=GetScreenLineFromY(fpScr,iTmp); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= 0; iTmp2 < fpScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iTmp)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iTmp*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iTmp)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + if (!(iY2==iY)) { + hgScrLine=GetScreenLineFromY(fpScr,iY2); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + for (iTmp2= 0; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2+(fpScr->width*iY2)])&& fpScrLine->text[iTmp2]) { + PatBlt(hDC,(iTmp2)*fpScr->cxChar,iY2*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(fpScr->width*iY2)]=fpScrLine->text[iTmp2]; + } + } + LINE_MEM_UNLOCK(hgScrLine); + } + + } + for (iTmp=iLocStart; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + + } + ReleaseDC(hWnd,hDC); + GlobalUnlock(hgScr); +} + +void Edit_ClearSelection(SCREEN *fpScr) { + int iTmp; + HDC hDC; + HMENU hMenu; + + hDC=GetDC(fpScr->hWnd); + for (iTmp=0; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + bSelection=FALSE; + hMenu=GetMenu(fpScr->hWnd); + EnableMenuItem(hMenu,IDM_COPY,MF_GRAYED); + ReleaseDC(fpScr->hWnd,hDC); +} + +void Edit_Copy(HWND hWnd) { + int iTmp,iIdx; + HGLOBAL hCutBuffer; + LPSTR lpCutBuffer; + SCREEN *fpScr; + HGLOBAL hgScr; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + + hCutBuffer= GlobalAlloc(GHND,(DWORD)(fpScr->width*fpScr->height+1)); + lpCutBuffer= GlobalLock(hCutBuffer); + + if (iLocStart > iLocEnd) { /* swap variables */ + iTmp=iLocStart; + iLocStart=iLocEnd; + iLocEnd=iLocStart; + } + iTmp=iLocStart; + iIdx=0; + while (iTmp < iLocEnd) { + if (!cInvertedArray[iTmp]) { + lpCutBuffer[iIdx++]='\r'; + lpCutBuffer[iIdx++]='\n'; + iTmp= (((int)(iTmp/fpScr->width))+1)*fpScr->width; + continue; + } + lpCutBuffer[iIdx++]=cInvertedArray[iTmp++]; + } + lpCutBuffer[iIdx]=0; + GlobalUnlock(hCutBuffer); + OpenClipboard(hWnd); + EmptyClipboard(); + SetClipboardData(CF_TEXT,hCutBuffer); + CloseClipboard(); +} + +void Edit_Paste(HWND hWnd) { + HGLOBAL hClipMemory; + static HGLOBAL hMyClipBuffer; + LPSTR lpClipMemory,lpMyClipBuffer; + HGLOBAL hgScr; + SCREEN *fpScr; + + if (hMyClipBuffer) GlobalFree(hMyClipBuffer); + OpenClipboard(hWnd); + hClipMemory = GetClipboardData(CF_TEXT); + hMyClipBuffer = GlobalAlloc(GHND,GlobalSize(hClipMemory)); + lpMyClipBuffer= GlobalLock(hMyClipBuffer); + lpClipMemory= GlobalLock(hClipMemory); + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + lstrcpy(lpMyClipBuffer,lpClipMemory); +// OutputDebugString(lpMyClipBuffer); + PostMessage(fpScr->hwndTel,WM_MYSCREENBLOCK,(WPARAM)hMyClipBuffer, + (HSCREEN)hgScr); + CloseClipboard(); + GlobalUnlock(hClipMemory); + GlobalUnlock(hMyClipBuffer); +} + +void Edit_LbuttonDblclk(HWND hWnd,LPARAM lParam) { + HDC hDC; + SCREEN *fpScr; + HGLOBAL hgScr; + int iTmp,iTmp2,iXlocStart,iYloc; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + hDC=GetDC(hWnd); + for (iTmp=0; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + bSelection=FALSE; + iXlocStart=(int)LOWORD(lParam)/fpScr->cxChar; + if (iXlocStart >= fpScr->width) + iXlocStart = fpScr->width - 1; + iYloc=(int)HIWORD(lParam)/fpScr->cyChar; + if (iYloc >= fpScr->height) + iYloc = fpScr->height - 1; + iLocStart=iXlocStart+(iYloc*fpScr->width); + + hgScrLine=GetScreenLineFromY(fpScr,iYloc); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + + iTmp=iXlocStart; + while (isalnum((int)fpScrLine->text[iTmp])) { + PatBlt(hDC,iTmp*fpScr->cxChar,iYloc*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp+(iYloc*fpScr->width)]=fpScrLine->text[iTmp]; + iTmp++; + } + iTmp2=iXlocStart-1; + while (isalnum((int)fpScrLine->text[iTmp2])) { + PatBlt(hDC,iTmp2*fpScr->cxChar,iYloc*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp2+(iYloc*fpScr->width)]=fpScrLine->text[iTmp2]; + iTmp2--; + } + iLocStart=(iTmp2+1)+(iYloc*fpScr->width); + iLocEnd=(iTmp)+(iYloc*fpScr->width); + + bSelection=TRUE; + ReleaseDC(hWnd,hDC); + LINE_MEM_UNLOCK(hgScrLine); + GlobalUnlock(hgScr); +} + +void Edit_TripleClick(HWND hWnd,LPARAM lParam) { + HDC hDC; + SCREEN *fpScr; + HGLOBAL hgScr; + int iTmp,iYloc; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + +// OutputDebugString("Triple Click \r\n"); + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + hDC=GetDC(hWnd); + for (iTmp=0; iTmp < fpScr->width*fpScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC,(iTmp%fpScr->width)*fpScr->cxChar,(int)(iTmp/fpScr->width)*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp]=0; + } + } + bSelection=FALSE; + iYloc=(int)HIWORD(lParam)/fpScr->cyChar; + if (iYloc >= fpScr->height) + iYloc = fpScr->height - 1; + iLocStart=(iYloc*fpScr->width); + + hgScrLine=GetScreenLineFromY(fpScr,iYloc); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + + for (iTmp=0; iTmpwidth; iTmp++) { + if (fpScrLine->text[iTmp]) { + PatBlt(hDC,iTmp*fpScr->cxChar,iYloc*fpScr->cyChar, + fpScr->cxChar,fpScr->cyChar,DSTINVERT); + cInvertedArray[iTmp+(iYloc*fpScr->width)]=fpScrLine->text[iTmp]; + } else break; + } + iLocEnd=(iTmp+(iYloc*fpScr->width)); + + bSelection=TRUE; + ReleaseDC(hWnd,hDC); + LINE_MEM_UNLOCK(hgScrLine); + GlobalUnlock(hgScr); +} diff --git a/src/windows/wintel/emul.c b/src/windows/wintel/emul.c new file mode 100644 index 000000000..027089ebe --- /dev/null +++ b/src/windows/wintel/emul.c @@ -0,0 +1,815 @@ +#include "windows.h" +#include "screen.h" + +/********************************************************************** +* Function : ScreenEmChar +* Purpose : Send a character to the virtual screen with no translantion +* Parameters : + fpScr - pointer top screen +* c - character to send to the virtual screen +* Returns : none +* Calls : +* Called by : ScreenEm() +**********************************************************************/ +static int ScreenEmChar(SCREEN *fpScr,unsigned char c) +{ + int sx; + int insert, + ocount, + attrib, + extra, + offend; + char *acurrent, /* pointer to the attributes for characters drawn */ + *current, /* pointer to the place to put characters */ + *start; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return (-1); + + current=start=&fpScrLine->text[fpScr->x]; + acurrent=&fpScrLine->attrib[fpScr->x]; + + attrib=fpScr->attrib; + insert=fpScr->IRM; /* boolean */ + ocount=fpScr->x; + offend=0; + extra=0; + sx=fpScr->x; + if(fpScr->x>fpScr->width) { + if(fpScr->DECAWM) { /* check for line wrapping on */ + fpScr->x=0; + ScreenIndex(fpScr); + } /* end if */ + else /* no line wrapping */ + fpScr->x=fpScr->width; + current=start=&fpScrLine->text[fpScr->x]; + acurrent=&fpScrLine->attrib[fpScr->x]; + ocount=fpScr->x; + sx=fpScr->x; + } /* end if */ + if(insert) + ScreenInsChar(fpScr,1); + *current=c; + *acurrent=(char)attrib; + if(fpScr->xwidth) { + acurrent++; + current++; + fpScr->x++; + } /* end if */ + else { + if(fpScr->DECAWM) { + fpScr->x++; + offend=1; + } /* end if */ + else { + fpScr->x=fpScr->width; + extra=1; + } /* end else */ + } /* end else */ + if(insert) + ScreenInsString(fpScr,fpScr->x-ocount+offend+extra,start); /* actually just decides which RS to use */ + else + ScreenDraw(fpScr,sx,fpScr->y,fpScr->attrib,fpScr->x-ocount+offend+extra,start); + LINE_MEM_UNLOCK(hgScrLine); +} /* end ScreenEmChar() */ + +void ScreenEm(LPSTR c,int len,HSCREEN hsScr) +{ + HSCREENLINE hgScrLine; + SCREEN *fpScr; + SCREENLINE *fpScrLine; + int escflg; /* vt100 escape level */ + RECT rc; + unsigned int ic; + char stat[20]; + int i; + + fpScr=(SCREEN *) GlobalLock(hsScr); + if (fpScr==NULL) { + OutputDebugString("Screen is hosed.\r\n"); + return; + } + + if (fpScr->screen_bottom != fpScr->buffer_bottom) { + ScreenUnscroll(fpScr); + InvalidateRect(fpScr->hWnd,NULL,TRUE); + SetScrollPos(fpScr->hWnd,SB_VERT,fpScr->numlines,TRUE); + } + + ScreenCursorOff(fpScr); + escflg=fpScr->escflg; + +#ifdef UM +/* @UM */ + if(fpScr->localprint && (len>0)) { /* see if printer needs anything */ + pcount=send_localprint(c,len); + len-=pcount; + c+=pcount; + } /* end if */ +/* @UM */ +#endif + + while(len>0) { + while((*c<32) && (escflg==0) && (len>0)) { /* look at first character in the vt100 string, if it is a non-printable ascii code */ + switch(*c) { + + case 0x1b: /* ESC found (begin vt100 control sequence) */ + escflg++; + break; + + case -1: /* IAC from telnet session */ + escflg=6; + break; + +#ifdef CISB + case 0x05: /* CTRL-E found (answerback) */ + bp_ENQ(); + break; + +#endif + case 0x07: /* CTRL-G found (bell) */ + ScreenBell(fpScr); + break; + + case 0x08: /* CTRL-H found (backspace) */ + ScreenBackspace(fpScr); + break; + + case 0x09: /* CTRL-I found (tab) */ + ScreenTab(fpScr); /* Later change for versatile tabbing */ + break; + + case 0x0a: /* CTRL-J found (line feed) */ + case 0x0b: /* CTRL-K found (treat as line feed) */ + case 0x0c: /* CTRL-L found (treat as line feed) */ + ScreenIndex(fpScr); + break; + case 0x0d: /* CTRL-M found (carriage feed) */ + ScreenCarriageFeed(fpScr); + break; + +#ifdef LATER + case 0x0e: /* CTRL-N found (invoke Graphics (G1) character set) */ + if(fpScr->G1) + fpScr->attrib=VSgraph(fpScr->attrib); + else + fpScr->attrib=VSnotgraph(fpScr->attrib); + fpScr->charset=1; + break; + + case 0x0f: /* CTRL-O found (invoke 'normal' (G0) character set) */ + if(fpScr->G0) + fpScr->attrib=VSgraph(fpScr->attrib); + else + fpScr->attrib=VSnotgraph(fpScr->attrib); + fpScr->charset=0; + break; +#endif +#ifdef CISB + case 0x10: /* CTRL-P found (undocumented in vt100) */ + bp_DLE( c, len); + len=0; + break; +#endif + +#ifdef NOT_USED + case 0x11: /* CTRL-Q found (XON) (unused presently) */ + case 0x13: /* CTRL-S found (XOFF) (unused presently) */ + case 0x18: /* CTRL-X found (CAN) (unused presently) */ + case 0x1a: /* CTRL-Z found (SUB) (unused presently) */ + break; +#endif + } /* end switch */ + c++; /* advance to the next character in the string */ + len--; /* decrement the counter */ + } /* end while */ + + if(escflg==0) { /* check for normal character to print */ + while((len>0) && (*c>=32)) { /* print out printable ascii chars, if we haven't found an ESCAPE char */ + int sx; + int insert, + ocount, + attrib, + extra, + offend; + char *acurrent, /* pointer to the attributes for characters drawn */ + *current, /* pointer to the place to put characters */ + *start; + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return; + + current=start=&fpScrLine->text[fpScr->x]; + acurrent=&fpScrLine->attrib[fpScr->x]; + attrib=fpScr->attrib; + insert=fpScr->IRM; /* boolean */ + ocount=fpScr->x; + offend=0; + extra=0; + sx=fpScr->x; + if(fpScr->x>fpScr->width) { + if(fpScr->DECAWM) { /* check for line wrapping on */ + fpScr->x=0; + ScreenIndex(fpScr); + } /* end if */ + else /* no line wrapping */ + fpScr->x=fpScr->width; + current=start=&fpScrLine->text[fpScr->x]; + acurrent=&fpScrLine->attrib[fpScr->x]; + ocount=fpScr->x; + sx=fpScr->x; + } /* end if */ + while((len>0) && (*c>=32) && (offend==0)) { + if(insert) + ScreenInsChar(fpScr,1); + *current=*c; + *acurrent=(char)attrib; + c++; + len--; + if(fpScr->xwidth) { + acurrent++; + current++; + fpScr->x++; + } /* end if */ + else { + if(fpScr->DECAWM) { + fpScr->x++; + offend=1; + } /* end if */ + else { + fpScr->x=fpScr->width; + extra=1; + } /* end else */ + } /* end else */ + } /* end while */ + if (insert) + ScreenInsString(fpScr,fpScr->x-ocount+offend+extra,start); /* actually just decides which RS to use */ + else + ScreenDraw(fpScr,sx,fpScr->y,fpScr->attrib,fpScr->x-ocount+offend+extra,start); + } /* end while */ + } /* end if */ + + while((len>0) && (escflg==1)) { /* ESC character was found */ + switch(*c) { + case 0x08: /* CTRL-H found (backspace) */ + ScreenBackspace(fpScr); + break; + + case '[': /* mostly cursor movement options, and DEC private stuff following */ +// OutputDebugString("["); + ScreenApClear(fpScr); + escflg=2; + break; + + case '#': /* various screen adjustments */ +// OutputDebugString("#"); + escflg=3; + break; + + case '(': /* G0 character set options */ +// OutputDebugString("("); + escflg=4; + break; + + case ')': /* G1 character set options */ +// OutputDebugString(")"); + escflg=5; + break; + + case '>': /* keypad numeric mode (DECKPAM) */ +// OutputDebugString(">"); + fpScr->DECPAM=0; + escflg=0; + break; + + case '=': /* keypad application mode (DECKPAM) */ +// OutputDebugString("="); + fpScr->DECPAM=1; + escflg=0; + break; + + case '7': /* save cursor (DECSC) */ +// OutputDebugString("7!"); + ScreenSaveCursor(fpScr); + escflg=0; + break; + + case '8': /* restore cursor (DECRC) */ +// OutputDebugString("8!"); + ScreenRestoreCursor(fpScr); + escflg=0; + break; +#ifdef LATER + case 'c': /* reset to initial state (RIS) */ + ScreenReset(fpScr); + escflg=0; + break; +#endif + case 'D': /* index (move down one line) (IND) */ + ScreenIndex(fpScr); + escflg=0; + break; + + case 'E': /* next line (move down one line and to first column) (NEL) */ +// OutputDebugString("E!"); + fpScr->x=0; + ScreenIndex(fpScr); + escflg=0; + break; + + case 'H': /* horizontal tab set (HTS) */ +// OutputDebugString("H!"); + fpScr->tabs[fpScr->x]='x'; + escflg=0; + break; + +#ifdef CISB + case 'I': /* undoumented in vt100 */ + bp_ESC_I(); + break; + +#endif + + case 'M': /* reverse index (move up one line) (RI) */ +// OutputDebugString("M!"); + ScreenRevIndex(fpScr); + escflg=0; + break; + + case 'Z': /* identify terminal (DECID) */ + OutputDebugString("Screen Send Ident- Not implemented! \r\n"); +// ScreenSendIdent(fpScr); + + escflg=0; + break; + + default: + ScreenEmChar(fpScr,0x1b); /* put the ESC character into the Screen */ + ScreenEmChar(fpScr,*c); /* put the next character into the Screen */ + escflg=0; + break; + + } /* end switch */ + c++; + len--; + } /* end while */ + while((escflg==2) && (len>0)) { /* '[' handling */ + switch(*c) { + case 0x08: /* backspace */ + ScreenBackspace(fpScr); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* numeric parameters */ + if(fpScr->parms[fpScr->parmptr]<0) + fpScr->parms[fpScr->parmptr]=0; + fpScr->parms[fpScr->parmptr]*=10; + fpScr->parms[fpScr->parmptr]+=*c-'0'; + break; + + case '?': /* vt100 mode change */ + fpScr->parms[fpScr->parmptr++]=(-2); + break; + + case ';': /* parameter divider */ + fpScr->parmptr++; + break; + + case 'A': /* cursor up (CUU) */ +// OutputDebugString("A"); + rc.left=((fpScr->x)*(fpScr->cxChar)); + rc.right=(((fpScr->x)+1)*(fpScr->cxChar)); + rc.top=((fpScr->cyChar)*(fpScr->y)); + rc.bottom=((fpScr->cyChar)*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +// OutputDebugString("[2A]"); + if(fpScr->parms[0]<1) + fpScr->y--; + else + fpScr->y-=fpScr->parms[0]; + if(fpScr->ytop) + fpScr->y=fpScr->top; + ScreenRange(fpScr); + escflg=0; + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); + break; + + case 'B': /* cursor down (CUD) */ +// OutputDebugString("B"); + rc.left=((fpScr->x)*(fpScr->cxChar)); + rc.right=(((fpScr->x)+1)*(fpScr->cxChar)); + rc.top=((fpScr->cyChar)*(fpScr->y)); + rc.bottom=((fpScr->cyChar)*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +// OutputDebugString("[2B]"); + if(fpScr->parms[0]<1) + fpScr->y++; + else + fpScr->y+=fpScr->parms[0]; + if(fpScr->y>fpScr->bottom) + fpScr->y=fpScr->bottom; + ScreenRange(fpScr); + escflg=0; + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); + break; + + case 'C': /* cursor forward (right) (CUF) */ +// OutputDebugString("C"); + rc.left=((fpScr->x)*(fpScr->cxChar)); + rc.right=(((fpScr->x)+1)*(fpScr->cxChar)); + rc.top=((fpScr->cyChar)*(fpScr->y)); + rc.bottom=((fpScr->cyChar)*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +// OutputDebugString("[2C]"); + if(fpScr->parms[0]<1) + fpScr->x++; + else + fpScr->x+=fpScr->parms[0]; + ScreenRange(fpScr); + if(fpScr->x>fpScr->width) + fpScr->x=fpScr->width; + escflg=0; + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); + break; + + case 'D': /* cursor backward (left) (CUB) */ +// OutputDebugString("D"); + rc.left=((fpScr->x)*(fpScr->cxChar)); + rc.right=(((fpScr->x)+1)*(fpScr->cxChar)); + rc.top=((fpScr->cyChar)*(fpScr->y)); + rc.bottom=((fpScr->cyChar)*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +// OutputDebugString("[2D]"); + if(fpScr->parms[0]<1) + fpScr->x--; + else + fpScr->x-=fpScr->parms[0]; + ScreenRange(fpScr); + escflg=0; + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); + break; + + case 'f': /* horizontal & vertical position (HVP) */ + case 'H': /* cursor position (CUP) */ +// OutputDebugString("fH"); + rc.left=((fpScr->x)*(fpScr->cxChar)); + rc.right=(((fpScr->x)+1)*(fpScr->cxChar)); + rc.top=((fpScr->cyChar)*(fpScr->y)); + rc.bottom=((fpScr->cyChar)*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +// OutputDebugString("[2H]"); + fpScr->x=fpScr->parms[1]-1; + fpScr->y=fpScr->parms[0]-1; + ScreenRange(fpScr); /* make certain the cursor position is valid */ + escflg=0; + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); + break; + + case 'J': /* erase in display (ED) */ +// OutputDebugString("J"); + switch(fpScr->parms[0]) { + case -1: + case 0: /* erase from active position to end of screen */ + ScreenEraseToEndOfScreen(fpScr); + break; + case 1: /* erase from start of screen to active position */ + OutputDebugString("[Screen Erase to Position- Not Implemented!]\r\n"); +// ScreenEraseToPosition(fpScr); + break; + + case 2: /* erase whole screen */ +// OutputDebugString("2"); + ScreenEraseScreen(fpScr); + break; + + default: + break; + } /* end switch */ + escflg=0; + break; + + case 'K': /* erase in line (EL) */ +// OutputDebugString("K"); + switch(fpScr->parms[0]) { + case -1: + case 0: /* erase to end of line */ +// OutputDebugString("0"); + ScreenEraseToEOL(fpScr); + break; + + case 1: /* erase to beginning of line */ +// OutputDebugString("1"); + ScreenEraseToBOL(fpScr); + break; + + case 2: /* erase whole line */ +// OutputDebugString("2"); + ScreenEraseLine(fpScr,-1); + break; + + default: + break; + } /* end switch */ + escflg=0; + break; + + case 'L': /* insert n lines preceding current line (IL) */ +// OutputDebugString("L"); + if(fpScr->parms[0]<1) + fpScr->parms[0]=1; + ScreenInsLines(fpScr,fpScr->parms[0],-1); + escflg=0; + break; + + case 'M': /* delete n lines from current position downward (DL) */ +// OutputDebugString("M"); + if(fpScr->parms[0]<1) + fpScr->parms[0]=1; + ScreenDelLines(fpScr,fpScr->parms[0],-1); + escflg=0; + break; + + case 'P': /* delete n chars from cursor to the left (DCH) */ +// OutputDebugString("P"); + if(fpScr->parms[0]<1) + fpScr->parms[0]=1; + ScreenDelChars(fpScr,fpScr->parms[0]); + escflg=0; + break; + +#ifdef NOT_NEEDED + case 'R': /* receive cursor position status from host */ + break; +#endif +#ifdef LATER + case 'c': /* device attributes (DA) */ + ScreenSendIdent(); + escflg=0; + break; +#endif + case 'g': /* tabulation clear (TBC) */ +// OutputDebugString("g"); + if(fpScr->parms[0]==3) /* clear all tabs */ + ScreenTabClear(fpScr); + else + if(fpScr->parms[0]<=0) /* clear tab stop at active position */ + fpScr->tabs[fpScr->x]=' '; + escflg=0; + break; + + case 'h': /* set mode (SM) */ +// OutputDebugString("h"); +// ScreenSetOption(fpScr,1); + escflg=0; + break; + + + case 'i': /* toggle printer */ +// if(fpScr->parms[fpScr->parmptr]==5) +// fpScr->localprint=1; +// else if(fpScr->parms[fpScr->parmptr]==4) +// fpScr->localprint=0; + escflg=0; + break; + + case 'l': /* reset mode (RM) */ +// OutputDebugString("l"); +// ScreenSetOption(fpScr,0); + escflg=0; + break; + + case 'm': /* select graphics rendition (SGR) */ +// OutputDebugString("m"); + { + int temp=0; + + while(temp<=fpScr->parmptr) { + if(fpScr->parms[temp]<1) + fpScr->attrib&=128; + else + fpScr->attrib|=(1<<(fpScr->parms[temp]-1)); + temp++; + } /* end while */ + } /* end case */ + escflg=0; + break; + + case 'n': /* device status report (DSR) */ + switch(fpScr->parms[0]) { +#ifdef NOT_SUPPORTED + case 0: /* response from vt100; ready, no malfunctions */ + case 3: /* response from vt100; malfunction, retry */ +#endif + case 5: /* send status */ + case 6: /* send active position */ + wsprintf(stat, "\033[%d;%dR", fpScr->y, fpScr->x); + for (i = 0; stat[i]; i++) + SendMessage(fpScr->hwndTel,WM_MYSCREENCHAR,stat[i],hsScr); + break; + } /* end switch */ + escflg=0; + break; + + case 'q': /* load LEDs (unsupported) (DECLL) */ + escflg=0; + break; + + case 'r': /* set top & bottom margins (DECSTBM) */ + if(fpScr->parms[0]<0) + fpScr->top=0; + else + fpScr->top=fpScr->parms[0]-1; + if(fpScr->parms[1]<0) + fpScr->bottom=fpScr->height-1; + else + fpScr->bottom=fpScr->parms[1]-1; + if(fpScr->top<0) + fpScr->top=0; + if(fpScr->top>fpScr->height-1) + fpScr->top=fpScr->height-1; + if(fpScr->bottom<1) + fpScr->bottom=fpScr->height; + if(fpScr->bottom>=fpScr->height) + fpScr->bottom=fpScr->height-1; + if(fpScr->top>=fpScr->bottom) { /* check for valid scrolling region */ + if(fpScr->bottom>=1) /* assume the bottom value has precedence, unless it is as the top of the screen */ + fpScr->top=fpScr->bottom-1; + else /* totally psychotic case, bottom of screen set to the very top line, move the bottom to below the top */ + fpScr->bottom=fpScr->top+1; + } /* end if */ + fpScr->x=0; + fpScr->y=0; +#ifdef NOT_SUPPORTED + if (fpScr->DECORG) + fpScr->y=fpScr->top; /* origin mode relative */ +#endif + escflg=0; + break; + +#ifdef NOT_SUPPORTED + case 'x': /* request/report terminal parameters (DECREQTPARM/DECREPTPARM) */ + case 'y': /* invoke confidence test (DECTST) */ + break; +#endif + default: /* Dag blasted strays... */ + escflg=0; + break; + + } /* end switch */ + c++; + len--; + +#ifdef NOT +/* @UM */ + if(fpScr->localprint && (len>0)) { /* see if printer needs anything */ + pcount=send_localprint(c,len); + len-=pcount; + c+=pcount; + } /* end if */ +/* @UM */ +#endif + } /* end while */ + while((escflg==3) && (len>0)) { /* # Handling */ + switch(*c) { + case 0x08: /* backspace */ + ScreenBackspace(fpScr); + break; + +#ifdef NOT_SUPPORTED + case '3': /* top half of double line (DECDHL) */ + case '4': /* bottom half of double line (DECDHL) */ + case '5': /* single width line (DECSWL) */ + case '6': /* double width line (DECDWL) */ + break; +#endif + case '8': /* screen alignment display (DECALN) */ + ScreenAlign(fpScr); +// OutputDebugString("8"); + escflg=0; + break; + default: + escflg=0; + break; + + } /* end switch */ + c++; + len--; + } /* end while */ + while((escflg==4) && (len>0)) { /* ( Handling (GO character set) */ + switch(*c) { + case 0x08: /* backspace */ + ScreenBackspace(fpScr); + break; + +#ifdef LATER + case 'A': /* united kingdom character set (unsupported) */ + case 'B': /* ASCII character set */ + case '1': /* choose standard graphics (same as ASCII) */ + fpScr->G0=0; + if(!fpScr->charset) + fpScr->attrib=ScreenNotGraph(fpScr->attrib); + escflg=0; + break; + + case '0': /* choose special graphics set */ + case '2': /* alternate character set (special graphics) */ + fpScr->G0=1; + if(!fpScr->charset) + fpScr->attrib=ScreenGraph(fpScr->attrib); + escflg=0; + break; +#endif + default: + escflg=0; + break; + } /* end switch */ + c++; + len--; + } /* end while */ + while((escflg==5) && (len>0)) { /* ) Handling (G1 handling) */ + switch(*c) { + case 0x08: /* backspace */ + ScreenBackspace(fpScr); + break; + +#ifdef LATER + case 'A': /* united kingdom character set (unsupported) */ + case 'B': /* ASCII character set */ + case '1': /* choose standard graphics (same as ASCII) */ + fpScr->G1=0; + if(fpScr->charset) + fpScr->attrib=ScreenNotGraph(fpScr->attrib); + escflg=0; + break; + + case '0': /* choose special graphics set */ + case '2': /* alternate character set (special graphics) */ + fpScr->G1=1; + if(fpScr->charset) + fpScr->attrib=ScreenGraph(fpScr->attrib); + escflg=0; + break; +#endif + default: + escflg=0; + break; + } /* end switch */ + c++; + len--; + } /* end while */ + + while((escflg>=6) && (escflg<=10) && (len>0)) { /* Handling IAC */ + ic = (unsigned char) *c; + switch (escflg) { + + case 6: /* Handling IAC xx */ + if (ic == 255) /* if IAC */ + escflg=0; + else if (ic == 250) /* if SB */ + escflg=7; + else + escflg=9; + break; + + case 7: /* Handling IAC SB xx */ + if (ic == 255) /* if IAC */ + escflg=8; + break; + + case 8: /* Handling IAC SB IAC xx */ + if (ic == 255) /* if IAC IAC */ + escflg=7; + else if (ic == 240) /* if IAC SE */ + escflg=0; + break; + + case 9: /* IAC xx xx */ + escflg=0; + break; + } + c++; /* advance to the next character in the string */ + len--; /* decrement the counter */ + } + + if((escflg>2 && escflg<6) && (len>0)) { + escflg=0; + c++; + len--; + } /* end if */ + } /* end while */ + fpScr->escflg=escflg; + ScreenCursorOn(fpScr); + GlobalUnlock(hsScr); +} /* end ScreenEm() */ diff --git a/src/windows/wintel/font.c b/src/windows/wintel/font.c new file mode 100644 index 000000000..9bdb00ec0 --- /dev/null +++ b/src/windows/wintel/font.c @@ -0,0 +1,128 @@ +#include +#include +#include "screen.h" +#include "ini.h" + +LOGFONT lf; +HFONT hFont; +char szStyle[LF_FACESIZE]; + +void ProcessFontChange(HWND hWnd) { + static DWORD dwFontColor; /* Color of font if one has been selected */ + CHOOSEFONT cf; + HDC hDC; + SCREEN *fpScr; + HGLOBAL hgScr; + TEXTMETRIC tm; + char buf[16]; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + cf.lStructSize = sizeof(cf); + cf.hwndOwner = hWnd; + cf.lpLogFont = (LPLOGFONT)&(fpScr->lf); + cf.lpszStyle = szStyle; + cf.Flags = CF_INITTOLOGFONTSTRUCT; // | CF_USESTYLE; + cf.Flags |= CF_SCREENFONTS; +// cf.Flags |= CF_ANSIONLY; + cf.Flags |= CF_FORCEFONTEXIST; + cf.Flags |= CF_FIXEDPITCHONLY; + cf.Flags |= CF_NOSIMULATIONS; + + if (ChooseFont(&cf)) { + if (fpScr->ghSelectedFont) DeleteObject(fpScr->ghSelectedFont); + + fpScr->ghSelectedFont = CreateFontIndirect((LPLOGFONT)&(fpScr->lf)); + fpScr->lf.lfUnderline=TRUE; + fpScr->ghSelectedULFont= CreateFontIndirect((LPLOGFONT)&(fpScr->lf)); + fpScr->lf.lfUnderline=FALSE; + hDC=GetDC(hWnd); + SelectObject(hDC,fpScr->ghSelectedFont); + GetTextMetrics(hDC,(LPTEXTMETRIC)&tm); + + fpScr->cxChar = tm.tmAveCharWidth; + fpScr->cyChar = tm.tmHeight+ tm.tmExternalLeading; + ReleaseDC(hWnd,hDC); + SetWindowPos(hWnd,NULL,0,0, fpScr->cxChar * fpScr->width + + FRAME_WIDTH, fpScr->cyChar * fpScr->height + + FRAME_HEIGHT, SWP_NOMOVE|SWP_NOZORDER); + + dwFontColor=RGB(255, 255, 255); + InvalidateRect(hWnd, NULL, TRUE); + } + + WritePrivateProfileString(INI_FONT,"FaceName",fpScr->lf.lfFaceName,TELNET_INI); + wsprintf(buf,"%d",(int)fpScr->lf.lfHeight); + WritePrivateProfileString(INI_FONT,"Height",buf,TELNET_INI); + wsprintf(buf,"%d",(int)fpScr->lf.lfWidth); + WritePrivateProfileString(INI_FONT,"Width",buf,TELNET_INI); + wsprintf(buf,"%d",(int)fpScr->lf.lfEscapement); + WritePrivateProfileString(INI_FONT,"Escapement",buf,TELNET_INI); + wsprintf(buf,"%d",(int)fpScr->lf.lfCharSet); + WritePrivateProfileString(INI_FONT,"CharSet",buf,TELNET_INI); + wsprintf(buf,"%d",(int)fpScr->lf.lfPitchAndFamily); + WritePrivateProfileString(INI_FONT,"PitchAndFamily",buf,TELNET_INI); + + GlobalUnlock(hgScr); + return; +} + +void NEAR InitializeStruct(WORD wCommDlgType, LPSTR lpStruct, HWND hWnd) +{ + LPCHOOSEFONT lpFontChunk; + + switch (wCommDlgType) + { + case IDC_FONT: + + lpFontChunk = (LPCHOOSEFONT)lpStruct; + + lpFontChunk->lStructSize = sizeof(CHOOSEFONT); + lpFontChunk->hwndOwner = hWnd; + +//The hDC field will be initialized when we return--this avoids passing +//the hDC in or getting the DC twice. +//The LOGFONT field will also be initialized when we get back. +// lpFontChunk->hDC = hDC; +// lpFontChunk->lpLogFont = &lf; + + lpFontChunk->Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | + CF_INITTOLOGFONTSTRUCT | CF_APPLY; + lpFontChunk->rgbColors = RGB(0, 0, 255); + lpFontChunk->lCustData = 0L; + lpFontChunk->lpfnHook = NULL; + lpFontChunk->lpTemplateName = (LPSTR)NULL; + lpFontChunk->hInstance = (HANDLE)NULL; + lpFontChunk->lpszStyle = (LPSTR)NULL; + lpFontChunk->nFontType = SCREEN_FONTTYPE; + lpFontChunk->nSizeMin = 0; + lpFontChunk->nSizeMax = 0; + break; + default: + break; + } + return; +} + +LPSTR NEAR AllocAndLockMem(HANDLE *hChunk, WORD wSize) { + LPSTR lpChunk; + + *hChunk = GlobalAlloc(GMEM_FIXED, wSize); + if (*hChunk) { + lpChunk = GlobalLock(*hChunk); + if (!lpChunk) { + GlobalFree(*hChunk); + ReportError(IDC_LOCKFAIL); + lpChunk=NULL; + } + } else { + ReportError(IDC_ALLOCFAIL); + lpChunk=NULL; + } + return(lpChunk); +} + + diff --git a/src/windows/wintel/ini.h b/src/windows/wintel/ini.h new file mode 100644 index 000000000..d391c8a86 --- /dev/null +++ b/src/windows/wintel/ini.h @@ -0,0 +1,16 @@ +/* Defines INI file vocabulary */ +#define TELNET_INI "kerberos.ini" + + #define INI_TELNET "Telnet" + #define INI_FONT "Font" + #define INI_WIDTH "Width" + #define INI_HEIGHT "Height" + #define INI_POSITION "Position" + #define INI_BACKSPACE "Backspace" + #define INI_BACKSPACE_BS "BS" + #define INI_BACKSPACE_DEL "DEL" + + #define INI_HOSTS "Telnet Hosts" + #define INI_HOST "Host" + #define INI_HOST_BS "BS" + #define INI_HOST_DEL "DEL" diff --git a/src/windows/wintel/intern.c b/src/windows/wintel/intern.c new file mode 100644 index 000000000..d2ec5fc37 --- /dev/null +++ b/src/windows/wintel/intern.c @@ -0,0 +1,837 @@ +#include +#include +#include "screen.h" +#define ScreenClearAttrib 0 + +HSCREENLINE GetScreenLineFromY(SCREEN *fpScr,int y) +{ + HSCREENLINE hgScrLine,hgScrLineTmp; + SCREENLINE *fpScrLine; + int idx; + + hgScrLine=fpScr->screen_top; + for (idx=0; idxheight; idx++) { + if (idx==y) return(hgScrLine); + fpScrLine=LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return (NULL); + hgScrLineTmp=fpScrLine->next; + LINE_MEM_UNLOCK(hgScrLine); + hgScrLine=hgScrLineTmp; + } + return(NULL); +} + +HSCREENLINE ScreenClearLine(SCREEN *fpScr,HSCREENLINE hgScrLine) +{ + SCREENLINE *fpScrLine; + + fpScrLine=LINE_MEM_LOCK(hgScrLine); + memset(fpScrLine->attrib, ScreenClearAttrib, fpScr->width); + memset(fpScrLine->text, ' ', fpScr->width); + LINE_MEM_UNLOCK(hgScrLine); + return(hgScrLine); +} + +void ScreenUnscroll(SCREEN *fpScr) +{ + int idx; + HSCREENLINE hgScrLine,hgScrLineTmp; + SCREENLINE *fpScrLine; + + if (fpScr->screen_bottom == fpScr->buffer_bottom) + return; + + fpScr->screen_bottom=fpScr->buffer_bottom; + hgScrLine=fpScr->screen_bottom; + for (idx = 1; idx < fpScr->height; idx++) { + fpScrLine=LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) + return; + hgScrLineTmp=fpScrLine->prev; + LINE_MEM_UNLOCK(hgScrLine); + hgScrLine=hgScrLineTmp; + } + fpScr->screen_top=hgScrLine; +} + +void ScreenCursorOn(SCREEN *fpScr) +{ + int y; + int nlines; + + if (fpScr->screen_bottom != fpScr->buffer_bottom) + nlines = fpScr->numlines - GetScrollPos(fpScr->hWnd, SB_VERT); + else + nlines = 0; + + y = fpScr->y + nlines; + SetCaretPos(fpScr->x * fpScr->cxChar, (y+1) * fpScr->cyChar); + ShowCaret(fpScr->hWnd); +} + +void ScreenCursorOff(SCREEN *fpScr) +{ + HideCaret(fpScr->hWnd); +} + +void ScreenELO(SCREEN *fpScr,int s) +{ + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + +/* fpScrrapnow(&i,&j); */ + if(s<0) + s=fpScr->y; + + hgScrLine=GetScreenLineFromY(fpScr,s); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + memset(fpScrLine->attrib, ScreenClearAttrib, fpScr->width); + memset(fpScrLine->text, ' ', fpScr->width); + LINE_MEM_UNLOCK(hgScrLine); + rc.left=0; + rc.right=(fpScr->width*fpScr->cxChar); + rc.top=(fpScr->cyChar*s); + rc.bottom=(fpScr->cyChar*(s+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); +} + +void ScreenEraseScreen(SCREEN *fpScr) +{ + int i; + int x1=0,y1=0; + int x2=fpScr->width,y2=fpScr->height; + int n=(-1); + + for(i=0; iheight; i++) + ScreenELO(fpScr,i); + InvalidateRect(fpScr->hWnd,NULL,TRUE); + UpdateWindow(fpScr->hWnd); +} + +void ScreenTabClear(SCREEN *fpScr) +{ + int x=0; + + while(x<=fpScr->width) { + fpScr->tabs[x]=' '; + x++; + } /* end while */ +} + +void ScreenTabInit(SCREEN *fpScr) +{ + int x=0; + + ScreenTabClear(fpScr); + + while(x<=fpScr->width) { + fpScr->tabs[x]='x'; + x+=8; + } /* end while */ + fpScr->tabs[fpScr->width]='x'; +} + +void ScreenReset(SCREEN *fpScr) +{ + fpScr->top=0; + fpScr->bottom=fpScr->height-1; + fpScr->parmptr=0; + fpScr->escflg=0; + fpScr->DECAWM=1; + fpScr->DECCKM=0; + fpScr->DECPAM=0; +/* fpScr->DECORG=0; */ +/* fpScr->Pattrib=-1; */ + fpScr->IRM=0; + fpScr->attrib=0; + fpScr->x=0; + fpScr->y=0; +// fpScr->charset=0; + ScreenEraseScreen(fpScr); + ScreenTabInit(fpScr); +// set_vtwrap(fpScrn,fpScr->DECAWM); /* QAK - 7/27/90: added because resetting the virtual screen's wrapping flag doesn't reset telnet window's wrapping */ +} + + +void ScreenListMove(HSCREENLINE hTD,HSCREENLINE hBD,HSCREENLINE hTI,HSCREENLINE hBI) +{ + HSCREENLINE hTmpLine; + SCREENLINE *TD,*BD,*TI,*BI,*tmpLine; + +// OutputDebugString("ScreenListMove"); + TD= (SCREENLINE *)GlobalLock(hTD); + BD= (SCREENLINE *)GlobalLock(hBD); + TI= (SCREENLINE *)GlobalLock(hTI); + BI= (SCREENLINE *)GlobalLock(hBI); + + if(TD->prev!=NULL) { + hTmpLine=TD->prev; + tmpLine=(SCREENLINE *)GlobalLock(hTmpLine); + tmpLine->next=BD->next; /* Maintain circularity */ + GlobalUnlock(hTmpLine); + } + if(BD->next!=NULL) { + hTmpLine=BD->next; + tmpLine=(SCREENLINE *)GlobalLock(hTmpLine); + tmpLine->prev=TD->prev; + GlobalUnlock(hTmpLine); + } + TD->prev=hTI; /* Place the node in its new home */ + BD->next=hBI; + if(TI!=NULL) + TI->next=hTD; /* Ditto prev->prev */ + if(BI!=NULL) + BI->prev=hBD; + + GlobalUnlock(hTD); + GlobalUnlock(hBD); + GlobalUnlock(hTI); + GlobalUnlock(hBI); +} + + +void ScreenDelLines(SCREEN *fpScr, int n, int s) +{ + HSCREENLINE hBI,hTI,hTD,hBD; + SCREENLINE *TI; + SCREENLINE *BD; + HSCREENLINE hLine; + SCREENLINE *fpLine; + HSCREENLINE hTemp; + int idx; + RECT rc; + HDC hDC; + + if (s < 0) + s = fpScr->y; + + if (s + n - 1 > fpScr->bottom) + n = fpScr->bottom - s + 1; + + hTD = GetScreenLineFromY(fpScr, s); + hBD = GetScreenLineFromY(fpScr, s + n - 1); + hTI = GetScreenLineFromY(fpScr, fpScr->bottom); + TI= LINE_MEM_LOCK(hTI); + hBI = TI->next; + LINE_MEM_UNLOCK(hTI); + + /* + Adjust the top of the screen and buffer if they will move. + */ + if (hTD == fpScr->screen_top) { + BD = LINE_MEM_LOCK(hBD); + if (fpScr->screen_top == fpScr->buffer_top) + fpScr->buffer_top = BD->next; + fpScr->screen_top = BD->next; + LINE_MEM_UNLOCK(hBD); + } + + /* + Adjust the bottom of the screen and buffer if they will move. + */ + if (hTI == fpScr->screen_bottom) { + if (fpScr->screen_bottom == fpScr->buffer_bottom) + fpScr->buffer_bottom = hBD; + fpScr->screen_bottom = hBD; + } + + if (hTI != hBD) + ScreenListMove(hTD, hBD, hTI, hBI); + + /* + Clear the lines moved from the deleted area to the + bottom of the scrolling area. + */ + hLine = hTI; + + for (idx = 0; idx < n; idx++) { + fpLine = LINE_MEM_LOCK(hLine); + hTemp = fpLine->next; + LINE_MEM_UNLOCK(hLine); + hLine = hTemp; + ScreenClearLine(fpScr, hLine); + } + +// CheckScreen(fpScr); + + /* + Scroll the affected area on the screen. + */ + rc.left = 0; + rc.right = fpScr->width * fpScr->cxChar; + rc.top = s * fpScr->cyChar; + rc.bottom = (fpScr->bottom + 1) * fpScr->cyChar; + + hDC = GetDC(fpScr->hWnd); + + ScrollDC(hDC, 0, -fpScr->cyChar * n, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, (fpScr->bottom - n + 1) * fpScr->cyChar, + fpScr->width * fpScr->cxChar, n * fpScr->cyChar, WHITENESS); + + ReleaseDC(fpScr->hWnd, hDC); + +} /* ScreenDelLines */ + + +void ScreenInsertLine(SCREEN *fpScr, int s) +{ + ScreenInsLines(fpScr, 1, s); +} /* ScreenInsertLine */ + + +void ScreenInsLines(SCREEN *fpScr, int n, int s) +{ + HSCREENLINE hLine; + HSCREENLINE hTemp; + HSCREENLINE hTI; + HSCREENLINE hBI; + HSCREENLINE hTD; + HSCREENLINE hBD; + SCREENLINE *fpLine; + SCREENLINE *BI; + SCREENLINE *TD; + int idx; + RECT rc; + HDC hDC; + +// wsprintf(strTmp, "ScreenInsLine (n=%d s=%d)", n, s); +// OutputDebugString(strTmp); + + if (s < 0) + s = fpScr->y; + + if (s + n - 1 > fpScr->bottom) + n = fpScr->bottom - s + 1; + + /* + Determine the top and bottom of the insert area. Also determine + the top and bottom of the area to be deleted and moved to the + insert area. + */ + hBI = GetScreenLineFromY(fpScr, s); + BI = LINE_MEM_LOCK(hBI); + hTI = BI->prev; + hTD = GetScreenLineFromY(fpScr, fpScr->bottom - n + 1); + hBD = GetScreenLineFromY(fpScr, fpScr->bottom); + + /* + Adjust the top of the screen and buffer if they will move. + */ + if (hBI == fpScr->screen_top) { + if (fpScr->screen_top == fpScr->buffer_top) + fpScr->buffer_top = hTD; + fpScr->screen_top = hTD; + } + + /* + Adjust the bottom of the screen and buffer if they will move. + */ + if (hBD == fpScr->screen_bottom) { + TD = LINE_MEM_LOCK(hTD); + if (fpScr->screen_bottom == fpScr->buffer_bottom) + fpScr->buffer_bottom = TD->prev; + fpScr->screen_bottom = TD->prev; + LINE_MEM_UNLOCK(hTD); + } + + /* + Move lines from the bottom of the scrolling region to the insert area. + */ + if (hTD != hBI) + ScreenListMove(hTD,hBD,hTI,hBI); + + /* + Clear the inserted lines + */ + hLine = GetScreenLineFromY(fpScr, s); + + for (idx = 0; idx < n; idx++) { + ScreenClearLine(fpScr, hLine); + fpLine = LINE_MEM_LOCK(hLine); + hTemp = fpLine->next; + LINE_MEM_UNLOCK(hLine); + hLine = hTemp; + } + +// CheckScreen(fpScr); + + /* + Scroll the affected area on the screen. + */ + rc.left = 0; + rc.right = fpScr->width * fpScr->cxChar; + rc.top = s * fpScr->cyChar; + rc.bottom = (fpScr->bottom + 1) * fpScr->cyChar; + + hDC = GetDC(fpScr->hWnd); + + ScrollDC(hDC, 0, fpScr->cyChar * n, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, s * fpScr->cyChar, + fpScr->width * fpScr->cxChar, n * fpScr->cyChar, WHITENESS); + + ReleaseDC(fpScr->hWnd, hDC); + +} /* ScreenInsLines */ + + +void ScreenIndex(SCREEN * fpScr) +{ + if(fpScr->y>=fpScr->bottom) + ScreenScroll(fpScr); + else + fpScr->y++; +} + +void ScreenWrapNow(SCREEN *fpScr,int *xp,int *yp) +{ + if(fpScr->x > fpScr->width) { + fpScr->x=0; + ScreenIndex(fpScr); + } /* end if */ + *xp=fpScr->x; + *yp=fpScr->y; +} + +void ScreenEraseToEOL(SCREEN *fpScr) +{ + int x1=fpScr->x,y1=fpScr->y; + int x2=fpScr->width,y2=fpScr->y; + int n=(-1); + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + + ScreenWrapNow(fpScr,&x1,&y1); + y2=y1; +// wsprintf(strTmp,"[EraseEOL:%d]",y2); +// OutputDebugString(strTmp); + hgScrLine=GetScreenLineFromY(fpScr,y2); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + memset(&fpScrLine->attrib[x1], ScreenClearAttrib, fpScr->width-x1+1); + memset(&fpScrLine->text[x1], ' ', fpScr->width-x1+1); + LINE_MEM_UNLOCK(hgScrLine); + rc.left=x1*fpScr->cxChar; + rc.right=(fpScr->width*fpScr->cxChar); + rc.top=(fpScr->cyChar*y1); + rc.bottom=(fpScr->cyChar*(y1+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); + UpdateWindow(fpScr->hWnd); +} + +void ScreenDelChars(SCREEN *fpScr, int n) +{ + int x = fpScr->x; + int y = fpScr->y; + int width; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + + hgScrLine = GetScreenLineFromY(fpScr, y); + fpScrLine = LINE_MEM_LOCK(hgScrLine); + + width = fpScr->width - x - n; + + if (width > 0) { + memmove(&fpScrLine->attrib[x], &fpScrLine->attrib[x + n], width); + memmove(&fpScrLine->text[x], &fpScrLine->text[x + n], width); + } + + memset(&fpScrLine->attrib[fpScr->width - n], ScreenClearAttrib, n); + memset(&fpScrLine->text[fpScr->width - n], ' ', n); + + LINE_MEM_UNLOCK(hgScrLine); + + rc.left = x * fpScr->cxChar; + rc.right = fpScr->width * fpScr->cxChar; + rc.top = fpScr->cyChar * y; + rc.bottom = fpScr->cyChar * (y + 1); + + InvalidateRect(fpScr->hWnd, &rc, TRUE); + + UpdateWindow(fpScr->hWnd); +} + +void ScreenRevIndex(SCREEN *fpScr) +{ + HSCREENLINE hgScrLine,hTopLine; + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + hTopLine=GetScreenLineFromY(fpScr,fpScr->top); + + if(hgScrLine==hTopLine) + ScreenInsertLine(fpScr,fpScr->y); + else + fpScr->y--; +} + +void ScreenEraseToBOL(SCREEN *fpScr) +{ + int x1=0,y1=fpScr->y; + int x2=fpScr->x,y2=fpScr->y; + int n=(-1); + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + + ScreenWrapNow(fpScr,&x2,&y1); + y2=y1; + memset(fpScrLine->attrib, ScreenClearAttrib, x2); + memset(fpScrLine->text, ' ', x2); + LINE_MEM_UNLOCK(hgScrLine); +} + +void ScreenEraseLine(SCREEN *fpScr,int s) +{ + int x1=0,y1=s; + int x2=fpScr->width,y2=s; + int n=(-1); + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + + if(s<0) { + ScreenWrapNow(fpScr,&x1,&y1); + s=y2=y1; + x1=0; + } /* end if */ + + hgScrLine=GetScreenLineFromY(fpScr,y1); + fpScrLine=LINE_MEM_LOCK(hgScrLine); + memset(fpScrLine->attrib, ScreenClearAttrib, fpScr->width); + memset(fpScrLine->text, ' ', fpScr->width); + LINE_MEM_UNLOCK(hgScrLine); + rc.left=0; + rc.right=(fpScr->width*fpScr->cxChar); + rc.top=(fpScr->cyChar*y1); + rc.bottom=(fpScr->cyChar*(y1+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); +} + +void ScreenEraseToEndOfScreen(SCREEN *fpScr) +{ + register int i; + int x1=0,y1=fpScr->y+1; + int x2=fpScr->width,y2=fpScr->height; + int n=(-1); + + ScreenWrapNow(fpScr,&x1,&y1); + y1++; + x1=0; + i=y1; + ScreenEraseToEOL(fpScr); + while(iheight) { + ScreenELO(fpScr,i); + ScreenEraseLine(fpScr,i); + i++; + } /* end while */ +} + +void ScreenRange(SCREEN *fpScr) /* check and resolve range errors on x and y */ +{ + int wrap=0; + + if(fpScr->DECAWM) + wrap=1; + if(fpScr->x<0) + fpScr->x=0; + if(fpScr->x>(fpScr->width+wrap)) + fpScr->x=fpScr->width+wrap; + if(fpScr->y<0) + fpScr->y=0; + if(fpScr->y>=fpScr->height) + fpScr->y=fpScr->height-1; +} + +void ScreenAlign(SCREEN *fpScr) /* vt100 alignment, fill screen with 'E's */ +{ + char *tt; + register int i,j; + HSCREENLINE hgScrLine,hgScrLineTmp; + SCREENLINE *fpScrLine; + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->top); + ScreenEraseScreen(fpScr); /* erase the screen */ + + for(j=0; jheight; j++) { + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + tt=&fpScrLine->text[0]; + for(i=0; i<=fpScr->width; i++) + *tt++='E'; + hgScrLineTmp=fpScrLine->next; + LINE_MEM_UNLOCK(hgScrLine); + hgScrLine=hgScrLineTmp; + + } /* end for */ + LINE_MEM_UNLOCK(hgScrLine); +} + +/* reset all the ANSI parameters back to the default state */ +void ScreenApClear(SCREEN *fpScr) +{ + for(fpScr->parmptr=5; fpScr->parmptr>=0; fpScr->parmptr--) + fpScr->parms[fpScr->parmptr]=-1; + fpScr->parmptr=0; +} + +void ScreenSetOption(SCREEN *fpScr,int toggle) { +// int WindWidth=(fpScr->width - 1); + + switch(fpScr->parms[0]) { + case -2: + switch(fpScr->parms[1]) { + case 1: /* set/reset cursor key mode */ + fpScr->DECCKM=toggle; + break; + +#ifdef NOT_SUPPORTED + case 2: /* set/reset ANSI/vt52 mode */ + break; +#endif + + case 3: /* set/reset column mode */ + fpScr->x=fpScr->y=0; /* Clear the screen, mama! */ + ScreenEraseScreen(fpScr); + #if 0 /* removed for variable screen size */ + if(toggle) /* 132 column mode */ + fpScr->width=fpScr->allwidth; + else + fpScr->width=79; + #endif + break; + +#ifdef NOT_SUPPORTED + case 4: /* set/reset scrolling mode */ + case 5: /* set/reset screen mode */ + case 6: /* set/rest origin mode */ + fpScr->DECORG = toggle; + break; +#endif + + case 7: /* set/reset wrap mode */ + fpScr->DECAWM=toggle; +// set_vtwrap(fpScrn,fpScr->DECAWM); /* QAK - 7/27/90: added because resetting the virtual screen's wrapping flag doesn't reset telnet window's wrapping */ + break; + +#ifdef NOT_SUPPORTED + case 8: /* set/reset autorepeat mode */ + case 9: /* set/reset interlace mode */ + break; +#endif + + default: + break; + } /* end switch */ + break; + + case 4: + fpScr->IRM=toggle; + break; + + default: + break; + + } /* end switch */ +} + +#ifdef NOT_SUPPORTED +void ScreenTab(SCREEN *fpScr) +{ + if(fpScr->x>=fpScr->width) + fpScr->x=fpScr->width; + fpScr->x++; + while((fpScr->tabs[fpScr->x] != 'x') && (fpScr->x < fpScr->width)) + fpScr->x++; +} +#endif + +int ScreenInsChar(SCREEN *fpScr,int x) +{ + int i; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + +// ScreenWrapNow(&i,&j); /* JEM- Why is this here? comment out for now */ + +// OutputDebugString("OOPS-InsChar!"); + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return (-1); + + for(i=fpScr->width-x; i>=fpScr->x; i--) { + fpScrLine->text[x+i]=fpScrLine->text[i]; + fpScrLine->attrib[x+i]=fpScrLine->attrib[i]; + } /* end for */ + + memset(&fpScrLine->attrib[fpScr->x], ScreenClearAttrib, x); + memset(&fpScrLine->text[fpScr->x], ' ', x); + + for(i=fpScr->x; ix+x; i++) { + fpScrLine->text[i]=' '; + fpScrLine->attrib[i]=ScreenClearAttrib; + } /* end for */ + LINE_MEM_UNLOCK(hgScrLine); + rc.left= (fpScr->cxChar*x); + rc.right= ((fpScr->cxChar*x)+(fpScr->cxChar*(x+fpScr->x))); + rc.top=(fpScr->cyChar*((fpScr->y)-1)); + rc.bottom=(fpScr->cyChar*(fpScr->y)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); +} + +void ScreenInsString(SCREEN *fpScr,int len,char *start) +{ + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + int idx; + RECT rc; + + if(fpScr->VSIDC) return; /* Call RSinsstring which does nothing? */ + + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return; + + for(idx=fpScr->x; idxx+len; idx++) { + fpScrLine->text[idx]=start[idx]; + fpScrLine->attrib[idx]=fpScr->attrib; + } /* end for */ + LINE_MEM_UNLOCK(hgScrLine); + rc.left= (fpScr->cxChar*fpScr->x); + rc.right= ((fpScr->cxChar*fpScr->x)+(fpScr->cxChar*(fpScr->x+len))); + rc.top=(fpScr->cyChar*(fpScr->y)); + rc.bottom=(fpScr->cyChar*(fpScr->y+1)); + + InvalidateRect(fpScr->hWnd,&rc,TRUE); + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); +} + +void ScreenSaveCursor(SCREEN *fpScr) +{ + fpScr->Px=fpScr->x; + fpScr->Py=fpScr->y; + fpScr->Pattrib=fpScr->attrib; +} + +void ScreenRestoreCursor(SCREEN *fpScr) +{ + fpScr->x=fpScr->Px; + fpScr->y=fpScr->Py; + ScreenRange(fpScr); +} + +void ScreenDraw(SCREEN *fpScr,int x,int y,int a,int len,char *c) +{ + int idx; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + RECT rc; + + hgScrLine=GetScreenLineFromY(fpScr,y); + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) { + OutputDebugString("fpScrLine==NULL"); + return; + } + + for(idx=x; idx<(x+len); idx++) { + fpScrLine->text[idx]=c[idx-x]; + fpScrLine->attrib[idx-x]=a; + } + LINE_MEM_UNLOCK(hgScrLine); + + rc.left= (fpScr->cxChar*x); + rc.right= (fpScr->cxChar*(x+len)); + rc.top=(fpScr->cyChar*(fpScr->y)); + rc.bottom=(fpScr->cyChar*((fpScr->y)+1)); + InvalidateRect(fpScr->hWnd,&rc,TRUE); + SendMessage(fpScr->hWnd,WM_PAINT,NULL,NULL); +} + +#ifdef _DEBUG + + BOOL CheckScreen(SCREEN *fpScr) + { + HSCREENLINE hLine; + HSCREENLINE hLinePrev; + SCREENLINE *fpLine; + int nscreen = 0; + int nbuffer = 0; + int topline = 0; + char buf[512]; + BOOL bBottom; + BOOL bOK; + + hLine = fpScr->buffer_top; + + if (hLine == NULL) { + OutputDebugString("CheckScreen: buffer_top invalid"); + MessageBox(NULL, "buffer_top invalid", "CheckScreen", MB_OK); + return(FALSE); + } + + bBottom = FALSE; + while (TRUE) { + hLinePrev = hLine; + if (nscreen > 0 || hLine == fpScr->screen_top) + if (!bBottom) + nscreen++; + nbuffer++; + if (hLine == fpScr->screen_top) + topline = nbuffer - 1; + if (hLine == fpScr->screen_bottom) + bBottom = TRUE; + fpLine = LINE_MEM_LOCK(hLine); + hLine = fpLine->next; + LINE_MEM_UNLOCK(hLine); + if (hLine == NULL) + break; + fpLine = LINE_MEM_LOCK(hLine); + if (fpLine->prev != hLinePrev) { + wsprintf(buf, + "Previous ptr of line %d does not match next ptr of line %d", + nbuffer, nbuffer - 1); + OutputDebugString(buf); + MessageBox(NULL, buf, "CheckScreen", MB_OK); + } + LINE_MEM_UNLOCK(hLine); + } + + if (hLinePrev == fpScr->buffer_bottom && nscreen == fpScr->height) + bOK = TRUE; + else { + OutputDebugString("CheckScreen: Invalid number of lines on screen"); + bOK = FALSE; + } + + wsprintf(buf, \ + "screen.width = %d\n" + "screen.height = %d\n" + "screen.maxlines = %d\n" + "screen.numlines = %d\n" + "screen.x = %d\n" + "screen.y = %d\n" + "screen.top = %d\n" + "screen.bottom = %d\n" + "Actual top line = %d\n" + "Actual buffer lines = %d\n" + "Actual screen lines = %d\n" + "Bottom of buffer is %s", + fpScr->width, fpScr->height, fpScr->maxlines, fpScr->numlines, + fpScr->x, fpScr->y, fpScr->top, fpScr->bottom, + topline, nbuffer, nscreen, + (hLinePrev == fpScr->buffer_bottom) ? "valid" : "invalid"); + + MessageBox(NULL, buf, "CheckScreen", MB_OK); + + return(bOK); + } + +#endif diff --git a/src/windows/wintel/k5stream.c b/src/windows/wintel/k5stream.c new file mode 100644 index 000000000..3745ed5a1 --- /dev/null +++ b/src/windows/wintel/k5stream.c @@ -0,0 +1,63 @@ +/*+************************************************************************* +** +** K5stream +** +** Emulates the kstream package in Kerberos 4 +** +***************************************************************************/ + +#include +#include +#include +#include "telnet.h" +#include "k5stream.h" +#include "auth.h" + +int +kstream_destroy (kstream ks) { + if (ks != NULL) { + auth_destroy (ks); /* Destroy authorizing */ + + closesocket (ks->fd); /* Close the socket??? */ + free (ks); + } + return 0; +} + +void +kstream_set_buffer_mode (kstream ks, int mode) { +} + + +kstream +kstream_create_from_fd (int fd, + const struct kstream_crypt_ctl_block __far *ctl, + kstream_ptr data) +{ + kstream ks; + int n; + + ks = malloc (sizeof(kstream *)); + if (ks == NULL) + return NULL; + + ks->fd = fd; + + n = auth_init (ks, data); /* Initialize authorizing */ + if (n) { + free (ks); + return NULL; + } + + return ks; +} + +int +kstream_write (kstream ks, void __far *p_data, size_t p_len) { + int n; + + n = send (ks->fd, p_data, p_len, 0); /* Write the data */ + + return n; /* higher layer does retries */ +} + diff --git a/src/windows/wintel/k5stream.h b/src/windows/wintel/k5stream.h new file mode 100644 index 000000000..0a9ce0808 --- /dev/null +++ b/src/windows/wintel/k5stream.h @@ -0,0 +1,52 @@ +/* Header file for encrypted-stream library. + * Written by Ken Raeburn (Raeburn@Cygnus.COM). + * Copyright (C) 1991, 1992, 1994 by Cygnus Support. + * + * Permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation. + * Cygnus Support makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef K5STREAM_H +#define K5STREAM_H + +typedef struct { /* Object we pass around */ + int fd; /* Open socket descriptor */ +} *kstream; + +typedef void *kstream_ptr; /* Data send on the kstream */ + +struct kstream_data_block { + kstream_ptr ptr; + size_t length; +}; + +struct kstream_crypt_ctl_block { + int (INTERFACE *encrypt) ( + struct kstream_data_block *, /* output -- written */ + struct kstream_data_block *, /* input */ + kstream str); + int (INTERFACE *decrypt) ( + struct kstream_data_block *, /* output -- written */ + struct kstream_data_block *, /* input */ + kstream str); + int (INTERFACE *init) (kstream str, kstream_ptr data); + void (INTERFACE *destroy) (kstream str); +}; + + +/* Prototypes */ + +int kstream_destroy (kstream); +void kstream_set_buffer_mode (kstream, int); +kstream kstream_create_from_fd (int fd, + const struct kstream_crypt_ctl_block __far *ctl, + kstream_ptr data); +int kstream_write (kstream, void __far *, size_t); + +#endif /* K5STREAM_H */ diff --git a/src/windows/wintel/makefile b/src/windows/wintel/makefile new file mode 100644 index 000000000..71aa82447 --- /dev/null +++ b/src/windows/wintel/makefile @@ -0,0 +1,104 @@ +# makefile: Constructs the kerborized telnet client +# Works for both k4 and k5 releases. +# +NAME = telnet +OBJS = telnet.obj negotiat.obj auth.obj edit.obj emul.obj \ + font.obj intern.obj screen.obj + +##### Options +DEBUG = 1 +!IF ! defined(KVERSION) +KVERSION = 5 +!endif +KRB = KRB$(KVERSION) + +!if $(KVERSION) == 4 +BUILDTOP = .. +LIBDIR = $(BUILDTOP)\lib\krb +KLIB = $(LIBDIR)\kerberos.lib +WLIB = $(LIBDIR)\winsock.lib +INCLUDES = /I$(BUILDTOP)\include +XOBJS = +!endif + +!if $(KVERSION) == 5 +BUILDTOP =..\.. +LIBDIR = $(BUILDTOP)\lib +KLIB = $(LIBDIR)\libkrb5.lib +WLIB = $(LIBDIR)\winsock.lib +INCLUDES = /I$(BUILDTOP)\include /I$(BUILDTOP)\include\krb5 \ + /I$(BUILDTOP)\lib\crypto\des +XOBJS = k5stream.obj +!endif + +##### C Compiler +CC = cl +CFLAGS_RELEASE = /nologo /W3 /AL /GAs /Gx /O1 /DNDEBUG +CFLAGS_DEBUG = /nologo /W3 /AL /GAs /Gx /G2 /Zi /Od /D_DEBUG /Fd"TELNET.PDB" +!if $(DEBUG) +CFLAGS = $(CFLAGS_DEBUG) $(INCLUDES) /D$(KRB)=1 +!else +CFLAGS = $(CFLAGS_RELEASE) $(INCLUDES) /D$(KRB)=1 +!endif + +##### RC Compiler +RC = rc +RFLAGS_RELEASE = /nologo +RFLAGS_DEBUG = /nologo /D_DEBUG +!if $(DEBUG) +RFLAGS = $(RFLAGS_DEBUG) $(INCLUDES) +!else +RFLAGS = $(RFLAGS_RELEASE) $(INCLUDES) +!endif + +##### Linker +LINK = link +LIBS = $(KLIB) $(WLIB) +SYSLIBS = libw llibcew commdlg +!if $(DEBUG) +LFLAGS = /co /nol /nod /packc:61440 /stack:32768 /align:16 /onerror:noexe +!else +LFLAGS = /nol /nod /packc:61440 /stack:32768 /align:16 /onerror:noexe +!endif + +all: makefile $(NAME).exe + +$(NAME).exe: $*.def $*.res $(OBJS) $(XOBJS) $(LIBS) + $(LINK) $(LFLAGS) $(OBJS) $(XOBJS), $@, $*.map, \ + $(LIBS) $(SYSLIBS), $*.def + $(RC) $(RFLAGS) /k $*.res $@ + +install: + copy telnet.exe ..\floppy + +clean: + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.res del *.res + if exist *.map del *.map + if exist *.pdb del *.pdb + if exist *.err del *.err + if exist ..\floppy\telnet.exe del ..\floppy\telnet.exe + +telnet.obj: telnet.h dialog.h screen.h struct.h wt-proto.h ini.h + +negotiat.obj: telnet.h dialog.h screen.h struct.h wt-proto.h ini.h + +auth.obj: telopts.h telnet.h dialog.h screen.h struct.h wt-proto.h ini.h + +edit.obj: screen.h + +emul.obj: screen.h + +font.obj: screen.h ini.h + +intern.obj: screen.h + +screen.obj: screen.h ini.h + +telnet.res: screen.h dialog.h telnet.dlg ncsa.ico terminal.ico + +!if $(KVERSION) == 5 +k5stream.c: k5stream.h auth.h +!endif + diff --git a/src/windows/wintel/ncsa.ico b/src/windows/wintel/ncsa.ico new file mode 100644 index 000000000..8a6cb6a56 Binary files /dev/null and b/src/windows/wintel/ncsa.ico differ diff --git a/src/windows/wintel/negotiat.c b/src/windows/wintel/negotiat.c new file mode 100644 index 000000000..abace443f --- /dev/null +++ b/src/windows/wintel/negotiat.c @@ -0,0 +1,788 @@ +/* +* negotiat.c +* +* Telnet option negotiation functions +* + +/* +* Includes +*/ + +/* #define USETEK */ +/* #define USERAS */ + +#if 0 /* define this to print the raw network data to debuging monitor */ +#define NEGOTIATEDEBUG +#endif + +#include +#include "telnet.h" +#include "telopts.h" +#include "auth.h" + +unsigned char parsedat[256]; + +/* Local functions */ +static void parse_subnegotiat(kstream ks,int end_sub); + +/* Local variables */ +static char *telstates[]={ + "EOF", + "Suspend Process", + "Abort Process", + "Unknown (239)", + "Subnegotiation End", + "NOP", + "Data Mark", + "Break", + "Interrupt Process", + "Abort Output", + "Are You There", + "Erase Character", + "Erase Line", + "Go Ahead", + "Subnegotiate", + "Will", + "Won't", + "Do", + "Don't" +}; + +static char *teloptions[256]={ /* ascii strings for Telnet options */ + "Binary", /* 0 */ + "Echo", + "Reconnection", + "Supress Go Ahead", + "Message Size Negotiation", + "Status", /* 5 */ + "Timing Mark", + "Remote Controlled Trans and Echo", + "Output Line Width", + "Output Page Size", + "Output Carriage-Return Disposition", /* 10 */ + "Output Horizontal Tab Stops", + "Output Horizontal Tab Disposition", + "Output Formfeed Disposition", + "Output Vertical Tabstops", + "Output Vertical Tab Disposition", /* 15 */ + "Output Linefeed Disposition", + "Extended ASCII", + "Logout", + "Byte Macro", + "Data Entry Terminal", /* 20 */ + "SUPDUP", + "SUPDUP Output", + "Send Location", + "Terminal Type", + "End of Record", /* 25 */ + "TACACS User Identification", + "Output Marking", + "Terminal Location Number", + "3270 Regime", + "X.3 PAD", /* 30 */ + "Negotiate About Window Size", + "Terminal Speed", + "Toggle Flow Control", + "Linemode", + "X Display Location", /* 35 */ + "Environment", + "Authentication", + "Data Encryption", + "39", + "40","41","42","43","44","45","46","47","48","49", + "50","51","52","53","54","55","56","57","58","59", + "60","61","62","63","64","65","66","67","68","69", + "70","71","72","73","74","75","76","77","78","79", + "80","81","82","83","84","85","86","87","88","89", + "90","91","92","93","94","95","96","97","98","99", + "100","101","102","103","104","105","106","107","108","109", + "110","111","112","113","114","115","116","117","118","119", + "120","121","122","123","124","125","126","127","128","129", + "130","131","132","133","134","135","136","137","138","139", + "140","141","142","143","144","145","146","147","148","149", + "150","151","152","153","154","155","156","157","158","159", + "160","161","162","163","164","165","166","167","168","169", + "170","171","172","173","174","175","176","177","178","179", + "180","181","182","183","184","185","186","187","188","189", + "190","191","192","193","194","195","196","197","198","199", + "200","201","202","203","204","205","206","207","208","209", + "210","211","212","213","214","215","216","217","218","219", + "220","221","222","223","224","225","226","227","228","229", + "230","231","232","233","234","235","236","237","238","239", + "240","241","242","243","244","245","246","247","248","249", + "250","251","252","253","254", + "Extended Options List" /* 255 */ +}; + +static char *LMoptions[]={ /* ascii strings for Linemode sub-options */ + "None", "MODE", "FORWARDMASK", "SLC" +}; + +static char *ModeOptions[]={ /* ascii strings for Linemode edit options */ + "None", "EDIT", "TRAPSIG", "ACK", "SOFT TAB", "LIT ECHO" +}; + +static char *SLCoptions[]={ /* ascii strings for Linemode SLC characters */ + "None", "SYNCH", "BREAK", "IP", "ABORT OUTPUT", + "AYT", "EOR", "ABORT", "EOF", "SUSP", + "EC", "EL", "EW", "RP", "LNEXT", + "XON", "XOFF", "FORW1", "FORW2", "MCL", + "MCR", "MCWL", "MCWR", "MCBOL", "MCEOL", + "INSRT", "OVER", "ECR", "EWR", "EBOL", + "EEOL" +}; + +static char *SLCflags[]={ /* ascii strings for Linemode SLC flags */ + "SLC_NOSUPPORT", "SLC_CANTCHANGE", "SLC_VALUE", "SLC_DEFAULT" +}; + + /* Linemode default character for each function */ +static unsigned char LMdefaults[NUMLMODEOPTIONS+1]={ + (unsigned char)-1, /* zero isn't used */ + (unsigned char)-1, /* we don't support SYNCH */ + 3, /* ^C is default for BRK */ + 3, /* ^C is default for IP */ + 15, /* ^O is default for AO */ + 25, /* ^Y is default for AYT */ /* 5 */ + (unsigned char)-1, /* we don't support EOR */ + 3, /* ^C is default for ABORT */ + 4, /* ^D is default for EOF */ + 26, /* ^Z is default for SUSP */ + 8, /* ^H is default for EC */ /* 10 */ + 21, /* ^U is default for EL */ + 23, /* ^W is default for EW */ + 18, /* ^R is default for RP */ + 22, /* ^V is default for LNEXT */ + 17, /* ^Q is default for XON */ /* 15 */ + 19, /* ^S is default for XOFF */ + 22, /* ^V is default for FORW1 */ + 5, /* ^E is default for FORW2 */ + (unsigned char)-1, /* we don't support MCL */ + (unsigned char)-1, /* we don't support MCR */ /* 20 */ + (unsigned char)-1, /* we don't support MCWL */ + (unsigned char)-1, /* we don't support MCWR */ + (unsigned char)-1, /* we don't support MCBOL */ + (unsigned char)-1, /* we don't support MCEOL */ + (unsigned char)-1, /* we don't support INSRT */ /* 25 */ + (unsigned char)-1, /* we don't support OVER */ + (unsigned char)-1, /* we don't support ECR */ + (unsigned char)-1, /* we don't support EWR */ + (unsigned char)-1, /* we don't support EBOL */ + (unsigned char)-1 /* we don't support EEOL */ /* 30 */ +}; + + +/*+******************************************************************** +* Function : start_negotiation() +* Purpose : Send the initial negotiations on the network and print +* the negotitations to the console screen. +* Parameters : +* dat - the port number to write to +* cvs - the console's virtual screen +* Returns : none +* Calls : tprintf(), netprintf() +* Called by : dosessions() +**********************************************************************/ +void +start_negotiation(kstream ks) +{ + char buf[128]; + + /* Send the initial tlnet negotiations */ + wsprintf(buf,"%c%c%c",IAC,DOTEL,SGA); + TelnetSend(ks,buf,lstrlen(buf),0); + wsprintf(buf,"%c%c%c",IAC,DOTEL,ECHO); + TelnetSend(ks,buf,lstrlen(buf),0); + wsprintf(buf,"%c%c%c",IAC,WILLTEL,NAWS); + TelnetSend(ks,buf,lstrlen(buf),0); + +#ifdef NOT + /* check whether we are going to be output mapping */ + if(tw->mapoutput) { + netprintf(tw->pnum,"%c%c%c",IAC,DOTEL,BINARY); + /* set the flag indicating we wanted server to start transmitting binary */ + tw->uwantbinary=1; + netprintf(tw->pnum,"%c%c%c",IAC,WILLTEL,BINARY); + /* set the flag indicating we want to start transmitting binary */ + tw->iwantbinary=1; + } /* end if */ +#endif + + /* Print to the console what we just did */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n",telstates[DOTEL-LOW_TEL_OPT], + teloptions[ECHO]); + OutputDebugString(strTmp); + wsprintf(strTmp,"SEND: %ls %ls\r\n",telstates[DOTEL-LOW_TEL_OPT], + teloptions[SGA]); + OutputDebugString(strTmp); + wsprintf(strTmp,"SEND: %ls %ls\r\n",telstates[WILLTEL-LOW_TEL_OPT], + teloptions[NAWS]); + OutputDebugString(strTmp); + +#ifdef NOT + tprintf(cvs,"SEND: %ls %ls\r\n",telstates[DOTEL-LOW_TEL_OPT], + teloptions[BINARY]); + tprintf(cvs,"SEND: %ls %ls\r\n",telstates[WILLTEL-LOW_TEL_OPT], + teloptions[BINARY]); +#endif +#endif +} /* end start_negotiation() */ + +/*+******************************************************************* +* parse +* Do the telnet negotiation parsing. +* +* look at the string which has just come in from outside and +* check for special sequences that we are interested in. +* +* Tries to pass through routine strings immediately, waiting for special +* characters ESC and IAC to change modes. +*/ +void +parse (CONNECTION *con,unsigned char *st,int cnt) { + static int sub_pos; /* the position we are in the subnegotiation parsing */ + static int end_sub; /* index of last byte in parsedat in a subnegotiation */ + unsigned char *mark, *orig; + char buf[256]; + kstream ks; + + ks=con->ks; + +#ifdef PRINT_EVERYTHING + OutputDebugString("\r\n"); + for(i=0; ipnum); +#endif + +/* +* traverse string, looking for any special characters which indicate that +* we need to change modes. +*/ + while(sttelstate!=STNORM && sttelstate) { + case IACFOUND: /* telnet option negotiation */ + if(*st==IAC) { /* real data=255 */ + st++; /* real 255 will get sent */ + con->telstate=STNORM; + break; + } /* end if */ + + if(*st>239) { + con->telstate=*st++; /* by what the option is */ + break; + } /* end if */ + +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"\r\n strange telnet option"); + OutputDebugString(buf); +#endif + orig=++st; + con->telstate=STNORM; + break; + + case EL: /* received a telnet erase line command */ + case EC: /* received a telnet erase character command */ + case AYT: /* received a telnet Are-You-There command */ + case AO: /* received a telnet Abort Output command */ + case IP: /* received a telnet Interrupt Process command */ + case BREAK: /* received a telnet Break command */ + case DM: /* received a telnet Data Mark command */ + case NOP: /* received a telnet No Operation command */ + case SE: /* received a telnet Subnegotiation End command */ + case ABORT: /* received a telnet Abort Process command */ + case SUSP: /* received a telnet Suspend Process command */ + case TEL_EOF:/* received a telnet EOF command */ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT]); + OutputDebugString(buf); +#endif + con->telstate=STNORM; + orig=++st; + break; + + case GOAHEAD: /* telnet go ahead option*/ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT]); + OutputDebugString(buf); +#endif + con->telstate=STNORM; + orig=++st; + break; + + case DOTEL: /* received a telnet DO negotiation */ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %ls %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT],teloptions[*st]); + OutputDebugString(buf); +#endif + switch(*st) { +#ifdef NOT + case BINARY: /* DO: binary transmission */ + if(!tw->ibinary) { /* binary */ + if(!tw->iwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,WILLTEL,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end if */ + else + tw->iwantbinary=0; /* turn off this now */ + tw->ibinary=1; + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end else */ + break; +#endif + + case SGA: /* DO: Suppress go-ahead */ + if(!con->igoahead) { /* suppress go-ahead */ + wsprintf(buf,"%c%c%c",IAC,WILLTEL,SGA); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[SGA]); + OutputDebugString(strTmp); + OutputDebugString("igoahead"); +#endif + con->igoahead=1; + } /* end if */ + else { +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp, + "NO REPLY NEEDED: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[SGA]); + OutputDebugString(strTmp); +#endif + } /* end else */ + break; + + case TERMTYPE: /* DO: terminal type negotiation */ + if(!con->termsent) { + con->termsent=TRUE; + wsprintf(buf,"%c%c%c",IAC,WILLTEL,TERMTYPE); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[TERMTYPE]); + OutputDebugString(strTmp); +#endif + } /* end if */ + else { +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"NO REPLY NEEDED: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[TERMTYPE]); + OutputDebugString(strTmp); +#endif + } /* end else */ + break; + +#ifdef LATER + case LINEMODE: /* DO: linemode negotiation */ + tw->lmflag=1; /* set the linemode flag */ + netprintf(tw->pnum,"%c%c%c",IAC,WILLTEL,LINEMODE); + /* + ** Tell the other side to send us + ** it's default character set + */ + netprintf(tw->pnum,"%c%c%c%c", + IAC,SB,LINEMODE,SLC,0,SLC_DEFAULT,0,IAC,SE); + if(tw->condebug>0) { + tprintf(cv,"SEND: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[LINEMODE]); + tprintf(cv, + "SEND: SB LINEMODE SLC 0 SLC_DEFAULT 0 IAC SE\r\n"); + } /* end if */ + break; +#endif + case NAWS: /* DO: Negotiate About Window Size */ + con->bResizeable=TRUE; + send_naws(con); + break; + + case AUTHENTICATION: /* DO: Authentication requested */ + wsprintf(buf,"%c%c%c",IAC,WILLTEL,AUTHENTICATION); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[WILLTEL-LOW_TEL_OPT], + teloptions[AUTHENTICATION]); + OutputDebugString(strTmp); +#endif + break; + + default: /* DO: */ + wsprintf(buf,"%c%c%c",IAC,WONTTEL,*st); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[WONTTEL-LOW_TEL_OPT],teloptions[*st]); + OutputDebugString(strTmp); +#endif + break; + + } /* end switch */ + con->telstate=STNORM; + orig=++st; + break; + + case DONTTEL: /* Received a telnet DONT option */ + if (*st==NAWS) + con->bResizeable=FALSE; +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %ls %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT],teloptions[*st]); + OutputDebugString(strTmp); +#endif + +#ifdef NOT + if((*st)==BINARY) { /* DONT: check for binary neg. */ + if(tw->ibinary) { /* binary */ + if(!tw->iwantbinary) { + netprintf(tw->pnum,"%c%c%c",IAC,WONTTEL,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %ls %ls\r\n", + telstates[WONTTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end if */ + else + tw->iwantbinary=0; /* turn off this now */ + tw->ibinary=0; + tw->mapoutput=0; /* turn output mapping off */ + } /* end if */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"NO REPLY NEEDED: %ls %ls\r\n", + telstates[WONTTEL-LOW_TEL_OPT], + teloptions[BINARY]); + OutputDebugString(strTmp); +#endif + } +#endif + con->telstate=STNORM; + orig=++st; + break; + + case WILLTEL: /* received a telnet WILL option */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %ls %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT], + teloptions[*st]); + OutputDebugString(strTmp); +#endif + switch(*st) { +#ifdef NOT + case BINARY: /* WILL: binary */ + if(!tw->ubinary) { /* binary */ + if(!tw->uwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,DOTEL,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %ls %ls\r\n", + telstates[DOTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end if */ + else + tw->uwantbinary=0; /* turn off this now */ + tw->ubinary=1; + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %ls %ls\r\n", + telstates[DOTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end else */ + break; +#endif + + case SGA: /* WILL: suppress go-ahead */ + if(!con->ugoahead) { + con->ugoahead=1; + wsprintf(buf,"%c%c%c",IAC,DOTEL,SGA); /* ack */ + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[DOTEL-LOW_TEL_OPT], + teloptions[SGA]); + OutputDebugString(strTmp); +#endif + } /* end if */ + break; + + case ECHO: /* WILL: echo */ + if(!con->echo) { + con->echo=1; + wsprintf(buf,"%c%c%c",IAC,DOTEL,ECHO); /* ack */ + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[DOTEL-LOW_TEL_OPT], + teloptions[ECHO]); + OutputDebugString(strTmp); +#endif + } /* end if */ + break; + + case TIMING: /* WILL: Timing mark */ + con->timing=0; + break; + + default: + wsprintf(buf,"%c%c%c",IAC,DONTTEL,*st); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[DONTTEL-LOW_TEL_OPT],teloptions[*st]); + OutputDebugString(strTmp); +#endif + break; + } /* end switch */ + con->telstate=STNORM; + orig=++st; + break; + + case WONTTEL: /* Received a telnet WONT option */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %ls %ls\r\n", + telstates[con->telstate-LOW_TEL_OPT],teloptions[*st]); + OutputDebugString((LPSTR)strTmp); +#endif + con->telstate=STNORM; + switch(*st++) { /* which option? */ +#ifdef NOT + case BINARY: /* WONT: binary */ + if(tw->ubinary) { /* binary */ + if(!tw->uwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,DONTTEL,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %ls %ls\r\n", + telstates[DONTTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end if */ + else + tw->uwantbinary=0; /* turn off this now */ + tw->ubinary=0; + tw->mapoutput=0; /* turn output mapping off */ + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %ls %ls\r\n", + telstates[DONTTEL-LOW_TEL_OPT], + teloptions[BINARY]); + } /* end else */ + break; + +#endif + case ECHO: /* WONT: echo */ + if(con->echo) { + con->echo=0; + wsprintf(buf,"%c%c%c",IAC,DONTTEL,ECHO); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %ls %ls\r\n", + telstates[DONTTEL-LOW_TEL_OPT], + teloptions[ECHO]); + OutputDebugString(strTmp); + OutputDebugString("Other side won't echo!"); +#endif + } /* end if */ + break; + + case TIMING: /* WONT: Telnet timing mark option */ + con->timing=0; + break; + + default: + break; + } /* end switch */ + orig=st; + break; + + case SB: /* telnet sub-options negotiation */ +// OutputDebugString("[SB]"); + con->telstate=NEGOTIATE; + orig=st; + end_sub=0; + sub_pos=con->substate=0; /* Defined for each */ +#ifdef OLD_WAY + break; +#endif + + case NEGOTIATE: +// OutputDebugString("[NEG:"); +// OutputDebugString(st); + /* until we change sub-negotiation states, accumulate bytes */ + if(con->substate==0) { + if(*st==IAC) { /* check if we found an IAC byte */ + if(*(st+1)==IAC) { /* skip over double IAC's */ + st++; + parsedat[sub_pos++]=*st++; + } /* end if */ + else { + end_sub=sub_pos; + con->substate=*st++; + } /* end else */ + } /* end if */ + else /* otherwise, just stash the byte */ + parsedat[sub_pos++]=*st++; + } /* end if */ + else { + con->substate=*st++; + /* check if we've really ended the sub-negotiations */ + if(con->substate==SE) + parse_subnegotiat(ks,end_sub); + orig=st; + con->telstate=STNORM; + } /* end else */ + break; + + default: + con->telstate=STNORM; + break; + } /* end switch */ + } /* end while */ + +/* +* quick scan of the remaining string, skip chars while they are +* uninteresting +*/ + if(con->telstate==STNORM && stubinary) +// *st&=127; /* mask off high bit */ + st++; + } /* end while */ +// if(!tw->timing) +// parsewrite(tw,orig,st-orig); + orig=st; /* forget what we have sent already */ + if(sttelstate=IACFOUND; + st++; + break; + + default: +#ifdef NEGOTIATEDEBUG +// wsprintf(buf," strange char>128\r\n"); +// OutputDebugString(buf); +#endif + st++; + break; + } /* end switch */ + } /* end if */ + } /* end while */ +} /* end parse() */ + + +/*+******************************************************************** +* Function : parse_subnegotiat() +* Purpose : Parse the telnet sub-negotiations read into the parsedat +* array. +* Parameters : +* end_sub - index of the character in the 'parsedat' array which +* is the last byte in a sub-negotiation +* Returns : none +* Calls : +* Called by : parse() +**********************************************************************/ +static void +parse_subnegotiat(kstream ks,int end_sub) { + char buf[128]; + +// OutputDebugString("INTO SUBNEGOTIATE"); + switch(parsedat[0]) { + case TERMTYPE: +// OutputDebugString(":INTO TERMTYPE"); + if(parsedat[1]==1) { +/* QAK!!! */ wsprintf(buf,"%c%c%c%cvt100%c%c",IAC,SB,TERMTYPE,0,IAC,SE); + TelnetSend(ks,(LPSTR)buf,11,0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SB TERMINAL-TYPE SEND\r\n" + "SEND: SB TERMINAL-TYPE IS vt100 \r\n len=%d \r\n", + lstrlen((LPSTR)buf)); +// OutputDebugString(strTmp); +#endif + } + break; + + case AUTHENTICATION: + auth_parse(ks, parsedat, end_sub); + break; + default: + break; + } /* end switch */ +} /* end parse_subnegotiat() */ +/*+******************************************************************** +* Function : send_naws +* Purpose : Send a window size sub-negotiation. +* Parameters : +* ks - the kstream to send to. +* Returns : none +**********************************************************************/ +void +send_naws(CONNECTION *con) { + unsigned char buf[13]; + int len; + + wsprintf(buf, "%c%c%c", IAC, SB, NAWS); + len = 3; + + buf[len++] = HIBYTE(con->width); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = LOBYTE(con->width); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = HIBYTE(con->height); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = LOBYTE(con->height); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = IAC; + buf[len++] = SE; + + TelnetSend(con->ks, buf, len, 0); + +#ifdef NEGOTIATEDEBUG +/// wsprintf(buf, "SEND: SB NAWS %d %d %d %d IAC SE\r\n", +/// HIBYTE(con->width), LOBYTE(con->width), +/// HIBYTE(con->height), LOBYTE(con->height)); +/// OutputDebugString(buf); +#endif +} /* send_naws */ diff --git a/src/windows/wintel/screen.c b/src/windows/wintel/screen.c new file mode 100644 index 000000000..2f12ad00c --- /dev/null +++ b/src/windows/wintel/screen.c @@ -0,0 +1,1281 @@ +#include +#include +#include +#include +#include "screen.h" +#include "ini.h" + +extern char *cInvertedArray; +HSCREEN ScreenList; +HINSTANCE hInst; +HDC hDC; +char gszAllocErrorMsg[]="Error Allocating Memory!"; +char gszLockErrorMsg[]="Error Locking Memory!"; +char gszLoadStrFail[]="LoadString failed!"; + +int bDoubleClick=FALSE; +extern LOGFONT lf; +extern HFONT hFont; +extern int bMouseDown; +extern int bSelection; + +char szScreenClass[]="ScreenWClass"; +char szScreenMenu[]="ScreenMenu"; + +OFSTRUCT ofFile; +HFILE fh; + +#ifdef WINMEM +CATCHBUF EndRtn; /* error return buffer (required by WinMem)*/ +#endif + +//#define FILE_DEBUG + +void ScreenInit(HANDLE hInstance) { + + WNDCLASS wc; + + hInst=hInstance; + +// wsprintf(strTmp,"hInst= %d \r\n",hInst); +// OutputDebugString(strTmp); + + ScreenList=NULL; + + wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS|CS_GLOBALCLASS; /* Class style(s). */ + wc.lpfnWndProc = ScreenWndProc; /* Function to retrieve messages for */ + /* windows of this class. */ + wc.cbClsExtra = 0; /* No per-class extra data. */ + wc.cbWndExtra = sizeof(HGLOBAL); /* Only extra data is handle to screen*/ + wc.hInstance = hInstance; /* Application that owns the class. */ + wc.hIcon = LoadIcon(hInstance, "TERMINAL"); + wc.hCursor = LoadCursor(NULL, IDC_IBEAM); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = szScreenMenu; /* Name of menu resource in .RC file. */ + wc.lpszClassName = szScreenClass; /* Name used in call to CreateWindow. */ + + /* Register the window class and return success/failure code. */ + if (!RegisterClass(&wc)) + MessageBox(NULL,"Couldn't register Class!",NULL,MB_OK); +} + +int GetNewScreen(void) { + HGLOBAL ghScr; + SCREEN *fpScr, *fpTmp, *fpTmp2; + static int id=0; + + if (ScreenList==NULL) { + ghScr = GlobalAlloc(GHND,sizeof(SCREEN)); + if (ghScr==NULL) return -1; + fpScr = (SCREEN *)GlobalLock(ghScr); + if (fpScr==NULL) return -1; + fpScr->next=NULL; + fpScr->prev=NULL; + GlobalUnlock(ghScr); + ScreenList=ghScr; + return(id++); + } + else { + ghScr = GlobalAlloc(GHND,sizeof(SCREEN)); + if (ghScr==NULL) return -1; + fpScr = (SCREEN *)GlobalLock(ghScr); + if (fpScr==NULL) return -1; + fpScr->next=ScreenList; + fpTmp = (SCREEN *)GlobalLock(ScreenList); + if (fpTmp != NULL) { + if (fpTmp->next==NULL) { + fpScr->next=ScreenList; + fpScr->prev=ScreenList; + fpTmp->next=ghScr; + fpTmp->prev=ghScr; + } else { + fpScr->prev=fpTmp->prev; + fpTmp2 = (SCREEN *)GlobalLock(fpTmp->prev); + if (fpTmp2 != NULL) + fpTmp2->next=ghScr; + GlobalUnlock(fpTmp->prev); + fpTmp->prev=ghScr; + } + } + GlobalUnlock(fpScr->next); + GlobalUnlock(ghScr); + ScreenList=ghScr; + return(id++); + } +} + +HSCREENLINE ScreenNewLine(void) +{ + + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + + hgScrLine=LINE_MEM_ALLOC(sizeof(SCREENLINE)+2*MAX_LINE_WIDTH); + if (hgScrLine==NULL) + return (NULL); + fpScrLine=LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) + return (NULL); + memset(fpScrLine,0,sizeof(SCREENLINE)+2*MAX_LINE_WIDTH); + fpScrLine->text=&fpScrLine->buffer[0]; + fpScrLine->attrib=&fpScrLine->buffer[MAX_LINE_WIDTH]; + LINE_MEM_UNLOCK(hgScrLine); + return(hgScrLine); +} + +static void MakeWindowTitle(char *host, int width, int height, char *title, int nchars) +{ + char buf[128]; + int hlen; + + hlen = strlen(host); + + title[0] = 0; + + if (hlen + 1 > nchars) + return; + + strcpy(title, host); + + wsprintf(buf, " (%dh x %dw)", height, width); + + if ((int) strlen(buf) + hlen + 1 > nchars) + return; + + strcat(title, buf); +} + +HSCREEN InitNewScreen(CONFIG *Config) { + TEXTMETRIC tm; + HMENU hMenu=NULL; + SCREEN *scr=NULL; + HSCREENLINE hgScrLine; + HSCREENLINE hgScrLineLast; + SCREENLINE *fpScrLine; + SCREENLINE *fpScrLineLast; + int id,idx=0; + HGLOBAL h; + char title[128]; + + id=GetNewScreen(); + if (id == -1) return(0); + scr=(SCREEN *) GlobalLock(ScreenList); + if (scr==NULL) OutputDebugString("Scr is NULL!\r\n"); + + hMenu = LoadMenu(hInst,szScreenMenu); + if (hMenu==NULL) OutputDebugString("hMenu is NULL! \r\n"); + + scr->title=Config->title; + MakeWindowTitle(Config->title,Config->width,Config->height,title,sizeof(title)); + + scr->hWnd = CreateWindow((char *)szScreenClass,title,WS_OVERLAPPEDWINDOW|WS_VSCROLL, + CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,hMenu,hInst,NULL); + + if (!(scr->hWnd)) { + OutputDebugString("Couldn't Create Window!! \r\n"); + return(0); + } + scr->hwndTel=Config->hwndTel; /* save HWND of calling window */ + + if (Config->backspace) { + CheckMenuItem(hMenu,IDM_BACKSPACE,MF_CHECKED); + CheckMenuItem(hMenu,IDM_DELETE,MF_UNCHECKED); + } + else { + CheckMenuItem(hMenu,IDM_BACKSPACE,MF_UNCHECKED); + CheckMenuItem(hMenu,IDM_DELETE,MF_CHECKED); + } + SetWindowWord(scr->hWnd,SCREEN_HANDLE,(WORD)ScreenList); + hDC = GetDC(scr->hWnd); + + scr->lf.lfPitchAndFamily=FIXED_PITCH; + GetPrivateProfileString(INI_FONT,"FaceName","Courier",scr->lf.lfFaceName, + LF_FACESIZE,TELNET_INI); + scr->lf.lfHeight=(int)GetPrivateProfileInt(INI_FONT,"Height",0,TELNET_INI); + scr->lf.lfWidth=(int)GetPrivateProfileInt(INI_FONT,"Width",0,TELNET_INI); + scr->lf.lfPitchAndFamily=(BYTE)GetPrivateProfileInt(INI_FONT,"PitchAndFamily",0,TELNET_INI); + scr->lf.lfCharSet=(BYTE)GetPrivateProfileInt(INI_FONT,"CharSet",0,TELNET_INI); + scr->lf.lfEscapement=(BYTE)GetPrivateProfileInt(INI_FONT,"Escapement",0,TELNET_INI); + scr->lf.lfQuality=PROOF_QUALITY; + scr->ghSelectedFont = CreateFontIndirect((LPLOGFONT)&(scr->lf)); + + SelectObject(hDC,scr->ghSelectedFont); + + GetTextMetrics(hDC,(LPTEXTMETRIC)&tm); + scr->cxChar = tm.tmAveCharWidth; + scr->cyChar = tm.tmHeight + tm.tmExternalLeading; + + ReleaseDC(scr->hWnd,hDC); + scr->width=Config->width; + scr->height=Config->height; + scr->ID=id; + scr->x=0; + scr->y=0; + scr->Oldx=0; + scr->Oldy=0; + scr->attrib=0; + scr->DECAWM=1; + scr->top=0; + scr->bottom=scr->height-1; + scr->parmptr=0; + scr->escflg=0; + scr->bAlert=FALSE; + scr->numlines=0; + scr->maxlines=150; + + h=GlobalAlloc(GHND,scr->width*scr->height); + if (h==NULL) + return(0); + cInvertedArray=GlobalLock(h); + + hgScrLineLast=ScreenNewLine(); + scr->screen_top=scr->buffer_top=hgScrLineLast; + hgScrLine=hgScrLineLast; + + for (idx=0; idxheight-1; idx++) { + hgScrLine=ScreenNewLine(); + fpScrLine=LINE_MEM_LOCK(hgScrLine); + if (fpScrLine == NULL) + return(NULL); + fpScrLine->prev=hgScrLineLast; + LINE_MEM_UNLOCK(hgScrLine); + + fpScrLineLast=LINE_MEM_LOCK(hgScrLineLast); + if (fpScrLineLast == NULL) + return(NULL); + fpScrLineLast->next=hgScrLine; + LINE_MEM_UNLOCK(hgScrLineLast); + + hgScrLineLast=hgScrLine; + } + + scr->screen_bottom=scr->buffer_bottom=hgScrLine; + + SetWindowPos(scr->hWnd,NULL,0,0,scr->cxChar * scr->width + FRAME_WIDTH, + scr->cyChar * scr->height + FRAME_HEIGHT, SWP_NOMOVE|SWP_NOZORDER); + + CreateCaret(scr->hWnd, NULL, scr->cxChar, 2); + SetCaretPos(scr->x*scr->cxChar, (scr->y+1)*scr->cyChar); + ShowCaret(scr->hWnd); + + GlobalUnlock(ScreenList); + return(ScreenList); +} + +void DeleteTopLine(SCREEN *fpScr) { + HSCREENLINE hsTop; + SCREENLINE *fpScrLine; + + fpScrLine=(SCREENLINE *) LINE_MEM_LOCK(fpScr->buffer_top); + if (fpScrLine==NULL) OutputDebugString("Hosed in DeleteTopLine.\r\n"); + hsTop=fpScrLine->next; + LINE_MEM_FREE(fpScr->buffer_top); + fpScr->buffer_top=hsTop; + fpScrLine=(SCREENLINE *) LINE_MEM_LOCK(fpScr->buffer_top); + if (fpScrLine==NULL) OutputDebugString("Hosed in DeleteTopLine.\r\n"); + fpScrLine->prev=NULL; + LINE_MEM_UNLOCK(fpScr->buffer_top); + fpScr->numlines--; +} + + +static void SetScreenScrollBar(SCREEN *fpScr) +{ + if (fpScr->numlines <= 0) { + SetScrollRange(fpScr->hWnd, SB_VERT, 0, 100, FALSE); + SetScrollPos(fpScr->hWnd, SB_VERT, 0, TRUE); + EnableScrollBar(fpScr->hWnd, SB_VERT, ESB_DISABLE_BOTH); + } + else { + SetScrollRange(fpScr->hWnd, SB_VERT, 0, fpScr->numlines, FALSE); + SetScrollPos(fpScr->hWnd, SB_VERT, fpScr->numlines, TRUE); + EnableScrollBar(fpScr->hWnd, SB_VERT, ESB_ENABLE_BOTH); + } +} /* SetScreenScrollBar */ + + +int ScreenScroll(SCREEN *fpScr) +{ + HSCREENLINE hgScrLine; + HSCREENLINE hScrollTop; + HSCREENLINE hScrollBottom; + HSCREENLINE hPrev; + HSCREENLINE hNext; + SCREENLINE *fpScrLine; + SCREENLINE *fpPrev; + SCREENLINE *fpNext; + SCREENLINE *fpScrollTop; + SCREENLINE *fpScrollBottom; + BOOL bFullScreen = TRUE; + HDC hDC; + RECT rc; + + Edit_ClearSelection(fpScr); + + hScrollTop = (HSCREENLINE) GetScreenLineFromY(fpScr, fpScr->top); + + hScrollBottom = (HSCREENLINE) GetScreenLineFromY(fpScr, fpScr->bottom); + + if (hScrollTop != fpScr->screen_top) { + bFullScreen = FALSE; + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = fpScr->cyChar * (fpScr->top); + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + + fpScrollTop = LINE_MEM_LOCK(hScrollTop); + hNext = fpScrollTop->next; + hPrev = fpScrollTop->prev; + LINE_MEM_UNLOCK(hScrollTop); + + fpPrev = LINE_MEM_LOCK(hPrev); + fpPrev->next = hNext; + fpNext = LINE_MEM_LOCK(hNext); + fpNext->prev = hPrev; + LINE_MEM_UNLOCK(hPrev); + LINE_MEM_UNLOCK(hNext); + + hgScrLine = hScrollTop; + ScreenClearLine(fpScr, hgScrLine); + } + else { + fpScr->numlines++; + hgScrLine = ScreenNewLine(); + if (hgScrLine == NULL) + return(0); + fpScrollTop = LINE_MEM_LOCK(hScrollTop); + fpScr->screen_top = fpScrollTop->next; + LINE_MEM_UNLOCK(hScrollTop); + } + + fpScrLine= LINE_MEM_LOCK(hgScrLine); + if (fpScrLine == NULL) + return(0); + + fpScrollBottom = LINE_MEM_LOCK(hScrollBottom); + hNext = fpScrollBottom->next; + fpScrollBottom->next = hgScrLine; + LINE_MEM_UNLOCK(hScrollBottom); + fpScrLine->next = hNext; + fpScrLine->prev = hScrollBottom; + if (hNext != NULL) { + fpNext = LINE_MEM_LOCK(hNext); + fpNext->prev = hgScrLine; + LINE_MEM_UNLOCK(hNext); + } + + LINE_MEM_UNLOCK(hgScrLine); + + if (hScrollBottom != fpScr->screen_bottom) { + bFullScreen = FALSE; + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = fpScr->cyChar * fpScr->top; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + } + else { + if (fpScr->screen_bottom == fpScr->buffer_bottom) + fpScr->buffer_bottom = hgScrLine; + fpScr->screen_bottom = hgScrLine; + } + +// CheckScreen(fpScr); + + fpScr->y++; + + if (fpScr->y > fpScr->bottom) + fpScr->y = fpScr->bottom; + + hDC = GetDC(fpScr->hWnd); + if (bFullScreen) + ScrollDC(hDC, 0, -fpScr->cyChar, NULL, NULL, NULL, NULL); + else + ScrollDC(hDC, 0, -fpScr->cyChar, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, fpScr->bottom * fpScr->cyChar, + fpScr->width * fpScr->cxChar, fpScr->cyChar, WHITENESS); + + ReleaseDC(fpScr->hWnd, hDC); + + if (fpScr->numlines == fpScr->maxlines) + DeleteTopLine(fpScr); + else + SetScreenScrollBar(fpScr); + + return(1); +} + + +void DrawCursor(SCREEN *fpScr) { +#ifdef NOT + HDC hDC; + char ch=95; + + hDC=GetDC(fpScr->hWnd); + SelectObject(hDC,fpScr->ghSelectedFont); + SetTextColor(hDC,RGB(255,255,255)); + TextOut(hDC,fpScr->Oldx*fpScr->cxChar,fpScr->Oldy*fpScr->cyChar,&ch,1); + fpScr->Oldx=fpScr->x; + fpScr->Oldy=fpScr->y; + SetTextColor(hDC,RGB(0,0,0)); + TextOut(hDC,fpScr->x*fpScr->cxChar,fpScr->y*fpScr->cyChar,&ch,1); + ReleaseDC(fpScr->hWnd,hDC); +#endif +} + +int DrawTextScreen(RECT rcInvalid, SCREEN * fpScr, HDC hDC) +{ + HSCREENLINE hgScrLine, hgScrLineTmp; + SCREENLINE *fpScrLine; + int x=0, y=0; + int left=0, right=0; + int i; + int len; + char attrib; + #define YPOS (y*fpScr->cyChar) + + hgScrLine=fpScr->screen_top; +// hgScrLine=GetScreenLineFromY(fpScr,0); +// wsprintf(strTmp,"{DTS: (%d)=%X }",fpScr->top,hgScrLine); +// OutputDebugString(strTmp); + + for (y = 0; y < fpScr->height; y++) { + fpScrLine = LINE_MEM_LOCK(hgScrLine); + + if (!fpScrLine) + continue; + + if (YPOS >= rcInvalid.top - fpScr->cyChar && + YPOS <= rcInvalid.bottom + fpScr->cyChar) { + + if (y < 0) + y = 0; + + if (y >= fpScr->height) + y = fpScr->height - 1; + + left = (rcInvalid.left / fpScr->cxChar) - 1; + + right = (rcInvalid.right / fpScr->cxChar) + 1; + + if (left < 0) + left = 0; + + if (right > fpScr->width - 1) + right = fpScr->width - 1; + + x = left; + + while (x <= right) { + if (!fpScrLine->text[x]) { + x++; + continue; + } + + if (SCR_isrev(fpScrLine->attrib[x])) { + SelectObject(hDC, fpScr->ghSelectedFont); + SetTextColor(hDC, RGB(255, 255, 255)); + SetBkColor(hDC, RGB(0, 0, 0)); + } + else if (SCR_isblnk(fpScrLine->attrib[x])) { + SelectObject(hDC, fpScr->ghSelectedFont); + SetTextColor(hDC, RGB(255, 0, 0)); + SetBkColor(hDC, RGB(255, 255, 255)); + } + else if (SCR_isundl(fpScrLine->attrib[x])) { + SetTextColor(hDC, RGB(255, 0, 0)); + SetBkColor(hDC, RGB(255, 255, 255)); + SelectObject(hDC, fpScr->ghSelectedULFont); + } + else { + SelectObject(hDC,fpScr->ghSelectedFont); + SetTextColor(hDC,RGB(0, 0, 0)); + SetBkColor(hDC,RGB(255, 255, 255)); + } + + len = 1; + attrib = fpScrLine->attrib[x]; + for (i = x + 1; i <= right; i++) { + if (fpScrLine->attrib[i] != attrib || !fpScrLine->text[i]) + break; + len++; + } + + TextOut(hDC, x*fpScr->cxChar, y*fpScr->cyChar, &fpScrLine->text[x], len); + x += len; + } + } + hgScrLineTmp = fpScrLine->next; + LINE_MEM_UNLOCK(hgScrLine); + hgScrLine = hgScrLineTmp; + } + return(0); +} + +static BOOL SetInternalScreenSize(SCREEN *fpScr, int width, int height) +{ + RECT rc; + char *p; + HGLOBAL h; + int idx; + int n; + int newlines; + HSCREENLINE hgNewLine; + SCREENLINE *fpNewLine; + HSCREENLINE hgTopLine; + SCREENLINE *fpTopLine; + HSCREENLINE hgBottomLine; + SCREENLINE *fpBottomLine; + #if 0 + int col; + int row; + int dydestbottom; + #endif + + GetClientRect(fpScr->hWnd, &rc); + + width = (rc.right - rc.left) / fpScr->cxChar; + height = (rc.bottom - rc.top) / fpScr->cyChar; + + if (fpScr->height == height && fpScr->width == width) + return(FALSE); + + fpScr->Oldx = 0; + fpScr->Oldy = 0; + fpScr->attrib = 0; + + /* + Reallocate the inverted array of bytes and copy the values + from the old screen to the new screen. + */ + h = GlobalAlloc(GHND, width * height); + if (h == NULL) + return(0); + + ScreenCursorOff(fpScr); + + p = GlobalLock(h); + + #if 0 /* Copy inversion array to desitination */ + for (col = 0; col < width; col++) { + for (row = 0; row < height; row++) { + dydestbottom = height - 1 - row; + if (col < fpScr->width && dydestbottom < fpScr->height - 1) + p[row * width + col] = + cInvertedArray[(fpScr->height - 1 - dydestbottom) * fpScr->width + col]; + } + } + #endif + + h = LOWORD(GlobalHandle(SELECTOROF(cInvertedArray))); + GlobalUnlock(h); + GlobalFree(h); + cInvertedArray = p; + + /* + Append any new lines which need to be added to accomodate the new + screen size. + */ + hgBottomLine = fpScr->buffer_bottom; + newlines = height - (fpScr->height + fpScr->numlines); + + if (newlines > 0) { + fpScr->y += fpScr->numlines; + fpScr->numlines = 0; + + for (idx = 0; idx < newlines; idx++) { + hgNewLine = ScreenNewLine(); + fpNewLine = LINE_MEM_LOCK(hgNewLine); + if (fpNewLine == NULL) + return(FALSE); + fpNewLine->prev = hgBottomLine; + + fpBottomLine = LINE_MEM_LOCK(hgBottomLine); + if (fpBottomLine == NULL) + return(FALSE); + fpBottomLine->next = hgNewLine; + LINE_MEM_UNLOCK(hgBottomLine); + + LINE_MEM_UNLOCK(hgNewLine); + + hgBottomLine = hgNewLine; + } + } + + /* + If we already have plenty of lines, then we need to get rid of the + scrollback lines, if too many exist. The cursor should end up + the same distance from the bottom of the screen as is started out + in this instance. + */ + if (newlines < 0) { + fpScr->y = (height - 1) - (fpScr->bottom - fpScr->y); + if (fpScr->y < 0) + fpScr->y = 0; + fpScr->numlines = -newlines; + n = fpScr->numlines - fpScr->maxlines; + for (idx = 0; idx < n; idx++) + DeleteTopLine(fpScr); + } + + /* + Calculate the position of the buffer relative to the screen. + */ + fpScr->screen_bottom = hgBottomLine; + fpScr->buffer_bottom = hgBottomLine; + + hgTopLine = hgBottomLine; + + for (idx = 1; idx < height; idx++) { + fpTopLine = LINE_MEM_LOCK(hgTopLine); + hgTopLine = fpTopLine->prev; + LINE_MEM_UNLOCK(hgTopLine); + } + + fpScr->screen_top = hgTopLine; + fpScr->width = width; + fpScr->height = height; + fpScr->top = 0; + fpScr->bottom = height - 1; + + if (fpScr->x >= width) + fpScr->x = width - 1; + + if (fpScr->y >= height) + fpScr->y = height - 1; + + SetScreenScrollBar(fpScr); + ScreenCursorOn(fpScr); + return(TRUE); +} + +static int ScreenAdjustUp(SCREEN *fpScr, int n) +{ + int idx; + HSCREENLINE hslLine1; + HSCREENLINE hslLine2; + SCREENLINE *fpScrLine1; + SCREENLINE *fpScrLine2; + + for (idx = 0; idx < n; idx++) { + if (fpScr->screen_top == fpScr->buffer_top) + return(-idx); + fpScrLine1 = LINE_MEM_LOCK(fpScr->screen_top); + hslLine1 = fpScrLine1->prev; + LINE_MEM_UNLOCK(fpScr->screen_top); + if (hslLine1 == NULL) + return(-idx); + fpScrLine2 = LINE_MEM_LOCK(fpScr->screen_bottom); + hslLine2 = fpScrLine2->prev; + LINE_MEM_UNLOCK(fpScr->screen_bottom); + if (hslLine2 == NULL) + return(-idx); + fpScr->screen_top = hslLine1; + fpScr->screen_bottom = hslLine2; + } + return(idx); +} + +static int ScreenAdjustDown(SCREEN *fpScr, int n) +{ + int idx; + HSCREENLINE hslLine1; + HSCREENLINE hslLine2; + SCREENLINE *fpScrLine1; + SCREENLINE *fpScrLine2; + + for (idx = 0; idx < n; idx++) { + if (fpScr->screen_bottom == fpScr->buffer_bottom) + return(-idx); + fpScrLine1 = LINE_MEM_LOCK(fpScr->screen_top); + hslLine1 = fpScrLine1->next; + LINE_MEM_UNLOCK(fpScr->screen_top); + if (hslLine1 == NULL) + return(-idx); + fpScrLine2 = LINE_MEM_LOCK(fpScr->screen_bottom); + hslLine2 = fpScrLine2->next; + LINE_MEM_UNLOCK(fpScr->screen_bottom); + if (hslLine2 == NULL) + return(-idx); + fpScr->screen_top = hslLine1; + fpScr->screen_bottom = hslLine2; + } + return(idx); +} + +long FAR PASCAL ScreenWndProc(hWnd, message, wParam, lParam) +HWND hWnd; /* window handle */ +UINT message; /* type of message */ +WPARAM wParam; /* additional information */ +LPARAM lParam; /* additional information */ +{ + MINMAXINFO *lpmmi; + SCREEN *fpScr; + HGLOBAL hgScr; + HMENU hMenu; + PAINTSTRUCT ps; + int x=0, + y=0, + ScrollPos,tmpScroll=0, + idx; + HSCREENLINE hslLine; + HDC hDC; + RECT rc; + char title[128]; + + switch (message) { + + case WM_COMMAND: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + switch (wParam) { + + case IDM_BACKSPACE: + hMenu=GetMenu(hWnd); + CheckMenuItem(hMenu,IDM_BACKSPACE,MF_CHECKED); + CheckMenuItem(hMenu,IDM_DELETE,MF_UNCHECKED); + SendMessage(fpScr->hwndTel,WM_MYSCREENCHANGEBKSP,VK_BACK,(HSCREEN)hgScr); + break; + case IDM_DELETE: + hMenu=GetMenu(hWnd); + CheckMenuItem(hMenu,IDM_BACKSPACE,MF_UNCHECKED); + CheckMenuItem(hMenu,IDM_DELETE,MF_CHECKED); + SendMessage(fpScr->hwndTel,WM_MYSCREENCHANGEBKSP,0x7f,(HSCREEN)hgScr); + break; + case IDM_FONT: + ScreenCursorOff(fpScr); + ProcessFontChange(hWnd); + ScreenCursorOn(fpScr); + break; + case IDM_COPY: + Edit_Copy(hWnd); + hMenu=GetMenu(hWnd); + Edit_ClearSelection(fpScr); + GlobalUnlock(hgScr); + break; + case IDM_PASTE: + Edit_Paste(hWnd); + break; +#ifdef _DEBUG + case IDM_DEBUG: + CheckScreen(fpScr); + break; +#endif + } + + GlobalUnlock(hgScr); + break; + + case WM_CREATE: +// OutputDebugString("WM_CREATE\r\n"); + SetWindowWord(hWnd,SCREEN_HANDLE,NULL); + SetScrollRange(hWnd,SB_VERT,0,100,FALSE); + SetScrollPos(hWnd,SB_VERT,0,TRUE); + EnableScrollBar(hWnd,SB_VERT,ESB_DISABLE_BOTH); + ShowWindow(hWnd,SW_SHOW); +#ifdef FILE_DEBUG + fh=OpenFile("d:\\debug.txt",&ofFile,OF_CREATE|OF_WRITE); +#endif + break; + + case WM_VSCROLL: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + + ScreenCursorOff(fpScr); + + switch(wParam) { + case SB_LINEDOWN: + if (ScreenAdjustDown(fpScr, 1) <= 0) + break; + hDC = GetDC(hWnd); + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = 0; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + ScrollDC(hDC, 0, -fpScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.top = fpScr->cyChar * fpScr->bottom; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(hWnd,SB_VERT); + SetScrollPos(hWnd,SB_VERT,ScrollPos+1,TRUE); + UpdateWindow(hWnd); + break; + + case SB_LINEUP: + if (ScreenAdjustUp(fpScr, 1) <= 0) + break; + hDC = GetDC(hWnd); + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = 0; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + ScrollDC(hDC, 0, fpScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.bottom = fpScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(fpScr->hWnd,SB_VERT); + SetScrollPos(hWnd,SB_VERT,ScrollPos-1,TRUE); + UpdateWindow(hWnd); + break; + + case SB_PAGEDOWN: + idx = abs(ScreenAdjustDown(fpScr, fpScr->height)); + hDC = GetDC(hWnd); + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = 0; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + ScrollDC(hDC, 0, -idx * fpScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.top = fpScr->cyChar * (fpScr->bottom - idx + 1); + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(hWnd,SB_VERT); + SetScrollPos(hWnd,SB_VERT,ScrollPos+idx,TRUE); + break; + + case SB_PAGEUP: + idx = abs(ScreenAdjustUp(fpScr, fpScr->height)); + hDC = GetDC(hWnd); + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = 0; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + ScrollDC(hDC, 0, idx * fpScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.bottom = idx * fpScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(hWnd,SB_VERT); + SetScrollPos(hWnd,SB_VERT,ScrollPos-idx,TRUE); + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + ScrollPos = GetScrollPos(hWnd,SB_VERT); + tmpScroll = ScrollPos - LOWORD(lParam); + if (tmpScroll == 0) + break; + if (tmpScroll > 0) + ScreenAdjustUp(fpScr, tmpScroll); + else + ScreenAdjustDown(fpScr, -tmpScroll); + if (abs(tmpScroll) < fpScr->height) { + hDC=GetDC(hWnd); + rc.left = 0; + rc.right = fpScr->cxChar * fpScr->width; + rc.top = 0; + rc.bottom = fpScr->cyChar * (fpScr->bottom+1); + ScrollDC(hDC,0,tmpScroll*fpScr->cyChar,&rc,&rc,NULL,NULL); + ReleaseDC(hWnd, hDC); + if (tmpScroll > 0) { + rc.bottom = tmpScroll * fpScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + } + else { + rc.top = (fpScr->bottom + tmpScroll + 1) * fpScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + } + } + else + InvalidateRect(hWnd, NULL, TRUE); + + SetScrollPos(hWnd,SB_VERT,LOWORD(lParam),TRUE); + UpdateWindow(hWnd); + break; + } + ScreenCursorOn(fpScr); + GlobalUnlock(hgScr); + break; + + case WM_KEYDOWN: + if (wParam==VK_INSERT) { + if (GetKeyState(VK_SHIFT)<0) + PostMessage(hWnd,WM_COMMAND,IDM_PASTE,NULL); + else if (GetKeyState(VK_CONTROL)<0) + PostMessage(hWnd,WM_COMMAND,IDM_COPY,NULL); + break; + } + if ((wParam < VK_PRIOR)||(wParam > VK_DOWN)) break; + switch (wParam) { + case VK_PRIOR: /* Page up */ + SendMessage(hWnd,WM_VSCROLL,SB_PAGEUP,NULL); + break; + case VK_NEXT: /* Page down */ + SendMessage(hWnd,WM_VSCROLL,SB_PAGEDOWN,NULL); + break; + case VK_UP: /* Line up */ + SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,NULL); + break; + case VK_DOWN: /* Line down */ + SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,NULL); + break; + } + UpdateWindow(hWnd); + break; + + case WM_CHAR: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) { + OutputDebugString("Hosed #1.\r\n"); + break; + } + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) { + OutputDebugString("Hosed #2.\r\n"); + break; + } + SendMessage(fpScr->hwndTel,WM_MYSCREENCHAR,wParam,(HSCREEN)hgScr); + GlobalUnlock(hgScr); + break; + + case WM_SYSCHAR: + if ((wParam=='c')||(wParam=='e')) + return (DefWindowProc(hWnd, message, wParam, lParam)); + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) { + OutputDebugString("Hosed #1.\r\n"); + break; + } + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) { + OutputDebugString("Hosed #2.\r\n"); + break; + } + SendMessage(fpScr->hwndTel,WM_MYSYSCHAR,wParam,(HSCREEN)hgScr); + GlobalUnlock(hgScr); + break; + + case WM_INITMENU: + if (IsClipboardFormatAvailable(CF_TEXT)) + EnableMenuItem((HMENU) wParam,IDM_PASTE,MF_ENABLED); + else EnableMenuItem((HMENU) wParam,IDM_PASTE,MF_GRAYED); + if (bSelection) EnableMenuItem((HMENU) wParam,IDM_COPY,MF_ENABLED); + else EnableMenuItem((HMENU) wParam,IDM_COPY,MF_GRAYED); + break; + + case WM_GETMINMAXINFO: +// OutputDebugString("WM_GETMINMAX_INFO\r\n"); + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) break; + fpScr=(SCREEN *)GlobalLock(hgScr); +// if (fpScr == NULL) OutputDebugString("Hosed in GetMinMaxInfo.\r\n"); +// wsprintf(strTmp,"cx=%d cy=%d width=%d height=%d",fpScr->cxChar,fpScr->cyChar,fpScr->width,fpScr->height); +// OutputDebugString(strTmp); + lpmmi = (MINMAXINFO *) lParam; + if (FRAME_WIDTH + MAX_LINE_WIDTH * fpScr->cxChar < lpmmi->ptMaxSize.x) + lpmmi->ptMaxSize.x = FRAME_WIDTH + MAX_LINE_WIDTH * fpScr->cxChar; + lpmmi->ptMaxTrackSize.x = lpmmi->ptMaxSize.x; + lpmmi->ptMinTrackSize.x = FRAME_WIDTH + 20 * fpScr->cxChar; + lpmmi->ptMinTrackSize.y = FRAME_HEIGHT + 4 * fpScr->cyChar; + GlobalUnlock(hgScr); + break; + + case WM_LBUTTONDOWN: + if (bDoubleClick) Edit_TripleClick(hWnd,lParam); + else Edit_LbuttonDown(hWnd,lParam); + break; + + case WM_LBUTTONUP: + Edit_LbuttonUp(hWnd,lParam); + break; + + case WM_LBUTTONDBLCLK: + bDoubleClick=TRUE; + SetTimer(hWnd,TIMER_TRIPLECLICK,GetDoubleClickTime(),NULL); + Edit_LbuttonDblclk(hWnd,lParam); + break; + + case WM_TIMER: + if (wParam==TIMER_TRIPLECLICK) bDoubleClick=FALSE; + break; + + case WM_RBUTTONUP: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) { + OutputDebugString("Hosed #1.\r\n"); + break; + } + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) { + OutputDebugString("Hosed #2.\r\n"); + break; + } + Edit_Copy(hWnd); + Edit_ClearSelection(fpScr); + Edit_Paste(hWnd); + GlobalUnlock(hgScr); + break; + + case WM_MOUSEMOVE: + if (bMouseDown) Edit_MouseMove(hWnd,lParam); + break; + + case WM_RBUTTONDOWN: { + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) { + OutputDebugString("Hosed #1.\r\n"); + break; + } + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) { + OutputDebugString("Hosed #2.\r\n"); + break; + } + hgScrLine=fpScr->screen_top; + fpScrLine=LINE_MEM_LOCK(hgScrLine); + +// wsprintf(strTmp,"fp->x=%d fp->y=%d text=%s \r\n",fpScr->x,fpScr->y,fpScrLine->text); +// OutputDebugString(strTmp); + LINE_MEM_LOCK(hgScrLine); + } + break; + + case WM_PAINT: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) { + OutputDebugString("Hosed #1.\r\n"); + break; + } + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) { + OutputDebugString("Hosed #2.\r\n"); + break; + } + BeginPaint (hWnd,&ps); + SelectObject(ps.hdc,fpScr->ghSelectedFont); + hslLine=fpScr->screen_bottom; + if (hslLine==NULL) { + OutputDebugString("screen_bottom is NULL.\r\n"); + EndPaint(hWnd,&ps); + GlobalUnlock(hgScr); + break; + } + DrawTextScreen(ps.rcPaint, fpScr, ps.hdc); + EndPaint(hWnd,&ps); + DrawCursor(fpScr); + GlobalUnlock(hgScr); + break; + + case WM_CLOSE: +#ifdef FILE_DEBUG + _lclose(fh); +#endif + if (MessageBox(hWnd,"Terminate this connection?","Telnet",MB_OKCANCEL) == IDOK) { + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) OutputDebugString("Hosed #1.\r\n"); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + SendMessage(fpScr->hwndTel,WM_MYSCREENCLOSE,NULL,(HSCREEN)hgScr); + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + break; + + case WM_DESTROY: + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr != NULL) { + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr != NULL) + DeleteObject(fpScr->ghSelectedFont); + } + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case WM_ACTIVATE: + if (wParam!=WA_INACTIVE) { + hgScr=(HGLOBAL)GetWindowWord(hWnd,SCREEN_HANDLE); + if (hgScr == NULL) return (DefWindowProc(hWnd, message, wParam, lParam)); + fpScr=(SCREEN *)GlobalLock(hgScr); + if (fpScr == NULL) OutputDebugString("Hosed #2.\r\n"); + if (fpScr->bAlert) { + char strTitle[128]; + int idx; + + GetWindowText(hWnd,strTitle,sizeof(strTitle)); + if (strTitle[0] == ALERT) { + idx=lstrlen(strTitle); + strTitle[idx-2]=0; + SetWindowText(hWnd,&strTitle[2]); + fpScr->bAlert=FALSE; + } + } + GlobalUnlock(hgScr); + } /* Allow control to drop down to DefWindowProc() */ + return (DefWindowProc(hWnd, message, wParam, lParam)); + break; + + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) + break; + + hgScr = (HGLOBAL) GetWindowWord(hWnd, SCREEN_HANDLE); + if (hgScr == NULL) + break; + fpScr = (SCREEN *) GlobalLock(hgScr); + if (fpScr == NULL) + break; + + if (SetInternalScreenSize(fpScr, LOWORD(lParam), HIWORD(lParam))) { + SendMessage(fpScr->hwndTel, WM_MYSCREENSIZE, 0, + MAKELONG(fpScr->width, fpScr->height)); + MakeWindowTitle(fpScr->title,fpScr->width,fpScr->height,title,sizeof(title)); + SetWindowText(hWnd,title); + } + + GlobalUnlock(hgScr); + break; + + case WM_SETFOCUS: + hgScr = (HGLOBAL) GetWindowWord(hWnd, SCREEN_HANDLE); + if (hgScr == NULL) + break; + fpScr = (SCREEN *) GlobalLock(hgScr); + if (fpScr == NULL) + break; + + CreateCaret(hWnd, NULL, fpScr->cxChar, 2); + ScreenCursorOn(fpScr); + break; + + case WM_KILLFOCUS: + DestroyCaret(); + break; + + default: /* Passes it on if unproccessed */ + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + + return (NULL); +} + +/************************************************************************** +* * +* Function: ReportError(WORD) * +* * +* Purpose: To report an error that has occurred while allocating * +* memory for the CD struct, locking the memory or while * +* trying to load a resource string. * +* * +* Returns: void * +* * +* Comments: * +* * +* History: Date Reason * +* -------- ----------------------------------- * +* * +* 10/01/91 Created * +* * +**************************************************************************/ +void ReportError(WORD wErrorType){ + LPSTR lpszErrorMsg; + + switch( wErrorType ) + { + case IDC_ALLOCFAIL: + + lpszErrorMsg=gszAllocErrorMsg; + break; + + case IDC_LOCKFAIL: + + lpszErrorMsg=gszLockErrorMsg; + break; + + case IDC_LOADSTRINGFAIL: + + lpszErrorMsg=gszLoadStrFail; + break; + + default: //let's hope we never get here! + return; + } + + MessageBox(NULL, (LPSTR)lpszErrorMsg, NULL, MB_OK); + + return; +} + +void ScreenBell(SCREEN *fpScr) { + MessageBeep(MB_ICONEXCLAMATION); + if (fpScr->hWnd != GetActiveWindow()) { + char strTitle[128]; + int idx; + + FlashWindow(fpScr->hWnd,TRUE); + if (!fpScr->bAlert) { + strTitle[0]=ALERT; + strTitle[1]=SPACE; + GetWindowText(fpScr->hWnd,&strTitle[2],sizeof(strTitle)-2); + idx=lstrlen(strTitle); + strTitle[idx]=SPACE; + strTitle[idx+1]=ALERT; + strTitle[idx+2]=0; + SetWindowText(fpScr->hWnd,strTitle); + } + FlashWindow(fpScr->hWnd,FALSE); + fpScr->bAlert=TRUE; + } +} + +void ScreenBackspace(SCREEN * fpScr) { + RECT rc; + +// hDC=GetDC(fpScr->hWnd); +// SelectObject(hDC,fpScr->ghSelectedFont); +// TextOut(hDC,fpScr->x*fpScr->cxChar,fpScr->y*fpScr->cyChar," ",1); +// ReleaseDC(fpScr->hWnd,hDC); + rc.left=fpScr->x*fpScr->cxChar; + rc.right=((fpScr->x+1)*fpScr->cxChar); + rc.top=(fpScr->cyChar*fpScr->y); + rc.bottom=(fpScr->cyChar*fpScr->y+1); + InvalidateRect(fpScr->hWnd,&rc,TRUE); + fpScr->x--; + if (fpScr->x < 0) fpScr->x=0; +// DrawCursor(fpScr); + UpdateWindow(fpScr->hWnd); + +} + +void ScreenTab(SCREEN *fpScr) { + int num_spaces,idx; + HSCREENLINE hgScrLine; + SCREENLINE *fpScrLine; + int iTest=0; + + num_spaces = TAB_SPACES - (fpScr->x % TAB_SPACES); + if ((fpScr->x + num_spaces) >= fpScr->width) { + ScreenScroll(fpScr); + num_spaces -= fpScr->width - fpScr->x; + fpScr->x=0; + } +// hgScrLine=fpScr->buffer_bottom; + hgScrLine=GetScreenLineFromY(fpScr,fpScr->y); + if (hgScrLine==NULL) return; + fpScrLine=(SCREENLINE *)LINE_MEM_LOCK(hgScrLine); + if (fpScrLine==NULL) return; + for (idx=0; idxx++) { + if (!fpScrLine->text[fpScr->x]) + iTest=1; + if (iTest) + fpScrLine->text[fpScr->x]=SPACE; + } +// fpScrLine->text[fpScr->x]=0; + hDC=GetDC(fpScr->hWnd); + SelectObject(hDC,fpScr->ghSelectedFont); + TextOut(hDC,(fpScr->x-num_spaces)*fpScr->cxChar,fpScr->y*fpScr->cyChar, + fpScrLine->text+fpScr->x-num_spaces,num_spaces); + ReleaseDC(fpScr->hWnd,hDC); + LINE_MEM_UNLOCK(hgScrLine); + DrawCursor(fpScr); +} + +void ScreenCarriageFeed(SCREEN *fpScr) { + DrawCursor(fpScr); + fpScr->x=0; +} diff --git a/src/windows/wintel/screen.h b/src/windows/wintel/screen.h new file mode 100644 index 000000000..edc4d1368 --- /dev/null +++ b/src/windows/wintel/screen.h @@ -0,0 +1,206 @@ +extern long FAR PASCAL ScreenWndProc(HWND,UINT,WPARAM,LPARAM); + +//#define WINMEM + +/* +* Definition of attribute bits in the Virtual Screen +* +* 0 - Bold +* 1 - +* 2 - +* 3 - Underline +* 4 - Blink +* 5 - +* 6 - Reverse +* 7 - Graphics character set +* +*/ +#define SCR_isbold(x) (x & 0x01) +#define SCR_isundl(x) (x & 0x08) +#define SCR_isblnk(x) (x & 0x10) +#define SCR_isrev(x) (x & 0x40) +#define SCR_setrev(x) (x ^= 0x40) +#define SCR_isgrph(x) (x & 0x80) +#define SCR_inattr(x) (x & 0xd9) +#define SCR_graph(x) (x | 0x80) +#define SCR_notgraph(x) (x & 0x7F) + +#define SCREEN_HANDLE 0 /* offset in extra window info */ + +#define WM_MYSCREENCHAR (WM_USER+1) +#define WM_MYSCREENBLOCK (WM_USER+2) +#define WM_MYSYSCHAR (WM_USER+3) +#define WM_MYSCREENCLOSE (WM_USER+4) +#define WM_MYSCREENCHANGEBKSP (WM_USER+5) +#define WM_MYSCREENSIZE (WM_USER+6) +#define WM_NETWORKEVENT (WM_USER+7) +#define WM_HOSTNAMEFOUND (WM_USER+8) + +#define FRAME_HEIGHT ((2* GetSystemMetrics(SM_CYFRAME))+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYMENU)+3) +#define FRAME_WIDTH (2*GetSystemMetrics(SM_CXFRAME)+GetSystemMetrics(SM_CXVSCROLL)) +#define TAB_SPACES 8 +#define SPACE 32 +#define ALERT 0x21 +#define MAX_LINE_WIDTH 256 /* not restricted to 1 byte */ + +#ifdef WINMEM +#define HSCREENLINE DWORD +#define LINE_MEM_ALLOC(x) sAlloc(x) +#define LINE_MEM_LOCK(x) (SCREENLINE *)sLock(x) +#define LINE_MEM_UNLOCK(x) sUnlock(x) +#define LINE_MEM_FREE(x) sFree(x) +#else +#define HSCREENLINE HGLOBAL +#define LINE_MEM_ALLOC(x) GlobalAlloc(GHND,x) +#define LINE_MEM_LOCK(x) (SCREENLINE *) GlobalLock(x) +#define LINE_MEM_UNLOCK(x) GlobalUnlock(x) +#define LINE_MEM_FREE(x) GlobalFree(x) +#endif + +#define HSCREEN HGLOBAL + +typedef struct SCREENLINE { + HSCREENLINE next; + HSCREENLINE prev; + int width; + char *text; + char *attrib; + char buffer[0]; +} SCREENLINE; + +typedef struct SCREEN { + LPSTR title; + HWND hWnd; + HWND hwndTel; + HSCREENLINE screen_top, + screen_bottom, + buffer_top, + buffer_bottom; + int ID, + type, + width, + height, + maxlines, //Maximum number of scrollback lines + numlines, //Current number of scrollback lines + savelines, //Save lines off top? + ESscroll, //Scroll screen when ES received + attrib, //current attribute + x,y, //current cursor position + Oldx,Oldy, // internally used to redraw cursor + Px,Py,Pattrib, //saved cursor pos and attribute + VSIDC, // Insert/Delete character mode 0=draw line + DECAWM, // AutoWrap mode 0=off + DECCKM, // Cursor key mode + DECPAM, // keyPad Application mode + IRM, // Insert/Replace mode + escflg, // Current Escape level + top,bottom, // Vertical bounds of screen + parmptr, + cxChar, /* Width of the current font */ + cyChar; /* Height of the current font */ + BOOL bAlert; + int parms[6]; //Ansi Params + LOGFONT lf; + HFONT ghSelectedFont,ghSelectedULFont; + char tabs[MAX_LINE_WIDTH]; + HSCREEN next, prev; +} SCREEN; + +typedef struct CONFIG { + LPSTR title; + HWND hwndTel; + int ID, + type, + height, + width, + maxlines, //Maximum number of scrollback lines + backspace, + ESscroll, //Scroll screen when ES received + VSIDC, // Insert/Delete character mode 0=draw line + DECAWM, // AutoWrap mode 0=off + IRM; // Insert/Replace mode +} CONFIG; + +#define TELNET_SCREEN 0 +#define CONSOLE_SCREEN 1 + +#define IDM_FONT 100 +#define IDM_BACKSPACE 101 +#define IDM_DELETE 102 + +#define IDM_COPY 200 +#define IDM_PASTE 201 +#define IDM_DEBUG 202 + +#define TIMER_TRIPLECLICK 1000 + +#define IDC_ALLOCFAIL 1 +#define IDC_LOCKFAIL 2 +#define IDC_LOADSTRINGFAIL 3 +#define IDC_FONT 6 + +#define DESIREDPOINTSIZE 12 + + +void ReportError(WORD); +LPSTR NEAR AllocAndLockMem(HANDLE *hChunk, WORD wSize); +void NEAR InitializeStruct(WORD wCommDlgType, LPSTR lpStruct, HWND hWnd); + +void ScreenInit(HANDLE hInstance); +HSCREENLINE ScreenNewLine(); +void ScreenBell(SCREEN *fpScr); +void ScreenBackspace(SCREEN * fpScr); +void ScreenTab(SCREEN *fpScr); +void ScreenCarriageFeed(SCREEN *fpScr); +int ScreenScroll(SCREEN *fpScr); +void DeleteTopLine(SCREEN *fpScr); +/* emul.c */ +void ScreenEm(LPSTR c,int len,HSCREEN hsScr); + + +/* intern.c */ +HSCREENLINE GetScreenLineFromY(SCREEN *fpScr,int y); +HSCREENLINE ScreenClearLine(SCREEN *fpScr,HSCREENLINE hgScrLine); +void ScreenUnscroll(SCREEN *fpScr); +void ScreenELO(SCREEN *fpScr,int s); +void ScreenEraseScreen(SCREEN *fpScr); +void ScreenTabClear(SCREEN *fpScr); +void ScreenTabInit(SCREEN *fpScr); +void ScreenReset(SCREEN *fpScr); +void ScreenIndex(SCREEN * fpScr); +void ScreenWrapNow(SCREEN *fpScr,int *xp,int *yp); +void ScreenEraseToEOL(SCREEN *fpScr); +void ScreenEraseToBOL(SCREEN *fpScr); +void ScreenEraseLine(SCREEN *fpScr,int s); +void ScreenEraseToEndOfScreen(SCREEN *fpScr); +void ScreenRange(SCREEN *fpScr); +void ScreenAlign(SCREEN *fpScr); +void ScreenApClear(SCREEN *fpScr); +int ScreenInsChar(SCREEN *fpScr,int x); +void ScreenInsString(SCREEN *fpScr,int len,char *start); +void ScreenSaveCursor(SCREEN *fpScr); +void ScreenRestoreCursor(SCREEN *fpScr); +void ScreenDraw(SCREEN *fpScr,int x,int y,int a,int len,char *c); +void ScreenCursorOff(SCREEN *fpScr); +void ScreenCursorOn(SCREEN *fpScr); +void ScreenDelChars(SCREEN *fpScr, int n); +void ScreenRevIndex(SCREEN *fpScr); +void ScreenDelLines(SCREEN *fpScr, int n, int s); +void ScreenInsLines(SCREEN *fpScr, int n, int s); +#ifdef _DEBUG + BOOL CheckScreen(SCREEN *fpScr); +#endif + +void ProcessFontChange(HWND hWnd); +void Edit_LbuttonDown(HWND hWnd,LPARAM lParam); +void Edit_LbuttonDblclk(HWND hWnd,LPARAM lParam); +void Edit_LbuttonUp(HWND hWnd, LPARAM lParam); +void Edit_TripleClick(HWND hWnd, LPARAM lParam); +void Edit_MouseMove(HWND hWnd, LPARAM lParam); +void Edit_ClearSelection(SCREEN *fpScr); +void Edit_Copy(HWND hWnd); +void Edit_Paste(HWND hWnd); + +HSCREEN InitNewScreen(CONFIG *Config); + + diff --git a/src/windows/wintel/struct.h b/src/windows/wintel/struct.h new file mode 100644 index 000000000..b31fa9a7c --- /dev/null +++ b/src/windows/wintel/struct.h @@ -0,0 +1,30 @@ +#include "winsock.h" +#ifdef KRB4 + #include "kstream.h" +#endif +#ifdef KRB5 + #include "k5stream.h" +#endif + +#define HCONNECTION HGLOBAL + +typedef struct CONNECTION { + HSCREEN hScreen; // handle to screen associated with connection + kstream ks; + SOCKET socket; + int pnum; // port number associated with connection + int telstate; // telnet state for this connection + int substate; // telnet subnegotiation state + int termsent; + int echo; + int ugoahead; + int igoahead; + int timing; + int backspace; + int ctrl_backspace; + int termstate; // terminal type for this connection + int width; + int height; + BOOL bResizeable; +} CONNECTION; + diff --git a/src/windows/wintel/telnet.c b/src/windows/wintel/telnet.c new file mode 100644 index 000000000..a334cf9e1 --- /dev/null +++ b/src/windows/wintel/telnet.c @@ -0,0 +1,814 @@ +/**************************************************************************** + + PROGRAM: telnet.c + + PURPOSE: Windows networking kernel - Telnet + + FUNCTIONS: + + WinMain() - calls initialization function, processes message loop + InitApplication() - initializes window data and registers window + InitInstance() - saves instance handle and creates main window + MainWndProc() - processes messages + About() - processes messages for "About" dialog box + + COMMENTS: + + Windows can have several copies of your application running at the + same time. The variable hInst keeps track of which instance this + application is so that processing will be to the correct window. + +****************************************************************************/ + +#include +#include +#include "telnet.h" +#include "auth.h" + +HANDLE hInst; /* current instance */ +HWND hWnd; /* Main window handle. */ +CONFIG *tmpConfig; +GLOBALHANDLE hGlobalMem, hTitleMem; +CONNECTION *con = NULL; +char hostdata[MAXGETHOSTSTRUCT]; +HGLOBAL ghCon; +SCREEN *fpScr; +int debug = 1; + +char __near strTmp[1024]; + +BOOL bAutoConnection = FALSE; +char szAutoHostName[64]; +char szUserName[64]; +char szHostName[64]; + +#ifdef KRB4 + #define WINDOW_CLASS "telnetWClass_4" +#endif + +#ifdef KRB5 + krb5_context k5_context; + #define WINDOW_CLASS "telnetWClass" +#endif + +/*+************************************************************************** + + FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) + + PURPOSE: calls initialization function, processes message loop + + COMMENTS: + + Windows recognizes this function by name as the initial entry point + for the program. This function calls the application initialization + routine, if no other instance of the program is running, and always + calls the instance initialization routine. It then executes a message + retrieval and dispatch loop that is the top-level control structure + for the remainder of execution. The loop is terminated when a WM_QUIT + message is received, at which time this function exits the application + instance by returning the value passed by PostQuitMessage(). + + If this function must abort before entering the message loop, it + returns the conventional value NULL. + +****************************************************************************/ + +int PASCAL +WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) +HANDLE hInstance; /* current instance */ +HANDLE hPrevInstance; /* previous instance */ +LPSTR lpCmdLine; /* command line */ +int nCmdShow; /* show-window type (open/icon) */ +{ + MSG msg; /* message */ + + if (!hPrevInstance) + if (!InitApplication(hInstance)) /* Initialize shared things */ + return (FALSE); /* Exits if unable to initialize */ + + /* Perform initializations that apply to a specific instance */ + + if (lpCmdLine[0]) { + bAutoConnection = TRUE; + lstrcpy((char *) szAutoHostName, lpCmdLine); + } + else bAutoConnection = FALSE; + + if (!InitInstance(hInstance, nCmdShow)) + return (FALSE); + + /* Acquire and dispatch messages until a WM_QUIT message is received. */ + + while (GetMessage(&msg, NULL, NULL, NULL)) { + TranslateMessage(&msg); /* Translates virtual key codes */ + DispatchMessage(&msg); /* Dispatches message to window */ + } + return (msg.wParam); /* Returns the value from PostQuitMessage */ +} + + +/*+************************************************************************** + + FUNCTION: InitApplication(HANDLE) + + PURPOSE: Initializes window data and registers window class + + COMMENTS: + + This function is called at initialization time only if no other + instances of the application are running. This function performs + initialization tasks that can be done once for any number of running + instances. + + In this case, we initialize a window class by filling out a data + structure of type WNDCLASS and calling the Windows RegisterClass() + function. Since all instances of this application use the same window + class, we only need to do this when the first instance is initialized. + + +****************************************************************************/ + +BOOL +InitApplication(hInstance) +HANDLE hInstance; /* current instance */ +{ + WNDCLASS wc; + + ScreenInit(hInstance); + + /* Fill in window class structure with parameters that describe the */ + /* main window. */ + + wc.style = CS_HREDRAW|CS_VREDRAW; /* Class style(s). */ + wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for */ + /* windows of this class. */ + wc.cbClsExtra = 0; /* No per-class extra data. */ + wc.cbWndExtra = 0; /* No per-window extra data. */ + wc.hInstance = hInstance; /* Application that owns the class. */ + wc.hIcon = NULL; //LoadIcon(hInstance, "NCSA"); + wc.hCursor = NULL; //Cursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; //GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */ + wc.lpszClassName = WINDOW_CLASS; /* Name used in call to CreateWindow. */ + + /* Register the window class and return success/failure code. */ + return (RegisterClass(&wc)); +} + + +/*+************************************************************************** + + FUNCTION: InitInstance(HANDLE, int) + + PURPOSE: Saves instance handle and creates main window + + COMMENTS: + + This function is called at initialization time for every instance of + this application. This function performs initialization tasks that + cannot be shared by multiple instances. + + In this case, we save the instance handle in a static variable and + create and display the main program window. + +****************************************************************************/ +BOOL +InitInstance(hInstance, nCmdShow) + HANDLE hInstance; /* Current instance identifier. */ + int nCmdShow; /* Param for first ShowWindow() call. */ +{ + int xScreen = 0, yScreen = 0; + + /* Save the instance handle in static variable, which will be used in */ + /* many subsequence calls from this application to Windows. */ + + hInst = hInstance; + + /* Create a main window for this application instance. */ + hWnd = CreateWindow( + WINDOW_CLASS, /* See RegisterClass() call. */ + "TCPWin", /* Text for window title bar. */ + WS_SYSMENU, /* Window style. */ + xScreen/3, /* Default horizontal position. */ + yScreen/3, /* Default vertical position. */ + xScreen/3, /* Default width. */ + yScreen/3, /* Default height. */ + NULL, /* Overlapped windows have no parent. */ + NULL, /* Use the window class menu. */ + hInstance, /* This instance owns this window. */ + NULL /* Pointer not needed. */ + ); + if (!hWnd) + return (FALSE); + +// ShowWindow(hWnd, SW_SHOW); /* Show the window */ +// UpdateWindow(hWnd); /* Sends WM_PAINT message */ + + { + WSADATA wsaData; + if (WSAStartup(0x0101, &wsaData) != 0) { /* Initialize the network */ + MessageBox(NULL, "Couldn't initialize Winsock!", + NULL, MB_OK | MB_ICONEXCLAMATION); + return FALSE; + } + } + + if (! OpenTelnetConnection()) { + WSACleanup(); + return(FALSE); + } + + #ifdef KRB5 + krb5_init_context(&k5_context); + krb5_init_ets(k5_context); + #endif + return (TRUE); +} + +/*+*************************************************************************** + + FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM) + + PURPOSE: Processes messages + + MESSAGES: + + WM_COMMAND - application menu (About dialog box) + WM_DESTROY - destroy window + +****************************************************************************/ + +long FAR PASCAL +MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + HSCREEN hgScr; + SCREEN *fpScr; + HGLOBAL hBuffer; + LPSTR lpBuffer; + char c; + int iEvent, namelen, cnt, ret; + char buf[1024]; + struct sockaddr_in name; + struct sockaddr_in remote_addr; + struct hostent *remote_host; + char *tmpCommaLoc; + + switch (message) { + + case WM_MYSCREENCHANGEBKSP: + if (!con) break; + con->backspace = wParam; + if (con->backspace == VK_BACK) { + con->ctrl_backspace = 0x7f; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_BS, TELNET_INI); + } + else { + con->ctrl_backspace = VK_BACK; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_DEL, TELNET_INI); + } + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", buf, 128, + TELNET_INI); + tmpCommaLoc = strchr(buf, ','); + if (tmpCommaLoc) { + tmpCommaLoc++; + if (con->backspace == VK_BACK) + strcpy(tmpCommaLoc, INI_HOST_BS); + else + strcpy(tmpCommaLoc, INI_HOST_DEL); + } + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + break; + + case WM_MYSCREENCHAR: + if (!con) break; + if (wParam == VK_BACK) + wParam = con->backspace; + else + if (wParam == 0x7f) + wParam = con->ctrl_backspace; + TelnetSend(con->ks, (char *)&wParam, 1, NULL); + break; + + case WM_MYSYSCHAR: + if (!con) break; + c = (char) wParam; + switch (c) { + case 'f': + getsockname(con->socket, (struct sockaddr *) &name, + (int *) &namelen); + wsprintf(buf, "ftp %d.%d.%d.%d\n", + name.sin_addr.S_un.S_un_b.s_b1, + name.sin_addr.S_un.S_un_b.s_b2, + name.sin_addr.S_un.S_un_b.s_b3, + name.sin_addr.S_un.S_un_b.s_b4); + TelnetSend(con->ks, buf, lstrlen(buf), NULL); + break; + case 'x': + hgScr = con->hScreen; + fpScr = (SCREEN *) GlobalLock(hgScr); + if (fpScr == NULL) break; + PostMessage(fpScr->hWnd, WM_CLOSE, NULL, NULL); + break; + + } + break; + + case WM_MYSCREENBLOCK: + if (!con) break; + hBuffer = (HGLOBAL) wParam; + lpBuffer = GlobalLock(hBuffer); + TelnetSend(con->ks, lpBuffer, lstrlen(lpBuffer), NULL); + GlobalUnlock(hBuffer); + break; + + case WM_MYSCREENCLOSE: + if (!con) break; + kstream_destroy(con->ks); + DestroyWindow(hWnd); + break; + + case WM_QUERYOPEN: + return(0); + break; + + case WM_DESTROY: /* message: window being destroyed */ + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + + case WM_NETWORKEVENT: + iEvent = WSAGETSELECTEVENT(lParam); + + switch (iEvent) { + + case FD_READ: + cnt = recv(con->socket, buf, 1024, NULL); + /* + The following line has been removed until kstream supports + non-blocking IO or larger size reads (jrivlin@fusion.com). + */ + /* cnt = kstream_read(con->ks, buf, 1024); */ + buf[cnt] = 0; + parse((CONNECTION *) con, (unsigned char *) buf, cnt); + ScreenEm(buf, cnt, con->hScreen); + break; + + case FD_CLOSE: + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + + case FD_CONNECT: + ret = WSAGETSELECTERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on Connect", ret); + OutputDebugString (buf); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + } + start_negotiation(con->ks); + break; + } + break; + + case WM_HOSTNAMEFOUND: + ret = WSAGETASYNCERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on GetHostbyName", ret); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + } + remote_host = (struct hostent *) hostdata; + remote_addr.sin_family = AF_INET; + remote_addr.sin_addr.S_un.S_un_b.s_b1 = remote_host->h_addr[0]; + remote_addr.sin_addr.S_un.S_un_b.s_b2 = remote_host->h_addr[1]; + remote_addr.sin_addr.S_un.S_un_b.s_b3 = remote_host->h_addr[2]; + remote_addr.sin_addr.S_un.S_un_b.s_b4 = remote_host->h_addr[3]; + #ifdef KRB4 + remote_addr.sin_port = htons(23); + #endif + #ifdef KRB5 + remote_addr.sin_port = htons(13131); + #endif + + connect(con->socket, (struct sockaddr*) &remote_addr, + sizeof(struct sockaddr)); + break; + + case WM_MYSCREENSIZE: + con->width = LOWORD(lParam); /* width in characters */ + con->height = HIWORD(lParam); /* height in characters */ + if (con->bResizeable && con->ks) + send_naws(con); + wsprintf(buf, "%d", con->height); + WritePrivateProfileString(INI_TELNET, INI_HEIGHT, buf, TELNET_INI); + wsprintf(buf, "%d", con->width); + WritePrivateProfileString(INI_TELNET, INI_WIDTH, buf, TELNET_INI); + break; + + default: /* Passes it on if unproccessed */ + return(DefWindowProc(hWnd, message, wParam, lParam)); + } + return (NULL); +} + + +/*+*************************************************************************** + + FUNCTION: SaveHostName(hostname) + + PURPOSE: Saves the currently selected host name in the KERBEROS.INI file + and returns the preferred backspace setting if one exists for + that host. + + RETURNS: VK_BACK or 0x7f depending on the desired backspace setting. + +****************************************************************************/ + +int +SaveHostName(char *host) +{ + char buf[128]; + char hostName[10][128]; + char *tmpCommaLoc; + char tmpName[128]; + char tmpBuf[80]; + int nhosts; + int n; + int iHostNum; + int bs; + + nhosts = 0; + for (iHostNum = 0; iHostNum < 10; iHostNum++) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", hostName[iHostNum], + 128, TELNET_INI); + strcpy(tmpName, hostName[iHostNum]); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) { + *tmpCommaLoc = '\0'; + while (tmpCommaLoc[1] == ' ') + tmpCommaLoc++; + } + if (!hostName[iHostNum][0]) + break; + nhosts++; + if (strcmp(tmpName, host) == 0) + break; + } + + for (iHostNum++; iHostNum < 10; iHostNum++) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", hostName[iHostNum], + 128, TELNET_INI); + if (!hostName[iHostNum][0]) + break; + nhosts++; + } + + if (tmpCommaLoc) + tmpCommaLoc++; + + if (tmpName[0] && tmpCommaLoc) { + if (_stricmp(tmpCommaLoc, INI_HOST_DEL) == 0) + bs = 0x7f; + else if (_stricmp(tmpCommaLoc, INI_HOST_BS) == 0) + bs = VK_BACK; + } + else { + GetPrivateProfileString(INI_TELNET, INI_BACKSPACE, INI_BACKSPACE_BS, + tmpBuf, sizeof(tmpBuf), TELNET_INI); + if (_stricmp(tmpBuf, INI_BACKSPACE_DEL) == 0) + bs = 0x7f; + else + bs = VK_BACK; + } + + strcpy(buf, tmpConfig->title); + strcat(buf, ", "); + if (bs == VK_BACK) + strcat(buf, INI_BACKSPACE_BS); + else + strcat(buf, INI_BACKSPACE_DEL); + + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + n = 1; + for (iHostNum = 0; iHostNum < nhosts; iHostNum++) { + strcpy(tmpName, hostName[iHostNum]); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) { + *tmpCommaLoc = '\0'; + while (tmpCommaLoc[1] == ' ') + tmpCommaLoc++; + } + if (strcmp(tmpName, host) != 0) { + wsprintf(tmpBuf, INI_HOST "%d", n++); + WritePrivateProfileString(INI_HOSTS, tmpBuf, hostName[iHostNum], + TELNET_INI); + } + } + return (bs); +} + +/*+*/ +int +OpenTelnetConnection(void) { + int nReturn, ret; + struct sockaddr_in sockaddr; + char *p; + static struct kstream_crypt_ctl_block ctl; + char buf[128]; + + hGlobalMem = GlobalAlloc(GPTR, sizeof(CONFIG)); + tmpConfig = (CONFIG *) GlobalLock(hGlobalMem); + + if (bAutoConnection) { + hTitleMem = GlobalAlloc(GPTR, lstrlen(szAutoHostName)); + tmpConfig->title = (char *) GlobalLock(hTitleMem); + lstrcpy(tmpConfig->title, (char *) szAutoHostName); + } else { + nReturn = DoDialog("OPENTELNETDLG", OpenTelnetDlg); + if (nReturn == FALSE) return(FALSE); + } + + con = (CONNECTION *) GetNewConnection(); + if (con == NULL) return(0); + + tmpConfig->width = GetPrivateProfileInt(INI_TELNET, INI_WIDTH, + DEF_WIDTH, TELNET_INI); + tmpConfig->height = GetPrivateProfileInt(INI_TELNET, INI_HEIGHT, + DEF_HEIGHT, TELNET_INI); + con->width = tmpConfig->width; + con->height = tmpConfig->height; + + con->backspace = SaveHostName(tmpConfig->title); + + if (con->backspace == VK_BACK) { + tmpConfig->backspace = TRUE; + con->ctrl_backspace = 0x7f; + } else { + tmpConfig->backspace = FALSE; + con->ctrl_backspace = 0x08; + } + + tmpConfig->hwndTel = hWnd; + con->hScreen = (HSCREEN) InitNewScreen((CONFIG *) tmpConfig); + if (!(con->hScreen)) { + OutputDebugString("Failed to initialize new screen! \r\n"); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + + ret = (SOCKET) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on socket = %d!", WSAGetLastError()); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + fpScr = (SCREEN *) GlobalLock(con->hScreen); + if (fpScr != NULL) + DestroyWindow(fpScr->hWnd); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + + con->socket = ret; + + sockaddr.sin_family = AF_INET ; + sockaddr.sin_addr.s_addr = htonl( INADDR_ANY ); + sockaddr.sin_port = htons( 0 ) ; + + ret = bind(con->socket, (struct sockaddr *) &sockaddr, + (int) sizeof(struct sockaddr_in)); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on bind!"); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + fpScr = (SCREEN *) GlobalLock(con->hScreen); + if (fpScr != NULL) + DestroyWindow(fpScr->hWnd); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + WSAAsyncSelect(con->socket, hWnd, WM_NETWORKEVENT, + FD_READ | FD_CLOSE | FD_CONNECT); + + lstrcpy(szHostName, tmpConfig->title); + p = strchr(szHostName, '@'); + if (p != NULL) { + *p = 0; + strcpy (szUserName, szHostName); + strcpy(szHostName, ++p); + } + + WSAAsyncGetHostByName(hWnd, WM_HOSTNAMEFOUND, szHostName, hostdata, + MAXGETHOSTSTRUCT); + GlobalUnlock(con->hScreen); +// GlobalUnlock(ghCon); +// GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + + ctl.encrypt = auth_encrypt; + ctl.decrypt = auth_decrypt; + ctl.init = auth_init; + ctl.destroy = auth_destroy; + + con->ks = kstream_create_from_fd(con->socket, &ctl, NULL); + + kstream_set_buffer_mode(con->ks, 0); + + if (con->ks == NULL) + return(-1); + + return(1); +} + +/*+*/ +CONNECTION * +GetNewConnection(void) { + CONNECTION *fpCon; + + ghCon = GlobalAlloc(GHND, sizeof(CONNECTION)); + if (ghCon == NULL) return NULL; + fpCon = (CONNECTION *) GlobalLock(ghCon); + if (fpCon == NULL) return NULL; + fpCon->backspace = TRUE; + fpCon->bResizeable = TRUE; + return(fpCon); +} + +/*+***************************************************************************/ +int NEAR +DoDialog(char *szDialog, FARPROC lpfnDlgProc) { + int nReturn; + + lpfnDlgProc = MakeProcInstance(lpfnDlgProc, hInst); + if (lpfnDlgProc == NULL) + MessageBox(hWnd, "Couldn't make procedure instance", NULL, MB_OK); + + nReturn = DialogBox(hInst, szDialog, hWnd, lpfnDlgProc); + FreeProcInstance(lpfnDlgProc); + return (nReturn); +} + +/*+*************************************************************************** + + FUNCTION: OpenTelnetDlg(HWND, unsigned, WORD, LONG) + + PURPOSE: Processes messages for "Open New Telnet Connection" dialog box + + MESSAGES: + + WM_INITDIALOG - initialize dialog box + WM_COMMAND - Input received + +****************************************************************************/ + +BOOL FAR PASCAL +OpenTelnetDlg(HWND hDlg, WORD message, WORD wParam, LONG lParam) { + char szConnectName[256]; + HDC hDC; + int xExt, yExt; + DWORD Ext; + HWND hEdit; + int nLen; + int iHostNum = 0; + char tmpName[128], tmpBuf[80]; + char *tmpCommaLoc; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + hDC = GetDC(hDlg); + Ext = GetDialogBaseUnits(); + xExt = (190 *LOWORD(Ext)) /4 ; + yExt = (72 * HIWORD(Ext)) /8 ; + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", tmpName, + 128, TELNET_INI); + if (tmpName[0]) { + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + SetDlgItemText(hDlg, TEL_CONNECT_NAME, tmpName); + } + hEdit = GetWindow(GetDlgItem(hDlg, TEL_CONNECT_NAME), GW_CHILD); + while (TRUE) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum++); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", tmpName, + 128, TELNET_INI); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + if (tmpName[0]) + SendDlgItemMessage(hDlg, TEL_CONNECT_NAME, CB_ADDSTRING, 0, + (LPARAM) ((LPSTR) tmpName)); + else + break; + } + SetWindowPos(hDlg, NULL, (GetSystemMetrics(SM_CXSCREEN)/2)-(xExt/2), + (GetSystemMetrics(SM_CYSCREEN)/2)-(yExt/2), 0, 0, + SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW); + ReleaseDC(hDlg, hDC); + SendMessage(hEdit, WM_USER+1, NULL, NULL); + SendMessage(hDlg, WM_SETFOCUS, NULL, NULL); + return (TRUE); + + case WM_COMMAND: /* message: received a command */ + switch (wParam) { + case TEL_CANCEL: + EndDialog(hDlg, FALSE); /* Exits the dialog box */ + break; + + case TEL_OK: + GetDlgItemText(hDlg, TEL_CONNECT_NAME, szConnectName, 256); + nLen = lstrlen(szConnectName); + if (nLen == 0) { + MessageBox(hDlg, "You must enter a session name!", + NULL, MB_OK); + break; + } + hTitleMem = GlobalAlloc(GPTR, nLen); + tmpConfig->title = (char *) GlobalLock(hTitleMem); + lstrcpy(tmpConfig->title, szConnectName); + EndDialog(hDlg, TRUE); + break; + } + return (FALSE); + } + return (FALSE); /* Didn't process a message */ +} + +/*+*************************************************************************** + + FUNCTION: TelnetSend(kstream ks, char *buf, int len, int flags) + + PURPOSE: This is a replacement for the WinSock send() function, to + send a buffer of characters to an output socket. It differs + by retrying endlessly if sending the bytes would cause + the send() to block. observed EWOULDBLOCK + errors when running using TCP Software's PC/TCP 3.0 stack, + even when writing as little as 109 bytes into a socket + that had no more than 9 bytes queued for output. Note also that + a kstream is used during output rather than a socket to facilitate + encryption. + + Eventually, for cleanliness and responsiveness, this + routine should not loop; instead, if the send doesn't + send all the bytes, it should put them into a buffer + and return. Message handling code would send out the + buffer whenever it gets an FD_WRITE message. + +****************************************************************************/ + +int +TelnetSend(kstream ks, char *buf, int len, int flags) { + + int writelen; + int origlen = len; + + while (TRUE) { + writelen = kstream_write(ks, buf, len); + + if (writelen == len) /* Success, first or Nth time */ + return (origlen); + + if (writelen == SOCKET_ERROR) { + if (WSAGetLastError() != WSAEWOULDBLOCK) + return (SOCKET_ERROR); /* Some error */ + /* For WOULDBLOCK, immediately repeat the send. */ + } + else { + /* Partial write; update the pointers and retry. */ + len -= writelen; + buf += writelen; + } + } +} diff --git a/src/windows/wintel/telnet.def b/src/windows/wintel/telnet.def new file mode 100644 index 000000000..e5c1061d9 --- /dev/null +++ b/src/windows/wintel/telnet.def @@ -0,0 +1,49 @@ +; module-definition file for testdll -- used by LINK.EXE +NAME telnet ; application's module name + +DESCRIPTION 'Sample Microsoft Windows Application' + +EXETYPE WINDOWS ; required for all Windows applications + +STUB 'WINSTUB.EXE' ; Generates error message if application + ; is run without Windows + +;CODE can be moved in memory and discarded/reloaded +CODE PRELOAD MOVEABLE +;DISCARDABLE + +;DATA must be MULTIPLE if program can be invoked more than once +DATA PRELOAD MOVEABLE + + +HEAPSIZE 10240 + +; All functions that will be called by any Windows routine +; MUST be exported. + +EXPORTS + MainWndProc @1 ; name of window processing function + OpenTelnetDlg @3 ; name of "Open New Telnet Connection" Dialog Function + +IMPORTS + WINSOCK.WSAStartup + WINSOCK.WSACleanup + WINSOCK.WSAAsyncSelect + WINSOCK.WSAGetLastError + WINSOCK.WSAAsyncGetHostByName + WINSOCK.listen + WINSOCK.accept + WINSOCK.__wsafdisset + WINSOCK.socket + WINSOCK.bind + WINSOCK.gethostbyname + WINSOCK.getsockname + WINSOCK.htons + WINSOCK.connect + WINSOCK.recv + WINSOCK.send + WINSOCK.htonl + WINSOCK.closesocket + WINSOCK.select + WINSOCK.ioctlsocket + WINSOCK.getpeername diff --git a/src/windows/wintel/telnet.dlg b/src/windows/wintel/telnet.dlg new file mode 100644 index 000000000..8b73ee842 --- /dev/null +++ b/src/windows/wintel/telnet.dlg @@ -0,0 +1,77 @@ +DLGINCLUDE RCDATA DISCARDABLE +BEGIN + "DIALOG.H\0" +END + +OPENTELNETDLG DIALOG 63, 65, 175, 51 +STYLE DS_ABSALIGN | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Open New Telnet Connection" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "To Host:", -1, "STATIC", NOT WS_GROUP, 3, 10, 33, 10 + CONTROL "", TEL_CONNECT_NAME, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_GROUP | WS_TABSTOP, 42, 9, 128, 60 + CONTROL "OK", TEL_OK, "BUTTON", WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON, 27, 30, 51, 14 + CONTROL "Cancel", TEL_CANCEL, "BUTTON", WS_TABSTOP, 97, 30, 51, 14 +END + +ABOUTBOX DIALOG 69, 33, 175, 148 +STYLE DS_ABSALIGN | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About TCPwin" +BEGIN + ICON "NCSA", -1, 15, 12, 16, 16 + CTEXT "Microsoft Windows", -1, 48, 11, 93, 8 + CTEXT "NCSA TCP/IP Networking Kernel", -1, 38, 21, 120, 8 + CTEXT "Version 1.0b2", -1, 20, 31, 144, 8 + CONTROL "OK", IDOK, "BUTTON", WS_GROUP, 72, 126, 39, 14 + CTEXT "Written By:", 606, 20, 50, 144, 8 + CTEXT "Jon Mittelhauser (jonm@ncsa.uiuc.edu)", 607, 20, 61, 144, 8 + CTEXT "Chris Wilson (cwilson@ncsa.uiuc.edu)", 608, 20, 71, 144, 8 + CTEXT "Special Thanks to:", 609, 21, 97, 143, 8 + CTEXT "Joe Lepore for DPMI interface code", 610, 20, 107, 144, 8 + CTEXT "Keberized by: Cygnus Support", 611, 20, 82, 144, 8 +END + +CONFIG_DLG DIALOG 6, 18, 160, 130 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Configure Session" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Session Name:", 301, 1, 5, 54, 8 + LTEXT "Default Session", CON_SESSIONNAME, 55, 5, 105, 8 + LTEXT "Window Title:", 303, 1, 17, 49, 8 + EDITTEXT CON_WINDOWTITLE, 53, 15, 102, 12, ES_AUTOHSCROLL + CONTROL "132", CON_COLUMNS132, "Button", BS_AUTORADIOBUTTON | + WS_GROUP, 53, 33, 39, 10 + CONTROL "80", CON_COLUMNS80, "Button", BS_AUTORADIOBUTTON, 110, + 33, 39, 10 + CONTROL "Backspace", CON_BACKSPACE, "Button", BS_AUTORADIOBUTTON | + WS_GROUP, 53, 46, 49, 10 + CONTROL "Delete", CON_DELETE, "Button", BS_AUTORADIOBUTTON, 110, + 46, 39, 10 + CONTROL "CRLF", CON_CRLF, "Button", BS_AUTORADIOBUTTON | + WS_GROUP, 53, 59, 39, 10 + CONTROL "CR-NUL", CON_CRNUL, "Button", BS_AUTORADIOBUTTON, 110, + 59, 39, 10 + CONTROL "Buffers", CON_BUFFERS, "Button", BS_AUTORADIOBUTTON | + WS_GROUP, 53, 72, 39, 10 + CONTROL "Sends", CON_SENDS, "Button", BS_AUTORADIOBUTTON, 110, + 72, 39, 10 + LTEXT "Columns", 313, 1, 33, 49, 8 + LTEXT "Backspace is", 314, 1, 46, 51, 8 + LTEXT "Return Sends", 315, 1, 59, 49, 8 + LTEXT "Echo Mode", 316, 1, 72, 49, 8 + CONTROL "Scrollback", CON_SCRLBCK, "Button", BS_AUTOCHECKBOX | + WS_TABSTOP, 1, 86, 50, 10 + EDITTEXT CON_NUMLINES, 53, 85, 28, 12, ES_AUTOHSCROLL + LTEXT "lines", 319, 85, 86, 33, 8 + DEFPUSHBUTTON "OK", CON_OK, 20, 108, 50, 14, WS_GROUP + PUSHBUTTON "Use Defaults", CON_USEDEFAULTS, 90, 108, 50, 14 +END + +IDM_PRINTQUEUE DIALOG 69, 25, 160, 80 +STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_VSCROLL | WS_HSCROLL | WS_SYSMENU +CAPTION "Print Queue" +FONT 8, "MS Sans Serif" +BEGIN +END diff --git a/src/windows/wintel/telnet.h b/src/windows/wintel/telnet.h new file mode 100644 index 000000000..ee68d7630 --- /dev/null +++ b/src/windows/wintel/telnet.h @@ -0,0 +1,36 @@ +#ifndef TELNET_H_INC +#define TELNET_H_INC + +#include +#include + +#ifdef KRB5 +#include "krb5.h" +#include "k5stream.h" +#endif + +#include "dialog.h" +#include "screen.h" +#include "struct.h" +#include "wt-proto.h" +#include "winsock.h" +#include "ini.h" + +/* globals */ +extern char szAutoHostName[64]; +extern char szUserName[64]; +extern char szHostName[64]; + +#ifdef KRB5 + extern krb5_context k5_context; +#endif + +extern void parse(CONNECTION *con,unsigned char *st,int cnt); +extern void send_naws(CONNECTION *con); +extern char __near strTmp[]; + +#define DEF_WIDTH 80 +#define DEF_HEIGHT 24 + +#endif /* TELNET_H_INC */ + diff --git a/src/windows/wintel/telnet.rc b/src/windows/wintel/telnet.rc new file mode 100644 index 000000000..bcdcdb569 --- /dev/null +++ b/src/windows/wintel/telnet.rc @@ -0,0 +1,26 @@ +#include +#include "dialog.h" +#include "telnet.dlg" +#include "screen.h" + +NCSA ICON ncsa.ico +TERMINAL ICON terminal.ico + +ScreenMenu MENU +BEGIN + POPUP "&Configure" + BEGIN + MENUITEM "&Backspace", IDM_BACKSPACE, CHECKED + MENUITEM "&Delete", IDM_DELETE + MENUITEM SEPARATOR + MENUITEM "&Font...", IDM_FONT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Copy Cltr+Ins",IDM_COPY + MENUITEM "&Paste Shift+Ins", IDM_PASTE + #ifdef _DEBUG + MENUITEM "&Debug", IDM_DEBUG + #endif + END +END diff --git a/src/windows/wintel/telopts.h b/src/windows/wintel/telopts.h new file mode 100644 index 000000000..e928a8428 --- /dev/null +++ b/src/windows/wintel/telopts.h @@ -0,0 +1,159 @@ +/* +* telopts.h +* Used for telnet options +**************************************************************************** +* * +* * +* NCSA Telnet * +* by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer * +* Additions by Kurt Mahan, Heeren Pathak, & Quincey Koziol * +* * +* National Center for Supercomputing Applications * +* 152 Computing Applications Building * +* 605 E. Springfield Ave. * +* Champaign, IL 61820 * +* * +**************************************************************************** +* Quincey Koziol +* Defines for telnet options and related things +*/ + +#ifndef TELOPTS_H +#define TELOPTS_H + +#define NUMLMODEOPTIONS 30 + +/* Definitions for telnet protocol */ + +#define STNORM 0 + +/* Definition of the lowest telnet byte following an IAC byte */ +#define LOW_TEL_OPT 236 + +#define TEL_EOF 236 +#define SUSP 237 +#define ABORT 238 + +#define SE 240 +#define NOP 241 +#define DM 242 +#define BREAK 243 +#define IP 244 +#define AO 245 +#define AYT 246 +#define EC 247 +#define EL 248 +#define GOAHEAD 249 +#define SB 250 +#define WILLTEL 251 +#define WONTTEL 252 +#define DOTEL 253 +#define DONTTEL 254 +#define IAC 255 + +/* Assigned Telnet Options */ +#define BINARY 0 +#define ECHO 1 +#define RECONNECT 2 +#define SGA 3 +#define AMSN 4 +#define STATUS 5 +#define TIMING 6 +#define RCTAN 7 +#define OLW 8 +#define OPS 9 +#define OCRD 10 +#define OHTS 11 +#define OHTD 12 +#define OFFD 13 +#define OVTS 14 +#define OVTD 15 +#define OLFD 16 +#define XASCII 17 +#define LOGOUT 18 +#define BYTEM 19 +#define DET 20 +#define SUPDUP 21 +#define SUPDUPOUT 22 +#define SENDLOC 23 +#define TERMTYPE 24 +#define EOR 25 +#define TACACSUID 26 +#define OUTPUTMARK 27 +#define TERMLOCNUM 28 +#define REGIME3270 29 +#define X3PAD 30 +#define NAWS 31 +#define TERMSPEED 32 +#define TFLOWCNTRL 33 +#define LINEMODE 34 + #define MODE 1 + #define MODE_EDIT 1 + #define MODE_TRAPSIG 2 + #define MODE_ACK 4 + #define MODE_SOFT_TAB 8 + #define MODE_LIT_ECHO 16 + + #define FORWARDMASK 2 + + #define SLC 3 + #define SLC_DEFAULT 3 + #define SLC_VALUE 2 + #define SLC_CANTCHANGE 1 + #define SLC_NOSUPPORT 0 + #define SLC_LEVELBITS 3 + + #define SLC_ACK 128 + #define SLC_FLUSHIN 64 + #define SLC_FLUSHOUT 32 + + #define SLC_SYNCH 1 + #define SLC_BRK 2 + #define SLC_IP 3 + #define SLC_AO 4 + #define SLC_AYT 5 + #define SLC_EOR 6 + #define SLC_ABORT 7 + #define SLC_EOF 8 + #define SLC_SUSP 9 + #define SLC_EC 10 + #define SLC_EL 11 + #define SLC_EW 12 + #define SLC_RP 13 + #define SLC_LNEXT 14 + #define SLC_XON 15 + #define SLC_XOFF 16 + #define SLC_FORW1 17 + #define SLC_FORW2 18 + #define SLC_MCL 19 + #define SLC_MCR 20 + #define SLC_MCWL 21 + #define SLC_MCWR 22 + #define SLC_MCBOL 23 + #define SLC_MCEOL 24 + #define SLC_INSRT 25 + #define SLC_OVER 26 + #define SLC_ECR 27 + #define SLC_EWR 28 + #define SLC_EBOL 29 + #define SLC_EEOL 30 + +#define XDISPLOC 35 +#define ENVIRONMENT 36 +#define AUTHENTICATION 37 +#define DATA_ENCRYPTION 38 +#define XOPTIONS 255 + +#define LINEMODE_MODES_SUPPORTED 0x1B +/* set this flag for linemode special functions which are supported by Telnet, even though they are not currently active */ +/* This is to allow the other side to negotiate to a "No Support" state for an option */ +/* and then change later to supporting it, so we know it's ok to change our "No Support" */ +/* state to something else ("Can't Change", "Value", whatever) */ +#define SLC_SUPPORTED 0x10 + +#define ESCFOUND 5 +#define IACFOUND 6 +#define NEGOTIATE 1 + +#endif /* telopts.h */ + diff --git a/src/windows/wintel/terminal.ico b/src/windows/wintel/terminal.ico new file mode 100644 index 000000000..7ec59e980 Binary files /dev/null and b/src/windows/wintel/terminal.ico differ diff --git a/src/windows/wintel/wt-proto.h b/src/windows/wintel/wt-proto.h new file mode 100644 index 000000000..67f550c4f --- /dev/null +++ b/src/windows/wintel/wt-proto.h @@ -0,0 +1,19 @@ +int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int); +BOOL InitApplication(HANDLE); +BOOL InitInstance(HANDLE, int); +long FAR PASCAL MainWndProc(HWND, UINT, WPARAM, LPARAM); +BOOL FAR PASCAL About(HWND, WORD, WORD, LONG); +BOOL FAR PASCAL OpenTelnetDlg(HWND, WORD, WORD, LONG); +int TelnetSend(kstream, char *, int, int); +BOOL FAR PASCAL ConfigSessionDlg(HWND, WORD, WORD, LONG); + +int OpenTelnetConnection(void); +int NEAR DoDialog(char *szDialog, FARPROC lpfnDlgProc); +///HCONNECTION FindConnectionFromPortNum(int ID); +///HCONNECTION FindConnectionFromTelstate(int telstate); +///HCONNECTION FindConnectionFromScreen(HSCREEN hScreen); +CONNECTION * GetNewConnection(void); +void start_negotiation(kstream ks); +/* somewhere... */ +struct machinfo * FAR PASCAL Shostlook(char *hname); +