source: git/src/printwin.c @ e3a14ae

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereowalls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since e3a14ae was 3857e321, checked in by Olly Betts <olly@…>, 23 years ago

Inform user where printer output is being sent.

git-svn-id: file:///home/survex-svn/survex/trunk@1762 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/* printwin.c */
2/* Device dependent part of Survex Win32 driver */
3/* Copyright (C) 1993-2002 Olly Betts
4 * Copyright (C) 2001 Philip Underwood
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <math.h>
28#include <string.h>
29#include <time.h>
30#include <ctype.h>
31#include <float.h>
32#include <limits.h>
33
34#include "debug.h" /* for BUG and ASSERT */
35#include "filelist.h"
36#include "filename.h"
37#include "ini.h"
38#include "message.h"
39#include "prcore.h"
40#include "prio.h"
41#include "useful.h"
42
43#include <windows.h>
44
45static double MarginLeft, MarginRight, MarginTop, MarginBottom;
46static int fontsize, fontsize_labels;
47static double LineWidth;
48
49static char *fontname, *fontname_labels;
50
51static const char *win_Name(void);
52static int win_Pre(int pagesToPrint, const char *title);
53static void win_NewPage(int pg, int pass, int pagesX, int pagesY);
54static char *win_Init(FILE **fh_list, const char *pth, const char *outfnm,
55                      double *pscX, double *pscY, bool fCalibrate);
56static int  win_Charset(void);
57static void win_MoveTo(long x, long y);
58static void win_DrawTo(long x, long y);
59static void win_DrawCross(long x, long y);
60static void win_SetFont(int fontcode);
61static void win_WriteString(const char *s);
62static void win_DrawCircle(long x, long y, long r);
63static void win_ShowPage(const char *szPageDetails);
64static void win_Quit(void);
65
66device printer = {
67   PR_FLAG_NOFILEOUTPUT, /* |PR_FLAG_NOINI - now read fontsize from ini file */
68   win_Name,
69   win_Init,
70   win_Charset,
71   win_Pre,
72   win_NewPage,
73   win_MoveTo,
74   win_DrawTo,
75   win_DrawCross,
76   win_SetFont,
77   win_WriteString,
78   win_DrawCircle,
79   win_ShowPage,
80   NULL, /* win_Post */
81   win_Quit
82};
83
84static HDC pd; /* printer context */
85
86static TEXTMETRIC *tm, tm_labels, tm_default; /* font info */
87
88static double scX, scY;
89
90static int cur_pass;
91
92static border clip;
93
94static long xpPageWidth, ypPageDepth;
95
96static long x_t, y_t;
97
98static int
99check_intersection(long x_p, long y_p)
100{
101#define U 1
102#define D 2
103#define L 4
104#define R 8
105   int mask_p = 0, mask_t = 0;
106   if (x_p < 0)
107      mask_p = L;
108   else if (x_p > xpPageWidth)
109      mask_p = R;
110
111   if (y_p < 0)
112      mask_p |= D;
113   else if (y_p > ypPageDepth)
114      mask_p |= U;
115
116   if (x_t < 0)
117      mask_t = L;
118   else if (x_t > xpPageWidth)
119      mask_t = R;
120
121   if (y_t < 0)
122      mask_t |= D;
123   else if (y_t > ypPageDepth)
124      mask_t |= U;
125
126#if 0
127   /* approximation to correct answer */
128   return !(mask_t & mask_p);
129#else
130   /* One end of the line is on the page */
131   if (!mask_t || !mask_p) return 1;
132
133   /* whole line is above, left, right, or below page */
134   if (mask_t & mask_p) return 0;
135
136   if (mask_t == 0) mask_t = mask_p;
137   if (mask_t & U) {
138      double v = (double)(y_p - ypPageDepth) / (y_p - y_t);
139      return v >= 0 && v <= 1;
140   }
141   if (mask_t & D) {
142      double v = (double)y_p / (y_p - y_t);
143      return v >= 0 && v <= 1;
144   }
145   if (mask_t & R) {
146      double v = (double)(x_p - xpPageWidth) / (x_p - x_t);
147      return v >= 0 && v <= 1;
148   }
149   ASSERT(mask_t & L);
150   {
151      double v = (double)x_p / (x_p - x_t);
152      return v >= 0 && v <= 1;
153   }
154#endif
155#undef U
156#undef D
157#undef L
158#undef R
159}
160
161static const char *
162win_Name(void)
163{
164   return "Win32 Printer";
165}
166
167static void
168win_MoveTo(long x, long y)
169{
170   x_t = x - clip.x_min;
171   y_t = clip.y_max - y;
172   if (cur_pass != -1) MoveToEx(pd, x_t, y_t, NULL);
173}
174
175static void
176win_DrawTo(long x, long y)
177{
178   long x_p = x_t, y_p = y_t;
179   x_t = x - clip.x_min;
180   y_t = clip.y_max - y;
181   if (cur_pass != -1) {
182      LineTo(pd, x_t, y_t);
183   } else {
184      if (check_intersection(x_p, y_p)) fBlankPage = fFalse;
185   }
186}
187
188#define POINTS_PER_INCH 72.0
189#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
190#define WIN_CROSS_SIZE (2 * scX / POINTS_PER_MM)
191
192static void
193win_DrawCross(long x, long y)
194{
195   if (cur_pass != -1) {
196      win_MoveTo(x - WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
197      win_DrawTo(x + WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
198      win_MoveTo(x + WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
199      win_DrawTo(x - WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
200      win_MoveTo(x, y);
201   } else {
202      if ((x + WIN_CROSS_SIZE > clip.x_min &&
203           x - WIN_CROSS_SIZE < clip.x_max) ||
204          (y + WIN_CROSS_SIZE > clip.y_min &&
205           y - WIN_CROSS_SIZE < clip.y_max)) {
206         fBlankPage = fFalse;
207      }
208   }
209}
210
211static HFONT font_labels, font_default, font_old;
212
213static void
214win_SetFont(int fontcode)
215{
216   switch (fontcode) {
217      case PR_FONT_DEFAULT:
218         SelectObject(pd, font_default);
219         tm = &tm_default;
220         break;
221      case PR_FONT_LABELS:
222         SelectObject(pd, font_labels);
223         tm = &tm_labels;
224         break;
225      default:
226         BUG("unknown font code");
227   }
228}
229
230static void
231win_WriteString(const char *s)
232{
233   if (cur_pass != -1) {
234      TextOut(pd, x_t, y_t - tm->tmAscent, s, strlen(s));
235   } else {
236      if ((y_t + tm->tmDescent > 0 &&
237           y_t - tm->tmAscent < clip.y_max - clip.y_min) ||
238          (x_t < clip.x_max - clip.x_min &&
239           x_t + strlen(s) * tm->tmAveCharWidth > 0)) {
240         fBlankPage = fFalse;
241      }
242   }
243}
244
245static void
246win_DrawCircle(long x, long y, long r)
247{
248   /* Don't need to check in first-pass - circle is only used in title box */
249   if (cur_pass != -1) {
250      x_t = x - clip.x_min;
251      y_t = clip.y_max - y;
252      Ellipse(pd, x_t - r, y_t - r, x_t + r, y_t + r);
253   }
254}
255
256static int
257win_Charset(void)
258{
259   return CHARSET_ISO_8859_1;
260}
261
262static int
263win_Pre(int pagesToPrint, const char *title)
264{
265   PRINTDLGA psd;
266   DOCINFO info;
267   int logpixelsy;
268
269   pagesToPrint = pagesToPrint; /* suppress compiler warning */
270
271   memset(&psd, 0, sizeof(PRINTDLGA));
272   psd.lStructSize = 66;
273   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
274
275   if (!PrintDlgA(&psd)) exit(1);
276   pd = psd.hDC;
277
278   logpixelsy = GetDeviceCaps(pd, LOGPIXELSY);
279   font_labels = CreateFont(-MulDiv(fontsize_labels, logpixelsy, 72),
280                            0, 0, 0, FW_NORMAL, 0, 0, 0,
281                            ANSI_CHARSET, OUT_DEFAULT_PRECIS,
282                            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
283                            FF_DONTCARE | DEFAULT_PITCH, "Arial");
284   font_default = CreateFont(-MulDiv(fontsize, logpixelsy, 72),
285                             0, 0, 0, FW_NORMAL, 0, 0, 0,
286                             ANSI_CHARSET, OUT_DEFAULT_PRECIS,
287                             CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
288                             FF_DONTCARE | DEFAULT_PITCH, "Arial");
289   font_old = SelectObject(pd, font_labels);
290   GetTextMetrics(pd, &tm_labels);
291   SelectObject(pd, font_default);
292   GetTextMetrics(pd, &tm_default);
293
294   memset(&info, 0, sizeof(DOCINFO));
295   info.cbSize = sizeof(DOCINFO);
296   info.lpszDocName = title;
297
298   StartDoc(pd, &info);
299   return 1; /* only need 1 pass */
300}
301
302static void
303win_NewPage(int pg, int pass, int pagesX, int pagesY)
304{
305   int x, y;
306
307   x = (pg - 1) % pagesX;
308   y = pagesY - 1 - ((pg - 1) / pagesX);
309
310   clip.x_min = (long)x * xpPageWidth;
311   clip.y_min = (long)y * ypPageDepth;
312   clip.x_max = clip.x_min + xpPageWidth; /* dm/pcl/ps had -1; */
313   clip.y_max = clip.y_min + ypPageDepth; /* dm/pcl/ps had -1; */
314
315   cur_pass = pass;
316   if (pass == -1) {
317      /* Don't count alignment marks, but do count borders */
318      fBlankPage = fNoBorder
319         || (x > 0 && y > 0 && x < pagesX - 1 && y < pagesY - 1);
320      return;
321   }
322
323   StartPage(pd);
324   drawticks(clip, 9 * scX / POINTS_PER_MM, x, y);
325}
326
327static void
328win_ShowPage(const char *szPageDetails)
329{
330   win_MoveTo((long)(6 * scX) + clip.x_min, clip.y_min - (long)(7 * scY));
331   win_WriteString(szPageDetails);
332   EndPage(pd);
333}
334
335/* Initialise printer routines */
336static char *
337win_Init(FILE **fh_list, const char *pth, const char *out_fnm,
338         double *pscX, double *pscY, bool fCalibrate)
339{
340   PRINTDLGA psd;
341   LPDEVNAMES *dn;
342   static const char *vars[] = {
343      "like",
344      "font_size_labels",
345      NULL
346   };
347   char **vals;
348
349   fCalibrate = fCalibrate; /* suppress unused argument warning */
350   out_fnm = out_fnm;
351   pth = pth;
352
353   vals = ini_read_hier(fh_list, "win", vars);
354
355   fontsize_labels = as_int(vars[1], vals[1], 1, INT_MAX);
356   fontsize = 10;
357
358   memset(&psd, 0, sizeof(PRINTDLGA));
359   psd.lStructSize = 66;
360   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
361
362   if (!PrintDlgA(&psd)) exit(1);
363
364   PaperWidth = GetDeviceCaps(psd.hDC, HORZSIZE);
365   PaperDepth = GetDeviceCaps(psd.hDC, VERTSIZE);
366   xpPageWidth = GetDeviceCaps(psd.hDC, HORZRES);
367   ypPageDepth = GetDeviceCaps(psd.hDC, VERTRES);
368   MarginLeft = MarginBottom = 0;
369   MarginRight = PaperWidth;
370   MarginTop = PaperDepth;
371   LineWidth = 0;
372   scX = *pscX = xpPageWidth / PaperWidth;
373   scY = *pscY = ypPageDepth / PaperDepth;
374   xpPageWidth--;
375   ypPageDepth = ypPageDepth - (int)(10 * *pscY);
376   DeleteDC(psd.hDC);
377   
378   dn = GlobalLock(psd.hDevNames);
379   if (dn) {
380      char *p = osstrdup((char *)dn + dn->wDeviceOffset);
381      GlobalUnlock(psd.hDevNames);
382      return p;
383   }
384   return NULL;
385}
386
387static void
388win_Quit(void)
389{
390   SelectObject(pd, font_old);
391   DeleteObject(font_labels);
392   DeleteObject(font_default);
393   EndDoc(pd);
394   DeleteDC(pd);
395}
Note: See TracBrowser for help on using the repository browser.