#include #include #include #include #include #include #include #include #include "int33.h" #include "utils.h" #include "dlog.h" #define DPREFIX "moustest: " enum T_COLOR { T_BLACK = 0, T_BLUE = 1, T_GREEN = 2, T_CYAN = 3, T_RED = 4, T_MAGENTA = 5, T_BROWN = 6, T_WHITE = 7, T_BRIGHT = 8 }; bool main_exiting = false; uint16_t driver_caps; uint16_t num_buttons; uint16_t num_wheels; struct videoconfig vidconf; bool vidconf_is_graphics, vidconf_is_color; struct textsettings txtconf; short ctexttop, ctextbot, ctextleft, ctextright; struct rccoord ctextpos; const short ctextcolor = T_WHITE; const long ctextbg = _BLACK; typedef enum gui_palette { GUI_COLOR_CONSOLE, GUI_COLOR_BAR, GUI_COLOR_WINDOW, GUI_COLOR_LIST, GUI_COLOR_LIST_SEL, GUI_COLOR_COUNT } gui_color; long gui_bg_color[GUI_COLOR_COUNT]; int gui_text_color[GUI_COLOR_COUNT]; void gui_print(gui_color color, const char *str) { if (vidconf_is_graphics) { const int char_width = vidconf.numxpixels / vidconf.numtextcols; const int char_height = vidconf.numypixels / vidconf.numtextrows; const int text_chars = strlen(str); const int text_width = text_chars * char_width; const int text_height = char_height; // No multiline support. struct rccoord textpos = _gettextposition(); const int text_x = char_width * (textpos.col - 1); const int text_y = char_height * (textpos.row - 1); _setcolor(gui_bg_color[color]); _rectangle(_GFILLINTERIOR, text_x, text_y, text_x + text_width, text_y + text_height); _setcolor(gui_text_color[color]); _moveto(text_x, text_y); _outgtext((char*) str); textpos.col += text_chars; _settextposition(textpos.row, textpos.col); } else { _settextcolor(gui_text_color[color]); _setbkcolor(gui_bg_color[color]); _outtext((char*) str); } } void gui_printf(gui_color color, const char *format, ...) { va_list arglist; char buffer[120]; va_start(arglist, format); vsprintf(buffer, format, arglist); va_end(arglist); gui_print(color, buffer); } void gui_draw_textrectangle(short top, short left, short bottom, short right, gui_color color) { const short char_width = vidconf.numxpixels / vidconf.numtextcols; const short char_height = vidconf.numypixels / vidconf.numtextrows; short x1 = (left - 1) * char_width; short y1 = (top - 1) * char_height; short x2 = right * char_width; short y2 = bottom * char_height; _setviewport(x1, y1, x2, y2); _setcolor(gui_bg_color[color]); _rectangle(_GFILLINTERIOR, 0, 0, x2 - x1, y2 - y1); } void gui_draw_textwindow(int top, int left, int bottom, int right, gui_color color) { _settextwindow(top, left, bottom, right); _settextcolor(gui_text_color[color]); // Not really required here if (vidconf_is_graphics) { gui_draw_textrectangle(top, left, bottom, right, color); } else { _setbkcolor(gui_bg_color[color]); _clearscreen(_GWINDOW); } } void gui_draw_title() { const int cols = vidconf.numtextcols; gui_draw_textwindow(1, 1, 1, cols, GUI_COLOR_BAR); gui_print(GUI_COLOR_BAR, "MOUSTEST ESC to exit, 'm' mode, 'r' reset, 's' show, 'h' hide"); } void gui_draw_status() { const int statusrow = vidconf.numtextrows; const int cols = vidconf.numtextcols; gui_draw_textwindow(statusrow, 1, statusrow, cols, GUI_COLOR_BAR); } void gui_draw_console() { const int rows = vidconf.numtextrows, cols = vidconf.numtextcols; ctexttop = 3; ctextbot = rows - 2; ctextleft = 1; ctextright = cols; gui_draw_textwindow(ctexttop, ctextleft, ctextbot, ctextright, GUI_COLOR_CONSOLE); ctextpos.row = 1; ctextpos.col = 1; } void gui_init() { _getvideoconfig(&vidconf); _gettextsettings(&txtconf); switch (vidconf.mode) { case _TEXTBW40: case _TEXTC40: case _TEXTBW80: case _TEXTC80: case _TEXTMONO: vidconf_is_graphics = false; break; default: vidconf_is_graphics = true; break; } switch (vidconf.mode) { case _TEXTBW40: case _TEXTBW80: case _TEXTMONO: case _HERCMONO: case _MRESNOCOLOR: case _ERESNOCOLOR: case _VRES2COLOR: vidconf_is_color = false; break; default: vidconf_is_color = true; break; } if (vidconf_is_graphics) { if (vidconf_is_color) { _remappalette(0, _BLACK); _remappalette(1, _CYAN); _remappalette(2, _BLUE); _remappalette(3, _WHITE); gui_bg_color[GUI_COLOR_CONSOLE] = 0; gui_bg_color[GUI_COLOR_BAR] = 3; gui_bg_color[GUI_COLOR_WINDOW] = 2; gui_bg_color[GUI_COLOR_LIST] = 1; gui_bg_color[GUI_COLOR_LIST_SEL] = 3; gui_text_color[GUI_COLOR_CONSOLE] = 3; gui_text_color[GUI_COLOR_BAR] = 0; gui_text_color[GUI_COLOR_WINDOW] = 3; gui_text_color[GUI_COLOR_LIST] = 0; gui_text_color[GUI_COLOR_LIST_SEL] = 0; } else { gui_bg_color[GUI_COLOR_CONSOLE] = T_BLACK; gui_bg_color[GUI_COLOR_BAR] = T_WHITE; gui_bg_color[GUI_COLOR_WINDOW] = T_WHITE; gui_bg_color[GUI_COLOR_LIST] = T_WHITE; gui_bg_color[GUI_COLOR_LIST_SEL] = T_BLACK; gui_text_color[GUI_COLOR_CONSOLE] = T_WHITE; gui_text_color[GUI_COLOR_BAR] = T_BLACK; gui_text_color[GUI_COLOR_WINDOW] = T_BLACK; gui_text_color[GUI_COLOR_LIST] = T_BLACK; gui_text_color[GUI_COLOR_LIST_SEL] = T_WHITE | T_BRIGHT; } } else { if (vidconf_is_color) { gui_bg_color[GUI_COLOR_CONSOLE] = T_BLACK; gui_bg_color[GUI_COLOR_BAR] = T_WHITE; gui_bg_color[GUI_COLOR_WINDOW] = T_BLUE; gui_bg_color[GUI_COLOR_LIST] = T_CYAN; gui_bg_color[GUI_COLOR_LIST_SEL] = T_WHITE; gui_text_color[GUI_COLOR_CONSOLE] = T_WHITE; gui_text_color[GUI_COLOR_BAR] = T_BLACK; gui_text_color[GUI_COLOR_WINDOW] = T_WHITE; gui_text_color[GUI_COLOR_LIST] = T_BLACK; gui_text_color[GUI_COLOR_LIST_SEL] = T_BLACK; } else { gui_bg_color[GUI_COLOR_CONSOLE] = T_BLACK; gui_bg_color[GUI_COLOR_BAR] = T_WHITE; gui_bg_color[GUI_COLOR_WINDOW] = T_WHITE; gui_bg_color[GUI_COLOR_LIST] = T_WHITE; gui_bg_color[GUI_COLOR_LIST_SEL] = T_BLACK; gui_text_color[GUI_COLOR_CONSOLE] = T_WHITE; gui_text_color[GUI_COLOR_BAR] = T_BLACK; gui_text_color[GUI_COLOR_WINDOW] = T_BLACK; gui_text_color[GUI_COLOR_LIST] = T_BLACK; gui_text_color[GUI_COLOR_LIST_SEL] = T_WHITE | T_BRIGHT; } } _displaycursor(_GCURSOROFF); _wrapon(_GWRAPOFF); gui_draw_title(); gui_draw_status(); gui_draw_console(); } void console_enter() { _settextwindow(ctexttop, ctextleft, ctextbot, ctextright); _settextposition(ctextpos.row, ctextpos.col); if (!vidconf_is_graphics) _setbkcolor(ctextbg); _settextcolor(ctextcolor); _wrapon(_GWRAPON); } void console_leave() { ctextpos = _gettextposition(); _wrapon(_GWRAPOFF); } void console_print(char __far *str) { _disable(); int33_hide_cursor(); console_enter(); _outtext(str); console_leave(); int33_show_cursor(); _enable(); } void console_printf(const char *format, ...) { va_list arglist; char buffer[120]; va_start(arglist, format); vsprintf(buffer, format, arglist); va_end(arglist); console_print(buffer); } struct modeentry { char *name; int modenum; } modelist[] = { {"TEXTBW40", _TEXTBW40}, {"TEXTC40", _TEXTC40}, {"TEXTBW80", _TEXTBW80}, {"TEXTC80", _TEXTC80}, {"MRES4COLOR", _MRES4COLOR}, {"MRESNOCOLOR", _MRESNOCOLOR}, {"HRESBW", _HRESBW}, {"TEXTMONO", _TEXTMONO}, {"HERCMONO", _HERCMONO}, {"MRES16COLOR", _MRES16COLOR}, {"HRES16COLOR", _HRES16COLOR}, {"ERESNOCOLOR", _ERESNOCOLOR}, {"ERESCOLOR", _ERESCOLOR}, {"VRES2COLOR", _VRES2COLOR}, {"VRES16COLOR", _VRES16COLOR}, {"MRES256COLOR", _MRES256COLOR}, {"URES256COLOR", _URES256COLOR}, {"VRES256COLOR", _VRES256COLOR}, {"SVRES16COLOR", _SVRES16COLOR}, {"SVRES256COLOR", _SVRES256COLOR}, {"XRES16COLOR", _XRES16COLOR}, {"XRES256COLOR", _XRES256COLOR}, }; const int num_modeentries = sizeof(modelist)/sizeof(struct modeentry); struct { int first_entry; int sel_entry; int list_rows; } mlistui; void modelist_switch_to(int entry) { struct modeentry *mode = &modelist[entry]; dprintf(DPREFIX "switching to mode %s %d\n", mode->name, mode->modenum); _setvideomode(mode->modenum); } int modelist_get_current() { int i; for (i = 0; i < num_modeentries; ++i) { if (modelist[i].modenum == vidconf.mode) { return i; } } return 0; } void __far modelist_mouse_callback(uint16_t events, uint16_t buttons, int16_t x, int16_t y, int16_t delta_x, int16_t delta_y) #pragma aux (INT33_CB) mouse_callback { int8_t z = buttons >> 8; (void) delta_x; (void) delta_y; #if 1 dprintf(DPREFIX "modelist_mouse_callback events=0x%x buttons=0x%x x=%d y=%d dx=%d dy=%d\n", events, buttons, x, y, delta_x, delta_y); #endif } void modelist_draw_window() { const int list_width = 23; const int rows = vidconf.numtextrows, cols = vidconf.numtextcols; int i; int33_hide_cursor(); gui_draw_textwindow(3, 4, rows - 3, list_width + 1, GUI_COLOR_WINDOW); gui_print(GUI_COLOR_WINDOW, " Choose video mode: "); int33_show_cursor(); } void modelist_draw_list() { const int list_width = 23; const int rows = vidconf.numtextrows, cols = vidconf.numtextcols; int i; int33_hide_cursor(); gui_draw_textwindow(5, 5, 5 + mlistui.list_rows - 1, list_width, GUI_COLOR_LIST); for (i = mlistui.first_entry; i < MIN(num_modeentries, mlistui.first_entry + mlistui.list_rows); ++i) { const bool selected = i == mlistui.sel_entry; _settextposition(1 + (i - mlistui.first_entry), 1); gui_print(selected ? GUI_COLOR_LIST_SEL : GUI_COLOR_LIST, modelist[i].name); } if (mlistui.first_entry > 0) { _settextposition(1, list_width); gui_print(GUI_COLOR_LIST, "\x18"); } if (mlistui.first_entry + mlistui.list_rows < num_modeentries) { _settextposition(1 + mlistui.list_rows, list_width); gui_print(GUI_COLOR_LIST, "\x19"); } int33_show_cursor(); } bool modelist_sel_entry(int offset) { int new_sel_entry = mlistui.sel_entry + offset; if (new_sel_entry < 0) { new_sel_entry = 0; } else if (new_sel_entry >= num_modeentries) { new_sel_entry = num_modeentries - 1; } if (new_sel_entry != mlistui.sel_entry) { mlistui.sel_entry = new_sel_entry; if (mlistui.sel_entry < mlistui.first_entry) { mlistui.first_entry = mlistui.sel_entry; } else if (mlistui.sel_entry >= mlistui.first_entry + mlistui.list_rows) { mlistui.first_entry = 1 + mlistui.sel_entry - mlistui.list_rows; } return true; } else { return false; } } void modelist_show_modal() { bool exiting = false; // TODO Mouse support here :) //int33_set_event_handler(INT33_EVENT_MASK_ALL, modelist_mouse_callback); int33_set_event_handler(0, NULL); int33_hide_cursor(); mlistui.first_entry = 0; mlistui.sel_entry = 0; mlistui.list_rows = vidconf.numtextrows - 8; modelist_sel_entry(modelist_get_current()); modelist_draw_window(); modelist_draw_list(); while (!exiting) { int c = getch(); dprintf(DPREFIX "modelist getch returns %d\n", c); switch (c) { case 27: // Escape exiting = true; break; case '\r': modelist_switch_to(mlistui.sel_entry); exiting = true; break; case 0: c = getch(); dprintf(DPREFIX "modelist getch returns extended %d\n", c); switch (c) { case 72: // Arrow-Up if (modelist_sel_entry(-1)) { modelist_draw_list(); } break; case 80: // Arrow-Down if (modelist_sel_entry(+1)) { modelist_draw_list(); } break; case 73: // Page-Up if (modelist_sel_entry(-mlistui.list_rows)) { modelist_draw_list(); } break; case 81: // Page-Down if (modelist_sel_entry(+mlistui.list_rows)) { modelist_draw_list(); } break; } break; } } int33_set_event_handler(0, NULL); } /** Called by the int33 mouse driver. */ void __far mouse_callback(uint16_t events, uint16_t buttons, int16_t x, int16_t y, int16_t delta_x, int16_t delta_y) #pragma aux (INT33_CB) mouse_callback { int8_t z = buttons >> 8; (void) delta_x; (void) delta_y; #if 0 dprintf(DPREFIX "mouse_callback events=0x%x buttons=0x%x x=%d y=%d dx=%d dy=%d\n", events, buttons, x, y, delta_x, delta_y); #endif // Update the status bar _disable(); gui_draw_status(); gui_printf(GUI_COLOR_BAR, " %3s %4u , %4u |", events & INT33_EVENT_MASK_ABSOLUTE ? "ABS" : "REL", x, y); if (num_buttons <= 2) { gui_printf(GUI_COLOR_BAR, " [%5s] [%5s] ", buttons & INT33_BUTTON_MASK_LEFT ? "LEFT" : "", buttons & INT33_BUTTON_MASK_RIGHT ? "RIGHT" : ""); } else { gui_printf(GUI_COLOR_BAR, " [%5s] [%5s] [%5s] ", buttons & INT33_BUTTON_MASK_LEFT ? "LEFT" : "", buttons & INT33_BUTTON_MASK_CENTER ? "MID " : "", buttons & INT33_BUTTON_MASK_RIGHT ? "RIGHT" : ""); if (num_buttons > 3) { gui_printf(GUI_COLOR_BAR, " [%3s] [%3s] ", buttons & INT33_BUTTON_MASK_4TH ? "4TH" : "", buttons & INT33_BUTTON_MASK_5TH ? "5TH" : ""); } } if (num_wheels > 0) { char c = ' '; if (events & INT33_EVENT_MASK_WHEEL_MOVEMENT) { c = z > 0 ? 0x19 : 0x18; } else if (events & INT33_EVENT_MASK_HORIZ_WHEEL_MOVEMENT) { c = z > 0 ? 0x1A : 0x1B; } gui_printf(GUI_COLOR_BAR, "| %c", c); } // Log the events if (events & INT33_EVENT_MASK_LEFT_BUTTON_PRESSED) { console_printf("Left button pressed\n"); } if (events & INT33_EVENT_MASK_LEFT_BUTTON_RELEASED) { console_printf("Left button released\n"); } if (events & INT33_EVENT_MASK_CENTER_BUTTON_PRESSED) { console_printf("Middle button pressed\n"); } if (events & INT33_EVENT_MASK_CENTER_BUTTON_RELEASED) { console_printf("Middle button released\n"); } if (events & INT33_EVENT_MASK_RIGHT_BUTTON_PRESSED) { console_printf("Right button pressed\n"); } if (events & INT33_EVENT_MASK_RIGHT_BUTTON_RELEASED) { console_printf("Right button released\n"); } if (events & INT33_EVENT_MASK_4TH_BUTTON_PRESSED) { console_printf("4th button pressed\n"); } if (events & INT33_EVENT_MASK_4TH_BUTTON_RELEASED) { console_printf("4th button released\n"); } if (events & INT33_EVENT_MASK_5TH_BUTTON_PRESSED) { console_printf("5th button pressed\n"); } if (events & INT33_EVENT_MASK_5TH_BUTTON_RELEASED) { console_printf("5th button released\n"); } if (events & INT33_EVENT_MASK_WHEEL_MOVEMENT) { console_printf("Wheel %s %d\n", z > 0 ? "down" : "up", z); } if (events & INT33_EVENT_MASK_HORIZ_WHEEL_MOVEMENT) { console_printf("Wheel %s %d\n", z > 0 ? "right" : "left", z); } _enable(); } bool mouse_reset() { if (!int33_reset_get_buttons(&num_buttons)) { puts("Mouse not installed"); return false; } driver_caps = int33_get_capabilities(); num_wheels = 0; if (driver_caps & INT33_CAPABILITY_WHEEL_API) { num_wheels = 1; } if (driver_caps & INT33_CAPABILITY_WHEEL2_API) { num_wheels = 2; } int33_set_event_handler(INT33_EVENT_MASK_ALL, mouse_callback); return true; } void mouse_report() { const char __far *fstr; if (driver_caps != 0) { console_printf("Driver capabilities bits: 0x%x %s %s\n", driver_caps, driver_caps & INT33_CAPABILITY_WHEEL_API ? "" : "", driver_caps & INT33_CAPABILITY_WHEEL2_API ? "" : ""); } fstr = int33_get_version_string(); if (fstr) { console_printf("Driver version string: %Fs\n", fstr); } console_printf("Number of buttons: %u\n", num_buttons); console_printf("Number of wheels: %u\n", num_wheels); } void mouse_quit() { int33_reset(); } void mouse_debug() { // Add test code here } int main(int argc, const char *argv[]) { int c; (void)argc; (void)argv; if (!mouse_reset()) { return EXIT_FAILURE; } gui_init(); mouse_report(); int33_show_cursor(); while (!main_exiting) { int c = getch(); dprintf(DPREFIX "getch returns %d\n", c); if (c == 0) { // Extended key c = getch(); console_printf("Keyboard extended key %d\n", c); } else { console_printf("Keyboard key %d '%c'\n", c, c); switch (c) { case 27: // Escape main_exiting = true; break; case 'r': console_printf("Reset mouse driver\n"); mouse_reset(); mouse_report(); break; case 's': int33_show_cursor(); break; case 'h': int33_hide_cursor(); break; case 'm': modelist_show_modal(); gui_init(); mouse_reset(); break; case 'd': mouse_debug(); break; case 'c': _clearscreen(_GCLEARSCREEN); break; } } } mouse_quit(); _setvideomode(_DEFAULTMODE); return EXIT_SUCCESS; }