📄 command.c
字号:
PVTS(r, page)->cmdbuf_endp - PVTS(r, page)->cmdbuf_ptr; assert (n == BUFSIZ - 1); assert (PVTS(r, page)->cmdbuf_ptr < PVTS(r, page)->cmdbuf_endp); MEMMOVE(PVTS(r, page)->cmdbuf_base, PVTS(r, page)->cmdbuf_ptr, len); PVTS(r, page)->cmdbuf_ptr = PVTS(r, page)->cmdbuf_base; PVTS(r, page)->cmdbuf_endp -= n; assert (PVTS(r, page)->cmdbuf_base <= PVTS(r, page)->cmdbuf_endp); }}/* * rxvt_cmd_getc() - Return next input character. * * Return the next input character after first passing any keyboard input to the * command. *//* INTPROTO */unsigned charrxvt_cmd_getc(rxvt_t *r, int* p_page){ int page = *p_page;#define TIMEOUT_USEC 5000 fd_set readfds; int quick_timeout, select_res;#ifdef POINTER_BLANK int want_motion_time = 0;#endif#ifdef CURSOR_BLINK int want_keypress_time = 0;#endif struct timeval value;#if defined(POINTER_BLANK) || defined(CURSOR_BLINK) || defined(TRANSPARENT) struct timeval tp;#endif struct rxvt_hidden *h = r->h; register int i; while (1) { /* loop until we can return something */ if (-1 != page) { assert (PVTS(r, page)->cmdbuf_base <= PVTS(r, page)->cmdbuf_endp); /* already have something in the buffer */ if (PVTS(r, page)->cmdbuf_ptr < PVTS(r, page)->cmdbuf_endp) return *(PVTS(r, page)->cmdbuf_ptr)++; /* output any pending chars of page's v_buffer */ if (PVTS(r, page)->v_bufstr < PVTS(r, page)->v_bufptr) rxvt_tt_write(r, page, NULL, 0); } else { assert (AVTS(r)->cmdbuf_base <= AVTS(r)->cmdbuf_endp); /* if -1 == page, we only process the active tab here */ if (AVTS(r)->cmdbuf_ptr < AVTS(r)->cmdbuf_endp) { *p_page = ATAB(r); return *(AVTS(r)->cmdbuf_ptr)++; } /* output any pending chars of page's v_buffer */ if (AVTS(r)->v_bufstr < AVTS(r)->v_bufptr) rxvt_tt_write(r, ATAB(r), NULL, 0); /* * if there is no data in active tab, we go to process the X events * before trying to find a tab that has some input/output. this * should improve the response performance of the active tab. */ }#if defined(POINTER_BLANK) || defined(CURSOR_BLINK) || defined(TRANSPARENT) /* presume == 0 implies time not yet retrieved */ tp.tv_sec = tp.tv_usec = 0;#endif /* POINTER_BLANK || CURSOR_BLINK || TRANSPARENT*/#ifdef CURSOR_BLINK want_keypress_time = 0;#endif /* CURSOR_BLINK */#ifdef POINTER_BLANK if (r->Options & Opt_pointerBlank) want_motion_time = 0;#endif /* POINTER_BLANK */ /* process all pending X events */ while (XPending(r->Xdisplay)) { XEvent xev; XNextEvent(r->Xdisplay, &xev);#ifdef CURSOR_BLINK if ( (r->Options & Opt_cursorBlink) && xev.type == KeyPress ) { if (h->hidden_cursor) { DBG_MSG(1, (stderr,"** hide cursor on keypress\n")); h->hidden_cursor = 0; h->want_refresh = 1; } want_keypress_time = 1; }#endif /* CURSOR_BLINK */#ifdef POINTER_BLANK if ( (r->Options & Opt_pointerBlank) && (h->pointerBlankDelay > 0) ) { if ( xev.type == MotionNotify || xev.type == ButtonPress || xev.type == ButtonRelease ) { /* only work for current active tab */ if (AVTS(r)->hidden_pointer) rxvt_pointer_unblank(r, ATAB(r)); want_motion_time = 1; } /* only work for current active tab */ if (xev.type == KeyPress && !AVTS(r)->hidden_pointer) rxvt_pointer_blank(r, ATAB(r)); }#endif /* POINTER_BLANK */#ifdef USE_XIM if (r->h->Input_Context != NULL) { if (!XFilterEvent(&xev, xev.xany.window)) rxvt_process_x_event(r, &xev); h->event_type = xev.type; } else#endif /* USE_XIM */ rxvt_process_x_event(r, &xev); /* In case button actions pushed chars to cmdbuf. */ if (-1 != page) { assert (PVTS(r, page)->cmdbuf_base <= PVTS(r, page)->cmdbuf_endp); if (PVTS(r, page)->cmdbuf_ptr < PVTS(r, page)->cmdbuf_endp) return *(PVTS(r, page)->cmdbuf_ptr)++; } else { assert (AVTS(r)->cmdbuf_base <= AVTS(r)->cmdbuf_endp); /* * -1 == page, only try the active tab here. we will handle * inactive tabs after processed all X events */ if (AVTS(r)->cmdbuf_ptr < AVTS(r)->cmdbuf_endp) { *p_page = ATAB(r); return *(AVTS(r)->cmdbuf_ptr)++; } /* * Notice that there might be something BAD here: the active tab * is changed by user interaction and data are pushed into * previous active tab (now inactive). Need to study on this in * the future. */ } } /* while ((XPending(r->Xdisplay)) */ if (-1 == page) { /* * in case -1 == page, and there's no X events to process. we will * not go to the select call if there's already input/output in some * tabs. to reach here, we have tried active tab but with no luck. */ if (rxvt_find_cmd_child (r, p_page)) return *(PVTS(r, *p_page)->cmdbuf_ptr)++; }#ifdef CURSOR_BLINK if (want_keypress_time) { /* reset last cursor change time on keypress event */ (void) gettimeofday (&tp, NULL); DBG_MSG(3, (stderr,"** init cursor time on keypress\n")); h->lastcursorchange.tv_sec = tp.tv_sec; h->lastcursorchange.tv_usec = tp.tv_usec; }#endif /* CURSOR_BLINK */#ifdef POINTER_BLANK if ((r->Options & Opt_pointerBlank) && want_motion_time) { (void) gettimeofday (&tp, NULL); h->lastmotion.tv_sec = tp.tv_sec; h->lastmotion.tv_usec = tp.tv_usec; }#endif /* POINTER_BLANK */ /* * The command input buffer is empty and we have no pending X events */ quick_timeout = 0;#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING) if (h->mouse_slip_wheel_speed) { quick_timeout = 1; /* Only work for current active tab */ if ( !h->mouse_slip_wheel_delay-- && rxvt_scr_page( r, ATAB(r), h->mouse_slip_wheel_speed >0 ? UP : DN, abs(h->mouse_slip_wheel_speed) ) ) { h->mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY; h->refresh_type |= SMOOTH_REFRESH; h->want_refresh = 1; } }#endif /* MOUSE_WHEEL && MOUSE_SLIP_WHEELING */#ifdef SELECTION_SCROLLING if (h->pending_scroll_selection) { quick_timeout = 1; /* Only work for current active tab */ if ( !h->scroll_selection_delay-- && rxvt_scr_page(r, ATAB(r), h->scroll_selection_dir, h->scroll_selection_lines) ) { rxvt_selection_extend(r, ATAB(r), h->selection_save_x, h->selection_save_y, h->selection_save_state); h->scroll_selection_delay = SCROLLBAR_CONTINUOUS_DELAY; h->refresh_type |= SMOOTH_REFRESH; h->want_refresh = 1; } }#endif /* SELECTION_SCROLLING */#ifdef HAVE_SCROLLBARS# ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING if (scrollbar_isUp() || scrollbar_isDn()) { quick_timeout = 1; /* Only work for current active tab */ if ( !h->scroll_arrow_delay-- && rxvt_scr_page(r, ATAB(r), scrollbar_isUp()?UP:DN, 1) ) { h->scroll_arrow_delay = SCROLLBAR_CONTINUOUS_DELAY; h->refresh_type |= SMOOTH_REFRESH; h->want_refresh = 1; } }# endif /* NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING */#endif /* Prepare to read in from children's file descriptors */ FD_ZERO(&readfds); for (i = 0; i <= LTAB(r); i ++) { /* remember to skip held childrens */ if ((r->Options2 & Opt2_holdExit) && (PVTS(r, i)->hold > 1)) { DBG_MSG(2,(stderr," not listen on vt[%d].cmd_fd\n",i)); continue; } FD_SET(PVTS(r, i)->cmd_fd, &readfds); DBG_MSG(2, (stderr, " listen on vt[%d].cmd_fd = %d\n", i, PVTS(r, i)->cmd_fd)); } FD_SET(r->Xfd, &readfds);#ifdef HAVE_X11_SM_SMLIB_H if (-1 != r->TermWin.ice_fd) FD_SET(r->TermWin.ice_fd, &readfds);#endif value.tv_usec = TIMEOUT_USEC; value.tv_sec = 0; if (!r->TermWin.mapped) quick_timeout = 0; else { quick_timeout |= (h->want_refresh || h->want_clip_refresh);#ifdef TRANSPARENT quick_timeout |= h->want_full_refresh;#endif /* TRANSPARENT */ }#if defined(POINTER_BLANK) || defined(CURSOR_BLINK) || defined(TRANSPARENT) { int set_quick_timeout = 0; long csdiff, psdiff, bsdiff; csdiff = psdiff = bsdiff = 60000000L; /* or, say, LONG_MAX */# ifdef TRANSPARENT /* Check if we should refresh our background */ if( h->lastCNotify.tv_sec ) { gettimeofday( &tp, NULL); bsdiff = (tp.tv_sec - h->lastCNotify.tv_sec) * 1000000L + tp.tv_usec - h->lastCNotify.tv_usec; if( bsdiff > h->bgRefreshInterval) { bsdiff = 0; h->lastCNotify.tv_sec = 0; /* Only refresh bg image if we've moved. */ if( ( !r->h->bgGrabbed || r->h->prevPos.x != r->szHint.x || r->h->prevPos.y != r->szHint.y || r->h->prevPos.width != r->szHint.width || r->h->prevPos.height != r->szHint.height) && rxvt_check_our_parents( r )) { h->want_full_refresh = 1; } } else bsdiff = h->bgRefreshInterval - bsdiff; DBG_MSG( 3, (stderr, "Waiting %ld.%06ld seconds longer for bg refresh\n", bsdiff / 1000000L, bsdiff % 1000000L)); set_quick_timeout = 1; }# endif /* TRANSPARENT */# if defined(CURSOR_BLINK) /* * Cursor only blinks when terminal window is focused. */ if ((r->Options & Opt_cursorBlink) && r->TermWin.focus) { DBG_MSG(3, (stderr,"** get cursor time on select\n")); (void)gettimeofday(&tp, NULL); csdiff = (tp.tv_sec - h->lastcursorchange.tv_sec) * 1000000L + tp.tv_usec - h->lastcursorchange.tv_usec; if (csdiff > h->blinkInterval) { /* XXX: settable blink times */ h->lastcursorchange.tv_sec = tp.tv_sec; h->lastcursorchange.tv_usec = tp.tv_usec; h->hidden_cursor = !h->hidden_cursor; DBG_MSG(3, (stderr, "%s\n", h->hidden_cursor ? "** hide cursor" : "** show cursor")); h->want_refresh = 1; csdiff = 0; } else csdiff = h->blinkInterval - csdiff; set_quick_timeout = 1; }# endif /* CURSOR_BLINK */# if defined(POINTER_BLANK) /* * If we haven't moved the pointer for a while */ if ( (r->Options & Opt_pointerBlank) && (h->pointerBlankDelay > 0) && (AVTS(r)->hidden_pointer == 0) ) { long pdelay; DBG_MSG(3, (stderr,"** get pointer time on select\n")); (void) gettimeofday(&tp, NULL); psdiff = (tp.tv_sec - h->lastmotion.tv_sec) * 1000000L + tp.tv_usec - h->lastmotion.tv_usec; pdelay = h->pointerBlankDelay * 1000000L; /* only work for current active tab */ if (psdiff >= pdelay) rxvt_pointer_blank(r, ATAB(r)); else { set_quick_timeout = 1; psdiff = pdelay - psdiff; } }# endif /* POINTER_BLANK */ if (!quick_timeout && set_quick_timeout) { MIN_IT(csdiff, bsdiff); MIN_IT(csdiff, psdiff); value.tv_sec = csdiff / 1000000L; value.tv_usec = csdiff % 1000000L; quick_timeout = 1; } }#endif /* POINTER_BLANK || CURSOR_BLINK || TRANSPARENT */ /* Now begin to read in from children's file descriptors */ DBG_MSG( 4, (stderr, "Waiting for %lumu for child\n", quick_timeout ? value.tv_sec * 1000000LU + value.tv_usec : ULONG_MAX)); if ( (select_res = select(r->num_fds, &readfds, NULL, NULL, (quick_timeout ? &value : NULL))) == 0 ) { /* * select statement timed out - we're not hard and fast scrolling */ h->refresh_limit = 1; }#ifdef CURSOR_BLINK /* * 2006-02-16 gi1242: Unnecessary. We should only refresh when the * cursor changes state. (I.e on one of the timeouts). Refreshing always * wastes CPU. */#if 0 if (r->Options & Opt_cursorBlink) h->want_refresh = 1;#endif#endif /* CURSOR_BLINK */ /* * Handle the children that have generate input. Notice in this loop we * only process input, but do NOT determine the child we want to return. */ for (i = 0; i <= LTAB(r); i++) { int n = 0; unsigned int count, bufsiz; /* check next file descriptor if this one has nothing to read in. */ if (!FD_ISSET(PVTS(r, i)->cmd_fd, &readfds)) continue; DBG_MSG(1, (stderr, "reading from shell %d\n", i)); /* check our command buffer before reading data */ rxvt_check_cmdbuf (r, i); assert (PVTS(r, i)->cmdbuf_base <= PVTS(r, i)->cmdbuf_endp); /* The buffer size is the buffer length - used length */ count = bufsiz = (BUFSIZ - 1) - (PVTS(r, i)->cmdbuf_endp - PVTS(r, i)->cmdbuf_base); while (count) { DBG_MSG(1, (stderr, "read maximal %u bytes\n", count)); errno = 0; /* clear errno */ n = read (PVTS(r, i)->cmd_fd, PVTS(r, i)->cmdbuf_endp, count); DBG_MSG(1, (stderr, "read %d bytes\n", n)); if (n > 0) { /* Update count and buffer pointer */ count -= n; PVTS(r, i)->cmdbuf_endp += n; /* * check the file descriptor to see if there are further * input, this is to avoid blocking on read(), which seems * to be an issue when running mc in bash. this will waste * several CPU cycles, but it's safer than blocking. */ FD_ZERO(&readfds); FD_SET(PVTS(r, i)->cmd_fd, &readfds); value.tv_sec = 0; value.tv_usec = 5; /* time out, 5us */ select_res = select(r->num_fds, &readfds, NULL, NULL, &value); if (0 == select_res) { /* time-out, no further data to read */ DBG_MSG(1, (stderr, "no further data\n")); break; } if (-1 == select_res) { /* error, stop reading */ DBG_MSG(1, (stderr, "select error\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -