1 /*
2 Copyright (c) 1991 - 1994 Michael Schoene & Heinz W. Werntges.
3 Parts Copyright (c) 1999 Martin Kroeker.
4
5 All rights reserved. Distributed by Free Software Foundation, Inc.
6
7 This file is part of HP2xx.
8
9 HP2xx is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
11 to anyone for the consequences of using it or for whether it serves any
12 particular purpose or works at all, unless he says so in writing. Refer
13 to the GNU General Public License, Version 2 or later, for full details.
14
15 Everyone is granted permission to copy, modify and redistribute
16 HP2xx, but only under the conditions described in the GNU General Public
17 License. A copy of this license is supposed to have been
18 given to you along with HP2xx so you can know your rights and
19 responsibilities. It should be in a file named COPYING. Among other
20 things, the copyright notice and this notice must be preserved on all
21 copies.
22
23 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
24 */
25
26 /** to_x11.c: X11 preview part of project "hp2xx" (UNIX only)
27 **
28 ** 92/01/15 V 1.00 HWW Derived from to_vga.c (V1.01b)
29 ** X11 essentials due to M. Schoene
30 ** 92/01/28 V 1.01 HWW Window offset user-defined via -o -O
31 ** 92/02/03 V 1.02 HWW bug fixes, error handling
32 ** 92/05/19 V 1.02b HWW Abort if color mode
33 ** 92/05/25 V 1.10 HWW 8 Colors supported
34 ** 93/01/06 V 1.10b HWW Improved selection of foreground color
35 ** 94/02/14 V 1.20a HWW Adapted to changes in hp2xx.h
36 ** 01/04/22 YuS Exit on button and key events
37 **
38 ** NOTE: Color assignment leaves something to be desired
39 ** with some X11 servers.
40 **/
41
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <sys/time.h>
47 #include <X11/Xlib.h>
48 #include <X11/Xutil.h>
49
50 #include "bresnham.h"
51 #include "pendef.h"
52 #include "hp2xx.h"
53 #include "x11.h"
54
55
56
57 #define WIN_NAME "x11" /* Window name */
58 #define PROG_NAME "hp2xx" /* Program name */
59
60
61
62 /**
63 ** Global variables for X11
64 **/
65
66 static Display *XDisplay = NULL; /* Workstation id */
67 static int XScreen;
68 static Window XRoot; /* Number of root window */
69 static Visual *XVisual = NULL;
70
71 static GC XGcWin;
72 static Window XWin; /* Window id */
73
74 static unsigned long col_table[CMS_SIZE];
75 static XColor Xcol;
76 static Colormap def_clut;
77
78 /**
79 ** Screen sizes
80 **/
81
82 static int scr_width;
83 static int scr_height;
84
85 /**
86 ** Window sizes
87 **/
88
89 static int width;
90 static int bytes;
91 static int height;
92
93 /* Added by YuS 22 April 2001 */
94 XEvent WaitEvent;
95
96 static int row_start = 0;
97 static int col_start = 0;
98 static int oversized = 0;
99 static int zoomed = 0;
100 /**
101 ** Initialize X11 and open window
102 **/
103
104 static int
win_open(const GEN_PAR * pg,char * title,int x,int y,int w,int h)105 win_open (const GEN_PAR * pg, char *title, int x, int y, int w, int h)
106 {
107 char *DisplayName = NULL;
108 char **argv;
109 XSizeHints Hints;
110 unsigned long ValueMask;
111 XSetWindowAttributes WinAttr;
112 XEvent Event;
113 char colorname[13];
114 int i;
115
116 /**
117 ** Simulate command line arguments
118 **/
119
120 argv = (char **) malloc (3 * sizeof (char *));
121 argv[0] = PROG_NAME;
122 argv[1] = title;
123 argv[2] = NULL;
124
125 /**
126 ** X11 server reachable ?
127 **/
128
129 if ((XDisplay = (Display *) XOpenDisplay (DisplayName)) == NULL)
130 {
131 Eprintf ("No X11 server found !\n");
132 return NO_SERVER;
133 }
134
135
136
137 XScreen = DefaultScreen (XDisplay);
138 XRoot = RootWindow (XDisplay, XScreen);
139 XVisual = DefaultVisual (XDisplay, XScreen);
140 XGcWin = DefaultGC (XDisplay, XScreen);
141
142 scr_width = WidthOfScreen (ScreenOfDisplay (XDisplay, XScreen));
143 scr_height = HeightOfScreen (ScreenOfDisplay (XDisplay, XScreen));
144 if (x + w > scr_width || y + h > scr_height)
145 {
146 if (!pg->quiet)
147 Eprintf ("Window exceeds screen limits, use mouse button 1 to pan\n");
148 w = MIN (w, scr_width);
149 h = MIN (h, scr_height);
150 oversized = 1;
151 /* return SIZE;*/
152 }
153
154 /**
155 ** Set window attributes
156 **/
157
158 WinAttr.background_pixel = WhitePixel (XDisplay, XScreen);
159 WinAttr.border_pixel = WhitePixel (XDisplay, XScreen);
160 WinAttr.backing_store = Always;
161 ValueMask = CWBackPixel | CWBorderPixel | CWBackingStore;
162
163 /**
164 ** Create Window
165 **/
166
167 XWin = XCreateWindow (XDisplay, XRoot,
168 x, y, w, h,
169 1, 0,
170 CopyFromParent, CopyFromParent, ValueMask, &WinAttr);
171
172 /**
173 ** Define window properties
174 **/
175
176 Hints.flags = PSize | PMinSize | PMaxSize | USPosition;
177 Hints.x = x;
178 Hints.y = y;
179 Hints.width = Hints.min_width = Hints.max_width = w;
180 Hints.height = Hints.min_height = Hints.max_height = h;
181
182 XSetStandardProperties (XDisplay, XWin,
183 title, title, 0, argv, 2, &Hints);
184
185 /**
186 ** Define color table (compatible to SunView and Turbo-C usage)
187 **/
188
189 def_clut = DefaultColormap (XDisplay, XScreen);
190 if (DefaultDepth (XDisplay, XScreen) < 4)
191 {
192 col_table[BLACK] = WhitePixel (XDisplay, XScreen);
193 col_table[WHITE] = BlackPixel (XDisplay, XScreen);
194 col_table[GRAY] = col_table[WHITE];
195 col_table[RED] = col_table[WHITE];
196 col_table[GREEN] = col_table[WHITE];
197 col_table[BLUE] = col_table[WHITE];
198 col_table[CYAN] = col_table[WHITE];
199 col_table[MAGENTA] = col_table[WHITE];
200 col_table[YELLOW] = col_table[WHITE];
201 col_table[LIGHTGRAY] = col_table[WHITE];
202 col_table[LIGHTRED] = col_table[WHITE];
203 col_table[LIGHTGREEN] = col_table[WHITE];
204 col_table[LIGHTBLUE] = col_table[WHITE];
205 col_table[LIGHTCYAN] = col_table[WHITE];
206 col_table[LIGHTMAGENTA] = col_table[WHITE];
207 }
208 else
209 {
210 XParseColor (XDisplay, def_clut, "gray10", &Xcol);
211 XAllocColor (XDisplay, def_clut, &Xcol);
212 col_table[GRAY] = Xcol.pixel;
213
214 for (i = 1; i <= pg->maxpens; i++)
215 {
216
217 sprintf (colorname, "#%2.2X%2.2X%2.2X",
218 pt.clut[i][0], pt.clut[i][1], pt.clut[i][2]);
219 XParseColor (XDisplay, def_clut, colorname, &Xcol);
220 XAllocColor (XDisplay, def_clut, &Xcol);
221 col_table[i] = Xcol.pixel;
222 }
223 }
224
225
226 /**
227 ** Set foreground and background colors
228 **/
229
230 XSetState (XDisplay, XGcWin,
231 col_table[BLACK], col_table[WHITE], GXcopy, AllPlanes);
232
233 /**
234 ** Define permitted events for this window
235 **/
236
237 XSelectInput (XDisplay, XWin,
238 ExposureMask | VisibilityChangeMask | KeyPressMask |
239 ButtonPressMask | ButtonReleaseMask);
240
241 /**
242 ** Display window
243 **/
244 XMapWindow (XDisplay, XWin);
245 do
246 {
247 XNextEvent (XDisplay, &Event);
248 }
249 while (Event.type != Expose && Event.type != VisibilityNotify);
250
251 width = w;
252 height = h;
253 bytes = (w + 7) / 8;
254
255
256 free ((char *) argv);
257 return (0);
258 }
259
260
261
262 void
win_close()263 win_close ()
264 {
265 XDestroyWindow (XDisplay, XWin);
266 XCloseDisplay (XDisplay);
267 }
268
269
270
271
272 #define setXcolor(col) XSetForeground (XDisplay, XGcWin, col_table[col])
273
274
275
276
277 int
PicBuf_to_X11(const GEN_PAR * pg,OUT_PAR * po)278 PicBuf_to_X11 ( const GEN_PAR * pg, OUT_PAR * po)
279 /**
280 ** Interface to higher-level routines,
281 ** similar in structure to other previewers
282 **/
283 {
284 int row_c, x, y;
285 int saved_col=0,saved_row=0;
286 int xref = 0, yref = 0;
287 const RowBuf *row;
288 const PicBuf *pb;
289 struct timeval tv;
290 tv.tv_usec = 10;
291
292 if (pg == NULL || po == NULL)
293 return ERROR;
294 pb = po->picbuf;
295 if (pb == NULL)
296 return ERROR;
297
298 if (!pg->quiet)
299 {
300 Eprintf ("\nX11 preview follows.\n");
301 Eprintf ("Press any key to end graphics mode\n");
302 }
303
304 if (win_open (pg, po->outfile, (int) (po->xoff * po->dpi_x / 25.4),
305 (int) (po->yoff * po->dpi_y / 25.4), pb->nb << 3, pb->nr))
306 return ERROR;
307 REDRAW:
308 /* Backward since highest index is lowest line on screen! */
309 for (row_c = row_start, y = MIN (height-row_start, pb->nr - 1);
310 row_c < pb->nr; row_c++, y--)
311 {
312 row = get_RowBuf (pb, row_c);
313 if (row == NULL)
314 return 0;
315 for (x = col_start; x < pb->nc; x++)
316 {
317 switch (index_from_RowBuf (row, x, pb))
318 {
319
320 case xxBackground:
321 continue;
322 case xxForeground:
323 setXcolor (WHITE);
324 break;
325 /*
326 case xxRed: setXcolor (RED); break;
327 case xxGreen: setXcolor (GREEN); break;
328 case xxBlue: setXcolor (BLUE); break;
329 case xxCyan: setXcolor (CYAN); break;
330 case xxMagenta: setXcolor (MAGENTA); break;
331 case xxYellow: setXcolor (YELLOW); break;
332 */
333 default:
334 setXcolor (index_from_RowBuf (row, x, pb));
335 break;
336 }
337 XDrawPoint (XDisplay, XWin, XGcWin, x - col_start, y + row_start);
338 }
339 }
340
341 /* Wait KeyPress of any mouse ButtonPress to exit */
342 do
343 {
344 XNextEvent (XDisplay, &WaitEvent);
345 if (WaitEvent.type == ButtonPress)
346 {
347 if (WaitEvent.xbutton.button == Button1)
348 {
349 xref = WaitEvent.xbutton.x;
350 yref = WaitEvent.xbutton.y;
351 }
352 if (WaitEvent.xbutton.button == Button2)
353 {
354 if (!zoomed){
355 zoomed=1;
356 po->dpi_x *=2;
357 po->dpi_y *=2;
358 po->HP_to_xdots *=2;
359 po->HP_to_ydots *=2;
360 saved_row=row_start;
361 saved_col=col_start;
362 row_start = height-WaitEvent.xbutton.y+2*saved_row;
363 if (height <scr_height) row_start = (height-WaitEvent.xbutton.y);
364 col_start = WaitEvent.xbutton.x+col_start;
365 } else {
366 zoomed=0;
367 po->dpi_x = po->dpi_x/2;
368 po->dpi_y = po->dpi_y/2;
369 po->HP_to_xdots = po->HP_to_xdots/2;
370 po->HP_to_ydots = po->HP_to_ydots/2;
371 row_start=saved_row;
372 col_start=saved_col;
373 }
374 free(po->picbuf);
375 po->picbuf=NULL;
376 TMP_to_BUF(pg, po);
377 pb=po->picbuf;
378 }
379 }
380 else if (WaitEvent.type == ButtonRelease)
381 {
382 if (WaitEvent.xbutton.button == Button1)
383 {
384 if (oversized)
385 {
386 row_start += WaitEvent.xbutton.y - yref;
387 col_start += xref - WaitEvent.xbutton.x;
388 if (row_start > pb->nr)
389 row_start = pb->nr - scr_height;
390 if (row_start < 0)
391 row_start = 0;
392 if (scr_width + col_start > pb->nc)
393 col_start = pb->nc - scr_width;
394 if (col_start < 0)
395 col_start = 0;
396 }
397 XSetForeground (XDisplay, XGcWin,
398 WhitePixel (XDisplay, XScreen));
399 XFillRectangle (XDisplay, XWin, XGcWin, 0, 0, scr_width,
400 scr_height);
401 goto REDRAW; /* yes, goto in C is ugly */
402 }
403 if (WaitEvent.xbutton.button == Button2){
404 XSetForeground (XDisplay, XGcWin,
405 WhitePixel (XDisplay, XScreen));
406 XFillRectangle (XDisplay, XWin, XGcWin, 0, 0, scr_width,
407 scr_height);
408 goto REDRAW; /* yes, goto in C is ugly */
409 }
410 break;
411 select (0, NULL, NULL, NULL, &tv);
412 }
413 }
414 while (WaitEvent.type != KeyPress);
415
416 win_close ();
417 return 0;
418 }
419