/* print.c simple print file utility for less by: Bob Leivian print -nh^ld#99|99t9wp: file1 {-nh...}file2 file3 ... this is designed to be called from the less with the expanded list of files to print with a option list */ #include #include long Open(); #define MODE_OLDFILE 1005L #define MODE_NEWFILE 1006L long std_out; extern char prog_name[]; /* this can be set with options */ int numbers = 0; int headers = 0; int control = 0; int prefix = 0; int lines_per_page = 0; int chars_per_line = 0; int tab_stops = 0; long printer = 0; start_print(my_argc, my_argv) int my_argc; char *my_argv[]; { int i; char *p; char name[30]; char theprefix [30]; char c; if (printer == 0) { printer = Open("PRT:", MODE_NEWFILE); if (!printer) exit(27); } while (my_argv[1]) { /* process options if any */ while (*my_argv[1] == '-') { p = (char *) &*my_argv[1]; p++; /* point to the option chars */ do { switch (*p) { case ' ': case '\0': /* ignore nulls and spaces */ break; case 'p': case 'P': /* turn on proportional mode */ Write(printer, "\x1b[2p", 3L); break; case 'c': case 'C': /* turn on compressed mode */ Write(printer, "\x1b[4w", 4L); break; case 'u': case 'U': /* turn on uncompressed mode */ Write(printer, "\x1b[3w", 4L); break; case 'l': case 'L': /* turn on letter quality mode */ Write(printer, "\x1b[2\"z", 5L); break; case 'd': case 'D': /* turn on draft mode */ Write(printer, "\x1b[1\"z", 5L); break; case ':': /* print control string first */ strcpy(theprefix, ++p); prefix++; goto next; /* consume rest of option */ case '^': /* print control chars as ^X */ control++; break; case 't': case 'T': /* set tab stops */ p++; if (isdigit(*p)) tab_stops = *p - '0'; else { tab_stops = 8; p--; } break; case '#': /* set lines per page */ p++; lines_per_page = 0; while(isdigit(*p)) { lines_per_page *= 10; lines_per_page += (*p++ - '0'); } p--; break; case '|': /* set chars per line */ p++; chars_per_line = 0; while(isdigit(*p)) { chars_per_line *= 10; chars_per_line += (*p++ - '0'); } p--; break; case 'n': case 'N': /* print line numbers */ numbers++; break; case 'h': /* print a header */ headers++; break; default: /* ignore invalid stuff for now */; } p++; } while (*p); next: my_argc--; my_argv++; } /* put out the control prefix if any */ if (prefix) { p = theprefix; while(*p) { if (*p == '^') { p++; c = *p - '@'; Write(printer, &c, 1L); } else Write(printer, *p, 1L); p++; } /* reset the prefix flag */ prefix = 0; } /* now print the file */ print_one_file(my_argv[1]); my_argv++; } Close(printer); printer = 0; } static char buf[1024]; /* Note! if called from WB we have */ static char outbuf[1024+100]; /* very limited stack space */ /* do the actual print for a file */ print_one_file(name) char *name; { long in; long bytes, Read(); register long outbytes; register char *p; int line; int page; int num_lines; int new_line; int chars; char line_buf[10]; char ctl[4]; int i; in = Open(name, MODE_OLDFILE); if (!in) { sprintf(buf, "unable to open: '%s'\f", name); Write(printer, buf, (long) strlen(buf)); return; } line = 1; page = 1; /* print a file header if desired */ if (headers) { sprintf(buf, "File: %s Page %d\n\n", name, page); Write(printer, buf, (long) strlen(buf)); num_lines = 3; } else num_lines = 1; if (numbers || control || lines_per_page || chars_per_line) { outbytes = 0; if (numbers) { sprintf(outbuf, "%4d ", line); outbytes = strlen(outbuf); chars = outbytes; } /* now read the file a block at a time */ while(bytes = Read(in, buf, 1024L)) { p = buf; if (bytes < 0) { sprintf(buf, "Error reading file: %s\n", name); Write(printer, buf, (long) sizeof(buf)); return; } /* now write out this block */ while(bytes) { /* check for control chars, if requested */ if (control) { if ((*p < ' ')&&(*p != '\n')&&(*p != '\t')){ /* print all other control chars in ^A format */ outbuf[outbytes++] = '^'; *p += '@'; chars++; } } /* check for a new line */ if ((*p == '\n')||(*p == '\f')) { /* newline, need a page break? */ if (((*p == '\f') && (!control)) || (lines_per_page && (num_lines >= lines_per_page))) { /* is this a user formfeed */ if (*p == '\f') { sprintf(buf, "
\f"); strcpy(&outbuf[outbytes], buf); outbytes += strlen(buf); line--; } else outbuf[outbytes++] = '\f'; /* print a file header if desired */ page++; if (headers) { sprintf(buf, "File: %s Page %d\n\n", name, page); strcpy(&outbuf[outbytes], buf); outbytes += strlen(buf); num_lines = 2; } else num_lines = 0; } line++; num_lines++; new_line = 1; } else new_line = 0; /* now put the character and account for it */ chars++; bytes--; switch (*p) { case '\t': if (tab_stops) { if ((chars % tab_stops) == 0) { for(i=0; i < tab_stops; i++) { outbuf[outbytes++] = ' '; chars++; } } else while(chars % tab_stops) { outbuf[outbytes++] = ' '; chars++; } p++; } else { while(chars % 8) chars++; outbuf[outbytes++] = *p++; } break; case '\f': /* formfeeds are accounted for eariler */ p++; break; case 8: chars--; outbuf[outbytes++] = *p++; break; default: outbuf[outbytes++] = *p++; } /* check for line overflow, if requested */ if (chars_per_line && (chars >= chars_per_line)) { outbuf[outbytes++] = '\n'; num_lines++; if (numbers) { strcpy(&outbuf[outbytes], " "); outbytes += 5; chars = 5; } else chars = 0; } /* now put out the line number if needed */ if (new_line && numbers) { sprintf(&outbuf[outbytes], "%4d ", line); outbytes += 5; chars = 5; } /* dump the buffer if near full */ if (outbytes >= 1000L) { Write(printer, outbuf, outbytes); outbytes = 0; } } /* while chars in this block */ } /* while not EOF */ /* flush last line */ if (outbytes) Write(printer, outbuf, outbytes); } else { /* we can just pump out the data untouched */ while(bytes = Read(in, buf, 1024L)) if (bytes > 0) Write(printer, buf, bytes); else { sprintf(buf, "Error reading file"); Write(printer, buf, (long) sizeof(buf)); } } Write(printer, "\f", 1L); Close(in); in = 0; } set_up_print(name) char *name; { long save; extern long tty; extern char **av; extern int called_from_WB; extern long current_dir; char option_string[80]; char numbuf[16]; char c; int i; char buf[100]; long result, Execute(); int fake_argc; char *fake_argv[4]; /* * print the current file */ save = tty; /* first make sure we can get the printer */ printer = Open("PRT:", MODE_NEWFILE); if (!printer) { error("can't access the printer at this time"); } else { /* printer is avail so... */ tty = Open("RAW:100/50/470/100/Less's print server", MODE_NEWFILE); if (!tty) { tty = save; Close(printer); printer = 0; error("Can't open window!"); return; } ttputs("Print File: "); ttputs(name); ttputs("\nEnter the first letter of each option, if any\n"); ttputs("For example 'nh#60|80t8^l', the options are...\n"); so_enter(); ttputs("numberedlines headers ^ctrl proportional \n"); ttputs("letterquality draft wide uncompressed \n"); ttputs("# of rows, | of columns, t tabstop\n"); so_exit(); ttputs("\nOptions or 'q' to quit? "); /* get a responce */ i = 0; while (c = ttgetc()) { if (c == 8) { /* backspace ? */ if (i > 0) { i--; ttputc(c); } } else { if ((c < ' ') || (i > 32)) break; option_string[i++] = c; ttputc(c); } } option_string[i] = 0; if(toupper(option_string[0]) != 'Q') { if (called_from_WB) { /* I haven't figured out how to queue from WB */ #ifndef WB_QUEUED if (option_string[0]) { sprintf(buf, "-%s", option_string); fake_argc = 3; fake_argv[1] = buf; fake_argv[2] = name; } else { fake_argc = 2; fake_argv[1] = name; } fake_argv[fake_argc] = NULL; ttputs("\nPrinting...\n"); start_print(fake_argc, fake_argv); ttputs("Complete!\n"); #else /* this should work but I can't figure out why not */ sprintf(buf, "RUN %s -p %ld ", prog_name, current_dir); if (option_string[0]) { strcat(buf, "-"); strcat(buf, option_string); strcat(buf, " "); } strcat(buf, name); /* give up the printer */ Close(printer); printer = 0; /* and execute the job */ std_out = Open("NIL:", MODE_OLDFILE); result = Execute(buf, 0L, std_out); if (result) { ttputs("\nJob queued\n"); } else { sprintf(buf, "\nError on Execute: %ld", result); ttputs(buf); } #endif } else { /* from CLI, queue it to a copy of myself */ sprintf(buf, "RUN %s -p ", prog_name); if (option_string[0]) { strcat(buf, "-"); strcat(buf, option_string); strcat(buf, " "); } strcat(buf, name); /* give up the printer */ Close(printer); printer = 0; /* and execute the job */ result = Execute(buf, 0L, 0L); if (result) { ttputs("\nJob queued\n"); } else { sprintf(buf, "\nError on Execute: %ld", result); ttputs(buf); } } } else { Close(printer); printer = 0; ttputs("\nPrint request canceled by user!\n"); } Delay(100L); ttclose(); tty = save; } }