Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 1 | /* |
| 2 | * a GUI application for displaying a console |
| 3 | * (N)Curses back end |
| 4 | * |
| 5 | * Copyright 2002 Eric Pouech |
| 6 | * |
| 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation; either |
| 10 | * version 2.1 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
| 18 | * License along with this library; if not, write to the Free Software |
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ |
| 21 | |
| 22 | /* Known issues & FIXME: |
| 23 | * - not all key mapping functions have been written |
| 24 | * - allow dyn loading of curses library (extreme care should be taken for |
| 25 | * functions which can be implemented as macros) |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 26 | * - finish buffer scrolling (mainly, need to decide of a nice way for |
| 27 | * requesting the UP/DOWN operations |
Jukka Heinonen | 944dd6e | 2003-06-04 20:14:47 +0000 | [diff] [blame] | 28 | * - Resizing (unix) terminal does not change (Win32) console size. |
| 29 | * - Initial console size comes from registry and not from terminal size. |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 30 | */ |
| 31 | |
| 32 | #include "config.h" |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 33 | #include "wine/port.h" |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 34 | |
| 35 | #include <stdio.h> |
Alexandre Julliard | 62986a0 | 2003-09-07 05:08:14 +0000 | [diff] [blame] | 36 | #include <stdarg.h> |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 37 | #include <stdlib.h> |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 38 | #ifdef HAVE_CURSES_H |
| 39 | #include <curses.h> |
| 40 | #endif |
| 41 | #ifdef HAVE_NCURSES_H |
| 42 | #include <ncurses.h> |
| 43 | #endif |
Alexandre Julliard | edcddb8 | 2003-04-03 23:57:39 +0000 | [diff] [blame] | 44 | #undef KEY_EVENT /* avoid redefinition warning */ |
Jon Griffiths | 09fefee | 2003-09-23 22:54:57 +0000 | [diff] [blame^] | 45 | #ifdef HAVE_UNISTD_H |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 46 | #include <unistd.h> |
Jon Griffiths | 09fefee | 2003-09-23 22:54:57 +0000 | [diff] [blame^] | 47 | #endif |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 48 | #include <windef.h> |
Alexandre Julliard | 864ca06 | 2003-08-20 18:22:31 +0000 | [diff] [blame] | 49 | #include <winbase.h> |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 50 | #include <winnls.h> |
| 51 | #include "winecon_private.h" |
| 52 | |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 53 | #include "wine/library.h" |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 54 | #include "wine/server.h" |
| 55 | #include "wine/debug.h" |
| 56 | |
| 57 | WINE_DEFAULT_DEBUG_CHANNEL(wineconsole); |
| 58 | |
| 59 | #define PRIVATE(data) ((struct inner_data_curse*)((data)->private)) |
| 60 | |
| 61 | #if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H) |
| 62 | |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 63 | #ifdef HAVE_NCURSES_H |
| 64 | #define CURSES_NAME "ncurses" |
| 65 | #else |
| 66 | #define CURSES_NAME "curses" |
| 67 | #endif |
| 68 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 69 | struct inner_data_curse |
| 70 | { |
| 71 | mmask_t initial_mouse_mask; |
| 72 | HANDLE hInput; |
| 73 | WINDOW* pad; |
| 74 | chtype* line; |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 75 | int allow_scroll; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 76 | }; |
| 77 | |
Jukka Heinonen | 944dd6e | 2003-06-04 20:14:47 +0000 | [diff] [blame] | 78 | |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 79 | static void *nc_handle = NULL; |
| 80 | |
| 81 | #define MAKE_FUNCPTR(f) static typeof(f) * p_##f; |
| 82 | |
| 83 | MAKE_FUNCPTR(curs_set) |
| 84 | MAKE_FUNCPTR(delwin) |
| 85 | MAKE_FUNCPTR(endwin) |
| 86 | MAKE_FUNCPTR(getmouse) |
| 87 | MAKE_FUNCPTR(has_colors) |
| 88 | MAKE_FUNCPTR(init_pair) |
| 89 | #ifndef initscr |
| 90 | MAKE_FUNCPTR(initscr) |
| 91 | #endif |
| 92 | #ifndef intrflush |
| 93 | MAKE_FUNCPTR(intrflush) |
| 94 | #endif |
| 95 | MAKE_FUNCPTR(keypad) |
| 96 | MAKE_FUNCPTR(mouseinterval) |
| 97 | MAKE_FUNCPTR(mousemask) |
| 98 | MAKE_FUNCPTR(newpad) |
| 99 | #ifndef nodelay |
| 100 | MAKE_FUNCPTR(nodelay) |
| 101 | #endif |
| 102 | #ifndef noecho |
| 103 | MAKE_FUNCPTR(noecho) |
| 104 | #endif |
| 105 | MAKE_FUNCPTR(prefresh) |
| 106 | MAKE_FUNCPTR(raw) |
| 107 | MAKE_FUNCPTR(start_color) |
| 108 | MAKE_FUNCPTR(stdscr) |
| 109 | MAKE_FUNCPTR(waddchnstr) |
| 110 | MAKE_FUNCPTR(wmove) |
| 111 | MAKE_FUNCPTR(wgetch) |
| 112 | |
| 113 | #undef MAKE_FUNCPTR |
| 114 | |
| 115 | /**********************************************************************/ |
| 116 | |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 117 | static BOOL WCCURSES_bind_libcurses(void) |
| 118 | { |
| 119 | #ifdef HAVE_NCURSES_H |
| 120 | static const char *ncname = SONAME_LIBNCURSES; |
| 121 | #else |
| 122 | static const char *ncname = SONAME_LIBCURSES; |
| 123 | #endif |
| 124 | |
| 125 | nc_handle = wine_dlopen(ncname, RTLD_NOW, NULL, 0); |
| 126 | if(!nc_handle) |
| 127 | { |
| 128 | WINE_MESSAGE("Wine cannot find the " CURSES_NAME " library (%s).\n", |
| 129 | ncname); |
| 130 | return FALSE; |
| 131 | } |
| 132 | |
| 133 | #define LOAD_FUNCPTR(f) \ |
| 134 | if((p_##f = wine_dlsym(nc_handle, #f, NULL, 0)) == NULL) \ |
| 135 | { \ |
| 136 | WINE_WARN("Can't find symbol %s\n", #f); \ |
| 137 | goto sym_not_found; \ |
| 138 | } |
| 139 | |
| 140 | LOAD_FUNCPTR(curs_set) |
| 141 | LOAD_FUNCPTR(delwin) |
| 142 | LOAD_FUNCPTR(endwin) |
| 143 | LOAD_FUNCPTR(getmouse) |
| 144 | LOAD_FUNCPTR(has_colors) |
| 145 | LOAD_FUNCPTR(init_pair) |
| 146 | #ifndef initscr |
| 147 | LOAD_FUNCPTR(initscr) |
| 148 | #endif |
| 149 | #ifndef intrflush |
| 150 | LOAD_FUNCPTR(intrflush) |
| 151 | #endif |
| 152 | LOAD_FUNCPTR(keypad) |
| 153 | LOAD_FUNCPTR(mouseinterval) |
| 154 | LOAD_FUNCPTR(mousemask) |
| 155 | LOAD_FUNCPTR(newpad) |
| 156 | #ifndef nodelay |
| 157 | LOAD_FUNCPTR(nodelay) |
| 158 | #endif |
| 159 | #ifndef noecho |
| 160 | LOAD_FUNCPTR(noecho) |
| 161 | #endif |
| 162 | LOAD_FUNCPTR(prefresh) |
| 163 | LOAD_FUNCPTR(raw) |
| 164 | LOAD_FUNCPTR(start_color) |
| 165 | LOAD_FUNCPTR(stdscr) |
| 166 | LOAD_FUNCPTR(waddchnstr) |
| 167 | LOAD_FUNCPTR(wmove) |
| 168 | LOAD_FUNCPTR(wgetch) |
| 169 | |
| 170 | #undef LOAD_FUNCPTR |
| 171 | |
| 172 | return TRUE; |
| 173 | |
| 174 | sym_not_found: |
| 175 | WINE_MESSAGE( |
| 176 | "Wine cannot find certain functions that it needs inside the " |
| 177 | CURSES_NAME "\nlibrary. To enable Wine to use " CURSES_NAME |
| 178 | " please upgrade your " CURSES_NAME "\nlibraries\n"); |
| 179 | wine_dlclose(nc_handle, NULL, 0); |
| 180 | nc_handle = NULL; |
| 181 | return FALSE; |
| 182 | } |
| 183 | |
| 184 | #define curs_set p_curs_set |
| 185 | #define delwin p_delwin |
| 186 | #define endwin p_endwin |
| 187 | #define getmouse p_getmouse |
| 188 | #define has_colors p_has_colors |
| 189 | #define init_pair p_init_pair |
| 190 | #ifndef initscr |
| 191 | #define initscr p_initscr |
| 192 | #endif |
| 193 | #ifndef intrflush |
| 194 | #define intrflush p_intrflush |
| 195 | #endif |
| 196 | #define keypad p_keypad |
| 197 | #define mouseinterval p_mouseinterval |
| 198 | #define mousemask p_mousemask |
| 199 | #define newpad p_newpad |
| 200 | #ifndef nodelay |
| 201 | #define nodelay p_nodelay |
| 202 | #endif |
| 203 | #ifndef noecho |
| 204 | #define noecho p_noecho |
| 205 | #endif |
| 206 | #define prefresh p_prefresh |
| 207 | #define raw p_raw |
| 208 | #define start_color p_start_color |
| 209 | #define stdscr (*p_stdscr) |
| 210 | #define waddchnstr p_waddchnstr |
| 211 | #define wmove p_wmove |
| 212 | #define wgetch p_wgetch |
| 213 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 214 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 215 | * WCCURSES_ResizeScreenBuffer |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 216 | * |
| 217 | * |
| 218 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 219 | static void WCCURSES_ResizeScreenBuffer(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 220 | { |
| 221 | /* reallocate a new pad. next event would redraw the whole pad */ |
| 222 | if (PRIVATE(data)->pad) delwin(PRIVATE(data)->pad); |
| 223 | PRIVATE(data)->pad = newpad(data->curcfg.sb_height, data->curcfg.sb_width); |
| 224 | if (!PRIVATE(data)->pad) |
| 225 | WINE_FIXME("Cannot create pad\n"); |
| 226 | PRIVATE(data)->line = HeapReAlloc(GetProcessHeap(), 0, PRIVATE(data)->line, |
| 227 | sizeof(chtype) * data->curcfg.sb_width); |
| 228 | } |
| 229 | |
| 230 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 231 | * WCCURSES_PosCursor |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 232 | * |
| 233 | * Set a new position for the cursor (and refresh any modified part of our pad) |
| 234 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 235 | static void WCCURSES_PosCursor(const struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 236 | { |
Jukka Heinonen | 944dd6e | 2003-06-04 20:14:47 +0000 | [diff] [blame] | 237 | int scr_width; |
| 238 | int scr_height; |
| 239 | |
Eric Pouech | eac6727 | 2003-01-07 19:39:25 +0000 | [diff] [blame] | 240 | if (data->curcfg.cursor_visible && |
| 241 | data->cursor.Y >= data->curcfg.win_pos.Y && |
| 242 | data->cursor.Y < data->curcfg.win_pos.Y + data->curcfg.win_height && |
| 243 | data->cursor.X >= data->curcfg.win_pos.X && |
| 244 | data->cursor.X < data->curcfg.win_pos.X + data->curcfg.win_width) |
| 245 | { |
| 246 | if (curs_set(2) == ERR) curs_set(1); |
| 247 | wmove(PRIVATE(data)->pad, data->cursor.Y, data->cursor.X); |
| 248 | } |
| 249 | else |
| 250 | { |
| 251 | curs_set(0); |
| 252 | } |
Eric Pouech | 71a71b3 | 2003-09-22 19:31:32 +0000 | [diff] [blame] | 253 | getmaxyx(stdscr, scr_height, scr_width); |
Eric Pouech | eac6727 | 2003-01-07 19:39:25 +0000 | [diff] [blame] | 254 | prefresh(PRIVATE(data)->pad, |
| 255 | data->curcfg.win_pos.Y, data->curcfg.win_pos.X, |
Eric Pouech | 71a71b3 | 2003-09-22 19:31:32 +0000 | [diff] [blame] | 256 | 0, 0, |
| 257 | min(scr_height, data->curcfg.win_height) - 1, |
| 258 | min(scr_width, data->curcfg.win_width) - 1); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 262 | * WCCURSES_ShapeCursor |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 263 | * |
| 264 | * Sets a new shape for the cursor |
| 265 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 266 | void WCCURSES_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 267 | { |
Eric Pouech | eac6727 | 2003-01-07 19:39:25 +0000 | [diff] [blame] | 268 | /* we can't do much about the size... */ |
| 269 | data->curcfg.cursor_size = size; |
| 270 | data->curcfg.cursor_visible = vis ? TRUE : FALSE; |
| 271 | WCCURSES_PosCursor(data); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 275 | * WCCURSES_ComputePositions |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 276 | * |
| 277 | * Recomputes all the components (mainly scroll bars) positions |
| 278 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 279 | void WCCURSES_ComputePositions(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 280 | { |
Eric Pouech | 71a71b3 | 2003-09-22 19:31:32 +0000 | [diff] [blame] | 281 | int x, y; |
| 282 | |
| 283 | getmaxyx(stdscr, y, x); |
| 284 | if ((data->curcfg.win_height && y < data->curcfg.win_height) || |
| 285 | (data->curcfg.win_width && x < data->curcfg.win_width)) |
| 286 | { |
| 287 | SMALL_RECT pos; |
| 288 | |
| 289 | WINE_WARN("Window too large (%dx%d), adjusting to curses' size (%dx%d)\n", |
| 290 | data->curcfg.win_width, data->curcfg.win_height, x, y); |
| 291 | pos.Left = pos.Top = 0; |
| 292 | pos.Right = x - 1; pos.Bottom = y - 1; |
| 293 | SetConsoleWindowInfo(data->hConOut, FALSE, &pos); |
| 294 | return; /* we'll get called again upon event for new window size */ |
| 295 | } |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 296 | if (PRIVATE(data)->pad) WCCURSES_PosCursor(data); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 300 | * WCCURSES_SetTitle |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 301 | * |
| 302 | * Sets the title to the wine console |
| 303 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 304 | static void WCCURSES_SetTitle(const struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 305 | { |
| 306 | WCHAR wbuf[256]; |
| 307 | |
| 308 | if (WINECON_GetConsoleTitle(data->hConIn, wbuf, sizeof(wbuf)/sizeof(WCHAR))) |
| 309 | { |
| 310 | char buffer[256]; |
| 311 | |
| 312 | WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buffer, sizeof(buffer), |
| 313 | NULL, NULL); |
| 314 | fputs("\033]2;", stdout); |
| 315 | fputs(buffer, stdout); |
| 316 | fputc('\a', stdout); |
| 317 | fflush(stdout); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | /****************************************************************** |
Jukka Heinonen | 944dd6e | 2003-06-04 20:14:47 +0000 | [diff] [blame] | 322 | * WCCURSES_Refresh |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 323 | * |
| 324 | * |
| 325 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 326 | static void WCCURSES_Refresh(const struct inner_data* data, int tp, int bm) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 327 | { |
| 328 | int x, y; |
| 329 | CHAR_INFO* cell; |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 330 | DWORD attr; |
| 331 | char ch; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 332 | |
| 333 | for (y = tp; y <= bm; y++) |
| 334 | { |
| 335 | cell = &data->cells[y * data->curcfg.sb_width]; |
| 336 | for (x = 0; x < data->curcfg.sb_width; x++) |
| 337 | { |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 338 | WideCharToMultiByte(CP_ACP, 0, &cell[x].Char.UnicodeChar, 1, |
| 339 | &ch, 1, NULL, NULL); |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 340 | attr = ((BYTE)ch < 32 || (BYTE)ch > 127) ? 32 : (BYTE)ch; |
| 341 | |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 342 | if (cell[x].Attributes & FOREGROUND_RED) attr |= COLOR_PAIR(COLOR_RED); |
| 343 | if (cell[x].Attributes & FOREGROUND_BLUE) attr |= COLOR_PAIR(COLOR_BLUE); |
| 344 | if (cell[x].Attributes & FOREGROUND_GREEN) attr |= COLOR_PAIR(COLOR_GREEN); |
| 345 | if (cell[x].Attributes & BACKGROUND_RED) attr |= COLOR_PAIR(COLOR_RED << 3); |
| 346 | if (cell[x].Attributes & BACKGROUND_BLUE) attr |= COLOR_PAIR(COLOR_BLUE << 3); |
| 347 | if (cell[x].Attributes & BACKGROUND_GREEN) attr |= COLOR_PAIR(COLOR_GREEN << 3); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 348 | |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 349 | if (cell[x].Attributes & FOREGROUND_INTENSITY) attr |= A_BOLD; |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 350 | PRIVATE(data)->line[x] = attr; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 351 | } |
| 352 | mvwaddchnstr(PRIVATE(data)->pad, y, 0, PRIVATE(data)->line, data->curcfg.sb_width); |
| 353 | } |
Jukka Heinonen | 944dd6e | 2003-06-04 20:14:47 +0000 | [diff] [blame] | 354 | |
| 355 | WCCURSES_PosCursor(data); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 356 | } |
| 357 | |
| 358 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 359 | * WCCURSES_Scroll |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 360 | * |
| 361 | * |
| 362 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 363 | static void WCCURSES_Scroll(struct inner_data* data, int pos, BOOL horz) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 364 | { |
| 365 | if (horz) |
| 366 | { |
| 367 | data->curcfg.win_pos.X = pos; |
| 368 | } |
| 369 | else |
| 370 | { |
| 371 | data->curcfg.win_pos.Y = pos; |
| 372 | } |
Eric Pouech | eac6727 | 2003-01-07 19:39:25 +0000 | [diff] [blame] | 373 | WCCURSES_PosCursor(data); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 377 | * WCCURSES_SetFont |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 378 | * |
| 379 | * |
| 380 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 381 | static void WCCURSES_SetFont(struct inner_data* data, const WCHAR* font, |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 382 | unsigned height, unsigned weight) |
| 383 | { |
| 384 | /* FIXME: really not much to do ? */ |
| 385 | } |
| 386 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 387 | /****************************************************************** |
| 388 | * WCCURSES_ScrollV |
| 389 | * |
| 390 | * |
| 391 | */ |
| 392 | static void WCCURSES_ScrollV(struct inner_data* data, int delta) |
| 393 | { |
| 394 | int pos = data->curcfg.win_pos.Y; |
| 395 | |
| 396 | pos += delta; |
| 397 | if (pos < 0) pos = 0; |
| 398 | if (pos > data->curcfg.sb_height - data->curcfg.win_height) |
| 399 | pos = data->curcfg.sb_height - data->curcfg.win_height; |
| 400 | if (pos != data->curcfg.win_pos.Y) |
| 401 | { |
| 402 | data->curcfg.win_pos.Y = pos; |
| 403 | WCCURSES_PosCursor(data); |
| 404 | WINECON_NotifyWindowChange(data); |
| 405 | } |
| 406 | } |
| 407 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 408 | /* Ascii -> VK, generated by calling VkKeyScanA(i) */ |
| 409 | static int vkkeyscan_table[256] = |
| 410 | { |
| 411 | 0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0, |
| 412 | 0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48, |
| 413 | 49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323, |
| 414 | 324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340, |
| 415 | 341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71, |
| 416 | 72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477, |
| 417 | 448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 418 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 419 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 420 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0 |
| 421 | }; |
| 422 | |
| 423 | static int mapvkey_0[256] = |
| 424 | { |
| 425 | 0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0, |
| 426 | 0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9, |
| 427 | 10,0,0,0,0,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16, |
| 428 | 19,31,20,22,47,17,45,21,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,78,0,74, |
| 429 | 0,53,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 430 | 0,0,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 431 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0, |
| 432 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,76,96,0,0,0,0,0,0,0,0, |
| 433 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
| 434 | }; |
| 435 | |
| 436 | /****************************************************************** |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 437 | * WCCURSES_InitComplexChar |
| 438 | * |
| 439 | * |
| 440 | */ |
| 441 | static inline void WCCURSES_InitComplexChar(INPUT_RECORD* ir, BOOL down, WORD vk, WORD kc, DWORD cks) |
| 442 | { |
| 443 | ir->EventType = KEY_EVENT; |
| 444 | ir->Event.KeyEvent.bKeyDown = down; |
| 445 | ir->Event.KeyEvent.wRepeatCount = 1; |
| 446 | |
| 447 | ir->Event.KeyEvent.wVirtualScanCode = vk; |
| 448 | ir->Event.KeyEvent.wVirtualKeyCode = kc; |
| 449 | ir->Event.KeyEvent.dwControlKeyState = cks; |
| 450 | ir->Event.KeyEvent.uChar.UnicodeChar = 0; |
| 451 | } |
| 452 | |
| 453 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 454 | * WCCURSES_FillSimpleChar |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 455 | * |
| 456 | * |
| 457 | */ |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 458 | static unsigned WCCURSES_FillSimpleChar(INPUT_RECORD* ir, unsigned real_inchar) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 459 | { |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 460 | unsigned vk; |
| 461 | unsigned inchar; |
| 462 | unsigned numEvent = 0; |
| 463 | DWORD cks = 0; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 464 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 465 | switch (real_inchar) |
| 466 | { |
| 467 | case 127: inchar = '\b'; break; |
| 468 | case 10: inchar = '\r'; real_inchar = 27; /* so that we don't think key is ctrl- something */ break; |
| 469 | case 27: |
| 470 | /* we assume that ESC & and the second character are atomically generated |
| 471 | * otherwise, we'll have a race here |
| 472 | */ |
| 473 | if ((inchar = wgetch(stdscr)) != ERR) |
| 474 | { |
| 475 | /* we got a alt-something key... */ |
| 476 | cks = LEFT_ALT_PRESSED; |
| 477 | } |
| 478 | else |
| 479 | inchar = 27; |
| 480 | break; |
| 481 | default: |
| 482 | inchar = real_inchar; |
| 483 | break; |
| 484 | } |
| 485 | if ((inchar & ~0xFF) != 0) WINE_FIXME("What a char (%u)\n", inchar); |
| 486 | vk = vkkeyscan_table[inchar]; |
| 487 | if (vk & 0x0100) |
| 488 | WCCURSES_InitComplexChar(&ir[numEvent++], 1, 0x2a, 0x10, SHIFT_PRESSED); |
| 489 | if ((vk & 0x0200) || (unsigned char)real_inchar <= 26) |
| 490 | WCCURSES_InitComplexChar(&ir[numEvent++], 1, 0x1d, 0x11, LEFT_CTRL_PRESSED); |
| 491 | if (vk & 0x0400) |
| 492 | WCCURSES_InitComplexChar(&ir[numEvent++], 1, 0x38, 0x12, LEFT_ALT_PRESSED); |
Eric Pouech | eac6727 | 2003-01-07 19:39:25 +0000 | [diff] [blame] | 493 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 494 | ir[numEvent].EventType = KEY_EVENT; |
| 495 | ir[numEvent].Event.KeyEvent.bKeyDown = 1; |
| 496 | ir[numEvent].Event.KeyEvent.wRepeatCount = 1; |
| 497 | ir[numEvent].Event.KeyEvent.dwControlKeyState = cks; |
| 498 | if (vk & 0x0100) |
| 499 | ir[numEvent].Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED; |
| 500 | if ((vk & 0x0200) || (unsigned char)real_inchar <= 26) |
| 501 | ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; |
| 502 | if (vk & 0x0400) |
| 503 | ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; |
| 504 | ir[numEvent].Event.KeyEvent.wVirtualKeyCode = vk; |
| 505 | ir[numEvent].Event.KeyEvent.wVirtualScanCode = mapvkey_0[vk & 0x00ff]; /* VirtualKeyCodes to ScanCode */ |
| 506 | ir[numEvent].Event.KeyEvent.uChar.UnicodeChar = (unsigned char)inchar; |
| 507 | |
| 508 | ir[numEvent + 1] = ir[numEvent]; |
| 509 | ir[numEvent + 1].Event.KeyEvent.bKeyDown = 0; |
| 510 | |
| 511 | numEvent += 2; |
| 512 | |
| 513 | if (vk & 0x0400) |
| 514 | WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x38, 0x12, LEFT_ALT_PRESSED); |
| 515 | if ((vk & 0x0200) || (unsigned char)real_inchar <= 26) |
| 516 | WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x1d, 0x11, 0); |
| 517 | if (vk & 0x0100) |
| 518 | WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x2a, 0x10, 0); |
| 519 | |
| 520 | return numEvent; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 521 | } |
| 522 | |
| 523 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 524 | * WCCURSES_FillComplexChar |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 525 | * |
| 526 | * |
| 527 | */ |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 528 | static unsigned WCCURSES_FillComplexChar(INPUT_RECORD* ir, WORD vk, WORD kc, DWORD cks) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 529 | { |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 530 | WCCURSES_InitComplexChar(&ir[0], 1, vk, kc, ENHANCED_KEY | cks); |
| 531 | WCCURSES_InitComplexChar(&ir[1], 0, vk, kc, ENHANCED_KEY | cks); |
| 532 | |
| 533 | return 2; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 534 | } |
| 535 | |
| 536 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 537 | * WCCURSES_FillMouse |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 538 | * |
| 539 | * |
| 540 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 541 | static unsigned WCCURSES_FillMouse(INPUT_RECORD* ir) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 542 | { |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 543 | static unsigned bstate /* = 0 */; |
| 544 | static COORD pos /* = {0, 0} */; |
| 545 | |
| 546 | MEVENT mevt; |
| 547 | |
| 548 | if (getmouse(&mevt) == ERR) |
| 549 | return 0; |
| 550 | |
| 551 | WINE_TRACE("[%u]: (%d, %d) %08lx\n", |
| 552 | mevt.id, mevt.x, mevt.y, (unsigned long)mevt.bstate); |
| 553 | |
| 554 | /* macros to ease mapping ncurse button numbering to windows's one */ |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 555 | #define BTN1_BIT FROM_LEFT_1ST_BUTTON_PRESSED |
| 556 | #define BTN2_BIT RIGHTMOST_BUTTON_PRESSED |
| 557 | #define BTN3_BIT FROM_LEFT_2ND_BUTTON_PRESSED |
| 558 | #define BTN4_BIT 0 /* not done yet */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 559 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 560 | if (mevt.bstate & BUTTON1_PRESSED) bstate |= BTN1_BIT; |
| 561 | if (mevt.bstate & BUTTON1_RELEASED) bstate &= ~BTN1_BIT; |
| 562 | if (mevt.bstate & BUTTON2_PRESSED) bstate |= BTN2_BIT; |
| 563 | if (mevt.bstate & BUTTON2_RELEASED) bstate &= ~BTN2_BIT; |
| 564 | if (mevt.bstate & BUTTON3_PRESSED) bstate |= BTN3_BIT; |
| 565 | if (mevt.bstate & BUTTON3_RELEASED) bstate &= ~BTN3_BIT; |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 566 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 567 | ir->EventType = MOUSE_EVENT; |
| 568 | ir->Event.MouseEvent.dwMousePosition.X = mevt.x; |
| 569 | ir->Event.MouseEvent.dwMousePosition.Y = mevt.y; |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 570 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 571 | ir->Event.MouseEvent.dwButtonState = bstate; |
| 572 | |
| 573 | /* partial conversion */ |
| 574 | ir->Event.MouseEvent.dwControlKeyState = 0; |
| 575 | if (mevt.bstate & BUTTON_SHIFT) ir->Event.MouseEvent.dwControlKeyState |= SHIFT_PRESSED; |
| 576 | /* choose to map to left ctrl... could use both ? */ |
| 577 | if (mevt.bstate & BUTTON_CTRL) ir->Event.MouseEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; |
| 578 | /* choose to map to left alt... could use both ? */ |
| 579 | if (mevt.bstate & BUTTON_ALT) ir->Event.MouseEvent.dwControlKeyState |= LEFT_ALT_PRESSED; |
| 580 | /* FIXME: unsupported yet flags: CAPSLOCK_ON, ENHANCED_KEY (??), NUMLOCK_ON, SCROLLLOCK_ON |
| 581 | * could be reported from the key events... |
| 582 | */ |
| 583 | |
| 584 | ir->Event.MouseEvent.dwEventFlags = 0; |
| 585 | /* FIXME: we no longer generate double click events */ |
| 586 | |
| 587 | if (!(mevt.bstate & (BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED)) && |
| 588 | (mevt.x != pos.X || mevt.y != pos.Y)) |
| 589 | { |
| 590 | ir->Event.MouseEvent.dwEventFlags |= MOUSE_MOVED; |
| 591 | } |
| 592 | pos.X = mevt.x; pos.Y = mevt.y; |
| 593 | |
| 594 | return 1; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 595 | } |
| 596 | |
| 597 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 598 | * WCCURSES_FillCode |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 599 | * |
| 600 | * |
| 601 | */ |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 602 | static unsigned WCCURSES_FillCode(struct inner_data* data, INPUT_RECORD* ir, int inchar) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 603 | { |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 604 | unsigned numEvent = 0; |
| 605 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 606 | switch (inchar) |
| 607 | { |
| 608 | case KEY_BREAK: |
| 609 | goto notFound; |
| 610 | case KEY_DOWN: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 611 | numEvent = WCCURSES_FillComplexChar(ir, 0x50, 0x28, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 612 | break; |
| 613 | case KEY_UP: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 614 | numEvent = WCCURSES_FillComplexChar(ir, 0x48, 0x26, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 615 | break; |
| 616 | case KEY_LEFT: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 617 | numEvent = WCCURSES_FillComplexChar(ir, 0x4b, 0x25, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 618 | break; |
| 619 | case KEY_RIGHT: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 620 | numEvent = WCCURSES_FillComplexChar(ir, 0x4d, 0x27, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 621 | break; |
| 622 | case KEY_HOME: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 623 | numEvent = WCCURSES_FillComplexChar(ir, 0x47, 0x24, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 624 | break; |
| 625 | case KEY_BACKSPACE: |
Eric Pouech | 71a71b3 | 2003-09-22 19:31:32 +0000 | [diff] [blame] | 626 | numEvent = WCCURSES_FillSimpleChar(ir, 127); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 627 | break; |
| 628 | |
| 629 | case KEY_F0: /* up to F63 */ |
| 630 | goto notFound; |
| 631 | |
| 632 | case KEY_F( 1): |
| 633 | case KEY_F( 2): |
| 634 | case KEY_F( 3): |
| 635 | case KEY_F( 4): |
| 636 | case KEY_F( 5): |
| 637 | case KEY_F( 6): |
| 638 | case KEY_F( 7): |
| 639 | case KEY_F( 8): |
| 640 | case KEY_F( 9): |
| 641 | case KEY_F(10): |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 642 | numEvent = WCCURSES_FillComplexChar(ir, 0x3b + inchar - KEY_F(1), 0, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 643 | break; |
| 644 | case KEY_F(11): |
| 645 | case KEY_F(12): |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 646 | if (PRIVATE(data)->allow_scroll) |
| 647 | { |
| 648 | WCCURSES_ScrollV(data, inchar == KEY_F(11) ? 8 : -8); |
| 649 | } |
| 650 | else |
| 651 | { |
| 652 | numEvent = WCCURSES_FillComplexChar(ir, 0xd9 + inchar - KEY_F(11), 0, 0); |
| 653 | } |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 654 | break; |
| 655 | |
| 656 | case KEY_DL: |
| 657 | case KEY_IL: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 658 | goto notFound; |
| 659 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 660 | case KEY_DC: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 661 | numEvent = WCCURSES_FillComplexChar(ir, 0x53, 0x2e, 0); |
| 662 | break; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 663 | case KEY_IC: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 664 | numEvent = WCCURSES_FillComplexChar(ir, 0x52, 0x2d, 0); |
| 665 | break; |
| 666 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 667 | case KEY_EIC: |
| 668 | case KEY_CLEAR: |
| 669 | case KEY_EOS: |
| 670 | case KEY_EOL: |
| 671 | case KEY_SF: |
| 672 | case KEY_SR: |
| 673 | goto notFound; |
| 674 | |
| 675 | case KEY_NPAGE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 676 | numEvent = WCCURSES_FillComplexChar(ir, 0x51, 0x22, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 677 | break; |
| 678 | case KEY_PPAGE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 679 | numEvent = WCCURSES_FillComplexChar(ir, 0x49, 0x21, 0); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 680 | break; |
| 681 | |
| 682 | case KEY_STAB: |
| 683 | case KEY_CTAB: |
| 684 | case KEY_CATAB: |
| 685 | case KEY_ENTER: |
| 686 | case KEY_SRESET: |
| 687 | case KEY_RESET: |
| 688 | case KEY_PRINT: |
| 689 | case KEY_LL: |
| 690 | case KEY_A1: |
| 691 | case KEY_A3: |
| 692 | case KEY_B2: |
| 693 | case KEY_C1: |
| 694 | case KEY_C3: |
| 695 | case KEY_BTAB: |
| 696 | case KEY_BEG: |
| 697 | case KEY_CANCEL: |
| 698 | case KEY_CLOSE: |
| 699 | case KEY_COMMAND: |
| 700 | case KEY_COPY: |
| 701 | case KEY_CREATE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 702 | goto notFound; |
| 703 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 704 | case KEY_END: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 705 | numEvent = WCCURSES_FillComplexChar(ir, 0x4f, 0x23, 0); |
| 706 | break; |
| 707 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 708 | case KEY_EXIT: |
| 709 | case KEY_FIND: |
| 710 | case KEY_HELP: |
| 711 | case KEY_MARK: |
| 712 | case KEY_MESSAGE: |
| 713 | goto notFound; |
| 714 | |
| 715 | case KEY_MOUSE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 716 | numEvent = WCCURSES_FillMouse(ir); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 717 | break; |
| 718 | |
| 719 | case KEY_MOVE: |
| 720 | case KEY_NEXT: |
| 721 | case KEY_OPEN: |
| 722 | case KEY_OPTIONS: |
| 723 | case KEY_PREVIOUS: |
| 724 | case KEY_REDO: |
| 725 | case KEY_REFERENCE: |
| 726 | case KEY_REFRESH: |
| 727 | case KEY_REPLACE: |
| 728 | case KEY_RESIZE: |
| 729 | case KEY_RESTART: |
| 730 | case KEY_RESUME: |
| 731 | case KEY_SAVE: |
| 732 | case KEY_SBEG: |
| 733 | case KEY_SCANCEL: |
| 734 | case KEY_SCOMMAND: |
| 735 | case KEY_SCOPY: |
| 736 | case KEY_SCREATE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 737 | goto notFound; |
| 738 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 739 | case KEY_SDC: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 740 | numEvent = WCCURSES_FillComplexChar(ir, 0x53, 0x2e, SHIFT_PRESSED); |
| 741 | break; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 742 | case KEY_SDL: |
| 743 | case KEY_SELECT: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 744 | goto notFound; |
| 745 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 746 | case KEY_SEND: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 747 | numEvent = WCCURSES_FillComplexChar(ir, 0x4f, 0x23, SHIFT_PRESSED); |
| 748 | break; |
| 749 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 750 | case KEY_SEOL: |
| 751 | case KEY_SEXIT: |
| 752 | case KEY_SFIND: |
| 753 | case KEY_SHELP: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 754 | goto notFound; |
| 755 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 756 | case KEY_SHOME: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 757 | numEvent = WCCURSES_FillComplexChar(ir, 0x47, 0x24, SHIFT_PRESSED); |
| 758 | break; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 759 | case KEY_SIC: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 760 | numEvent = WCCURSES_FillComplexChar(ir, 0x52, 0x2d, SHIFT_PRESSED); |
| 761 | break; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 762 | case KEY_SLEFT: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 763 | numEvent = WCCURSES_FillComplexChar(ir, 0x4b, 0x25, SHIFT_PRESSED); |
| 764 | break; |
| 765 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 766 | case KEY_SMESSAGE: |
| 767 | case KEY_SMOVE: |
| 768 | case KEY_SNEXT: |
| 769 | case KEY_SOPTIONS: |
| 770 | case KEY_SPREVIOUS: |
| 771 | case KEY_SPRINT: |
| 772 | case KEY_SREDO: |
| 773 | case KEY_SREPLACE: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 774 | goto notFound; |
| 775 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 776 | case KEY_SRIGHT: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 777 | numEvent = WCCURSES_FillComplexChar(ir, 0x4d, 0x27, SHIFT_PRESSED); |
| 778 | break; |
| 779 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 780 | case KEY_SRSUME: |
| 781 | case KEY_SSAVE: |
| 782 | case KEY_SSUSPEND: |
| 783 | case KEY_SUNDO: |
| 784 | case KEY_SUSPEND: |
| 785 | case KEY_UNDO: |
| 786 | notFound: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 787 | WINE_FIXME("Not done yet (%o)\n", inchar); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 788 | break; |
| 789 | default: |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 790 | WINE_ERR("Unknown val (%o)\n", inchar); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 791 | break; |
| 792 | } |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 793 | return numEvent; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 794 | } |
| 795 | |
| 796 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 797 | * WCCURSES_GetEvents |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 798 | * |
| 799 | * |
| 800 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 801 | static void WCCURSES_GetEvents(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 802 | { |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 803 | int inchar; |
| 804 | INPUT_RECORD ir[8]; |
| 805 | unsigned numEvent; |
| 806 | DWORD n; |
| 807 | |
| 808 | if ((inchar = wgetch(stdscr)) == ERR) {WINE_FIXME("Ooch. somebody beat us\n");return;} |
| 809 | |
| 810 | WINE_TRACE("Got %d\n", inchar); |
| 811 | |
| 812 | if (inchar & KEY_CODE_YES) |
| 813 | { |
| 814 | numEvent = WCCURSES_FillCode(data, ir, inchar); |
| 815 | } |
| 816 | else |
| 817 | { |
| 818 | numEvent = WCCURSES_FillSimpleChar(ir, inchar); |
| 819 | } |
| 820 | if (numEvent) |
| 821 | WriteConsoleInput(data->hConIn, ir, numEvent, &n); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 822 | } |
| 823 | |
| 824 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 825 | * WCCURSES_DeleteBackend |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 826 | * |
| 827 | * |
| 828 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 829 | static void WCCURSES_DeleteBackend(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 830 | { |
| 831 | mmask_t mm; |
| 832 | |
| 833 | if (!PRIVATE(data)) return; |
| 834 | |
| 835 | CloseHandle(PRIVATE(data)->hInput); |
| 836 | |
| 837 | delwin(PRIVATE(data)->pad); |
| 838 | mousemask(PRIVATE(data)->initial_mouse_mask, &mm); |
| 839 | endwin(); |
| 840 | |
| 841 | HeapFree(GetProcessHeap(), 0, PRIVATE(data)->line); |
| 842 | HeapFree(GetProcessHeap(), 0, PRIVATE(data)); |
| 843 | PRIVATE(data) = NULL; |
| 844 | } |
| 845 | |
| 846 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 847 | * WCCURSES_MainLoop |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 848 | * |
| 849 | * |
| 850 | */ |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 851 | static int WCCURSES_MainLoop(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 852 | { |
| 853 | HANDLE hin[2]; |
| 854 | |
| 855 | hin[0] = PRIVATE(data)->hInput; |
| 856 | hin[1] = data->hSynchro; |
| 857 | |
| 858 | for (;;) |
| 859 | { |
| 860 | unsigned ret = WaitForMultipleObjects(2, hin, FALSE, INFINITE); |
| 861 | switch (ret) |
| 862 | { |
| 863 | case WAIT_OBJECT_0: |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 864 | WCCURSES_GetEvents(data); |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 865 | break; |
| 866 | case WAIT_OBJECT_0+1: |
| 867 | if (!WINECON_GrabChanges(data)) return 0; |
| 868 | break; |
| 869 | default: |
| 870 | WINE_ERR("got pb\n"); |
| 871 | /* err */ |
| 872 | break; |
| 873 | } |
| 874 | } |
| 875 | } |
| 876 | |
| 877 | /****************************************************************** |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 878 | * WCCURSES_InitBackend |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 879 | * |
| 880 | * Initialisation part II: creation of window. |
| 881 | * |
| 882 | */ |
Eric Pouech | 99bc640 | 2003-06-13 16:32:52 +0000 | [diff] [blame] | 883 | enum init_return WCCURSES_InitBackend(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 884 | { |
Mike McCormack | 9557d1b | 2003-08-20 04:19:01 +0000 | [diff] [blame] | 885 | if( !WCCURSES_bind_libcurses() ) |
| 886 | return init_failed; |
| 887 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 888 | data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_curse)); |
Eric Pouech | 99bc640 | 2003-06-13 16:32:52 +0000 | [diff] [blame] | 889 | if (!data->private) return init_failed; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 890 | |
Eric Pouech | 6a88716 | 2002-12-23 01:35:27 +0000 | [diff] [blame] | 891 | data->fnMainLoop = WCCURSES_MainLoop; |
| 892 | data->fnPosCursor = WCCURSES_PosCursor; |
| 893 | data->fnShapeCursor = WCCURSES_ShapeCursor; |
| 894 | data->fnComputePositions = WCCURSES_ComputePositions; |
| 895 | data->fnRefresh = WCCURSES_Refresh; |
| 896 | data->fnResizeScreenBuffer = WCCURSES_ResizeScreenBuffer; |
| 897 | data->fnSetTitle = WCCURSES_SetTitle; |
| 898 | data->fnScroll = WCCURSES_Scroll; |
| 899 | data->fnSetFont = WCCURSES_SetFont; |
| 900 | data->fnDeleteBackend = WCCURSES_DeleteBackend; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 901 | |
| 902 | if (wine_server_fd_to_handle(0, GENERIC_READ|SYNCHRONIZE, FALSE, |
| 903 | (obj_handle_t*)&PRIVATE(data)->hInput)) |
| 904 | { |
| 905 | WINE_FIXME("Cannot open 0\n"); |
Eric Pouech | 99bc640 | 2003-06-13 16:32:52 +0000 | [diff] [blame] | 906 | return init_failed; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 907 | } |
| 908 | |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 909 | /* FIXME: should find a good way to enable buffer scrolling |
| 910 | * For the time being, setting this to 1 will allow scrolling up/down |
| 911 | * on buffer with F11/F12. |
| 912 | */ |
Eric Pouech | 71a71b3 | 2003-09-22 19:31:32 +0000 | [diff] [blame] | 913 | /* PRIVATE(data)->allow_scroll = 1; */ |
Eric Pouech | 00d73d0 | 2003-02-14 19:23:36 +0000 | [diff] [blame] | 914 | |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 915 | initscr(); |
| 916 | |
| 917 | /* creating the basic colors - FIXME intensity not handled yet */ |
| 918 | if (has_colors()) |
| 919 | { |
| 920 | int i, j; |
| 921 | |
| 922 | start_color(); |
| 923 | for (i = 0; i < 8; i++) |
| 924 | for (j = 0; j < 8; j++) |
| 925 | init_pair(i | (j << 3), i, j); |
| 926 | } |
| 927 | |
| 928 | raw(); |
| 929 | noecho(); |
| 930 | intrflush(stdscr, FALSE); |
| 931 | nodelay(stdscr, TRUE); |
| 932 | keypad(stdscr, TRUE); |
Eric Pouech | c7b5d0a | 2003-03-04 02:13:05 +0000 | [diff] [blame] | 933 | if (data->curcfg.quick_edit) |
| 934 | { |
| 935 | mousemask(BUTTON1_PRESSED|BUTTON1_RELEASED| |
| 936 | BUTTON2_PRESSED|BUTTON2_RELEASED| |
| 937 | BUTTON3_PRESSED|BUTTON3_RELEASED| |
| 938 | BUTTON_SHIFT|BUTTON_CTRL|BUTTON_ALT|REPORT_MOUSE_POSITION, |
| 939 | &PRIVATE(data)->initial_mouse_mask); |
| 940 | /* no click event generation... we just need button up/down events |
| 941 | * it doesn't seem that mouseinterval(-1) behaves as documented... |
| 942 | * 0 seems to be better value to disable click event generation |
| 943 | */ |
| 944 | mouseinterval(0); |
| 945 | } |
| 946 | else |
| 947 | { |
| 948 | mousemask(0, &PRIVATE(data)->initial_mouse_mask); |
| 949 | } |
| 950 | |
Eric Pouech | 99bc640 | 2003-06-13 16:32:52 +0000 | [diff] [blame] | 951 | return init_success; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 952 | } |
| 953 | |
| 954 | #else |
Alexandre Julliard | 6dbf42c | 2003-06-14 01:34:53 +0000 | [diff] [blame] | 955 | enum init_return WCCURSES_InitBackend(struct inner_data* data) |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 956 | { |
Eric Pouech | 99bc640 | 2003-06-13 16:32:52 +0000 | [diff] [blame] | 957 | return init_not_supported; |
Eric Pouech | 09c9fed | 2002-12-13 23:37:06 +0000 | [diff] [blame] | 958 | } |
| 959 | #endif |