#include #include #include #include #if XVT_OS == XVT_OS_SCOUNIX extern "C" {long nap(long period);} #endif // FATAL_HOOK che intercetta errori fatali XVT // put breakpoint here void fatal_hook() { #ifdef DBG int dummy = 0; dummy++; #endif } #if XVTWS == WMWS short CHARX = 8; short CHARY = 8; short COLX = 8; short ROWY = 8; COLOR MASK_BACK_COLOR = COLOR_WHITE; COLOR NORMAL_COLOR = COLOR_BLACK; COLOR NORMAL_BACK_COLOR = COLOR_WHITE; COLOR DISABLED_COLOR = COLOR_GRAY; COLOR DISABLED_BACK_COLOR = COLOR_WHITE; COLOR FOCUS_COLOR = COLOR_BLACK; COLOR FOCUS_BACK_COLOR = COLOR_WHITE; #else #include HIDDEN COLORREF COLOR2RGB(COLOR c) { const byte red = byte((c >> 16) & 0xFF); const byte gre = byte((c >> 8) & 0xFF); const byte blu = byte(c & 0xFF); return RGB(red, gre, blu); } HIDDEN COLOR RGB2COLOR(COLORREF c) { const byte red = byte(c & 0xFF); const byte gre = byte((c >> 8) & 0xFF); const byte blu = byte((c >> 16) & 0xFF); return MAKE_COLOR(red, gre, blu); } extern "C" { WINDOW xvtwi_hwnd_to_window(HWND); #include } #include short COLX = 8; short ROWY = GetSystemMetrics(SM_CYSCREEN) / 25; short CHARX = 8; short CHARY = 14; HIDDEN LOGFONT NormalLogFont = { CHARY-3, CHARX, 0, 0, 300, FALSE, FALSE, FALSE, OEM_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL }; HIDDEN HFONT NormalFont = CreateFontIndirect(&NormalLogFont); COLOR MASK_BACK_COLOR = MAKE_COLOR(0,128,128); COLOR NORMAL_COLOR = COLOR_BLACK; COLOR NORMAL_BACK_COLOR = COLOR_LTGRAY; COLOR DISABLED_COLOR = COLOR_GRAY; COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR; HIDDEN COLORREF MaskColor = COLOR2RGB(MASK_BACK_COLOR); HIDDEN HBRUSH MaskBrush = CreateSolidBrush(MaskColor); HIDDEN COLORREF FocusForeColor = COLOR2RGB(COLOR_BLACK); // GetSysColor(COLOR_HIGHLIGHTTEXT); HIDDEN COLORREF FocusBackColor = COLOR2RGB(COLOR_CYAN); // GetSysColor(COLOR_HIGHLIGHT); HIDDEN HBRUSH FocusBrush = CreateSolidBrush(FocusBackColor); COLOR FOCUS_COLOR = RGB2COLOR(FocusForeColor); COLOR FOCUS_BACK_COLOR = RGB2COLOR(FocusBackColor); HIDDEN COLORREF NormalForeColor = COLOR2RGB(NORMAL_COLOR); HIDDEN COLORREF NormalBackColor = COLOR2RGB(NORMAL_BACK_COLOR); HIDDEN HBRUSH NormalBrush = CreateSolidBrush(NormalBackColor); HIDDEN BOOLEAN event_hook(HWND hwnd, UINT msg, UINT wparam, ULONG lparam, long* ret) { if (msg == WM_CTLCOLOR) { const word type = HIWORD(lparam); if (type == CTLCOLOR_LISTBOX || type == CTLCOLOR_EDIT || type == CTLCOLOR_MSGBOX) { HWND hwnd = LOWORD(lparam); HDC hdc = wparam; if (!IsWindowEnabled(hwnd)) // Campo disabilitato { if (type != CTLCOLOR_MSGBOX) { SetTextColor(hdc, NormalForeColor); SetBkColor(hdc, MaskColor); } *ret = MaskBrush; return TRUE; } bool focus = GetFocus() == hwnd; if (type != CTLCOLOR_MSGBOX) { SetTextColor(hdc, focus ? FocusForeColor : NormalForeColor); SetBkColor(hdc, focus ? FocusBackColor : NormalBackColor); } *ret = focus ? FocusBrush : NormalBrush; return TRUE; } } else if (msg == WM_COMMAND) { word notify = HIWORD(lparam); if (notify == EN_KILLFOCUS || notify == EN_SETFOCUS) { HWND hwnd = LOWORD(lparam); InvalidateRect(hwnd, NULL, TRUE); } } else if (msg == WM_KEYUP) { if (wparam == VK_PRIOR || wparam == VK_NEXT || wparam == VK_UP || wparam == VK_DOWN ) { char name[16]; GetClassName(hwnd, name, 15); if (stricmp(name, "Edit") == 0) { WINDOW w = xvtwi_hwnd_to_window(GetParent(hwnd)); switch(wparam) { case VK_PRIOR:wparam = K_PREV; break; case VK_NEXT :wparam = K_NEXT; break; case VK_UP :wparam = K_UP; break; case VK_DOWN :wparam = K_DOWN; break; default:wparam = 0; break; } if (wparam) dispatch_e_char(w, wparam); } } } return FALSE; } #endif RCT& resize_rect(short x, short y, short dx, short dy, WIN_TYPE wt, WINDOW parent) { static RCT r; if (parent != TASK_WIN) { if (get_window_type(parent) == W_PLAIN) // Mask with Toolbar { if (y >= 0) y++; if (x >= 0 && wt != WO_TE) { const int width = (int)get_value(NULL_WIN, ATTR_SCREEN_WIDTH); if (width > 640) x += (width-640) / (2*COLX); } } wt = WC_EDIT; } #if XVT_OS == XVT_OS_WIN switch (wt) { case WC_EDIT : r.left = (x+1)*COLX; r.top = y*ROWY; r.right = dx*CHARX; r.bottom = CHARY+3; if (dy > 1) r.bottom += ROWY*(dy-1); break; case W_DOC: r.left = x * COLX; r.top = y * ROWY; r.right = dx * CHARX; r.bottom = dy * CHARY; break; default: r.left = x * COLX; r.top = y * ROWY; r.right = (dx+2)*COLX; r.bottom = dy*ROWY-1; break; } #else r.left = x * CHARX; r.top = y * CHARY; r.right = dx * CHARX; r.bottom = dy * CHARY; #endif if (x < 0 || y < 0 || dx <= 0 || dy <= 0) { RCT pc; if (parent == NULL_WIN) parent = TASK_WIN; get_client_rect(parent, &pc); // Get parent window size const short MAXX = pc.right; const short MAXY = pc.bottom; if (x < 0) { x = -x; if (wt != WC_EDIT && x == 1) x = 11; if (x > 10) { const int num = x/10 -1; const int tot = x%10; const int spc = (MAXX - tot*r.right) / (tot+1); r.left = spc + num*(spc+r.right); } else r.left = MAXX - r.right - x*COLX; } if (y < 0) { y = -y; if (wt != WC_EDIT && y == 1) y = 11; if (y > 10) { const int num = y/10 -1; const int tot = y%10; const int spc = (MAXY - tot*r.bottom) / (tot+1); r.top = spc + num*(spc+r.bottom); } else r.top = MAXY - r.bottom - (y-1)*ROWY; } if (dx <= 0) r.right = MAXX + dx*COLX; else r.right += r.left; if (dy <= 0) r.bottom = MAXY + dy*ROWY; else r.bottom += r.top; } else { r.right += r.left; r.bottom += r.top; } return r; } void beep() { xvt_beep(); } /////////////////////////////////////////////////////////// // Event Handling /////////////////////////////////////////////////////////// class TEvent_manager { enum { MAX = 16 }; WINDOW _w[MAX]; EVENT _e[MAX]; int _begin, _end; public: TEvent_manager() : _begin(0), _end(0) {} void push(WINDOW win, const EVENT& event); void pop(); }; HIDDEN TEvent_manager EM; void TEvent_manager::push(WINDOW w, const EVENT& e) { _w[_end] = w; _e[_end] = e; _end = (++_end) % MAX; CHECKD(_end != _begin, "Too many events queued: max. ", MAX); } void TEvent_manager::pop() { if (_begin != _end) { const int i = _begin; _begin = (++_begin) % MAX; // Other events may occur! dispatch_event(_w[i], &_e[i]); } } void do_events() { process_events(); EM.pop(); #if XVT_OS == XVT_OS_SCOUNIX nap(20); #endif } KEY e_char_to_key(const EVENT* ep) { CHECK(ep->type == E_CHAR, "Can't convert to key a Non-E_CHAR event"); KEY key = ep->v.chr.ch; if (key < K_INS || key > K_HELP) { if (ep->v.chr.shift && !isprint(key)) key += K_SHIFT; if (key >= ' ' && ep->v.chr.control) key += K_CTRL; } return key; } void dispatch_e_char(WINDOW win, KEY key) { EVENT e; e.type = E_CHAR; if (key > 10000) { e.v.chr.control = TRUE; key -= K_CTRL; } else e.v.chr.control = FALSE; if (key > 1000) { e.v.chr.shift = TRUE; key -= K_SHIFT; } else e.v.chr.shift = FALSE; e.v.chr.ch = short(key); // dispatch_event(win, &e); EM.push(win, e); } void dispatch_e_scroll(WINDOW win, KEY key) { EVENT e; EVENT_TYPE& t = e.type; SCROLL_CONTROL& w = e.v.scroll.what; short& p = e.v.scroll.pos; w = SC_NONE; switch(key) { case K_HOME: t = E_HSCROLL; w = SC_THUMB; p = 0; break; case K_LHOME: t = E_VSCROLL; w = SC_THUMB; p = 0; break; case K_UP: t = E_VSCROLL; w = SC_LINE_UP; break; case K_DOWN: t = E_VSCROLL; w = SC_LINE_DOWN; break; case K_BTAB: t = E_HSCROLL; w = SC_PAGE_UP; break; case K_TAB: t = E_HSCROLL; w = SC_PAGE_DOWN; break; case K_PREV: t = E_VSCROLL; w = SC_PAGE_UP; break; case K_NEXT: t = E_VSCROLL; w = SC_PAGE_DOWN; break; case K_LEFT: t = E_HSCROLL; w = SC_LINE_UP; break; case K_RIGHT: t = E_HSCROLL; w = SC_LINE_DOWN; break; default: break; }; if (w != SC_NONE) dispatch_event(win, &e); } void customize_controls(bool on) { #if XVTWS == WMWS if (on) { // set_value(NULL_WIN,ATTR_CH_SHADOW,XVT_CH_SHADOW_WINDOW|XVT_CH_SHADOW_DIALOG); set_value(NULL_WIN, ATTR_CH_TOGGLE_COMBO, (long)K_F9); } #endif #if XVT_OS == XVT_OS_WIN if (on) { const long style = WSF_ICONIZABLE | WSF_SIZE | WSF_CLOSE | WSF_MAXIMIZED; set_value(NULL_WIN,ATTR_WIN_PM_TWIN_STARTUP_STYLE, style); set_value(NULL_WIN,ATTR_WIN_PM_DRAWABLE_TWIN, TRUE); set_value(NULL_WIN,ATTR_EVENT_HOOK, (long)event_hook); } else { DeleteObject(NormalFont); DeleteObject(MaskBrush); DeleteObject(NormalBrush); DeleteObject(FocusBrush); free_controls_bmp(); } #endif if (on) set_value(NULL_WIN,ATTR_FATAL_ERR_HANDLER, (long)fatal_hook); } void xvt_set_font(WINDOW win, int family, int style, int dim) { CHECK(win > 0, "Can't set the font in a NULL window"); #if XVT_OS == XVT_OS_WIN if (dim < 1) { NormalLogFont.lfHeight = (style & FS_BOLD) ? CHARY-1 : CHARY-3; NormalLogFont.lfWidth = (style & FS_BOLD) ? CHARX-1 : CHARX; NormalLogFont.lfWeight = (style & FS_BOLD) ? 600 : 300; NormalLogFont.lfItalic = (style & FS_ITALIC) ? TRUE : FALSE; set_value(NULL_WIN, ATTR_WIN_PM_LOGFONT, long(&NormalLogFont)); set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, TRUE); win_set_font(win, NULL, FALSE); set_value(NULL_WIN, ATTR_WIN_PM_USERFONT, FALSE); return; } #endif FONT font; select_font(family, style, dim < 1 ? CHARY : dim, &font); win_set_font(win, &font, FALSE); } WINDOW xvt_create_window(WIN_TYPE wt, short x, short y, short dx, short dy, const char* caption, WINDOW parent, long flags, EVENT_HANDLER eh, long app_data ) { RCT& rect = resize_rect(x, y, dx, dy, wt, parent); if (wt == WD_MODAL) wt = W_DOC; WINDOW win = create_window(wt, &rect, (char*)caption, 0, parent, flags, EM_ALL, eh, app_data); CHECKD(win, "Can't create a window: XVT error ", get_xvterrno()); #if XVT_OS == XVT_OS_WIN static bool set = TRUE; if (set) { HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); word style = GetClassWord(hwnd, GCW_STYLE); style |= CS_BYTEALIGNCLIENT | CS_SAVEBITS; SetClassWord(hwnd, GCW_STYLE, style); set = FALSE; } #endif return win; } WINDOW xvt_create_control(WIN_TYPE wt, short x, short y, short dx, short dy, const char* caption, WINDOW parent, long flags, long app_data, int id) { RCT r = resize_rect(x, y, dx, dy, wt, parent); WINDOW win = NULL_WIN; #if XVT_OS == XVT_OS_WIN if (wt == WC_CHECKBOX) win = xvt_create_checkbox(r.left, r.top, r.right, r.bottom, caption, parent, flags, app_data, id); if (wt == WC_RADIOBUTTON) win = xvt_create_radiobutton(r.left, r.top, r.right, r.bottom, caption, parent, flags, app_data, id); if (wt == WC_PUSHBUTTON) win = xvt_create_pushbutton(r.left, r.top, r.right, r.bottom, caption, parent, flags, app_data, id); if (wt == WC_GROUPBOX) { win = xvt_create_groupbox(r.left, r.top, r.right, r.bottom, caption, parent, flags, app_data, id); } if (wt == WC_TEXT) { win = xvt_create_text(r.left, r.top, r.right, r.bottom, caption, parent, flags, app_data, id); } #endif if (win == NULL_WIN) { if (wt == WC_PUSHBUTTON) { if (dy == 2) r.bottom -= ROWY; if (id == DLG_F9) { wt = WC_TEXT; r.right = r.left+CHARX; caption = "*"; } else if (*caption == '#') caption = ""; } while (*caption == '@') caption += 2; win = create_control(wt, &r, (char*)caption, parent, flags, app_data, id); } #ifdef DBG if (win == NULL_WIN) fatal_box("Can't create control %d: XVT error %d", id, get_xvterrno()); #endif #if XVT_OS == XVT_OS_WIN if (wt == WC_EDIT || wt == WC_LISTBUTTON) { HWND hwnd = (HWND)get_value(win, ATTR_NATIVE_WINDOW); SendMessage(hwnd, WM_SETFONT, NormalFont, TRUE); } #endif return win; } const char* xvt_get_title(WINDOW win) { #if XVTWS == WINWS TControl* c = TControl::WINDOW2TControl(win); return c->caption(); #else static char title[81]; get_title(win, title, 80); return title; #endif } void xvt_set_front_control(WINDOW win) { #if XVTWS == WINWS TControl* c = TControl::WINDOW2TControl(win); c->focus(TRUE); #endif set_front_window(win); } void xvt_enable_control(WINDOW win, bool on) { #if XVTWS == WINWS TControl* c = TControl::WINDOW2TControl(win); c->enable(on); #else enable_window(win, on); #endif } void xvt_check_box(WINDOW win, bool on) { #if XVTWS == WMWS win_check_box(win, on); #else TControl* c = (TControl*)TControl::WINDOW2TControl(win); c->check(on); #endif } bool xvt_get_checked_state(WINDOW win) { #if XVTWS == WMWS return get_checked_state(win); #else TControl* c = TControl::WINDOW2TControl(win); return c->checked(); #endif } void xvt_check_radio_button(WINDOW win, const WINDOW* ctls, int count) { #if XVTWS == WMWS win_check_radio_button(win, (WINDOW*)ctls, count); #else for (int i = 0; i < count; i++) xvt_check_box(ctls[i], ctls[i] == win); #endif } int xvt_get_checked_radio(const WINDOW* ctls, int count) { for (int i = 0; i < count; i++) if (xvt_get_checked_state(ctls[i])) return i; #ifdef DBG error_box("Accendi la tua radio per favore!"); #endif return 0; } /////////////////////////////////////////////////////////// // Gestione Status bar /////////////////////////////////////////////////////////// HIDDEN WINDOW statbar = NULL_WIN; WINDOW xvt_create_statbar() { CHECK(statbar == NULL_WIN, "Onli uan stabar, plis"); #if XVT_OS == XVT_OS_WIN const int prop_count = 4; char* prop_list[prop_count+1] = { "", "HEIGHT=23", "TASK_WIN=TRUE", "FIELD_OFFSET=24", NULL }; statbar = statbar_create(-1, 0, 0, 1, 1, prop_count, prop_list, TASK_WIN, 0, 0, NULL); xvt_set_font(statbar, FF_FIXED, 0); DRAW_CTOOLS ct; win_get_draw_ctools(statbar, &ct); #ifndef XVT_R3_API statbar_set_font(statbar, &ct.font); #endif #endif return statbar; } void xvt_statbar_set(const char* text) { TString80 t(text); const TDate oggi(TODAY); t << '\t' << oggi.string() << " - " << MainApp()->title(); #if XVT_OS == XVT_OS_WIN statbar_set_title(statbar, (char*)(const char*)t); #endif } void xvt_statbar_refresh() { invalidate_rect(statbar, NULL); } /////////////////////////////////////////////////////////// // Test menu /////////////////////////////////////////////////////////// HIDDEN bool test_menu_tag(MENU_ITEM* mi, MENU_TAG tag) { CHECK(mi, "Can't test NULL MENU_ITEM"); if (mi->tag == tag) return TRUE; if (mi->child != NULL) return test_menu_tag(mi->child, tag); return FALSE; } bool xvt_test_menu_tag(MENU_TAG tag) { MENU_ITEM *mi = win_menu_fetch(TASK_WIN); const bool ok = test_menu_tag(mi, tag); menu_free(mi); return ok; } // translation of graphics attributes from codes chars // used by print functions COLOR trans_color(char c) { switch (c) { case 'n': return COLOR_BLACK; break; case 'r': return COLOR_RED; break; case 'g': return COLOR_GREEN; break; case 'b': return COLOR_BLUE; break; case 'c': return COLOR_CYAN; break; case 'y': return COLOR_YELLOW; break; case 'v': return COLOR_MAGENTA; break; case 'w': return COLOR_WHITE; break; case 'm': return MASK_BACK_COLOR; break; case 'd': return COLOR_DKGRAY; break; case 'l': return COLOR_LTGRAY; break; case 'k': return COLOR_GRAY; break; default: CHECK(0,"trans_color: Undefined color"); return -1; break; } } PAT_STYLE trans_brush(char p) { switch (p) { case 'n' : return PAT_NONE; break; case 'h' : return PAT_HOLLOW; break; case 's' : return PAT_SOLID; break; case '-' : return PAT_HORZ; break; case '|' : return PAT_VERT; break; case '/' : return PAT_FDIAG; break; case '\\': return PAT_BDIAG; break; case 'X' : return PAT_DIAGCROSS; break; case '+' : return PAT_CROSS; break; default: CHECK(0,"trans_brush: Undefined pattern"); return PAT_NONE; break; } } PEN_STYLE trans_pen(char p) { switch (p) { case 'n' : return P_SOLID; break; case '.' : return P_DOT; break; case '-' : return P_DASH; break; default: CHECK(0,"trans_pen: Undefined pattern"); return P_SOLID; break; } }