home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
mskermit
/
msphpl.c
< prev
next >
Wrap
C/C++ Source or Header
|
2018-01-01
|
11KB
|
381 lines
static char copyr[] = "Copyright 1990 by Dr. R. Brooks Van Horn, Jr.";
/*
This version of the Print Screen routine is for the HP Laser
series printers and a VGA or EGA video adaptor with the higher
resolution video modes, including super VGA.
*/
#include <malloc.h>
#include <bios.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define dither 6
#define esc 27
#define LENMAX 770
/* functions needed in program */
void interrupt (far * int05) (void);
void interrupt PrtScrn (void);
int Print ( int, char * );
void PinSet ( int, int, int, int );
char Read_Pixel (int, int);
/* data needed */
static int dpi = 300;
static long Columns;
static int Max_Rows;
static int Max_Cols;
static char Video_Mode;
int far * dkb = 0x0000041a; /* DOS Keyboard Area */
char far * dds = 0x00000000; /* DOS Data Segment */
char far * vds = 0x00000500; /* Video Data Segment */
char far * Regen = 0xa0000000; /* Video Screen Address */
char buffer[LENMAX], pline[256];
int h_ratio, h_fract, v_ratio, v_fract;
static int number;
/*----------------------------------------------------------------------*/
main ()
{
unsigned int pgm_size;
char far * ptr = 0x00000467; /* use cassette data area */
number = 0;
*vds = 0;
if (*ptr == 'b' && *(ptr+1) == 'v' && *(ptr+2) == 'h') {
puts ("Laser.Exe TSR is already resident.");
exit (1);
}
int05 = getvect (0x05);
*(ptr ) = 'b';
*(ptr+1) = 'v';
*(ptr+2) = 'h';
setvect (0x05, PrtScrn);
pgm_size = farsetsize(0);
puts ("Laser Graphics Print Screen TSR");
puts ( copyr );
puts ("has now been installed.");
keep (0, pgm_size);
}
/*----------------------------------------------------------------------*/
void interrupt PrtScrn (void)
{
int kb_head = *dkb, kb_tail= *(dkb+1);
int row, col, cbit, error;
int total, pin, i, j, k, rtot, extra, tcheck, begin, lenth;
char pat, pat1, pat2, pat3, zero = 0x00;
char crlf[] = { 0x0d, 0x0a }; /* do cr/lf cmd */
char init_prn[] = {
esc, 'E', /* Reset */
esc, '&', 'l', '0', 'O', /* Portrait */
esc, '*', 't', '3', '0', '0', 'R', /* dpi resolution */
esc, '&', 'a', '6', '5', '0', 'H', /* move cursor from left */
esc, '&', 'a', '2', '0', '0', 'V', /* and from the top */
esc, '*', 'r', '1', 'A' /* strt grphs @ cursor pos */
};
/* Transmit xxx bytes of data following command */
char graph[] = { esc, '*', 'b', 'x', 'x', 'x', 'W', 0, 0 };
char width[] = " ";
char eop[] = { esc, '*', 'r', 'B', /* end graphics */
12, /* form feed */
esc, 'E' /* and reset printer */
};
union REGS regs;
if (++number > 2)
*vds = 0;
if (*vds != 0) { /* if printing is active then exit */
sound ( 950, 18 );
return;
}
Video_Mode = *(dds + 0x0449);
if (Video_Mode <= 3) {/* if we are not in a graphics mode */
int05();
return;
}
/* we are now in a position to do a print screen */
*vds = 0xff; /* mark print screen status flag for others */
enable(); /* enable further interrupts */
Max_Rows = (int) *(dds + 0x0484) + 1;
Max_Cols = ((int) *(dds + 0x044a)) + (((int) *(dds + 0x0000044b)) << 8);
Max_Rows *= (int) *(dds + 0x0485); /* convert text chars to pixels */
Columns = (long) Max_Cols;
Max_Cols *= 8;
/*
The dimensions of the screen were obtained from the bios data area.
The next step is to determine the size of the picture based on
reserving a one inch margin on all sides and trying to use a 5 x 5
dithering matrix. We use the term vertical to represent the
direction along the 8.5" side of the printer paper and horizontal
along the 11" side.
┌──────────────────────────────┐
│ 1" │
│ ┌──────────────────────┐ │
│ │ Top │ │
│ │ │ │
│ │ │ │
<------- │ 1"│ Picture │1" │ 8.5"(v)
Paper │ │ │ │
Feed │ │Left │ │
│ └──────────────────────┘ │
│ 1" │
└──────────────────────────────┘
11" (h)
*/
v_ratio = (( 13 * dpi ) >> 1); /* 6.5" * dots per inch */
/* but adjust if it is too big for dithering matrix */
v_ratio = v_ratio > (dither * Max_Rows) ? (dither * Max_Rows) : v_ratio;
h_ratio = (4 * v_ratio + 1) / 3; /* 4:3 ratio adj for length*/
/* get the fraction part of the ratio for vertical and horizontal */
v_fract = v_ratio % Max_Rows;
v_fract = (10 * v_fract + (Max_Rows>>1)) / Max_Rows; /* in [0,9] */
h_fract = h_ratio % Max_Cols;
h_fract = (10 * h_fract + (Max_Cols>>1)) / Max_Cols; /* in [0,9] */
/* then get the integer part of the ratios */
v_ratio = v_ratio / Max_Rows;
h_ratio = h_ratio / Max_Cols;
/* now check for overflows in rounding too high */
if (v_fract >= 10) {
v_ratio++;
v_fract -= 10;
}
if (h_fract >= 10) {
h_ratio++;
h_fract -= 10;
}
/* now get the actual bytes to be sent to the printer per pass */
tcheck = ((((10 * v_ratio + v_fract) * Max_Cols) / 10) + 7) >> 3;
/* initialize the printer */
regs.byte.ah = 1;
regs.word.dx = 0;
int86 ( 0x17, ®s, ®s ); /* initialize port LPT0 */
if (Print ( 33, init_prn )) { /* reset the printer */
*vds = 0;
return;
}
/*
We now process the video screen from the left to the right
on the columns. The given pixel values will be dithered to
provide a shading like effect for the black and white laser
printer.
*/
total = 0;
for ( col = 0; col < Max_Cols; ++col) {
if ((col % 100) == 0)
sound ( 1500, 1 );
/* check to see if a key has been pressed */
if ((*dkb != kb_head) || (*(dkb+1) != kb_tail)) {
*dkb = kb_head;
*(dkb+1) = kb_tail;
Print ( 7, eop );
goto GET_OUT;
}
/* read a row of pixels for this column */
for (i = 0, row = Max_Rows-1; row >= 0; --row, ++i )
buffer[i] = Read_Pixel ( row, col );
/* clear out the printer line for packing */
memset ( pline, 0, 256 );
/*
now build the 'tcheck' bytes to send to the printer
remembering that we will be multiline processing too.
*/
pin = h_ratio;
/* add fraction in to the sum */
total += h_fract;
if (total >= 10) { /* adjust for fractionals */
total -= 10;
++pin;
}
/* This column will be processed 'pin' times in dither length */
for (k = 0; k < pin; ++k) {
extra = 0;
rtot = 0;
begin = 0;
lenth = 1;
for (i = 0; i < Max_Rows; ++i) {
rtot += v_ratio;
extra += v_fract;
if (extra >= 10) {
extra -= 10;
++rtot;
}
if (buffer[i])
lenth = rtot;
PinSet ( i, k, begin, rtot );
begin = rtot;
}
/* declare number of items to send to printer */
lenth = (lenth + 7) >> 3;
itoa ( lenth, width, 10);
if (lenth >= LENMAX) {
puts (width);
lenth = LENMAX;
sound (1100,36);
}
strcpy ( &graph[3], width ); /* copy # bytes to txmt */
strcat (graph, "W");
for (j = 0; graph[j]; ++j) ; /* get length of string */
if ( Print ( j, graph ) )
goto GET_OUT;
if ( Print ( lenth, pline ) )
goto GET_OUT;
} /* end for-loop on duplicate rows */
} /* end for-loop on cols */
Print ( 7, eop );
GET_OUT:
sound ( 1500, 9 );
*vds = 0;
number = 0;
return;
}
/*----------------------------------------------------------------------*/
char Read_Pixel ( int row, int col )
{
long offset = (long) row * Columns + (long)(col>>3);
int plane, k;
char color = 0x00, mask, temp;
union REGS regs;
if (row >= Max_Rows || col >= Max_Cols)
return 0;
if (Video_Mode < 8) { /* if CGA let BIOS do it */
regs.word.ax = 0x0d00;
regs.word.bx = 0;
regs.word.dx = row;
regs.word.cx = col;
int86 ( 16, ®s, ®s );
color = regs.byte.al;
}
else {
mask = 0x80 >> (col % 8); /* bit mask for addressed byte */
outp (0x3ce,4); /* select the Map Mask register */
for (plane = 3; plane >= 0; --plane) {
outp (0x3cf,plane); /* address the bit plane */
temp = *(Regen + offset) & mask; /* get bit value */
temp = temp ? 1 : 0 ; /* set bit if color match */
color = (color << 1) | temp; /* save plane results */
}
outp (0x3c4,2); /* restore to Write Mode 0 */
outp (0x3c5,15); /* with all planes enabled */
}
return color;
}
/*----------------------------------------------------------------------*/
void PinSet ( ndx, sect, b1, b2 )
int ndx; /* index to the color pattern to be smoothed */
int sect; /* the row duplication index */
int b1; /* the beginning bit to set */
int b2; /* the last bit to set */
{
char pats[dither][dither];
int bit, j, k, wd, i, kmod;
char I, R, G, B, pat = buffer[ndx];
if (pat == 0) /* if nothing to set then return */
return;
k = v_ratio >= dither ? dither : (v_ratio + 1);
switch ( k ) {
case 1:
case 2:
case 3:
I = R = G = B = pat;
kmod = 1;
break;
case 4:
case 5:
B = pat & 0x09; /* B or I */
R = pat & 0x0a; /* R or I */
G = pat & 0x0c; /* G or I */
I = pat & 0x08; /* I */
kmod = 3;
break;
default:
B = pat & 0x01;
R = pat & 0x02;
G = pat & 0x04;
I = pat & 0x08;
kmod = 4;
}
bit = 0;
for (i = 0; i < k; ++i) {
for (j = 0; j < k; ++j, ++bit) {
switch ( bit % kmod ) {
case 0:
pats[i][j] = R;
break;
case 1:
pats[i][j] = G;
break;
case 2:
pats[i][j] = B;
break;
case 3:
pats[i][j] = I;
}
}
}
/* now create bytes for printing with these patterns */
for (bit = b1; bit < b2; ++bit) {
k = bit - b1; /* row index to pats array */
if (pats[k][sect]) { /* if dithering has something here */
wd = bit / 8; /* word index */
i = 7 - ( bit % 8 ); /* bit index */
pline[wd] |= (0x01 << i); /* and the bit mask */
}
}
return;
}
/*--------------------------------------------------------------*/
int Print ( int items, char * strng )
{
int i;
int result;
union REGS regs;
for (i= 0; i < items; ++i) {
regs.byte.ah = 0; /* function number */
regs.byte.al = strng[i]; /* character to print */
regs.word.dx = 0; /* printer Lpt0 */
int86 ( 0x17, ®s, ®s );
result = (int) regs.byte.ah; /* printer return code */
if (result & 0x0029) {
/* printer error */
return ( result );
}
}
return 0;
}