void ttext_::signal_handler_middle_button_click( const event::tevent event, bool& handled) { DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n"; paste_selection(true); handled = true; }
void ttext_::signal_handler_sdl_key_down(const event::tevent event , bool& handled , const SDLKey key , SDLMod modifier , const Uint16 unicode) { DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n"; // For copy/paste we use a different key on the MAC. Other ctrl modifiers won't // be modifed seems not to be required when I read the comment in // widgets/textbox.cpp:516. Would be nice if somebody on a MAC would test it. #ifdef __APPLE__ const unsigned copypaste_modifier = KMOD_LMETA | KMOD_RMETA; #else const unsigned copypaste_modifier = KMOD_CTRL; #endif switch(key) { case SDLK_LEFT : handle_key_left_arrow(modifier, handled); break; case SDLK_RIGHT : handle_key_right_arrow(modifier, handled); break; case SDLK_UP : handle_key_up_arrow(modifier, handled); break; case SDLK_DOWN : handle_key_down_arrow(modifier, handled); break; case SDLK_PAGEUP : handle_key_page_up(modifier, handled); break; case SDLK_PAGEDOWN : handle_key_page_down(modifier, handled); break; case SDLK_a : if(!(modifier & KMOD_CTRL)) { handle_key_default(handled, key, modifier, unicode); break; } // If ctrl-a is used for home drop the control modifier modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL); /* FALL DOWN */ case SDLK_HOME : handle_key_home(modifier, handled); break; case SDLK_e : if(!(modifier & KMOD_CTRL)) { handle_key_default(handled, key, modifier, unicode); break; } // If ctrl-e is used for end drop the control modifier modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL); /* FALL DOWN */ case SDLK_END : handle_key_end(modifier, handled); break; case SDLK_BACKSPACE : handle_key_backspace(modifier, handled); break; case SDLK_u : if(modifier & KMOD_CTRL) { handle_key_clear_line(modifier, handled); } else { handle_key_default(handled, key, modifier, unicode); } break; case SDLK_DELETE : handle_key_delete(modifier, handled); break; case SDLK_c : if(!(modifier & copypaste_modifier)) { handle_key_default(handled, key, modifier, unicode); break; } // atm we don't care whether there is something to copy or paste // if nothing is there we still don't want to be chained. copy_selection(false); handled = true; break; case SDLK_x : if(!(modifier & copypaste_modifier)) { handle_key_default(handled, key, modifier, unicode); break; } copy_selection(false); delete_selection(); handled = true; break; case SDLK_v : if(!(modifier & copypaste_modifier)) { handle_key_default(handled, key, modifier, unicode); break; } paste_selection(false); handled = true; break; default : handle_key_default(handled, key, modifier, unicode); } if(text_changed_callback_) { text_changed_callback_(this, this->text()); } }
/** * Edit a stream * @param console_in stream to read console from * @param console_out stream to write console to * @param stream stream to read/write file to */ void muon_edit(handle_t console_in, handle_t console_out, const char *title, handle_t stream) { int rc; int i; editor_t *ed = (editor_t *) neutron_malloc(sizeof(editor_t)); memset(ed, 0, sizeof(editor_t)); ed->console_in = console_in; ed->console_out = console_out; ed->title = title; ed->anchor = -1; rc = load_file(ed, stream); get_console_size(ed); bool done = false; int key; ed->refresh = 1; while (!done) { if (ed->refresh) { draw_screen(ed); draw_full_statusline(ed); ed->refresh = 0; ed->lineupdate = 0; } else if (ed->lineupdate) { update_line(ed); ed->lineupdate = 0; draw_statusline(ed); } else { draw_statusline(ed); } position_cursor(ed); key = getkey(ed); if (key >= ' ' && key <= 0x7F) { insert_char(ed, (char) key); } else { switch (key) { case KEY_F1: help(ed); break; case KEY_F5: redraw_screen(ed); break; case KEY_UP: up(ed, 0); break; case KEY_DOWN: down(ed, 0); break; case KEY_LEFT: left(ed, 0); break; case KEY_RIGHT: right(ed, 0); break; case KEY_HOME: home(ed, 0); break; case KEY_END: end(ed, 0); break; case KEY_PGUP: pageup(ed, 0); break; case KEY_PGDN: pagedown(ed, 0); break; case KEY_CTRL_RIGHT: wordright(ed, 0); break; case KEY_CTRL_LEFT: wordleft(ed, 0); break; case KEY_CTRL_HOME: top(ed, 0); break; case KEY_CTRL_END: bottom(ed, 0); break; case KEY_SHIFT_UP: up(ed, 1); break; case KEY_SHIFT_DOWN: down(ed, 1); break; case KEY_SHIFT_LEFT: left(ed, 1); break; case KEY_SHIFT_RIGHT: right(ed, 1); break; case KEY_SHIFT_PGUP: pageup(ed, 1); break; case KEY_SHIFT_PGDN: pagedown(ed, 1); break; case KEY_SHIFT_HOME: home(ed, 1); break; case KEY_SHIFT_END: end(ed, 1); break; case KEY_SHIFT_CTRL_RIGHT: wordright(ed, 1); break; case KEY_SHIFT_CTRL_LEFT: wordleft(ed, 1); break; case KEY_SHIFT_CTRL_HOME: top(ed, 1); break; case KEY_SHIFT_CTRL_END: bottom(ed, 1); break; case ctrl('a'): select_all(ed); break; case ctrl('c'): copy_selection(ed); break; case ctrl('f'): find_text(ed, 0); break; case ctrl('l'): goto_line(ed); break; case ctrl('g'): find_text(ed, 1); break; case KEY_TAB: indent(ed, INDENT); break; case KEY_SHIFT_TAB: unindent(ed, INDENT); break; case KEY_ENTER: newline(ed); break; case KEY_BACKSPACE: backspace(ed); break; case KEY_DEL: del(ed); break; case ctrl('x'): cut_selection(ed); break; case ctrl('z'): undo(ed); break; case ctrl('r'): redo(ed); break; case ctrl('v'): paste_selection(ed); break; case ctrl('s'): save_editor(ed); break; case ctrl('q'): done = close_editor(ed); break; } } } gotoxy(ed, 0, ed->lines + 1); outstr(ed, RESET_COLOR CLREOL); if (ed->clipboard) neutron_free(ed->clipboard); if (ed->search) neutron_free(ed->search); if (ed->linebuf) neutron_free(ed->linebuf); clear_undo(ed); neutron_free(ed); }
int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { struct tty_struct * tty; struct tty_struct * other_tty; struct tty_struct * termios_tty; pid_t pgrp; int dev; int termios_dev; int retval; if (MAJOR(file->f_rdev) != TTY_MAJOR) { printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n"); return -EINVAL; } dev = MINOR(file->f_rdev); tty = TTY_TABLE(dev); if (!tty) return -EINVAL; if (IS_A_PTY(dev)) other_tty = tty_table[PTY_OTHER(dev)]; else other_tty = NULL; if (IS_A_PTY_MASTER(dev)) { termios_tty = other_tty; termios_dev = PTY_OTHER(dev); } else { termios_tty = tty; termios_dev = dev; } switch (cmd) { case TCGETS: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (struct termios)); if (retval) return retval; memcpy_tofs((struct termios *) arg, termios_tty->termios, sizeof (struct termios)); return 0; case TCSETSF: case TCSETSW: case TCSETS: retval = check_change(termios_tty, termios_dev); if (retval) return retval; if (cmd == TCSETSF || cmd == TCSETSW) { if (cmd == TCSETSF) flush_input(termios_tty); wait_until_sent(termios_tty, 0); } return set_termios(termios_tty, (struct termios *) arg, termios_dev); case TCGETA: return get_termio(termios_tty,(struct termio *) arg); case TCSETAF: case TCSETAW: case TCSETA: retval = check_change(termios_tty, termios_dev); if (retval) return retval; if (cmd == TCSETAF || cmd == TCSETAW) { if (cmd == TCSETAF) flush_input(termios_tty); wait_until_sent(termios_tty, 0); } return set_termio(termios_tty, (struct termio *) arg, termios_dev); case TCXONC: retval = check_change(tty, dev); if (retval) return retval; switch (arg) { case TCOOFF: stop_tty(tty); break; case TCOON: start_tty(tty); break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) put_tty_queue(STOP_CHAR(tty), &tty->write_q); break; case TCION: if (START_CHAR(tty) != __DISABLED_CHAR) put_tty_queue(START_CHAR(tty), &tty->write_q); break; default: return -EINVAL; } return 0; case TCFLSH: retval = check_change(tty, dev); if (retval) return retval; switch (arg) { case TCIFLUSH: flush_input(tty); break; case TCIOFLUSH: flush_input(tty); /* fall through */ case TCOFLUSH: flush_output(tty); break; default: return -EINVAL; } return 0; case TIOCEXCL: set_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNXCL: clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCSCTTY: if (current->leader && (current->session == tty->session)) return 0; /* * The process must be a session leader and * not have a controlling tty already. */ if (!current->leader || (current->tty >= 0)) return -EPERM; if (tty->session > 0) { /* * This tty is already the controlling * tty for another session group! */ if ((arg == 1) && suser()) { /* * Steal it away */ struct task_struct *p; for_each_task(p) if (p->tty == dev) p->tty = -1; } else return -EPERM; } current->tty = dev; tty->session = current->session; tty->pgrp = current->pgrp; return 0; case TIOCGPGRP: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (pid_t)); if (retval) return retval; if (current->tty != termios_dev) return -ENOTTY; put_fs_long(termios_tty->pgrp, (pid_t *) arg); return 0; case TIOCSPGRP: retval = check_change(termios_tty, termios_dev); if (retval) return retval; if ((current->tty < 0) || (current->tty != termios_dev) || (termios_tty->session != current->session)) return -ENOTTY; pgrp = get_fs_long((pid_t *) arg); if (pgrp < 0) return -EINVAL; if (session_of_pgrp(pgrp) != current->session) return -EPERM; termios_tty->pgrp = pgrp; return 0; case TIOCOUTQ: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (unsigned long)); if (retval) return retval; put_fs_long(CHARS(&tty->write_q), (unsigned long *) arg); return 0; case TIOCINQ: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (unsigned long)); if (retval) return retval; if (L_ICANON(tty)) put_fs_long(inq_canon(tty), (unsigned long *) arg); else put_fs_long(CHARS(&tty->secondary), (unsigned long *) arg); return 0; case TIOCSTI: if ((current->tty != dev) && !suser()) return -EPERM; retval = verify_area(VERIFY_READ, (void *) arg, 1); if (retval) return retval; put_tty_queue(get_fs_byte((char *) arg), &tty->read_q); TTY_READ_FLUSH(tty); return 0; case TIOCGWINSZ: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (struct winsize)); if (retval) return retval; memcpy_tofs((struct winsize *) arg, &tty->winsize, sizeof (struct winsize)); return 0; case TIOCSWINSZ: if (IS_A_PTY_MASTER(dev)) set_window_size(other_tty,(struct winsize *) arg); return set_window_size(tty,(struct winsize *) arg); case TIOCLINUX: switch (get_fs_byte((char *)arg)) { case 0: return do_screendump(arg); case 1: return do_get_ps_info(arg); #ifdef CONFIG_SELECTION case 2: return set_selection(arg); case 3: return paste_selection(tty); case 4: unblank_screen(); return 0; #endif /* CONFIG_SELECTION */ default: return -EINVAL; } case TIOCCONS: if (IS_A_CONSOLE(dev)) { if (!suser()) return -EPERM; redirect = NULL; return 0; } if (redirect) return -EBUSY; if (!suser()) return -EPERM; if (IS_A_PTY_MASTER(dev)) redirect = other_tty; else if (IS_A_PTY_SLAVE(dev)) redirect = tty; else return -ENOTTY; return 0; case FIONBIO: arg = get_fs_long((unsigned long *) arg); if (arg) file->f_flags |= O_NONBLOCK; else file->f_flags &= ~O_NONBLOCK; return 0; case TIOCNOTTY: if (current->tty != dev) return -ENOTTY; if (current->leader) disassociate_ctty(0); current->tty = -1; return 0; case TIOCGETD: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (unsigned long)); if (retval) return retval; put_fs_long(tty->disc, (unsigned long *) arg); return 0; case TIOCSETD: retval = check_change(tty, dev); if (retval) return retval; arg = get_fs_long((unsigned long *) arg); return tty_set_ldisc(tty, arg); case TIOCGLCKTRMIOS: arg = get_fs_long((unsigned long *) arg); retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (struct termios)); if (retval) return retval; memcpy_tofs((struct termios *) arg, &termios_locked[termios_dev], sizeof (struct termios)); return 0; case TIOCSLCKTRMIOS: if (!suser()) return -EPERM; arg = get_fs_long((unsigned long *) arg); memcpy_fromfs(&termios_locked[termios_dev], (struct termios *) arg, sizeof (struct termios)); return 0; case TIOCPKT: if (!IS_A_PTY_MASTER(dev)) return -ENOTTY; retval = verify_area(VERIFY_READ, (void *) arg, sizeof (unsigned long)); if (retval) return retval; if (get_fs_long(arg)) { if (!tty->packet) { tty->packet = 1; tty->link->ctrl_status = 0; } } else tty->packet = 0; return 0; case TCSBRK: case TCSBRKP: retval = check_change(tty, dev); if (retval) return retval; wait_until_sent(tty, 0); if (!tty->ioctl) return 0; tty->ioctl(tty, file, cmd, arg); return 0; default: if (tty->ioctl) { retval = (tty->ioctl)(tty, file, cmd, arg); if (retval != -EINVAL) return retval; } if (ldiscs[tty->disc].ioctl) { retval = (ldiscs[tty->disc].ioctl) (tty, file, cmd, arg); return retval; } return -EINVAL; }
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; } } }
/* * On button press, we get an explicit number (1,2,3), and on release we don't * really know which button, but assume it is the last-pressed button. */ int on_mouse_click(int button, int y, int x) { static int first_x, first_y, pending; WINDOW *this_wp, *that_wp; int status; if (button > 0) { if (valid_window(this_wp = row2window(y)) && (y != mode_row(this_wp))) { /* * If we get a click on the "<" marking the left side * of a shifted window, force the screen right. This * makes it more consistent if there's a tab. */ if (w_val(this_wp, WVAL_SIDEWAYS) && x == 0) { mvleftwind(FALSE, 1); } if (!doingsweep) { if (button == BTN_EXTEND) { first_x = offs2col(this_wp, this_wp->w_dot.l, this_wp->w_dot.o); first_y = line_no(this_wp->w_bufp, this_wp->w_dot.l) - line_no(this_wp->w_bufp, this_wp->w_line.l); } else { first_x = x; first_y = y; } } status = setcursor(y, x); /* * Check for button1-down while we're in multimotion * sweep, so we can suppress highlighting extension. */ if (button != BTN_EXTEND && status == TRUE && doingsweep) { status = SORTOFTRUE; if (button == BTN_BEGIN) { first_x = x; first_y = y; } } } else { /* pressed button on modeline */ status = SORTOFTRUE; first_x = x; first_y = y; } pending = button; } else if (pending) { button = pending; pending = FALSE; this_wp = row2window(y); that_wp = row2window(first_y); if (this_wp == 0 || that_wp == 0 || reading_msg_line) { TRACE(("MOUSE cannot move msg-line\n")); status = FALSE; } else if (insertmode && (this_wp != curwp || that_wp != curwp)) { TRACE(("MOUSE cannot move from window while inserting\n")); kbd_alarm(); status = ABORT; } else if (first_y == mode_row(that_wp)) { /* drag modeline? */ if (first_y == y) { sel_release(); status = SEL_RELEASE; } else { WINDOW *save_wp = curwp; TRACE(("MOUSE dragging modeline\n")); set_curwp(that_wp); status = shrinkwind(FALSE, first_y - y); set_curwp(save_wp); } } else if (y != first_y || x != first_x) { /* drag selection */ if (button == BTN_PASTE) { (void) setcursor(y, x); status = paste_selection(); } else if (doingsweep) { switch (button) { case BTN_BEGIN: (void) release_selection(TRUE); status = setcursor(first_y, first_x); if (status == TRUE) { MK = DOT; status = SEL_BEGIN; TRACE(("MOUSE setting SEL_BEGIN MK %d.%d\n", line_no(curbp, MK.l), MK.o)); } break; default: (void) setcursor(y, x); status = SEL_EXTEND; TRACE(("MOUSE setting SEL_EXTEND DOT %d.%d MK %d.%d\n", line_no(curbp, MK.l), MK.o, line_no(curbp, DOT.l), DOT.o)); break; } } else { TRACE(("MOUSE begin multimotion on button%d-up\n", button)); if (button == BTN_EXTEND) { (void) setcursor(y, x); y = first_y; x = first_x; } do_sweep(SORTOFTRUE); (void) sel_begin(); (void) sel_setshape(rgn_EXACT); (void) setcursor(y, x); status = multimotion(TRUE, 1); TRACE(("MOUSE end multimotion after button%d-up\n", button)); if (status == SEL_PASTE) status = paste_selection(); } } else { /* position the cursor */ TRACE(("MOUSE button %d position cursor\n", button)); (void) setcursor(y, x); switch (button) { case BTN_BEGIN: status = SEL_FINISH; break; case BTN_PASTE: status = paste_selection(); break; default: status = release_selection(TRUE); break; } } } else { TRACE(("MOUSE ignored (illegal state)\n")); status = FALSE; } if (status == TRUE || status >= SORTOFTRUE) (void) update(TRUE); TRACE(("MOUSE status:%d\n", status)); return status; }