gdi32: Add GdiGetDevmodeForPage implementation.

This commit is contained in:
Piotr Caban 2023-10-10 18:04:59 +02:00 committed by Alexandre Julliard
parent 78acbb6fec
commit 12c3579bcb

View file

@ -25,6 +25,7 @@
#include "ntuser.h"
#include "ddrawgdi.h"
#include "winnls.h"
#include "winppi.h"
#include "wine/list.h"
#include "wine/debug.h"
@ -68,6 +69,47 @@ struct print
DEVMODEW *devmode;
};
BOOL WINAPI SeekPrinter( HANDLE, LARGE_INTEGER, LARGE_INTEGER*, DWORD, BOOL );
enum
{
EMRI_METAFILE = 1,
EMRI_ENGINE_FONT,
EMRI_DEVMODE,
EMRI_TYPE1_FONT,
EMRI_PRESTARTPAGE,
EMRI_DESIGNVECTOR,
EMRI_SUBSET_FONT,
EMRI_DELTA_FONT,
EMRI_FORM_METAFILE,
EMRI_BW_METAFILE,
EMRI_BW_FORM_METAFILE,
EMRI_METAFILE_DATA,
EMRI_METAFILE_EXT,
EMRI_BW_METAFILE_EXT,
EMRI_ENGINE_FONT_EXT,
EMRI_TYPE1_FONT_EXT,
EMRI_DESIGNVECTOR_EXT,
EMRI_SUBSET_FONT_EXT,
EMRI_DELTA_FONT_EXT,
EMRI_PS_JOB_DATA,
EMRI_EMBED_FONT_EXT,
EMRI_HEADER = 65536
};
struct spool_handle
{
HANDLE spool;
int devmodes_no;
int devmodes_size;
struct
{
int page;
DEVMODEW *devmode;
} *devmodes;
};
DC_ATTR *get_dc_attr( HDC hdc )
{
DWORD type = gdi_handle_type( hdc );
@ -2670,8 +2712,41 @@ ULONG WINAPI DdQueryDisplaySettingsUniqueness(void)
HANDLE WINAPI GdiGetSpoolFileHandle( WCHAR *printer_name,
DEVMODEW *devmode, WCHAR *doc_name )
{
FIXME( "%s %p %s\n", wine_dbgstr_w(printer_name), devmode, wine_dbgstr_w(doc_name) );
return NULL;
struct spool_handle *ret;
HANDLE spool;
TRACE( "%s %p %s\n", wine_dbgstr_w(printer_name), devmode, wine_dbgstr_w(doc_name) );
if (!devmode) return NULL;
if (!OpenPrinterW( doc_name, &spool, NULL )) return NULL;
ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) );
if (!ret)
{
ClosePrinter( spool );
return NULL;
}
ret->spool = spool;
ret->devmodes = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret->devmodes) * 8);
if (!ret->devmodes)
{
GdiDeleteSpoolFileHandle( ret );
return NULL;
}
ret->devmodes_size = 8;
ret->devmodes[0].devmode = HeapAlloc( GetProcessHeap(), 0,
devmode->dmSize + devmode->dmDriverExtra );
if (!ret->devmodes[0].devmode)
{
GdiDeleteSpoolFileHandle( ret );
return NULL;
}
memcpy( ret->devmodes[0].devmode, devmode, devmode->dmSize + devmode->dmDriverExtra );
ret->devmodes[0].page = 0;
ret->devmodes_no = 1;
return ret;
}
/*******************************************************************
@ -2679,8 +2754,108 @@ HANDLE WINAPI GdiGetSpoolFileHandle( WCHAR *printer_name,
*/
BOOL WINAPI GdiDeleteSpoolFileHandle( HANDLE h )
{
FIXME( "%p\n", h );
return FALSE;
struct spool_handle *sh = (struct spool_handle *)h;
int i;
TRACE( "%p\n", h );
if (!sh)
return FALSE;
ClosePrinter( sh->spool );
for (i = 0; i < sh->devmodes_no; i++)
HeapFree( GetProcessHeap(), 0, sh->devmodes[i].devmode );
HeapFree( GetProcessHeap(), 0, sh->devmodes );
return TRUE;
}
static BOOL read_emfspool_record( struct spool_handle *sh )
{
struct record_hdr
{
unsigned int ulID;
unsigned int cjSize;
} hdr;
LARGE_INTEGER pos;
BOOL ret;
DWORD r;
if (!sh->spool) return FALSE;
ret = ReadPrinter( sh->spool, &hdr, sizeof(hdr), &r );
if (!ret || r != sizeof(hdr))
{
ClosePrinter( sh->spool );
sh->spool = NULL;
return FALSE;
}
TRACE( "parsing record %u\n", hdr.ulID );
if (hdr.ulID == EMRI_HEADER)
hdr.cjSize -= sizeof(hdr);
switch (hdr.ulID)
{
case EMRI_DEVMODE:
/* remove unused devmode */
if (sh->devmodes_no - 2 >= 0 && sh->devmodes[sh->devmodes_no - 2].page ==
sh->devmodes[sh->devmodes_no - 1].page)
{
HeapFree( GetProcessHeap(), 0, sh->devmodes[sh->devmodes_no - 1].devmode );
sh->devmodes_no--;
}
else if (sh->devmodes_no == sh->devmodes_size)
{
void *alloc = HeapReAlloc( GetProcessHeap(), 0, sh->devmodes, sh->devmodes_size * 2 );
if (!alloc)
{
ClosePrinter( sh->spool );
sh->spool = NULL;
return FALSE;
}
sh->devmodes = alloc;
sh->devmodes_size *= 2;
}
sh->devmodes[sh->devmodes_no].devmode = HeapAlloc( GetProcessHeap(), 0, hdr.cjSize );
if (!sh->devmodes[sh->devmodes_no].devmode)
{
ClosePrinter( sh->spool );
sh->spool = NULL;
return FALSE;
}
ret = ReadPrinter( sh->spool, sh->devmodes[sh->devmodes_no].devmode, hdr.cjSize, &r );
if (!ret || r != hdr.cjSize)
{
ClosePrinter( sh->spool );
sh->spool = NULL;
return FALSE;
}
sh->devmodes[sh->devmodes_no].page = sh->devmodes[sh->devmodes_no - 1].page;
sh->devmodes_no++;
return TRUE;
case EMRI_METAFILE:
case EMRI_FORM_METAFILE:
case EMRI_BW_METAFILE:
case EMRI_BW_FORM_METAFILE:
case EMRI_METAFILE_EXT:
case EMRI_BW_METAFILE_EXT:
sh->devmodes[sh->devmodes_no - 1].page++;
/* fall through */
default:
pos.QuadPart = hdr.cjSize;
ret = SeekPrinter( sh->spool, pos, NULL, FILE_CURRENT, FALSE );
if (!ret)
{
ClosePrinter( sh->spool );
sh->spool = NULL;
return FALSE;
}
return TRUE;
}
}
/*******************************************************************
@ -2688,6 +2863,33 @@ BOOL WINAPI GdiDeleteSpoolFileHandle( HANDLE h )
*/
BOOL WINAPI GdiGetDevmodeForPage( HANDLE h, DWORD page, DEVMODEW **cur, DEVMODEW **prev )
{
FIXME( "%p %ld %p %p\n", h, page, cur, prev );
return FALSE;
struct spool_handle *sh = (struct spool_handle *)h;
int i;
TRACE( "%p %ld %p %p\n", h, page, cur, prev );
if (!sh)
return FALSE;
i = 0;
while (1)
{
if (sh->devmodes[i].page >= page)
{
if (cur) *cur = sh->devmodes[i].devmode;
if (prev)
{
if (!i || sh->devmodes[i - 1].page != page - 1)
*prev = sh->devmodes[i].devmode;
else
*prev = sh->devmodes[i - 1].devmode;
}
return TRUE;
}
if (i + 1 < sh->devmodes_no)
i++;
else if (!read_emfspool_record( sh ))
return FALSE;
}
}