print.c revision e39b573c
1/* $XTermId: print.c,v 1.138 2011/07/14 23:49:10 tom Exp $ */ 2 3/************************************************************ 4 5Copyright 1997-2010,2011 by Thomas E. Dickey 6 7 All Rights Reserved 8 9Permission is hereby granted, free of charge, to any person obtaining a 10copy of this software and associated documentation files (the 11"Software"), to deal in the Software without restriction, including 12without limitation the rights to use, copy, modify, merge, publish, 13distribute, sublicense, and/or sell copies of the Software, and to 14permit persons to whom the Software is furnished to do so, subject to 15the following conditions: 16 17The above copyright notice and this permission notice shall be included 18in all copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 24CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28Except as contained in this notice, the name(s) of the above copyright 29holders shall not be used in advertising or otherwise to promote the 30sale, use or other dealings in this Software without prior written 31authorization. 32 33********************************************************/ 34 35#include <xterm.h> 36#include <data.h> 37#include <menu.h> 38#include <error.h> 39#include <xstrings.h> 40 41#include <stdio.h> 42#include <sys/stat.h> 43 44#undef CTRL 45#define CTRL(c) ((c) & 0x1f) 46 47#define SHIFT_IN '\017' 48#define SHIFT_OUT '\016' 49 50#define CSET_IN 'A' 51#define CSET_OUT '0' 52 53#define isForm(c) ((c) == '\r' || (c) == '\n' || (c) == '\f') 54#define Strlen(a) strlen((const char *)a) 55#define Strcmp(a,b) strcmp((const char *)a,(const char *)b) 56#define Strncmp(a,b,c) strncmp((const char *)a,(const char *)b,c) 57 58#define SPS PrinterOf(screen) 59 60#ifdef VMS 61#define VMS_TEMP_PRINT_FILE "sys$scratch:xterm_print.txt" 62#endif 63 64static void charToPrinter(XtermWidget /* xw */ , 65 unsigned /* chr */ ); 66static void printLine(XtermWidget /* xw */ , 67 int /* row */ , 68 unsigned /* chr */ , 69 PrinterFlags * /* p */ ); 70static void send_CharSet(XtermWidget /* xw */ , 71 LineData * /* ld */ ); 72static void send_SGR(XtermWidget /* xw */ , 73 unsigned /* attr */ , 74 unsigned /* fg */ , 75 unsigned /* bg */ ); 76static void stringToPrinter(XtermWidget /* xw */ , 77 const char * /*str */ ); 78 79void 80closePrinter(XtermWidget xw GCC_UNUSED) 81{ 82 if (xtermHasPrinter(xw) != 0) { 83 TScreen *screen = TScreenOf(xw); 84#ifdef VMS 85 char pcommand[256]; 86 (void) sprintf(pcommand, "%s %s;", 87 SPS.printer_command, 88 VMS_TEMP_PRINT_FILE); 89#endif 90 91 if (SPS.fp != 0) { 92 fclose(SPS.fp); 93 TRACE(("closed printer, waiting...\n")); 94#ifdef VMS /* This is a quick hack, really should use 95 spawn and check status or system services 96 and go straight to the queue */ 97 (void) system(pcommand); 98#else /* VMS */ 99 while (nonblocking_wait() > 0) 100#endif /* VMS */ 101 ; 102 SPS.fp = 0; 103 SPS.isOpen = False; 104 TRACE(("closed printer\n")); 105 } 106 } 107} 108 109static void 110printCursorLine(XtermWidget xw) 111{ 112 TScreen *screen = TScreenOf(xw); 113 114 TRACE(("printCursorLine\n")); 115 printLine(xw, screen->cur_row, '\n', getPrinterFlags(xw, NULL, 0)); 116} 117 118#define NO_COLOR ((unsigned)-1) 119 120/* 121 * DEC's manual doesn't document whether trailing blanks are removed, or what 122 * happens with a line that is entirely blank. This function prints the 123 * characters that xterm would allow as a selection (which may include blanks). 124 */ 125static void 126printLine(XtermWidget xw, int row, unsigned chr, PrinterFlags * p) 127{ 128 TScreen *screen = TScreenOf(xw); 129 int inx = ROW2INX(screen, row); 130 LineData *ld; 131 Char attr = 0; 132 unsigned ch; 133 int last = MaxCols(screen); 134 int col; 135#if OPT_ISO_COLORS && OPT_PRINT_COLORS 136#define ColorOf(ld,col) (ld->color[col]) 137#endif 138 unsigned fg = NO_COLOR, last_fg = NO_COLOR; 139 unsigned bg = NO_COLOR, last_bg = NO_COLOR; 140 int cs = CSET_IN; 141 int last_cs = CSET_IN; 142 143 ld = getLineData(screen, inx); 144 if (ld == 0) 145 return; 146 147 TRACE(("printLine(row=%d/%d, top=%d:%d, chr=%d):%s\n", 148 row, ROW2INX(screen, row), screen->topline, screen->max_row, chr, 149 visibleIChars(ld->charData, (unsigned) last))); 150 151 while (last > 0) { 152 if ((ld->attribs[last - 1] & CHARDRAWN) == 0) 153 last--; 154 else 155 break; 156 } 157 if (last) { 158 if (p->print_attributes) { 159 send_CharSet(xw, ld); 160 send_SGR(xw, 0, NO_COLOR, NO_COLOR); 161 } 162 for (col = 0; col < last; col++) { 163 ch = ld->charData[col]; 164#if OPT_PRINT_COLORS 165 if (screen->colorMode) { 166 if (p->print_attributes > 1) { 167 fg = (ld->attribs[col] & FG_COLOR) 168 ? extract_fg(xw, ColorOf(ld, col), ld->attribs[col]) 169 : NO_COLOR; 170 bg = (ld->attribs[col] & BG_COLOR) 171 ? extract_bg(xw, ColorOf(ld, col), ld->attribs[col]) 172 : NO_COLOR; 173 } 174 } 175#endif 176 if ((((ld->attribs[col] & SGR_MASK) != attr) 177#if OPT_PRINT_COLORS 178 || (last_fg != fg) || (last_bg != bg) 179#endif 180 ) 181 && ch) { 182 attr = CharOf(ld->attribs[col] & SGR_MASK); 183#if OPT_PRINT_COLORS 184 last_fg = fg; 185 last_bg = bg; 186#endif 187 if (p->print_attributes) 188 send_SGR(xw, attr, fg, bg); 189 } 190 191 if (ch == 0) 192 ch = ' '; 193 194#if OPT_WIDE_CHARS 195 if (screen->utf8_mode) 196 cs = CSET_IN; 197 else 198#endif 199 cs = (ch >= ' ' && ch != ANSI_DEL) ? CSET_IN : CSET_OUT; 200 if (last_cs != cs) { 201 if (p->print_attributes) { 202 charToPrinter(xw, 203 (unsigned) ((cs == CSET_OUT) 204 ? SHIFT_OUT 205 : SHIFT_IN)); 206 } 207 last_cs = cs; 208 } 209 210 /* FIXME: we shouldn't have to map back from the 211 * alternate character set, except that the 212 * corresponding charset information is not encoded 213 * into the CSETS array. 214 */ 215 charToPrinter(xw, 216 ((cs == CSET_OUT) 217 ? (ch == ANSI_DEL ? 0x5f : (ch + 0x5f)) 218 : ch)); 219 if_OPT_WIDE_CHARS(screen, { 220 size_t off; 221 for_each_combData(off, ld) { 222 ch = ld->combData[off][col]; 223 if (ch == 0) 224 break; 225 charToPrinter(xw, ch); 226 } 227 }); 228 } 229 if (p->print_attributes) { 230 send_SGR(xw, 0, NO_COLOR, NO_COLOR); 231 if (cs != CSET_IN) 232 charToPrinter(xw, SHIFT_IN); 233 } 234 } 235 236 /* finish line (protocol for attributes needs a CR */ 237 if (p->print_attributes) 238 charToPrinter(xw, '\r'); 239 240 if (chr && !(p->printer_newline)) { 241 if (LineTstWrapped(ld)) 242 chr = '\0'; 243 } 244 245 if (chr) 246 charToPrinter(xw, chr); 247 248 return; 249} 250 251#define PrintNewLine() (unsigned) (((top < bot) || p->printer_newline) ? '\n' : '\0') 252 253static void 254printLines(XtermWidget xw, int top, int bot, PrinterFlags * p) 255{ 256 TRACE(("printLines, rows %d..%d\n", top, bot)); 257 while (top <= bot) { 258 printLine(xw, top, PrintNewLine(), p); 259 ++top; 260 } 261} 262 263void 264xtermPrintScreen(XtermWidget xw, Bool use_DECPEX, PrinterFlags * p) 265{ 266 if (XtIsRealized((Widget) xw)) { 267 TScreen *screen = TScreenOf(xw); 268 Bool extent = (use_DECPEX && p->printer_extent); 269 Boolean was_open = SPS.isOpen; 270 271 printLines(xw, 272 extent ? 0 : screen->top_marg, 273 extent ? screen->max_row : screen->bot_marg, 274 p); 275 if (p->printer_formfeed) 276 charToPrinter(xw, '\f'); 277 278 if (!was_open || SPS.printer_autoclose) { 279 closePrinter(xw); 280 } 281 } else { 282 Bell(xw, XkbBI_MinorError, 0); 283 } 284} 285 286/* 287 * If p->print_everything is zero, use this behavior: 288 * If the alternate screen is active, we'll print only that. Otherwise, print 289 * the normal screen plus all scrolled-back lines. The distinction is made 290 * because the normal screen's buffer is part of the overall scrollback buffer. 291 * 292 * Otherwise, decode bits: 293 * 1 = current screen 294 * 2 = normal screen 295 * 4 = alternate screen 296 * 8 = saved lines 297 */ 298void 299xtermPrintEverything(XtermWidget xw, PrinterFlags * p) 300{ 301 TScreen *screen = TScreenOf(xw); 302 Boolean was_open = SPS.isOpen; 303 int save_which = screen->whichBuf; 304 int done_which = 0; 305 306 if (p->print_everything) { 307 if (p->print_everything & 8) { 308 printLines(xw, -screen->savedlines, -(screen->topline + 1), p); 309 } 310 if (p->print_everything & 4) { 311 screen->whichBuf = 1; 312 done_which |= 2; 313 printLines(xw, 0, screen->max_row, p); 314 screen->whichBuf = save_which; 315 } 316 if (p->print_everything & 2) { 317 screen->whichBuf = 0; 318 done_which |= 1; 319 printLines(xw, 0, screen->max_row, p); 320 screen->whichBuf = save_which; 321 } 322 if (p->print_everything & 1) { 323 if (!(done_which & (1 << screen->whichBuf))) { 324 printLines(xw, 0, screen->max_row, p); 325 } 326 } 327 } else { 328 int top = 0; 329 int bot = screen->max_row; 330 if (!screen->whichBuf) { 331 top = -screen->savedlines - screen->topline; 332 bot -= screen->topline; 333 } 334 printLines(xw, top, bot, p); 335 } 336 if (p->printer_formfeed) 337 charToPrinter(xw, '\f'); 338 339 if (!was_open || SPS.printer_autoclose) { 340 closePrinter(xw); 341 } 342} 343 344static void 345send_CharSet(XtermWidget xw, LineData * ld) 346{ 347#if OPT_DEC_CHRSET 348 const char *msg = 0; 349 350 switch (GetLineDblCS(ld)) { 351 case CSET_SWL: 352 msg = "\033#5"; 353 break; 354 case CSET_DHL_TOP: 355 msg = "\033#3"; 356 break; 357 case CSET_DHL_BOT: 358 msg = "\033#4"; 359 break; 360 case CSET_DWL: 361 msg = "\033#6"; 362 break; 363 } 364 if (msg != 0) 365 stringToPrinter(xw, msg); 366#else 367 (void) xw; 368 (void) ld; 369#endif /* OPT_DEC_CHRSET */ 370} 371 372static void 373send_SGR(XtermWidget xw, unsigned attr, unsigned fg, unsigned bg) 374{ 375 char msg[80]; 376 377 strcpy(msg, "\033[0"); 378 if (attr & BOLD) 379 strcat(msg, ";1"); 380 if (attr & UNDERLINE) 381 strcat(msg, ";4"); /* typo? DEC documents this as '2' */ 382 if (attr & BLINK) 383 strcat(msg, ";5"); 384 if (attr & INVERSE) /* typo? DEC documents this as invisible */ 385 strcat(msg, ";7"); 386#if OPT_PRINT_COLORS 387 if (bg != NO_COLOR) { 388 sprintf(msg + strlen(msg), ";%u", (bg < 8) ? (40 + bg) : (92 + bg)); 389 } 390 if (fg != NO_COLOR) { 391#if OPT_PC_COLORS 392 if (TScreenOf(xw)->boldColors 393 && fg > 8 394 && (attr & BOLD) != 0) 395 fg -= 8; 396#endif 397 sprintf(msg + strlen(msg), ";%u", (fg < 8) ? (30 + fg) : (82 + fg)); 398 } 399#else 400 (void) bg; 401 (void) fg; 402#endif 403 strcat(msg, "m"); 404 stringToPrinter(xw, msg); 405} 406 407/* 408 * This implementation only knows how to write to a pipe. 409 */ 410static void 411charToPrinter(XtermWidget xw, unsigned chr) 412{ 413 TScreen *screen = TScreenOf(xw); 414 415 if (!SPS.isOpen && xtermHasPrinter(xw)) { 416 switch (SPS.toFile) { 417 /* 418 * write to a pipe. 419 */ 420 case False: 421#ifdef VMS 422 /* 423 * This implementation only knows how to write to a file. When the 424 * file is closed the print command executes. Print command must 425 * be of the form: 426 * print/que=name/delete [/otherflags]. 427 */ 428 SPS.fp = fopen(VMS_TEMP_PRINT_FILE, "w"); 429#else 430 { 431 FILE *input; 432 int my_pipe[2]; 433 int c; 434 pid_t my_pid; 435 436 if (pipe(my_pipe)) 437 SysError(ERROR_FORK); 438 if ((my_pid = fork()) < 0) 439 SysError(ERROR_FORK); 440 441 if (my_pid == 0) { 442 TRACE_CLOSE(); 443 close(my_pipe[1]); /* printer is silent */ 444 close(screen->respond); 445 446 close(fileno(stdout)); 447 dup2(fileno(stderr), 1); 448 449 if (fileno(stderr) != 2) { 450 dup2(fileno(stderr), 2); 451 close(fileno(stderr)); 452 } 453 454 /* don't want privileges! */ 455 if (xtermResetIds(screen) < 0) 456 exit(1); 457 458 SPS.fp = popen(SPS.printer_command, "w"); 459 input = fdopen(my_pipe[0], "r"); 460 while ((c = fgetc(input)) != EOF) { 461 fputc(c, SPS.fp); 462 if (isForm(c)) 463 fflush(SPS.fp); 464 } 465 pclose(SPS.fp); 466 exit(0); 467 } else { 468 close(my_pipe[0]); /* won't read from printer */ 469 SPS.fp = fdopen(my_pipe[1], "w"); 470 TRACE(("opened printer from pid %d/%d\n", 471 (int) getpid(), (int) my_pid)); 472 } 473 } 474#endif 475 break; 476 case True: 477 TRACE(("opening \"%s\" as printer output\n", SPS.printer_command)); 478 SPS.fp = fopen(SPS.printer_command, "w"); 479 break; 480 } 481 SPS.isOpen = True; 482 } 483 if (SPS.fp != 0) { 484#if OPT_WIDE_CHARS 485 if (chr > 127) { 486 Char temp[10]; 487 *convertToUTF8(temp, chr) = 0; 488 fputs((char *) temp, SPS.fp); 489 } else 490#endif 491 fputc((int) chr, SPS.fp); 492 if (isForm(chr)) 493 fflush(SPS.fp); 494 } 495} 496 497static void 498stringToPrinter(XtermWidget xw, const char *str) 499{ 500 while (*str) 501 charToPrinter(xw, CharOf(*str++)); 502} 503 504/* 505 * This module implements the MC (Media Copy) and related printing control 506 * sequences for VTxxx emulation. This is based on the description in the 507 * VT330/VT340 Programmer Reference Manual EK-VT3XX-TP-001 (Digital Equipment 508 * Corp., March 1987). 509 */ 510void 511xtermMediaControl(XtermWidget xw, int param, int private_seq) 512{ 513 TRACE(("MediaCopy param=%d, private=%d\n", param, private_seq)); 514 515 if (private_seq) { 516 switch (param) { 517 case 1: 518 printCursorLine(xw); 519 break; 520 case 4: 521 setPrinterControlMode(xw, 0); 522 break; 523 case 5: 524 setPrinterControlMode(xw, 1); 525 break; 526 case 10: /* VT320 */ 527 xtermPrintScreen(xw, False, getPrinterFlags(xw, NULL, 0)); 528 break; 529 case 11: /* VT320 */ 530 xtermPrintEverything(xw, getPrinterFlags(xw, NULL, 0)); 531 break; 532 } 533 } else { 534 switch (param) { 535 case -1: 536 case 0: 537 xtermPrintScreen(xw, True, getPrinterFlags(xw, NULL, 0)); 538 break; 539 case 4: 540 setPrinterControlMode(xw, 0); 541 break; 542 case 5: 543 setPrinterControlMode(xw, 2); 544 break; 545 } 546 } 547} 548 549/* 550 * When in autoprint mode, the printer prints a line from the screen when you 551 * move the cursor off that line with an LF, FF, or VT character, or an 552 * autowrap occurs. The printed line ends with a CR and the character (LF, FF 553 * or VT) that moved the cursor off the previous line. 554 */ 555void 556xtermAutoPrint(XtermWidget xw, unsigned chr) 557{ 558 TScreen *screen = TScreenOf(xw); 559 560 if (SPS.printer_controlmode == 1) { 561 TRACE(("AutoPrint %d\n", chr)); 562 printLine(xw, screen->cursorp.row, chr, getPrinterFlags(xw, NULL, 0)); 563 if (SPS.fp != 0) 564 fflush(SPS.fp); 565 } 566} 567 568/* 569 * When in printer controller mode, the terminal sends received characters to 570 * the printer without displaying them on the screen. The terminal sends all 571 * characters and control sequences to the printer, except NUL, XON, XOFF, and 572 * the printer controller sequences. 573 * 574 * This function eats characters, returning 0 as long as it must buffer or 575 * divert to the printer. We're only invoked here when in printer controller 576 * mode, and handle the exit from that mode. 577 */ 578#define LB '[' 579 580int 581xtermPrinterControl(XtermWidget xw, int chr) 582{ 583 TScreen *screen = TScreenOf(xw); 584 /* *INDENT-OFF* */ 585 static const struct { 586 const Char seq[5]; 587 int active; 588 } tbl[] = { 589 { { ANSI_CSI, '5', 'i' }, 2 }, 590 { { ANSI_CSI, '4', 'i' }, 0 }, 591 { { ANSI_ESC, LB, '5', 'i' }, 2 }, 592 { { ANSI_ESC, LB, '4', 'i' }, 0 }, 593 }; 594 /* *INDENT-ON* */ 595 596 static Char bfr[10]; 597 static size_t length; 598 size_t n; 599 600 TRACE(("In printer:%04X\n", chr)); 601 602 switch (chr) { 603 case 0: 604 case CTRL('Q'): 605 case CTRL('S'): 606 return 0; /* ignored by application */ 607 608 case ANSI_CSI: 609 case ANSI_ESC: 610 case '[': 611 case '4': 612 case '5': 613 case 'i': 614 bfr[length++] = CharOf(chr); 615 for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); n++) { 616 size_t len = Strlen(tbl[n].seq); 617 618 if (length == len 619 && Strcmp(bfr, tbl[n].seq) == 0) { 620 setPrinterControlMode(xw, tbl[n].active); 621 if (SPS.printer_autoclose 622 && SPS.printer_controlmode == 0) 623 closePrinter(xw); 624 length = 0; 625 return 0; 626 } else if (len > length 627 && Strncmp(bfr, tbl[n].seq, length) == 0) { 628 return 0; 629 } 630 } 631 length--; 632 633 /* FALLTHRU */ 634 635 default: 636 for (n = 0; n < length; n++) 637 charToPrinter(xw, bfr[n]); 638 bfr[0] = CharOf(chr); 639 length = 1; 640 return 0; 641 } 642} 643 644/* 645 * If there is no printer command, we will ignore printer controls. 646 */ 647Bool 648xtermHasPrinter(XtermWidget xw) 649{ 650 TScreen *screen = TScreenOf(xw); 651 652 return (strlen(SPS.printer_command) != 0); 653} 654 655#define showPrinterControlMode(mode) \ 656 (((mode) == 0) \ 657 ? "normal" \ 658 : ((mode) == 1 \ 659 ? "autoprint" \ 660 : "printer controller")) 661 662void 663setPrinterControlMode(XtermWidget xw, int mode) 664{ 665 TScreen *screen = TScreenOf(xw); 666 667 if (xtermHasPrinter(xw) 668 && SPS.printer_controlmode != mode) { 669 TRACE(("%s %s mode\n", 670 (mode 671 ? "set" 672 : "reset"), 673 (mode 674 ? showPrinterControlMode(mode) 675 : showPrinterControlMode(SPS.printer_controlmode)))); 676 SPS.printer_controlmode = mode; 677 update_print_redir(); 678 } 679} 680 681PrinterFlags * 682getPrinterFlags(XtermWidget xw, String * params, Cardinal *param_count) 683{ 684 /* *INDENT-OFF* */ 685 static const struct { 686 const char *name; 687 unsigned offset; 688 int value; 689 } table[] = { 690 { "noFormFeed", XtOffsetOf(PrinterFlags, printer_formfeed), 0 }, 691 { "FormFeed", XtOffsetOf(PrinterFlags, printer_formfeed), 1 }, 692 { "noNewLine", XtOffsetOf(PrinterFlags, printer_newline), 0 }, 693 { "NewLine", XtOffsetOf(PrinterFlags, printer_newline), 1 }, 694 { "noAttrs", XtOffsetOf(PrinterFlags, print_attributes), 0 }, 695 { "monoAttrs", XtOffsetOf(PrinterFlags, print_attributes), 1 }, 696 { "colorAttrs", XtOffsetOf(PrinterFlags, print_attributes), 2 }, 697 }; 698 /* *INDENT-ON* */ 699 700 TScreen *screen = TScreenOf(xw); 701 PrinterFlags *result = &(screen->printer_flags); 702 703 TRACE(("getPrinterFlags %d params\n", param_count ? *param_count : 0)); 704 705 result->printer_extent = SPS.printer_extent; 706 result->printer_formfeed = SPS.printer_formfeed; 707 result->printer_newline = SPS.printer_newline; 708 result->print_attributes = SPS.print_attributes; 709 result->print_everything = SPS.print_everything; 710 711 if (param_count != 0 && *param_count != 0) { 712 Cardinal j; 713 unsigned k; 714 for (j = 0; j < *param_count; ++j) { 715 TRACE(("param%d:%s\n", j, params[j])); 716 for (k = 0; k < XtNumber(table); ++k) { 717 if (!x_strcasecmp(params[j], table[k].name)) { 718 int *ptr = (int *) (void *) ((char *) result + table[k].offset); 719 TRACE(("...PrinterFlags(%s) %d->%d\n", 720 table[k].name, 721 *ptr, 722 table[k].value)); 723 *ptr = table[k].value; 724 break; 725 } 726 } 727 } 728 } 729 730 return result; 731} 732 733/* 734 * Print a timestamped copy of everything. 735 */ 736void 737xtermPrintImmediately(XtermWidget xw, String filename, int opts, int attrs) 738{ 739 TScreen *screen = TScreenOf(xw); 740 PrinterState save_state = screen->printer_state; 741 char *my_filename = malloc(TIMESTAMP_LEN + strlen(filename)); 742 743 if (my_filename != 0) { 744 unsigned save_umask = umask(0177); 745 746 timestamp_filename(my_filename, filename); 747 SPS.fp = 0; 748 SPS.isOpen = False; 749 SPS.toFile = True; 750 SPS.printer_command = my_filename; 751 SPS.printer_autoclose = True; 752 SPS.printer_formfeed = False; 753 SPS.printer_newline = True; 754 SPS.print_attributes = attrs; 755 SPS.print_everything = opts; 756 xtermPrintEverything(xw, getPrinterFlags(xw, NULL, 0)); 757 758 umask(save_umask); 759 screen->printer_state = save_state; 760 } 761} 762 763void 764xtermPrintOnXError(XtermWidget xw, int n) 765{ 766#if OPT_PRINT_ON_EXIT 767 /* 768 * The user may have requested that the contents of the screen will be 769 * written to a file if an X error occurs. 770 */ 771 if (TScreenOf(xw)->write_error && !IsEmpty(resource.printFileOnXError)) { 772 Boolean printIt = False; 773 774 switch (n) { 775 case ERROR_XERROR: 776 /* FALLTHRU */ 777 case ERROR_XIOERROR: 778 /* FALLTHRU */ 779 case ERROR_ICEERROR: 780 printIt = True; 781 break; 782 } 783 784 if (printIt) { 785 xtermPrintImmediately(xw, 786 resource.printFileOnXError, 787 resource.printOptsOnXError, 788 resource.printModeOnXError); 789 } 790 } 791#else 792 (void) xw; 793 (void) n; 794#endif 795} 796