386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gp_dosfb.c
CommitLineData
79177862
WJ
1/* Copyright (C) 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* gp_dosfb.c */
21/* MS-DOS frame buffer swapping routines for Ghostscript */
22#include <conio.h>
23#include "memory_.h"
24#include "gx.h"
25#include "gp.h"
26#include "gserrors.h"
27#include "gxdevice.h"
28
29/* On MS-DOS machines, we maintain a console image in memory, */
30/* and swap screens on request. */
31#define cw_width 80
32#define cw_height 25
33typedef struct text_line_s {
34 int end;
35 char text[cw_width + 1];
36} text_line;
37typedef struct {
38 text_line _ds *line;
39 text_line lines[cw_height];
40} ds_text_screen;
41
42private ds_text_screen console;
43
44private int console_is_current;
45
46/* Buffer one scan line of graphics. */
47#define row_buf_size 1280
48private char graphics_file_name[] = "_temp_.gfb";
49
50/* Forward references */
51private int save_graphics(P1(gx_device *));
52private int restore_graphics(P1(gx_device *));
53
54/* Initialize the console buffer. */
55void
56gp_init_console()
57{ memset(&console.lines, 0, sizeof(console.lines));
58 console.line = &console.lines[0];
59 console_is_current = 0;
60}
61
62/* Write a string to the console. */
63void
64gp_console_puts(const char *str, uint size)
65{ register ds_text_screen _ds *cop = &console;
66 register text_line _ds *lip = cop->line;
67 for ( ; size ; str++, size-- )
68 switch ( *str )
69 {
70 case '\n':
71 if ( lip == &cop->lines[cw_height - 1] )
72 { /* Scroll up */
73 memcpy(&cop->lines[0], &cop->lines[1],
74 sizeof(text_line) * (cw_height - 1));
75 }
76 else
77 cop->line = ++lip;
78 lip->end = 0;
79 break;
80 case '\t':
81 gp_console_puts(" ", 8 - (lip->end & 7));
82 lip = cop->line;
83 break;
84 default:
85 if ( lip->end == cw_width )
86 { gp_console_puts("\n", 1);
87 lip = cop->line;
88 }
89 lip->text[lip->end++] = *str;
90 }
91}
92
93/* Make the console current on the screen. */
94int
95gp_make_console_current(gx_device *dev)
96{ int code = 0;
97 if ( !console_is_current )
98 code = save_graphics(dev);
99 /* Transfer the console buffer to the screen. */
100 /* Unfortunately, there is no standard way to clear the screen. */
101 /* Output the ANSI sequence and hope for the best. */
102 cputs("\r\033[2J\r \r");
103 { int i;
104 register text_line _ds *lip;
105 for ( i = 0, lip = &console.lines[0]; i < cw_height; i++, lip++ )
106 { if ( i != 0 ) cputs("\r\n");
107 lip->text[lip->end] = 0;
108 cputs(lip->text);
109 }
110 }
111 console_is_current = 1;
112 return code;
113}
114
115/* Make the graphics current on the screen. */
116int
117gp_make_graphics_current(gx_device *dev)
118{ if ( console_is_current )
119 { int code = restore_graphics(dev);
120 if ( code < 0 ) return code;
121 console_is_current = 0;
122 }
123 return 0;
124}
125
126/* ------ Internal routines ------ */
127
128/* We compress the pixmap just a little, by noting */
129/* replicated bytes at the beginning and end of a line. */
130typedef struct { ushort pre, post; } row_head;
131
132/* Save the graphics screen on a file. */
133private int
134save_graphics(gx_device *dev)
135{ uint row_size = gx_device_bytes_per_scan_line(dev, 0);
136 char row_buf[row_buf_size];
137 int count = row_buf_size / row_size;
138 FILE *gfile;
139 int y;
140 if ( count == 0 ) return -1;
141 gfile = fopen(graphics_file_name, "wb");
142 if ( gfile == 0 ) return gs_error_ioerror;
143 for ( y = 0; y < dev->height; y += count )
144 { char _ss *row = row_buf;
145 int n = count;
146 (*dev->procs->get_bits)(dev, y, row, row_buf_size, 0);
147 while ( n-- )
148 { row_head head;
149 char _ss *beg = row, *end = row + row_size - 1;
150 while ( end > beg && *end == end[-1] ) end--;
151 if ( beg < end )
152 while ( *beg == beg[1] ) beg++;
153 head.pre = beg - row;
154 head.post = end + 1 - row;
155 fwrite((char *)&head, 1, sizeof(head), gfile);
156 fwrite(beg, head.post - head.pre, 1, gfile);
157 row += row_size;
158 }
159 }
160 fclose(gfile);
161 return 0;
162}
163
164/* Restore the graphics screen from a file. */
165private int
166restore_graphics(gx_device *dev)
167{ FILE *gfile;
168 uint row_size = gx_device_bytes_per_scan_line(dev, 0);
169 char row_buf[row_buf_size];
170 int y;
171 if ( row_size > row_buf_size ) return -1;
172 gfile = fopen(graphics_file_name, "rb");
173 if ( gfile == 0 ) return gs_error_ioerror;
174 for ( y = 0; y < dev->height; y ++ )
175 { row_head head;
176 char _ss *beg, *end;
177 fread((char *)&head, 1, sizeof(head), gfile);
178 beg = row_buf + head.pre;
179 end = row_buf + head.post;
180 fread(beg, 1, end - beg, gfile);
181 if ( head.pre )
182 memset(row_buf, *beg, head.pre);
183 if ( head.post < row_size )
184 memset(end, end[-1], row_size - head.post);
185 (*dev->procs->copy_color)(dev, row_buf, 0, row_size, gx_no_bitmap_id, 0, y, dev->width, 1);
186 }
187 fclose(gfile);
188 return 0;
189}