source: git/src/printwin.c @ a11230b

RELEASE/1.0RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereowalls-datawalls-data-hanging-as-warning
Last change on this file since a11230b was 255f57b9, checked in by Olly Betts <olly@…>, 21 years ago

Fix various MSVC warnings.

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

  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[396b9dd]1/* printwin.c */
[55b7334]2/* Device dependent part of Survex Win32 driver */
[b7b666d]3/* Copyright (C) 1993-2002 Olly Betts
[4888f06]4 * Copyright (C) 2001 Philip Underwood
[55b7334]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
[4c07c51]34#include "debug.h" /* for BUG and SVX_ASSERT */
[c34796a]35#include "filelist.h"
[55b7334]36#include "filename.h"
[c34796a]37#include "ini.h"
[55b7334]38#include "message.h"
39#include "prcore.h"
[c34796a]40#include "prio.h"
41#include "useful.h"
42
[55b7334]43#include <windows.h>
44
[6974a34]45static double MarginLeft, MarginRight, MarginTop, MarginBottom;
[55b7334]46static int fontsize, fontsize_labels;
[6974a34]47static double LineWidth;
[55b7334]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);
[3857e321]54static char *win_Init(FILE **fh_list, const char *pth, const char *outfnm,
55                      double *pscX, double *pscY, bool fCalibrate);
[08e95aa]56static int  win_Charset(void);
[55b7334]57static void win_MoveTo(long x, long y);
58static void win_DrawTo(long x, long y);
59static void win_DrawCross(long x, long y);
[abb82a4]60static void win_SetFont(int fontcode);
[54a5339]61static void win_SetColour(int colourcode);
[55b7334]62static void win_WriteString(const char *s);
63static void win_DrawCircle(long x, long y, long r);
64static void win_ShowPage(const char *szPageDetails);
65static void win_Quit(void);
66
67device printer = {
[a7f068f]68   PR_FLAG_NOFILEOUTPUT, /* |PR_FLAG_NOINI - now read fontsize from ini file */
[55b7334]69   win_Name,
70   win_Init,
[08e95aa]71   win_Charset,
[55b7334]72   win_Pre,
73   win_NewPage,
74   win_MoveTo,
75   win_DrawTo,
76   win_DrawCross,
[abb82a4]77   win_SetFont,
[ca4058d]78   win_SetColour,
[55b7334]79   win_WriteString,
80   win_DrawCircle,
81   win_ShowPage,
[9d46af2]82   NULL, /* win_Post */
[55b7334]83   win_Quit
84};
85
[d0ffc05]86static HDC pd; /* printer context */
[55b7334]87
[9e58834]88static TEXTMETRIC *tm, tm_labels, tm_default; /* font info */
[55b7334]89
[ca4058d]90static COLORREF colour_leg, colour_surface_leg, colour_cross, colour_frame;
91static COLORREF colour_text, colour_labels;
[54a5339]92static HPEN pen_leg, pen_surface_leg, pen_cross, pen_frame;
[ca4058d]93
[6974a34]94static double scX, scY;
[55b7334]95
[396b9dd]96static int cur_pass;
97
[55b7334]98static border clip;
99
100static long xpPageWidth, ypPageDepth;
101
[0658e7b]102static long x_t, y_t;
103
[396b9dd]104static int
105check_intersection(long x_p, long y_p)
106{
107#define U 1
108#define D 2
109#define L 4
[421b7d2]110#define R 8
[f7cdeb2]111   int mask_p = 0, mask_t = 0;
[f17dbe2]112   if (x_p < 0)
[396b9dd]113      mask_p = L;
[f17dbe2]114   else if (x_p > xpPageWidth)
[396b9dd]115      mask_p = R;
116
[f17dbe2]117   if (y_p < 0)
[396b9dd]118      mask_p |= D;
[f17dbe2]119   else if (y_p > ypPageDepth)
[396b9dd]120      mask_p |= U;
121
[f17dbe2]122   if (x_t < 0)
[396b9dd]123      mask_t = L;
[f17dbe2]124   else if (x_t > xpPageWidth)
[396b9dd]125      mask_t = R;
126
[f17dbe2]127   if (y_t < 0)
[396b9dd]128      mask_t |= D;
[f17dbe2]129   else if (y_t > ypPageDepth)
[396b9dd]130      mask_t |= U;
131
132#if 0
133   /* approximation to correct answer */
134   return !(mask_t & mask_p);
[69fde77]135#else
[396b9dd]136   /* One end of the line is on the page */
137   if (!mask_t || !mask_p) return 1;
138
139   /* whole line is above, left, right, or below page */
140   if (mask_t & mask_p) return 0;
141
142   if (mask_t == 0) mask_t = mask_p;
143   if (mask_t & U) {
[f17dbe2]144      double v = (double)(y_p - ypPageDepth) / (y_p - y_t);
[396b9dd]145      return v >= 0 && v <= 1;
146   }
147   if (mask_t & D) {
[f17dbe2]148      double v = (double)y_p / (y_p - y_t);
[396b9dd]149      return v >= 0 && v <= 1;
150   }
151   if (mask_t & R) {
[f17dbe2]152      double v = (double)(x_p - xpPageWidth) / (x_p - x_t);
[396b9dd]153      return v >= 0 && v <= 1;
154   }
[4c07c51]155   SVX_ASSERT(mask_t & L);
[396b9dd]156   {
[f17dbe2]157      double v = (double)x_p / (x_p - x_t);
[396b9dd]158      return v >= 0 && v <= 1;
159   }
160#endif
161#undef U
162#undef D
163#undef L
164#undef R
165}
166
[55b7334]167static const char *
168win_Name(void)
169{
170   return "Win32 Printer";
171}
172
173static void
174win_MoveTo(long x, long y)
175{
176   x_t = x - clip.x_min;
177   y_t = clip.y_max - y;
[396b9dd]178   if (cur_pass != -1) MoveToEx(pd, x_t, y_t, NULL);
[55b7334]179}
180
181static void
182win_DrawTo(long x, long y)
183{
[396b9dd]184   long x_p = x_t, y_p = y_t;
[55b7334]185   x_t = x - clip.x_min;
186   y_t = clip.y_max - y;
[396b9dd]187   if (cur_pass != -1) {
188      LineTo(pd, x_t, y_t);
189   } else {
190      if (check_intersection(x_p, y_p)) fBlankPage = fFalse;
191   }
[55b7334]192}
193
[7be0ba8]194#define POINTS_PER_INCH 72.0
195#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
[255f57b9]196#define WIN_CROSS_SIZE (int)(2 * scX / POINTS_PER_MM)
[7be0ba8]197
[55b7334]198static void
199win_DrawCross(long x, long y)
200{
[396b9dd]201   if (cur_pass != -1) {
[d3d9230]202      win_MoveTo(x - WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
203      win_DrawTo(x + WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
204      win_MoveTo(x + WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
205      win_DrawTo(x - WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
[396b9dd]206      win_MoveTo(x, y);
207   } else {
[39e4399a]208      if ((x + WIN_CROSS_SIZE > clip.x_min &&
209           x - WIN_CROSS_SIZE < clip.x_max) ||
210          (y + WIN_CROSS_SIZE > clip.y_min &&
211           y - WIN_CROSS_SIZE < clip.y_max)) {
[396b9dd]212         fBlankPage = fFalse;
213      }
214   }
[55b7334]215}
216
[b7b666d]217static HFONT font_labels, font_default, font_old;
218
[abb82a4]219static void
220win_SetFont(int fontcode)
221{
222   switch (fontcode) {
223      case PR_FONT_DEFAULT:
[b7b666d]224         SelectObject(pd, font_default);
[9e58834]225         tm = &tm_default;
[abb82a4]226         break;
227      case PR_FONT_LABELS:
[b7b666d]228         SelectObject(pd, font_labels);
[9e58834]229         tm = &tm_labels;
[abb82a4]230         break;
231      default:
232         BUG("unknown font code");
233   }
234}
235
[ca4058d]236static void
237win_SetColour(int colourcode)
238{
239   switch (colourcode) {
240      case PR_COLOUR_TEXT:
[4d3c384e]241         SetTextColor(pd, colour_text);
[ca4058d]242         break;
243      case PR_COLOUR_LABELS:
[4d3c384e]244         SetTextColor(pd, colour_labels);
[c1633e5]245         SetBkMode(pd, TRANSPARENT);
[ca4058d]246         break;
247      case PR_COLOUR_FRAME:
248         SelectObject(pd, pen_frame);
249         break;
250      case PR_COLOUR_LEG:
251         SelectObject(pd, pen_leg);
252         break;
253      case PR_COLOUR_CROSS:
254         SelectObject(pd, pen_cross);
255         break;
256      case PR_COLOUR_SURFACE_LEG:
257         SelectObject(pd, pen_surface_leg);
258         break;
259      default:
260         BUG("unknown colour code");
261   }
262}
263
[55b7334]264static void
265win_WriteString(const char *s)
266{
[396b9dd]267   if (cur_pass != -1) {
[9e58834]268      TextOut(pd, x_t, y_t - tm->tmAscent, s, strlen(s));
[396b9dd]269   } else {
[9e58834]270      if ((y_t + tm->tmDescent > 0 &&
271           y_t - tm->tmAscent < clip.y_max - clip.y_min) ||
[396b9dd]272          (x_t < clip.x_max - clip.x_min &&
[9e58834]273           x_t + strlen(s) * tm->tmAveCharWidth > 0)) {
[396b9dd]274         fBlankPage = fFalse;
275      }
276   }
[55b7334]277}
278
279static void
280win_DrawCircle(long x, long y, long r)
281{
[396b9dd]282   /* Don't need to check in first-pass - circle is only used in title box */
283   if (cur_pass != -1) {
284      x_t = x - clip.x_min;
285      y_t = clip.y_max - y;
286      Ellipse(pd, x_t - r, y_t - r, x_t + r, y_t + r);
287   }
[55b7334]288}
289
[08e95aa]290static int
291win_Charset(void)
292{
293   return CHARSET_ISO_8859_1;
294}
295
[55b7334]296static int
297win_Pre(int pagesToPrint, const char *title)
298{
[5824d76]299   PRINTDLGA psd;
300   DOCINFO info;
[6b1901c]301   int logpixelsy;
[5824d76]302
303   pagesToPrint = pagesToPrint; /* suppress compiler warning */
[9d46af2]304
[5824d76]305   memset(&psd, 0, sizeof(PRINTDLGA));
[d0ffc05]306   psd.lStructSize = 66;
[5824d76]307   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
[8bc2567]308
[5824d76]309   if (!PrintDlgA(&psd)) exit(1);
[d0ffc05]310   pd = psd.hDC;
[5824d76]311
[cdbfeff]312   logpixelsy = GetDeviceCaps(pd, LOGPIXELSY);
[6b1901c]313   font_labels = CreateFont(-MulDiv(fontsize_labels, logpixelsy, 72),
314                            0, 0, 0, FW_NORMAL, 0, 0, 0,
[abb82a4]315                            ANSI_CHARSET, OUT_DEFAULT_PRECIS,
316                            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
[9e58834]317                            FF_DONTCARE | DEFAULT_PITCH, "Arial");
[6b1901c]318   font_default = CreateFont(-MulDiv(fontsize, logpixelsy, 72),
319                             0, 0, 0, FW_NORMAL, 0, 0, 0,
320                             ANSI_CHARSET, OUT_DEFAULT_PRECIS,
321                             CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
[9e58834]322                             FF_DONTCARE | DEFAULT_PITCH, "Arial");
[c1633e5]323   /* Pen width of 0 should work, but seemed to give problems, so we'll
324    * try 1 instead... */
325   pen_leg = CreatePen(PS_SOLID, 1, colour_leg);
326   pen_surface_leg = CreatePen(PS_SOLID, 1, colour_surface_leg);
327   pen_cross = CreatePen(PS_SOLID, 1, colour_cross);
328   pen_frame = CreatePen(PS_SOLID, 1, colour_frame);
[abb82a4]329   font_old = SelectObject(pd, font_labels);
330   GetTextMetrics(pd, &tm_labels);
331   SelectObject(pd, font_default);
332   GetTextMetrics(pd, &tm_default);
[9e58834]333
[8bc2567]334   memset(&info, 0, sizeof(DOCINFO));
[d0ffc05]335   info.cbSize = sizeof(DOCINFO);
[5824d76]336   info.lpszDocName = title;
337
[d0ffc05]338   StartDoc(pd, &info);
339   return 1; /* only need 1 pass */
[55b7334]340}
341
342static void
343win_NewPage(int pg, int pass, int pagesX, int pagesY)
344{
345   int x, y;
346
[396b9dd]347   x = (pg - 1) % pagesX;
348   y = pagesY - 1 - ((pg - 1) / pagesX);
349
[f17dbe2]350   clip.x_min = (long)x * xpPageWidth;
351   clip.y_min = (long)y * ypPageDepth;
352   clip.x_max = clip.x_min + xpPageWidth; /* dm/pcl/ps had -1; */
353   clip.y_max = clip.y_min + ypPageDepth; /* dm/pcl/ps had -1; */
354
[396b9dd]355   cur_pass = pass;
[f3ed07f]356   if (pass == -1) return;
[55b7334]357
358   StartPage(pd);
[255f57b9]359   drawticks(clip, int(9 * scX / POINTS_PER_MM), x, y);
[55b7334]360}
361
362static void
363win_ShowPage(const char *szPageDetails)
364{
[d0ffc05]365   win_MoveTo((long)(6 * scX) + clip.x_min, clip.y_min - (long)(7 * scY));
366   win_WriteString(szPageDetails);
367   EndPage(pd);
[55b7334]368}
369
[ca4058d]370static COLORREF
371to_rgb(const char *var, char *val)
372{
[d0bea876]373   unsigned long rgb;
[c1633e5]374   if (!val) return RGB(0, 0, 0);
[d0bea876]375   rgb = as_colour(var, val);
[ca4058d]376   return RGB((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, rgb & 0xff);
377}
378
[9d46af2]379/* Initialise printer routines */
[3857e321]380static char *
[e1fb3cb]381win_Init(FILE **fh_list, const char *pth, const char *out_fnm,
[b7b666d]382         double *pscX, double *pscY, bool fCalibrate)
[55b7334]383{
[5824d76]384   PRINTDLGA psd;
[de035c3]385   LPDEVNAMES dn;
[abb82a4]386   static const char *vars[] = {
387      "like",
388      "font_size_labels",
[ca4058d]389      "colour_text",
390      "colour_labels",
391      "colour_frame",
392      "colour_legs",
393      "colour_crosses",
394      "colour_surface_legs",
[abb82a4]395      NULL
396   };
397   char **vals;
398
399   fCalibrate = fCalibrate; /* suppress unused argument warning */
[e1fb3cb]400   out_fnm = out_fnm;
[c34796a]401   pth = pth;
[9d46af2]402
[abb82a4]403   vals = ini_read_hier(fh_list, "win", vars);
404
[3aff368]405   fontsize_labels = as_int(vars[1], vals[1], 1, INT_MAX);
[abb82a4]406   fontsize = 10;
407
[ca4058d]408   colour_text = to_rgb(vars[2], vals[2]);
409   colour_labels = to_rgb(vars[3], vals[3]);
410   colour_frame = to_rgb(vars[4], vals[4]);
411   colour_leg = to_rgb(vars[5], vals[5]);
412   colour_cross = to_rgb(vars[6], vals[6]);
[28fd16a]413   colour_surface_leg = to_rgb(vars[7], vals[7]);
[ca4058d]414
[5824d76]415   memset(&psd, 0, sizeof(PRINTDLGA));
[d0ffc05]416   psd.lStructSize = 66;
[5824d76]417   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
418
[421b7d2]419   if (!PrintDlgA(&psd)) exit(1);
[5824d76]420
[d0ffc05]421   PaperWidth = GetDeviceCaps(psd.hDC, HORZSIZE);
422   PaperDepth = GetDeviceCaps(psd.hDC, VERTSIZE);
423   xpPageWidth = GetDeviceCaps(psd.hDC, HORZRES);
424   ypPageDepth = GetDeviceCaps(psd.hDC, VERTRES);
425   MarginLeft = MarginBottom = 0;
426   MarginRight = PaperWidth;
427   MarginTop = PaperDepth;
428   LineWidth = 0;
429   scX = *pscX = xpPageWidth / PaperWidth;
430   scY = *pscY = ypPageDepth / PaperDepth;
431   xpPageWidth--;
432   ypPageDepth = ypPageDepth - (int)(10 * *pscY);
433   DeleteDC(psd.hDC);
[5757725]434
[3857e321]435   dn = GlobalLock(psd.hDevNames);
436   if (dn) {
437      char *p = osstrdup((char *)dn + dn->wDeviceOffset);
438      GlobalUnlock(psd.hDevNames);
439      return p;
440   }
441   return NULL;
[55b7334]442}
443
444static void
445win_Quit(void)
446{
[abb82a4]447   SelectObject(pd, font_old);
448   DeleteObject(font_labels);
449   DeleteObject(font_default);
[d0ffc05]450   EndDoc(pd);
451   DeleteDC(pd);
[55b7334]452}
Note: See TracBrowser for help on using the repository browser.