1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

ANSI remote printer support. Raw mode only.

[originally from svn r1581]
This commit is contained in:
Simon Tatham 2002-03-09 17:59:15 +00:00
parent 04fba1e540
commit ae476d5567
6 changed files with 205 additions and 5 deletions

View File

@ -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

View File

@ -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

13
putty.h
View File

@ -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

View File

@ -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);

View File

@ -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();
}
}
/*
@ -1007,6 +1017,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
@ -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

View File

@ -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) {