:-> Matching is now done on UTF-8, which makes it almost instant.
- perl/selection, perl/selection-autotransform: regexes are now
being interpreted in the locale urxvt was started.
+ - perl-overlays and refresh hooks were not applied in correct order.
+ - changed coordinate-system of view_start/nsaved to be top to bottom.
- applied many patches by Emanuele Giaquinta that clean the code up
and fix more bugs in the utmp logging code.
- add tsl/fsl and related capabilities to the terminfo description,
for (;;)
{
- const line_t &l = ROW(y - view_start);
+ const line_t &l = ROW(y + view_start);
text_t t = l.t[x];
{
if (SHOULD_INVOKE (HOOK_LINE_UPDATE))
{
- int row = -view_start;
+ int row = view_start;
int end_row = row + nrow;
- while (row > -nsaved && ROW (row - 1).is_longer ())
+ while (row > top_row && ROW (row - 1).is_longer ())
--row;
do
|| mouse_slip_wheel_speed < 0 ? scr_page (DN, -mouse_slip_wheel_speed)
: scr_page (UP, mouse_slip_wheel_speed))
{
- if (view_start == nsaved ||
- view_start == 0)
+ if (view_start == top_row || view_start == 0)
mouse_slip_wheel_speed = 0;
refresh_type |= SMOOTH_REFRESH;
no re 'eval'; # just to be sure
if (my $re = eval { qr/$search/ }) {
- while ($self->nrow > $row && $row > -$self->nsaved) {
+ while ($self->nrow > $row && $row > $self->top_row) {
my $line = $self->line ($row)
or last;
} while $text =~ /$re/g;
$self->{row} = $row;
- $self->view_start (List::Util::max 0, -$row + ($self->nrow >> 1));
+ $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1));
$self->want_refresh;
last;
}
$self->{row} = $self->nrow - 1;
$self->view_start (0);
} elsif ($keysym == 0xff52) { # up
- $self->{row}-- if $self->{row} > -$self->nsaved;
+ $self->{row}-- if $self->{row} > $self->top_row;
$self->search (-1);
} elsif ($keysym == 0xff54) { # down
$self->{row}++ if $self->{row} < $self->nrow;
void set_font_style ();
void scr_charset_choose (int set);
void scr_charset_set (int set, unsigned int ch);
- int scr_move_to (int y, int len);
- int scr_page (enum page_dirn direction, int nlines);
- int scr_changeview (unsigned int oldviewstart);
+ void scr_move_to (int y, int len);
+ bool scr_page (enum page_dirn direction, int nlines);
+ bool scr_changeview (int new_view_start);
void scr_bell ();
void scr_printscreen (int fullhist);
void scr_xor_rect (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle1, rend_t rstyle2);
* ncol : 1 <= ncol <= MAX(tlen_t)
* nrow : 1 <= nrow <= MAX(int)
* saveLines : 0 <= saveLines <= MAX(int)
- * total_rows : nrow + saveLines
- * nsaved : 0 <= nsaved <= saveLines
* term_start : 0 <= term_start < saveLines
- * view_start : 0 <= view_start < saveLines
+ * total_rows : nrow + saveLines
+ *
+ * top_row : -saveLines <= top_row <= 0
+ * view_start : top_row <= view_start <= 0
*
* | most coordinates are stored relative to term_start,
* ROW_BUF | which is the first line of the terminal screen
* |························= row_buf[1]
* |························= row_buf[2] etc.
* |
- * +------------+···········= term_start - nsaved
+ * +------------+···········= term_start + top_row
* | scrollback |
- * | scrollback +---------+·= term_start - view_start
+ * | scrollback +---------+·= term_start + view_start
* | scrollback | display |
* | scrollback | display |
* +------------+·display·+·= term_start
int lineSpace; /* number of extra pixels between rows */
int saveLines; /* number of lines that fit in scrollback */
int total_rows; /* total number of rows in this terminal */
- int nsaved; /* number of rows saved to scrollback */
int term_start; /* term lines start here */
int view_start; /* scrollback view starts here */
+ int top_row; /* topmost row index of scrollback */
Window parent[6]; /* parent identifiers - we're parent[0] */
Window vt; /* vt100 window */
GC gc; /* GC for drawing */
text_t *t1 = text [y];
rend_t *r1 = rend [y];
- text_t *t2 = ROW(y + ov_y - THIS->view_start).t + ov_x;
- rend_t *r2 = ROW(y + ov_y - THIS->view_start).r + ov_x;
+ text_t *t2 = ROW(y + ov_y + THIS->view_start).t + ov_x;
+ rend_t *r2 = ROW(y + ov_y + THIS->view_start).r + ov_x;
for (int x = ov_w; x--; )
{
}
}
+static void
+swap_overlays (rxvt_term *term)
+{
+ HV *hv = (HV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
+
+ if (HvKEYS (hv))
+ {
+ hv_iterinit (hv);
+
+ while (HE *he = hv_iternext (hv))
+ ((overlay *)SvIV (hv_iterval (hv, he)))->swap ();
+ }
+}
+
bool
rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
{
}
else
{
- if (htype == HOOK_REFRESH_BEGIN || htype == HOOK_REFRESH_END)
- {
- HV *hv = (HV *)SvRV (*hv_fetch ((HV *)SvRV ((SV *)term->perl.self), "_overlay", 8, 0));
+ if (htype == HOOK_REFRESH_END)
+ swap_overlays (term);
- if (HvKEYS (hv))
- {
- hv_iterinit (hv);
-
- while (HE *he = hv_iternext (hv))
- ((overlay *)SvIV (hv_iterval (hv, he)))->swap ();
- }
+ if (!term->perl.should_invoke [htype])
+ {
+ if (htype == HOOK_REFRESH_BEGIN)
+ swap_overlays (term);
+ return false;
}
-
- if (!term->perl.should_invoke [htype])
- return false;
}
swap (perl_environ, environ);
ungrab (term); // better lose the grab than the session
}
- if (htype == HOOK_DESTROY)
+ if (htype == HOOK_REFRESH_BEGIN)
+ swap_overlays (term);
+ else if (htype == HOOK_DESTROY)
{
clearSVptr ((SV *)term->perl.self);
SvREFCNT_dec ((SV *)term->perl.self);
#define TERM_OFFSET_mapped TERM_OFFSET(mapped)
#define TERM_OFFSET_saveLines TERM_OFFSET(saveLines)
#define TERM_OFFSET_total_rows TERM_OFFSET(total_rows)
-#define TERM_OFFSET_nsaved TERM_OFFSET(nsaved)
+#define TERM_OFFSET_top_row TERM_OFFSET(top_row)
int
rxvt_term::width ()
mapped = TERM_OFFSET_mapped
saveLines = TERM_OFFSET_saveLines
total_rows = TERM_OFFSET_total_rows
- nsaved = TERM_OFFSET_nsaved
+ top_row = TERM_OFFSET_top_row
CODE:
RETVAL = *(int *)((char *)THIS + ix);
OUTPUT:
RETVAL
int
-rxvt_term::view_start (int newval = -1)
+rxvt_term::view_start (int newval = 1)
PROTOTYPE: $;$
CODE:
{
RETVAL = THIS->view_start;
- if (newval >= 0)
- {
- THIS->view_start = min (newval, THIS->nsaved);
- THIS->scr_changeview (RETVAL);
- }
+ if (newval <= 0)
+ THIS->scr_changeview (max (newval, THIS->top_row));
}
OUTPUT:
RETVAL
rxvt_term::ROW_t (int row_number, SV *new_text = 0, int start_col = 0, int start_ofs = 0, int max_len = MAX_COLS)
PPCODE:
{
- if (!IN_RANGE_EXC (row_number, -THIS->nsaved, THIS->nrow))
+ if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
XSRETURN_EMPTY;
line_t &l = ROW(row_number);
rxvt_term::ROW_r (int row_number, SV *new_rend = 0, int start_col = 0, int start_ofs = 0, int max_len = MAX_COLS)
PPCODE:
{
- if (!IN_RANGE_EXC (row_number, -THIS->nsaved, THIS->nrow))
+ if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
XSRETURN_EMPTY;
line_t &l = ROW(row_number);
rxvt_term::ROW_l (int row_number, int new_length = -1)
CODE:
{
- if (!IN_RANGE_EXC (row_number, -THIS->nsaved, THIS->nrow))
+ if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
XSRETURN_EMPTY;
line_t &l = ROW(row_number);
rxvt_term::ROW_is_longer (int row_number, int new_is_longer = -1)
CODE:
{
- if (!IN_RANGE_EXC (row_number, -THIS->nsaved, THIS->nrow))
+ if (!IN_RANGE_EXC (row_number, THIS->top_row, THIS->nrow))
XSRETURN_EMPTY;
line_t &l = ROW(row_number);
if (items == 3)
{
- rc.row = clamp (SvIV (ST (1)), -THIS->nsaved, THIS->nrow - 1);
+ rc.row = clamp (SvIV (ST (1)), THIS->top_row, THIS->nrow - 1);
rc.col = clamp (SvIV (ST (2)), 0, THIS->ncol - 1);
if (ix)
//TODO//FIXME
saveLines++;
prev_nrow--;
- nsaved++;
+ top_row--;
}
want_refresh = 1;
/*
* first time called so just malloc everything: don't rely on realloc
*/
- nsaved = 0; /* no saved lines */
+ top_row = 0; /* no saved lines */
term_start = 0;
talloc = new rxvt_salloc (ncol * sizeof (text_t));
row_buf = (line_t *)rxvt_calloc (total_rows + nrow, sizeof (line_t));
int p = MOD (term_start + prev_nrow, prev_total_rows); // previous row
- int pend = MOD (term_start - nsaved , prev_total_rows);
+ int pend = MOD (term_start + top_row , prev_total_rows);
int q = total_rows; // rewrapped row
- if (nsaved)
+ if (top_row)
{
// re-wrap lines, this is rather ugly, possibly because I am too dumb
// to come up with a lean and mean algorithm.
while (p != pend && q > 0);
term_start = total_rows - nrow;
- nsaved = term_start - q;
+ top_row = q - term_start;
// make sure all terminal lines exist
- while (nsaved < 0)
- scr_blank_screen_mem (ROW (-++nsaved), DEFAULT_RSTYLE);
+ while (top_row > 0)
+ scr_blank_screen_mem (ROW (--top_row), DEFAULT_RSTYLE);
}
else
{
}
#ifdef DEBUG_STRICT //TODO: remove
- for (int i = -nsaved; i < nrow; i++)
+ for (int i = top_row; i < nrow; i++)
assert (ROW (i).t);
#endif
&& row1 == 0
&& (current_screen == PRIMARY || OPTION (Opt_secondaryScroll)))
{
- nsaved = min (nsaved + count, saveLines);
+ top_row = max (top_row - count, -saveLines);
- HOOK_INVOKE ((this, HOOK_SCROLL_BACK, DT_INT, count, DT_INT, nsaved, DT_END));
+ HOOK_INVOKE ((this, HOOK_SCROLL_BACK, DT_INT, count, DT_INT, top_row, DT_END));
// scroll everything up 'count' lines
term_start = (term_start + count) % total_rows;
selection.end.row -= count;
selection.mark.row -= count;
- if (selection.beg.row < -nsaved
- || selection.end.row < -nsaved
- || selection.mark.row < -nsaved)
+ if (selection.beg.row < top_row
+ || selection.end.row < top_row
+ || selection.mark.row < top_row)
{
CLEAR_ALL_SELECTION ();
selection.op = SELECTION_CLEAR;
// finally move the view window, if desired
if (OPTION (Opt_scrollWithBuffer)
&& view_start != 0
- && view_start != saveLines)
+ && view_start != -saveLines)
scr_page (UP, count);
}
else
#ifdef DEBUG_STRICT
assert (screen.cur.col < ncol);
assert (screen.cur.row < nrow
- && screen.cur.row >= -nsaved);
+ && screen.cur.row >= top_row);
#endif
int row = screen.cur.row;
want_refresh = 1;
ZERO_SCROLLBACK ();
- nsaved = 0;
+ top_row = 0;
}
#endif
* Move the display so that the line represented by scrollbar value Y is at
* the top of the screen
*/
-int
+void
rxvt_term::scr_move_to (int y, int len)
{
- long p = 0;
- unsigned int oldviewstart;
-
- oldviewstart = view_start;
-
- if (y < len)
- {
- p = (nrow + nsaved) * (len - y) / len;
- p -= (long) (nrow - 1);
- p = max (p, 0);
- }
+ int p = (top_row - nrow) * (len - y) / len + (nrow - 1);
- view_start = (unsigned int)min (p, nsaved);
-
- return scr_changeview (oldviewstart);
+ scr_changeview (p);
}
/* ------------------------------------------------------------------------- */
* Page the screen up/down nlines
* direction should be UP or DN
*/
-int
+bool
rxvt_term::scr_page (enum page_dirn direction, int nlines)
{
- int n;
- unsigned int oldviewstart;
-
- oldviewstart = view_start;
-
- if (direction == UP)
- {
- n = view_start + nlines;
- view_start = min (n, nsaved);
- }
- else
- {
- n = view_start - nlines;
- view_start = max (n, 0);
- }
+ int new_view_start =
+ direction == UP ? view_start - nlines
+ : view_start + nlines;
- return scr_changeview (oldviewstart);
+ return scr_changeview (new_view_start);
}
-int
-rxvt_term::scr_changeview (unsigned int oldviewstart)
+bool
+rxvt_term::scr_changeview (int new_view_start)
{
- if (view_start != oldviewstart)
+ clamp_it (new_view_start, top_row, 0);
+
+ if (new_view_start != view_start)
{
+ num_scr += new_view_start - view_start;
+ view_start = new_view_start;
HOOK_INVOKE ((this, HOOK_VIEW_CHANGE, DT_INT, view_start, DT_END));
-
want_refresh = 1;
- num_scr -= (view_start - oldviewstart);
- }
- return (int)view_start - (int)oldviewstart;
+ return true;
+ }
+ else
+ return false;
}
/* ------------------------------------------------------------------------- */
if (fullhist)
{
- nrows = nrow + nsaved;
- row_start = -nsaved;
+ nrows = nrow - top_row;
+ row_start = top_row;
}
else
{
nrows = nrow;
- row_start = -view_start;
+ row_start = view_start;
}
wctomb (0, 0);
setoldcursor = 0;
if (ocrow != -1)
{
- if (screen.cur.row + view_start != ocrow
+ if (screen.cur.row - view_start != ocrow
|| screen.cur.col != oldcursor.col)
{
if (ocrow < nrow
if (setoldcursor)
{
- if (screen.cur.row + view_start >= nrow)
+ if (screen.cur.row - view_start >= nrow)
oldcursor.row = -1;
else
{
- oldcursor.row = screen.cur.row + view_start;
+ oldcursor.row = screen.cur.row - view_start;
oldcursor.col = screen.cur.col;
}
}
{
if (row + i >= 0 && row + i < nrow && row + i != ocrow)
{
- line_t s = ROW(row - view_start);
+ line_t s = ROW(view_start + row);
line_t d = drawn_buf[row];
line_t d2 = drawn_buf[row + i];
*/
for (row = 0; row < nrow; row++)
{
- text_t *stp = ROW(row - view_start).t;
- rend_t *srp = ROW(row - view_start).r;
+ text_t *stp = ROW(view_start + row).t;
+ rend_t *srp = ROW(view_start + row).r;
text_t *dtp = drawn_buf[row].t;
rend_t *drp = drawn_buf[row].r;
void
rxvt_term::scr_xor_rect (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle1, rend_t rstyle2)
{
- int view_end = -view_start + nrow;
+ int view_end = view_start + nrow;
int row, col;
- for (row = max (beg_row, -view_start); row <= min (end_row, view_end); row++)
+ for (row = max (beg_row, view_start); row <= min (end_row, view_end); row++)
{
text_t *stp = ROW(row).t;
rend_t *srp = ROW(row).r;
void
rxvt_term::scr_xor_span (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle)
{
- int view_end = -view_start + nrow;
+ int view_end = view_start + nrow;
int row, col;
- if (beg_row >= -view_start)
+ if (beg_row >= view_start)
{
col = beg_col;
row = beg_row;
else
{
col = 0;
- row = -view_start;
+ row = view_start;
}
for (; row < min (end_row, view_end); row++, col = 0)
{
if (selection.op
&& current_screen == selection.screen
- && selection.end.row >= -view_start)
+ && selection.end.row >= view_start)
{
#if ENABLE_FRILLS
if (selection.rect)
return;
pos.row = pos.col = 0;
- if (!IN_RANGE_EXC (selection.beg.row, -nsaved, nrow)
- || !IN_RANGE_EXC (selection.mark.row, -nsaved, nrow)
- || !IN_RANGE_EXC (selection.end.row, -nsaved, nrow)
+ if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow)
+ || !IN_RANGE_EXC (selection.mark.row, top_row, nrow)
+ || !IN_RANGE_EXC (selection.end.row, top_row, nrow)
|| (check_more == 1
&& current_screen == selection.screen
&& !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
if (clicks == 2 || clicks == 3)
selection_extend_colrow (selection.mark.col,
- selection.mark.row + view_start,
+ selection.mark.row - view_start,
0, /* button 3 */
1, /* button press */
0); /* click change */
{
want_refresh = 1;
- selection.mark.row = row - view_start;
+ selection.mark.row = row + view_start;
selection.mark.col = col;
- selection.mark.row = clamp (selection.mark.row, -nsaved, nrow - 1);
+ selection.mark.row = clamp (selection.mark.row, top_row, nrow - 1);
selection.mark.col = clamp (selection.mark.col, 0, ncol - 1);
while (selection.mark.col > 0
if (dirn == UP)
{
- bound.row = - nsaved - 1;
+ bound.row = top_row - 1;
bound.col = 0;
dirnadd = -1;
}
*/
if (((selection.clicks % 3) == 1) && !flag
&& (col == selection.mark.col
- && (row == selection.mark.row + view_start)))
+ && (row == selection.mark.row - view_start)))
{
/* select nothing */
selection.beg.row = selection.end.row = 0;
}
pos.col = col;
- pos.row = row - view_start;
+ pos.row = view_start + row;
/*
* This is mainly xterm style selection with a couple of differences, mainly
text_t *t1 = ov_text[y];
rend_t *r1 = ov_rend[y];
- text_t *t2 = ROW(y + ov_y - view_start).t + ov_x;
- rend_t *r2 = ROW(y + ov_y - view_start).r + ov_x;
+ text_t *t2 = ROW(y + ov_y + view_start).t + ov_x;
+ rend_t *r2 = ROW(y + ov_y + view_start).r + ov_x;
for (int x = ov_w; x--; )
{
init_scrollbar_stuff ();
}
- if (nsaved == 0 || !update)
+ if (top_row == 0 || !update)
{
XFillRectangle (disp, scrollBar.win, grayGC, 0, 0,
SB_WIDTH_NEXT + 1, height);
SB_LEFT_PADDING, 0, SB_BUTTON_WIDTH, height);
}
- if (nsaved)
+ if (top_row)
{
if (last_top < scrollBar.top || !update)
XFillRectangle (disp, scrollBar.win, stippleGC,
if (update)
{
- top = nsaved - view_start;
+ top = view_start - top_row;
bot = top + (nrow - 1);
- len = max (nsaved + (nrow - 1), 1);
+ len = max (nrow - 1 - top_row, 1);
adj = (((bot - top) * scrollbar_size ()) % len) > 0 ? 1 : 0;
scrollBar.top = (scrollBar.beg + (top * scrollbar_size ()) / len);
=item $nrow_plus_saveLines = $term->total_rows
-=item $lines_in_scrollback = $term->nsaved
+=item $topmost_scrollback_row = $term->top_row
Return various integers describing terminal characteristics.
=item $view_start = $term->view_start ([$newvalue])
-Returns the negative row number of the topmost line. Minimum value is
-C<0>, which displays the normal terminal contents. Larger values scroll
+Returns the row number of the topmost displayed line. Maximum value is
+C<0>, which displays the normal terminal contents. Lower values scroll
this many lines into the scrollback buffer.
=item $term->want_refresh