campo-sirio/xvaga/oswin32.cpp

1067 lines
26 KiB
C++
Raw Normal View History

#include "wxinc.h"
#include "wx/filename.h"
#include "wx/image.h"
#include "wx/paper.h"
#include "wx/printdlg.h"
#include "oswin32.h"
#include "aclapi.h"
#include "xvt_menu.h"
#include "xvt_help.h"
#include "xvtart.h"
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define STRICT
#include <windows.h>
#include <winspool.h>
#include <shellapi.h>
bool OsWin32_CheckPrinterInfo(const void* data, unsigned int size)
{
bool ok = data != NULL;
if (ok)
{
LPDEVMODE pdm = (LPDEVMODE)data;
const unsigned int s = pdm->dmSize + pdm->dmDriverExtra;
ok = s > 0 && s == size;
}
return ok;
}
static int AdjustDevmodePlease(PDEVMODE dm)
{
// Forse dovremmo fare una Black List su file delle stampanti incompatibili):
// 1) "NRG SP 4100N PCL 5e"
// 2) aggiungere qui le altre
// Ma per ora zappiamo tutti i driver troppo grandi (> 3Kb)
if (dm->dmDriverExtra > 3*1024)
dm->dmDriverExtra = 0;
// Controllo il formato della carta
wxPrintPaperType* paper = wxThePrintPaperDatabase->FindPaperTypeByPlatformId(dm->dmPaperSize);
if (paper == NULL)
{
dm->dmFields |= DM_PAPERSIZE;
wxThePrintPaperDatabase->WXADDPAPER((wxPaperSize)dm->dmPaperSize /*wxPAPER_NONE*/, dm->dmPaperSize,
dm->dmFormName, dm->dmPaperWidth, dm->dmPaperLength);
}
return dm->dmSize + dm->dmDriverExtra;
}
void* OsWin32_ConvertFromNativePrinterInfo(void* hGlobal, unsigned int& nDataSize)
{
void* buff = NULL;
if (hGlobal != NULL)
{
PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal);
nDataSize = AdjustDevmodePlease(dm);
buff = new char[nDataSize];
memcpy(buff, dm, nDataSize);
::GlobalUnlock(hGlobal);
}
return buff;
}
void* OsWin32_ConvertToNativePrinterInfo(void* data, unsigned int nDataSize)
{
HGLOBAL hGlobal = ::GlobalAlloc(GHND, nDataSize); // Alloco lo spazio necessario
if (hGlobal != NULL)
{
PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal); // Trasformo l'handle in puntatore
memcpy(dm, data, nDataSize); // Ricopio i dati della stampante
const unsigned int sz = AdjustDevmodePlease(dm); // Metto a posto parametri non standard
wxASSERT(nDataSize == sz);
::GlobalUnlock(hGlobal); // Libero il lock sull'handle
}
return hGlobal;
}
struct XvtData
{
char** families;
long* sizes;
short* scalable;
int max_count;
int cur_count;
XvtData() { memset(this, 0, sizeof(XvtData)); }
};
int CALLBACK FamilyEnumerator(
const LOGFONT *plf, // pointer to logical-font data
const TEXTMETRIC * WXUNUSED(lpntme), // pointer to physical-font data
unsigned long WXUNUSED(FontType), // type of font
LPARAM lParam // application-defined data
)
{
XvtData* d = (XvtData*)lParam;
int& n = d->cur_count;
int i;
for (i = n-1; i >= 0 && wxStricmp(d->families[i], plf->lfFaceName); i--);
if (i < 0) // Controlla che il nome del font non ci sia gia'
d->families[n++] = wxStrdup(plf->lfFaceName);
return n < d->max_count;
}
int CALLBACK SizeEnumerator(
const LOGFONT *plf, // pointer to logical-font data
const TEXTMETRIC *lpntme, // pointer to physical-font data
unsigned long WXUNUSED(FontType), // type of font
LPARAM lParam // application-defined data
)
{
XvtData* d = (XvtData*)lParam;
int& i = d->cur_count;
int size = (plf->lfHeight+5) / 10;
if (size <= 0)
{
for (const char* n = plf->lfFaceName; *n; n++)
if (*n >= '1' && *n <= '9')
{
size = int(120.0 / atoi(n) + 0.5);
break;
}
if (size <= 0)
size = 12;
}
if (i == 0 || size > d->sizes[i-1])
{
d->sizes[i] = size;
if (lpntme->tmPitchAndFamily & TMPF_TRUETYPE)
*d->scalable = TRUE;
i++;
}
return i < d->max_count;
}
int FamilySorter(const void* p1,const void* p2)
{
const char* s1 = *(const char**)p1;
const char* s2 = *(const char**)p2;
return wxStricmp(s1, s2);
}
int OsWin32_EnumerateFamilies(WXHDC hDC, char** families, int max_count)
{
XvtData data;
data.families = families;
data.max_count = max_count;
LOGFONT lf; memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
::EnumFontFamiliesEx((HDC)hDC, &lf, FamilyEnumerator, (LPARAM)&data, 0);
qsort(families, data.cur_count, sizeof(char*), FamilySorter);
return data.cur_count;
}
int OsWin32_EnumerateSizes(WXHDC hDC, const char* name, long* sizes, short* scalable, int max_count)
{
XvtData data;
data.sizes = sizes;
data.scalable = scalable;
data.max_count = max_count;
LOGFONT lf; memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
strcpy(lf.lfFaceName, name);
::EnumFontFamiliesEx((HDC)hDC, &lf, SizeEnumerator, (LPARAM)&data, 0);
return data.cur_count;
}
void* OsWin32_GetPrinterInfo(int& size, const char* printer)
{
LPDEVMODE pdm = NULL;
size = 0;
char name[_MAX_PATH] = "";
if (printer == NULL || *printer == '\0')
{
unsigned long namelen = _MAX_PATH;
::GetDefaultPrinter(name, &namelen);
}
else
wxStrncpy(name, printer, sizeof(name));
HANDLE hPrinter = NULL;
if (::OpenPrinter(name, &hPrinter, NULL))
{
size = ::DocumentProperties(0, hPrinter, name, NULL, NULL, 0); // Determina dimensione DEVMODE
if (size > 0)
{
pdm = (LPDEVMODE)new BYTE[size]; // Alloca un DEVMODE sufficientemente capiente
memset(pdm, 0, size); // Azzera tutto per bene
::DocumentProperties(0, hPrinter, name, pdm, NULL, DM_OUT_BUFFER); // Legge DEVMODE
size = AdjustDevmodePlease(pdm);
}
else
size = 0;
::ClosePrinter(hPrinter);
}
return pdm;
}
void OsWin32_SetCaptionStyle(WXHWND handle, long style)
{
HWND hWnd = (HWND)handle;
LONG s = ::GetWindowLong(hWnd, GWL_STYLE);
if (style & wxSYSTEM_MENU)
s |= WS_CAPTION;
else
s &= ~WS_CAPTION;
if (style & wxCLOSE_BOX)
s |= WS_SYSMENU;
else
s &= ~WS_SYSMENU;
s |= WS_CLIPSIBLINGS; // Forzatura necessaria da wx261
::SetWindowLong(hWnd, GWL_STYLE, s);
if (style & wxCLOSE_BOX)
{
HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
WXHICON hIcon = xvtart_GetIconResource(0).GetHICON();
::SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
}
}
///////////////////////////////////////////////////////////
// Drawing bitmaps
///////////////////////////////////////////////////////////
HBITMAP OsWin32_CreateBitmap(const wxImage& img, wxDC& dc)
{
static wxPalette pal;
HDC hDC = (HDC)dc.GetHDC();
int nDepth = dc.GetDepth();
// Altrimenti le stampanti in B/N perdono i toni di grigio
if (nDepth == 1 && !OsWin32_IsWindowsServer())
{
hDC = NULL;
nDepth = 24;
}
if (nDepth == 8)
{
if (!pal.Ok())
{
unsigned char red[256], green[256], blue[256];
PALETTEENTRY pe[256]; memset(pe, 0, sizeof(pe));
UINT nEntries = ::GetSystemPaletteEntries(hDC, 0, 256, pe);
for (UINT i = 0; i < nEntries; i++)
{
red[i] = pe[i].peRed;
green[i] = pe[i].peGreen;
blue[i] = pe[i].peBlue;
}
pal.Create(nEntries, red, green, blue);
}
dc.SetPalette(pal);
}
const int nWidth = img.GetWidth();
const int nHeight = img.GetHeight();
int nBytesPerLine = 0;
int nPadding = 0;
int nBitCount = 24;
switch (nDepth)
{
case 32: // Better if > Win98 :-) too
nBitCount = 32;
nBytesPerLine = nWidth*4;
break;
default:
nBytesPerLine = nWidth*3;
break;
}
const int nResto = nBytesPerLine % 4;
if (nResto != 0)
{
nPadding = 4 - nResto;
nBytesPerLine += nPadding;
}
const int nImageSize = nHeight*nBytesPerLine;
// Create the DIB section
unsigned char* pbits = (unsigned char*)calloc(nImageSize, 1);
const size_t bi_size = sizeof(BITMAPINFOHEADER);
BITMAPINFO* bi = (BITMAPINFO*)calloc(bi_size, 1);
bi->bmiHeader.biSize = bi_size;
bi->bmiHeader.biWidth = nWidth;
bi->bmiHeader.biHeight = -nHeight;
bi->bmiHeader.biCompression = BI_RGB;
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = nBitCount;
bi->bmiHeader.biSizeImage = nImageSize;
switch (nBitCount)
{
case 24:
{
unsigned char* d = img.GetData();
unsigned char* p = pbits;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
*(p++) = *(d+2);
*(p++) = *(d+1);
*(p++) = *(d+0);
d += 3;
}
for (int i = 0; i < nPadding; i++)
*(p++) = 0;
}
}
break;
case 32:
{
unsigned char* d = img.GetData();
unsigned char* p = pbits;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
*(p++) = *(d+2);
*(p++) = *(d+1);
*(p++) = *(d+0);
*(p++) = 0;
d += 3;
}
}
}
break;
default:
break;
}
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
if (hBitmap)
{
HDC memdc = ::CreateCompatibleDC( hDC );
HBITMAP hOldBitmap = (HBITMAP)::SelectObject( memdc, hBitmap);
HPALETTE hOldPalette = NULL;
if (nDepth == 8)
{
hOldPalette = ::SelectPalette(memdc, (HPALETTE)pal.GetHPALETTE(), FALSE);
::RealizePalette(memdc);
}
::StretchDIBits( memdc, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, pbits, bi, DIB_RGB_COLORS, SRCCOPY);
if (hOldBitmap)
::SelectObject(memdc, hOldBitmap);
if (hOldPalette)
::SelectPalette(memdc, hOldPalette, FALSE);
::DeleteDC(memdc);
}
free(pbits);
free(bi);
return hBitmap;
}
bool OsWin32_DrawBitmap(HBITMAP hBMP, wxDC& dc, const wxRect& dst, const wxRect& src)
{
static wxPalette pal;
bool ok = hBMP != NULL;
if (ok)
{
HDC hDC = (HDC)dc.GetHDC();
const int nTechno = ::GetDeviceCaps(hDC, TECHNOLOGY);
HDC hMemDC = NULL;
if (OsWin32_IsWindowsServer())
hMemDC = ::CreateCompatibleDC(hDC); // Per Terminal Server devo fare cosi'
else
hMemDC = ::CreateCompatibleDC(NULL); // Per gli altri sistemi devo fare cosa'
BITMAP bmp; ::GetObject(hBMP, sizeof(bmp), &bmp);
if (nTechno == DT_RASPRINTER) // Sto stampando!
{
const size_t bi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
BITMAPINFO* bi = (BITMAPINFO*)calloc(bi_size, 1); // Alloca ed azzera
BITMAPINFOHEADER& bih = bi->bmiHeader;
bih.biSize = sizeof(bih);
GetDIBits(hMemDC, hBMP, 0, bmp.bmHeight, NULL, bi, DIB_RGB_COLORS);
ok = bih.biSizeImage > 0;
if (ok)
{
LPBYTE bits = new BYTE[bih.biSizeImage];
::GetDIBits(hMemDC, hBMP, 0, src.height, bits, bi, DIB_RGB_COLORS);
::StretchDIBits(hDC, dst.x, dst.y, dst.width, dst.height, src.x, src.y, src.width, src.height,
bits, bi, DIB_RGB_COLORS, SRCCOPY);
delete bits;
}
free(bi);
}
else
{
HGDIOBJ hOldBitmap = ::SelectObject(hMemDC, hBMP);
::SetStretchBltMode(hDC, HALFTONE);
::StretchBlt(hDC, dst.x, dst.y, dst.width, dst.height,
hMemDC, src.x, src.y, src.width, src.height, SRCCOPY);
::SelectObject(hMemDC, hOldBitmap);
}
::DeleteDC(hMemDC);
}
return ok;
}
void OsWin32_DrawDottedRect(WXHDC hDC, int left, int top, int right, int bottom)
{
LOGBRUSH lBrush;
lBrush.lbHatch = 0; lBrush.lbStyle = BS_SOLID;
lBrush.lbColor = ::GetTextColor((HDC)hDC);
HPEN hPen = ::ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lBrush, 0, NULL);
HGDIOBJ hOldPen = ::SelectObject((HDC)hDC, hPen);
HGDIOBJ hBrush = ::GetStockObject(HOLLOW_BRUSH);
HGDIOBJ hOldBrush = ::SelectObject((HDC)hDC, hBrush);
::Rectangle((HDC)hDC, left, top, right, bottom);
::SelectObject((HDC)hDC, hOldBrush);
::SelectObject((HDC)hDC, hOldPen);
::DeleteObject(hPen);
}
void OsWin32_Beep(int severity)
{
switch (severity)
{
case 1: ::MessageBeep(MB_ICONEXCLAMATION); break;
case 2: ::MessageBeep(MB_ICONSTOP); break;
default: ::MessageBeep(MB_OK); break;
}
}
static wxString GetHelpDir()
{
return "htmlhelp/";
}
static wxString FindHelpFile(const char* topic)
{
wxString strTopic = topic;
wxString strApp;
wxFileName::SplitPath(wxTheApp->argv[0], NULL, &strApp, NULL);
if (strTopic.IsEmpty())
{
strTopic = strApp;
strTopic += "100a";
}
wxString str;
for (int i = 0; i < 2; i++)
{
str = GetHelpDir();
str += i == 0 ? strTopic.Left(2) : strApp.Left(2);
str += "/";
str += strTopic;
str += ".html";
if (wxFileExists(str))
break;
}
return str;
}
int OsWin32_Help(WXHWND handle, const char* WXUNUSED(hlp), unsigned int cmd, const char* topic)
{
wxString str;
switch(cmd)
{
case M_HELP_ONCONTEXT:
str = FindHelpFile(topic);
if (wxFileExists(str))
break;
default:
str = GetHelpDir();
str += "index.html";
break;
}
if (!str.IsEmpty() && wxFileExists(str))
{
::ShellExecute((HWND)handle, "open", str, NULL, NULL, SW_SHOWDEFAULT);
return true;
}
OsWin32_Beep(1);
return false;
}
///////////////////////////////////////////////////////////
// Execute in window support
///////////////////////////////////////////////////////////
struct TFindWindowInfo
{
HINSTANCE _instance;
wxString _file;
HWND _hwnd;
TFindWindowInfo() : _instance(NULL), _hwnd(NULL) { }
};
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_instance != NULL)
{
HINSTANCE inst = (HINSTANCE)::GetWindowLong(hwnd, GWL_HINSTANCE);
if (inst == w->_instance)
{
// Cerco di capire se e' la finetra principale dal fatto che
// abbia la caption ed i bottoni di chiusura
const DWORD dwWanted = WS_CAPTION | WS_SYSMENU;
const DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
if ((style & dwWanted) == dwWanted)
{
w->_hwnd = hwnd;
return FALSE;
}
return TRUE;
}
}
if (!w->_file.IsEmpty())
{
char str[_MAX_PATH];
if (::GetWindowText(hwnd, str, sizeof(str)))
{
wxString title = str;
title.MakeUpper();
if (title.Find(w->_file) >= 0)
{
w->_hwnd = hwnd;
return FALSE;
}
}
}
return TRUE;
}
void OsWin32_PlaceProcessInWindow(unsigned int instance, const char* name, unsigned int parent)
{
TFindWindowInfo w;
w._instance = (HINSTANCE)instance;
w._file = name;
w._file.MakeUpper();
for (int i = 0; w._hwnd == NULL && i < 20; i++)
{
::wxMilliSleep(500);
::EnumWindows(EnumWindowsProc, LPARAM(&w));
}
if (w._hwnd != NULL) // L'ho trovata!
{
RECT rct; ::GetClientRect((HWND)parent, &rct);
::SetParent(w._hwnd, (HWND)parent);
const int fx = ::GetSystemMetrics(SM_CXFRAME);
const int fy = ::GetSystemMetrics(SM_CYFRAME);
int cy = ::GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYBORDER);
if (::GetMenu(w._hwnd) != NULL)
cy += ::GetSystemMetrics(SM_CYMENU);
::SetWindowPos(w._hwnd, (HWND)parent, -fx, -fy-cy, rct.right+2*fx, rct.bottom+cy+2*fy, SWP_NOZORDER);
}
}
static BOOL CALLBACK EnumCampoChildrenProc(HWND hwnd, LPARAM lParam)
{
char str[_MAX_PATH];
if (::GetWindowText(hwnd, str, sizeof(str)))
{
TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_file == str) // str == "__CAMPO_HOST_WINDOW__"
{
str[13] = '\0'; // Impedisce che questa finestra abbia altri figli indesiderati
::SetWindowText(hwnd, str);
w->_hwnd = hwnd;
return FALSE; // Fine della ricerca
}
}
return TRUE; // Continua a cercare
}
static BOOL CALLBACK EnumCampoMenuChildrenProc(HWND hwnd, LPARAM lParam)
{
char str[_MAX_PATH];
if (::GetWindowText(hwnd, str, sizeof(str)))
{
const wxString title = str;
if (title.StartsWith("Base - ")) // Scandisco solo i figli del menu
{
::EnumChildWindows(hwnd, EnumCampoChildrenProc, lParam);
const TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_hwnd != NULL)
return FALSE; // Fine della ricerca
}
}
return TRUE; // Continua a cercare
}
unsigned int OsWin32_FindMenuContainer()
{
TFindWindowInfo w;
w._file = "__CAMPO_HOST_WINDOW__";
::EnumWindows(EnumCampoMenuChildrenProc, LPARAM(&w));
return (unsigned int)w._hwnd;
}
static BOOL CALLBACK CountChildrenProc(HWND WXUNUSED(hwnd), LPARAM lParam)
{
if (lParam)
{
LONG* n = (LONG*)lParam;
(*n)++;
}
return TRUE;
}
long OsWin32_GetChildrenCount(unsigned int parent)
{
LONG n = 0;
::EnumChildWindows((HWND)parent, CountChildrenProc, (LPARAM)&n);
return n;
}
static BOOL CALLBACK CloseChildrenProc(HWND hwnd, LPARAM lParam)
{
::PostMessage(hwnd, WM_CLOSE, 0, 0);
return CountChildrenProc(hwnd, lParam);
}
long OsWin32_CloseChildren(unsigned int parent)
{
LONG n = 0;
::EnumChildWindows((HWND)parent, CloseChildrenProc, (LPARAM)&n);
return n;
}
static BOOL CALLBACK CloseSiblingProc(HWND hwnd, LPARAM lParam)
{
if (hwnd != (HWND)lParam)
{
if (!::IsWindowVisible(hwnd))
{
char str[256];
::GetClassName(hwnd, str, sizeof(str));
if (strcmp(str, "wxWindowClassNR") == 0)
{
::GetWindowText(hwnd, str, sizeof(str));
if (str[0] == '\0')
{
OsWin32_CloseChildren((UINT)hwnd);
CloseChildrenProc(hwnd, 0L);
}
}
}
}
return TRUE;
}
void OsWin32_CloseSiblings(unsigned int WXUNUSED(parent))
{
// NON FUNZIONA!!!!!!!!!!!!!!!!!!!!!!!!!!!
// ::EnumWindows(CloseSiblingProc, parent);
}
///////////////////////////////////////////////////////////
// Hardlock Support
///////////////////////////////////////////////////////////
#include "hlapi_c.h"
bool OsWin32_HL_Login(unsigned short address, const unsigned char* label, const unsigned char* password)
{
int err = HL_LOGIN(address, LOCAL_DEVICE, (unsigned char*)label, (unsigned char*)password);
return err == STATUS_OK;
}
bool OsWin32_HL_Logout()
{
HL_LOGOUT();
return TRUE;
}
bool OsWin32_HL_Read(unsigned short reg, unsigned short* data)
{
int err = HL_READ(reg, data);
return err == STATUS_OK;
}
bool OsWin32_HL_ReadBlock(unsigned char* data)
{
int err = HL_READBL(data);
return err == STATUS_OK;
}
bool OsWin32_HL_Write(unsigned short reg, unsigned short data)
{
int err = HL_WRITE(reg, data);
return err == STATUS_OK;
}
bool OsWin32_HL_Crypt(unsigned short* data) // Array di 4 words (8 bytes)
{
int err = HL_CODE(data, 1);
return err == STATUS_OK;
}
///////////////////////////////////////////////////////////
// Eutron Smartlink Support
///////////////////////////////////////////////////////////
#include "skeylink.h"
static KEY_NET _eutron_key;
bool OsWin32_SL_Crypt(unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = SCRAMBLING_MODE;
memcpy(_eutron_key.data, data, 8);
smartlink(&_eutron_key);
if (_eutron_key.status == ST_OK)
memcpy(data, _eutron_key.data, 8);
return _eutron_key.status == ST_OK;
}
bool OsWin32_SL_Login(const unsigned char* label, const unsigned char* password)
{
memset(&_eutron_key, 0, sizeof(KEY_NET));
_eutron_key.net_command = NET_KEY_OPEN;
_eutron_key.status = ST_HW_FAILURE; // Don't leave ST_OK = 0 here!
memcpy(_eutron_key.label, label, strlen((const char*)label));
memcpy(_eutron_key.password, password, strlen((const char*)password));
smartlink(&_eutron_key);
return _eutron_key.status == ST_OK;
}
bool OsWin32_SL_Logout()
{
_eutron_key.net_command = NET_KEY_CLOSE;
_eutron_key.command = 0;
smartlink(&_eutron_key);
return true;
}
bool OsWin32_SL_ReadBlock(unsigned short reg, unsigned short size, unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = BLOCK_READING_MODE;
unsigned short* pointer = (unsigned short*)(&_eutron_key.data[0]);
unsigned short* number = (unsigned short*)(&_eutron_key.data[2]);
*pointer = reg;
*number = size;
smartlink(&_eutron_key);
bool ok = _eutron_key.status == ST_OK;
if (ok)
memcpy(data, &_eutron_key.data[4], size*sizeof(unsigned short));
return ok;
}
bool OsWin32_SL_WriteBlock(unsigned short reg, unsigned short size, const unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = BLOCK_WRITING_MODE;
unsigned short* pointer = (unsigned short*)(&_eutron_key.data[0]);
unsigned short* number = (unsigned short*)(&_eutron_key.data[2]);
*pointer = reg;
*number = size;
memcpy(&_eutron_key.data[4], data, size*sizeof(unsigned short));
smartlink(&_eutron_key);
return _eutron_key.status == ST_OK;
}
///////////////////////////////////////////////////////////
// Ex-Golem utilities
///////////////////////////////////////////////////////////
static long GetRegistryString(HKEY key, const char* subkey, wxString& retstr)
{
HKEY hkey;
long retval = ::RegOpenKey(key, subkey, &hkey);
if (retval == ERROR_SUCCESS)
{
char retdata[_MAX_PATH];
long datasize = sizeof(retdata);
::RegQueryValue(hkey, NULL, retdata, &datasize);
::RegCloseKey(hkey);
retstr = retdata;
}
return retval;
}
wxString OsWin32_File2App(const char* filename)
{
wxString app;
if (*filename != '.')
{
char retdata[_MAX_PATH];
HINSTANCE hinst = ::FindExecutable(filename, ".", retdata);
DWORD* pinst = (DWORD*)hinst;
UINT err = LOWORD(pinst);
if (err > 32)
app = retdata;
}
if (app.IsEmpty())
{
wxString ext;
if (*filename == '.')
ext = filename;
else
wxSplitPath(filename, NULL, NULL, &ext);
ext.MakeLower();
wxString key;
if (GetRegistryString(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS)
{
key << "\\shell\\open\\command";
if (GetRegistryString(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS)
{
key.Replace("\"", " ");
int pos = key.Find("%1");
if (pos > 0)
key.Truncate(pos);
key.Trim(false); key.Trim(true);
app = key;
}
}
}
return app;
}
static bool IsInternetAddress(const char* filename)
{
wxString url(filename); url.MakeLower();
if (url.StartsWith("http:") || url.StartsWith("ftp:"))
return true;
if (url.Find("www.") >= 0)
return true;
wxString ext; wxFileName::SplitPath(url, NULL, NULL, NULL, &ext);
const char* const extensions[] = { "com","edu","gov","it","mil","net","org", NULL };
for (int e = 0; extensions[e]; e++)
if (ext == extensions[e])
return true;
return false;
}
wxIcon OsWin32_LoadIcon(const char* filename)
{
int icon_number = 0;
wxString ext;
if (*filename == '.' && strlen(filename) < _MAX_EXT)
ext = filename;
else
{
if (IsInternetAddress(filename))
ext = ".htm";
else
{
wxFileName::SplitPath(filename, NULL, NULL, NULL, &ext);
if (!ext.StartsWith("."))
ext.insert(0, ".");
}
}
ext.MakeLower();
wxString key;
if (ext != ".exe")
{
if (::GetRegistryString(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS)
{
key << "\\DefaultIcon";
if (::GetRegistryString(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS) // Windows 95 only
{
const int comma = key.find(',');
if (comma > 0)
{
icon_number = atoi(key.Mid(comma+1));
key.Truncate(comma);
}
}
else
{
key = OsWin32_File2App(filename);
if (key.IsEmpty())
key = OsWin32_File2App(".htm");
}
}
}
else
key = filename;
// Toglie eventuali parametri sulla riga si comando
const int ext_pos = key.Find(".exe");
if (ext_pos > 0)
key.Truncate(ext_pos+4);
wxString strFullName = key;
if (icon_number > 0)
strFullName << ";" << icon_number;
wxIcon ico(strFullName, wxBITMAP_TYPE_ICO);
return ico;
}
// action = [ open, edit, print ];
bool OsWin32_GotoUrl(const char* url, const char* action)
{
bool ok = false;
// Sarebbe meglio un flag esplicito, ma per ora attendiamo solo le stampe
if (action && wxStricmp(action, "print") == 0)
{
SHELLEXECUTEINFO sei; memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
sei.lpVerb = action;
sei.lpFile = url;
sei.nShow = SW_SHOWNORMAL;
if (::ShellExecuteEx(&sei))
{
if (sei.hProcess != NULL)
{
::WaitForSingleObject(sei.hProcess, 0);
::CloseHandle(sei.hProcess);
}
ok = true;
}
}
else
{
HINSTANCE hinst = ::ShellExecute(NULL, action, url, NULL, NULL, SW_SHOWNORMAL);
DWORD winst = DWORD((DWORD*)hinst); // Tutto 'sto giro per evitare un warning
ok = UINT(winst) > 32;
}
return ok;
}
/*
void OsWin32_SpoolNewLine(unsigned int hdc)
{
char output[4];
output[0] = 1; // Lunghezza: byte basso
output[1] = 0; // Lunghezza: byte alto
output[2] = '\n'; // A capo
output[3] = 0; // Shwarzenegger
::Escape((HDC)hdc, PASSTHROUGH, 0, output, NULL );
}
bool OsWin32_IsGenericTextOnly(void* data)
{
LPDEVMODE pdm = (LPDEVMODE)data;
if (pdm->dmYResolution == 6) // Win 9x only
return true;
if (strstr((const char*)pdm->dmDeviceName, "eneric") != NULL)
return true;
return false;
}
*/
#ifdef SPEECH_API
#include "\Programmi\Microsoft Speech SDK 5.1\Include\sapi.h"
static ISpVoice* m_pVoice = NULL;
bool OsWin32_InitializeSpeech()
{
if (m_pVoice == NULL)
CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&m_pVoice);
return m_pVoice != NULL;
}
void OsWin32_DeinitializeSpeech()
{
if (m_pVoice != NULL)
{
m_pVoice->WaitUntilDone(1000);
m_pVoice->Release();
m_pVoice = NULL;
}
}
bool OsWin32_Speak(const char* text, bool async)
{
if (m_pVoice != NULL)
{
WCHAR str[1204];
MultiByteToWideChar(CP_ACP, 0, text, -1, str, strlen(text)+1);
if (async)
m_pVoice->Speak(str, SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL);
else
m_pVoice->Speak(str, SPF_PURGEBEFORESPEAK, NULL);
return true;
}
return false;
}
#endif
int OsWin32_GetSessionId()
{
DWORD session = 0;
::ProcessIdToSessionId(::GetCurrentProcessId(), &session);
return (int)session;
}
bool OsWin32_IsWindowsServer()
{
return ::GetSystemMetrics(SM_REMOTESESSION) != 0;
}
void OsWin32_NumberFormat(char* str, int size)
{
static char decsep = '\0', thosep = '\0';
char buf[80] = "";
if (!decsep)
{
::GetNumberFormat(LOCALE_USER_DEFAULT, 0, "1936.27", NULL, buf, sizeof(buf));
decsep = buf[strlen(buf)-3];
thosep = buf[1] == '9' ? '\0' : buf[1];
}
if (str && *str)
{
int j = 0;
for (int i = 0; str[i]; i++)
{
switch (str[i])
{
case '.': buf[j++] = decsep; break;
case ',': break; // Ignore thousand separator
default : buf[j++] = str[i]; break;
}
}
buf[j] = '\0';
wxStrncpy(str, buf, size);
}
}