console: add "fixed_position" option
The fixed_position option allows to explicitely keep the scrollback-buffer position instead of scrolling on new input. This was already the current behavior but now we can also scroll on new input if this is set to false. Also fix up the formatting of the comments and remove old information. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
bfe6702c1e
commit
d2786e12d3
144
src/console.c
144
src/console.c
@ -59,24 +59,36 @@ struct line {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct kmscon_buffer {
|
struct kmscon_buffer {
|
||||||
unsigned int sb_count;
|
/* scroll-back buffer */
|
||||||
struct line *sb_first;
|
unsigned int sb_count; /* number of lines in sb */
|
||||||
struct line *sb_last;
|
struct line *sb_first; /* first line; was moved first */
|
||||||
unsigned int sb_max;
|
struct line *sb_last; /* last line; was moved last*/
|
||||||
|
unsigned int sb_max; /* max-limit of lines in sb */
|
||||||
|
|
||||||
|
/* current position in sb; if NULL, the main screen is shown */
|
||||||
struct line *position;
|
struct line *position;
|
||||||
|
/* fixed=true means that if the current focus is on the sb, then the
|
||||||
|
* focus will stay on the line even if new lines are added to the sb or
|
||||||
|
* removed. fixed=false means the distance from the current position to
|
||||||
|
* the main-buffer is kept constant. In most situations this means that
|
||||||
|
* the sb seems to scroll-up while staying on the line
|
||||||
|
*/
|
||||||
|
bool fixed_position;
|
||||||
|
|
||||||
unsigned int size_x;
|
/* current cell/row count of the main screen */
|
||||||
unsigned int size_y;
|
unsigned int size_x; /* cell count */
|
||||||
|
unsigned int size_y; /* row count */
|
||||||
|
|
||||||
unsigned int scroll_y;
|
/* main scroll buffer */
|
||||||
unsigned int scroll_fill;
|
unsigned int scroll_y; /* number of rows in this buffer */
|
||||||
struct line **scroll_buf;
|
unsigned int scroll_fill; /* current fill; last line pushed */
|
||||||
|
struct line **scroll_buf; /* lines of the buffer */
|
||||||
|
|
||||||
unsigned int mtop_y;
|
/* margin buffers */
|
||||||
struct line **mtop_buf;
|
unsigned int mtop_y; /* number of rows in top margin */
|
||||||
unsigned int mbottom_y;
|
struct line **mtop_buf; /* lines of the top margin */
|
||||||
struct line **mbottom_buf;
|
unsigned int mbottom_y; /* number of rows in bottom margin */
|
||||||
|
struct line **mbottom_buf; /* lines of the bottom margin */
|
||||||
|
|
||||||
struct gl_m4_stack *stack;
|
struct gl_m4_stack *stack;
|
||||||
};
|
};
|
||||||
@ -104,9 +116,8 @@ struct kmscon_console {
|
|||||||
unsigned int cursor_y;
|
unsigned int cursor_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/* Console Buffer and Cell Objects
|
||||||
* Console Buffer and Cell Objects
|
* A console buffer maintains an array of lines of the current screen buffer
|
||||||
* A console buffer maintains an array of the lines of the current screen buffer
|
|
||||||
* and a list of lines in the scrollback buffer. The screen buffer can be
|
* and a list of lines in the scrollback buffer. The screen buffer can be
|
||||||
* modified, the scrollback buffer is constant.
|
* modified, the scrollback buffer is constant.
|
||||||
*
|
*
|
||||||
@ -134,7 +145,7 @@ struct kmscon_console {
|
|||||||
* A single line is represented by a "struct line". It has an array of cells
|
* A single line is represented by a "struct line". It has an array of cells
|
||||||
* which can be accessed directly. The length of each line may vary and for
|
* which can be accessed directly. The length of each line may vary and for
|
||||||
* faster resizing we also keep a \size member.
|
* faster resizing we also keep a \size member.
|
||||||
* A line may be shorter than the current buffer width. We do not resize them to
|
* Lines may be shorter than the current buffer width. We do not resize them to
|
||||||
* speed up the buffer operations. If a line is printed which is longer or
|
* speed up the buffer operations. If a line is printed which is longer or
|
||||||
* shorted than the screen width, it is simply filled with spaces or truncated
|
* shorted than the screen width, it is simply filled with spaces or truncated
|
||||||
* to screen width.
|
* to screen width.
|
||||||
@ -144,8 +155,8 @@ struct kmscon_console {
|
|||||||
* Screen position:
|
* Screen position:
|
||||||
* The current screen position may be any line inside the scrollback buffer. If
|
* The current screen position may be any line inside the scrollback buffer. If
|
||||||
* it is NULL, the current position is set to the current screen buffer.
|
* it is NULL, the current position is set to the current screen buffer.
|
||||||
* If it is non-NULL it will stick to the given line and will not scroll back on
|
* If it is non-NULL it will stick to the given line and will not scroll back
|
||||||
* new input.
|
* on new input.
|
||||||
*
|
*
|
||||||
* Cells
|
* Cells
|
||||||
* A single cell describes a single character that is printed in that cell. The
|
* A single cell describes a single character that is printed in that cell. The
|
||||||
@ -255,8 +266,9 @@ static struct line *get_line(struct kmscon_buffer *buf, unsigned int y)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* This links the given line into the scrollback-buffer. This always succeeds.
|
||||||
* This links the given line into the scrollback-buffer. This always succeeds.
|
* If \line is NULL then an empty line is created that is pushed to the
|
||||||
|
* scrollback buffer.
|
||||||
*/
|
*/
|
||||||
static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
||||||
{
|
{
|
||||||
@ -271,6 +283,10 @@ static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* line==NULL means the line is empty. The scrollback buffer cannot
|
||||||
|
* contain such lines, though. Therefore, explicitely allocate a new
|
||||||
|
* empty line with line!=NULL but size=0.
|
||||||
|
*/
|
||||||
if (!line) {
|
if (!line) {
|
||||||
ret = new_line(&line);
|
ret = new_line(&line);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -279,6 +295,12 @@ static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove a line from the scrollback buffer if it reaches its maximum.
|
||||||
|
* We must take care to correctly keep the current position as the new
|
||||||
|
* line is linked in after we remove the top-most line here.
|
||||||
|
* sb_max == 0 is tested earlier so we can assume sb_max > 0 here. In
|
||||||
|
* other words, buf->sb_first is a valid line if sb_count >= sb_max.
|
||||||
|
*/
|
||||||
if (buf->sb_count >= buf->sb_max) {
|
if (buf->sb_count >= buf->sb_max) {
|
||||||
tmp = buf->sb_first;
|
tmp = buf->sb_first;
|
||||||
buf->sb_first = tmp->next;
|
buf->sb_first = tmp->next;
|
||||||
@ -288,8 +310,21 @@ static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
|||||||
buf->sb_last = NULL;
|
buf->sb_last = NULL;
|
||||||
buf->sb_count--;
|
buf->sb_count--;
|
||||||
|
|
||||||
if (buf->position == tmp)
|
/* (position==tmp && !next) means we have sb_max=1 so set
|
||||||
|
* position to the new line. Otherwise, set to new first line.
|
||||||
|
* If position!=tmp and we have a fixed_position then nothing
|
||||||
|
* needs to be done because we can stay at the same line. If we
|
||||||
|
* have no fixed_position, we need to set the position to the
|
||||||
|
* next inserted line, which can be "line", too.
|
||||||
|
*/
|
||||||
|
if (buf->position) {
|
||||||
|
if (buf->position == tmp || !buf->fixed_position) {
|
||||||
|
if (buf->position->next)
|
||||||
|
buf->position = buf->position->next;
|
||||||
|
else
|
||||||
buf->position = line;
|
buf->position = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
free_line(tmp);
|
free_line(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,9 +338,7 @@ static void link_to_scrollback(struct kmscon_buffer *buf, struct line *line)
|
|||||||
buf->sb_count++;
|
buf->sb_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Unlinks last line from the scrollback buffer, Returns NULL if it is empty */
|
||||||
* Unlinks last line from the scrollback buffer. Returns NULL if it is empty.
|
|
||||||
*/
|
|
||||||
static struct line *get_from_scrollback(struct kmscon_buffer *buf)
|
static struct line *get_from_scrollback(struct kmscon_buffer *buf)
|
||||||
{
|
{
|
||||||
struct line *line;
|
struct line *line;
|
||||||
@ -321,16 +354,25 @@ static struct line *get_from_scrollback(struct kmscon_buffer *buf)
|
|||||||
buf->sb_first = NULL;
|
buf->sb_first = NULL;
|
||||||
buf->sb_count--;
|
buf->sb_count--;
|
||||||
|
|
||||||
|
/* correctly move the current position if it is set in the sb */
|
||||||
|
if (buf->position) {
|
||||||
|
if (buf->fixed_position) {
|
||||||
if (buf->position == line)
|
if (buf->position == line)
|
||||||
buf->position = NULL;
|
buf->position = NULL;
|
||||||
|
} else if (!buf->position->prev) {
|
||||||
|
if (buf->position == line)
|
||||||
|
buf->position = NULL;
|
||||||
|
} else {
|
||||||
|
buf->position = buf->position->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
line->next = NULL;
|
line->next = NULL;
|
||||||
line->prev = NULL;
|
line->prev = NULL;
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Resize scroll buffer. Despite being used for scroll region only, it is kept
|
||||||
* Resize scroll buffer. Despite being used for scroll region only, it is kept
|
|
||||||
* big enough to hold both margins too. We do this to allow fast merges of
|
* big enough to hold both margins too. We do this to allow fast merges of
|
||||||
* margins and scroll buffer.
|
* margins and scroll buffer.
|
||||||
*/
|
*/
|
||||||
@ -341,16 +383,15 @@ static int resize_scrollbuf(struct kmscon_buffer *buf, unsigned int y)
|
|||||||
|
|
||||||
/* Resize y size by adjusting the scroll-buffer size */
|
/* Resize y size by adjusting the scroll-buffer size */
|
||||||
if (y < buf->scroll_y) {
|
if (y < buf->scroll_y) {
|
||||||
/*
|
/* Shrink scroll-buffer. First move enough elements from the
|
||||||
* Shrink scroll-buffer. First move enough elements from the
|
|
||||||
* scroll-buffer into the scroll-back buffer so we can shrink
|
* scroll-buffer into the scroll-back buffer so we can shrink
|
||||||
* it without loosing data.
|
* it without loosing data.
|
||||||
* Then reallocate the buffer (we shrink it so we never fail
|
* Then reallocate the buffer (we shrink it so we never fail
|
||||||
* here) and correctly set values in \buf. If the buffer has
|
* here) and correctly set values in \buf. If the buffer has
|
||||||
* unused lines, we can shrink it down without moving lines into
|
* unused lines, we can shrink it down without moving lines
|
||||||
* the scrollback-buffer so first calculate the current fill of
|
* into the scrollback-buffer so first calculate the current
|
||||||
* the buffer and then move appropriate amount of elements to
|
* fill of the buffer and then move appropriate amount of
|
||||||
* the scrollback buffer.
|
* elements to the scrollback buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (buf->scroll_fill > y) {
|
if (buf->scroll_fill > y) {
|
||||||
@ -369,8 +410,7 @@ static int resize_scrollbuf(struct kmscon_buffer *buf, unsigned int y)
|
|||||||
if (buf->scroll_fill > y)
|
if (buf->scroll_fill > y)
|
||||||
buf->scroll_fill = y;
|
buf->scroll_fill = y;
|
||||||
} else if (y > buf->scroll_y) {
|
} else if (y > buf->scroll_y) {
|
||||||
/*
|
/* Increase scroll-buffer to new size. Reset all new elements
|
||||||
* Increase scroll-buffer to new size. Reset all new elements
|
|
||||||
* to NULL so they are empty. Copy existing buffer into new
|
* to NULL so they are empty. Copy existing buffer into new
|
||||||
* buffer and correctly set values in \buf.
|
* buffer and correctly set values in \buf.
|
||||||
* If we have more space in the buffer, we simply move lines
|
* If we have more space in the buffer, we simply move lines
|
||||||
@ -506,10 +546,9 @@ static int resize_mbottom(struct kmscon_buffer *buf, unsigned int y)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Resize the current console buffer
|
||||||
* Resize the current console buffer
|
* This resizes the current buffer. We do not resize the lines or modify them
|
||||||
* This resizes the current buffer. We do not resize the lines or modify them in
|
* in any way. This would take too long if multiple resize-operations are
|
||||||
* any way. This would take too long if multiple resize-operations are
|
|
||||||
* performed.
|
* performed.
|
||||||
*/
|
*/
|
||||||
static int kmscon_buffer_resize(struct kmscon_buffer *buf, unsigned int x,
|
static int kmscon_buffer_resize(struct kmscon_buffer *buf, unsigned int x,
|
||||||
@ -570,6 +609,9 @@ static void kmscon_buffer_set_max_sb(struct kmscon_buffer *buf,
|
|||||||
buf->sb_last = NULL;
|
buf->sb_last = NULL;
|
||||||
buf->sb_count--;
|
buf->sb_count--;
|
||||||
|
|
||||||
|
/* We treat fixed/unfixed position the same here because we
|
||||||
|
* remove lines from the TOP of the scrollback buffer.
|
||||||
|
*/
|
||||||
if (buf->position == line) {
|
if (buf->position == line) {
|
||||||
if (buf->sb_first)
|
if (buf->sb_first)
|
||||||
buf->position = buf->sb_first;
|
buf->position = buf->sb_first;
|
||||||
@ -963,6 +1005,15 @@ static void kmscon_buffer_erase_region(struct kmscon_buffer *buf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Console Object
|
||||||
|
* The console object is a state-machine that represents the current state of
|
||||||
|
* the whole console. Besides managing the buffer it also controls the current
|
||||||
|
* cursor position on similar.
|
||||||
|
* The functions that are provided by this console are exactly the ones that
|
||||||
|
* are needed to emulate the classic VTs. Therefore, they are designed to have
|
||||||
|
* the desired behavior and configuration-options.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline unsigned int to_abs_x(struct kmscon_console *con, unsigned int x)
|
static inline unsigned int to_abs_x(struct kmscon_console *con, unsigned int x)
|
||||||
{
|
{
|
||||||
return x;
|
return x;
|
||||||
@ -1061,8 +1112,8 @@ unsigned int kmscon_console_get_height(struct kmscon_console *con)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Resize console to \x and \y. The \height argument is just a quality hint for
|
* Resize console to \x and \y. The \height argument is just a quality hint for
|
||||||
* internal rendering. It is supposed to be the maximal height in pixels of your
|
* internal rendering. It is supposed to be the maximal height in pixels of
|
||||||
* output. The internal texture will have this height (the width is computed
|
* your output. The internal texture will have this height (the width is calced
|
||||||
* automatically from the font and height). You can still use *_map() to map
|
* automatically from the font and height). You can still use *_map() to map
|
||||||
* this texture to arbitrary outputs but if you have huge resolutions, this
|
* this texture to arbitrary outputs but if you have huge resolutions, this
|
||||||
* would result in bad quality if you do not specify a proper height here.
|
* would result in bad quality if you do not specify a proper height here.
|
||||||
@ -1130,13 +1181,10 @@ int kmscon_console_resize(struct kmscon_console *con, unsigned int x,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This maps the console onto the current GL framebuffer. It expects the
|
* This maps the console onto the current GL framebuffer. It expects the
|
||||||
* framebuffer to have 0/0 in the middle, -1/-1 in the upper left and 1/1 in the
|
* framebuffer to have 0/0 in the middle, -1/-1 in the upper left and 1/1 in
|
||||||
* lower right (default GL settings).
|
* the lower right (default GL settings).
|
||||||
* This does not clear the screen, nor does it paint the background. Instead the
|
* This does not clear the screen, nor does it paint the background. Instead
|
||||||
* background is transparent and blended on top of the framebuffer.
|
* the background is transparent and blended on top of the framebuffer.
|
||||||
*
|
|
||||||
* You must have called kmscon_console_draw() before, otherwise this will map an
|
|
||||||
* empty image onto the screen.
|
|
||||||
*/
|
*/
|
||||||
void kmscon_console_map(struct kmscon_console *con, struct gl_shader *shader)
|
void kmscon_console_map(struct kmscon_console *con, struct gl_shader *shader)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user