#define XVT_INCL_NATIVE #define XI_INTERNAL #include #include #include #include #include #include #ifndef ATTR_WIN_USE_CTL3D #include #endif #include #include #include #include #include #include extern "C" { WINDOW xvtwi_hwnd_to_window(HWND); } /////////////////////////////////////////////////////////// // Win16 event hook /////////////////////////////////////////////////////////// const word WM_WAKEUP = RegisterWindowMessage("WAKEUP"); HTASK _waiting_for = 0xFFFF; extern "C" { WINDOW xvtwi_hwnd_to_window(HWND); } HIDDEN BOOLEAN event_hook(HWND hwnd, UINT msg, UINT wparam, ULONG lparam, long* ret) { switch(msg) { #ifndef ATTR_WIN_USE_CTL3D case WM_SYSCOLORCHANGE: Ctl3dColorChange(); break; #endif case WM_MENUCHAR: if (wparam > ' ' && wparam <= 'z') { WINDOW win = cur_win(); if (win != NULL_WIN) { const KEY key = toupper(wparam)+K_CTRL; dispatch_e_char(win, key); *ret = 2 << 16; } } break; case WM_KEYDOWN: if (wparam == VK_F1) { if ((lparam & (1<<29)) == 0) // Il tasto alt non e' premuto { KEY k = K_F1; int sc = GetAsyncKeyState(VK_CONTROL); // Stato del tasto control if (sc & 0x8000) k += K_CTRL; int ss = GetAsyncKeyState(VK_SHIFT); // Stato del tasto shift if (ss & 0x8000) k += K_SHIFT; WINDOW win = cur_win(); if (win != NULL_WIN) dispatch_e_char(win, k); } } break; case WM_DROPFILES: if (cur_win() != NULL_WIN) { WINDOW win = xvtwi_hwnd_to_window(hwnd); if (win != NULL) { EVENT e; e.type = E_USER; e.v.user.id = E_DROP_FILES; e.v.user.ptr = (void*)wparam; xvt_win_dispatch_event(win, &e); } } break; default: if (msg == WM_WAKEUP) { if (wparam == _waiting_for) _waiting_for = 0xFFFF; } break; } return TRUE; // Continua col processo normale } /////////////////////////////////////////////////////////// // Operating system dependent functions /////////////////////////////////////////////////////////// bool os_allow_another_instance() { NFCHECK("Bisogna implementare la allow_another_instance"); return TRUE; } COLOR os_choose_color(COLOR col, WINDOW win) { CHOOSECOLOR cc; memset(&cc, 0, sizeof(cc)); // Azzera struttura if (win == NULL_WIN) win = TASK_WIN; // Sceglie una finestra valida HWND hwnd = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); HDC hdc = GetDC(hwnd); // Legge la palette di sistema PALETTEENTRY* pe = NULL; int max_entries = 0; if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) { max_entries = GetDeviceCaps(hdc, SIZEPALETTE); pe = new PALETTEENTRY[max_entries]; GetSystemPaletteEntries(hdc, 0, max_entries, pe); } ReleaseDC(hwnd, hdc); // Definisce i 16 colori customizzabili unsigned long custom_colors[16]; for (int c = 0; c < 16; c++) { if (pe) { const PALETTEENTRY& e = pe[c < 8 ? c : max_entries - 16 + c]; custom_colors[c] = RGB(e.peRed, e.peGreen, e.peBlue); } else { const unsigned char val = (c & 0x8) ? 255 : 127; const unsigned char red = (c & 0x1) ? val : 0; const unsigned char green = (c & 0x2) ? val : 0; const unsigned char blue = (c & 0x4) ? val : 0; custom_colors[c] = RGB(red, green, blue); } } if (pe) { delete pe; pe = NULL; } cc.lStructSize = sizeof(cc); // Setta dimensioni cc.hwndOwner = hwnd; // Setta finestra padre cc.rgbResult = RGB(XVT_COLOR_GET_RED(c), XVT_COLOR_GET_GREEN(c), XVT_COLOR_GET_BLUE(c)); cc.lpCustColors = custom_colors; // Fissa colori custom cc.Flags = CC_RGBINIT; // Usa col come primo colore if (ChooseColor(&cc) != 0) col = RGB2COLOR(GetRValue(cc.rgbResult), GetGValue(cc.rgbResult), GetBValue(cc.rgbResult)); else col = COLOR_INVALID; return col; } bool os_deny_another_instance() { return TRUE; } bool os_destroy_native_icon(unsigned icon) { return DestroyIcon((HICON)icon) != 0; } void os_draw_native_icon(WINDOW win, const RCT& rct, unsigned icon) { HDC hdc = (HDC)xvt_vobj_get_attr(win, ATTR_NATIVE_GRAPHIC_CONTEXT); int x = (rct.right + rct.left - 32) / 2; int y = (rct.bottom + rct.top - 32) / 2; DrawIcon(hdc, x, y, (HICON)icon); } unsigned long os_get_free_memory() { return GetFreeSpace(0); } bool os_is_removable_drive(const char* path) { bool yes = isalpha(path[0]) && path[1] == ':'; if (yes) yes = GetDriveType(toupper(path[0]) - 'A') == DRIVE_REMOVABLE; return yes; } bool os_is_network_drive(const char* path) { bool yes = isalpha(path[0]) && path[1] == ':'; if (yes) yes = GetDriveType(toupper(path[0]) - 'A') == DRIVE_REMOTE; return yes; } bool os_is_fixed_drive(const char* path) { bool yes = isalpha(path[0]) && path[1] == ':'; if (yes) yes = GetDriveType(toupper(path[0]) - 'A') == DRIVE_FIXED; return yes; } bool os_test_disk_free_space(const char* path, unsigned long filesize) { int disk = 0; if (path && *path && path[1] == ':') { const char letter = toupper(path[0]); disk = letter - 'A' + 1; } bool space_ok = FALSE; struct _diskfree_t drive; if (_dos_getdiskfree(disk, &drive) == 0) { const unsigned requested_clusters = unsigned(filesize / drive.sectors_per_cluster / drive.bytes_per_sector) + 1; space_ok = requested_clusters <= drive.avail_clusters; } return space_ok; } unsigned long os_get_disk_size(const char* path) { int disk = 0; if (path && *path && path[1] == ':') { const char letter = toupper(path[0]); disk = letter - 'A' + 1; } unsigned long bytes = 0; struct _diskfree_t drive; if (_dos_getdiskfree(disk, &drive) == 0) { bytes = drive.total_clusters; bytes *= drive.sectors_per_cluster; bytes *= drive.bytes_per_sector; } return bytes; } void os_exec_help_command(MENU_TAG tag, const char* key) { TFilename hlp("prassi.hlp"); TString mod(key); if (mod.not_empty()) { mod.cut(2); mod.lower(); if (mod != "ba") hlp.insert(mod, 0); } else { if (tag == M_HELP_ONCONTEXT) tag = M_HELP_CONTENTS; } HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); switch(tag) { case M_HELP_CONTENTS: WinHelp(hwnd, hlp, HELP_CONTENTS, 0); break; case M_HELP_SEARCH: WinHelp(hwnd, hlp, HELP_PARTIALKEY, (DWORD)""); break; case M_HELP_HELPONHELP: WinHelp(hwnd, hlp, HELP_HELPONHELP, 0); break; case M_HELP_ONCONTEXT: if (hlp.exist()) { struct MULTIGUY { UINT mkSize; BYTE mkKeylist; char mkKeyphrase[16]; } mk; mk.mkSize = sizeof(MULTIGUY); mk.mkKeylist = 'M'; strcpy(mk.mkKeyphrase, key); WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); } break; default: break; } } int os_execute(const TFilename& path, bool sync, bool iconizetask, bool showchild) { word exitcode = ::WinExec(path, showchild ? SW_SHOWNORMAL : SW_HIDE); if (exitcode < 32) { switch (exitcode) { case 0: exitcode = 8; case 8: error_box("Memoria o risorse insufficienti per eseguire '%s'", (const char*)path); break; default: error_box("Impossibile eseguire '%s': %d", (const char*)path, exitcode); break; } return exitcode; } if (sync) { bool was_maximized = FALSE; if (iconizetask) { HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); if (hwnd) { was_maximized = IsZoomed(hwnd); TTemp_window tw(TASK_WIN); tw.iconize(); tw.deactivate(); } } const char* szModule = path.name(); HTASK child = NULL; TASKENTRY te; te.dwSize = sizeof(TASKENTRY); for (bool ok = TaskFirst(&te); ok; ok = TaskNext(&te)) if (te.hInst == (HINSTANCE)exitcode || stricmp(te.szModule, szModule) == 0) { child = te.hTask; break; } // Warning! child could be NULL if you run that beast called Foxpro _waiting_for = child; for (byte i = 0; _waiting_for == child; i++) { // Esegue il controllo solo ogni 256 cicli if (i == 0 && ok && TaskFindHandle(&te, child) == FALSE) { _waiting_for = 0xFFFF; // Annulla attesa del processo break; } xvt_app_process_pending_events(); } if (iconizetask && TASK_WIN) { TTemp_window tw(TASK_WIN); if (was_maximized) tw.maximize(); // Non e' piu' detto che sia massimizzata! else os_restore_window(tw.win()); tw.activate(); } xvt_app_process_pending_events(); } xvt_statbar_refresh(); return 0; } bool os_spawn_by_menu() { TASKENTRY te; te.dwSize = sizeof(TASKENTRY); HTASK ct = GetCurrentTask(); TaskFindHandle(&te, ct); TaskFindHandle(&te, te.hTaskParent); bool yes = stricmp(te.szModule, "BA0") == 0 || #ifdef DBG stricmp(te.szModule, "CVW4") == 0 || stricmp(te.szModule, "MSVC") == 0 || #endif stricmp(te.szModule, "Explorer") == 0 || stricmp(te.szModule, "PROGMAN") == 0; return yes; } int os_get_printer_names(TToken_string& t) { char* buf = t.get_buffer(4096); // ammazzao' GetProfileString ("devices", NULL, "", buf, t.size()); for (int i = 0; i < t.size(); i++) { if (buf[i] == '\0') { if (buf[i+1] != '\0') buf[i] = '|'; else break; } } return t.items(); } bool os_set_default_printer(const char* name) { CHECK(name && *name > ' ', "Null printer name"); TString pdev(name); if (pdev.find(',') < 0) { TString szDevice(256); GetProfileString ("devices", pdev, "", szDevice.get_buffer(), szDevice.size()); pdev << ',' << szDevice; } bool ok = WriteProfileString("windows", "device", pdev) != 0; return ok; } bool os_get_default_printer(TString& name) { char* buf = name.get_buffer(128); bool ok = GetProfileString ("windows", "device", ",,,", buf, name.size()) != 0; return ok; } bool os_get_image_editor_path(TFilename& name) { // where is EasyDoc installed? GetPrivateProfileString("Easydoc", "Path", "\\EASYDOC", name.get_buffer(), name.size(), "EasyDoc.ini"); // You're unlucky there is no EasyDoc if (name.empty()) return FALSE; // paste EasyDoc path name.add("easydoc.exe"); // is EasyDoc present? bool ok = name.exist(); return ok; } os_type os_get_type() { const DWORD winflags = GetWinFlags(); if (winflags & 0x4000) return os_WindowsNT; const DWORD osver = GetVersion(); const DWORD winver = LOWORD(osver); const BYTE majwinver = LOBYTE(winver); const BYTE minwinver = HIBYTE(winver); if (majwinver == 3 && minwinver == 95) { const DWORD dosver = HIWORD(osver); const BYTE majdosver = LOBYTE(dosver); // Should be 7 anyway const BYTE mindosver = HIBYTE(dosver); return (majdosver > 7 || (majdosver == 7 && mindosver >= 10)) ? os_Windows98 : os_Windows95; } else { if (majwinver == 4) return os_WindowsME; } return os_Windows; } void os_post_menu_event(WINDOW win, MENU_TAG tag) { HWND w = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); PostMessage(w, WM_COMMAND, tag, 0L); } void os_set_event_hook() { xvt_vobj_set_attr(NULL_WIN, ATTR_EVENT_HOOK, (long)event_hook); #ifdef ATTR_WIN_USE_CTL3D xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_USE_CTL3D, TRUE); #endif long twin_style = WSF_ICONIZABLE | WSF_CLOSE | WSF_SIZE; const int scx = GetSystemMetrics(SM_CXSCREEN); const int scy = GetSystemMetrics(SM_CYSCREEN); static RCT rct; if (scx <= 640 && os_get_type() >= os_Windows95) { const int bcx = GetSystemMetrics(SM_CXFRAME); const int bcy = GetSystemMetrics(SM_CYFRAME); rct.left = -bcx; rct.top = GetSystemMetrics(SM_CYCAPTION)-bcy-1; rct.right = scx+bcx; rct.bottom = scy+bcy; xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); } else { TConfig cfg(CONFIG_USER, "Colors"); const int res = cfg.get_int("Resolution"); if (res >= 640 && res < scx) { const int width = res + 2*GetSystemMetrics(SM_CXFRAME); const int height = (res * 3) / 4 + 2*GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION) - 1; const int deltax = (scx - width) / 2; const int deltay = (scy - height) / 2; rct.left = deltax; rct.top = deltay; rct.right = deltax + width; rct.bottom = deltay + height; xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_RCT, long(&rct)); } else twin_style |= WSF_MAXIMIZED; } xvt_vobj_set_attr(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, twin_style); } void os_wake_up_caller() { const HTASK ht = GetCurrentTask(); // SendMessage(HWND_BROADCAST, WM_WAKEUP, (WPARAM)ht, 0L); PostMessage(HWND_BROADCAST, WM_WAKEUP, (WPARAM)ht, 0L); HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); WinHelp(hwnd, "prassi.hlp", HELP_QUIT, 0L); // do_events(); non si puo' fare qui } bool os_file_exist(const char* file) { HFILE hf = _lopen(file, READ); bool ok = hf != HFILE_ERROR; if (ok) _lclose(hf); return ok; } bool os_open_spool_row(const char* device) { return TRUE; } bool os_spool_row(const char* str) { return SpoolRow((char*)str, strlen(str)) != 0; } bool os_close_spool_row() { return TRUE; } void os_iconize_window(WINDOW win) { HWND hwnd = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_MINIMIZE); } void os_maximize_window(WINDOW win) { HWND hwnd = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); HWND twin = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW); if (hwnd != twin) { HWND pare = GetParent(hwnd); RECT rct; GetClientRect(pare, &rct); if (pare == twin) rct.bottom -= 24; SetWindowPos(hwnd, pare, rct.left, rct.top, rct.right, rct.bottom, SWP_NOZORDER); } else ShowWindow(hwnd, SW_SHOWMAXIMIZED); } void os_restore_window(WINDOW win) { HWND hwnd = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_NORMAL); } bool os_dongle_server_running() { ATOM a = GlobalFindAtom("DONGLE_SERVER_ATOM"); return a != 0; } HIDDEN const char* _file_to_find = NULL; struct TFindWindowInfo { HINSTANCE _instance; TFilename _file; HWND _hwnd; TFindWindowInfo() : _instance(NULL), _hwnd(NULL) { } }; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { TFindWindowInfo* w = (TFindWindowInfo*)lParam; HINSTANCE inst = GetWindowWord(hwnd, GWW_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; } TString256 str; GetWindowText(hwnd, str.get_buffer(), str.size()); str.upper(); if (str.find(w->_file) >= 0) { w->_hwnd = hwnd; return FALSE; } return TRUE; } unsigned long os_execute_in_window(const TFilename& path, WINDOW win) { const word exitcode = WinExec(path, SW_SHOWNORMAL); if (exitcode < 32) return 0; TFindWindowInfo w; w._instance = exitcode; const int space = path.find(' '); if (space > 0) w._file = path.mid(space+1); else w._file = path; w._file = w._file.name(); w._file.ext(""); w._file.upper(); const clock_t start = clock(); while (w._hwnd == NULL && (clock() - start) < 10*CLOCKS_PER_SEC) { xvt_app_process_pending_events(); FARPROC farproc = MakeProcInstance(FARPROC(EnumWindowsProc), NULL); EnumWindows(farproc, LPARAM(&w)); FreeProcInstance(farproc); } if (w._hwnd != NULL) // L'ho trovata! { RCT rct; xvt_vobj_get_client_rect(win, &rct); HWND nat = (HWND)xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); SetParent(w._hwnd, nat); // LONG style = GetWindowLong(w._hwnd, GWL_STYLE); // style |= WS_CHILD; // SetWindowLong(w._hwnd, GWL_STYLE, style); 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, nat, -fx, -fy-cy, rct.right+2*fx, rct.bottom+cy+2*fy, SWP_NOZORDER); } return w._hwnd; } bool os_test_network_version() { if (os_get_type() == os_Windows95) { const char* VREDIRNAME = "vredir.vxd"; DWORD handle; BYTE infoBuffer[512]; DWORD dwSize = GetFileVersionInfoSize(VREDIRNAME,&handle); if (dwSize) { GetFileVersionInfo(VREDIRNAME,handle,dwSize,infoBuffer); long *language; void * lpBuffer; char szName[128]; UINT Size; if (VerQueryValue(infoBuffer, "\\VarFileInfo\\Translation", (void **)&language, &Size) && Size!=0) { sprintf(szName, "\\StringFileInfo\\%04x%04x\\FileVersion",LOWORD(*language), HIWORD(*language)); if (VerQueryValue(infoBuffer, szName, &lpBuffer, &Size) && Size!=0) { TToken_string v((const char *)lpBuffer,'.'); int subver=atoi(v.get(2)); if (subver >=1111 && subver <=1115) return error_box("La versione %s del driver di rete '%s' contiene un errore riconosciuto da Microsoft.\nConsultare il vostro tecnico per aggiornare il sistema operativo.",(const char *)lpBuffer, VREDIRNAME); else return TRUE; } } } //VREDIR.VXD puo' non esistere; inutile la segnalazione seguente. //message_box("Impossibile determinare la versione del driver di rete '%s'",VREDIRNAME); } return TRUE; } void os_sleep(long m) { clock_t fine = ((m * CLOCKS_PER_SEC)/1000) + clock(); while (fine > clock()) do_events(); } void os_beep(int severity) { switch (severity) { case 0: MessageBeep(MB_OK); break; case 1: MessageBeep(MB_ICONEXCLAMATION); break; default: MessageBeep(MB_ICONSTOP); break; } }