#include "wxinc.h" #include "wx/filename.h" #include "wx/paper.h" #include "oswin32.h" #include "xvt_menu.h" #include "xvt_help.h" #define WIN32_LEAN_AND_MEAN #define WIN32_EXTRA_LEAN #define STRICT #include #include #include 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 void TestPaper(PDEVMODE dm) { 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); } } void* OsWin32_ConvertFromNativePrinterInfo(void* hGlobal, unsigned int& nDataSize) { PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal); nDataSize = dm->dmSize+dm->dmDriverExtra; void* buff = new char[nDataSize]; TestPaper(dm); memcpy(buff, dm, nDataSize); ::GlobalUnlock(hGlobal); return buff; } void* OsWin32_ConvertToNativePrinterInfo(void* data, unsigned int nDataSize) { HGLOBAL hGlobal = ::GlobalAlloc(GHND, nDataSize); PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal); memcpy(dm, data, nDataSize); TestPaper(dm); ::GlobalUnlock(hGlobal); 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 *lpntme, // pointer to physical-font data unsigned long FontType, // type of font LPARAM lParam // application-defined data ) { XvtData* d = (XvtData*)lParam; int& n = d->cur_count; for (int i = n-1; i >= 0 && stricmp(d->families[i], plf->lfFaceName); i--); if (i < 0) // Controlla che il nome del font non ci sia gia' d->families[n++] = strdup(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 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 strcmp(s1, s2); } int OsWin32_EnumerateFamilies(unsigned int 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(unsigned int 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) { char name[256]; size = 0; if (printer == NULL || *printer == '\0') { if (::GetProfileString("windows", "device", ",,,", name, sizeof(name)) == 0) return NULL; char* comma = strchr(name, ','); if (comma) *comma = '\0'; } else strcpy(name, printer); LPDEVMODE pdm = NULL; HANDLE hPrinter; if (::OpenPrinter(name, &hPrinter, NULL) != 0) { size = ::DocumentProperties(0, hPrinter, name, NULL, NULL, 0); // Determina dimensione DEVMODE if (size > 0) { pdm = (LPDEVMODE)new char[size]; // Alloca un DEVMODE sufficientemente capiente memset(pdm, 0, size); ::DocumentProperties(0, hPrinter, name, pdm, NULL, DM_OUT_BUFFER); // Legge DEVMODE } else size = 0; ::ClosePrinter(hPrinter); } return pdm; } void OsWin32_SetCaptionStyle(unsigned int handle, bool set) { HWND hwnd = (HWND)handle; DWORD s = ::GetWindowLong(hwnd, GWL_STYLE); if (set) s |= WS_CAPTION; else s &= ~WS_CAPTION; #if !wxCHECK_VERSION(2,3,2) s |= WS_CLIPSIBLINGS; #endif ::SetWindowLong(hwnd, GWL_STYLE, s); } /////////////////////////////////////////////////////////// // Drawing bitmaps /////////////////////////////////////////////////////////// bool OsWin32_DrawBitmap(const wxBitmap& bmp, wxDC& dc, const wxRect& dst, const wxRect& src) { HBITMAP hBMP = (HBITMAP)bmp.GetHBITMAP(); bool ok = hBMP != NULL; if (ok) { HDC hDC = (HDC)dc.GetHDC(); HDC hMemDC = ::CreateCompatibleDC((HDC)NULL); const int nTechno = ::GetDeviceCaps(hDC, TECHNOLOGY); if (nTechno == DT_RASPRINTER) // Sto stampando! { const size_t bi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); BITMAPINFO* bi = (BITMAPINFO*)malloc(bi_size); memset(bi, 0, bi_size); BITMAPINFOHEADER& bih = bi->bmiHeader; bih.biSize = sizeof(bih); GetDIBits(hMemDC, hBMP, 0, bmp.GetHeight(), 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); const wxPalette* pPalette = bmp.GetPalette(); ::SetStretchBltMode(hDC, pPalette == NULL ? COLORONCOLOR : 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(unsigned int 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(unsigned int handle, const char* hlp, unsigned int cmd, const char* topic) { HWND hwnd = (HWND)handle; wxString str; switch(cmd) { case M_HELP_ONCONTEXT: str = FindHelpFile(topic); break; default: str = GetHelpDir(); str += "index.html"; break; } if (!str.IsEmpty() && wxFileExists(str)) { ::ShellExecute(hwnd, "open", str, NULL, NULL, SW_SHOWDEFAULT); return true; } OsWin32_Beep(1); return false; } bool OsWin32_TestNetworkVersion() { // Win95 only! char* VREDIRNAME = "vredir.vxd"; DWORD handle; DWORD dwSize = ::GetFileVersionInfoSize(VREDIRNAME,&handle); if (dwSize) { BYTE infoBuffer[512]; GetFileVersionInfo(VREDIRNAME,handle,dwSize,infoBuffer); long *language; void * lpBuffer; UINT Size; if (VerQueryValue(infoBuffer, "\\VarFileInfo\\Translation", (void **)&language, &Size) && Size!=0) { char szName[128]; sprintf(szName, "\\StringFileInfo\\%04x%04x\\FileVersion",LOWORD(*language), HIWORD(*language)); if (VerQueryValue(infoBuffer, szName, &lpBuffer, &Size) && Size!=0) { const char* s = (const char *)lpBuffer; for (int i = 0; i < 2; i++) s = strchr(s, '.')+1; int subver=atoi(s); if (subver >= 1111 && subver <= 1115) return false; } } } return true; } /////////////////////////////////////////////////////////// // Execute in window support /////////////////////////////////////////////////////////// struct TFindWindowInfo { HINSTANCE _instance; wxString _file; HWND _hwnd; TFindWindowInfo() : _instance(NULL), _hwnd(NULL) { } }; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { TFindWindowInfo* w = (TFindWindowInfo*)lParam; HINSTANCE inst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE); if (inst == w->_instance) { const LONG style = GetWindowLong(hwnd, GWL_STYLE); if ((style & WS_CAPTION) != 0) // Ha la caption? { w->_hwnd = hwnd; return FALSE; } return TRUE; } char str[256]; 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++) { wxThread::Sleep(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); } } /////////////////////////////////////////////////////////// // 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()) { char ext[_MAX_EXT]; if (*filename == '.') strcpy(ext, filename); else _splitpath(filename, NULL, NULL, NULL, ext); _strlwr(ext); 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) { const wxString url(filename); if (url.StartsWith("http:") || url.StartsWith("ftp:")) return TRUE; if (url.Find("www.") >= 0) return TRUE; char ext[_MAX_EXT]; _splitpath(filename, NULL, NULL, NULL, ext); _strlwr(ext); const char* const extensions[] = { "com","edu","gov","it","mil","net","org", NULL }; for (int e = 0; extensions[e]; e++) if (stricmp(ext, extensions[e]) == 0) return true; return false; } unsigned int OsWin32_LoadIcon(const char* filename) { unsigned int icon = 0; int icon_number = 0; char ext[_MAX_EXT]; if (*filename == '.' && strlen(filename) < _MAX_EXT) strcpy(ext, filename); else { if (IsInternetAddress(filename)) strcpy(ext, ".htm"); else _splitpath(filename, NULL, NULL, NULL, ext); } _strlwr(ext); 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); HINSTANCE hInst = NULL; HICON hicon = ::ExtractIcon(hInst, key, icon_number); if (hicon == NULL && icon_number != 0) hicon = ::ExtractIcon(hInst, key, 0); if (hicon != NULL) { DWORD dwicon = DWORD((DWORD*)hicon); icon = LOWORD(dwicon); } return icon; } bool OsWin32_GotoUrl(const char* url, const char* action) { // action = [ open, edit, print ]; HINSTANCE hinst = ShellExecute(NULL, action, url, NULL, NULL, SW_SHOWNORMAL); DWORD winst = DWORD((DWORD*)hinst); UINT error = UINT(winst); // Tutto 'sto giro per evitare un warning return error > 32; } // The function that prints one line without formfeed BOOL OsWin32_SpoolRow(const char* pData, unsigned int cbBytes, unsigned int nPrnDC) { int iEsc; BOOL bLocalDC = TRUE; // Assume we must create a DC (hPrnDC == NULL) HGLOBAL HMem; char * pOutput; HMem = GlobalAlloc(GPTR, sizeof(WORD) + cbBytes); if (HMem == NULL) return FALSE; pOutput = (char *)GlobalLock(HMem); if (pOutput == NULL) { GlobalFree(HMem); return FALSE; } BOOL bAbort = FALSE; // Haven't aborted yet // Make sure we have a printer DC HDC hPrnDC = (HDC)nPrnDC; bLocalDC = FALSE; // Use passed in hPrnDC if (!hPrnDC) return FALSE; /* if (bLocalDC) Escape (hPrnDC, SETABORTPROC, 0, (LPSTR) PrintAbortProc, NULL); */ // PASSTHROUGH is required. If driver doesn't support it, bail out. bAbort = FALSE; iEsc = PASSTHROUGH; if (!Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&iEsc, NULL)) { bAbort = TRUE; goto MPLCleanUp; } // Call EPSPRINTING if it is supported (that is, if we're on a // PostScript printer) to suppress downloading the pscript header. iEsc = EPSPRINTING; if (Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&iEsc, NULL)) { iEsc = 1; // 1 == enable PASSTHROUGH (disable pscript header) Escape(hPrnDC, EPSPRINTING, sizeof(int), (LPSTR)&iEsc, NULL); } // Start a Document Escape (hPrnDC, STARTDOC, 0, "", NULL); // Put data in the buffer and send to the printer *(WORD *)pOutput = cbBytes; memcpy( &(pOutput[sizeof(WORD)]), pData, cbBytes ); if( Escape( hPrnDC, PASSTHROUGH, 0, pOutput, NULL ) <= 0 ) bAbort = TRUE; // End the Document if (!bAbort) Escape(hPrnDC, ENDDOC, NULL, NULL, NULL); MPLCleanUp: // Done // Clean up if (bLocalDC) DeleteDC( hPrnDC ); GlobalUnlock(HMem); GlobalFree(HMem); return !bAbort; } #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