⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtelnet.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/* dtelnet.c
 * Copyright (c) 1997 David Cole
 *
 * Mainline for the dtelnet program.  The actions performed are:
 * - All menu management.
 * - .INI and .HLP file identification.
 * - Application window management.
 * - Child window placement.
 * - Command line argument parsing.
 *
 * The application window has two child windows; the terminal window,
 * and the status bar.  No drawing is performed in the application
 * window.
 */
#include <windows.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <direct.h>

#include "platform.h"
#include "utils.h"
#include "log.h"
#include "term.h"
#include "emul.h"
#include "socket.h"
#include "about.h"
#include "connect.h"
#include "filetype.h"
#include "status.h"
#include "font.h"
#include "argv.h"
#include "dialog.h"
#include "raw.h"
#include "termdef.h"
#include "printing.h"
#include "editor.h"
#include "proxy.h"
#include "dtchars.h"
#include "dtelnet.h"


/* Windows classname of application window
 */
static char* telnetWinClass = "DTelnetWClass";

static HWND telnetWnd;		/* handle of application window */

static HINSTANCE instanceHnd;	/* application instance handle */
static char helpFileName[_MAX_PATH + 1]; /* Help file name*/
static char iniFileName[_MAX_PATH + 1];	/* INI file to use */

EmulNames emuls;


HINSTANCE telnetGetInstance(void)
{
    return instanceHnd;
}
HWND telnetGetWnd(void)
{
    return telnetWnd;
}

/* Destroy the application window to trigger exit
 */
void telnetExit()
{
    DestroyWindow(telnetWnd);
}

/* Return the name of the application
 */
char* telnetAppName()
{
    return "Dave's Telnet";
}

/* Report a fatal error then exit
 *
 * Args:
 * fmt - printf format string
 * ... - arguments to format string
 */
void telnetFatal(const char* fmt, ...)
{
    va_list ap;
    char msg[512];

    va_start(ap, fmt);
    vsprintf(msg, fmt, ap);
    MessageBox(telnetWnd, msg, telnetAppName(),
	       MB_APPLMODAL|MB_ICONSTOP|MB_OK);
    telnetExit();
}

/* Return the name of the .INI file
 */
char* telnetIniFile()
{
    return iniFileName;
}
/* Add previous connections to the history on the menu.
 *
 * Args:
 * menu - handle of application window menu
 *
 * Maintain the connection history in the Connect menu.  Gray entries
 * when we are online.
 */
static void addConnectHistory(HMENU menu)
{
    int num;			/* iterate over connection history */
    char histline [MAX_HISTORY_SIZE];
    char* text;			/* formatted session */
    UINT action = socketOffline() ? MF_ENABLED : MF_GRAYED;

    for (num = 0; (text = connectGetHistory (histline, num, TRUE)) != NULL; ++num) {
	int id = ID_CONNECT_HISTORY + num;
	if (GetMenuState(menu, id, MF_BYCOMMAND) == (UINT)-1) {
	    if (num == 0)
		AppendMenu(menu, MF_ENABLED | MF_SEPARATOR, 0, NULL);
	    AppendMenu(menu, action, id, text);
	} else
	ModifyMenu(menu, id, MF_BYCOMMAND | action, id, text);
    }
}

/* Menu is about to pop up - customise it
 *
 * Args:
 * wnd -  handle of application window
 * menu - handle of application window menu
 */
static void initMenu(HWND wnd, HMENU menu)
{
    const char *termname;
    HMENU terminalMenu, emulateMenu;
    unsigned int i;

    if (socketOffline()) {
	/* We are offline, enable connect, disable disconnect
	 */
	EnableMenuItem(menu, (UINT)ID_CONNECT_REMOTE_SYSTEM,
					 MF_BYCOMMAND | MF_ENABLED);
	EnableMenuItem(menu, (UINT)ID_CONNECT_DISCONNECT,
					 MF_BYCOMMAND | MF_GRAYED);
	/* Disable copy/paste
	 */
	EnableMenuItem(menu, ID_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
	EnableMenuItem(menu, ID_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);

        /* Enable Proxy Settings
         */
        EnableMenuItem(menu, (UINT)ID_CONNECT_PROXY, MF_BYCOMMAND | MF_ENABLED);
    } else {
	/* We are online, disable connect, enable disconnect
	 */
	EnableMenuItem(menu, (UINT)ID_CONNECT_REMOTE_SYSTEM,
					 MF_BYCOMMAND | MF_GRAYED);
	EnableMenuItem(menu, (UINT)ID_CONNECT_DISCONNECT,
					 MF_BYCOMMAND | MF_ENABLED);

	/* Enable copy if we are in windows select mode, and there is
	 * a selection.
	 */
	EnableMenuItem(menu, ID_EDIT_COPY,
					 MF_BYCOMMAND | (!termAutoCopy() && termHaveSelection()
							 ? MF_ENABLED : MF_GRAYED));
	/* Enable Edit/Paste when there is text on clipboard
	 */
	if (OpenClipboard(wnd)) {
	    if (IsClipboardFormatAvailable(CF_TEXT)
		|| IsClipboardFormatAvailable(CF_OEMTEXT))
		EnableMenuItem(menu, ID_EDIT_PASTE, MF_BYCOMMAND | MF_ENABLED);
			else
		EnableMenuItem(menu, ID_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
			CloseClipboard();
	}
        /* Disable Proxy Settings
         */
        EnableMenuItem(menu, (UINT)ID_CONNECT_PROXY, MF_BYCOMMAND | MF_GRAYED);
    }

    /* Initialise the Connect menu
     */
    CheckMenuItem(menu, (UINT)ID_CONNECT_EXIT_DISCONNECT,
	MF_BYCOMMAND | (connectGetExitOnDisconnect()
			? MF_CHECKED : MF_UNCHECKED));
	addConnectHistory(GetSubMenu(menu, 0));

    /* Initialise the Edit menu
     */
    CheckMenuItem(menu, (UINT)ID_EDIT_AUTO_COPY,
	MF_BYCOMMAND | (termAutoCopy()
			? MF_CHECKED : MF_UNCHECKED));
    CheckMenuItem(menu, (UINT)ID_TERMINAL_BOTTOM_ON_OUTPUT,
	MF_BYCOMMAND | (termBottomOnOutput()
			? MF_CHECKED : MF_UNCHECKED));

    if (editGetCMMode()==ID_CM_FREE) {
	CheckMenuItem(menu, ID_CM_FREE, MF_BYCOMMAND | MF_CHECKED);
	CheckMenuItem(menu, ID_CM_TEXT, MF_BYCOMMAND | MF_UNCHECKED);
    } else {
	CheckMenuItem(menu, ID_CM_FREE, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(menu, ID_CM_TEXT, MF_BYCOMMAND | MF_CHECKED);
    }

    CheckMenuItem(menu, (UINT)ID_TERMINAL_BACKSPACE_ALT,
	MF_BYCOMMAND | (connectGetBs2DelOption() ? MF_CHECKED : MF_UNCHECKED));

    CheckMenuItem(menu, ID_TERMINAL_CS_BLOCK,
	MF_BYCOMMAND | (termCursorStyle() == cursorBlock) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(menu, ID_TERMINAL_CS_UNDERLINE,
	MF_BYCOMMAND | (termCursorStyle() == cursorUnderLine) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(menu, ID_TERMINAL_CS_VERTLINE,
	MF_BYCOMMAND | (termCursorStyle() == cursorVertLine) ? MF_CHECKED : MF_UNCHECKED);

    EnableMenuItem(menu, (UINT)ID_TERMINAL_START_LOGGING,
    	MF_BYCOMMAND | (logLogging() ? MF_GRAYED : MF_ENABLED));
    EnableMenuItem(menu, (UINT)ID_TERMINAL_STOP_LOGGING,
	MF_BYCOMMAND | (logLogging() ? MF_ENABLED : MF_GRAYED));
    CheckMenuItem(menu, (UINT)ID_TERMINAL_LOG_SESSION,
    	MF_BYCOMMAND | (logLoggingSession()
    			? MF_CHECKED : MF_UNCHECKED));
    CheckMenuItem(menu, (UINT)ID_TERMINAL_LOG_PROTOCOL,
	MF_BYCOMMAND | (logLoggingProtocol()
    			? MF_CHECKED : MF_UNCHECKED));
    CheckMenuItem(menu, (UINT)ID_TERMINAL_ATTPRINT,
	MF_BYCOMMAND | (termAttachedPrinter()
    			? MF_CHECKED : MF_UNCHECKED));
    CheckMenuItem(menu, (UINT)ID_TERMINAL_ENABLE_PRINTSCR,
	MF_BYCOMMAND | (termPrintScreenEnabled()
    			? MF_CHECKED : MF_UNCHECKED));
    EnableMenuItem(menu, (UINT)ID_TERMINAL_PRINTSCREEN,
    	MF_BYCOMMAND | (termPrintScreenEnabled() ? MF_ENABLED : MF_GRAYED));

    /* Initialise the Terminal menu
     */
    telnetEnumTermProfiles(&emuls);
    termname = emulGetTerm()->name;

    terminalMenu = GetSubMenu(menu, 3);
    if (!terminalMenu) return;

    emulateMenu = GetSubMenu(terminalMenu, 4);
    if (!emulateMenu) return;
    
    for (i=0; i < emuls.num; i++)
    {
	int id = ID_MENU_EMULATE_FIRST + i;
	if (GetMenuState(menu, id, MF_BYCOMMAND) == (UINT)-1) {
	    AppendMenu(emulateMenu, MF_STRING, id, emuls.names[i]);
	} else
	ModifyMenu(menu, id, MF_BYCOMMAND | MF_STRING, id, emuls.names[i]);
	CheckMenuItem(emulateMenu, id, MF_BYCOMMAND
           | (strcmp(termname, emuls.names[i])==0 ? MF_CHECKED : MF_UNCHECKED));
    }

}

/* The telnet window has been created, the terminal window has been
 * created and sized.  Set our initial window size if given.
 */
void initSetWindowPos(HWND telnetWnd)
{
		RECT workspace;		/* the area of the useable workspace */
		RECT window;		/* the area of the application window */
		int x, y;			/* the new coordinates of the window */

		if (!term.useInitPos)
				return;

#ifdef WIN32
		SystemParametersInfo(SPI_GETWORKAREA, 0, &workspace, 0);
#else
		workspace.left = workspace.top = 0;
		workspace.right = GetSystemMetrics(SM_CXSCREEN);
		workspace.bottom = GetSystemMetrics(SM_CYSCREEN);
#endif
		GetWindowRect(telnetWnd, &window);

		if (term.winInitPos.cx < 0)
				x = workspace.right - (window.right - window.left)
			+ term.winInitPos.cx;
		else
				x = term.winInitPos.cx;

		if (term.winInitPos.cy < 0)
				y = workspace.bottom - (window.bottom - window.top)
			+ term.winInitPos.cy;
		else
				y = term.winInitPos.cy;

    SetWindowPos(telnetWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

static void recalcInitPos(void)
{
    RECT rect;
    RECT workspace;		/* the area of the useable workspace */

    if (!term.useInitPos)
	return;
    GetWindowRect(telnetWnd, &rect);
#ifdef WIN32
    SystemParametersInfo(SPI_GETWORKAREA, 0, &workspace, 0);
#else
    workspace.top = workspace.left = 0;
		workspace.right = GetSystemMetrics(SM_CXSCREEN);
    workspace.bottom = GetSystemMetrics(SM_CYSCREEN);
#endif

    if (rect.left >= 0)
				term.winInitPos.cx = rect.left;
    else
	term.winInitPos.cx = rect.right - workspace.right;
    if (rect.top >= 0)
        term.winInitPos.cy = rect.top;
    else
	term.winInitPos.cy = rect.bottom - workspace.bottom;
    statusRedraw();
}

/* The terminal window has just resized to specified width/height.  We
 * have to resize ourselves to allow the terminal resize.
 *
 * Args:
 * xs - width (in pixels) of the terminal child window
 * ys - height (in pixels) of the terminal child window
 */
void telnetTerminalSize(int xs, int ys)
{
    RECT window;		/* screen rectangle of application window */
    RECT client;		/* size of client rectangle */
    RECT status;		/* size/position of status bar */
    SIZE newSize;		/* calculate new size of application window */
    int statusHeight;		/* calculate height of status bar child */

    /* Query and calculate current sizes and positions of all players
     */
    GetWindowRect(telnetWnd, &window);
    GetClientRect(telnetWnd, &client);
    GetWindowRect(statusGetWnd(), &status);
    statusHeight = status.bottom - status.top;

    /* Work out the new size of the application window
     */
    newSize.cx = xs + window.right - window.left - client.right;
    newSize.cy = ys + window.bottom - window.top - client.bottom
	+ statusHeight;

    /* Now make ourselves the adjusted size
     */
    SetWindowPos(telnetWnd, HWND_TOPMOST, 0, 0,
		 newSize.cx, newSize.cy,
		 SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
		/* Move the status bar to the new position
     */
    MoveWindow(statusGetWnd(), 0, ys, xs, statusHeight, TRUE);
}

/* The user is dragging the window frame.  Modify the resize as it is
 * happening to force a grid of one character.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -