// $Header: /MeWin/Src/PRINT.S 18    2/01/95 10:29a Johnp $
Macro_File Print;

#include windows.sh
#include dialog.sh
#include commdlg.sh
#include mewhelp.sh
#include mewlib.sh
#include mew_btn.sh
#include metools.sh
#include print.sh
// #include msglog.sh

// Setup Dialog Control IDs
#define _P_HELP           1038
#define _P_DEFBTN         1058
#define _P_SELPRINTER     1136
#define _P_PRNPRINTER     1088

#define _PS_LMARGIN       2001
#define _PS_RMARGIN       2002
#define _PS_TMARGIN       2003
#define _PS_BMARGIN       2004
#define _PS_HEADER        2010
#define _PS_FOOTER        2011
#define _PS_HEADERON      2012
#define _PS_FOOTERON      2013
#define _PS_HEADEROFFSET  2014
#define _PS_FOOTEROFFSET  2015
#define _PS_LINENUMBERING 2016

#define _PS_FONTS         2020
#define _PS_PAGESETUP     2021

#define _PO_FF            2050
#define _PO_WRAP          2051

#define _PN_OPTIONS       3010


// db files and pages
#define DBFILE      "MECONFIG"
#define PRINTPAGE   "PRINT.CFG"

#define PRINT_HELPLINK        "Print"
#define PRINTSETUP_HELPLINK   "Print Setup"
#define PAGESETUP_HELPLINK    "Page Setup"
#define PRINTOPT_HELPLINK     "Print Options"
#define PRINTFONT_HELPLINK    ""

struct TPrintWork
{
  int     window;
  WORD    dc;

  ASCIIZ  header  [128];
  ASCIIZ  footer  [128];
  int     line;
  int     page;

  WORD    nCharWidth;
  WORD    nCharHeight;
  WORD    nCharsPerLine;
  WORD    nLinesPerPage;
}

// Temporary place holder for template names for Commdlg Hook
struct TPrintRec
{
  ASCIIZ  PrintTemplate [32];
  ASCIIZ  SetupTemplate [32];
}

void TransHF (struct TPrintDlg pds, struct TPrintOptions Popt, struct TPrintWork PWork)
{
  int cmx, rmx;
  int jx, jy;
  str tline, tstr, stime[2];

  int tRefresh = Refresh;
  Refresh = False;

  int tWin = cur_window;
  Switch_Window (PWork.Window);

  GetProfileString ("intl", "sTime", ":", sTime,2);

  // Setup Current time string
  str time_str[12]  = Str_Del(TIME, 6, 3);
  if (xpos (sTime, time_str, 1) == 2)
    time_str = Str_Del(TIME, 5, 3);

  // Get Time/Date Integer for current file
  first_file (file_name);
  jy = last_file_time;

  // Setup File time string
  jx = jy & 0xffff;
  str ftime_str[12] = str_del (Make_Time_Str (jx >> 11,(jx >> 5) & 0x3f, 0), 6, 3);
  if (xpos (sTime, ftime_str, 1) == 2)
    ftime_str = Str_Del(TIME, 5, 3);

  jx = jy >> 16;
  str fdate_str[12] = make_date_str ((jx >> 9) + 1980, (jx >> 5) & 0x0f, jx & 0x1f);

  if ( ((POpt.Flags & POPTF_HEADERON) != 0) && ( POpt.Header != "" ) )
  {
    tline = TranslateCmdLine (Popt.Header, file_name);
    Call XlatePrint;
    PWork.Header = tline;
  }

  if ( ((POpt.Flags & POPTF_FOOTERON) != 0) && (POpt.Footer != "") )
  {
    tline = TranslateCmdLine (pOpt.Footer, file_name);
    Call XlatePrint;
    PWork.Footer = tline;
  }


  Switch_Window (tWin);
  Refresh = tRefresh;
  Return ();

XlatePrint:
  // Put page number
  while ( jx = xpos('<PAGE>', Caps (tline), 1) )
	{
    tline = Str_Del(tline, jx, 6);
    tline = Str_Ins(str (PWork.page), tline, jx);
	}
  // Put Current time
  while ( jx = xpos('<CTIME>', Caps (tline), 1) )
	{
    tline = Str_Del(tline, jx, 7);
    tline = Str_Ins(time_str, tline, jx);
  }
  // Put Current Date
  while ( jx = xpos('<CDATE>', Caps (tline), 1) )
	{
    tline = Str_Del(tline, jx, 7);
    tline = Str_Ins(DATE, tline, jx);
  }
  // Put Last file save time
  while ( jx = xpos('<FTIME>', Caps (tline), 1) )
	{
    tline = Str_Del(tline, jx, 7);
    tline = Str_Ins(ftime_str, tline, jx);
  }
  // Put Last file save date
  while ( jx = xpos('<FDATE>', Caps (tline), 1) )
	{
    tline = Str_Del(tline, jx, 7);
    tline = Str_Ins(fdate_str, tline, jx);
  }

  // These need to come after all other translations.
  cmx = 0;
  rmx = 0;
  while ( jx = xpos('<LM>', Caps (tline), 1) )
  {
    tline = Str_Del(tline, jx, 4);
  }
  while ( jx = xpos('<CM>', Caps (tline), 1) )
  {
    tline = Str_Del(tline, jx, 4);
    cmx = jx;
  }
  while ( jx = xpos('<RM>', Caps (tline), 1) )
  {
    tline = Str_Del(tline, jx, 4);
    rmx = jx;
  }

  if ( !(cmx | rmx) )
    ret;
  if ( rmx && (cmx >= rmx)  )
    cmx = 0;

  tstr  = '';
  pad_str (tstr, PWork.nCharsPerLine, " ");


  if (cmx != 0)
  {
    tstr = Str_Ins (Copy (tline, 1, cmx-1), tstr, 1);
    if ( rmx != 0) {
      jy = rmx - cmx;
    }
    else {
      jy = (Length (tline) - cmx) + 1;
    }
    jx = (PWork.nCharsPerLine / 2) - (jy / 2);
    if ( jx < cmx )
      jx = cmx;
    tstr = Str_Ins (Copy(tline, cmx, jy), tstr, jx);
    cmx = jx + jy;
  }

  if ( rmx != 0)
  {
    if ( cmx == 0) {
      tstr = Str_Ins (Copy (tline, 1, rmx-1), tstr, 1);
    }
    jy = (Length (tline) - rmx) + 1;
    jx = PWork.nCharsPerLine - jy;

    if ( jx < cmx )
      jx = cmx;

    tstr = Str_Ins (Copy(tline, rmx, jy), tstr, jx);
  }
  tline = shorten_str (tstr);
  ret;
}

void SavePrintCfg ()
{

  int tinsert = insert_mode;
  insert_mode = TRUE;

  int twin = cur_window;

  struct TPrintOptions pOpt;
  str tstr [1024] = POPtionsStruct;
  str_to_struct (pOpt, tstr);

  if( LocateDbPage( DBFILE, PRINTPAGE, TRUE ) )
  {
    down;
    goto_col (1);
    while ( !at_eof || XPos ('|12', get_line, 1))
    {
      del_line;
    }
    cr;
    up;
    Text ("FLAGS="
              + "/USEFF="     + str ((POpt.flags & POPTF_USEFF) != 0)
              + "/WRAP="      + str ((POpt.flags & POPTF_WRAP) != 0)
              + "/HEADERON="  + str ((POpt.flags & POPTF_HEADERON) != 0)
              + "/FOOTERON="  + str ((POpt.flags & POPTF_FOOTERON) != 0)
              + "/NUM="       + str (POpt.LineNumbering));
    cr;
    Text ("MARGINS="
              + "/RM=" + str (POpt.RMargin)
              + "/LM=" + str (POpt.LMargin)
              + "/TM=" + str (POpt.TMargin)
              + "/BM=" + str (POpt.BMargin));
    cr;
    Text ("HEADER=" + POpt.Header);
    cr;
    Text ("FOOTER=" + POpt.Footer);
    cr;
    Text ("OFFSETS="
                + "/HO=" + str (POpt.HeaderOffset)
                + "/FO=" + str (POpt.FooterOffset));
    cr;
    Text ("FONT="
                + "/NAME=" + Popt.FontName
                + "/SIZE=" + str (Popt.FontHeight)
                + "/POINT=" + str (POpt.FontPointSize)
                + "/SET="  + str (POpt.CharSet));
  }
  Switch_window (twin);
  insert_mode = tInsert;
}

void SetPrintCfg ()
{

  str dbline [2048];
  str tstr   [2048];
  struct TPrintOptions POpt;

  int twin = cur_window;
  if( LocateDbPage( DBFILE, PRINTPAGE, FALSE) )
  {
    down;
    goto_col (1);
    while ( !at_eof || (cur_char == '|12') )
    {
      dbline = get_line;

      tstr = parse_str ("FLAGS=", dbline);
      if ( tstr != "" )
      {
        Popt.Flags = 0;
        if ( Parse_int ("/USEFF=", tstr) )
          POpt.flags |= POPTF_USEFF;
        if ( Parse_int ("/WRAP=", tstr) )
          POpt.flags |= POPTF_WRAP;
        if ( Parse_int ("/HEADERON=", tstr) )
          POpt.flags |= POPTF_HEADERON;
        if ( Parse_int ("/FOOTERON=", tstr) )
          POpt.flags |= POPTF_FOOTERON;

        Popt.LineNumbering = Parse_Int ("/NUM=", tstr);
        goto loopit;
      }
      tstr = parse_str ("MARGINS=", dbline);
      if ( tstr != "" )
      {
        POpt.RMargin = Parse_Int ("/RM=" , tstr);
        POpt.LMargin = Parse_Int ("/LM=" , tstr);
        POpt.TMargin = Parse_Int ("/TM=" , tstr);
        POpt.BMargin = Parse_Int ("/BM=" , tstr);
        goto loopit;
      }
      tstr = Parse_Str ("HEADER=", dbline);
      if ( tstr != "" )
      {
        POpt.Header = tstr;
        goto loopit;
      }
      tstr = Parse_Str ("FOOTER=", dbline);
      if ( tstr != "" )
      {
        POpt.Footer = tstr;
        goto loopit;
      }
      tstr = Parse_Str ("OFFSETS=", dbline);
      if ( tstr != "" )
      {
        POpt.HeaderOffset = Parse_Int ("/HO=", tstr);
        POpt.FooterOffset = Parse_Int ("/FO=", tstr);
        goto loopit;
      }
      tstr = Parse_Str ("FONT=", dbline);
      if ( tstr != "" )
      {
        POpt.FontName       = Parse_Str ("/NAME=", tstr);
        POpt.FontHeight     = Parse_Int ("/SIZE=", tstr);
        Popt.FontPointSize  = Parse_Int ("/POINT=", tstr);
        POpt.CharSet        = Parse_Int ("/SET=", tstr);
        goto loopit;
      }
loopit:
      down;
    }
    struct_to_str (tstr, POpt);
    POptionsStruct = tstr;
  }

  Switch_window (twin);
}

int GetPrinterDC (str szInDevice)
{
  int jx;
  str szPrinter[80], szDevice[80], szDriver[20], szOutput[30];


  if ( szInDevice == "")
  {
    GetProfileString ("windows", "device", "", szPrinter, 80);
    jx = XPos (',', szPrinter, 1);
    if ( jx )
    {
      szDevice = Copy (szPrinter, 1, jx-1);
      jx++;
    }
    else
    {
      return (0);
    }
  }
  else
  {
    GetProfileString ("devices", szInDevice, "", szPrinter, 128);
    szDevice = szInDevice;
    jx = 1;
  }

  int jy = XPos (',', szPrinter, jx);
  if (jy )
  {
    str szDriver = Copy (szPrinter, jx, jy-jx);
    jy++;
    str szOutput = Copy (szPrinter, jy, svl(szPrinter) - jy);

    return (CreateDC (szDriver, szDevice, szOutput, 0));
  }
  return (0);
}

struct TS
{
  ASCIIZ style [100];
}
int PrintFontProc ( int dlg, int message, int wparam, int lparam, struct TChooseFont frec ) No_Break
{

  int result = 0;
  switch ( message )
  {
    case WM_ACTIVATE :
    {
      if ( wparam )
      {
        HelpLink_String = PRINTFONT_HELPLINK;
      }
      else
      {
        HelpLink_String = "";
      }
      break;
    }

    case WM_COMMAND :
    {
      switch ( wparam )
      {
        case _P_HELP :
          MewHelp_Context();
					result = 1;
					break;
      }
    }
  }
  return (result);
}
int SelectPFont (int dlg, int dc)
{
  struct TLogFont     PrintFont;
  struct TChooseFont  ChooseRec;
  struct TS           t;

  struct TPrintOptions pOpt;
  str tstr [1024] = POPtionsStruct;
  str_to_struct (pOpt, tstr);


  PrintFont.lfHeight          = POpt.FontHeight;
  PrintFont.lfWidth           = 0;
  PrintFont.lfEscapement      = 0;
  PrintFont.lfWeight          = FW_NORMAL;
  PrintFont.lfItalic          = 0;
  PrintFont.lfUnderline       = 0;
  PrintFont.lfStrikeOut       = 0;
  PrintFont.lfOrientation     = 0;
  PrintFont.lfCharSet         = POpt.CharSet;
  PrintFont.lfCLipPrecision   = CLIP_DEFAULT_PRECIS;
  PrintFont.lfQuality         = DEFAULT_QUALITY;
  PrintFont.lfPitchAndFamily  = FIXED_PITCH | FF_DONTCARE;
  PrintFont.lfFaceName        = POpt.FontName;

  ChooseRec.lStructSize     = 46;
  ChooseRec.hWndOwner       = dlg;                // caller's window handle
  ChooseRec.hDC             = dc;                 // printer DC/IC or nil
  ChooseRec.lpLogFont       = &PrintFont;         // ptr. to a LOGFONT struct
  ChooseRec.iPointSize      = 0;                  // 10 * size in points of selected font
  ChooseRec.Flags           = CF_PRINTERFONTS | CF_INITTOLOGFONTSTR | CF_FIXEDPITCHONLY;   // enum. type flags
  ChooseRec.rgbColors       = 0x00ffffff;         // returned text color
  ChooseRec.lCustData       = 0;                  // data passed to hook fn.
  ChooseRec.lpfnHook        = 0;                  // ptr. to hook function
  ChooseRec.lpTemplateName  = 0;                  // custom template name
  ChooseRec.hInstance       = app_handle;
  ChooseRec.lpszStyle       = &t.style;           /* return the style field here
                                                    must be lf_FaceSize or bigger */
  ChooseRec.nFontType       = PRINTER_FONTTYPE;                  /* same value reported to the EnumFonts
                                                      call back with the extra fonttype_
                                                      bits added */
  ChooseRec.nSizeMin        = 0;                  // minimum pt size allowed &
  ChooseRec.nSizeMax        = 0;                  /* max pt size allowed if
                                                  cf_LimitSize is used      */

  if( HookFontPromptWithMacro( &ChooseRec, "PrintFontProc" ) )
	{

    POpt.FontName       = PrintFont.lfFaceName;
    POpt.FontHeight     = PrintFont.lfHeight;
    POpt.FontPointSize  = ChooseRec.iPointSize;
    Popt.CharSet        = PrintFont.lfCharset;

    struct_to_str (tstr, POpt);
    POptionsStruct = tstr;

		return(TRUE);
	}
  return (FALSE);
}

void PrintPageDialog (int dlg, struct TPrintDlg Pds)
{
  int jx;
  struct TPrintOptions pOpt;
  str tstr [1024] = POptionsStruct;
  str_to_struct (pOpt, tstr);

  int dlg;
	DlgCreate(dlg);

  DlgAddCtrl( dlg, DLG_GroupBox, "Margins", 1, 1, 18, 6, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Static,  "&Left:",   2, Dlg_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",         DLG_PosOffset + 8, Dlg_PosOffset, 5, 0, _PS_LMARGIN, 0, "/MAX=100/MIN=0");
  DlgAddCtrl( dlg, DLG_Static,  "&Right:",  2, Dlg_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",         DLG_PosOffset + 8, Dlg_PosOffset, 5, 0, _PS_RMARGIN, 0, "/MAX=100/MIN=0");
  DlgAddCtrl( dlg, DLG_Static,  "&Top:",    2, Dlg_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",         DLG_PosOffset + 8, Dlg_PosOffset, 5, 0, _PS_TMARGIN, 0, "/MAX=100/MIN=0");
  DlgAddCtrl( dlg, DLG_Static,  "&Bottom:", 2, Dlg_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",         DLG_PosOffset + 8, Dlg_PosOffset, 5, 0, _PS_BMARGIN, 0, "/MAX=100/MIN=0");

  DlgSetInt ( dlg, _PS_LMARGIN, POpt.LMargin);
  DlgSetInt ( dlg, _PS_RMARGIN, POpt.RMargin);
  DlgSetInt ( dlg, _PS_TMARGIN, POpt.TMargin);
  DlgSetInt ( dlg, _PS_BMARGIN, POpt.BMargin);

  DlgAddCtrl( dlg, DLG_GroupBox, "Header/Footer", 21, 1, 50, 6, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Static,   "H&eader:",  22, DLG_PosOffset + 1, 10, 0, -1,   0, "");
  DlgAddCtrl( dlg, DLG_CheckBox, "",          22, Dlg_PosOffset + 1, DLG_Units | 10,  0, _PS_HEADERON, 0, "");
  DlgAddCtrl( dlg, DLG_Text,     "",          DLG_PosOffset + 3, DLG_PosOffset, 45, 0, _PS_HEADER,   0, "/ML=128/HISTORY=HEADER_HISTORY");
  DlgAddCtrl( dlg, DLG_Static,   "F&ooter:",  22, DLG_PosOffset + 1, 10, 0, -1,   0, "");
  DlgAddCtrl( dlg, DLG_CheckBox, "",          22, DLG_PosOffset + 1, DLG_Units | 10,  0, _PS_FOOTERON, 0, "");
  DlgAddCtrl( dlg, DLG_Text,     "",          DLG_PosOffset + 3, DLG_PosOffset, 45, 0, _PS_FOOTER,   0, "/ML=128/HISTORY=FOOTER_HISTORY");

  DlgSetInt ( dlg, _PS_HEADERON, (POpt.Flags & POPTF_HEADERON) != 0);
  DlgSetInt ( dlg, _PS_FOOTERON, (POpt.Flags & POPTF_FOOTERON) != 0);
  jx = Parse_Int ("/#=", Global_Str ("HEADER_HISTORY") );
  if (jx) {
    DlgSetStr (dlg, _PS_HEADER, Global_Str ("HEADER_HISTORY" + Str (jx)));
  } else {
    DlgSetStr (dlg, _PS_HEADER, POpt.Header);
  }
  jx = Parse_Int ("/#=", Global_Str ("FOOTER_HISTORY") );
  if (jx) {
    DlgSetStr (dlg, _PS_FOOTER, Global_Str ("FOOTER_HISTORY" + Str (jx)));
  } else {
    DlgSetStr (dlg, _PS_FOOTER, POpt.Footer);
  }

  DlgAddCtrl( dlg, DLG_GroupBox, "From Edge", 73, 1, 20, 3, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Static,  "Hea&der:",  74, DLG_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",          DLG_PosOffset + 9, DLG_PosOffset, 5, 0, _PS_HEADEROFFSET, 0, "/MAX=100/MIN=0");
  DlgAddCtrl( dlg, DLG_Static,  "Foo&ter:",  74, DLG_PosOffset + 1, 8, 0, -1, 0, "");
  DlgAddCtrl( dlg, DLG_Integer, "",          DLG_PosOffset + 9, DLG_PosOffset, 5, 0, _PS_FOOTEROFFSET, 0, "/MAX=100/MIN=0");

  DlgSetInt ( dlg, _PS_HEADEROFFSET, POpt.HeaderOffset);
  DlgSetInt ( dlg, _PS_FOOTEROFFSET, POpt.FooterOffset);

  DlgAddCtrl(dlg, DLG_Static, "Line &Numbering:", 73, 5, 20, 0, -1, 0, "");
  DlgAddCtrl(dlg, DLG_Choice, "None()Number from Top()Number from Block()", DLG_PosOffset, DLG_PosOffset + 1, 20, 0, _PS_LINENUMBERING, 0, "");
  DlgSetInt (dlg, _PS_LINENUMBERING, POpt.LineNumbering + 1);

  DlgAddCtrl( dlg, DLG_PushButton, "OK", 1,   Dlg_PosOffset + 2,  Dlg_StanBtnWidth,                 0, 101, DLGF_DefButton, "/R=1");
  DlgAddCtrl( dlg, DLG_PushButton, "Cancel",  Dlg_PosOffset + 12, Dlg_PosOffset, Dlg_StanBtnWidth,  0, 102, 0, "/R=0");
  DlgAddCtrl( dlg, DLG_PushButton, "&Help",   Dlg_PosOffset + 60, Dlg_PosOffset, Dlg_StanBtnWidth,  0, 103, 0, "/R=2");

  int tint = DlgExecute(dlg, 101, "Page Setup", PAGESETUP_HELPLINK, '', 0);

  if ( tint == 1 )
  {
    POpt.LMargin = DlgGetInt ( dlg, _PS_LMARGIN);
    POpt.RMargin = DlgGetInt ( dlg, _PS_RMARGIN);
    POpt.TMargin = DlgGetInt ( dlg, _PS_TMARGIN);
    POpt.BMargin = DlgGetInt ( dlg, _PS_BMARGIN);
    POpt.HeaderOffset = DlgGetInt ( dlg, _PS_HEADEROFFSET);
    POpt.FooterOffset = DlgGetInt ( dlg, _PS_FOOTEROFFSET);

    POpt.Header = DlgGetStr (dlg, _PS_HEADER);
    POpt.Footer = DlgGetStr (dlg, _PS_FOOTER);

    POpt.LineNumbering = DlgGetInt (dlg, _PS_LINENUMBERING) - 1;

    if (DlgGetInt (dlg, _PS_HEADERON))
      POpt.flags |= POPTF_HEADERON;
    else
      POpt.flags &= (POPTF_HEADERON ^ 0xffff);

    if (DlgGetInt (dlg, _PS_FOOTERON))
      POpt.flags |= POPTF_FOOTERON;
    else
      POpt.flags &= (POPTF_FOOTERON ^ 0xffff);

    DlgKill (dlg);
    struct_to_str (tstr, POpt);
    POptionsStruct = tstr;
  }
}


int PrintSetupHook( int dlg, int message, int wparam, int lparam, struct TPrintDlg pds ) No_Break
{
  int result = 0;
 // msglog (1, "Setup", dlg, message, wparam, lparam);
  switch ( message )
  {
    case WM_INITDIALOG :
      // InitSetupDialog (dlg, pds);
      HelpLink_String = PRINTSETUP_HELPLINK;
      break;

    case WM_ACTIVATE :
      if ( wparam )
      {
        HelpLink_String = PRINTSETUP_HELPLINK;
      } else {
        HelpLink_String = "";
      }
      break;

    case WM_COMMAND :
      switch ( wparam  )
      {
        case _PS_PAGESETUP :
        {
          PrintPageDialog (dlg, pds);
          result = 1;
          break;
        }

        case _PS_FONTS :
        {
          int jx, dc;
          str szPrinter;

          if (SendDlgItemMessage (dlg, _P_DEFBTN, BM_GETSTATE, 0, 0) & 0x03) {
            dc = GetPrinterDC("");
          } else {
            jx = SendDlgItemMessage (dlg, _P_SELPRINTER, CB_GETCURSEL, 0, 0);
            SendDlgItemMessageStr (dlg, _P_SELPRINTER, CB_GETLBTEXT, jx, szPrinter);

            jx = XPos (' on ', szPrinter, 1);
            if ( jx )
            {
              dc = GetPrinterDC (Copy (szPrinter, 1, jx-1));
            }
            else
            {
              dc = 0;
            }
          }
          SelectPFont (dlg, dc);
          if ( dc )
            DeleteDC (dc);
          result = 1;
          break;
        }

        case ID_OK :
          break;

        case _P_HELP :
          MewHelp_Context ();
          result = 1;
          break;
      }
      break;
  }
  return (result);
}

void PrintOptsDialog (int dlg, struct TPrintDlg Pds)
{
  struct TPrintOptions pOpt;
  str tstr [1024] = POptionsStruct;
  str_to_struct (pOpt, tstr);

  int dlg;
	DlgCreate(dlg);
  DlgAddCtrl( dlg, DLG_CheckBox, "&Page Breaks from Embedded Formfeed", 3, 1, 0, 0, _PO_FF, 0, "");
  DlgSetInt ( dlg, _PO_FF, (POpt.Flags & POPTF_USEFF) != 0);
  DlgAddCtrl( dlg, DLG_CheckBox, "&Wrap Text at Margin", 3, 2, 0, 0, _PO_WRAP, DLGF_Disable, "");

  DlgAddCtrl( dlg, DLG_PushButton, "OK", 1, Dlg_PosOffset + 2, Dlg_StanBtnWidth, 0, 101, DLGF_DefButton, "/R=1");
  DlgAddCtrl( dlg, DLG_PushButton, "Cancel", Dlg_PosOffset + 12, Dlg_PosOffset, Dlg_StanBtnWidth, 0, 102, 0, "/R=0");
  DlgAddCtrl( dlg, DLG_PushButton, "&Help", Dlg_PosOffset + 40, Dlg_PosOffset, Dlg_StanBtnWidth, 0, 103, 0, "/R=2");

  return_int = DlgExecute(dlg, _PO_FF, "Print Options", PRINTOPT_HELPLINK, '', 0);

  if ( return_int == 1 )
  {
    if (DlgGetInt (dlg, _PO_FF))
      POpt.flags |= POPTF_USEFF;
    else
      POpt.flags &= (POPTF_USEFF ^ 0xffff);

    if (DlgGetInt (dlg, _PO_WRAP))
      POpt.flags |= POPTF_WRAP;
    else
      POpt.flags &= (POPTF_WRAP ^ 0xffff);

    DlgKill (dlg);
    struct_to_str (tstr, POpt);
    POptionsStruct = tstr;
  }
}

int PrintHook( int dlg, int message, int wparam, int lparam, struct TPrintDlg pds ) No_Break
{
  int result = 0;
  // msglog (1, "Print", dlg, message, wparam, lparam);
  switch ( message )
  {
    case WM_INITDIALOG :
      HelpLink_String  = PRINT_HELPLINK;
      break;

    case WM_ACTIVATE :
      if ( wparam )
      {
        HelpLink_String  = PRINT_HELPLINK;
      } else {
        HelpLink_String  = "";
      }

      break;

    case WM_COMMAND :
      switch ( wparam  )
      {
        case _PN_OPTIONS :
          PrintOptsDialog (dlg, pds);
          result = 1;
          break;

        case _PS_PAGESETUP :
          PrintPageDialog (dlg, pds);
          result = 1;
          break;

        case _PS_FONTS :
        {
          int jx, dc;
          str szPrinter[128];

          GetWindowText (GetDlgItem (dlg, _P_PRNPRINTER), szPrinter, 127);
          if ( XPos ('Default Printer', szPrinter, 1) ) {
            dc = GetPrinterDC("");
          } else {
            jx = XPos (' on ', szPrinter, 1);
            if ( jx ) {
              dc = GetPrinterDC (Copy (szPrinter, 1, jx-1));
            } else {
              dc = 0;
            }
          }
          SelectPFont (dlg, dc);
          if ( dc )
            DeleteDC (dc);
          result = 1;
          break;
        }
        case ID_OK :
          break;

        case _P_HELP :
          MewHelp_Context();
          result = 1;
          break;
      }

  }
  return (result);
}

void InitOptions ()
{
  struct TPrintOptions pOpt;
  str tstr [1024] = POPtionsStruct;
  if ( tstr == "")
  {
    POpt.Header = "<LM><FILE>.<EXT><RM><CDATE> <CTIME>";
    POpt.Footer = "<CM>Page: <PAGE>";

    POpt.LMargin = 3;
    POpt.RMargin = 3;
    POpt.TMargin = 3;
    POpt.BMargin = 3;

    POpt.LineNumbering = 0;

    POpt.HeaderOffset = 1;
    POpt.FooterOffset = 1;

    POpt.Flags = POPTF_HEADERON | POPTF_FOOTERON;

    POpt.FontName       = "Courier New";
    POpt.FontHeight     = -13;
    Popt.FontPointSize  = 90;
    POpt.CharSet        = 0;
  }
  else
  {
    str_to_struct (pOpt, tstr);
    if ( POpt.Fontname == '' )
    {
      POpt.FontName       = "Courier New";
      POpt.FontHeight     = -13;
      Popt.FontPointSize  = 90;
      POpt.CharSet        = 0;
    }
  }
  if ( parse_int ("/#=", Global_Str("HEADER_HISTORY")) == 0 )
  {
    return_str = POpt.Header;
    RM ("HISTORY_LIST /M=1/HISTORY=HEADER_HISTORY");
  }
  if ( parse_int ("/#=", Global_Str("FOOTER_HISTORY")) == 0 )
  {
    return_str = POpt.Footer;
    RM ("HISTORY_LIST /M=1/HISTORY=FOOTER_HISTORY");
  }

  struct_to_str (tstr, pOpt);
  POptionsStruct = tstr;
}



void PrintWindow ( int parent = parse_int("/DLGHANDLE=", mparm_str),
                   int win    = parse_int("/WINHANDLE=", mparm_str) )
{
  int result;
  int tRefresh = refresh;

  struct TPrintDlg pds;
  struct TPrintRec prec;

  InitOptions ();

  if ( !parent )
    parent = frame_handle;

  int twin = cur_window;
  if ( win )
    switch_window (win);

  HelpLink_String = PRINT_HELPLINK;
  refresh = FALSE;

  prec.PrintTemplate    = "PRINTPROMPT";
  prec.SetupTemplate    = "PRINTSETUPPROMPT";

  pds.hWndOwner             = parent;
  pds.HInstance             = app_handle;
  pds.hDevMode              = hMewDevMode;
  pds.hDevNames             = hMewDevNames;
  pds.nCopies               = 1;
  pds.nFromPage             = 0xffff;
  pds.nToPage               = 0xffff;
  pds.nMinPage              = 0;
  pds.nMaxPage              = 0;
  pds.flags                 = PD_ENABLEPRINTTEMP | PD_ENABLESETUPTEMP | PD_SHOWHELP | PD_RETURNDC;
  pds.lCustData             = 0;
  pds.lpfnPrintHook         = 0;
  pds.lpfnSetupHook         = 0;
  pds.lpPrintTemplateName   = &prec.PrintTemplate;
  pds.lpSetupTemplateName   = &prec.SetupTemplate;

  pds.flags |= PD_COLLATE;

  if (doc_mode) {
    pds.nMinPage = 1;
    pds.nMaxPage = 0xffff;
  } else {
    pds.flags |= PD_NOPAGENUMS;
  }

  if ( block_stat) {
    pds.flags |= PD_SELECTION;
  } else {
    pds.flags |= PD_NOSELECTION | PD_ALLPAGES;
  }
  result = HookPrintPromptWithMacro ( &pds, "PrintHook", "PrintSetupHook");

  if ( result  )
  {
    hMewDevMode   = pds.hDevMode;
    hMewDevNames  = pds.hDevNames;

    SavePrintCfg ();

    struct TPrintOptions PrnOpt;
    str tstr [1024] = POptionsStruct;
    str_to_struct (PrnOpt, tstr);

    PrintFromWindow (parent, cur_window, &pds, &PrnOpt);
    DeleteDC (pds.hdc);
  }
  else
  {
    int error = CommDlgExtendedError ();
    if ( error )
    {
      Make_Message ("Error= " + str (CommDlgExtendedError()));
    }
  }
  HelpLink_String = "";

  switch_window (twin);
  refresh = tRefresh;
  return ();
}


void PrintSetup ( int parent = parse_int("/DLGHANDLE=", mparm_str) )
{
  int result;
  int tRefresh = refresh;

  InitOptions ();
  if (!parent )
  {
    parent = frame_handle;
  }
  struct TPrintDlg pds;
  struct TPrintRec prec;

  refresh = FALSE;

  prec.SetupTemplate        = "PRINTSETUPPROMPT";

  pds.hWndOwner             = parent;
  pds.HInstance             = app_handle;
  pds.hDevMode              = hMewDevMode;
  pds.hDevNames             = hMewDevNames;
  pds.nCopies               = 1;
  pds.nFromPage             = 0xffff;
  pds.nToPage               = 0xffff;
  pds.nMinPage              = 0;
  pds.nMaxPage              = 0;
  pds.flags                 = PD_ENABLESETUPTEMP | PD_PRINTSETUP | PD_SHOWHELP;
  pds.lCustData             = 0;
  pds.lpfnPrintHook         = 0;
  pds.lpfnSetupHook         = 0;
  pds.lpPrintTemplateName   = 0;
  pds.lpSetupTemplateName   = &prec.SetupTemplate;

  result = HookPrintPromptWithMacro ( &pds, "", "PrintSetupHook");

  if ( result )
  {
    hMewDevMode   = pds.hDevMode;
    hMewDevNames  = pds.hDevNames;

    SavePrintCfg ();
  }

  refresh = tRefresh;
  return();
}

void Prn_Conv_To_Hex ( str &t_str) TRANS2 {
  str raw_str[1024] = t_str,
      t_hex_str[2];
  int t_int;
  t_str = "";

  for (t_int = 1; t_int <= svl(raw_str); ++t_int) {
    t_hex_str = Hex_Str(Ascii(str_char(raw_str,t_int)));
    if (svl(t_hex_str) == 1) {
      t_hex_str = "0" + t_hex_str;
    }
    t_str += t_hex_str + " ";
  }

  Return ();
}

void Prn_Filter (str &t_str) TRANS2 {
  int filter_char = global_int("@PRN_FILTER_CHAR"),
      t_int,
      t_str_addr = ((seg(t_str) << 16) | ofs(t_str)) + 3;

  if (filter_char == 0) {
    filter_char = 32; // default is a space
  } else if (filter_char == -1) {
    filter_char = 0; // null if global is -1
  }

  for (t_int = 1; t_int <= svl(t_str); ++t_int) {
    if (xpos(str_char(t_str,t_int),"\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",1)) {
      memb(t_str_addr + t_int, filter_char);
    }
  }
}