home *** CD-ROM | disk | FTP | other *** search
/ Languages Around the World / LanguageWorld.iso / language / japanese / win_prog / win_jwp / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  50.2 KB  |  1,510 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4. #include <math.h>
  5.  
  6.  
  7. MEASUREINFO Measurements[] = {
  8.     { "inches",         "\"",       2,  1.00 },
  9.     { "centimeters",    " cm",      1,  2.536 },
  10.     { "millimeters",    " mm",      0,  25.36 },
  11.     { "points",         " pts",     1,  72.00 },
  12.     { "pixels",         " dots",    0,  0.00 },
  13.     { NULL,             NULL,       0,  0.00 }
  14. };
  15.  
  16. static int PrintFrom, PrintTo;
  17. static HWND printdlghwnd;
  18. static BOOL UserAbort, PrintError;
  19.  
  20.  
  21. #define ESCAPECHAR      '&'
  22.  
  23. static struct {
  24.     char escape;
  25.     int summary;
  26. } HeaderStrings[] = {
  27.     { 'L', 0 },
  28.     { 'S', 1 },
  29.     { 'A', 2 },
  30.     { 'K', 3 },
  31.     { 'C', 4 },
  32.     { 'T', -1 },
  33.     { 'D', -2 },
  34.     { 'P', -3 },
  35.     { 'F', -4 },
  36.     { '\0', 0 }
  37. };
  38.  
  39.  
  40.  
  41. MEASUREMENT FindMeasurement (char *name, MEASUREMENT measure)
  42. {
  43.     int i;
  44.  
  45.     if (measure >= 0) {
  46.         strcpy(name, Measurements[measure].name);
  47.         return (measure);
  48.     }
  49.  
  50.     for (i = 0; Measurements[i].name != NULL; i++) {
  51.         if (!stricmp(name, Measurements[i].name)) return ((MEASUREMENT) i);
  52.     }
  53.     return (-1);
  54. }
  55.  
  56.  
  57.  
  58. HDC GetPrinterDC (BOOL IcOnly, char *name)
  59. {
  60.     char buffer[MAXLINELEN];
  61.     char *device, *driver, *output;
  62.  
  63.     /* Opens the printer device */
  64.  
  65.     GetProfileString ("windows", "device", ",,,", buffer, MAXLINELEN);
  66.  
  67.     if ((device = strtok(buffer, ",")) &&
  68.         (driver = strtok(NULL, ", ")) &&
  69.         (output = strtok(NULL, ", "))) {
  70.             if (name != NULL) sprintf(name, "%s on %s", device, output);
  71.  
  72.             if (IcOnly) {
  73.                 return (CreateIC(driver, device, output, NULL));
  74.             } else {
  75.                 return (CreateDC(driver, device, output, NULL));
  76.             }
  77.     }
  78.  
  79.     if (name != NULL) strcpy(name, "(None)");
  80.     return (NULL);
  81. }
  82.  
  83.  
  84.  
  85. BOOL SetupPrinter (BOOL ReloadDriver)
  86. {
  87.     HDC hdc;
  88.     POINT printdots;
  89.     double temp;
  90.     double nr_points[2], dpp[2];
  91.     char buffer[MAXLINELEN];
  92.  
  93.     if (ReloadDriver) {
  94.         hdc = GetPrinterDC(TRUE, buffer);
  95.         if (hdc == NULL) {
  96.             ErrorMessage(global.hwnd, "There are no printer currently connected.\n\n");
  97.             hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
  98.             global.printer = "DISPLAY";
  99.         } else if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_BITBLT)) {
  100.             ErrorMessage(global.hwnd, "The current printer is incapable of printing bitmaps.\n\n"
  101.                                          "You will not be able to print.");
  102.             DeleteDC(hdc);
  103.             hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
  104.             global.printer = "DISPLAY";
  105.         } else {
  106.             global.printer = DupString(buffer);
  107.         }
  108.  
  109.         global.resolution.x = GetDeviceCaps(hdc, LOGPIXELSX);
  110.         global.resolution.y = GetDeviceCaps(hdc, LOGPIXELSY);
  111.  
  112.         global.printable.x = GetDeviceCaps(hdc, HORZRES);
  113.         global.printable.y = GetDeviceCaps(hdc, VERTRES);
  114.  
  115.         Measurements[M_PIXELS].conversion = global.resolution.y;
  116.  
  117.         global.paper[0] = (double) GetDeviceCaps(hdc, HORZSIZE) / Measurements[M_MM].conversion;
  118.         global.paper[1] = (double) GetDeviceCaps(hdc, VERTSIZE) / Measurements[M_MM].conversion;
  119.     }
  120.  
  121.     dpp[0] = (double) global.resolution.x / 72.0;
  122.     dpp[1] = (double) global.resolution.y / 72.0;
  123.  
  124.  
  125.     /* We compensate for the printer's aspect ratio.  If necessary, */
  126.     /* stretching or compressing the horizontal axis.               */
  127.  
  128.     printdots.y = PRINTFONT->height * global.printscale;
  129.     temp = (double) PRINTFONT->width * (double) global.printscale;
  130.     temp = temp * (double) global.resolution.x / (double) global.resolution.y;
  131.     printdots.x = temp;
  132.  
  133.     /* This is the number of points per printing font */
  134.  
  135.     nr_points[0] = (double) printdots.x / dpp[0];
  136.     nr_points[1] = (double) printdots.y / dpp[1];
  137.  
  138.     global.dispscale = (double) BASEFONT->height / (double) PRINTFONT->height;
  139.  
  140.     if (ReloadDriver) DeleteDC(hdc);
  141.     return (TRUE);
  142. }
  143.  
  144.  
  145.  
  146. void InitPrinting (void)
  147. {
  148.     SetupPrinter(TRUE);
  149. }
  150.  
  151.  
  152. void ChangePrinterOrFonts (void)
  153. {
  154.     FILEOPTIONS *f;
  155.     HCURSOR hcursor;
  156.     HFONT hfont;
  157.     HDC hdc;
  158.     HWND FocusHwnd;
  159.  
  160.     hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  161.     ShowCursor(TRUE);
  162.  
  163.     FocusHwnd = SetFocus(NULL);
  164.  
  165.     SetupPrinter(TRUE);
  166.  
  167.     hdc = GetPrinterDC(TRUE, NULL);
  168.     if (hdc == NULL) hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  169.  
  170.     hfont = SelectAsciiFont(hdc, DefAsciiFont.facename, DefAsciiFont.size, NULL);
  171.  
  172.     if (DefAsciiFont.hfont != NULL) DeleteObject(DefAsciiFont.hfont);
  173.  
  174.     DefAsciiFont.hfont =
  175.         FindMatchingScreenFont(hfont, global.dispscale / global.printscale,
  176.                                &(DefAsciiFont.textmetric));
  177.     DeleteObject(hfont);
  178.     DeleteDC(hdc);
  179.  
  180.     FontCharWidth (0, -1);      /* Reload width tables */
  181.  
  182.     global.leading = (int) ((double) PRINTFONT->leading * global.dispscale);
  183.     if (global.leading % 2 != 0) global.leading++;
  184.  
  185.     global.spacing = (int) ((double) PRINTFONT->spacing * global.dispscale);
  186.     if (global.spacing % 2 != 0) global.spacing++;
  187.  
  188.     for (f = fileoptions; f != NULL; f = f->next) {
  189.         f->leading = global.leading;
  190.         f->spacing = global.spacing;
  191.         f->basefont = BASEFONT;
  192.         f->linelen = CalcLineLength(f);
  193.         ReformatFile(f);
  194.  
  195.         if (!FindCaret(f, TRUE)) MoveIntoWindow(f);
  196.         InvalidateRect(f->hwnd, NULL, TRUE);
  197.         if(RULER(f).hwnd != NULL) InvalidateRect(RULER(f).hwnd, NULL, TRUE);
  198.     }
  199.  
  200.     ShowCursor(FALSE);
  201.     SetCursor(hcursor);
  202.  
  203.     if (FocusHwnd != NULL) SetFocus(FocusHwnd);
  204. }
  205.  
  206.  
  207.  
  208. static void FormatTimeDate (char *timep, char *datep)
  209. {
  210.     time_t t;
  211.     struct tm *tmp;
  212.     static int idate, itime;
  213.     static char sdate[3], stime[3], sam[6], spm[6];
  214.     static BOOL Filled = FALSE;
  215.  
  216.     if (!Filled || (timep == NULL && datep == NULL)) {
  217.         idate = GetProfileInt("intl", "iDate", 0);
  218.         itime = GetProfileInt("intl", "iTime", 0);
  219.  
  220.         GetProfileString("intl", "sDate", "/", sdate, 2);
  221.         GetProfileString("intl", "sTime", ":", stime, 2);
  222.         GetProfileString("intl", "s1159", "AM", sam, 5);
  223.         GetProfileString("intl", "s2359", "PM", spm, 5);
  224.         Filled = TRUE;
  225.     }
  226.  
  227.     time(&t);
  228.     tmp = localtime(&t);
  229.  
  230.     if (datep != NULL) {
  231.         sprintf(datep, "%d%s%02d%s%02d",
  232.                 idate == 1 ? tmp->tm_mday : idate == 2 ? (tmp->tm_year % 100) : (tmp->tm_mon + 1), sdate,
  233.                 idate == 1 ? (tmp->tm_mon + 1) : idate == 2 ? (tmp->tm_mon + 1) : tmp->tm_mday, sdate,
  234.                 idate == 1 ? (tmp->tm_year % 100) : idate == 2 ? tmp->tm_mday : (tmp->tm_year % 100));
  235.     }
  236.     if (timep != NULL) {
  237.         if (itime == 1) {
  238.             sprintf(timep, "%02d%s%02d", tmp->tm_hour, stime, tmp->tm_min);
  239.         } else {
  240.             sprintf(timep, "%d%s%02d %s",
  241.                     (tmp->tm_hour % 12) ? (tmp->tm_hour % 12) : 12, stime,
  242.                     tmp->tm_min, (tmp->tm_hour / 12) ? spm : sam);
  243.         }
  244.     }
  245. }
  246.  
  247.  
  248.  
  249. static void BuildHeaderString (FILEOPTIONS *f, KANJI far *kp, int PageNum, KANJI far *out)
  250. {
  251.     int i, j, k;
  252.     char cch;
  253.     KANJI kch;
  254.     KANJI far *kp1;
  255.  
  256.     j = 0;
  257.  
  258.     for (i = 0; kp[i]; i++) {
  259.         kch = kp[i];
  260.         if (ISKANJI(kch)) cch = LOBYTE(TranslateJAscii(kch, TRUE));
  261.         else cch = LOBYTE(kch);
  262.         if ('a' <= cch && cch <= 'z') cch -= 32;
  263.  
  264.         if (cch == ESCAPECHAR) {
  265.             i++;
  266.             if (ISKANJI(kp[i])) cch = LOBYTE(TranslateJAscii(kp[i], TRUE));
  267.             else cch = LOBYTE(kp[i]);
  268.             if ('a' <= cch && cch <= 'z') cch -= 32;
  269.  
  270.             for (k = 0; HeaderStrings[k].escape; k++) {
  271.                 if (HeaderStrings[k].escape == cch) break;
  272.             }
  273.  
  274.             if (!HeaderStrings[k].escape) {
  275.                 out[j++] = kch; out[j++] = kp[i]; break;
  276.             } else if (HeaderStrings[k].summary >= 0) {
  277.                 kp1 = f->summary[HeaderStrings[k].summary];
  278.                 if (kp1 != NULL) for (k = 0; kp1[k]; k++) out[j++] = kp1[k];
  279.             } else {
  280.                 char buffer[50];
  281.  
  282.                 switch (HeaderStrings[k].summary) {
  283.                     case -1:    /* Time */
  284.                         FormatTimeDate(buffer, NULL);
  285.                         break;
  286.  
  287.                     case -2:    /* Date */
  288.                         FormatTimeDate(NULL, buffer);
  289.                         break;
  290.  
  291.                     case -3:    /* Page */
  292.                         sprintf(buffer, "%d", PageNum);
  293.                         break;
  294.  
  295.                     case -4:    /* File name */
  296.                         for (k = strlen(f->filename) - 1; k >= 0; k--) {
  297.                             if (strchr(":/\\", f->filename[k]) != NULL) break;
  298.                         }
  299.                         strcpy(buffer, f->filename + k + 1);
  300.                         break;
  301.                 }
  302.  
  303.                 for (k = 0; buffer[k]; k++) out[j++] = buffer[k];
  304.             }
  305.             continue;
  306.         }
  307.  
  308.         out[j++] = kch;
  309.     }
  310.  
  311.     out[j] = 0;
  312. }
  313.  
  314.  
  315.  
  316. static BOOL MoveToNextLine (PARAGRAPH far **pp, ONELINE far **lp, int Direction)
  317. {
  318.     if (Direction > 0) {
  319.         *lp = (*lp)->next;
  320.         if (*lp == NULL) {
  321.             *pp = (*pp)->next;
  322.             if (*pp == NULL) return (FALSE);
  323.             *lp = (*pp)->lines;
  324.         }
  325.         return (TRUE);
  326.     } else if (Direction < 0) {
  327.         *lp = (*lp)->prev;
  328.         if (*lp == NULL) {
  329.             *pp = (*pp)->prev;
  330.             if (*pp == NULL) return (FALSE);
  331.             *lp = (*pp)->lastline;
  332.         }
  333.         return (TRUE);
  334.     } else {
  335.         return (TRUE);
  336.     }
  337. }
  338.  
  339.  
  340.  
  341. // PageNum <> 0: Find the page
  342. // PageNum == 0 and dPage <> 0: Jump pages, starting from pos
  343. // PageNum == 0 and dPage == 0: Find the page containing pos
  344.  
  345. static int FindPage (FILEOPTIONS *f, int PageLength, int PageNum, int dPage, POSITION *pos)
  346. {
  347.     int i, y;
  348.     int LineHeight;
  349.     PARAGRAPH far *pp;
  350.     ONELINE far *lp;
  351.  
  352.  
  353.     LineHeight = (int) floor((double) (PRINTFONT->height + PRINTFONT->spacing) * global.printscale + 0.5);
  354.     POSOF(*pos) = 0;
  355.  
  356.     /* Find absolute page */
  357.  
  358.     if (PageNum > 0) {
  359.         i = 1;
  360.         y = 0;
  361.  
  362.         for (pp = f->paragraph, lp = pp->lines; ; ) {
  363.             if (y + LineHeight >= PageLength) {
  364.                 i++;
  365.                 y = 0;
  366.             }
  367.             if (i >= PageNum) {
  368.                 PARAOF(*pos) = pp;
  369.                 LINEOF(*pos) = lp;
  370.                 return (i);
  371.             }
  372.             y += LineHeight;
  373.             if (!MoveToNextLine (&pp, &lp, +1)) break;
  374.         }
  375.         return (0);
  376.     }
  377.  
  378.     /* Skip pages */
  379.  
  380.     if (dPage != 0) {
  381.         i = y = 0;
  382.         if (dPage > 0) {
  383.             for (pp = PARAOF(*pos), lp = LINEOF(*pos); ; ) {
  384.                 if (y + LineHeight >= PageLength) {
  385.                     i++;
  386.                     y = 0;
  387.                 }
  388.                 if (i >= dPage) {
  389.                     PARAOF(*pos) = pp;
  390.                     LINEOF(*pos) = lp;
  391.                     return (i);
  392.                 }
  393.                 y += LineHeight;
  394.                 if (!MoveToNextLine (&pp, &lp, +1)) break;
  395.             }
  396.         } else {
  397.             for (pp = PARAOF(*pos), lp = LINEOF(*pos); ; ) {
  398.                 if (y + LineHeight >= PageLength) {
  399.                     i--;
  400.                     y = 0;
  401.                 }
  402.                 if (i <= dPage) {
  403.                     PARAOF(*pos) = pp;
  404.                     LINEOF(*pos) = lp;
  405.                     return (i);
  406.                 }
  407.                 y += LineHeight;
  408.                 if (!MoveToNextLine (&pp, &lp, -1)) break;
  409.             }
  410.         }
  411.         return (0);
  412.     }
  413.  
  414.     /* Find page number */
  415.  
  416.     i = 1;
  417.     y = 0;
  418.  
  419.     for (pp = f->paragraph, lp = pp->lines; ; ) {
  420.         if (y + LineHeight >= PageLength) {
  421.             i++;
  422.             y = 0;
  423.         }
  424.         if (pp == PARAOF(*pos) && lp == LINEOF(*pos)) return (i);
  425.         y += LineHeight;
  426.         if (!MoveToNextLine (&pp, &lp, +1)) break;
  427.     }
  428.  
  429.     return (0);
  430. }
  431.  
  432.  
  433.  
  434. BOOL FAR PASCAL PrintAbortProc (HDC hdc, short nCode)
  435. {
  436.     MSG msg;
  437.  
  438.     while (!UserAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  439.         if (printdlghwnd == NULL || !IsDialogMessage(printdlghwnd, &msg)) {
  440.             TranslateMessage(&msg);
  441.             DispatchMessage(&msg);
  442.         }
  443.     }
  444.     return (!UserAbort);
  445. }
  446.  
  447.  
  448.  
  449. BOOL FAR PASCAL PrintDlgProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  450. {
  451.     switch (message) {
  452.         case WM_INITDIALOG:
  453.             CenterDialogBox(hwnd);
  454.             return (TRUE);
  455.  
  456.         case WM_COMMAND:
  457.             switch (wParam) {
  458.                 case IDCANCEL:
  459.                     UserAbort = TRUE;
  460.                     return (TRUE);
  461.             }
  462.             break;
  463.     }
  464.  
  465.     return (FALSE);
  466. }
  467.  
  468.  
  469.  
  470. static void PrintErrorMessage (int error, char *action)
  471. {
  472.     switch (error) {
  473.         case SP_ERROR:      ErrorMessage(global.hwnd, "Cannot %s!", action); break;
  474.         case SP_APPABORT:
  475.         case SP_USERABORT:  break;
  476.         case SP_OUTOFDISK:  ErrorMessage(global.hwnd, "Out of Disk Space!  Cannot continue printing."); break;
  477.         case SP_OUTOFMEMORY:ErrorMessage(global.hwnd, "Out of Memory!  Cannot continue printing."); break;
  478.     }
  479. }
  480.  
  481.  
  482.  
  483. #define LEFTMG           (MarginDots[0])
  484. #define RIGHTMG          (MarginDots[1])
  485. #define TOPMG            (MarginDots[2])
  486. #define BOTTOMMG         (MarginDots[3])
  487.  
  488. #define CHECKABORT()     if (!abortprinting(hdc, 0)) break;
  489.  
  490. void PrintFile (FILEOPTIONS *f)
  491. {
  492.     int i, j, k, h, n, r;
  493.     int x, y, num, temp, size, ScreenLen;
  494.     int PrintWidth, PrintHeight;
  495.     int PrintLeading, PrintSpacing;
  496.     int PrintCell, PageNum, NrPages;
  497.     int WhiteSpaces[2], MarginDots[4];
  498.     int errorcode;
  499.     BOOL ChangeView = FALSE;
  500.     JUSTIFICATION Jmode;
  501.     double ratio;
  502.     UNIT far *up;
  503.     HDC hdc, hdcmem;
  504.     FARPROC abortprinting;
  505.     HFONT hfont;
  506.     HCURSOR hcursor;
  507.     RECT rect;
  508.     PARAGRAPH far *pp;
  509.     ONELINE far *lp;
  510.     POSITION StartPos, NextPos;
  511.     HBITMAP hbitmap;
  512.     TEXTMETRIC tm;
  513.     BYTE far *cbufp;
  514.     char buffer[MAXLINELEN];
  515.     int Widths[256];
  516.  
  517.  
  518.     hdc = GetPrinterDC(FALSE, buffer);
  519.     if (hdc == NULL) {
  520.         ErrorMessage(global.hwnd, "Cannot get printer driver!");
  521.         return;
  522.     }
  523.     if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_BITBLT)) {
  524.         DeleteDC(hdc);
  525.         ErrorMessage(global.hwnd, "Cannot print to the current printer!");
  526.         return;
  527.     }
  528.  
  529.  
  530.     /* Initialize stuff */
  531.  
  532.     SetBkMode(hdc, TRANSPARENT);
  533.  
  534.     ratio = (double) global.resolution.x / (double) global.resolution.y;
  535.     PrintHeight = floor((double) PRINTFONT->height * global.printscale + 0.5);
  536.     PrintWidth = floor((double) PrintHeight * ratio + 0.5);
  537.     PrintLeading = floor((double) PRINTFONT->leading * global.printscale * ratio + 0.5);
  538.     PrintSpacing = floor((double) PRINTFONT->spacing * global.printscale + 0.5);
  539.     PrintCell = PrintWidth + PrintLeading;
  540.  
  541.     hbitmap = CreateBitmap(PRINTFONT->width, PRINTFONT->height, 1, 1, NULL);
  542.     hdcmem = CreateCompatibleDC(hdc);
  543.     SetMapMode(hdcmem, GetMapMode(hdc));
  544.  
  545.     /* Load the ASCII font */
  546.  
  547.     hfont = SelectAsciiFont(hdc, DefAsciiFont.facename, DefAsciiFont.size, &tm);
  548.     SelectObject(hdc, hfont);
  549.     GetCharWidth(hdc, 0, 255, Widths);
  550.  
  551.     WhiteSpaces[0] = ((global.paper[0] * global.resolution.x) - global.printable.x) / 2;
  552.     WhiteSpaces[1] = ((global.paper[1] * global.resolution.y) - global.printable.y) / 2;
  553.  
  554.     MarginDots[0] = (f->pagesetup.margins[0] * global.resolution.x) - WhiteSpaces[0];
  555.     MarginDots[1] = (f->pagesetup.margins[1] * global.resolution.x) - WhiteSpaces[0];
  556.     MarginDots[2] = (f->pagesetup.margins[2] * global.resolution.y) - WhiteSpaces[1];
  557.     MarginDots[3] = (f->pagesetup.margins[3] * global.resolution.y) - WhiteSpaces[1];
  558.  
  559.  
  560.     /* Set the abort procedures */
  561.  
  562.     abortprinting = MakeProcInstance(PrintAbortProc, hInstance);
  563.  
  564.     EnableWindow(global.hwnd, FALSE);
  565.     EnableWindow(global.clienthwnd, FALSE);
  566.  
  567.     UserAbort = PrintError = FALSE;
  568.     printdlghwnd = CreateDialog(hInstance, "Printing", f->parent, PrintDlgProc);
  569.  
  570.     hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  571.     ShowCursor(TRUE);
  572.  
  573.  
  574.     /* Reformat? */
  575.  
  576.     if (global.draftview) {
  577.         SetDlgItemText(printdlghwnd, 4201, "Reformatting File...");
  578.         abortprinting(hdc, 0);
  579.         global.draftview = FALSE;
  580.         ReformatFile(f);
  581.         ChangeView = TRUE;
  582.     }
  583.  
  584.  
  585.     /* Pagenate */
  586.  
  587.     SetDlgItemText(printdlghwnd, 4201, "Repagenating File...");
  588.     abortprinting(hdc, 0);
  589.  
  590.     if (PrintFrom < 0 && PrintTo < 0) {     /* Current Page */
  591.         StartPos = f->current;
  592.         PageNum = FindPage(f, global.printable.y - TOPMG - BOTTOMMG, 0, 0, &StartPos);
  593.         i = FindPage(f, global.printable.y - TOPMG - BOTTOMMG, PageNum, 0, &StartPos);
  594.         if (i == 0) {
  595.             ErrorMessage(global.hwnd, "There %s less than %d page%s in this document!",
  596.                             (PrintFrom > 1) ? "are" : "is", PrintFrom, (PrintFrom > 1) ? "s" : "");
  597.             goto CleanUp;
  598.         }
  599.         NrPages = 1;
  600.     } else {
  601.         if (PrintFrom <= 0) {
  602.             PARAOF(StartPos) = f->paragraph;
  603.             LINEOF(StartPos) = f->paragraph->lines;
  604.             PageNum = 1;
  605.         } else {
  606.             i = FindPage(f, global.printable.y - TOPMG - BOTTOMMG, PrintFrom, 0, &StartPos);
  607.             if (i == 0) {
  608.                 ErrorMessage(global.hwnd, "There %s less than %d page%s in this document!",
  609.                                 (PrintFrom > 1) ? "are" : "is", PrintFrom, (PrintFrom > 1) ? "s" : "");
  610.                 goto CleanUp;
  611.             }
  612.             PageNum = PrintFrom;
  613.         }
  614.  
  615.         if (PrintTo <= 0) {
  616.             NrPages = -1;
  617.         } else if (PrintFrom <= 0) {
  618.             NrPages = PrintTo;
  619.         } else {
  620.             NrPages = PrintTo - PrintFrom + 1;
  621.             if (NrPages <= 0) NrPages = 1;
  622.         }
  623.     }
  624.  
  625.     NextPos = StartPos;
  626.     i = FindPage(f, global.printable.y - TOPMG - BOTTOMMG, 0, +1, &NextPos);
  627.     if (i == 0) PARAOF(NextPos) = NULL;
  628.  
  629.  
  630.     if (!(f->filename[0])) {
  631.         strcpy(buffer, "Printing ");
  632.         GetWindowText(f->parent, buffer + strlen(buffer), MAXLINELEN);
  633.         sprintf(buffer + strlen(buffer), "\n\n%s", global.printer);
  634.     } else {
  635.         sprintf(buffer, "Printing %s\n\n%s", f->filename, global.printer);
  636.     }
  637.  
  638.     SetDlgItemText(printdlghwnd, 4201, buffer);
  639.  
  640.     SetDlgItemText(printdlghwnd, 4202, "Initializing printer...");
  641.     abortprinting(hdc, 0);
  642.  
  643.     sprintf(buffer, "%s ", PROGNAME);
  644.     GetWindowText(f->parent, buffer + strlen(buffer), MAXLINELEN);
  645.  
  646.     errorcode = Escape(hdc, STARTDOC, strlen(buffer), buffer, NULL);
  647.     if (errorcode <= 0) {
  648.         PrintErrorMessage(errorcode, "initialize printer");
  649.         goto CleanUp;
  650.     }
  651.  
  652.     Escape(hdc, SETABORTPROC, 0, (LPSTR) abortprinting, NULL);
  653.  
  654.  
  655.     /* Do the true printing */
  656.  
  657. Loop:
  658.  
  659.     sprintf(buffer, "Currently Printing Page %d...", PageNum);
  660.     SetDlgItemText(printdlghwnd, 4202, buffer);
  661.     abortprinting(hdc, 0);
  662.  
  663.     /* Process each band */
  664.  
  665.     errorcode = Escape(hdc, NEXTBAND, 0, NULL, (LPSTR) &rect);
  666.     if (errorcode < 0) {
  667.         PrintError = TRUE;
  668.         PrintErrorMessage(errorcode, "continue printing");
  669.     }
  670.  
  671.     SelectObject(hdc, hfont);
  672.     SetBkMode(hdc, TRANSPARENT);
  673.  
  674.     while (!PrintError && !UserAbort && !IsRectEmpty(&rect)) {
  675.         /* Header / Footer ? */
  676.  
  677.         CHECKABORT();
  678.  
  679.         for (h = 0; h < 2; h++) {
  680.             KANJI kbuffer[MAXLINELEN];
  681.  
  682.             if (f->nofirstpage && PageNum <= 1) break;
  683.  
  684.             switch (h) {
  685.                 default: continue;
  686.  
  687.                 case 0: y = TOPMG - PrintHeight - PrintSpacing;
  688.                         if (rect.top >= y) continue;
  689.                         y -= PrintHeight;
  690.                         if (f->lrheader) {
  691.                             num = (PageNum % 2 == 0) ? 1 : 0;
  692.                         } else {
  693.                             num = 0;
  694.                         }
  695.                         break;
  696.  
  697.                 case 1: y = global.printable.y - BOTTOMMG + PrintHeight + PrintSpacing;
  698.                         if (rect.bottom <= y) continue;
  699.                         if (f->lrheader) {
  700.                             num = (PageNum % 2 == 0) ? 2 : 3;
  701.                         } else {
  702.                             num = 2;
  703.                         }
  704.                         break;
  705.             }
  706.  
  707.             for (i = 0; i < NRHEADERS; i++) {
  708.                 if (f->header[num][i] == NULL) continue;
  709.                 CHECKABORT();
  710.  
  711.                 BuildHeaderString (f, f->header[num][i], PageNum, kbuffer);
  712.  
  713.                 n = kanjilen(kbuffer);
  714.                 if (n <= 0) continue;
  715.  
  716.                 for (j = k = 0; kbuffer[j]; j++) {
  717.                     CHECKABORT();
  718.                     if (ISKANJI(kbuffer[j])) {
  719.                         k += PrintCell;
  720.                     } else {
  721.                         k += Widths[kbuffer[j]];
  722.                         if (buffer[j+1] && ISKANJI(kbuffer[j+1])) k += PrintLeading;
  723.                     }
  724.                 }
  725.  
  726.                 switch (i) {
  727.                     default:
  728.                     case 0: x = LEFTMG; break;
  729.                     case 1: x = (f->linelen * PrintCell - PrintLeading - k) / 2 + LEFTMG; break;
  730.                     case 2: x = f->linelen * PrintCell - PrintLeading - k + LEFTMG; break;
  731.                 }
  732.  
  733.                 for (j = 0; kbuffer[j]; j++) {
  734.                     CHECKABORT();
  735.                     if (ISKANJI(kbuffer[j])) {
  736.                         r = Jis2Index(kbuffer[j], PRINTFONT->holes);
  737.                         if (r < 0) r = Jis2Index(BADKANJI, PRINTFONT->holes);
  738.                         r = GetKanjiBitmap(PRINTFONT, r, &cbufp);
  739.                         SetBitmapBits(hbitmap, (DWORD) r, cbufp);
  740.                         SelectObject(hdcmem, hbitmap);
  741.                         StretchBlt(hdc, x, y, PrintWidth, PrintHeight, hdcmem, 0, 0, PRINTFONT->width, PRINTFONT->height, SRCCOPY);
  742.                         x += PrintCell;
  743.                     } else {
  744.                         TextOut(hdc, x, y + PrintHeight - tm.tmHeight, kbuffer + j, 1);
  745.                         x += Widths[kbuffer[j]];
  746.                         if (kbuffer[j+1] && ISKANJI(kbuffer[j+1])) x += PrintLeading;
  747.                     }
  748.                 }
  749.             }
  750.         }
  751.  
  752.         if (UserAbort) break;
  753.  
  754.         pp = PARAOF(StartPos);
  755.         lp = LINEOF(StartPos);
  756.         y = TOPMG;
  757.  
  758.         for (;;) {
  759.             if (pp == PARAOF(NextPos) && lp == LINEOF(NextPos)) break;
  760.  
  761.             if (y > rect.bottom) break;
  762.  
  763.             CHECKABORT();
  764.  
  765.             if (y + PrintHeight + PrintSpacing < rect.top) {
  766.                 if (!MoveToNextLine(&pp, &lp, +1)) break;
  767.                 y += PrintHeight + PrintSpacing;
  768.                 continue;
  769.             }
  770.  
  771.             x = ((lp == pp->lines) ? pp->firstindent : pp->leftindent) * PrintCell + LEFTMG;
  772.             ScreenLen = ((lp == pp->lines) ? pp->firstindent : pp->leftindent) * BASEWIDTH(f);
  773.  
  774.             up = pp->text + lp->position;
  775.  
  776.             for (i = 0; i < lp->length; i++) {
  777.                 if (x > rect.right) break;
  778.  
  779.                 CHECKABORT();
  780.  
  781.                 if (ISKANJI(up->kanji) && x + PrintCell < rect.left) {
  782.                     x += PrintCell;
  783.                     ScreenLen += BASEWIDTH(f);
  784.                     up++;
  785.                     continue;
  786.                 }
  787.  
  788.                 if (up->kanji == 0x2121 /* Blank */) {
  789.                     x += PrintCell;
  790.                     ScreenLen += BASEWIDTH(f);
  791.                     up++;
  792.                 } else if (ISKANJI(up->kanji)) {
  793.                     r = Jis2Index(up->kanji, PRINTFONT->holes);
  794.                     if (r < 0) r = Jis2Index(BADKANJI, PRINTFONT->holes);
  795.                     r = GetKanjiBitmap(PRINTFONT, r, &cbufp);
  796.                     SetBitmapBits(hbitmap, (DWORD) r, cbufp);
  797.                     SelectObject(hdcmem, hbitmap);
  798.                     StretchBlt(hdc, x, y, PrintWidth, PrintHeight, hdcmem, 0, 0, PRINTFONT->width, PRINTFONT->height, SRCCOPY);
  799.                     x += PrintCell;
  800.                     ScreenLen += BASEWIDTH(f);
  801.                     up++;
  802.                 } else {
  803.                     /* Get the text string */
  804.  
  805.                     SetTextAlign(hdc, TA_LEFT | TA_BOTTOM | TA_NOUPDATECP);
  806.                     SetTextJustification(hdc, 0, 0);
  807.  
  808.                     ratio = (double) global.resolution.y / (double) global.resolution.x;
  809.                     ratio *= global.dispscale / global.printscale;
  810.  
  811.                     for (j = k = 0; i < lp->length; i++, j++, up++) {
  812.                         if (ISKANJI(up->kanji)) break;
  813.                         if (up->kanji == '\t') break;
  814.  
  815.                         buffer[j] = LOBYTE(up->kanji);
  816.  
  817.                         //temp = FontCharWidth(up->kanji, 1) - FontDisplayError(up->kanji, pp, lp);
  818.                         temp = FontCharWidth(up->kanji, 1) - FontDisplayError(up->kanji, i);
  819.  
  820.                         ScreenLen += temp;
  821.                         k += Widths[up->kanji];
  822.                     }
  823.                     buffer[j] = 0;
  824.  
  825.                     Jmode = global.shortjust;
  826.  
  827.                     if (i >= lp->length || i <= j) {    /* Open ended */
  828.                         Jmode = global.longjust;
  829.                         if (Jmode == J_RIGHT || Jmode == J_CENTER) Jmode = J_JUSTIFY;
  830.                         if (lp->next == NULL && Jmode == J_JUSTIFY) Jmode = J_LEFT;
  831.  
  832.                         if (buffer[0] && i >= lp->length) {
  833.                             for (temp = strlen(buffer) - 1; temp >= 0 && buffer[temp] == ' '; temp--);
  834.                             buffer[++temp] = '\0';
  835.                             k -= (j - temp) * Widths[' '];
  836.                         }
  837.                     } else if (up->kanji != '\t') {     /* In between */
  838.                         Jmode = J_LEFT;
  839.                     }
  840.  
  841.                     k = LOWORD(GetTextExtent(hdc, buffer, strlen(buffer)));
  842.  
  843.                     /* Now, get the amount of tab */
  844.  
  845.                     if (Jmode != J_LEFT) {
  846.                         if (i >= lp->length) {
  847.                             ScreenLen = (f->linelen - pp->rightindent) * BASEWIDTH(f) - global.leading;
  848.                             r = (f->linelen - pp->rightindent) * PrintCell - PrintLeading - x - k + LEFTMG;
  849.                         } else {
  850.                             ScreenLen += BASEWIDTH(f) - (ScreenLen % BASEWIDTH(f));
  851.                             r = (ScreenLen / BASEWIDTH(f)) * PrintCell - PrintLeading - x - k + LEFTMG;
  852.                         }
  853.                     } else if (up->kanji == '\t') {
  854.                         ScreenLen += BASEWIDTH(f) - (ScreenLen % BASEWIDTH(f));
  855.                         r = (ScreenLen / BASEWIDTH(f)) * PrintCell - PrintLeading - x - k + LEFTMG;
  856.                     } else {
  857.                         r = 0;
  858.                     }
  859.  
  860.                     if (r < 0) Jmode = J_JUSTIFY;
  861.  
  862.                     switch (Jmode) {
  863.                         LeftText:
  864.                         case J_LEFT:
  865.                             CHECKABORT();
  866.                             TextOut(hdc, x, y + PrintHeight, buffer, strlen(buffer));
  867.                             x += k + r;
  868.                             break;
  869.  
  870.                         RightText:
  871.                         case J_RIGHT:
  872.                             CHECKABORT();
  873.                             TextOut(hdc, x + r, y + PrintHeight, buffer, strlen(buffer));
  874.                             x += k + r;
  875.                             break;
  876.  
  877.                         CenterText:
  878.                         case J_CENTER:
  879.                             TextOut(hdc, x + r/2, y + PrintHeight, buffer, strlen(buffer));
  880.                             x += k + r;
  881.                             break;
  882.  
  883.                         case J_JUSTIFY:
  884.                             /* Count the nuber of spaces */
  885.                             for (temp = n = 0; buffer[temp]; temp++)
  886.                                 if (buffer[temp] == ' ') n++;
  887.  
  888.                             if (n > 0) {
  889.                                 if (r > Widths[' ']) {
  890.                                     if (buffer[0] != ' ' && i > j) {
  891.                                         x += Widths[' ']/2;
  892.                                         r -= Widths[' ']/2;
  893.                                     }
  894.                                     if (i < lp->length) {
  895.                                         SetTextJustification(hdc, r - Widths[' ']/2, n);
  896.                                     } else {
  897.                                         SetTextJustification(hdc, r, n);
  898.                                     }
  899.                                 } else {
  900.                                     SetTextJustification(hdc, r, n);
  901.                                 }
  902.                                 CHECKABORT();
  903.                                 TextOut(hdc, x, y + PrintHeight, buffer, strlen(buffer));
  904.                                 x += k + r;
  905.                             } else if (i >= lp->length) {
  906.                                 if (i <= j) goto LeftText; else goto RightText;
  907.                             } else {
  908.                                 if (i <= j) goto LeftText; else goto CenterText;
  909.                             }
  910.                             break;
  911.                     }
  912.  
  913.                     if (i >= lp->length) break;
  914.                     if (ISKANJI(up->kanji)) {
  915.                         i--;
  916.                         x += PrintLeading;
  917.                         ScreenLen += global.leading;
  918.                     }
  919.                     if (up->kanji == '\t') {
  920.                         x += PrintLeading;
  921.                         up++;
  922.                     }
  923.                 }
  924.             }
  925.  
  926.             y += PrintHeight + PrintSpacing;
  927.  
  928.             CHECKABORT();
  929.  
  930.             if (!MoveToNextLine(&pp, &lp, +1)) break;
  931.         }
  932.  
  933.         errorcode = Escape(hdc, NEXTBAND, 0, NULL, (LPSTR) &rect);
  934.         if (errorcode < 0) {
  935.             PrintError = TRUE;
  936.             PrintErrorMessage(errorcode, "continue printing");
  937.             break;
  938.         }
  939.     }
  940.  
  941.     /* Another page? */
  942.  
  943.     if (!UserAbort && !PrintError && (NrPages < 0 || NrPages > 1) && PARAOF(NextPos) != NULL) {
  944.         if (NrPages > 0) NrPages--;
  945.         StartPos = NextPos;
  946.         i = FindPage(f, global.printable.y - TOPMG - BOTTOMMG, 0, +1, &NextPos);
  947.         if (i != 0) PageNum++; else PARAOF(NextPos) = NULL;
  948.         goto Loop;
  949.     }
  950.  
  951.     /* Finishes the accounting */
  952.  
  953.     if (!PrintError) {
  954.         if (UserAbort) {
  955.             SetDlgItemText(printdlghwnd, 4202, "Printing Aborted!");
  956.             abortprinting(hdc, 0);
  957.             Escape(hdc, ABORTDOC, 0, NULL, NULL);
  958.         } else {
  959.             SetDlgItemText(printdlghwnd, 4202, "Printing Completed.");
  960.             abortprinting(hdc, 0);
  961.             Escape(hdc, ENDDOC, 0, NULL, NULL);
  962.         }
  963.     }
  964.  
  965.  
  966. CleanUp:
  967.  
  968.     /* Clean up... */
  969.  
  970.     if (ChangeView) {
  971.         SetDlgItemText(printdlghwnd, 4201, "Reformatting File...");
  972.         abortprinting(hdc, 0);
  973.         global.draftview = TRUE;
  974.         ReformatFile(f);
  975.     }
  976.  
  977.     EnableWindow(global.hwnd, TRUE);
  978.     EnableWindow(global.clienthwnd, TRUE);
  979.  
  980.     DestroyWindow(printdlghwnd);
  981.     printdlghwnd = NULL;
  982.  
  983.     FreeProcInstance(abortprinting);
  984.  
  985.     ShowCursor(FALSE);
  986.     SetCursor(hcursor);
  987.  
  988.     if (hdcmem != NULL) DeleteDC(hdcmem);
  989.     if (hdc != NULL) DeleteDC(hdc);
  990.     if (hbitmap != NULL) DeleteObject(hbitmap);
  991.     if (hfont != NULL) DeleteObject(hfont);
  992. }
  993.  
  994.  
  995.  
  996. BOOL FAR PASCAL PrinterSetupProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  997. {
  998.     static char *Devices = NULL;
  999.     static char *CurDevice = NULL;
  1000.     static HANDLE library = NULL;
  1001.  
  1002.     switch (message) {
  1003.         case WM_INITDIALOG: {
  1004.             int i, j;
  1005.             char printer[MAXLINELEN];
  1006.             char text[MAXLINELEN];
  1007.             char *driver, *output;
  1008.  
  1009.             if (Devices != NULL) FreeMem(Devices);
  1010.             Devices = MemAlloc(MAXLINELEN);
  1011.             CurDevice = NULL;
  1012.  
  1013.             EnableWindow(GetDlgItem(hwnd, 4201), FALSE);
  1014.  
  1015.             GetProfileString("devices", NULL, "", Devices, MAXLINELEN);
  1016.             for (i = 0, j = 0;; j++) {
  1017.                 if (!Devices[i]) break;
  1018.                 GetProfileString("devices", Devices+ i, "", printer, MAXLINELEN);
  1019.                 driver = strtok(printer, ", ");
  1020.                 output = strtok(NULL, ", ");
  1021.                 sprintf(text, "%s on %s", Devices + i, output);
  1022.                 SendDlgItemMessage(hwnd, 4211, LB_ADDSTRING, 0, (LONG) ((char far *) text));
  1023.                 if (!stricmp(text, global.printer)) {
  1024.                     CurDevice = Devices + i;
  1025.                     SendDlgItemMessage(hwnd, 4211, LB_SETCURSEL, j, 0L);
  1026.                     EnableWindow(GetDlgItem(hwnd, 4201), TRUE);
  1027.                 }
  1028.                 i += strlen(Devices + i) + 1;
  1029.             }
  1030.  
  1031.             CenterDialogBox(hwnd);
  1032.  
  1033.             SetFocus(GetDlgItem(hwnd, 4211));
  1034.  
  1035.             return (TRUE);
  1036.         }
  1037.  
  1038.         case WM_COMMAND:
  1039.             switch (wParam) {
  1040.                 case 4211:      /* List box */
  1041.                     switch (HIWORD(lParam)) {
  1042.                         case LBN_SELCHANGE: {
  1043.                             int i, j;
  1044.  
  1045.                             i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  1046.                             if (i == LB_ERR) {
  1047.                                 MessageBeep(0);
  1048.                                 return (TRUE);
  1049.                             }
  1050.  
  1051.                             /* Find the device */
  1052.  
  1053.                             CurDevice = Devices;
  1054.                             for (j = 0; j < i; j++) {
  1055.                                 if (!CurDevice[0]) {
  1056.                                     CurDevice = Devices;
  1057.                                     MessageBeep(0);
  1058.                                     return (TRUE);
  1059.                                 }
  1060.                                 CurDevice += strlen(CurDevice) + 1;
  1061.                             }
  1062.                             EnableWindow(GetDlgItem(hwnd, 4201), TRUE);
  1063.                             return (TRUE);
  1064.                         }
  1065.  
  1066.                         case LBN_DBLCLK:
  1067.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1068.                             return (TRUE);
  1069.                     }
  1070.                     return (TRUE);
  1071.  
  1072.                 case 4201: {    /* Options */
  1073.                     char driver[MAXLINELEN];
  1074.                     char driverfile[MAXLINELEN];
  1075.                     char *output;
  1076.                     FARPROC devicemode;
  1077.  
  1078.                     GetProfileString("devices", CurDevice, "", driver, MAXLINELEN);
  1079.                     (void) strtok(driver, ", ");
  1080.                     output = strtok(NULL, ", ");
  1081.                     sprintf(driverfile, "%s.DRV", driver);
  1082.  
  1083.                     if (library >= 32) FreeLibrary(library);
  1084.                     library = LoadLibrary(driverfile);
  1085.                     if (library >= 32) {
  1086.                         devicemode = GetProcAddress(library, "DEVICEMODE");
  1087.                         devicemode(hwnd, library, (LPSTR) driver, (LPSTR) output);
  1088.                     }
  1089.                     return (TRUE);
  1090.                 }
  1091.  
  1092.                 case IDOK: {
  1093.                     char buffer[MAXLINELEN];
  1094.  
  1095.                     if (CurDevice != NULL) {
  1096.                         sprintf(buffer, "%s,", CurDevice);
  1097.                         GetProfileString("devices", CurDevice, "", buffer + strlen(buffer), MAXLINELEN);
  1098.                         WriteProfileString("windows", "device", buffer);
  1099.                         FreeMem(CurDevice);
  1100.                         ChangePrinterOrFonts();
  1101.                     }
  1102.                     CurDevice = NULL;
  1103.                     EndDialog(hwnd, TRUE);
  1104.                     return (TRUE);
  1105.                 }
  1106.  
  1107.                 case IDCANCEL:
  1108.                     if (CurDevice != NULL) FreeMem(CurDevice);
  1109.                     CurDevice = NULL;
  1110.                     EndDialog(hwnd, FALSE);
  1111.                     return (TRUE);
  1112.             }
  1113.             break;
  1114.  
  1115.         case WM_DESTROY:
  1116.             if (library >= 32) FreeLibrary(library);
  1117.             library = NULL;
  1118.             return (TRUE);
  1119.     }
  1120.  
  1121.     return (FALSE);
  1122. }
  1123.  
  1124.  
  1125.  
  1126. BOOL FAR PASCAL PageSetupProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1127. {
  1128.     static MEASUREMENT OldMeasure;
  1129.  
  1130.     switch (message) {
  1131.         case WM_INITDIALOG: {
  1132.             int i;
  1133.             MEASUREINFO *mp;
  1134.             char buffer[MAXLINELEN];
  1135.             char format[30];
  1136.  
  1137.             SetDlgItemText(hwnd, 4201, global.printer);
  1138.  
  1139.             /* Page orientation */
  1140.  
  1141.             SendDlgItemMessage(hwnd, 4211, CB_ADDSTRING, 0, (LONG) "Portrait");
  1142.             SendDlgItemMessage(hwnd, 4211, CB_ADDSTRING, 0, (LONG) "Landscape");
  1143.             SendDlgItemMessage(hwnd, 4211, CB_SETCURSEL, global.pagesetup.landscape ? 1 : 0, 0L);
  1144.  
  1145.             /* Measurements */
  1146.  
  1147.             for (i = 0; Measurements[i].name != NULL; i++) {
  1148.                 SendDlgItemMessage(hwnd, 4212, CB_ADDSTRING, 0, (LONG) Measurements[i].name);
  1149.             }
  1150.             mp = Measurements + global.measure;
  1151.             SendDlgItemMessage(hwnd, 4212, CB_SETCURSEL, global.measure, 0L);
  1152.  
  1153.             /* Line length */
  1154.  
  1155.             if (global.active != NULL) {
  1156.                 SetDlgItemInt(hwnd, 4213, global.active->linelen, TRUE);
  1157.             } else {
  1158.                 SetDlgItemInt(hwnd, 4213, CalcLineLength(global.active), TRUE);
  1159.             }
  1160.             /* Margins */
  1161.  
  1162.             sprintf(format, "%%%d.%dlf%%s", mp->decimal + 2, mp->decimal);
  1163.  
  1164.             if (global.active != NULL) {
  1165.                 for (i = 0; i < 4; i++) {
  1166.                     sprintf(buffer, format, global.active->pagesetup.margins[i] * mp->conversion, "");
  1167.                     SetDlgItemText(hwnd, 4221 + i, buffer);
  1168.                 }
  1169.             } else {
  1170.                 for (i = 0; i < 4; i++) {
  1171.                     sprintf(buffer, format, global.pagesetup.margins[i] * mp->conversion, "");
  1172.                     SetDlgItemText(hwnd, 4221 + i, buffer);
  1173.                 }
  1174.             }
  1175.  
  1176.             for (i = 0; i < 4; i++) {
  1177.                 sprintf(buffer, format, global.pagesetup.margins[i] * mp->conversion, mp->symbol);
  1178.                 SetDlgItemText(hwnd, 4231 + i, buffer);
  1179.             }
  1180.  
  1181.             OldMeasure = global.measure;
  1182.  
  1183.             CenterDialogBox(hwnd);
  1184.             return (TRUE);
  1185.         }
  1186.  
  1187.         case WM_COMMAND: {
  1188.             int i, j;
  1189.             double num, temp, minmargins[4];
  1190.             int NeedReformat;   /* 0 = no, 1 = file, 2 = all */
  1191.             MEASUREINFO *mp, *mp1;
  1192.             FILEOPTIONS *f;
  1193.             char buffer[MAXLINELEN];
  1194.             char format[30];
  1195.  
  1196.             minmargins[0] = minmargins[1] = ((global.paper[0] * global.resolution.x) - global.printable.x) / 2;
  1197.             minmargins[2] = minmargins[3] = ((global.paper[1] * global.resolution.y) - global.printable.y) / 2;
  1198.  
  1199.             switch (wParam) {
  1200.                 case 4241:      /* Make default */
  1201.                     if (YesNo(hwnd, "Make these margin settings the default?") == IDYES) {
  1202.                         mp = Measurements + OldMeasure;
  1203.                         sprintf(format, "%%%d.%dlf%%s", mp->decimal + 2, mp->decimal);
  1204.  
  1205.                         for (i = 0; i < 4; i++) {
  1206.                             GetDlgItemText(hwnd, 4221 + i, buffer, MAXLINELEN);
  1207.                             num = atof(buffer);
  1208.  
  1209.                             switch (i) {
  1210.                                 case 0:
  1211.                                 case 1: temp = (double) minmargins[i] / (double) global.resolution.x;
  1212.                                         break;
  1213.                                 case 2:
  1214.                                 case 3: temp = (double) minmargins[i] / (double) global.resolution.x;
  1215.                                         break;
  1216.                             }
  1217.  
  1218.                             if (num < temp) num = temp;
  1219.  
  1220.                             sprintf(buffer, format, num, mp->symbol);
  1221.                             SetDlgItemText(hwnd, 4231 + i, buffer);
  1222.                         }
  1223.                     }
  1224.                     return (TRUE);
  1225.  
  1226.                 case 4212:      /* Measurement */
  1227.                     j = SendDlgItemMessage(hwnd, 4212, CB_GETCURSEL, 0, 0L);
  1228.                     if (j == CB_ERR) return (TRUE);
  1229.                     if (j == OldMeasure) return (TRUE);
  1230.  
  1231.                     mp = Measurements + OldMeasure;
  1232.                     mp1 = Measurements + j;
  1233.                     sprintf(format, "%%%d.%dlf%%s", mp1->decimal + 2, mp1->decimal);
  1234.  
  1235.                     for (i = 0; i < 4; i++) {
  1236.                         GetDlgItemText(hwnd, 4221 + i, buffer, MAXLINELEN);
  1237.                         num = atof(buffer);
  1238.  
  1239.                         switch (i) {
  1240.                             case 0:
  1241.                             case 1: temp = (double) minmargins[i] / (double) global.resolution.x;
  1242.                                     break;
  1243.                             case 2:
  1244.                             case 3: temp = (double) minmargins[i] / (double) global.resolution.x;
  1245.                                     break;
  1246.                         }
  1247.  
  1248.                         if (num < temp) num = temp;
  1249.  
  1250.                         sprintf(buffer, format, num * mp1->conversion / mp->conversion, "");
  1251.                         SetDlgItemText(hwnd, 4221 + i, buffer);
  1252.                     }
  1253.                     for (i = 0; i < 4; i++) {
  1254.                         GetDlgItemText(hwnd, 4231 + i, buffer, MAXLINELEN);
  1255.                         num = atof(buffer);
  1256.  
  1257.                         switch (i) {
  1258.                             case 0:
  1259.                             case 1: temp = (double) minmargins[i] / (double) global.resolution.x;
  1260.                                     break;
  1261.                             case 2:
  1262.                             case 3: temp = (double) minmargins[i] / (double) global.resolution.x;
  1263.                                     break;
  1264.                         }
  1265.  
  1266.                         if (num < temp) num = temp;
  1267.  
  1268.                         sprintf(buffer, format, num * mp1->conversion / mp->conversion, mp1->symbol);
  1269.                         SetDlgItemText(hwnd, 4231 + i, buffer);
  1270.                     }
  1271.  
  1272.                     OldMeasure = j;
  1273.  
  1274.                     num = (double) (PRINTFONT->width + PRINTFONT->leading) * global.printscale;
  1275.                     num *= (double) global.resolution.x / (double) global.resolution.y;
  1276.                     SetDlgItemInt(hwnd, 4213, (int) floor((double) global.printable.x / num), TRUE);
  1277.                     return (TRUE);
  1278.  
  1279.                 case IDOK:
  1280.                     NeedReformat = 0;
  1281.  
  1282.                     /* Orientation */
  1283.  
  1284.                     i = SendDlgItemMessage(hwnd, 4211, CB_GETCURSEL, 0, 0L);
  1285.                     if (i != CB_ERR && i != global.active->pagesetup.landscape) {
  1286.                         OptionsChanged = TRUE;
  1287.                         global.active->pagesetup.landscape = i;
  1288.                         NeedReformat = 2;
  1289.                     }
  1290.  
  1291.                     /* Measurement */
  1292.  
  1293.                     i = SendDlgItemMessage(hwnd, 4212, CB_GETCURSEL, 0, 0L);
  1294.                     if (i != CB_ERR && i != global.measure) {
  1295.                         OptionsChanged = TRUE;
  1296.                         global.measure = i;
  1297.                     }
  1298.  
  1299.                     /* Margins */
  1300.  
  1301.                     if (global.active != NULL) {
  1302.                         for (i = 0; i < 4; i++) {
  1303.                             GetDlgItemText(hwnd, 4221 + i, buffer, MAXLINELEN);
  1304.                             num = atof(buffer);
  1305.  
  1306.                             switch (i) {
  1307.                                 case 0:
  1308.                                 case 1: temp = (double) minmargins[i] / (double) global.resolution.x;
  1309.                                         break;
  1310.                                 case 2:
  1311.                                 case 3: temp = (double) minmargins[i] / (double) global.resolution.x;
  1312.                                         break;
  1313.                             }
  1314.  
  1315.                             if (num < temp) num = temp;
  1316.                             num /= Measurements[global.measure].conversion;
  1317.  
  1318.                             if (fabs(num - global.active->pagesetup.margins[i]) > 0.01) {
  1319.                                 global.active->pagesetup.margins[i] = num;
  1320.                                 NeedReformat = 1;
  1321.                                 OptionsChanged = TRUE;
  1322.                             }
  1323.                         }
  1324.                     }
  1325.  
  1326.                     for (i = 0; i < 4; i++) {
  1327.                         GetDlgItemText(hwnd, 4231 + i, buffer, MAXLINELEN);
  1328.                         num = atof(buffer);
  1329.  
  1330.                         switch (i) {
  1331.                             case 0:
  1332.                             case 1: temp = (double) minmargins[i] / (double) global.resolution.x;
  1333.                                     break;
  1334.                             case 2:
  1335.                             case 3: temp = (double) minmargins[i] / (double) global.resolution.x;
  1336.                                     break;
  1337.                         }
  1338.  
  1339.                         if (num < temp) num = temp;
  1340.                         num /= Measurements[global.measure].conversion;
  1341.  
  1342.                         if (fabs(num - global.pagesetup.margins[i]) > 0.01) {
  1343.                             global.pagesetup.margins[i] = num;
  1344.                             OptionsChanged = TRUE;
  1345.                         }
  1346.                     }
  1347.  
  1348.                     switch (NeedReformat) {
  1349.                         case 0: break;
  1350.  
  1351.                         case 1: if (global.active != NULL) {
  1352.                                     global.active->linelen = CalcLineLength(global.active);
  1353.                                     ReformatFile(global.active);
  1354.                                     InvalidateRect(global.active->hwnd, NULL, TRUE);
  1355.                                 }
  1356.                                 break;
  1357.  
  1358.                         case 2: for (f = fileoptions; f != NULL; f = f->next) {
  1359.                                     f->linelen = CalcLineLength(f);
  1360.                                     ReformatFile(f);
  1361.                                     InvalidateRect(f->hwnd, NULL, TRUE);
  1362.                                 }
  1363.                                 break;
  1364.                     }
  1365.  
  1366.                     EndDialog(hwnd, NeedReformat);
  1367.                     return (TRUE);
  1368.  
  1369.                 case IDCANCEL:
  1370.                     EndDialog(hwnd, 0);
  1371.                     return (TRUE);
  1372.             }
  1373.             break;
  1374.         }
  1375.         break;
  1376.     }
  1377.     return (FALSE);
  1378. }
  1379.  
  1380.  
  1381.  
  1382. BOOL FAR PASCAL PrintProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1383. {
  1384.     switch (message) {
  1385.         case WM_INITDIALOG: {
  1386.             char buffer[MAXLINELEN];
  1387.             char format[30];
  1388.             MEASUREINFO *mp;
  1389.  
  1390.             SetDlgItemText(hwnd, 4211, global.printer);
  1391.             SetDlgItemText(hwnd, 4212, global.active->pagesetup.landscape ? "Landscape" : "Portrait");
  1392.  
  1393.             mp = Measurements + global.measure;
  1394.             sprintf(format, "%%%d.%dlf%s x %%%d.%dlf%s",
  1395.                         mp->decimal + 2, mp->decimal, mp->symbol,
  1396.                         mp->decimal + 2, mp->decimal, mp->symbol);
  1397.             sprintf(buffer, format, global.paper[0] * mp->conversion, global.paper[1] * mp->conversion);
  1398.             SetDlgItemText(hwnd, 4213, buffer);
  1399.  
  1400.             SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, TRUE, 0L);
  1401.             SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1402.             SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1403.  
  1404.             EnableWindow(GetDlgItem(hwnd, 4231), FALSE);
  1405.             EnableWindow(GetDlgItem(hwnd, 4232), FALSE);
  1406.  
  1407.             SendDlgItemMessage(hwnd, 4241, CB_ADDSTRING, 0, (LONG) "Left");
  1408.             SendDlgItemMessage(hwnd, 4241, CB_ADDSTRING, 0, (LONG) "Right");
  1409.             SendDlgItemMessage(hwnd, 4241, CB_ADDSTRING, 0, (LONG) "Center");
  1410.             SendDlgItemMessage(hwnd, 4241, CB_ADDSTRING, 0, (LONG) "Justify");
  1411.             switch (global.shortjust) {
  1412.                 case J_LEFT:    SendDlgItemMessage(hwnd, 4241, CB_SETCURSEL, 0, 0L); break;
  1413.                 case J_RIGHT:   SendDlgItemMessage(hwnd, 4241, CB_SETCURSEL, 1, 0L); break;
  1414.                 default:
  1415.                 case J_CENTER:  SendDlgItemMessage(hwnd, 4241, CB_SETCURSEL, 2, 0L); break;
  1416.                 case J_JUSTIFY: SendDlgItemMessage(hwnd, 4241, CB_SETCURSEL, 3, 0L); break;
  1417.             }
  1418.  
  1419.             SendDlgItemMessage(hwnd, 4242, CB_ADDSTRING, 0, (LONG) "Left");
  1420.             SendDlgItemMessage(hwnd, 4242, CB_ADDSTRING, 0, (LONG) "Justify");
  1421.             switch (global.longjust) {
  1422.                 case J_LEFT:    SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 0, 0L); break;
  1423.                 default:
  1424.                 case J_JUSTIFY: SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 1, 0L); break;
  1425.             }
  1426.  
  1427.             CenterDialogBox(hwnd);
  1428.             return (TRUE);
  1429.         }
  1430.  
  1431.         case WM_COMMAND:
  1432.             switch (wParam) {
  1433.                 case 4221:      /* All */
  1434.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, TRUE, 0L);
  1435.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1436.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1437.                     EnableWindow(GetDlgItem(hwnd, 4231), FALSE);
  1438.                     EnableWindow(GetDlgItem(hwnd, 4232), FALSE);
  1439.                     return (TRUE);
  1440.  
  1441.                 case 4222:      /* Current */
  1442.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, FALSE, 0L);
  1443.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, TRUE, 0L);
  1444.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1445.                     EnableWindow(GetDlgItem(hwnd, 4231), FALSE);
  1446.                     EnableWindow(GetDlgItem(hwnd, 4232), FALSE);
  1447.                     return (TRUE);
  1448.  
  1449.                 case 4223:      /* Selected */
  1450.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, FALSE, 0L);
  1451.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1452.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, TRUE, 0L);
  1453.                     EnableWindow(GetDlgItem(hwnd, 4231), TRUE);
  1454.                     EnableWindow(GetDlgItem(hwnd, 4232), TRUE);
  1455.                     return (TRUE);
  1456.  
  1457.                 case 4201:      /* Page setup */
  1458.                     DialogBox(hInstance, "PageSetup", hwnd, PageSetupProc);
  1459.                     return (TRUE);
  1460.  
  1461.                 case 4202:      /* Printer setup */
  1462.                     DialogBox(hInstance, "PrinterSetup", hwnd, PrinterSetupProc);
  1463.                     return (TRUE);
  1464.  
  1465.                 case IDOK: {
  1466.                     int i;
  1467.                     char buffer[MAXLINELEN];
  1468.  
  1469.                     i = SendDlgItemMessage(hwnd, 4241, CB_GETCURSEL, 0, 0L);
  1470.                     if (i != CB_ERR) {
  1471.                         switch (i) {
  1472.                             case 0: global.shortjust = J_LEFT; break;
  1473.                             case 1: global.shortjust = J_RIGHT; break;
  1474.                             case 2: global.shortjust = J_CENTER; break;
  1475.                             case 3: global.shortjust = J_JUSTIFY; break;
  1476.                         }
  1477.                     }
  1478.                     i = SendDlgItemMessage(hwnd, 4242, CB_GETCURSEL, 0, 0L);
  1479.                     if (i != CB_ERR) {
  1480.                         switch (i) {
  1481.                             case 0: global.longjust = J_LEFT; break;
  1482.                             case 1: global.longjust = J_JUSTIFY; break;
  1483.                         }
  1484.                     }
  1485.  
  1486.                     if (IsDlgButtonChecked(hwnd, 4221)) {
  1487.                         PrintFrom = PrintTo = 0;
  1488.                     } else if (IsDlgButtonChecked(hwnd, 4222)) {
  1489.                         PrintFrom = PrintTo = -1;
  1490.                     } else {
  1491.                         GetDlgItemText(hwnd, 4231, buffer, MAXLINELEN);
  1492.                         PrintFrom = atoi(buffer);
  1493.                         if (PrintFrom < 0) PrintFrom = 0;
  1494.                         GetDlgItemText(hwnd, 4232, buffer, MAXLINELEN);
  1495.                         PrintTo = atoi(buffer);
  1496.                         if (PrintTo < PrintFrom) PrintTo = PrintFrom;
  1497.                     }
  1498.                     EndDialog(hwnd, TRUE);
  1499.                     return (TRUE);
  1500.                 }
  1501.  
  1502.                 case IDCANCEL:
  1503.                     EndDialog(hwnd, FALSE);
  1504.                     return (TRUE);
  1505.             }
  1506.             break;
  1507.     }
  1508.     return (FALSE);
  1509. }
  1510.