From b44b307ac0fc00f2a61ef64d4681fe201ecb927c Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 9 Mar 2002 17:59:15 +0000 Subject: [PATCH] ANSI remote printer support. Raw mode only. git-svn-id: svn://svn.tartarus.org/sgt/putty@1581 cda61777-01e9-0310-a592-d414129be87e --- Makefile | 1 + doc/config.but | 34 +++++++++++++++++- putty.h | 13 +++++++ settings.c | 2 ++ terminal.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- windlg.c | 48 +++++++++++++++++++++++-- 6 files changed, 205 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ed0c8319..3c27e211 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ RES=res ##-- objects putty puttytel GOBJS1 = window.$(OBJ) windlg.$(OBJ) winctrls.$(OBJ) terminal.$(OBJ) GOBJS2 = sizetip.$(OBJ) wcwidth.$(OBJ) unicode.$(OBJ) logging.$(OBJ) +GOBJS3 = printing.$(OBJ) ##-- objects putty puttytel plink LOBJS1 = telnet.$(OBJ) raw.$(OBJ) rlogin.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ) ##-- objects putty plink diff --git a/doc/config.but b/doc/config.but index 5387a8a3..04dd0d01 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1,4 +1,4 @@ -\versionid $Id: config.but,v 1.28 2002/03/09 11:47:39 simon Exp $ +\versionid $Id: config.but,v 1.29 2002/03/09 17:59:15 simon Exp $ \C{config} Configuring PuTTY @@ -380,6 +380,38 @@ this configuration option to override its choice: you can force local line editing to be turned on, or force it to be turned off, instead of relying on the automatic detection. +\S{config-printing} Remote-controlled printing + +\cfg{winhelp-topic}{terminal.printing} + +A lot of VT100-compatible terminals support printing under control +of the remote server. PuTTY supports this feature as well, but it is +turned off by default. + +To enable remote-controlled printing, choose a printer from the +\q{Printer to send ANSI printer output to} drop-down list box. This +should allow you to select from all the printers you have installed +drivers for on your computer. Alternatively, you can type the +network name of a networked printer (for example, +\c{\\\\printserver\\printer1}) even if you haven't already +installed a driver for it on your own machine. + +When the remote server attempts to print some data, PuTTY will send +that data to the printer \e{raw} - without translating it, +attempting to format it, or doing anything else to it. It is up to +you to ensure your remote server knows what type of printer it is +talking to. + +Since PuTTY sends data to the printer raw, it cannot offer options +such as portrait versus landscape, print quality, or paper tray +selection. All these things would be done by your PC printer driver +(which PuTTY bypasses); if you need them done, you will have to find +a way to configure your remote server to do them. + +To disable remote printing again, choose \q{None (printing +disabled)} from the printer selection list. This is the default +state. + \H{config-keyboard} The Keyboard panel The Keyboard configuration panel allows you to control the behaviour diff --git a/putty.h b/putty.h index e37c1a18..79f0b8d9 100644 --- a/putty.h +++ b/putty.h @@ -336,6 +336,7 @@ typedef struct { int sunken_edge; int window_border; char answerback[256]; + char printer[128]; /* Colour options */ int try_palette; int bold_colour; @@ -609,4 +610,16 @@ extern int console_batch_mode; extern char *console_password; int console_get_line(const char *prompt, char *str, int maxlen, int is_pw); +/* + * Exports from printing.c. + */ +typedef struct printer_enum_tag printer_enum; +typedef struct printer_job_tag printer_job; +printer_enum *printer_start_enum(int *nprinters); +char *printer_get_name(printer_enum *, int); +void printer_finish_enum(printer_enum *); +printer_job *printer_start_job(char *printer); +void printer_job_data(printer_job *, void *, int); +void printer_finish_job(printer_job *); + #endif diff --git a/settings.c b/settings.c index 3d54fe1f..55955acc 100644 --- a/settings.c +++ b/settings.c @@ -261,6 +261,7 @@ void save_settings(char *section, int do_host, Config * cfg) write_setting_s(sesskey, buf, buf2); } write_setting_s(sesskey, "LineCodePage", cfg->line_codepage); + write_setting_s(sesskey, "Printer", cfg->printer); write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr); write_setting_i(sesskey, "ScrollBar", cfg->scrollbar); write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen); @@ -503,6 +504,7 @@ void load_settings(char *section, int do_host, Config * cfg) */ gpps(sesskey, "LineCodePage", "", cfg->line_codepage, sizeof(cfg->line_codepage)); + gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer)); gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr); gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar); gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen); diff --git a/terminal.c b/terminal.c index af175d52..a224afdd 100644 --- a/terminal.c +++ b/terminal.c @@ -115,6 +115,10 @@ static int vt52_bold; /* Force bold on non-bold colours */ static int utf_state; /* Is there a pending UTF-8 character */ static int utf_char; /* and what is it so far. */ static int utf_size; /* The size of the UTF character. */ +static int printing, only_printing; /* Are we doing ANSI printing? */ +static int print_state; /* state of print-end-sequence scan */ +static bufchain printer_buf; /* buffered data for printer */ +static printer_job *print_job; static int xterm_mouse; /* send mouse messages to app */ @@ -206,6 +210,7 @@ static void erase_lots(int, int, int); static void swap_screen(int); static void update_sbar(void); static void deselect(void); +static void term_print_finish(void); /* * Resize a line to make it `cols' columns wide. @@ -302,6 +307,7 @@ static void power_on(void) blink_is_real = cfg.blinktext; erase_char = ERASE_CHAR; alt_which = 0; + term_print_finish(); { int i; for (i = 0; i < 256; i++) @@ -352,8 +358,9 @@ void term_pwron(void) /* * When the user reconfigures us, we need to check the forbidden- - * alternate-screen config option, and also disable raw mouse mode - * if the user has disabled mouse reporting. + * alternate-screen config option, disable raw mouse mode if the + * user has disabled mouse reporting, and abandon a print job if + * the user has disabled printing. */ void term_reconfig(void) { @@ -368,6 +375,9 @@ void term_reconfig(void) sco_acs = alt_sco_acs = 0; utf = 0; } + if (!*cfg.printer) { + term_print_finish(); + } } /* @@ -1008,6 +1018,50 @@ static void do_osc(void) } /* + * ANSI printing routines. + */ +static void term_print_setup(void) +{ + bufchain_clear(&printer_buf); + print_job = printer_start_job(cfg.printer); +} +static void term_print_flush(void) +{ + void *data; + int len; + int size; + while ((size = bufchain_size(&printer_buf)) > 5) { + bufchain_prefix(&printer_buf, &data, &len); + if (len > size-5) + len = size-5; + printer_job_data(print_job, data, len); + bufchain_consume(&printer_buf, len); + } +} +static void term_print_finish(void) +{ + void *data; + int len, size; + char c; + + term_print_flush(); + while ((size = bufchain_size(&printer_buf)) > 0) { + bufchain_prefix(&printer_buf, &data, &len); + c = *(char *)data; + if (c == '\033' || c == '\233') { + bufchain_consume(&printer_buf, size); + break; + } else { + printer_job_data(print_job, &c, 1); + bufchain_consume(&printer_buf, 1); + } + } + printer_finish_job(print_job); + print_job = NULL; + printing = only_printing = FALSE; +} + +/* * Remove everything currently in `inbuf' and stick it up on the * in-memory display. There's a big state machine in here to * process escape sequences... @@ -1051,6 +1105,40 @@ void term_out(void) * of i18n. */ + /* + * If we're printing, add the character to the printer + * buffer. + */ + if (printing) { + char cc = c; + bufchain_add(&printer_buf, &c, 1); + + /* + * If we're in print-only mode, we use a much simpler + * state machine designed only to recognise the ESC[4i + * termination sequence. + */ + if (only_printing) { + if (c == '\033') + print_state = 1; + else if (c == (unsigned char)'\233') + print_state = 2; + else if (c == '[' && print_state == 1) + print_state = 2; + else if (c == '4' && print_state == 2) + print_state = 3; + else if (c == 'i' && print_state == 3) + print_state = 4; + else + print_state = 0; + if (print_state == 4) { + printing = only_printing = FALSE; + term_print_finish(); + } + continue; + } + } + /* First see about all those translations. */ if (termstate == TOPLEVEL) { if (in_utf) @@ -1815,6 +1903,24 @@ void term_out(void) toggle_mode(esc_args[i], esc_query, TRUE); } break; + case 'i': + case ANSI_QUE('i'): + compatibility(VT100); + { + int i; + if (esc_nargs != 1) break; + if (esc_args[0] == 5 && *cfg.printer) { + printing = TRUE; + only_printing = !esc_query; + print_state = 0; + term_print_setup(); + } else if (esc_args[0] == 4 && printing) { + printing = FALSE; + only_printing = FALSE; + term_print_finish(); + } + } + break; case 'l': /* toggle modes to low */ case ANSI_QUE('l'): compatibility(VT100); @@ -2657,6 +2763,8 @@ void term_out(void) check_selection(curs, cursplus); } } + + term_print_flush(); } #if 0 diff --git a/windlg.c b/windlg.c index 2912040f..316115e5 100644 --- a/windlg.c +++ b/windlg.c @@ -27,6 +27,8 @@ static int requested_help; static struct prefslist cipherlist; +#define PRINTER_DISABLED_STRING "None (printing disabled)" + void force_normal(HWND hwnd) { static int recurse = 0; @@ -307,6 +309,7 @@ enum { IDCX_ABOUT = IDC_TITLE_TERMINAL, IDC_BOX_TERMINAL1, IDC_BOX_TERMINAL2, + IDC_BOX_TERMINAL3, IDC_WRAPMODE, IDC_DECOM, IDC_LFHASCR, @@ -322,6 +325,8 @@ enum { IDCX_ABOUT = IDC_EDITBACKEND, IDC_EDITYES, IDC_EDITNO, + IDC_PRINTERSTATIC, + IDC_PRINTER, terminalpanelend, featurespanelstart, @@ -724,6 +729,9 @@ char *help_context_cmd(int id) case IDC_EDITYES: case IDC_EDITNO: return "JI(`',`terminal.localedit')"; + case IDC_PRINTERSTATIC: + case IDC_PRINTER: + return "JI(`',`terminal.printing')"; case IDC_BELLSTATIC: case IDC_BELL_DISABLED: @@ -1203,7 +1211,25 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess) } SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage); } - + + { + int i, nprinters; + printer_enum *pe; + pe = printer_start_enum(&nprinters); + strcpy(cfg.line_codepage, cp_name(decode_codepage(cfg.line_codepage))); + SendDlgItemMessage(hwnd, IDC_PRINTER, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING, + 0, (LPARAM) PRINTER_DISABLED_STRING); + for (i = 0; i < nprinters; i++) { + char *printer_name = printer_get_name(pe, i); + SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING, + 0, (LPARAM) printer_name); + } + printer_finish_enum(pe); + SetDlgItemText(hwnd, IDC_PRINTER, + *cfg.printer ? cfg.printer : PRINTER_DISABLED_STRING); + } + CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE, cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS : cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI : @@ -1330,7 +1356,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) } if (panel == terminalpanelstart) { - /* The Terminal panel. Accelerators used: [acgoh] wdren lts */ + /* The Terminal panel. Accelerators used: [acgoh] wdren lts p */ struct ctlpos cp; ctlposinit(&cp, hwnd, 80, 3, 13); bartitle(&cp, "Options controlling the terminal emulation", @@ -1354,6 +1380,11 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) "Auto", IDC_EDITBACKEND, "Force on", IDC_EDITYES, "Force off", IDC_EDITNO, NULL); endbox(&cp); + + beginbox(&cp, "Remote-controlled printing", IDC_BOX_TERMINAL3); + combobox(&cp, "&Printer to send ANSI printer output to:", + IDC_PRINTERSTATIC, IDC_PRINTER); + endbox(&cp); } if (panel == featurespanelstart) { @@ -3109,6 +3140,19 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage); } break; + case IDC_PRINTER: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_PRINTER, + CB_GETCURSEL, 0, 0); + SendDlgItemMessage(hwnd, IDC_PRINTER, CB_GETLBTEXT, + index, (LPARAM)cfg.printer); + } else if (HIWORD(wParam) == CBN_EDITCHANGE) { + GetDlgItemText(hwnd, IDC_PRINTER, cfg.printer, + sizeof(cfg.printer) - 1); + } + if (!strcmp(cfg.printer, PRINTER_DISABLED_STRING)) + *cfg.printer = '\0'; + break; case IDC_CAPSLOCKCYR: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { -- 2.11.0