-- printws.ew --
-- a modified print.ew originally by Jacques Deschenes,
-- "corrupted" by Wolfgang Fritz for win32lib
without warning


global function peeksz(atom pStr) -- peek string zero
-- return from allocated memory a string terminated by zero
	integer c,i
	sequence str
	
	str = {}
	i = 1  c = 1
	c = peek(pStr)
	while c != 0 do
    	str = str & c
	    c = peek(pStr+i)
    	i = i + 1
  	end while
  	
	return str
end function

atom ok
constant FATAL_ERR = "Fatal error in printws.ew",
OPEN_DLL_FAILED = "Failed to open %s dll",
DEFINE_FAILED = "Failed to define one of %s dll function"

-- winspool.drv defines --
constant iwinspool = open_dll("winspool.drv")
if not iwinspool then
    ok = message_box(sprintf(OPEN_DLL_FAILED,{"winspool.drv"}),FATAL_ERR,0)
    abort(1)
end if
-- gdi32.dll defines --
constant igdi32 = open_dll("gdi32.dll")
if not igdi32 then
    ok = message_box(sprintf(OPEN_DLL_FAILED,{"gdi32.dll"}),FATAL_ERR,0)
    abort(1)
end if
constant
 iEnumPrinters = define_c_func(iwinspool,"EnumPrintersA",{C_INT,C_INT,C_INT,
                               C_INT,C_INT,C_INT,C_INT},C_INT)
  if find(0,{
       iEnumPrinters
     })   then
    ok = message_box(sprintf(DEFINE_FAILED,{"winspool.drv"}),FATAL_ERR,0)
    abort(1)
  end if                              

constant
  iCreateDC = define_c_func(igdi32,"CreateDCA",
                            {C_INT,C_INT,C_INT,C_INT},C_INT),
  iStartDoc = define_c_func(igdi32,"StartDocA",{C_INT,C_INT},C_INT),
  iEndDoc = define_c_func(igdi32,"EndDoc",{C_INT},C_INT),
  iStartPage = define_c_func(igdi32,"StartPage",{C_INT},C_INT),
  iEndPage =  define_c_func(igdi32,"EndPage",{C_INT},C_INT),
  iAbortDoc = define_c_func(igdi32,"AbortDoc",{C_INT},C_INT),
  iGetTextMetrics = define_c_func(igdi32,"GetTextMetricsA",
                                  {C_UINT,C_POINTER},C_INT),
  iGetDeviceCaps = define_c_func(igdi32,"GetDeviceCaps",
                                 {C_INT,C_INT},C_INT),
  iTextOut = define_c_func(igdi32,"TextOutA",
                           {C_INT,C_INT,C_INT,C_POINTER,C_INT},C_INT)
  if find(-1,{
     iCreateDC,
     iStartDoc,
     iEndDoc ,
     iStartPage ,
     iEndPage ,
     iAbortDoc,
     iGetTextMetrics,
     iGetDeviceCaps,
     iTextOut
   })then
    ok = message_box(sprintf(DEFINE_FAILED,{"gdi32.dll"}),FATAL_ERR,0)
    abort(1)
  end if
  
-- printers enumeration --

constant -- printer info structures
  -- PRINTER_INFO_5
  piPrinterName = 0, 
  piPortName = 4,
  piAttributes = 8, 
  piDeviceNotSelectedTimeout = 12, 
  piTransmissionRetryTimeout = 16, 
  PINFO5_SIZE = 20
  
constant 
  PRINTER_ENUM_DEFAULT = 1,
  PRINTER_ENUM_LOCAL = 2
    
global function DefaultPrinterName()
-- return default printer name
atom pPInfo5, pNeeded, pReturned, ok, needed
sequence PrinterName

 pNeeded = allocate(4)    mem_set(pNeeded,0,4)
 pReturned = allocate(4)  mem_set(pReturned,0,4)
 -- first try to know how many bytes needed for pPInfo5
 ok = w32Func(iEnumPrinters,{PRINTER_ENUM_DEFAULT, NULL,5,0,0,pNeeded,pReturned})
 needed = peek4u(pNeeded)
 pPInfo5 = allocate(needed)    mem_set(pPInfo5,0,needed)
 ok = w32Func(iEnumPrinters,{PRINTER_ENUM_DEFAULT,NULL,5,pPInfo5,needed,
                            pNeeded,pReturned})
 free(pNeeded)
 free(pReturned)
 if not ok then
    free(pPInfo5)
    return {}
 else
    PrinterName  = peeksz(peek4u(pPInfo5))
    free(pPInfo5)
    return PrinterName
 end if
end function 

global function GetPrinterDC(sequence PrinterName)
atom pStr, hpdc
  pStr = allocate_string(PrinterName)
  hpdc = w32Func(iCreateDC,{0,pStr,0,0})
  free(pStr)
  return hpdc
end function

constant -- DOCINFO structure
  diSize = 0,
  diDocName = 4,
  diOutput = 8,
  diDataType = 12,
  diType = 16,
  DOCINFO_SIZE = 20
  
global function StartDoc(atom hpdc, sequence DocName)
atom ok, pStr, pDocInfo

  pStr = allocate_string(DocName)
  pDocInfo = allocate(DOCINFO_SIZE)
  mem_set(pDocInfo,0,DOCINFO_SIZE)
  poke4(pDocInfo+diDocName,pStr)
  ok = w32Func(iStartDoc,{hpdc,pDocInfo})
  free(pStr)
  free(pDocInfo)
  return ok
end function

global function EndDoc(atom hpdc)
  return w32Func(iEndDoc,{hpdc})
end function

global function StartPage(atom hpdc)
  return w32Func(iStartPage,{hpdc})
end function

global function EndPage(atom hpdc)
  return w32Func(iEndPage,{hpdc})
end function

global function AbortDoc(atom hpdc)
  return w32Func(iAbortDoc,{hpdc})
end function

-- ** here is the "bastard" procedure which is NOT Win32 API standard.
global procedure pTextOut(atom hdc, integer x,integer y, sequence text)
atom pStr, ok
  pStr = allocate_string(text)
  ok = w32Func(iTextOut,{hdc,x,y,pStr,length(text)})
  free(pStr)
end procedure

global procedure DeleteDC(atom hdc)
  return w32Proc(xDeleteDC,{hdc})
end procedure

constant itmFirstChar = 44,
         itm_struc_size = 53

global function GetTextMetrics(atom hdc)
atom pTM
integer ok
sequence itm
  pTM = allocate(itm_struc_size)
  ok = w32Func(iGetTextMetrics,{hdc, pTM})
  if not ok then
  free(pTM)
  return 0
  else
  itm = peek4u({pTM,11}) & peek({pTM+itmFirstChar,9})
  free(pTM)
  return itm
  end if
end function 

global function GetDeviceCaps(atom hdc, atom index)
  return  w32Func(iGetDeviceCaps,{hdc,index})
end function
----
