print.c revision 956cc18d
1956cc18dSsnj/* $XTermId: print.c,v 1.109 2009/09/10 09:06:30 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/************************************************************ 4d522f475Smrg 54e40088cSchristosCopyright 1997-2007,2009 by Thomas E. Dickey 6d522f475Smrg 7d522f475Smrg All Rights Reserved 8d522f475Smrg 9d522f475SmrgPermission is hereby granted, free of charge, to any person obtaining a 10d522f475Smrgcopy of this software and associated documentation files (the 11d522f475Smrg"Software"), to deal in the Software without restriction, including 12d522f475Smrgwithout limitation the rights to use, copy, modify, merge, publish, 13d522f475Smrgdistribute, sublicense, and/or sell copies of the Software, and to 14d522f475Smrgpermit persons to whom the Software is furnished to do so, subject to 15d522f475Smrgthe following conditions: 16d522f475Smrg 17d522f475SmrgThe above copyright notice and this permission notice shall be included 18d522f475Smrgin all copies or substantial portions of the Software. 19d522f475Smrg 20d522f475SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21d522f475SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22d522f475SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23d522f475SmrgIN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 24d522f475SmrgCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25d522f475SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26d522f475SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27d522f475Smrg 28d522f475SmrgExcept as contained in this notice, the name(s) of the above copyright 29d522f475Smrgholders shall not be used in advertising or otherwise to promote the 30d522f475Smrgsale, use or other dealings in this Software without prior written 31d522f475Smrgauthorization. 32d522f475Smrg 33d522f475Smrg********************************************************/ 34d522f475Smrg 35d522f475Smrg#include <xterm.h> 36d522f475Smrg#include <data.h> 37d522f475Smrg#include <menu.h> 38d522f475Smrg#include <error.h> 39d522f475Smrg 40d522f475Smrg#include <stdio.h> 41d522f475Smrg 42d522f475Smrg#undef CTRL 43d522f475Smrg#define CTRL(c) ((c) & 0x1f) 44d522f475Smrg 45d522f475Smrg#define SHIFT_IN '\017' 46d522f475Smrg#define SHIFT_OUT '\016' 47d522f475Smrg 48d522f475Smrg#define CSET_IN 'A' 49d522f475Smrg#define CSET_OUT '0' 50d522f475Smrg 51d522f475Smrg#define isForm(c) ((c) == '\r' || (c) == '\n' || (c) == '\f') 52d522f475Smrg#define Strlen(a) strlen((char *)a) 53d522f475Smrg#define Strcmp(a,b) strcmp((char *)a,(char *)b) 54d522f475Smrg#define Strncmp(a,b,c) strncmp((char *)a,(char *)b,c) 55d522f475Smrg 56d522f475Smrg#ifdef VMS 57d522f475Smrg#define VMS_TEMP_PRINT_FILE "sys$scratch:xterm_print.txt" 58d522f475Smrg#endif 59d522f475Smrg 60956cc18dSsnjstatic void charToPrinter(XtermWidget /* xw */ , 61956cc18dSsnj unsigned /* chr */ ); 62956cc18dSsnjstatic void printLine(XtermWidget /* xw */ , 63956cc18dSsnj int /* row */ , 64956cc18dSsnj unsigned /* chr */ ); 65956cc18dSsnjstatic void send_CharSet(XtermWidget /* xw */ , 66956cc18dSsnj LineData * /* ld */ ); 67956cc18dSsnjstatic void send_SGR(XtermWidget /* xw */ , 68956cc18dSsnj unsigned /* attr */ , 69956cc18dSsnj unsigned /* fg */ , 70956cc18dSsnj unsigned /* bg */ ); 71956cc18dSsnjstatic void stringToPrinter(XtermWidget /* xw */ , 72956cc18dSsnj char * /*str */ ); 73d522f475Smrg 74d522f475Smrgstatic FILE *Printer; 75d522f475Smrgstatic pid_t Printer_pid; 76d522f475Smrgstatic int initialized; 77d522f475Smrg 78d522f475Smrgstatic void 79956cc18dSsnjclosePrinter(XtermWidget xw GCC_UNUSED) 80d522f475Smrg{ 81956cc18dSsnj if (xtermHasPrinter(xw) != 0) { 82d522f475Smrg#ifdef VMS 83956cc18dSsnj TScreen *screen = TScreenOf(xw); 84d522f475Smrg 85d522f475Smrg char pcommand[256]; 86d522f475Smrg (void) sprintf(pcommand, "%s %s;", 87d522f475Smrg screen->printer_command, 88d522f475Smrg VMS_TEMP_PRINT_FILE); 89d522f475Smrg#endif 90d522f475Smrg 91d522f475Smrg if (Printer != 0) { 92d522f475Smrg fclose(Printer); 93d522f475Smrg TRACE(("closed printer, waiting...\n")); 94d522f475Smrg#ifdef VMS /* This is a quick hack, really should use 95d522f475Smrg spawn and check status or system services 96d522f475Smrg and go straight to the queue */ 97d522f475Smrg (void) system(pcommand); 98d522f475Smrg#else /* VMS */ 99d522f475Smrg while (nonblocking_wait() > 0) 100d522f475Smrg#endif /* VMS */ 101d522f475Smrg ; 102d522f475Smrg Printer = 0; 103d522f475Smrg initialized = 0; 104d522f475Smrg TRACE(("closed printer\n")); 105d522f475Smrg } 106d522f475Smrg } 107d522f475Smrg} 108d522f475Smrg 109d522f475Smrgstatic void 110956cc18dSsnjprintCursorLine(XtermWidget xw) 111d522f475Smrg{ 112956cc18dSsnj TScreen *screen = TScreenOf(xw); 113d522f475Smrg 114d522f475Smrg TRACE(("printCursorLine\n")); 115956cc18dSsnj printLine(xw, screen->cur_row, '\n'); 116d522f475Smrg} 117d522f475Smrg 118d522f475Smrg#define NO_COLOR ((unsigned)-1) 119d522f475Smrg 120d522f475Smrg/* 121d522f475Smrg * DEC's manual doesn't document whether trailing blanks are removed, or what 122d522f475Smrg * happens with a line that is entirely blank. This function prints the 123d522f475Smrg * characters that xterm would allow as a selection (which may include blanks). 124d522f475Smrg */ 125d522f475Smrgstatic void 126956cc18dSsnjprintLine(XtermWidget xw, int row, unsigned chr) 127d522f475Smrg{ 128956cc18dSsnj TScreen *screen = TScreenOf(xw); 129d522f475Smrg int inx = ROW2INX(screen, row); 130956cc18dSsnj LineData *ld; 131d522f475Smrg Char attr = 0; 132d522f475Smrg unsigned ch; 133d522f475Smrg int last = MaxCols(screen); 134d522f475Smrg int col; 135d522f475Smrg#if OPT_ISO_COLORS && OPT_PRINT_COLORS 136956cc18dSsnj CellColor *fb = 0; 137956cc18dSsnj#define ColorOf(ld,col) (ld->color[col]) 138d522f475Smrg#endif 139d522f475Smrg unsigned fg = NO_COLOR, last_fg = NO_COLOR; 140d522f475Smrg unsigned bg = NO_COLOR, last_bg = NO_COLOR; 141d522f475Smrg int cs = CSET_IN; 142d522f475Smrg int last_cs = CSET_IN; 143d522f475Smrg 144956cc18dSsnj ld = getLineData(screen, inx); 145d522f475Smrg TRACE(("printLine(row=%d/%d, top=%d:%d, chr=%d):%s\n", 146d522f475Smrg row, ROW2INX(screen, row), screen->topline, screen->max_row, chr, 147956cc18dSsnj visibleIChars(ld->charData, (unsigned) last))); 148956cc18dSsnj 149956cc18dSsnj if_OPT_ISO_COLORS(screen, { 150956cc18dSsnj fb = ld->color; 151d522f475Smrg }); 152d522f475Smrg while (last > 0) { 153956cc18dSsnj if ((ld->attribs[last - 1] & CHARDRAWN) == 0) 154d522f475Smrg last--; 155d522f475Smrg else 156d522f475Smrg break; 157d522f475Smrg } 158d522f475Smrg if (last) { 159d522f475Smrg if (screen->print_attributes) { 160956cc18dSsnj send_CharSet(xw, ld); 161956cc18dSsnj send_SGR(xw, 0, NO_COLOR, NO_COLOR); 162d522f475Smrg } 163d522f475Smrg for (col = 0; col < last; col++) { 164956cc18dSsnj ch = ld->charData[col]; 165d522f475Smrg#if OPT_PRINT_COLORS 166d522f475Smrg if (screen->colorMode) { 167d522f475Smrg if (screen->print_attributes > 1) { 168956cc18dSsnj fg = (ld->attribs[col] & FG_COLOR) 169956cc18dSsnj ? extract_fg(xw, ColorOf(ld, col), ld->attribs[col]) 170d522f475Smrg : NO_COLOR; 171956cc18dSsnj bg = (ld->attribs[col] & BG_COLOR) 172956cc18dSsnj ? extract_bg(xw, ColorOf(ld, col), ld->attribs[col]) 173d522f475Smrg : NO_COLOR; 174d522f475Smrg } 175d522f475Smrg } 176d522f475Smrg#endif 177956cc18dSsnj if ((((ld->attribs[col] & SGR_MASK) != attr) 178d522f475Smrg#if OPT_PRINT_COLORS 179d522f475Smrg || (last_fg != fg) || (last_bg != bg) 180d522f475Smrg#endif 181d522f475Smrg ) 182d522f475Smrg && ch) { 183956cc18dSsnj attr = CharOf(ld->attribs[col] & SGR_MASK); 184d522f475Smrg last_fg = fg; 185d522f475Smrg last_bg = bg; 186d522f475Smrg if (screen->print_attributes) 187956cc18dSsnj send_SGR(xw, attr, fg, bg); 188d522f475Smrg } 189d522f475Smrg 190d522f475Smrg if (ch == 0) 191d522f475Smrg ch = ' '; 192d522f475Smrg 193d522f475Smrg#if OPT_WIDE_CHARS 194d522f475Smrg if (screen->utf8_mode) 195d522f475Smrg cs = CSET_IN; 196d522f475Smrg else 197d522f475Smrg#endif 198d522f475Smrg cs = (ch >= ' ' && ch != ANSI_DEL) ? CSET_IN : CSET_OUT; 199d522f475Smrg if (last_cs != cs) { 200d522f475Smrg if (screen->print_attributes) { 201956cc18dSsnj charToPrinter(xw, 202956cc18dSsnj (unsigned) ((cs == CSET_OUT) 203d522f475Smrg ? SHIFT_OUT 204d522f475Smrg : SHIFT_IN)); 205d522f475Smrg } 206d522f475Smrg last_cs = cs; 207d522f475Smrg } 208d522f475Smrg 209d522f475Smrg /* FIXME: we shouldn't have to map back from the 210d522f475Smrg * alternate character set, except that the 211d522f475Smrg * corresponding charset information is not encoded 212d522f475Smrg * into the CSETS array. 213d522f475Smrg */ 214956cc18dSsnj charToPrinter(xw, 215956cc18dSsnj ((cs == CSET_OUT) 216d522f475Smrg ? (ch == ANSI_DEL ? 0x5f : (ch + 0x5f)) 217d522f475Smrg : ch)); 218d522f475Smrg if_OPT_WIDE_CHARS(screen, { 219956cc18dSsnj size_t off; 220956cc18dSsnj for_each_combData(off, ld) { 221956cc18dSsnj ch = ld->combData[off][col]; 222956cc18dSsnj if (ch == 0) 223d522f475Smrg break; 224956cc18dSsnj charToPrinter(xw, ch); 225d522f475Smrg } 226d522f475Smrg }); 227d522f475Smrg } 228d522f475Smrg if (screen->print_attributes) { 229956cc18dSsnj send_SGR(xw, 0, NO_COLOR, NO_COLOR); 230d522f475Smrg if (cs != CSET_IN) 231956cc18dSsnj charToPrinter(xw, SHIFT_IN); 232d522f475Smrg } 233d522f475Smrg } 234d522f475Smrg if (screen->print_attributes) 235956cc18dSsnj charToPrinter(xw, '\r'); 236956cc18dSsnj charToPrinter(xw, chr); 237956cc18dSsnj 238956cc18dSsnj return; 239d522f475Smrg} 240d522f475Smrg 241d522f475Smrgvoid 242956cc18dSsnjxtermPrintScreen(XtermWidget xw, Bool use_DECPEX) 243d522f475Smrg{ 244956cc18dSsnj if (XtIsRealized((Widget) xw)) { 245956cc18dSsnj TScreen *screen = TScreenOf(xw); 246d522f475Smrg Bool extent = (use_DECPEX && screen->printer_extent); 247d522f475Smrg int top = extent ? 0 : screen->top_marg; 248d522f475Smrg int bot = extent ? screen->max_row : screen->bot_marg; 249d522f475Smrg int was_open = initialized; 250d522f475Smrg 251d522f475Smrg TRACE(("xtermPrintScreen, rows %d..%d\n", top, bot)); 252d522f475Smrg 253d522f475Smrg while (top <= bot) 254956cc18dSsnj printLine(xw, top++, '\n'); 255d522f475Smrg if (screen->printer_formfeed) 256956cc18dSsnj charToPrinter(xw, '\f'); 257d522f475Smrg 258d522f475Smrg if (!was_open || screen->printer_autoclose) { 259956cc18dSsnj closePrinter(xw); 260d522f475Smrg } 261d522f475Smrg } else { 262d522f475Smrg Bell(XkbBI_MinorError, 0); 263d522f475Smrg } 264d522f475Smrg} 265d522f475Smrg 266d522f475Smrg/* 267d522f475Smrg * If the alternate screen is active, we'll print only that. Otherwise, print 268d522f475Smrg * the normal screen plus all scrolled-back lines. The distinction is made 269d522f475Smrg * because the normal screen's buffer is part of the overall scrollback buffer. 270d522f475Smrg */ 271956cc18dSsnjvoid 272956cc18dSsnjxtermPrintEverything(XtermWidget xw) 273d522f475Smrg{ 274956cc18dSsnj TScreen *screen = TScreenOf(xw); 275d522f475Smrg int top = 0; 276d522f475Smrg int bot = screen->max_row; 277d522f475Smrg int was_open = initialized; 278d522f475Smrg 279956cc18dSsnj if (!screen->whichBuf) { 280956cc18dSsnj top = -screen->savedlines - screen->topline; 281956cc18dSsnj bot -= screen->topline; 282956cc18dSsnj } 283d522f475Smrg 284d522f475Smrg TRACE(("xtermPrintEverything, rows %d..%d\n", top, bot)); 285d522f475Smrg while (top <= bot) 286956cc18dSsnj printLine(xw, top++, '\n'); 287d522f475Smrg if (screen->printer_formfeed) 288956cc18dSsnj charToPrinter(xw, '\f'); 289d522f475Smrg 290d522f475Smrg if (!was_open || screen->printer_autoclose) { 291956cc18dSsnj closePrinter(xw); 292d522f475Smrg } 293d522f475Smrg} 294d522f475Smrg 295d522f475Smrgstatic void 296956cc18dSsnjsend_CharSet(XtermWidget xw, LineData * ld) 297d522f475Smrg{ 298d522f475Smrg#if OPT_DEC_CHRSET 299d522f475Smrg char *msg = 0; 300d522f475Smrg 301956cc18dSsnj switch (GetLineDblCS(ld)) { 302d522f475Smrg case CSET_SWL: 303d522f475Smrg msg = "\033#5"; 304d522f475Smrg break; 305d522f475Smrg case CSET_DHL_TOP: 306d522f475Smrg msg = "\033#3"; 307d522f475Smrg break; 308d522f475Smrg case CSET_DHL_BOT: 309d522f475Smrg msg = "\033#4"; 310d522f475Smrg break; 311d522f475Smrg case CSET_DWL: 312d522f475Smrg msg = "\033#6"; 313d522f475Smrg break; 314d522f475Smrg } 315d522f475Smrg if (msg != 0) 316956cc18dSsnj stringToPrinter(xw, msg); 317d522f475Smrg#else 318956cc18dSsnj (void) xw; 319956cc18dSsnj (void) ld; 320d522f475Smrg#endif /* OPT_DEC_CHRSET */ 321d522f475Smrg} 322d522f475Smrg 323d522f475Smrgstatic void 324956cc18dSsnjsend_SGR(XtermWidget xw, unsigned attr, unsigned fg, unsigned bg) 325d522f475Smrg{ 326d522f475Smrg char msg[80]; 327d522f475Smrg strcpy(msg, "\033[0"); 328d522f475Smrg if (attr & BOLD) 329d522f475Smrg strcat(msg, ";1"); 330d522f475Smrg if (attr & UNDERLINE) 331d522f475Smrg strcat(msg, ";4"); /* typo? DEC documents this as '2' */ 332d522f475Smrg if (attr & BLINK) 333d522f475Smrg strcat(msg, ";5"); 334d522f475Smrg if (attr & INVERSE) /* typo? DEC documents this as invisible */ 335d522f475Smrg strcat(msg, ";7"); 336d522f475Smrg#if OPT_PRINT_COLORS 337d522f475Smrg if (bg != NO_COLOR) { 338d522f475Smrg sprintf(msg + strlen(msg), ";%u", (bg < 8) ? (40 + bg) : (92 + bg)); 339d522f475Smrg } 340d522f475Smrg if (fg != NO_COLOR) { 341d522f475Smrg#if OPT_PC_COLORS 342956cc18dSsnj if (xw->screen.boldColors 343d522f475Smrg && fg > 8 344d522f475Smrg && (attr & BOLD) != 0) 345d522f475Smrg fg -= 8; 346d522f475Smrg#endif 347d522f475Smrg sprintf(msg + strlen(msg), ";%u", (fg < 8) ? (30 + fg) : (82 + fg)); 348d522f475Smrg } 349d522f475Smrg#else 350d522f475Smrg (void) bg; 351d522f475Smrg (void) fg; 352d522f475Smrg#endif 353d522f475Smrg strcat(msg, "m"); 354956cc18dSsnj stringToPrinter(xw, msg); 355d522f475Smrg} 356d522f475Smrg 357d522f475Smrg/* 358d522f475Smrg * This implementation only knows how to write to a pipe. 359d522f475Smrg */ 360d522f475Smrgstatic void 361956cc18dSsnjcharToPrinter(XtermWidget xw, unsigned chr) 362d522f475Smrg{ 363956cc18dSsnj TScreen *screen = TScreenOf(xw); 364d522f475Smrg 365956cc18dSsnj if (!initialized && xtermHasPrinter(xw)) { 366d522f475Smrg#if defined(VMS) 367d522f475Smrg /* 368d522f475Smrg * This implementation only knows how to write to a file. When the 369d522f475Smrg * file is closed the print command executes. Print command must be of 370d522f475Smrg * the form: 371d522f475Smrg * print/que=name/delete [/otherflags]. 372d522f475Smrg */ 373d522f475Smrg Printer = fopen(VMS_TEMP_PRINT_FILE, "w"); 374d522f475Smrg#else 375d522f475Smrg /* 376d522f475Smrg * This implementation only knows how to write to a pipe. 377d522f475Smrg */ 378d522f475Smrg FILE *input; 379d522f475Smrg int my_pipe[2]; 380d522f475Smrg int c; 381d522f475Smrg 382d522f475Smrg if (pipe(my_pipe)) 383d522f475Smrg SysError(ERROR_FORK); 384d522f475Smrg if ((Printer_pid = fork()) < 0) 385d522f475Smrg SysError(ERROR_FORK); 386d522f475Smrg 387d522f475Smrg if (Printer_pid == 0) { 388d522f475Smrg TRACE(((char *) 0)); 389d522f475Smrg close(my_pipe[1]); /* printer is silent */ 390d522f475Smrg close(screen->respond); 391d522f475Smrg 392d522f475Smrg close(fileno(stdout)); 393d522f475Smrg dup2(fileno(stderr), 1); 394d522f475Smrg 395d522f475Smrg if (fileno(stderr) != 2) { 396d522f475Smrg dup2(fileno(stderr), 2); 397d522f475Smrg close(fileno(stderr)); 398d522f475Smrg } 399d522f475Smrg 400d522f475Smrg /* don't want privileges! */ 401d522f475Smrg if (xtermResetIds(screen) < 0) 402d522f475Smrg exit(1); 403d522f475Smrg 404d522f475Smrg Printer = popen(screen->printer_command, "w"); 405d522f475Smrg input = fdopen(my_pipe[0], "r"); 406d522f475Smrg while ((c = fgetc(input)) != EOF) { 407d522f475Smrg fputc(c, Printer); 408d522f475Smrg if (isForm(c)) 409d522f475Smrg fflush(Printer); 410d522f475Smrg } 411d522f475Smrg pclose(Printer); 412d522f475Smrg exit(0); 413d522f475Smrg } else { 414d522f475Smrg close(my_pipe[0]); /* won't read from printer */ 415d522f475Smrg Printer = fdopen(my_pipe[1], "w"); 416d522f475Smrg TRACE(("opened printer from pid %d/%d\n", 417d522f475Smrg (int) getpid(), Printer_pid)); 418d522f475Smrg } 419d522f475Smrg#endif 420d522f475Smrg initialized++; 421d522f475Smrg } 422d522f475Smrg if (Printer != 0) { 423d522f475Smrg#if OPT_WIDE_CHARS 424d522f475Smrg if (chr > 127) { 425d522f475Smrg Char temp[10]; 426d522f475Smrg *convertToUTF8(temp, chr) = 0; 427d522f475Smrg fputs((char *) temp, Printer); 428d522f475Smrg } else 429d522f475Smrg#endif 430d522f475Smrg fputc((int) chr, Printer); 431d522f475Smrg if (isForm(chr)) 432d522f475Smrg fflush(Printer); 433d522f475Smrg } 434d522f475Smrg} 435d522f475Smrg 436d522f475Smrgstatic void 437956cc18dSsnjstringToPrinter(XtermWidget xw, char *str) 438d522f475Smrg{ 439d522f475Smrg while (*str) 440956cc18dSsnj charToPrinter(xw, CharOf(*str++)); 441d522f475Smrg} 442d522f475Smrg 443d522f475Smrg/* 444d522f475Smrg * This module implements the MC (Media Copy) and related printing control 445d522f475Smrg * sequences for VTxxx emulation. This is based on the description in the 446d522f475Smrg * VT330/VT340 Programmer Reference Manual EK-VT3XX-TP-001 (Digital Equipment 447d522f475Smrg * Corp., March 1987). 448d522f475Smrg */ 449d522f475Smrgvoid 450956cc18dSsnjxtermMediaControl(XtermWidget xw, int param, int private_seq) 451d522f475Smrg{ 452d522f475Smrg TRACE(("MediaCopy param=%d, private=%d\n", param, private_seq)); 453d522f475Smrg 454d522f475Smrg if (private_seq) { 455d522f475Smrg switch (param) { 456d522f475Smrg case 1: 457956cc18dSsnj printCursorLine(xw); 458d522f475Smrg break; 459d522f475Smrg case 4: 460956cc18dSsnj setPrinterControlMode(xw, 0); 461d522f475Smrg break; 462d522f475Smrg case 5: 463956cc18dSsnj setPrinterControlMode(xw, 1); 464d522f475Smrg break; 465d522f475Smrg case 10: /* VT320 */ 466956cc18dSsnj xtermPrintScreen(xw, False); 467d522f475Smrg break; 468d522f475Smrg case 11: /* VT320 */ 469956cc18dSsnj xtermPrintEverything(xw); 470d522f475Smrg break; 471d522f475Smrg } 472d522f475Smrg } else { 473d522f475Smrg switch (param) { 474d522f475Smrg case -1: 475d522f475Smrg case 0: 476956cc18dSsnj xtermPrintScreen(xw, True); 477d522f475Smrg break; 478d522f475Smrg case 4: 479956cc18dSsnj setPrinterControlMode(xw, 0); 480d522f475Smrg break; 481d522f475Smrg case 5: 482956cc18dSsnj setPrinterControlMode(xw, 2); 483d522f475Smrg break; 484d522f475Smrg } 485d522f475Smrg } 486d522f475Smrg} 487d522f475Smrg 488d522f475Smrg/* 489d522f475Smrg * When in autoprint mode, the printer prints a line from the screen when you 490d522f475Smrg * move the cursor off that line with an LF, FF, or VT character, or an 491d522f475Smrg * autowrap occurs. The printed line ends with a CR and the character (LF, FF 492d522f475Smrg * or VT) that moved the cursor off the previous line. 493d522f475Smrg */ 494d522f475Smrgvoid 495956cc18dSsnjxtermAutoPrint(XtermWidget xw, unsigned chr) 496d522f475Smrg{ 497956cc18dSsnj TScreen *screen = TScreenOf(xw); 498d522f475Smrg 499d522f475Smrg if (screen->printer_controlmode == 1) { 500d522f475Smrg TRACE(("AutoPrint %d\n", chr)); 501956cc18dSsnj printLine(xw, screen->cursorp.row, chr); 502d522f475Smrg if (Printer != 0) 503d522f475Smrg fflush(Printer); 504d522f475Smrg } 505d522f475Smrg} 506d522f475Smrg 507d522f475Smrg/* 508d522f475Smrg * When in printer controller mode, the terminal sends received characters to 509d522f475Smrg * the printer without displaying them on the screen. The terminal sends all 510d522f475Smrg * characters and control sequences to the printer, except NUL, XON, XOFF, and 511d522f475Smrg * the printer controller sequences. 512d522f475Smrg * 513d522f475Smrg * This function eats characters, returning 0 as long as it must buffer or 514d522f475Smrg * divert to the printer. We're only invoked here when in printer controller 515d522f475Smrg * mode, and handle the exit from that mode. 516d522f475Smrg */ 517d522f475Smrg#define LB '[' 518d522f475Smrg 519d522f475Smrgint 520956cc18dSsnjxtermPrinterControl(XtermWidget xw, int chr) 521d522f475Smrg{ 522956cc18dSsnj TScreen *screen = TScreenOf(xw); 523d522f475Smrg /* *INDENT-OFF* */ 524d522f475Smrg static struct { 525d522f475Smrg Char seq[5]; 526d522f475Smrg int active; 527d522f475Smrg } tbl[] = { 528d522f475Smrg { { ANSI_CSI, '5', 'i' }, 2 }, 529d522f475Smrg { { ANSI_CSI, '4', 'i' }, 0 }, 530d522f475Smrg { { ANSI_ESC, LB, '5', 'i' }, 2 }, 531d522f475Smrg { { ANSI_ESC, LB, '4', 'i' }, 0 }, 532d522f475Smrg }; 533d522f475Smrg /* *INDENT-ON* */ 534d522f475Smrg 535d522f475Smrg static Char bfr[10]; 536d522f475Smrg static size_t length; 537d522f475Smrg size_t n; 538d522f475Smrg 539d522f475Smrg TRACE(("In printer:%04X\n", chr)); 540d522f475Smrg 541d522f475Smrg switch (chr) { 542d522f475Smrg case 0: 543d522f475Smrg case CTRL('Q'): 544d522f475Smrg case CTRL('S'): 545d522f475Smrg return 0; /* ignored by application */ 546d522f475Smrg 547d522f475Smrg case ANSI_CSI: 548d522f475Smrg case ANSI_ESC: 549d522f475Smrg case '[': 550d522f475Smrg case '4': 551d522f475Smrg case '5': 552d522f475Smrg case 'i': 5534e40088cSchristos bfr[length++] = CharOf(chr); 554d522f475Smrg for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); n++) { 555d522f475Smrg size_t len = Strlen(tbl[n].seq); 556d522f475Smrg 557d522f475Smrg if (length == len 558d522f475Smrg && Strcmp(bfr, tbl[n].seq) == 0) { 559956cc18dSsnj setPrinterControlMode(xw, tbl[n].active); 560d522f475Smrg if (screen->printer_autoclose 561d522f475Smrg && screen->printer_controlmode == 0) 562956cc18dSsnj closePrinter(xw); 563d522f475Smrg length = 0; 564d522f475Smrg return 0; 565d522f475Smrg } else if (len > length 566d522f475Smrg && Strncmp(bfr, tbl[n].seq, length) == 0) { 567d522f475Smrg return 0; 568d522f475Smrg } 569d522f475Smrg } 570d522f475Smrg length--; 571d522f475Smrg 572d522f475Smrg /* FALLTHRU */ 573d522f475Smrg 574d522f475Smrg default: 575d522f475Smrg for (n = 0; n < length; n++) 576956cc18dSsnj charToPrinter(xw, bfr[n]); 5774e40088cSchristos bfr[0] = CharOf(chr); 578d522f475Smrg length = 1; 579d522f475Smrg return 0; 580d522f475Smrg } 581d522f475Smrg} 582d522f475Smrg 583d522f475Smrg/* 584d522f475Smrg * If there is no printer command, we will ignore printer controls. 585d522f475Smrg */ 586d522f475SmrgBool 587956cc18dSsnjxtermHasPrinter(XtermWidget xw) 588d522f475Smrg{ 589956cc18dSsnj TScreen *screen = TScreenOf(xw); 590d522f475Smrg 591d522f475Smrg return (strlen(screen->printer_command) != 0); 592d522f475Smrg} 593d522f475Smrg 594d522f475Smrg#define showPrinterControlMode(mode) \ 595d522f475Smrg (((mode) == 0) \ 596d522f475Smrg ? "normal" \ 597d522f475Smrg : ((mode) == 1 \ 598d522f475Smrg ? "autoprint" \ 599d522f475Smrg : "printer controller")) 600d522f475Smrg 601d522f475Smrgvoid 602956cc18dSsnjsetPrinterControlMode(XtermWidget xw, int mode) 603d522f475Smrg{ 604956cc18dSsnj if (xtermHasPrinter(xw) 605956cc18dSsnj && xw->screen.printer_controlmode != mode) { 606d522f475Smrg TRACE(("%s %s mode\n", 607d522f475Smrg (mode 608d522f475Smrg ? "set" 609d522f475Smrg : "reset"), 610d522f475Smrg (mode 611d522f475Smrg ? showPrinterControlMode(mode) 612956cc18dSsnj : showPrinterControlMode(xw->screen.printer_controlmode)))); 613956cc18dSsnj xw->screen.printer_controlmode = mode; 614d522f475Smrg update_print_redir(); 615d522f475Smrg } 616d522f475Smrg} 617