/* * putting the input tty in polling mode lets us check for * user typeahead */ static void set_kbd_polling(int yes) { static int kbd_flags = -1; /* initial keyboard flags */ static int kbd_is_polled; /* are we in O_NDELAY mode? */ if (kbd_flags == -1) { kbd_flags = fcntl(0, F_GETFL, 0); if (kbd_flags == -1) imdying(SIGINT); kbd_is_polled = FALSE; } if (yes) { /* turn polling on -- put us in NDELAY mode */ if (!kbd_is_polled) { if (fcntl(0, F_SETFL, kbd_flags | O_NDELAY) < 0) imdying(SIGINT); } kbd_is_polled = TRUE; /* I think */ } else { /* turn polling off -- clear NDELAY mode */ if (kbd_is_polled) { if (fcntl(0, F_SETFL, kbd_flags) < 0) imdying(SIGINT); } kbd_is_polled = FALSE; } }
static BOOL WINAPI nthandler(DWORD ctrl_type) { switch (ctrl_type) { case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: imdying(1); break; } return TRUE; }
static int vl_getchar(void) { char c; int n; n = (int) read(0, &c, (size_t) 1); if (n <= 0) { if (n < 0 && errno == EINTR) return -1; imdying(SIGINT); } return (c & 0xff); }
static int ntconio_getch(void) { INPUT_RECORD ir; DWORD nr; int key; #ifdef VAL_AUTOCOLOR int milli_ac, orig_milli_ac; #endif if (saveCount > 0) { saveCount--; return savedChar; } #ifdef VAL_AUTOCOLOR orig_milli_ac = global_b_val(VAL_AUTOCOLOR); #endif for_ever { #ifdef VAL_AUTOCOLOR milli_ac = orig_milli_ac; while (milli_ac > 0) { if (PeekConsoleInput(hConsoleInput, &ir, 1, &nr) == 0) break; /* ?? system call failed ?? */ if (nr > 0) break; /* something in the queue */ Sleep(20); /* sleep a bit, but be responsive to keybd input */ milli_ac -= 20; } if (orig_milli_ac && milli_ac <= 0) { ac_active = TRUE; autocolor(); ac_active = FALSE; } #endif if (!ReadConsoleInput(hConsoleInput, &ir, 1, &nr)) imdying(0); switch (ir.EventType) { case KEY_EVENT: key = decode_key_event(&ir); if (key == NOKYMAP) continue; if (ir.Event.KeyEvent.wRepeatCount > 1) { saveCount = ir.Event.KeyEvent.wRepeatCount - 1; savedChar = key; } return key; case WINDOW_BUFFER_SIZE_EVENT: newscreensize( ir.Event.WindowBufferSizeEvent.dwSize.Y, ir.Event.WindowBufferSizeEvent.dwSize.X ); GetConsoleScreenBufferInfo(hConsoleOutput, &csbi); continue; case MOUSE_EVENT: handle_mouse_event(ir.Event.MouseEvent); continue; } } }
static void handle_mouse_event(MOUSE_EVENT_RECORD mer) { static DWORD lastclick = 0; static int clicks = 0; int onmode = FALSE; COORD current, first, latest; MARK lmbdn_mark; /* left mouse button down here */ int sel_pending = 0, state; DWORD thisclick; UINT clicktime = GetDoubleClickTime(); buttondown = FALSE; for_ever { current = mer.dwMousePosition; switch (mer.dwEventFlags) { case 0: state = mer.dwButtonState; if (state == 0) { /* button released */ thisclick = GetTickCount(); TRACE(("CLICK %d/%d\n", lastclick, thisclick)); if (thisclick - lastclick < clicktime) { clicks++; TRACE(("MOUSE CLICKS %d\n", clicks)); } else { clicks = 0; } lastclick = thisclick; switch (clicks) { case 1: on_double_click(); break; case 2: on_triple_click(); break; } if (buttondown) { int dummy; halt_autoscroll_thread(); /* Finalize cursor position. */ (void) MouseClickSetPos(¤t, &dummy); if (!(onmode || sel_pending)) sel_yank(0); } return; } if (state & FROM_LEFT_1ST_BUTTON_PRESSED) { if (MouseClickSetPos(¤t, &onmode)) { first = latest = current; lmbdn_mark = DOT; sel_pending = FALSE; mouse_wp = row2window(latest.Y); if (onmode) { buttondown = TRUE; sel_release(); update(TRUE); } else { HWND hwnd; (void) update(TRUE); /* possible wdw change */ buttondown = FALSE; /* until all inits are successful */ /* Capture mouse to console vile's window handle. */ hwnd = GetVileWindow(); (void) SetCapture(hwnd); /* Compute pixel height of each row on screen. */ (void) GetClientRect(hwnd, &client_rect); row_height = client_rect.bottom / term.rows; /* * Create mutex to ensure that main thread and worker * thread don't update display at the same time. */ if ((hAsMutex = CreateMutex(0, FALSE, 0)) == NULL) mlforce("[Can't create autoscroll mutex]"); else { /* * Setup a worker thread to act as a pseudo * timer that kicks off autoscroll when * necessary. */ if (_beginthread(autoscroll_thread, 0, NULL) == (unsigned long) -1) { (void) CloseHandle(hAsMutex); mlforce("[Can't create autoscroll thread]"); } else sel_pending = buttondown = TRUE; } if (!buttondown) (void) ReleaseCapture(); } } } else if (state & FROM_LEFT_2ND_BUTTON_PRESSED) { if (MouseClickSetPos(¤t, &onmode) && !onmode) { sel_yank(0); sel_release(); paste_selection(); (void) update(TRUE); } return; } else { if (MouseClickSetPos(¤t, &onmode) && onmode) { sel_release(); update(TRUE); } else { kbd_alarm(); } } break; case MOUSE_MOVED: if (!buttondown) return; if (onmode) { /* on mode line, resize window (if possible). */ if (!adjust_window(mouse_wp, ¤t, &latest)) { /* * left mouse button still down, but cursor moved off mode * line. Update latest to keep track of cursor in case * it wanders back on the mode line. */ latest = current; } } else { mousemove(&sel_pending, &first, ¤t, &lmbdn_mark, (mer.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ); } break; #ifdef MOUSE_WHEELED case MOUSE_WHEELED: /* * Trial and error experimentation shows that dwButtonState * has its high bit set when the wheel moves back and not * set otherwise. */ mvupwind(TRUE, ((long) mer.dwButtonState < 0) ? -3 : 3); update(TRUE); return; #endif /* MOUSE_WHEELED */ } for_ever { INPUT_RECORD ir; DWORD nr; int key; if (!ReadConsoleInput(hConsoleInput, &ir, 1, &nr)) imdying(0); switch (ir.EventType) { case KEY_EVENT: key = decode_key_event(&ir); if (key == ESC) { if (buttondown) halt_autoscroll_thread(); sel_release(); (void) update(TRUE); return; } continue; case MOUSE_EVENT: mer = ir.Event.MouseEvent; break; } break; } } }