mirror of
https://github.com/tmate-io/tmate.git
synced 2024-12-22 23:00:51 +01:00
Internal screen data rewrite for better 256 colour/UTF-8 support.
This commit is contained in:
parent
9edb4d4b85
commit
efe557313a
12
CHANGES
12
CHANGES
@ -1,3 +1,13 @@
|
||||
25 September 2008
|
||||
|
||||
* Large internal rewrite to better support 256 colours and UTF-8. Screen data
|
||||
is now stored as single two-way array of structures rather than as multiple
|
||||
separate arrays. Also simplified a lot of code.
|
||||
|
||||
Only external changes are three new flags, -2, -d and -u, which force tmux to
|
||||
assume the terminal supports 256 colours, default colours (useful for
|
||||
xterm-256color which lacks the AX flag), or UTF-8 respectively.
|
||||
|
||||
10 September 2008
|
||||
|
||||
* Split off colour conversion code from screen code.
|
||||
@ -664,4 +674,4 @@
|
||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||
customisation.
|
||||
|
||||
$Id: CHANGES,v 1.160 2008-09-10 18:59:29 nicm Exp $
|
||||
$Id: CHANGES,v 1.161 2008-09-25 20:08:51 nicm Exp $
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: GNUmakefile,v 1.39 2008-09-09 22:16:36 nicm Exp $
|
||||
# $Id: GNUmakefile,v 1.40 2008-09-25 20:08:51 nicm Exp $
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
@ -12,7 +12,9 @@ DATE= $(shell date +%Y%m%d-%H%M)
|
||||
META?= \002
|
||||
|
||||
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
||||
xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \
|
||||
xmalloc.c xmalloc-debug.c input.c input-keys.c \
|
||||
screen.c screen-write.c screen-redraw.c \
|
||||
grid.c grid-view.c \
|
||||
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
|
||||
key-string.c key-bindings.c resize.c arg.c mode-key.c \
|
||||
cmd.c cmd-generic.c cmd-string.c \
|
||||
@ -31,7 +33,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
||||
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
|
||||
cmd-respawn-window.c \
|
||||
window-scroll.c window-more.c window-copy.c options.c paste.c \
|
||||
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c utf8.c
|
||||
tty.c tty-keys.c tty-write.c colour.c utf8.c
|
||||
|
||||
CC?= gcc
|
||||
INCDIRS+= -I. -I-
|
||||
|
5
Makefile
5
Makefile
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.74 2008-09-10 18:59:29 nicm Exp $
|
||||
# $Id: Makefile,v 1.75 2008-09-25 20:08:51 nicm Exp $
|
||||
|
||||
.SUFFIXES: .c .o .y .h
|
||||
.PHONY: clean update-index.html upload-index.html
|
||||
@ -17,7 +17,8 @@ META?= \002 # C-b
|
||||
|
||||
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
||||
xmalloc.c xmalloc-debug.c input.c input-keys.c \
|
||||
screen.c screen-display.c screen-write.c screen-redraw.c \
|
||||
screen.c screen-write.c screen-redraw.c \
|
||||
grid.c grid-view.c \
|
||||
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
|
||||
key-string.c key-bindings.c resize.c arg.c mode-key.c \
|
||||
cmd.c cmd-generic.c cmd-string.c \
|
||||
|
125
TODO
125
TODO
@ -41,127 +41,10 @@
|
||||
|
||||
-- For 0.5 --------------------------------------------------------------------
|
||||
|
||||
XXX
|
||||
screen contains grid
|
||||
|
||||
screen_write <-- write to TTY and to screen using close-to-ANSI functions
|
||||
screen_redraw <-- write areas of screen to TTY
|
||||
grid_view <-- write to viewable area of grid
|
||||
grid <-- manipulate grid and history
|
||||
|
||||
XXX
|
||||
grid_view has ox,oy
|
||||
XXX
|
||||
|
||||
- FINISH UTF8: fix copy and paste
|
||||
- SPLIT u_short attr into attr,flags?
|
||||
- maybe rethink backend data structure?
|
||||
- utf8 can be 1-4 bytes
|
||||
- most common is 1 bytes
|
||||
- there can be double-width characters which take n bytes but 2 columns on screen
|
||||
- they are not only drawn as two characters, they also require two backspaces to remove
|
||||
- three operations:
|
||||
- simultaneously update screen and ttys
|
||||
- redraw screen or section of screen to ttys
|
||||
- write to ttys without updating screen
|
||||
|
||||
---
|
||||
NEED to be able to:
|
||||
resize screen
|
||||
apply ops to both screen and tty simultaneously
|
||||
both when parsing input and when eg scrolling history
|
||||
draw on the top of the screen without modifying it
|
||||
display arbitrary parts of the history
|
||||
redraw arbitrary parts of the visible screen
|
||||
---
|
||||
NEVER need to draw into the history
|
||||
|
||||
split off grid manip:
|
||||
16-bit characters
|
||||
8-bit flags
|
||||
8-bit attributes
|
||||
8-bit fg colour
|
||||
8-bit bg colour
|
||||
|
||||
struct grid_data {
|
||||
struct grid_cell **data;
|
||||
int *sizes;
|
||||
|
||||
int sx;
|
||||
int sy;
|
||||
|
||||
int hsize;
|
||||
int hlimit;
|
||||
};
|
||||
struct grid_cell {
|
||||
u_short data;
|
||||
u_char attr;
|
||||
u_char flags;
|
||||
u_char fg;
|
||||
u_char bg;
|
||||
};
|
||||
const struct grid_default_cell = { 0x20, 0, 0, 8, 8 };
|
||||
|
||||
; grid logically split from
|
||||
; -hlimit to 0 and 0 to sy
|
||||
|
||||
; ALWAYS fill with default
|
||||
|
||||
const struct grid_cell *grid_get(int x, int y);
|
||||
void grid_set(int x, int y, const struct grid_cell *cell);
|
||||
|
||||
void grid_resize()
|
||||
void grid_shift() /* shift lines into history */
|
||||
|
||||
struct grid_view {
|
||||
int ox;
|
||||
int oy;
|
||||
|
||||
int sx;
|
||||
int sy;
|
||||
|
||||
struct grid_data *gdata;
|
||||
struct grid_view *parent;
|
||||
};
|
||||
|
||||
struct grid_cell *grid_view_get_cell(int x, int y)
|
||||
void grid_view_set_cell(int x, int y, const struct grid_cell *cell);
|
||||
|
||||
int grid_view_absolute_x(int x);
|
||||
int grid_view_absolute_y(int y);
|
||||
|
||||
int grid_view_relative_x(int x);
|
||||
int grid_view_relative_y(int y);
|
||||
|
||||
void grid_view_delete_lines(int y, int ny)
|
||||
void grid_view_insert_lines(int y, int ny)
|
||||
void grid_view_clear_lines(int y, int ny)
|
||||
void grid_view_fill_lines(int y, int ny, const struct grid_cell *cell)
|
||||
|
||||
void grid_view_delete_cells(int x, int y, int nx)
|
||||
void grid_view_insert_cells(int x, int y, int nx)
|
||||
void grid_view_clear_cells(int x, int y, int nx)
|
||||
void grid_view_fill_cells(int x, int nx, const struct grid_cell *cell)
|
||||
|
||||
void grid_view_clear_area(int x, int y, int nx, int ny)
|
||||
void grid_view_fill_area(int x, int y, int nx, int ny, const struct grid_cell *cell)
|
||||
|
||||
---
|
||||
|
||||
screen has two (both grid_view):
|
||||
base and overlay
|
||||
|
||||
---
|
||||
screen_write writes into overlay if it exists and then base, also optionally to tty
|
||||
screen_draw draws overlay + base to display
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
Would it be better to just expand char to 16-bits and use it as an index only
|
||||
for >2-byte characters? or - better - don't support entire UTF range? only the BMP?
|
||||
this would get rid of UTF table and limits, but still leave double-width character annoyances
|
||||
also would double memory usage
|
||||
TODO -- 2 fix window-*.c
|
||||
3 resizing
|
||||
4 audit for leftover/unused code
|
||||
5 next phase of tidying
|
||||
----
|
||||
|
||||
21:09 < merdely> NicM: if I run 'tmux attach -t main' and there is no tmux session named main, start a new one.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-windows.c,v 1.23 2008-09-09 22:16:36 nicm Exp $ */
|
||||
/* $Id: cmd-list-windows.c,v 1.24 2008-09-25 20:08:52 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -48,6 +48,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
struct grid_data *gd;
|
||||
u_int i;
|
||||
unsigned long long size;
|
||||
const char *name;
|
||||
@ -57,27 +58,23 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
w = wl->window;
|
||||
gd = w->base.grid;
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < w->base.hsize; i++)
|
||||
size += w->base.grid_size[i] * 3;
|
||||
size += w->base.hsize * (sizeof *w->base.grid_data);
|
||||
size += w->base.hsize * (sizeof *w->base.grid_attr);
|
||||
size += w->base.hsize * (sizeof *w->base.grid_fg);
|
||||
size += w->base.hsize * (sizeof *w->base.grid_bg);
|
||||
size += w->base.hsize * (sizeof *w->base.grid_size);
|
||||
|
||||
for (i = 0; i < gd->hsize; i++)
|
||||
size += gd->size[i] * sizeof **gd->data;
|
||||
size += gd->hsize * (sizeof *gd->data);
|
||||
size += gd->hsize * (sizeof *gd->size);
|
||||
|
||||
if (w->fd != -1)
|
||||
name = ttyname(w->fd);
|
||||
else
|
||||
name = "";
|
||||
ctx->print(ctx,
|
||||
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes] "
|
||||
"[UTF8 table %u/%u]",
|
||||
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]",
|
||||
wl->idx, w->name, w->base.title, name,
|
||||
screen_size_x(&w->base), screen_size_y(&w->base),
|
||||
w->base.hsize, w->base.hlimit, size,
|
||||
ARRAY_LENGTH(&w->base.utf8_table.array), UTF8_LIMIT);
|
||||
gd->hsize, gd->hlimit, size);
|
||||
}
|
||||
|
||||
if (ctx->cmdclient != NULL)
|
||||
|
199
grid-view.c
Normal file
199
grid-view.c
Normal file
@ -0,0 +1,199 @@
|
||||
/* $Id: grid-view.c,v 1.1 2008-09-25 20:08:52 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Grid view functions. These work using coordinates relative to the visible
|
||||
* screen area.
|
||||
*/
|
||||
|
||||
#define grid_view_x(gd, x) (x)
|
||||
#define grid_view_y(gd, y) ((gd)->hsize + (y))
|
||||
|
||||
/* Get cell for reading. */
|
||||
const struct grid_cell *
|
||||
grid_view_peek_cell(struct grid_data *gd, u_int px, u_int py)
|
||||
{
|
||||
return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
|
||||
}
|
||||
|
||||
/* Get cell for writing. */
|
||||
struct grid_cell *
|
||||
grid_view_get_cell(struct grid_data *gd, u_int px, u_int py)
|
||||
{
|
||||
return (grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
|
||||
}
|
||||
|
||||
/* Set cell. */
|
||||
void
|
||||
grid_view_set_cell(
|
||||
struct grid_data *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
{
|
||||
grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
|
||||
}
|
||||
|
||||
/* Clear area. */
|
||||
void
|
||||
grid_view_clear(struct grid_data *gd, u_int px, u_int py, u_int nx, u_int ny)
|
||||
{
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
|
||||
|
||||
px = grid_view_x(gd, px);
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
grid_clear(gd, px, py, nx, ny);
|
||||
}
|
||||
|
||||
/* Fill area. */
|
||||
void
|
||||
grid_view_fill(struct grid_data *gd,
|
||||
const struct grid_cell *gc, u_int px, u_int py, u_int nx, u_int ny)
|
||||
{
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
|
||||
|
||||
px = grid_view_x(gd, px);
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
grid_fill(gd, gc, px, py, nx, ny);
|
||||
}
|
||||
|
||||
/* Scroll region up. */
|
||||
void
|
||||
grid_view_scroll_region_up(struct grid_data *gd, u_int rupper, u_int rlower)
|
||||
{
|
||||
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
|
||||
|
||||
if (rupper == 0 && rlower == gd->sy - 1) {
|
||||
grid_scroll_line(gd);
|
||||
return;
|
||||
}
|
||||
|
||||
rupper = grid_view_y(gd, rupper);
|
||||
rlower = grid_view_y(gd, rlower);
|
||||
|
||||
grid_move_lines(gd, rupper, rupper + 1, rlower - rupper);
|
||||
}
|
||||
|
||||
/* Scroll region down. */
|
||||
void
|
||||
grid_view_scroll_region_down(struct grid_data *gd, u_int rupper, u_int rlower)
|
||||
{
|
||||
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
|
||||
|
||||
rupper = grid_view_y(gd, rupper);
|
||||
rlower = grid_view_y(gd, rlower);
|
||||
|
||||
grid_move_lines(gd, rupper + 1, rupper, rlower - rupper);
|
||||
}
|
||||
|
||||
/* Insert lines. */
|
||||
void
|
||||
grid_view_insert_lines(struct grid_data *gd, u_int py, u_int ny)
|
||||
{
|
||||
u_int sy;
|
||||
|
||||
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
|
||||
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
sy = grid_view_y(gd, gd->sy);
|
||||
|
||||
grid_move_lines(gd, py + ny, py, sy - py - ny);
|
||||
}
|
||||
|
||||
/* Insert lines in region. */
|
||||
void
|
||||
grid_view_insert_lines_region(
|
||||
struct grid_data *gd, u_int rupper, u_int rlower, u_int py, u_int ny)
|
||||
{
|
||||
GRID_DEBUG(
|
||||
gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
|
||||
|
||||
rupper = grid_view_y(gd, rupper);
|
||||
rlower = grid_view_y(gd, rlower);
|
||||
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
grid_move_lines(gd, py + ny, py, (rlower + 1) - py - ny);
|
||||
}
|
||||
|
||||
/* Delete lines. */
|
||||
void
|
||||
grid_view_delete_lines(struct grid_data *gd, u_int py, u_int ny)
|
||||
{
|
||||
u_int sy;
|
||||
|
||||
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
|
||||
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
sy = grid_view_y(gd, gd->sy);
|
||||
|
||||
grid_move_lines(gd, py, py + ny, sy - py - ny);
|
||||
}
|
||||
|
||||
/* Delete lines inside scroll region. */
|
||||
void
|
||||
grid_view_delete_lines_region(
|
||||
struct grid_data *gd, u_int rupper, u_int rlower, u_int py, u_int ny)
|
||||
{
|
||||
GRID_DEBUG(
|
||||
gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
|
||||
|
||||
rupper = grid_view_y(gd, rupper);
|
||||
rlower = grid_view_y(gd, rlower);
|
||||
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
grid_move_lines(gd, py, py + ny, (rlower + 1) - py - ny);
|
||||
}
|
||||
|
||||
/* Insert characters. */
|
||||
void
|
||||
grid_view_insert_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int sx;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
|
||||
|
||||
px = grid_view_x(gd, px);
|
||||
|
||||
sx = grid_view_x(gd, gd->sx);
|
||||
|
||||
grid_move_cells(gd, px + nx, px, py, (sx - 1) - (px + nx));
|
||||
}
|
||||
|
||||
/* Delete characters. */
|
||||
void
|
||||
grid_view_delete_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int sx;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
|
||||
|
||||
px = grid_view_x(gd, px);
|
||||
|
||||
sx = grid_view_x(gd, gd->sx);
|
||||
|
||||
grid_move_cells(gd, px, px + nx, py, (sx - 1) - (px + nx));
|
||||
}
|
353
grid.c
Normal file
353
grid.c
Normal file
@ -0,0 +1,353 @@
|
||||
/* $Id: grid.c,v 1.1 2008-09-25 20:08:52 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Grid data. This is the basic data structure that represents what is shown on
|
||||
* screen.
|
||||
*
|
||||
* A grid is a grid of cells (struct grid_cell). It is sparse, in that cells
|
||||
* are not allocated until they are written to. The grid is logically split
|
||||
* into history and viewable data with the history starting at row (line) 0 and
|
||||
* extending to (hsize - 1); from hsize to hsize + (sy - 1) is the viewable
|
||||
* data. All functions in this file work on absolute coordinates, grid-view.c
|
||||
* has functions which work on the screen data.
|
||||
*/
|
||||
|
||||
/* Default grid cell data. */
|
||||
const struct grid_cell grid_default_cell = { ' ', 0, 0, 8, 8 };
|
||||
|
||||
#define grid_check_x(gd, px) do { \
|
||||
if ((px) >= (gd)->sx) \
|
||||
log_fatalx("x out of range: %u", px); \
|
||||
} while (0)
|
||||
|
||||
#define grid_check_y(gd, py) do { \
|
||||
if ((py) >= (gd)->hsize + (gd)->sy) \
|
||||
log_fatalx("y out of range: %u", py); \
|
||||
} while (0)
|
||||
|
||||
#define grid_put_cell(gd, px, py, gc) do { \
|
||||
memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \
|
||||
} while (0)
|
||||
|
||||
/* Create a new grid. */
|
||||
struct grid_data *
|
||||
grid_create(u_int sx, u_int sy, u_int hlimit)
|
||||
{
|
||||
struct grid_data *gd;
|
||||
|
||||
gd = xmalloc(sizeof *gd);
|
||||
gd->sx = sx;
|
||||
gd->sy = sy;
|
||||
|
||||
gd->hsize = 0;
|
||||
gd->hlimit = hlimit;
|
||||
|
||||
gd->size = xcalloc(gd->sy, sizeof *gd->size);
|
||||
gd->data = xcalloc(gd->sy, sizeof *gd->data);
|
||||
|
||||
return (gd);
|
||||
}
|
||||
|
||||
/* Destroy grid. */
|
||||
void
|
||||
grid_destroy(struct grid_data *gd)
|
||||
{
|
||||
u_int yy;
|
||||
|
||||
for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
|
||||
if (gd->data[yy] != NULL)
|
||||
xfree(gd->data[yy]);
|
||||
}
|
||||
|
||||
if (gd->data != NULL)
|
||||
xfree(gd->data);
|
||||
if (gd->size != NULL)
|
||||
xfree(gd->size);
|
||||
xfree(gd);
|
||||
}
|
||||
|
||||
/* Scroll a line into the history. */
|
||||
void
|
||||
grid_scroll_line(struct grid_data *gd)
|
||||
{
|
||||
u_int yy;
|
||||
|
||||
GRID_DEBUG(gd, "");
|
||||
|
||||
if (gd->hsize >= gd->hlimit - 1) {
|
||||
/* If the limit is hit, free the bottom 10% and shift up. */
|
||||
yy = gd->hlimit / 10;
|
||||
if (yy < 1)
|
||||
yy = 1;
|
||||
|
||||
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
|
||||
gd->hsize -= yy;
|
||||
}
|
||||
|
||||
yy = gd->hsize + gd->sy;
|
||||
gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
|
||||
gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
|
||||
|
||||
gd->data[yy] = NULL;
|
||||
gd->size[yy] = 0;
|
||||
|
||||
gd->hsize++;
|
||||
}
|
||||
|
||||
/* Reduce line to fit to cell. */
|
||||
void
|
||||
grid_reduce_line(struct grid_data *gd, u_int py, u_int sx)
|
||||
{
|
||||
if (sx >= gd->size[py])
|
||||
return;
|
||||
|
||||
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
|
||||
gd->size[py] = sx;
|
||||
}
|
||||
|
||||
/* Expand line to fit to cell. */
|
||||
void
|
||||
grid_expand_line(struct grid_data *gd, u_int py, u_int sx)
|
||||
{
|
||||
u_int xx;
|
||||
|
||||
if (sx <= gd->size[py])
|
||||
return;
|
||||
|
||||
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
|
||||
for (xx = gd->size[py]; xx < sx; xx++)
|
||||
grid_put_cell(gd, xx, py, &grid_default_cell);
|
||||
gd->size[py] = sx;
|
||||
}
|
||||
|
||||
/* Get cell for reading. */
|
||||
const struct grid_cell *
|
||||
grid_peek_cell(struct grid_data *gd, u_int px, u_int py)
|
||||
{
|
||||
grid_check_x(gd, px);
|
||||
grid_check_y(gd, py);
|
||||
|
||||
if (px >= gd->size[py])
|
||||
return (&grid_default_cell);
|
||||
return (&gd->data[py][px]);
|
||||
}
|
||||
|
||||
/* Get cell at relative position (for writing). */
|
||||
struct grid_cell *
|
||||
grid_get_cell(struct grid_data *gd, u_int px, u_int py)
|
||||
{
|
||||
grid_check_x(gd, px);
|
||||
grid_check_y(gd, py);
|
||||
|
||||
grid_expand_line(gd, py, px + 1);
|
||||
return (&gd->data[py][px]);
|
||||
}
|
||||
|
||||
/* Set cell at relative position. */
|
||||
void
|
||||
grid_set_cell(
|
||||
struct grid_data *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
{
|
||||
grid_check_x(gd, px);
|
||||
grid_check_y(gd, py);
|
||||
|
||||
grid_expand_line(gd, py, px + 1);
|
||||
grid_put_cell(gd, px, py, gc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear area. Note this is different from a fill as it just omits unallocated
|
||||
* cells.
|
||||
*/
|
||||
void
|
||||
grid_clear(struct grid_data *gd, u_int px, u_int py, u_int nx, u_int ny)
|
||||
{
|
||||
u_int xx, yy;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
|
||||
if (px == 0 && nx == gd->sx) {
|
||||
grid_clear_lines(gd, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
grid_check_x(gd, px);
|
||||
grid_check_x(gd, px + nx - 1);
|
||||
grid_check_y(gd, py);
|
||||
grid_check_y(gd, py + ny - 1);
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= gd->size[yy])
|
||||
break;
|
||||
grid_put_cell(gd, xx, yy, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill area. */
|
||||
void
|
||||
grid_fill(struct grid_data *gd,
|
||||
const struct grid_cell *gc, u_int px, u_int py, u_int nx, u_int ny)
|
||||
{
|
||||
u_int xx, yy;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
|
||||
grid_check_x(gd, px);
|
||||
grid_check_x(gd, px + nx - 1);
|
||||
grid_check_y(gd, py);
|
||||
grid_check_y(gd, py + ny - 1);
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
grid_expand_line(gd, yy, xx + 1);
|
||||
grid_put_cell(gd, xx, py, gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear lines. This just frees and truncates the lines. */
|
||||
void
|
||||
grid_clear_lines(struct grid_data *gd, u_int py, u_int ny)
|
||||
{
|
||||
u_int yy;
|
||||
|
||||
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
|
||||
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
grid_check_y(gd, py);
|
||||
grid_check_y(gd, py + ny - 1);
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
if (gd->data[yy] != NULL) {
|
||||
xfree(gd->data[yy]);
|
||||
gd->data[yy] = NULL;
|
||||
gd->size[yy] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill a group of lines. */
|
||||
void
|
||||
grid_fill_lines(
|
||||
struct grid_data *gd, const struct grid_cell *gc, u_int py, u_int ny)
|
||||
{
|
||||
grid_fill(gd, gc, 0, py, gd->sx, ny);
|
||||
}
|
||||
|
||||
/* Move a group of lines. */
|
||||
void
|
||||
grid_move_lines(struct grid_data *gd, u_int dy, u_int py, u_int ny)
|
||||
{
|
||||
u_int yy;
|
||||
|
||||
GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny);
|
||||
|
||||
if (ny == 0 || py == dy)
|
||||
return;
|
||||
|
||||
grid_check_y(gd, py);
|
||||
grid_check_y(gd, py + ny - 1);
|
||||
grid_check_y(gd, dy);
|
||||
grid_check_y(gd, dy + ny - 1);
|
||||
|
||||
/* Free any lines which are being replaced. */
|
||||
for (yy = dy; yy < dy + ny; yy++) {
|
||||
if (yy >= py && yy < py + ny)
|
||||
continue;
|
||||
grid_clear_lines(gd, yy, 1);
|
||||
}
|
||||
|
||||
memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data));
|
||||
memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size));
|
||||
|
||||
/* Wipe any lines that have been moved (without freeing them). */
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
if (yy >= dy && yy < dy + ny)
|
||||
continue;
|
||||
gd->data[yy] = NULL;
|
||||
gd->size[yy] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear a group of cells. */
|
||||
void
|
||||
grid_clear_cells(struct grid_data *gd, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int xx;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
|
||||
|
||||
if (nx == 0)
|
||||
return;
|
||||
|
||||
grid_check_x(gd, px);
|
||||
grid_check_x(gd, px + nx - 1);
|
||||
grid_check_y(gd, py);
|
||||
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= gd->size[py])
|
||||
break;
|
||||
grid_put_cell(gd, xx, py, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move a group of cells. */
|
||||
void
|
||||
grid_move_cells(struct grid_data *gd, u_int dx, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int xx;
|
||||
|
||||
GRID_DEBUG(gd, "dx=%u, px=%u, py=%u, nx=%u", dx, px, py, nx);
|
||||
|
||||
if (nx == 0 || px == dx)
|
||||
return;
|
||||
|
||||
grid_check_x(gd, px);
|
||||
grid_check_x(gd, px + nx - 1);
|
||||
grid_check_y(gd, py);
|
||||
|
||||
grid_expand_line(gd, py ,px + nx);
|
||||
grid_expand_line(gd, py, dx + nx);
|
||||
memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data));
|
||||
|
||||
/* Wipe any cells that have been moved. */
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= dx && xx < dx + nx)
|
||||
continue;
|
||||
memcpy(
|
||||
&gd->data[py][xx], &grid_default_cell, sizeof **gd->data);
|
||||
}
|
||||
}
|
||||
|
358
input.c
358
input.c
@ -1,4 +1,4 @@
|
||||
/* $Id: input.c,v 1.58 2008-09-09 22:16:36 nicm Exp $ */
|
||||
/* $Id: input.c,v 1.59 2008-09-25 20:08:52 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -186,12 +186,20 @@ input_state(struct input_ctx *ictx, void *state)
|
||||
void
|
||||
input_init(struct window *w)
|
||||
{
|
||||
ARRAY_INIT(&w->ictx.args);
|
||||
struct input_ctx *ictx = &w->ictx;
|
||||
|
||||
w->ictx.string_len = 0;
|
||||
w->ictx.string_buf = NULL;
|
||||
ARRAY_INIT(&ictx->args);
|
||||
|
||||
input_state(&w->ictx, input_state_first);
|
||||
ictx->string_len = 0;
|
||||
ictx->string_buf = NULL;
|
||||
|
||||
memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
|
||||
|
||||
memcpy(&ictx->saved_cell, &grid_default_cell, sizeof ictx->saved_cell);
|
||||
ictx->saved_cx = 0;
|
||||
ictx->saved_cy = 0;
|
||||
|
||||
input_state(ictx, input_state_first);
|
||||
}
|
||||
|
||||
void
|
||||
@ -341,10 +349,9 @@ void
|
||||
input_state_title_next(u_char ch, struct input_ctx *ictx)
|
||||
{
|
||||
if (ch == '\007') {
|
||||
if (ictx->string_type == STRING_TITLE) {
|
||||
screen_write_set_title(
|
||||
&ictx->ctx, input_get_string(ictx));
|
||||
} else
|
||||
if (ictx->string_type == STRING_TITLE)
|
||||
screen_set_title(ictx->ctx.s, input_get_string(ictx));
|
||||
else
|
||||
input_abort_string(ictx);
|
||||
input_state(ictx, input_state_first);
|
||||
return;
|
||||
@ -490,59 +497,67 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
|
||||
void
|
||||
input_state_utf8(u_char ch, struct input_ctx *ictx)
|
||||
{
|
||||
u_int value;
|
||||
|
||||
log_debug2("-- un %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
ictx->utf8_buf.data[ictx->utf8_off++] = ch;
|
||||
ictx->utf8_buf[ictx->utf8_off++] = ch;
|
||||
if (--ictx->utf8_len != 0)
|
||||
return;
|
||||
input_state(ictx, input_state_first);
|
||||
|
||||
screen_write_put_utf8(&ictx->ctx, &ictx->utf8_buf);
|
||||
value = utf8_combine(ictx->utf8_buf);
|
||||
if (value > 0xffff) /* non-BMP not supported */
|
||||
value = '_';
|
||||
|
||||
ictx->cell.data = value;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell);
|
||||
}
|
||||
|
||||
void
|
||||
input_handle_character(u_char ch, struct input_ctx *ictx)
|
||||
{
|
||||
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
if (ch > 0x7f) {
|
||||
/*
|
||||
* UTF8 sequence.
|
||||
* UTF-8 sequence.
|
||||
*
|
||||
* 11000010-11011111 C2-DF start of 2-byte sequence
|
||||
* 11100000-11101111 E0-EF start of 3-byte sequence
|
||||
* 11110000-11110100 F0-F4 start of 4-byte sequence
|
||||
*/
|
||||
memset(&ictx->utf8_buf.data, 0xff, sizeof &ictx->utf8_buf.data);
|
||||
ictx->utf8_buf.data[0] = ch;
|
||||
memset(ictx->utf8_buf, 0xff, sizeof ictx->utf8_buf);
|
||||
ictx->utf8_buf[0] = ch;
|
||||
ictx->utf8_off = 1;
|
||||
|
||||
if (ch >= 0xc2 && ch <= 0xdf) {
|
||||
log_debug2(":: u2");
|
||||
log_debug2("-- u2 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
input_state(ictx, input_state_utf8);
|
||||
ictx->utf8_len = 1;
|
||||
return;
|
||||
}
|
||||
if (ch >= 0xe0 && ch <= 0xef) {
|
||||
log_debug2(":: u3");
|
||||
log_debug2("-- u3 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
input_state(ictx, input_state_utf8);
|
||||
ictx->utf8_len = 2;
|
||||
return;
|
||||
}
|
||||
if (ch >= 0xf0 && ch <= 0xf4) {
|
||||
log_debug2(":: u4");
|
||||
log_debug2("-- u4 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
input_state(ictx, input_state_utf8);
|
||||
ictx->utf8_len = 3;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
screen_write_put_character(&ictx->ctx, ch);
|
||||
ictx->cell.data = ch;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell);
|
||||
}
|
||||
|
||||
void
|
||||
input_handle_c0_control(u_char ch, struct input_ctx *ictx)
|
||||
{
|
||||
struct screen *s = ictx->ctx.s;
|
||||
u_short attr;
|
||||
|
||||
log_debug2("-- c0 %zu: %hhu", ictx->off, ch);
|
||||
|
||||
@ -550,32 +565,31 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx)
|
||||
case '\0': /* NUL */
|
||||
break;
|
||||
case '\n': /* LF */
|
||||
screen_write_cursor_down_scroll(&ictx->ctx);
|
||||
screen_write_linefeed(&ictx->ctx);
|
||||
break;
|
||||
case '\r': /* CR */
|
||||
screen_write_move_cursor(&ictx->ctx, 0, s->cy);
|
||||
screen_write_carriagereturn(&ictx->ctx);
|
||||
break;
|
||||
case '\007': /* BELL */
|
||||
ictx->w->flags |= WINDOW_BELL;
|
||||
break;
|
||||
case '\010': /* BS */
|
||||
screen_write_cursor_left(&ictx->ctx, 1);
|
||||
screen_write_cursorleft(&ictx->ctx, 1);
|
||||
break;
|
||||
case '\011': /* TAB */
|
||||
/* XXX right? */
|
||||
s->cx = ((s->cx / 8) * 8) + 8;
|
||||
if (s->cx > screen_last_x(s)) {
|
||||
if (s->cx > screen_size_x(s) - 1) {
|
||||
s->cx = 0;
|
||||
screen_write_cursor_down(&ictx->ctx, 1);
|
||||
screen_write_cursordown(&ictx->ctx, 1);
|
||||
}
|
||||
screen_write_move_cursor(&ictx->ctx, s->cx, s->cy);
|
||||
screen_write_cursormove(&ictx->ctx, s->cx, s->cy);
|
||||
break;
|
||||
case '\016': /* SO */
|
||||
attr = s->attr | ATTR_CHARSET;
|
||||
screen_write_set_attributes(&ictx->ctx, attr, s->fg, s->bg);
|
||||
ictx->cell.attr |= GRID_ATTR_CHARSET;
|
||||
break;
|
||||
case '\017': /* SI */
|
||||
attr = s->attr & ~ATTR_CHARSET;
|
||||
screen_write_set_attributes(&ictx->ctx, attr, s->fg, s->bg);
|
||||
ictx->cell.attr &= ~GRID_ATTR_CHARSET;
|
||||
break;
|
||||
default:
|
||||
log_debug("unknown c0: %hhu", ch);
|
||||
@ -590,7 +604,7 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx)
|
||||
|
||||
switch (ch) {
|
||||
case 'M': /* RI */
|
||||
screen_write_cursor_up_scroll(&ictx->ctx);
|
||||
screen_write_reverseindex(&ictx->ctx);
|
||||
break;
|
||||
default:
|
||||
log_debug("unknown c1: %hhu", ch);
|
||||
@ -607,27 +621,22 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx)
|
||||
|
||||
switch (ch) {
|
||||
case '=': /* DECKPAM */
|
||||
screen_write_set_mode(&ictx->ctx, MODE_KKEYPAD);
|
||||
screen_write_kkeypadmode(&ictx->ctx, 1);
|
||||
log_debug("kkeypad on (application mode)");
|
||||
break;
|
||||
case '>': /* DECKPNM */
|
||||
screen_write_clear_mode(&ictx->ctx, MODE_KKEYPAD);
|
||||
screen_write_kkeypadmode(&ictx->ctx, 0);
|
||||
log_debug("kkeypad off (number mode)");
|
||||
break;
|
||||
case '7': /* DECSC */
|
||||
s->saved_cx = s->cx;
|
||||
s->saved_cy = s->cy;
|
||||
s->saved_attr = s->attr;
|
||||
s->saved_fg = s->fg;
|
||||
s->saved_bg = s->bg;
|
||||
s->mode |= MODE_SAVED;
|
||||
memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
|
||||
ictx->saved_cx = s->cx;
|
||||
ictx->saved_cy = s->cy;
|
||||
break;
|
||||
case '8': /* DECRC */
|
||||
if (!(s->mode & MODE_SAVED))
|
||||
break;
|
||||
screen_write_set_attributes(
|
||||
&ictx->ctx, s->saved_attr, s->saved_fg, s->saved_bg);
|
||||
screen_write_move_cursor(&ictx->ctx, s->saved_cx, s->saved_cy);
|
||||
memcpy(&ictx->cell, &ictx->saved_cell, sizeof ictx->cell);
|
||||
screen_write_cursormove(
|
||||
&ictx->ctx, ictx->saved_cx, ictx->saved_cy);
|
||||
break;
|
||||
default:
|
||||
log_debug("unknown p2: %hhu", ch);
|
||||
@ -641,6 +650,21 @@ input_handle_standard_two(u_char ch, struct input_ctx *ictx)
|
||||
log_debug2("-- s2 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
switch (ch) {
|
||||
case 'c': /* RIS */
|
||||
memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
|
||||
|
||||
memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
|
||||
ictx->saved_cx = 0;
|
||||
ictx->saved_cy = 0;
|
||||
|
||||
screen_write_insertmode(&ictx->ctx, 0);
|
||||
screen_write_kcursormode(&ictx->ctx, 0);
|
||||
screen_write_kkeypadmode(&ictx->ctx, 0);
|
||||
screen_write_mousemode(&ictx->ctx, 0);
|
||||
|
||||
screen_write_clearscreen(&ictx->ctx);
|
||||
screen_write_cursormove(&ictx->ctx, 0, 0);
|
||||
break;
|
||||
case 'k':
|
||||
input_start_string(ictx, STRING_NAME);
|
||||
input_state(ictx, input_state_string_next);
|
||||
@ -718,7 +742,7 @@ input_handle_sequence_cuu(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_cursor_up(&ictx->ctx, n);
|
||||
screen_write_cursorup(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -736,7 +760,7 @@ input_handle_sequence_cud(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_cursor_down(&ictx->ctx, n);
|
||||
screen_write_cursordown(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -754,7 +778,7 @@ input_handle_sequence_cuf(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_cursor_right(&ictx->ctx, n);
|
||||
screen_write_cursorright(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -772,7 +796,7 @@ input_handle_sequence_cub(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_cursor_left(&ictx->ctx, n);
|
||||
screen_write_cursorleft(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -790,7 +814,7 @@ input_handle_sequence_dch(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_delete_characters(&ictx->ctx, n);
|
||||
screen_write_deletecharacter(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -808,7 +832,7 @@ input_handle_sequence_dl(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_delete_lines(&ictx->ctx, n);
|
||||
screen_write_deleteline(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -826,7 +850,7 @@ input_handle_sequence_ich(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_insert_characters(&ictx->ctx, n);
|
||||
screen_write_insertcharacter(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -844,7 +868,7 @@ input_handle_sequence_il(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_insert_lines(&ictx->ctx, n);
|
||||
screen_write_insertline(&ictx->ctx, n);
|
||||
}
|
||||
|
||||
void
|
||||
@ -863,7 +887,7 @@ input_handle_sequence_vpa(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_move_cursor(&ictx->ctx, s->cx, n - 1);
|
||||
screen_write_cursormove(&ictx->ctx, s->cx, n - 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -882,7 +906,7 @@ input_handle_sequence_hpa(struct input_ctx *ictx)
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
screen_write_move_cursor(&ictx->ctx, n - 1, s->cy);
|
||||
screen_write_cursormove(&ictx->ctx, n - 1, s->cy);
|
||||
}
|
||||
|
||||
void
|
||||
@ -904,7 +928,7 @@ input_handle_sequence_cup(struct input_ctx *ictx)
|
||||
if (m == 0)
|
||||
m = 1;
|
||||
|
||||
screen_write_move_cursor(&ictx->ctx, m - 1, n - 1);
|
||||
screen_write_cursormove(&ictx->ctx, m - 1, n - 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -924,10 +948,13 @@ input_handle_sequence_ed(struct input_ctx *ictx)
|
||||
|
||||
switch (n) {
|
||||
case 0:
|
||||
screen_write_fill_end_of_screen(&ictx->ctx);
|
||||
screen_write_clearendofscreen(&ictx->ctx);
|
||||
break;
|
||||
case 1:
|
||||
screen_write_clearstartofscreen(&ictx->ctx);
|
||||
break;
|
||||
case 2:
|
||||
screen_write_fill_screen(&ictx->ctx);
|
||||
screen_write_clearscreen(&ictx->ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -949,13 +976,13 @@ input_handle_sequence_el(struct input_ctx *ictx)
|
||||
|
||||
switch (n) {
|
||||
case 0:
|
||||
screen_write_fill_end_of_line(&ictx->ctx);
|
||||
screen_write_clearendofline(&ictx->ctx);
|
||||
break;
|
||||
case 1:
|
||||
screen_write_fill_start_of_line(&ictx->ctx);
|
||||
screen_write_clearstartofline(&ictx->ctx);
|
||||
break;
|
||||
case 2:
|
||||
screen_write_fill_line(&ictx->ctx);
|
||||
screen_write_clearline(&ictx->ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -973,15 +1000,15 @@ input_handle_sequence_sm(struct input_ctx *ictx)
|
||||
if (ictx->private == '?') {
|
||||
switch (n) {
|
||||
case 1: /* GATM */
|
||||
screen_write_set_mode(&ictx->ctx, MODE_KCURSOR);
|
||||
screen_write_kcursormode(&ictx->ctx, 1);
|
||||
log_debug("kcursor on");
|
||||
break;
|
||||
case 25: /* TCEM */
|
||||
screen_write_set_mode(&ictx->ctx, MODE_CURSOR);
|
||||
screen_write_cursormode(&ictx->ctx, 1);
|
||||
log_debug("cursor on");
|
||||
break;
|
||||
case 1000:
|
||||
screen_write_set_mode(&ictx->ctx, MODE_MOUSE);
|
||||
screen_write_mousemode(&ictx->ctx, 1);
|
||||
log_debug("mouse on");
|
||||
break;
|
||||
default:
|
||||
@ -991,7 +1018,7 @@ input_handle_sequence_sm(struct input_ctx *ictx)
|
||||
} else {
|
||||
switch (n) {
|
||||
case 4: /* IRM */
|
||||
screen_write_set_mode(&ictx->ctx, MODE_INSERT);
|
||||
screen_write_insertmode(&ictx->ctx, 1);
|
||||
log_debug("insert on");
|
||||
break;
|
||||
case 34:
|
||||
@ -1017,15 +1044,15 @@ input_handle_sequence_rm(struct input_ctx *ictx)
|
||||
if (ictx->private == '?') {
|
||||
switch (n) {
|
||||
case 1: /* GATM */
|
||||
screen_write_clear_mode(&ictx->ctx, MODE_KCURSOR);
|
||||
screen_write_kcursormode(&ictx->ctx, 0);
|
||||
log_debug("kcursor off");
|
||||
break;
|
||||
case 25: /* TCEM */
|
||||
screen_write_clear_mode(&ictx->ctx, MODE_CURSOR);
|
||||
screen_write_cursormode(&ictx->ctx, 0);
|
||||
log_debug("cursor off");
|
||||
break;
|
||||
case 1000:
|
||||
screen_write_clear_mode(&ictx->ctx, MODE_MOUSE);
|
||||
screen_write_mousemode(&ictx->ctx, 0);
|
||||
log_debug("mouse off");
|
||||
break;
|
||||
default:
|
||||
@ -1035,7 +1062,7 @@ input_handle_sequence_rm(struct input_ctx *ictx)
|
||||
} else if (ictx->private == '\0') {
|
||||
switch (n) {
|
||||
case 4: /* IRM */
|
||||
screen_write_clear_mode(&ictx->ctx, MODE_INSERT);
|
||||
screen_write_insertmode(&ictx->ctx, 0);
|
||||
log_debug("insert off");
|
||||
break;
|
||||
case 34:
|
||||
@ -1093,118 +1120,107 @@ input_handle_sequence_decstbm(struct input_ctx *ictx)
|
||||
if (m == 0)
|
||||
m = screen_size_y(s);
|
||||
|
||||
screen_write_set_region(&ictx->ctx, n - 1, m - 1);
|
||||
screen_write_scrollregion(&ictx->ctx, n - 1, m - 1);
|
||||
}
|
||||
|
||||
void
|
||||
input_handle_sequence_sgr(struct input_ctx *ictx)
|
||||
{
|
||||
struct screen *s = ictx->ctx.s;
|
||||
u_int i, n;
|
||||
uint16_t m, o;
|
||||
u_short attr;
|
||||
u_char fg, bg;
|
||||
struct grid_cell *gc = &ictx->cell;
|
||||
u_int i;
|
||||
uint16_t m, o;
|
||||
|
||||
attr = s->attr;
|
||||
fg = s->fg;
|
||||
bg = s->bg;
|
||||
if (ARRAY_LENGTH(&ictx->args) == 0) {
|
||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||
return;
|
||||
}
|
||||
|
||||
n = ARRAY_LENGTH(&ictx->args);
|
||||
if (n == 0) {
|
||||
attr = 0;
|
||||
fg = 8;
|
||||
bg = 8;
|
||||
} else {
|
||||
for (i = 0; i < n; i++) {
|
||||
if (input_get_argument(ictx, i, &m, 0) != 0)
|
||||
for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
|
||||
if (input_get_argument(ictx, i, &m, 0) != 0)
|
||||
return;
|
||||
|
||||
if (m == 38 || m == 48) {
|
||||
i++;
|
||||
if (input_get_argument(ictx, i, &o, 0) != 0)
|
||||
return;
|
||||
|
||||
if (m == 38 || m == 48) {
|
||||
i++;
|
||||
if (input_get_argument(ictx, i, &o, 0) != 0)
|
||||
return;
|
||||
if (o != 5)
|
||||
continue;
|
||||
|
||||
i++;
|
||||
if (input_get_argument(ictx, i, &o, 0) != 0)
|
||||
return;
|
||||
if (m == 38) {
|
||||
attr |= ATTR_FG256;
|
||||
fg = o;
|
||||
} else if (m == 48) {
|
||||
attr |= ATTR_BG256;
|
||||
bg = o;
|
||||
}
|
||||
if (o != 5)
|
||||
continue;
|
||||
|
||||
i++;
|
||||
if (input_get_argument(ictx, i, &o, 0) != 0)
|
||||
return;
|
||||
if (m == 38) {
|
||||
gc->flags |= GRID_FLAG_FG256;
|
||||
gc->fg = o;
|
||||
} else if (m == 48) {
|
||||
gc->flags |= GRID_FLAG_BG256;
|
||||
gc->bg = o;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (m) {
|
||||
case 0:
|
||||
case 10:
|
||||
attr &= ATTR_CHARSET;
|
||||
fg = 8;
|
||||
bg = 8;
|
||||
break;
|
||||
case 1:
|
||||
attr |= ATTR_BRIGHT;
|
||||
break;
|
||||
case 2:
|
||||
attr |= ATTR_DIM;
|
||||
break;
|
||||
case 3:
|
||||
attr |= ATTR_ITALICS;
|
||||
break;
|
||||
case 4:
|
||||
attr |= ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 5:
|
||||
attr |= ATTR_BLINK;
|
||||
break;
|
||||
case 7:
|
||||
attr |= ATTR_REVERSE;
|
||||
break;
|
||||
case 8:
|
||||
attr |= ATTR_HIDDEN;
|
||||
break;
|
||||
case 23:
|
||||
attr &= ~ATTR_ITALICS;
|
||||
break;
|
||||
case 24:
|
||||
attr &= ~ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
attr &= ~ATTR_FG256;
|
||||
fg = m - 30;
|
||||
break;
|
||||
case 39:
|
||||
attr &= ~ATTR_FG256;
|
||||
fg = 8;
|
||||
break;
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
attr &= ~ATTR_BG256;
|
||||
bg = m - 40;
|
||||
break;
|
||||
case 49:
|
||||
attr &= ~ATTR_BG256;
|
||||
bg = 8;
|
||||
break;
|
||||
}
|
||||
switch (m) {
|
||||
case 0:
|
||||
case 10:
|
||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||
break;
|
||||
case 1:
|
||||
gc->attr |= GRID_ATTR_BRIGHT;
|
||||
break;
|
||||
case 2:
|
||||
gc->attr |= GRID_ATTR_DIM;
|
||||
break;
|
||||
case 3:
|
||||
gc->attr |= GRID_ATTR_ITALICS;
|
||||
break;
|
||||
case 4:
|
||||
gc->attr |= GRID_ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 5:
|
||||
gc->attr |= GRID_ATTR_BLINK;
|
||||
break;
|
||||
case 7:
|
||||
gc->attr |= GRID_ATTR_REVERSE;
|
||||
break;
|
||||
case 8:
|
||||
gc->attr |= GRID_ATTR_HIDDEN;
|
||||
break;
|
||||
case 23:
|
||||
gc->attr &= ~GRID_ATTR_ITALICS;
|
||||
break;
|
||||
case 24:
|
||||
gc->attr &= ~GRID_ATTR_UNDERSCORE;
|
||||
break;
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
gc->flags &= ~GRID_FLAG_FG256;
|
||||
gc->fg = m - 30;
|
||||
break;
|
||||
case 39:
|
||||
gc->flags &= ~GRID_FLAG_FG256;
|
||||
gc->fg = 8;
|
||||
break;
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
gc->flags &= ~GRID_FLAG_BG256;
|
||||
gc->bg = m - 40;
|
||||
break;
|
||||
case 49:
|
||||
gc->flags &= ~GRID_FLAG_BG256;
|
||||
gc->bg = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
screen_write_set_attributes(&ictx->ctx, attr, fg, bg);
|
||||
}
|
||||
|
5
log.c
5
log.c
@ -1,4 +1,4 @@
|
||||
/* $Id: log.c,v 1.5 2008-08-08 17:35:42 nicm Exp $ */
|
||||
/* $Id: log.c,v 1.6 2008-09-25 20:08:52 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -224,6 +224,9 @@ log_vfatal(const char *msg, va_list ap)
|
||||
}
|
||||
free(fmt);
|
||||
|
||||
#ifdef DEBUG
|
||||
abort();
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
477
screen-display.c
477
screen-display.c
@ -1,477 +0,0 @@
|
||||
/* $Id: screen-display.c,v 1.21 2008-09-09 22:16:36 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Get a cell. */
|
||||
void
|
||||
screen_display_get_cell(struct screen *s,
|
||||
u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg)
|
||||
{
|
||||
screen_get_cell(
|
||||
s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
|
||||
}
|
||||
|
||||
/* Set a cell. */
|
||||
void
|
||||
screen_display_set_cell(struct screen *s,
|
||||
u_int px, u_int py, u_char data, u_short attr, u_char fg, u_char bg)
|
||||
{
|
||||
screen_set_cell(
|
||||
s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
|
||||
}
|
||||
|
||||
/* Create a region of lines. */
|
||||
void
|
||||
screen_display_make_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
screen_make_lines(s, screen_y(s, py), ny);
|
||||
if (s->attr != 0 || s->fg != 8 || s->bg != 8) {
|
||||
screen_display_fill_area(
|
||||
s, 0, py, screen_size_x(s), ny, ' ', s->attr, s->fg, s->bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free a region of lines. */
|
||||
void
|
||||
screen_display_free_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
screen_free_lines(s, screen_y(s, py), ny);
|
||||
}
|
||||
|
||||
/* Move a set of lines. */
|
||||
void
|
||||
screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny)
|
||||
{
|
||||
if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) {
|
||||
SCREEN_DEBUG3(s, dy, py, ny);
|
||||
return;
|
||||
}
|
||||
if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) {
|
||||
SCREEN_DEBUG3(s, dy, py, ny);
|
||||
return;
|
||||
}
|
||||
screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny);
|
||||
}
|
||||
|
||||
/* Fill a set of cells. */
|
||||
void
|
||||
screen_display_fill_area(struct screen *s, u_int px, u_int py,
|
||||
u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg)
|
||||
{
|
||||
if (nx == 0 || ny == 0) {
|
||||
SCREEN_DEBUG4(s, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
|
||||
SCREEN_DEBUG4(s, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
if (!screen_in_x(s, px + nx - 1) || !screen_in_y(s, py + ny - 1)) {
|
||||
SCREEN_DEBUG4(s, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
screen_fill_area(
|
||||
s, screen_x(s, px), screen_y(s, py), nx, ny, data, attr, fg, bg);
|
||||
}
|
||||
|
||||
/* Scroll region up. */
|
||||
void
|
||||
screen_display_scroll_region_up(struct screen *s)
|
||||
{
|
||||
u_int ny, sy;
|
||||
|
||||
/*
|
||||
* If the region is the entire screen, this is easy-peasy. Allocate
|
||||
* a new line and adjust the history size.
|
||||
* XXX should this be done somewhere else?
|
||||
*/
|
||||
if (s->rupper == 0 && s->rlower == screen_last_y(s)) {
|
||||
if (s->hsize == s->hlimit) {
|
||||
/* If the limit is hit, free 10% and shift up. */
|
||||
ny = s->hlimit / 10;
|
||||
if (ny < 1)
|
||||
ny = 1;
|
||||
|
||||
sy = screen_size_y(s) + s->hsize;
|
||||
screen_free_lines(s, 0, ny);
|
||||
screen_move_lines(s, 0, ny, sy - ny);
|
||||
|
||||
s->hsize -= ny;
|
||||
}
|
||||
s->hsize++;
|
||||
|
||||
sy = screen_size_y(s) + s->hsize;
|
||||
s->grid_data = xrealloc(s->grid_data, sy, sizeof *s->grid_data);
|
||||
s->grid_attr = xrealloc(s->grid_attr, sy, sizeof *s->grid_attr);
|
||||
s->grid_fg = xrealloc(s->grid_fg, sy, sizeof *s->grid_fg);
|
||||
s->grid_bg = xrealloc(s->grid_bg, sy, sizeof *s->grid_fg);
|
||||
s->grid_size = xrealloc(s->grid_size, sy, sizeof *s->grid_size);
|
||||
screen_display_make_lines(s, screen_last_y(s), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll scrolling region up:
|
||||
* - delete rupper
|
||||
* - move rupper + 1 to rlower to rupper
|
||||
* - make new line at rlower
|
||||
*
|
||||
* Example: region is 12 to 24.
|
||||
* rlower = 24, rupper = 12
|
||||
* screen_free_lines(s, 12, 1);
|
||||
* screen_move_lines(s, 12, 13, 12);
|
||||
* screen_make_lines(s, 24, 1);
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, s->rupper, 1);
|
||||
|
||||
if (s->rupper != s->rlower) {
|
||||
screen_display_move_lines(s,
|
||||
s->rupper, s->rupper + 1, s->rlower - s->rupper);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, s->rlower, 1);
|
||||
}
|
||||
|
||||
/* Scroll region down. */
|
||||
void
|
||||
screen_display_scroll_region_down(struct screen *s)
|
||||
{
|
||||
/*
|
||||
* Scroll scrolling region down:
|
||||
* - delete rlower
|
||||
* - move rupper to rlower - 1 to rupper + 1
|
||||
* - make new line at rupper
|
||||
*
|
||||
* Example: region is 12 to 24.
|
||||
* rlower = 24, rupper = 12
|
||||
* screen_free_lines(s, 24, 1);
|
||||
* screen_move_lines(s, 13, 12, 12);
|
||||
* screen_make_lines(s, 12, 1);
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, s->rlower, 1);
|
||||
|
||||
if (s->rupper != s->rlower) {
|
||||
screen_display_move_lines(s,
|
||||
s->rupper + 1, s->rupper, s->rlower - s->rupper);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, s->rupper, 1);
|
||||
}
|
||||
|
||||
/* Insert lines. */
|
||||
void
|
||||
screen_display_insert_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (!screen_in_y(s, py)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
if (py + ny > screen_last_y(s))
|
||||
ny = screen_size_y(s) - py;
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert range of ny lines at py:
|
||||
* - Free ny lines from end of screen.
|
||||
* - Move from py to end of screen - ny to py + ny.
|
||||
* - Create ny lines at py.
|
||||
*
|
||||
* Example: insert 2 lines at 4.
|
||||
* sy = 10, py = 4, ny = 2
|
||||
* screen_free_lines(s, 8, 2); - delete lines 8,9
|
||||
* screen_move_lines(s, 6, 4, 4); - move 4,5,6,7 to 6,7,8,9
|
||||
* screen_make_lines(s, 4, 2); - make lines 4,5
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, screen_size_y(s) - ny, ny);
|
||||
|
||||
if (py + ny != screen_size_y(s)) {
|
||||
screen_display_move_lines(
|
||||
s, py + ny, py, screen_size_y(s) - py - ny);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, py, ny);
|
||||
}
|
||||
|
||||
/* Insert lines in region. */
|
||||
void
|
||||
screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (!screen_in_region(s, py)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
if (py + ny > s->rlower)
|
||||
ny = (s->rlower + 1) - py;
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert range of ny lines at py:
|
||||
* - Free ny lines from end of screen.
|
||||
* - Move from py to end of screen - ny to py + ny.
|
||||
* - Create ny lines at py.
|
||||
*
|
||||
* Example: insert 2 lines at 4.
|
||||
* ryu = 11, ryl = 16, py = 13, ny = 2
|
||||
* screen_free_lines(s, 15, 2); - delete lines 15,16
|
||||
* screen_move_lines(s, 13, 15, 2);- move 13,14 to 15,16
|
||||
* screen_make_lines(s, 13, 2); - make lines 13,14
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, (s->rlower + 1) - ny, ny);
|
||||
|
||||
if (py + ny != s->rlower + 1) {
|
||||
screen_display_move_lines(
|
||||
s, py + ny, py, (s->rlower + 1) - py - ny);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, py, ny);
|
||||
}
|
||||
|
||||
/* Delete lines. */
|
||||
void
|
||||
screen_display_delete_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (!screen_in_y(s, py)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
if (py + ny > screen_last_y(s))
|
||||
ny = screen_size_y(s) - py;
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete range of ny lines at py:
|
||||
* - Free ny lines at py.
|
||||
* - Move from py + ny to end of screen to py.
|
||||
* - Free and recreate last ny lines.
|
||||
*
|
||||
* Example: delete lines 3,4.
|
||||
* sy = 10, py = 3, ny = 2
|
||||
* screen_free_lines(s, 3, 2); - delete lines 3,4
|
||||
* screen_move_lines(s, 3, 5, 5); - move 5,6,7,8,9 to 3
|
||||
* screen_make_lines(s, 8, 2); - make lines 8,9
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, py, ny);
|
||||
|
||||
if (py + ny != screen_size_y(s)) {
|
||||
screen_display_move_lines(
|
||||
s, py, py + ny, screen_size_y(s) - py - ny);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, screen_size_y(s) - ny, ny);
|
||||
}
|
||||
|
||||
/* Delete lines inside scroll region. */
|
||||
void
|
||||
screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
if (!screen_in_region(s, py)) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
if (ny == 0) {
|
||||
SCREEN_DEBUG2(s, py, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
if (py + ny > s->rlower)
|
||||
ny = (s->rlower + 1) - py;
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Delete range of ny lines at py:
|
||||
* - Free ny lines at py.
|
||||
* - Move from py + ny to end of region to py.
|
||||
* - Free and recreate last ny lines.
|
||||
*
|
||||
* Example: delete lines 13,14.
|
||||
* ryu = 11, ryl = 16, py = 13, ny = 2
|
||||
* screen_free_lines(s, 13, 2); - delete lines 13,14
|
||||
* screen_move_lines(s, 15, 16, 2);- move 15,16 to 13
|
||||
* screen_make_lines(s, 15, 16); - make lines 15,16
|
||||
*/
|
||||
|
||||
screen_display_free_lines(s, py, ny);
|
||||
|
||||
if (py + ny != s->rlower + 1) {
|
||||
screen_display_move_lines(
|
||||
s, py, py + ny, (s->rlower + 1) - py - ny);
|
||||
}
|
||||
|
||||
screen_display_make_lines(s, (s->rlower + 1) - ny, ny);
|
||||
}
|
||||
|
||||
/* Insert characters. */
|
||||
void
|
||||
screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int mx;
|
||||
|
||||
if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
|
||||
SCREEN_DEBUG3(s, px, py, nx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (px + nx > screen_last_x(s))
|
||||
nx = screen_last_x(s) - px;
|
||||
|
||||
py = screen_y(s, py);
|
||||
|
||||
/* XXX Cheat and make the line a full line. */
|
||||
if (s->grid_size[py] < screen_size_x(s))
|
||||
screen_expand_line(s, py, screen_size_x(s));
|
||||
|
||||
/*
|
||||
* Inserting a range of nx at px.
|
||||
*
|
||||
* - Move sx - (px + nx) from px to px + nx.
|
||||
* - Clear the range at px to px + nx.
|
||||
*/
|
||||
|
||||
if (px + nx != screen_last_x(s)) {
|
||||
mx = screen_last_x(s) - (px + nx);
|
||||
memmove(&s->grid_data[py][px + nx],
|
||||
&s->grid_data[py][px], mx * sizeof **s->grid_data);
|
||||
memmove(&s->grid_attr[py][px + nx],
|
||||
&s->grid_attr[py][px], mx * sizeof **s->grid_attr);
|
||||
memmove(&s->grid_fg[py][px + nx],
|
||||
&s->grid_fg[py][px], mx * sizeof **s->grid_fg);
|
||||
memmove(&s->grid_bg[py][px + nx],
|
||||
&s->grid_bg[py][px], mx * sizeof **s->grid_bg);
|
||||
}
|
||||
|
||||
memset(&s->grid_data[py][px], ' ', nx);
|
||||
memset(&s->grid_attr[py][px], s->attr, nx);
|
||||
memset(&s->grid_fg[py][px], s->fg, nx);
|
||||
memset(&s->grid_bg[py][px], s->bg, nx);
|
||||
}
|
||||
|
||||
/* Delete characters. */
|
||||
void
|
||||
screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx)
|
||||
{
|
||||
u_int mx;
|
||||
|
||||
if (!screen_in_x(s, px) || !screen_in_y(s, py)) {
|
||||
SCREEN_DEBUG3(s, px, py, nx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (px + nx > screen_last_x(s))
|
||||
nx = screen_last_x(s) - px;
|
||||
|
||||
py = screen_y(s, py);
|
||||
|
||||
/* XXX Cheat and make the line a full line. */
|
||||
if (s->grid_size[py] < screen_size_x(s))
|
||||
screen_expand_line(s, py, screen_size_x(s));
|
||||
|
||||
/*
|
||||
* Deleting the range from px to px + nx.
|
||||
*
|
||||
* - Move sx - (px + nx) from px + nx to px.
|
||||
* - Clear the range from sx - nx to sx.
|
||||
*/
|
||||
|
||||
if (px + nx != screen_last_x(s)) {
|
||||
mx = screen_last_x(s) - (px + nx);
|
||||
memmove(&s->grid_data[py][px], &s->grid_data[py][px + nx], mx);
|
||||
memmove(&s->grid_attr[py][px], &s->grid_attr[py][px + nx], mx);
|
||||
memmove(&s->grid_fg[py][px], &s->grid_fg[py][px + nx], mx);
|
||||
memmove(&s->grid_bg[py][px], &s->grid_bg[py][px + nx], mx);
|
||||
}
|
||||
|
||||
memset(&s->grid_data[py][screen_size_x(s) - nx], ' ', nx);
|
||||
memset(&s->grid_attr[py][screen_size_x(s) - nx], s->attr, nx);
|
||||
memset(&s->grid_fg[py][screen_size_x(s) - nx], s->fg, nx);
|
||||
memset(&s->grid_bg[py][screen_size_x(s) - nx], s->bg, nx);
|
||||
}
|
||||
|
||||
/* Fill cells from another screen, with an offset. */
|
||||
void
|
||||
screen_display_copy_area(struct screen *dst, struct screen *src,
|
||||
u_int px, u_int py, u_int nx, u_int ny, u_int ox, u_int oy)
|
||||
{
|
||||
u_int i, j;
|
||||
u_short attr;
|
||||
u_char data, fg, bg;
|
||||
|
||||
if (nx == 0 || ny == 0) {
|
||||
SCREEN_DEBUG4(dst, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
if (!screen_in_x(dst, px) || !screen_in_y(dst, py)) {
|
||||
SCREEN_DEBUG4(dst, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
if (!screen_in_x(dst, px + nx - 1) || !screen_in_y(dst, py + ny - 1)) {
|
||||
SCREEN_DEBUG4(dst, px, py, nx, ny);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = py; i < py + ny; i++) {
|
||||
for (j = px; j < px + nx; j++) {
|
||||
screen_get_cell(src,
|
||||
screen_x(src, j) + ox, screen_y(src, i) - oy,
|
||||
&data, &attr, &fg, &bg);
|
||||
screen_display_set_cell(dst, j, i, data, attr, fg, bg);
|
||||
}
|
||||
}
|
||||
}
|
122
screen-redraw.c
122
screen-redraw.c
@ -1,4 +1,4 @@
|
||||
/* $Id: screen-redraw.c,v 1.11 2008-09-08 22:03:54 nicm Exp $ */
|
||||
/* $Id: screen-redraw.c,v 1.12 2008-09-25 20:08:54 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -22,9 +22,6 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
void screen_redraw_get_cell(struct screen_redraw_ctx *,
|
||||
u_int, u_int, u_char *, u_short *, u_char *, u_char *);
|
||||
|
||||
/* Initialise redrawing with a window. */
|
||||
void
|
||||
screen_redraw_start_window(struct screen_redraw_ctx *ctx, struct window *w)
|
||||
@ -66,16 +63,15 @@ screen_redraw_start(struct screen_redraw_ctx *ctx,
|
||||
* Save screen cursor position. Emulation of some TTY_* commands
|
||||
* requires this to be correct in the screen, so rather than having
|
||||
* a local copy and just manipulating it, save the screen's values,
|
||||
* modify them during redraw, and restore them when finished.
|
||||
* modify them during redraw, and restore them when finished. XXX.
|
||||
*/
|
||||
ctx->saved_cx = s->cx;
|
||||
ctx->saved_cy = s->cy;
|
||||
|
||||
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
|
||||
ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s));
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
|
||||
ctx->write(ctx->data, TTY_CURSOROFF);
|
||||
ctx->write(ctx->data, TTY_MOUSEOFF);
|
||||
ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_size_y(s) - 1);
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy);
|
||||
ctx->write(ctx->data, TTY_CURSORMODE, 0);
|
||||
ctx->write(ctx->data, TTY_MOUSEMODE, 0);
|
||||
}
|
||||
|
||||
/* Finish redrawing. */
|
||||
@ -87,62 +83,38 @@ screen_redraw_stop(struct screen_redraw_ctx *ctx)
|
||||
s->cx = ctx->saved_cx;
|
||||
s->cy = ctx->saved_cy;
|
||||
|
||||
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
|
||||
ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower);
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx);
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy);
|
||||
if (s->mode & MODE_CURSOR)
|
||||
ctx->write(ctx->data, TTY_CURSORON);
|
||||
ctx->write(ctx->data, TTY_CURSORMODE, 1);
|
||||
if (s->mode & MODE_MOUSE)
|
||||
ctx->write(ctx->data, TTY_MOUSEON);
|
||||
ctx->write(ctx->data, TTY_MOUSEMODE, 1);
|
||||
}
|
||||
|
||||
/* Get cell data. */
|
||||
/* Write character. */
|
||||
void
|
||||
screen_redraw_get_cell(struct screen_redraw_ctx *ctx,
|
||||
u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg)
|
||||
screen_redraw_putc(
|
||||
struct screen_redraw_ctx *ctx, struct grid_cell *gc, u_char ch)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
|
||||
screen_get_cell(
|
||||
s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
|
||||
}
|
||||
|
||||
/* Move cursor. */
|
||||
void
|
||||
screen_redraw_move_cursor(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
{
|
||||
if (px != ctx->s->cx || py != ctx->s->cy) {
|
||||
ctx->s->cx = px;
|
||||
ctx->s->cy = py;
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cy, ctx->s->cx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set attributes. */
|
||||
void
|
||||
screen_redraw_set_attributes(
|
||||
struct screen_redraw_ctx *ctx, u_short attr, u_char fg, u_char bg)
|
||||
{
|
||||
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
|
||||
gc->data = ch;
|
||||
ctx->write(ctx->data, TTY_CELL, gc);
|
||||
ctx->s->cx++;
|
||||
}
|
||||
|
||||
/* Write string. */
|
||||
void printflike2
|
||||
screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...)
|
||||
void printflike3
|
||||
screen_redraw_puts(
|
||||
struct screen_redraw_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *msg, *ptr;
|
||||
va_list ap;
|
||||
char *msg, *ptr;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
for (ptr = msg; *ptr != '\0'; ptr++) {
|
||||
if (*ptr < 0x20)
|
||||
continue;
|
||||
ctx->write(ctx->data, TTY_CHARACTER, *ptr);
|
||||
ctx->s->cx++;
|
||||
}
|
||||
for (ptr = msg; *ptr != '\0'; ptr++)
|
||||
screen_redraw_putc(ctx, gc, (u_char) *ptr);
|
||||
|
||||
xfree(msg);
|
||||
}
|
||||
@ -151,41 +123,45 @@ screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...)
|
||||
void
|
||||
screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
{
|
||||
u_short attr;
|
||||
u_char data, fg, bg;
|
||||
const struct grid_cell *gc;
|
||||
struct grid_cell hc;
|
||||
|
||||
screen_redraw_move_cursor(ctx, px, py);
|
||||
screen_redraw_get_cell(ctx, px, py, &data, &attr, &fg, &bg);
|
||||
|
||||
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg);
|
||||
ctx->write(ctx->data, TTY_CHARACTER, data);
|
||||
|
||||
ctx->s->cx++;
|
||||
}
|
||||
|
||||
/* Redraw area of cells. */
|
||||
void
|
||||
screen_redraw_area(
|
||||
struct screen_redraw_ctx *ctx, u_int px, u_int py, u_int nx, u_int ny)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
for (i = py; i < py + ny; i++) {
|
||||
for (j = px; j < px + nx; j++)
|
||||
screen_redraw_cell(ctx, j, i);
|
||||
if (px != ctx->s->cx || py != ctx->s->cy) {
|
||||
ctx->s->cx = px;
|
||||
ctx->s->cy = py;
|
||||
ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cx, ctx->s->cy);
|
||||
}
|
||||
|
||||
gc = grid_view_peek_cell(ctx->s->grid, px, py);
|
||||
if (screen_check_selection(ctx->s, px, py)) {
|
||||
memcpy(&hc, gc, sizeof hc);
|
||||
hc.attr |= GRID_ATTR_REVERSE;
|
||||
ctx->write(ctx->data, TTY_CELL, &hc);
|
||||
} else
|
||||
ctx->write(ctx->data, TTY_CELL, gc);
|
||||
ctx->s->cx++;
|
||||
}
|
||||
|
||||
/* Draw set of lines. */
|
||||
void
|
||||
screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny)
|
||||
{
|
||||
screen_redraw_area(ctx, 0, py, screen_size_x(ctx->s), ny);
|
||||
u_int i, j;
|
||||
|
||||
for (j = py; j < py + ny; j++) {
|
||||
for (i = 0; i < screen_size_x(ctx->s); i++)
|
||||
screen_redraw_cell(ctx, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw set of columns. */
|
||||
void
|
||||
screen_redraw_columns(struct screen_redraw_ctx *ctx, u_int px, u_int nx)
|
||||
{
|
||||
screen_redraw_area(ctx, px, 0, nx, screen_size_y(ctx->s));
|
||||
u_int i, j;
|
||||
|
||||
for (j = 0; j < screen_size_y(ctx->s); j++) {
|
||||
for (i = px; i < px + nx; i++)
|
||||
screen_redraw_cell(ctx, i, j);
|
||||
}
|
||||
}
|
||||
|
955
screen-write.c
955
screen-write.c
File diff suppressed because it is too large
Load Diff
375
screen.c
375
screen.c
@ -1,4 +1,4 @@
|
||||
/* $Id: screen.c,v 1.71 2008-09-10 19:15:04 nicm Exp $ */
|
||||
/* $Id: screen.c,v 1.72 2008-09-25 20:08:54 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -22,90 +22,18 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Virtual screen.
|
||||
*
|
||||
* A screen is stored as three arrays of lines of 8-bit values, one for the
|
||||
* actual characters (data), one for attributes and one for colours. Three
|
||||
* seperate blocks means memset and friends can be used. Each array is y by x
|
||||
* in size, row then column order. Sizes are 0-based. There is an additional
|
||||
* array of u_ints with the size of each line.
|
||||
*
|
||||
* Each screen has a history starting at the beginning of the arrays and
|
||||
* extending for hsize lines. Beyond that is the screen display of size
|
||||
* dy:
|
||||
*
|
||||
* ----------- array base
|
||||
* | |
|
||||
* | history |
|
||||
* ----------- array base + hsize
|
||||
* | |
|
||||
* | display |
|
||||
* | |
|
||||
* ----------- array base + hsize + dy
|
||||
*
|
||||
* The screen_x/screen_y macros are used to convert a cell on the displayed
|
||||
* area to an absolute position in the arrays.
|
||||
*
|
||||
* Screen handling code is split into four files:
|
||||
*
|
||||
* screen.c: Creation/deletion, utility functions, and basic functions to
|
||||
* manipulate the screen based on offsets from the base.
|
||||
* screen-display.c: Basic functions for manipulating the displayed
|
||||
* part of the screen. x,y coordinates passed to these
|
||||
* are relative to the display. These are largely
|
||||
* utility functions for screen-write.c.
|
||||
* screen-redraw.c: Functions for redrawing all or part of a screen to
|
||||
* one or more ttys. A context is filled via one of the
|
||||
* screen_redraw_start* variants which sets up (removes
|
||||
* cursor etc) and figures out which tty_write_* function
|
||||
* to use to write to the terminals, then the other
|
||||
* screen_redraw_* functions are used to draw the screen,
|
||||
* and screen_redraw_stop used to reset the cursor and
|
||||
* clean up. These are used when changing window and a
|
||||
* few other bits (status line).
|
||||
* screen-write.c: Functions for modifying (writing into) the screen and
|
||||
* optionally simultaneously updating one or more ttys.
|
||||
* These are used in much the same way as the redraw
|
||||
* functions. These are used to update when parsing
|
||||
* input from the window (input.c) and for the various
|
||||
* other modes which maintain private screens.
|
||||
*
|
||||
* If you're thinking this all seems too complicated, that's because it is :-/.
|
||||
*/
|
||||
void screen_resize_x(struct screen *, u_int);
|
||||
void screen_resize_y(struct screen *, u_int);
|
||||
|
||||
/* Create a new screen. */
|
||||
void
|
||||
screen_init(struct screen *s, u_int dx, u_int dy, u_int hlimit)
|
||||
screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
{
|
||||
s->dx = dx;
|
||||
s->dy = dy;
|
||||
s->cx = 0;
|
||||
s->cy = 0;
|
||||
s->grid = grid_create(sx, sy, hlimit);
|
||||
|
||||
s->rupper = 0;
|
||||
s->rlower = s->dy - 1;
|
||||
|
||||
s->hsize = 0;
|
||||
s->hlimit = hlimit;
|
||||
|
||||
s->attr = 0;
|
||||
s->fg = 8;
|
||||
s->bg = 8;
|
||||
|
||||
s->mode = MODE_CURSOR;
|
||||
s->title = xstrdup("");
|
||||
|
||||
s->grid_data = xmalloc(dy * (sizeof *s->grid_data));
|
||||
s->grid_attr = xmalloc(dy * (sizeof *s->grid_attr));
|
||||
s->grid_fg = xmalloc(dy * (sizeof *s->grid_fg));
|
||||
s->grid_bg = xmalloc(dy * (sizeof *s->grid_bg));
|
||||
s->grid_size = xmalloc(dy * (sizeof *s->grid_size));
|
||||
screen_make_lines(s, 0, dy);
|
||||
|
||||
utf8_init(&s->utf8_table, UTF8_LIMIT);
|
||||
|
||||
screen_clear_selection(s);
|
||||
screen_reinit(s);
|
||||
}
|
||||
|
||||
/* Reinitialise screen. */
|
||||
@ -116,16 +44,13 @@ screen_reinit(struct screen *s)
|
||||
s->cy = 0;
|
||||
|
||||
s->rupper = 0;
|
||||
s->rlower = s->dy - 1;
|
||||
|
||||
s->attr = 0;
|
||||
s->fg = 8;
|
||||
s->bg = 8;
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
|
||||
s->mode = MODE_CURSOR;
|
||||
|
||||
screen_display_fill_area(s, 0, 0,
|
||||
screen_size_x(s), screen_size_y(s), ' ', 0, 8, 8);
|
||||
/* XXX */
|
||||
grid_clear_lines(
|
||||
s->grid, s->grid->hsize, s->grid->hsize + s->grid->sy - 1);
|
||||
|
||||
screen_clear_selection(s);
|
||||
}
|
||||
@ -134,245 +59,121 @@ screen_reinit(struct screen *s)
|
||||
void
|
||||
screen_free(struct screen *s)
|
||||
{
|
||||
utf8_free(&s->utf8_table);
|
||||
xfree(s->title);
|
||||
screen_free_lines(s, 0, s->dy + s->hsize);
|
||||
xfree(s->grid_data);
|
||||
xfree(s->grid_attr);
|
||||
xfree(s->grid_fg);
|
||||
xfree(s->grid_bg);
|
||||
xfree(s->grid_size);
|
||||
grid_destroy(s->grid);
|
||||
}
|
||||
|
||||
/* Set screen title. */
|
||||
void
|
||||
screen_set_title(struct screen *s, const char *title)
|
||||
{
|
||||
xfree(s->title);
|
||||
s->title = xstrdup(title);
|
||||
}
|
||||
|
||||
/* Resize screen. */
|
||||
void
|
||||
screen_resize(struct screen *s, u_int sx, u_int sy)
|
||||
{
|
||||
u_int i, ox, oy, ny, my;
|
||||
|
||||
if (sx < 1)
|
||||
sx = 1;
|
||||
if (sy < 1)
|
||||
sy = 1;
|
||||
|
||||
ox = s->dx;
|
||||
oy = s->dy;
|
||||
if (sx == ox && sy == oy)
|
||||
if (sx != screen_size_x(s))
|
||||
screen_resize_x(s, sx);
|
||||
if (sy != screen_size_y(s))
|
||||
screen_resize_y(s, sy);
|
||||
}
|
||||
|
||||
void
|
||||
screen_resize_x(struct screen *s, u_int sx)
|
||||
{
|
||||
struct grid_data *gd = s->grid;
|
||||
const struct grid_cell *gc;
|
||||
u_int xx, yy;
|
||||
|
||||
/* If getting larger, not much to do. */
|
||||
if (sx > screen_size_x(s)) {
|
||||
gd->sx = sx;
|
||||
return;
|
||||
|
||||
/*
|
||||
* X dimension.
|
||||
*/
|
||||
if (sx != ox) {
|
||||
/*
|
||||
* If getting smaller, nuke any data in lines over the new
|
||||
* size.
|
||||
*/
|
||||
if (sx < ox) {
|
||||
for (i = s->hsize; i < s->hsize + oy; i++) {
|
||||
if (s->grid_size[i] > sx)
|
||||
screen_reduce_line(s, i, sx);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->cx >= sx)
|
||||
s->cx = sx - 1;
|
||||
s->dx = sx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Y dimension.
|
||||
*/
|
||||
if (sy == oy)
|
||||
return;
|
||||
/* If getting smaller, nuke any data in lines over the new size. */
|
||||
for (yy = gd->hsize; yy < gd->hsize + screen_size_y(s); yy++) {
|
||||
/*
|
||||
* If the character after the last is wide or padding, remove
|
||||
* it and any leading padding.
|
||||
*/
|
||||
for (xx = sx; xx > 0; xx--) {
|
||||
gc = grid_peek_cell(gd, xx - 1, yy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
|
||||
}
|
||||
if (xx > 0 && xx != sx && utf8_width(gc->data) != 1)
|
||||
grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
|
||||
|
||||
/* Reduce the line size. */
|
||||
grid_reduce_line(gd, yy, sx);
|
||||
}
|
||||
|
||||
if (s->cx >= sx)
|
||||
s->cx = sx - 1;
|
||||
gd->sx = sx;
|
||||
}
|
||||
|
||||
void
|
||||
screen_resize_y(struct screen *s, u_int sy)
|
||||
{
|
||||
struct grid_data *gd = s->grid;
|
||||
u_int oy, yy, ny;
|
||||
|
||||
/* Size decreasing. */
|
||||
if (sy < oy) {
|
||||
ny = oy - sy;
|
||||
if (sy < screen_size_y(s)) {
|
||||
oy = screen_size_y(s);
|
||||
|
||||
if (s->cy != 0) {
|
||||
/*
|
||||
* The cursor is not at the start. Try to remove as
|
||||
* many lines as possible from the top. (Up to the
|
||||
* cursor line.)
|
||||
*/
|
||||
my = s->cy;
|
||||
if (my > ny)
|
||||
my = ny;
|
||||
ny = s->cy;
|
||||
if (ny > oy - sy)
|
||||
ny = oy - sy;
|
||||
|
||||
screen_free_lines(s, s->hsize, my);
|
||||
screen_move_lines(s, s->hsize, s->hsize + my, oy - my);
|
||||
grid_view_delete_lines(gd, 0, ny);
|
||||
|
||||
s->cy -= my;
|
||||
oy -= my;
|
||||
s->cy -= ny;
|
||||
oy -= ny;
|
||||
}
|
||||
|
||||
ny = oy - sy;
|
||||
if (ny > 0) {
|
||||
/*
|
||||
* Remove any remaining lines from the bottom.
|
||||
*/
|
||||
screen_free_lines(s, s->hsize + oy - ny, ny);
|
||||
if (sy < oy) {
|
||||
/* Remove any remaining lines from the bottom. */
|
||||
grid_view_delete_lines(gd, sy, oy - sy);
|
||||
if (s->cy >= sy)
|
||||
s->cy = sy - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resize line arrays. */
|
||||
ny = s->hsize + sy;
|
||||
s->grid_data = xrealloc(s->grid_data, ny, sizeof *s->grid_data);
|
||||
s->grid_attr = xrealloc(s->grid_attr, ny, sizeof *s->grid_attr);
|
||||
s->grid_fg = xrealloc(s->grid_fg, ny, sizeof *s->grid_fg);
|
||||
s->grid_bg = xrealloc(s->grid_bg, ny, sizeof *s->grid_bg);
|
||||
s->grid_size = xrealloc(s->grid_size, ny, sizeof *s->grid_size);
|
||||
s->dy = sy;
|
||||
gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size);
|
||||
gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data);
|
||||
|
||||
/* Size increasing. */
|
||||
if (sy > oy)
|
||||
screen_make_lines(s, s->hsize + oy, sy - oy);
|
||||
if (sy > screen_size_y(s)) {
|
||||
oy = screen_size_y(s);
|
||||
for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) {
|
||||
gd->size[yy] = 0;
|
||||
gd->data[yy] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gd->sy = sy;
|
||||
|
||||
s->rupper = 0;
|
||||
s->rlower = s->dy - 1;
|
||||
}
|
||||
|
||||
/* Expand line. */
|
||||
void
|
||||
screen_expand_line(struct screen *s, u_int py, u_int nx)
|
||||
{
|
||||
u_int ox;
|
||||
|
||||
ox = s->grid_size[py];
|
||||
s->grid_size[py] = nx;
|
||||
|
||||
s->grid_data[py] = xrealloc(
|
||||
s->grid_data[py], sizeof **s->grid_data, nx);
|
||||
memset(&s->grid_data[py][ox], ' ', (nx - ox) * sizeof **s->grid_data);
|
||||
s->grid_attr[py] = xrealloc(
|
||||
s->grid_attr[py], sizeof **s->grid_attr, nx);
|
||||
memset(&s->grid_attr[py][ox], 0, (nx - ox) * sizeof **s->grid_attr);
|
||||
s->grid_fg[py] = xrealloc(
|
||||
s->grid_fg[py], sizeof **s->grid_fg, nx);
|
||||
memset(&s->grid_fg[py][ox], 8, (nx - ox) * sizeof **s->grid_fg);
|
||||
s->grid_bg[py] = xrealloc(
|
||||
s->grid_bg[py], sizeof **s->grid_bg, nx);
|
||||
memset(&s->grid_bg[py][ox], 8, (nx - ox) * sizeof **s->grid_bg);
|
||||
}
|
||||
|
||||
/* Reduce line. */
|
||||
void
|
||||
screen_reduce_line(struct screen *s, u_int py, u_int nx)
|
||||
{
|
||||
s->grid_size[py] = nx;
|
||||
|
||||
s->grid_data[py] = xrealloc(
|
||||
s->grid_data[py], sizeof **s->grid_data, nx);
|
||||
s->grid_attr[py] = xrealloc(
|
||||
s->grid_attr[py], sizeof **s->grid_attr, nx);
|
||||
s->grid_fg[py] = xrealloc(
|
||||
s->grid_fg[py], sizeof **s->grid_fg, nx);
|
||||
s->grid_bg[py] = xrealloc(
|
||||
s->grid_bg[py], sizeof **s->grid_bg, nx);
|
||||
}
|
||||
|
||||
/* Get cell. */
|
||||
void
|
||||
screen_get_cell(struct screen *s,
|
||||
u_int cx, u_int cy, u_char *data, u_short *attr, u_char *fg, u_char *bg)
|
||||
{
|
||||
if (cx >= s->grid_size[cy]) {
|
||||
*data = ' ';
|
||||
*attr = 0;
|
||||
*fg = 8;
|
||||
*bg = 8;
|
||||
} else {
|
||||
*data = s->grid_data[cy][cx];
|
||||
*attr = s->grid_attr[cy][cx];
|
||||
*fg = s->grid_fg[cy][cx];
|
||||
*bg = s->grid_bg[cy][cx];
|
||||
}
|
||||
|
||||
if (screen_check_selection(s, cx, cy))
|
||||
*attr |= ATTR_REVERSE;
|
||||
}
|
||||
|
||||
/* Set a cell. */
|
||||
void
|
||||
screen_set_cell(struct screen *s,
|
||||
u_int cx, u_int cy, u_char data, u_short attr, u_char fg, u_char bg)
|
||||
{
|
||||
if (cx >= s->grid_size[cy])
|
||||
screen_expand_line(s, cy, cx + 1);
|
||||
|
||||
s->grid_data[cy][cx] = data;
|
||||
s->grid_attr[cy][cx] = attr;
|
||||
s->grid_fg[cy][cx] = fg;
|
||||
s->grid_bg[cy][cx] = bg;
|
||||
}
|
||||
|
||||
/* Create a range of lines. */
|
||||
void
|
||||
screen_make_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = py; i < py + ny; i++) {
|
||||
s->grid_data[i] = NULL;
|
||||
s->grid_attr[i] = NULL;
|
||||
s->grid_fg[i] = NULL;
|
||||
s->grid_bg[i] = NULL;
|
||||
s->grid_size[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free a range of ny lines at py. */
|
||||
void
|
||||
screen_free_lines(struct screen *s, u_int py, u_int ny)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = py; i < py + ny; i++) {
|
||||
if (s->grid_data[i] != NULL)
|
||||
xfree(s->grid_data[i]);
|
||||
s->grid_data[i] = NULL;
|
||||
if (s->grid_attr[i] != NULL)
|
||||
xfree(s->grid_attr[i]);
|
||||
s->grid_attr[i] = NULL;
|
||||
if (s->grid_fg[i] != NULL)
|
||||
xfree(s->grid_fg[i]);
|
||||
s->grid_fg[i] = NULL;
|
||||
if (s->grid_bg[i] != NULL)
|
||||
xfree(s->grid_bg[i]);
|
||||
s->grid_bg[i] = NULL;
|
||||
s->grid_size[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move a range of lines. */
|
||||
void
|
||||
screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny)
|
||||
{
|
||||
memmove(
|
||||
&s->grid_data[dy], &s->grid_data[py], ny * (sizeof *s->grid_data));
|
||||
memmove(
|
||||
&s->grid_attr[dy], &s->grid_attr[py], ny * (sizeof *s->grid_attr));
|
||||
memmove(
|
||||
&s->grid_fg[dy], &s->grid_fg[py], ny * (sizeof *s->grid_fg));
|
||||
memmove(
|
||||
&s->grid_bg[dy], &s->grid_bg[py], ny * (sizeof *s->grid_bg));
|
||||
memmove(
|
||||
&s->grid_size[dy], &s->grid_size[py], ny * (sizeof *s->grid_size));
|
||||
}
|
||||
|
||||
/* Fill an area. */
|
||||
void
|
||||
screen_fill_area(struct screen *s, u_int px, u_int py,
|
||||
u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
for (i = py; i < py + ny; i++) {
|
||||
for (j = px; j < px + nx; j++)
|
||||
screen_set_cell(s, j, i, data, attr, fg, bg);
|
||||
}
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
}
|
||||
|
||||
/* Set selection. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: server-msg.c,v 1.50 2008-09-09 22:16:37 nicm Exp $ */
|
||||
/* $Id: server-msg.c,v 1.51 2008-09-25 20:08:54 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -189,6 +189,10 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c)
|
||||
tty_init(&c->tty, data.tty, xstrdup(term));
|
||||
if (data.flags & IDENTIFY_UTF8)
|
||||
c->tty.flags |= TTY_UTF8;
|
||||
if (data.flags & IDENTIFY_256COLOURS)
|
||||
c->tty.term_flags |= TERM_256COLOURS;
|
||||
if (data.flags & IDENTIFY_HASDEFAULTS)
|
||||
c->tty.term_flags |= TERM_HASDEFAULTS;
|
||||
xfree(term);
|
||||
|
||||
c->flags |= CLIENT_TERMINAL;
|
||||
|
28
server.c
28
server.c
@ -1,4 +1,4 @@
|
||||
/* $Id: server.c,v 1.80 2008-09-10 19:15:04 nicm Exp $ */
|
||||
/* $Id: server.c,v 1.81 2008-09-25 20:08:54 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -186,14 +186,14 @@ server_main(const char *srv_path, int srv_fd)
|
||||
server_fill_clients(&pfd);
|
||||
|
||||
/* Do the poll. */
|
||||
log_debug("polling %d fds", nfds);
|
||||
/* log_debug("polling %d fds", nfds); */
|
||||
if ((nfds = poll(pfds, nfds, 100)) == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
fatal("poll failed");
|
||||
}
|
||||
pfd = pfds;
|
||||
log_debug("poll returned %d", nfds);
|
||||
/* log_debug("poll returned %d", nfds); */
|
||||
|
||||
/* Handle server socket. */
|
||||
#ifndef BROKEN_POLL
|
||||
@ -271,7 +271,7 @@ server_fill_windows(struct pollfd **pfd)
|
||||
(*pfd)->events = POLLIN;
|
||||
if (BUFFER_USED(w->out) > 0)
|
||||
(*pfd)->events |= POLLOUT;
|
||||
log_debug("adding window %d (%d)", (*pfd)->fd, w->fd);
|
||||
/* log_debug("adding window %d (%d)", (*pfd)->fd, w->fd); */
|
||||
}
|
||||
(*pfd)++;
|
||||
}
|
||||
@ -286,7 +286,7 @@ server_handle_windows(struct pollfd **pfd)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||
if ((w = ARRAY_ITEM(&windows, i)) != NULL && w->fd != -1) {
|
||||
log_debug("testing window %d (%d)", (*pfd)->fd, w->fd);
|
||||
/* log_debug("testing window %d (%d)", (*pfd)->fd, w->fd); */
|
||||
if (buffer_poll(*pfd, w->in, w->out) != 0)
|
||||
server_lost_window(w);
|
||||
else
|
||||
@ -303,6 +303,7 @@ server_check_redraw(struct client *c)
|
||||
struct session *s;
|
||||
struct screen_redraw_ctx ctx;
|
||||
struct screen screen;
|
||||
struct grid_cell gc;
|
||||
u_int xx, yy, sx, sy;
|
||||
char title[BUFSIZ];
|
||||
int flags;
|
||||
@ -344,8 +345,9 @@ server_check_redraw(struct client *c)
|
||||
if (sx < xx)
|
||||
screen_redraw_columns(&ctx, sx, xx - sx);
|
||||
if (sy < yy) {
|
||||
screen_fill_area(
|
||||
&screen, 0, sy, xx, 1, '-', 0, 8, 8);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.data = '-';
|
||||
grid_view_fill(screen.grid, &gc, 0, sy, xx, 1);
|
||||
screen_redraw_lines(&ctx, sy, yy - sy);
|
||||
}
|
||||
screen_redraw_stop(&ctx);
|
||||
@ -423,7 +425,7 @@ server_fill_clients(struct pollfd **pfd)
|
||||
(*pfd)->events = POLLIN;
|
||||
if (BUFFER_USED(c->out) > 0)
|
||||
(*pfd)->events |= POLLOUT;
|
||||
log_debug("adding client %d (%d)", (*pfd)->fd, c->fd);
|
||||
/* log_debug("adding client %d (%d)", (*pfd)->fd, c->fd); */
|
||||
}
|
||||
(*pfd)++;
|
||||
|
||||
@ -434,7 +436,7 @@ server_fill_clients(struct pollfd **pfd)
|
||||
(*pfd)->events = POLLIN;
|
||||
if (BUFFER_USED(c->tty.out) > 0)
|
||||
(*pfd)->events |= POLLOUT;
|
||||
log_debug("adding tty %d (%d)", (*pfd)->fd, c->tty.fd);
|
||||
/* log_debug("adding tty %d (%d)", (*pfd)->fd, c->tty.fd); */
|
||||
}
|
||||
(*pfd)++;
|
||||
}
|
||||
@ -451,7 +453,7 @@ server_handle_clients(struct pollfd **pfd)
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
|
||||
if (c != NULL) {
|
||||
log_debug("testing client %d (%d)", (*pfd)->fd, c->fd);
|
||||
/* log_debug("testing client %d (%d)", (*pfd)->fd, c->fd); */
|
||||
if (buffer_poll(*pfd, c->in, c->out) != 0) {
|
||||
server_lost_client(c);
|
||||
(*pfd) += 2;
|
||||
@ -462,7 +464,7 @@ server_handle_clients(struct pollfd **pfd)
|
||||
(*pfd)++;
|
||||
|
||||
if (c != NULL && c->tty.fd != -1 && c->session != NULL) {
|
||||
log_debug("testing tty %d (%d)", (*pfd)->fd, c->tty.fd);
|
||||
/* log_debug("testing tty %d (%d)", (*pfd)->fd, c->tty.fd); */
|
||||
if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0)
|
||||
server_lost_client(c);
|
||||
else
|
||||
@ -594,12 +596,12 @@ server_handle_window(struct window *w)
|
||||
action = options_get_number(&s->options, "bell-action");
|
||||
switch (action) {
|
||||
case BELL_ANY:
|
||||
tty_write_session(s, TTY_CHARACTER, '\007');
|
||||
tty_write_session(s, TTY_BELL);
|
||||
break;
|
||||
case BELL_CURRENT:
|
||||
if (s->curw->window != w)
|
||||
break;
|
||||
tty_write_session(s, TTY_CHARACTER, '\007');
|
||||
tty_write_session(s, TTY_BELL);
|
||||
break;
|
||||
}
|
||||
update = 1;
|
||||
|
135
status.c
135
status.c
@ -1,4 +1,4 @@
|
||||
/* $Id: status.c,v 1.45 2008-09-08 22:03:54 nicm Exp $ */
|
||||
/* $Id: status.c,v 1.46 2008-09-25 20:08:54 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -25,7 +25,7 @@
|
||||
#include "tmux.h"
|
||||
|
||||
size_t status_width(struct winlink *);
|
||||
char *status_print(struct session *, struct winlink *, u_short *);
|
||||
char *status_print(struct session *, struct winlink *, struct grid_cell *);
|
||||
|
||||
/* Draw status for client on the last lines of given context. */
|
||||
void
|
||||
@ -38,8 +38,7 @@ status_redraw(struct client *c)
|
||||
char lbuf[BUFSIZ], rbuf[BUFSIZ];
|
||||
size_t llen, rlen, offset, xx, yy;
|
||||
size_t size, start, width;
|
||||
u_short attr;
|
||||
u_char fg, bg;
|
||||
struct grid_cell gc;
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
int larrow, rarrow;
|
||||
@ -50,8 +49,8 @@ status_redraw(struct client *c)
|
||||
|
||||
if (gettimeofday(&c->status_timer, NULL) != 0)
|
||||
fatal("gettimeofday");
|
||||
fg = options_get_number(&s->options, "status-fg");
|
||||
bg = options_get_number(&s->options, "status-bg");
|
||||
gc.fg = options_get_number(&s->options, "status-fg");
|
||||
gc.bg = options_get_number(&s->options, "status-bg");
|
||||
|
||||
yy = c->sy - 1;
|
||||
if (yy == 0)
|
||||
@ -138,24 +137,22 @@ draw:
|
||||
|
||||
/* Begin drawing and move to the starting position. */
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
if (llen != 0) {
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
screen_redraw_write_string(&ctx, "%s ", lbuf);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
screen_redraw_puts(&ctx, &gc, "%s ", lbuf);
|
||||
if (larrow)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
} else {
|
||||
if (larrow)
|
||||
screen_redraw_move_cursor(&ctx, 1, yy);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 1, yy);
|
||||
else
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
}
|
||||
|
||||
/* Draw each character in succession. */
|
||||
offset = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
text = status_print(s, wl, &attr);
|
||||
screen_redraw_set_attributes(&ctx, attr, fg, bg);
|
||||
text = status_print(s, wl, &gc);
|
||||
|
||||
if (larrow == 1 && offset < start) {
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
@ -166,7 +163,7 @@ draw:
|
||||
|
||||
for (ptr = text; *ptr != '\0'; ptr++) {
|
||||
if (offset >= start && offset < start + width)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, *ptr);
|
||||
screen_redraw_putc(&ctx, &gc, *ptr);
|
||||
offset++;
|
||||
}
|
||||
|
||||
@ -177,10 +174,10 @@ draw:
|
||||
rarrow = -1;
|
||||
}
|
||||
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
if (offset < start + width) {
|
||||
if (offset >= start) {
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
@ -189,52 +186,50 @@ draw:
|
||||
}
|
||||
|
||||
/* Fill the remaining space if any. */
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
while (offset++ < xx)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
|
||||
/* Draw the last item. */
|
||||
if (rlen != 0) {
|
||||
screen_redraw_move_cursor(&ctx, c->sx - rlen - 1, yy);
|
||||
screen_redraw_write_string(&ctx, " %s", rbuf);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 1, yy);
|
||||
screen_redraw_puts(&ctx, &gc, " %s", rbuf);
|
||||
}
|
||||
|
||||
/* Draw the arrows. */
|
||||
if (larrow != 0) {
|
||||
if (larrow == -1) {
|
||||
screen_redraw_set_attributes(
|
||||
&ctx, ATTR_REVERSE, fg, bg);
|
||||
} else
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
if (llen != 0)
|
||||
screen_redraw_move_cursor(&ctx, llen + 1, yy);
|
||||
if (larrow == -1)
|
||||
gc.attr |= GRID_ATTR_REVERSE;
|
||||
else
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
ctx.write(ctx.data, TTY_CHARACTER, '<');
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
if (llen != 0)
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, llen + 1, yy);
|
||||
else
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
screen_redraw_putc(&ctx, &gc, '<');
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
}
|
||||
if (rarrow != 0) {
|
||||
if (rarrow == -1) {
|
||||
screen_redraw_set_attributes(
|
||||
&ctx, ATTR_REVERSE, fg, bg);
|
||||
} else
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
if (rlen != 0)
|
||||
screen_redraw_move_cursor(&ctx, c->sx - rlen - 2, yy);
|
||||
if (rarrow == -1)
|
||||
gc.attr |= GRID_ATTR_REVERSE;
|
||||
else
|
||||
screen_redraw_move_cursor(&ctx, c->sx - 1, yy);
|
||||
ctx.write(ctx.data, TTY_CHARACTER, '>');
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
if (rlen != 0)
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 2, yy);
|
||||
else
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - 1, yy);
|
||||
screen_redraw_putc(&ctx, &gc, '>');
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
}
|
||||
|
||||
|
||||
screen_redraw_stop(&ctx);
|
||||
return;
|
||||
|
||||
blank:
|
||||
/* Just draw the whole line as blank. */
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
screen_redraw_set_attributes(&ctx, 0, fg, bg);
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
for (offset = 0; offset < c->sx; offset++)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
screen_redraw_stop(&ctx);
|
||||
|
||||
return;
|
||||
@ -247,10 +242,9 @@ off:
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
/* If the screen is too small, use blank. */
|
||||
if (screen_size_y(c->session->curw->window->screen) < c->sy) {
|
||||
screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
|
||||
screen_redraw_set_attributes(&ctx, 0, 8, 8);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, c->sy - 1);
|
||||
for (offset = 0; offset < c->sx; offset++)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
} else
|
||||
screen_redraw_lines(&ctx, c->sy - 1, 1);
|
||||
screen_redraw_stop(&ctx);
|
||||
@ -276,7 +270,7 @@ status_width(struct winlink *wl)
|
||||
}
|
||||
|
||||
char *
|
||||
status_print(struct session *s, struct winlink *wl, u_short *attr)
|
||||
status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
|
||||
{
|
||||
char *text, flag;
|
||||
|
||||
@ -286,14 +280,14 @@ status_print(struct session *s, struct winlink *wl, u_short *attr)
|
||||
if (wl == s->curw)
|
||||
flag = '*';
|
||||
|
||||
*attr = 0;
|
||||
gc->attr &= ~GRID_ATTR_REVERSE;
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY)) {
|
||||
flag = '#';
|
||||
*attr = ATTR_REVERSE;
|
||||
gc->attr |= GRID_ATTR_REVERSE;
|
||||
}
|
||||
if (session_alert_has(s, wl, WINDOW_BELL)) {
|
||||
flag = '!';
|
||||
*attr = ATTR_REVERSE;
|
||||
gc->attr |= GRID_ATTR_REVERSE;
|
||||
}
|
||||
|
||||
xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag);
|
||||
@ -306,6 +300,7 @@ status_message_redraw(struct client *c)
|
||||
{
|
||||
struct screen_redraw_ctx ctx;
|
||||
size_t xx, yy;
|
||||
struct grid_cell gc;
|
||||
|
||||
if (c->sx == 0 || c->sy == 0)
|
||||
return;
|
||||
@ -315,16 +310,19 @@ status_message_redraw(struct client *c)
|
||||
xx = c->sx;
|
||||
yy = c->sy - 1;
|
||||
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.attr |= GRID_ATTR_REVERSE;
|
||||
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->message_string);
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->message_string);
|
||||
for (; xx < c->sx; xx++)
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
|
||||
screen_redraw_stop(&ctx);
|
||||
|
||||
tty_write_client(c, TTY_CURSOROFF);
|
||||
tty_write_client(c, TTY_CURSORMODE, 0);
|
||||
}
|
||||
|
||||
/* Draw client prompt on status line of present else on last line. */
|
||||
@ -334,6 +332,7 @@ status_prompt_redraw(struct client *c)
|
||||
struct screen_redraw_ctx ctx;
|
||||
size_t i, xx, yy, left, size, offset;
|
||||
char ch;
|
||||
struct grid_cell gc;
|
||||
|
||||
if (c->sx == 0 || c->sy == 0)
|
||||
return;
|
||||
@ -344,11 +343,13 @@ status_prompt_redraw(struct client *c)
|
||||
xx = c->sx;
|
||||
yy = c->sy - 1;
|
||||
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 8, 8);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.attr |= GRID_ATTR_REVERSE;
|
||||
|
||||
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||
screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->prompt_string);
|
||||
screen_redraw_start_client(&ctx, c);
|
||||
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy);
|
||||
screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->prompt_string);
|
||||
|
||||
left = c->sx - xx;
|
||||
if (left != 0) {
|
||||
@ -360,29 +361,29 @@ status_prompt_redraw(struct client *c)
|
||||
left--;
|
||||
size = left;
|
||||
}
|
||||
screen_redraw_write_string(
|
||||
&ctx, "%.*s", (int) left, c->prompt_buffer + offset);
|
||||
screen_redraw_puts(
|
||||
&ctx, &gc, "%.*s", (int) left, c->prompt_buffer + offset);
|
||||
|
||||
for (i = xx + size; i < c->sx; i++) {
|
||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||
screen_redraw_putc(&ctx, &gc, ' ');
|
||||
ctx.s->cx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a fake cursor. */
|
||||
screen_redraw_set_attributes(&ctx, 0, 8, 8);
|
||||
screen_redraw_move_cursor(&ctx, xx + c->prompt_index - offset, yy);
|
||||
ctx.write(ctx.data, TTY_CURSORMOVE, xx + c->prompt_index - offset, yy);
|
||||
if (c->prompt_index == strlen(c->prompt_buffer))
|
||||
ch = ' ';
|
||||
else
|
||||
ch = c->prompt_buffer[c->prompt_index];
|
||||
if (ch == '\0')
|
||||
ch = ' ';
|
||||
tty_write_client(c, TTY_CHARACTER, ch);
|
||||
gc.attr &= ~GRID_ATTR_REVERSE;
|
||||
screen_redraw_putc(&ctx, &gc, ch);
|
||||
|
||||
screen_redraw_stop(&ctx);
|
||||
|
||||
tty_write_client(c, TTY_CURSOROFF);
|
||||
tty_write_client(c, TTY_CURSORMODE, 0);
|
||||
}
|
||||
|
||||
/* Handle keys in prompt. */
|
||||
|
11
tmux.1
11
tmux.1
@ -1,4 +1,4 @@
|
||||
.\" $Id: tmux.1,v 1.48 2008-06-30 18:27:14 nicm Exp $
|
||||
.\" $Id: tmux.1,v 1.49 2008-09-25 20:08:56 nicm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
.\"
|
||||
@ -668,6 +668,15 @@ maintain this maximum length.
|
||||
Set the maximum number of lines held in window history.
|
||||
This setting applies only to new windows - existing window histories are not
|
||||
resized and retain the limit at the point they were created.
|
||||
.It Xo Ic mode-keys
|
||||
.Op Ic vi | Ic emacs
|
||||
.Xc
|
||||
Use
|
||||
.Xr vi 1 -
|
||||
or
|
||||
.Xr emacs 1 -
|
||||
style key bindings in scroll and copy modes.
|
||||
Key bindings default to emacs.
|
||||
.It Ic prefix Ar key
|
||||
Set the current prefix key.
|
||||
.It Xo Ic remain-by-default
|
||||
|
12
tmux.c
12
tmux.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.c,v 1.75 2008-09-09 22:16:37 nicm Exp $ */
|
||||
/* $Id: tmux.c,v 1.76 2008-09-25 20:08:56 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -62,7 +62,7 @@ __dead void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-qVv] [-f file] [-S socket-path] [command [flags]]\n",
|
||||
"usage: %s [-2dquVv] [-f file] [-S socket-path] [command [flags]]\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
@ -179,8 +179,11 @@ main(int argc, char **argv)
|
||||
|
||||
flags = 0;
|
||||
path = NULL;
|
||||
while ((opt = getopt(argc, argv, "f:qS:uVv")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "2df:qS:uVv")) != EOF) {
|
||||
switch (opt) {
|
||||
case '2':
|
||||
flags |= IDENTIFY_256COLOURS;
|
||||
break;
|
||||
case 'f':
|
||||
cfg_file = xstrdup(optarg);
|
||||
break;
|
||||
@ -193,6 +196,9 @@ main(int argc, char **argv)
|
||||
case 'u':
|
||||
flags |= IDENTIFY_UTF8;
|
||||
break;
|
||||
case 'd':
|
||||
flags |= IDENTIFY_HASDEFAULTS;
|
||||
break;
|
||||
case 'v':
|
||||
debug_level++;
|
||||
break;
|
||||
|
379
tmux.h
379
tmux.h
@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.h,v 1.188 2008-09-10 19:15:04 nicm Exp $ */
|
||||
/* $Id: tmux.h,v 1.189 2008-09-25 20:08:56 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -19,7 +19,7 @@
|
||||
#ifndef TMUX_H
|
||||
#define TMUX_H
|
||||
|
||||
#define PROTOCOL_VERSION -2
|
||||
#define PROTOCOL_VERSION -3
|
||||
|
||||
/* Shut up gcc warnings about empty if bodies. */
|
||||
#define RB_AUGMENT(x) do {} while (0)
|
||||
@ -321,28 +321,32 @@ struct buffer {
|
||||
#define KEYC_KP4_2 (KEYC_OFFSET + 0x10f)
|
||||
|
||||
/* Output codes. */
|
||||
#define TTY_CHARACTER 0
|
||||
#define TTY_CURSORUP 1
|
||||
#define TTY_CURSORDOWN 2
|
||||
#define TTY_CURSORRIGHT 3
|
||||
#define TTY_CURSORLEFT 4
|
||||
#define TTY_INSERTCHARACTER 5
|
||||
#define TTY_DELETECHARACTER 6
|
||||
#define TTY_INSERTLINE 7
|
||||
#define TTY_DELETELINE 8
|
||||
#define TTY_CLEARLINE 9
|
||||
#define TTY_CLEARENDOFLINE 10
|
||||
#define TTY_CLEARSTARTOFLINE 11
|
||||
#define TTY_CURSORMOVE 12
|
||||
#define TTY_ATTRIBUTES 13
|
||||
#define TTY_CURSOROFF 14
|
||||
#define TTY_CURSORON 15
|
||||
#define TTY_REVERSEINDEX 16
|
||||
#define TTY_SCROLLREGION 17
|
||||
#define TTY_INSERTON 18
|
||||
#define TTY_INSERTOFF 19
|
||||
#define TTY_MOUSEON 20
|
||||
#define TTY_MOUSEOFF 21 /* XXX merge all on/off into 1 arg? */
|
||||
#define TTY_CURSORUP 0
|
||||
#define TTY_CURSORDOWN 1
|
||||
#define TTY_CURSORRIGHT 2
|
||||
#define TTY_CURSORLEFT 3
|
||||
#define TTY_INSERTCHARACTER 4
|
||||
#define TTY_DELETECHARACTER 5
|
||||
#define TTY_INSERTLINE 6
|
||||
#define TTY_DELETELINE 7
|
||||
#define TTY_CLEARLINE 8
|
||||
#define TTY_CLEARENDOFLINE 9
|
||||
#define TTY_CLEARSTARTOFLINE 10
|
||||
#define TTY_CURSORMOVE 11
|
||||
#define TTY_CURSORMODE 12
|
||||
#define TTY_REVERSEINDEX 13
|
||||
#define TTY_SCROLLREGION 14
|
||||
#define TTY_INSERTMODE 15
|
||||
#define TTY_MOUSEMODE 16
|
||||
#define TTY_LINEFEED 17
|
||||
#define TTY_CARRIAGERETURN 18
|
||||
#define TTY_BELL 19
|
||||
#define TTY_KCURSORMODE 20
|
||||
#define TTY_KKEYPADMODE 21
|
||||
#define TTY_CLEARENDOFSCREEN 22
|
||||
#define TTY_CLEARSTARTOFSCREEN 23
|
||||
#define TTY_CLEARSCREEN 24
|
||||
#define TTY_CELL 25
|
||||
|
||||
/* Message codes. */
|
||||
enum hdrtype {
|
||||
@ -376,6 +380,8 @@ struct msg_identify_data {
|
||||
int version;
|
||||
|
||||
#define IDENTIFY_UTF8 0x1
|
||||
#define IDENTIFY_256COLOURS 0x2
|
||||
#define IDENTIFY_HASDEFAULTS 0x4
|
||||
int flags;
|
||||
|
||||
u_int sx;
|
||||
@ -389,45 +395,52 @@ struct msg_resize_data {
|
||||
u_int sy;
|
||||
};
|
||||
|
||||
/* UTF8 data. */
|
||||
struct utf8_data {
|
||||
u_char data[4];
|
||||
};
|
||||
|
||||
struct utf8_table {
|
||||
u_int limit;
|
||||
ARRAY_DECL(, struct utf8_data) array;
|
||||
};
|
||||
#define UTF8_LIMIT ((1<<11) - 1)
|
||||
|
||||
/* Attributes. */
|
||||
#define ATTR_BRIGHT 0x1
|
||||
#define ATTR_DIM 0x2
|
||||
#define ATTR_UNDERSCORE 0x4
|
||||
#define ATTR_BLINK 0x8
|
||||
#define ATTR_REVERSE 0x10
|
||||
#define ATTR_HIDDEN 0x20
|
||||
#define ATTR_ITALICS 0x40
|
||||
#define ATTR_CHARSET 0x80 /* alternative character set */
|
||||
|
||||
#define ATTR_FG256 0x100
|
||||
#define ATTR_BG256 0x200
|
||||
|
||||
#define ATTR_UTF8 0x400
|
||||
#define ATTR_PAD 0x800
|
||||
|
||||
#define ATTR_UTF8b8 0x8000
|
||||
#define ATTR_UTF8b9 0x4000
|
||||
#define ATTR_UTF8b10 0x2000
|
||||
#define ATTR_UTF8b11 0x1000
|
||||
|
||||
/* Modes. */
|
||||
#define MODE_CURSOR 0x1
|
||||
#define MODE_INSERT 0x2
|
||||
#define MODE_KCURSOR 0x4
|
||||
#define MODE_KKEYPAD 0x8
|
||||
#define MODE_SAVED 0x10
|
||||
#define MODE_MOUSE 0x20
|
||||
#define MODE_MOUSE 0x10
|
||||
|
||||
/* Grid output. */
|
||||
#define GRID_DEBUG(gd, fmt, ...) log_debug3("%s: (sx=%u, sy=%u, hsize=%u) " \
|
||||
fmt, __func__, (gd)->sx, (gd)->sy, (gd)->hsize, ## __VA_ARGS__)
|
||||
|
||||
/* Grid attributes. */
|
||||
#define GRID_ATTR_BRIGHT 0x1
|
||||
#define GRID_ATTR_DIM 0x2
|
||||
#define GRID_ATTR_UNDERSCORE 0x4
|
||||
#define GRID_ATTR_BLINK 0x8
|
||||
#define GRID_ATTR_REVERSE 0x10
|
||||
#define GRID_ATTR_HIDDEN 0x20
|
||||
#define GRID_ATTR_ITALICS 0x40
|
||||
#define GRID_ATTR_CHARSET 0x80 /* alternative character set */
|
||||
|
||||
/* Grid flags. */
|
||||
#define GRID_FLAG_FG256 0x1
|
||||
#define GRID_FLAG_BG256 0x2
|
||||
#define GRID_FLAG_PADDING 0x4
|
||||
|
||||
/* Grid cell. */
|
||||
struct grid_cell {
|
||||
u_short data;
|
||||
u_char attr;
|
||||
u_char flags;
|
||||
u_char fg;
|
||||
u_char bg;
|
||||
} __packed;
|
||||
|
||||
/* Grid data. */
|
||||
struct grid_data {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int hsize;
|
||||
u_int hlimit;
|
||||
|
||||
u_int *size;
|
||||
struct grid_cell **data;
|
||||
};
|
||||
|
||||
/* Screen selection. */
|
||||
struct screen_sel {
|
||||
@ -444,34 +457,13 @@ struct screen_sel {
|
||||
struct screen {
|
||||
char *title;
|
||||
|
||||
u_char **grid_data;
|
||||
u_short **grid_attr;
|
||||
u_char **grid_fg;
|
||||
u_char **grid_bg;
|
||||
u_int *grid_size;
|
||||
|
||||
u_int dx; /* display x size */
|
||||
u_int dy; /* display y size */
|
||||
|
||||
u_int hsize; /* history y size */
|
||||
u_int hlimit; /* history y limit */
|
||||
|
||||
u_int rupper; /* scroll region top */
|
||||
u_int rlower; /* scroll region bottom */
|
||||
struct grid_data *grid; /* grid data */
|
||||
|
||||
u_int cx; /* cursor x */
|
||||
u_int cy; /* cursor y */
|
||||
u_short attr;
|
||||
u_char fg;
|
||||
u_char bg;
|
||||
|
||||
struct utf8_table utf8_table;
|
||||
|
||||
u_int saved_cx;
|
||||
u_int saved_cy;
|
||||
u_short saved_attr;
|
||||
u_char saved_fg;
|
||||
u_char saved_bg;
|
||||
u_int rupper; /* scroll region top */
|
||||
u_int rlower; /* scroll region bottom */
|
||||
|
||||
int mode;
|
||||
|
||||
@ -497,51 +489,11 @@ struct screen_write_ctx {
|
||||
struct screen *s;
|
||||
};
|
||||
|
||||
/* Screen display access macros. */
|
||||
#define screen_x(s, x) (x)
|
||||
#define screen_y(s, y) ((s)->hsize + y)
|
||||
|
||||
#define screen_last_x(s) ((s)->dx - 1)
|
||||
#define screen_last_y(s) ((s)->dy - 1)
|
||||
|
||||
#define screen_size_x(s) ((s)->dx)
|
||||
#define screen_size_y(s) ((s)->dy)
|
||||
|
||||
#define screen_in_x(s, x) ((x) < screen_size_x(s))
|
||||
#define screen_in_y(s, y) ((y) < screen_size_y(s))
|
||||
#define screen_in_region(s, y) ((y) >= (s)->rupper && (y) <= (s)->rlower)
|
||||
|
||||
/* These are inclusive... */
|
||||
#define screen_left_x(s, x) ((x) + 1)
|
||||
#define screen_right_x(s, x) \
|
||||
((x) < screen_size_x(s) ? screen_size_x(s) - (x) : 0)
|
||||
|
||||
#define screen_above_y(s, y) ((y) + 1)
|
||||
#define screen_below_y(s, y) \
|
||||
((y) < screen_size_y(s) ? screen_size_y(s) - (y) : 0)
|
||||
|
||||
#define SCREEN_DEBUG(s) do { \
|
||||
log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u", __func__, \
|
||||
s->cx, s->cy, screen_size_x(s), screen_size_y(s)); \
|
||||
} while (0)
|
||||
#define SCREEN_DEBUG1(s, n) do { \
|
||||
log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u", __func__, \
|
||||
s->cx, s->cy, screen_size_x(s), screen_size_y(s), n); \
|
||||
} while (0)
|
||||
#define SCREEN_DEBUG2(s, n, m) do { \
|
||||
log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u", __func__, \
|
||||
s->cx, s->cy, screen_size_x(s), screen_size_y(s), n, m); \
|
||||
} while (0)
|
||||
#define SCREEN_DEBUG3(s, n, m, o) do { \
|
||||
log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u o=%u", \
|
||||
__func__, s->cx, s->cy, screen_size_x(s), screen_size_y(s), \
|
||||
n, m, o); \
|
||||
} while (0)
|
||||
#define SCREEN_DEBUG4(s, n, m, o, p) do { \
|
||||
log_warnx("%s: cx=%u,cy=%u sx=%u,sy=%u n=%u m=%u o=%u p=%u", \
|
||||
__func__, s->cx, s->cy, screen_size_x(s), screen_size_y(s), \
|
||||
n, m, o, p); \
|
||||
} while (0)
|
||||
/* Screen size. */
|
||||
#define screen_size_x(s) ((s)->grid->sx)
|
||||
#define screen_size_y(s) ((s)->grid->sy)
|
||||
#define screen_hsize(s) ((s)->grid->hsize)
|
||||
#define screen_hlimit(s) ((s)->grid->hlimit)
|
||||
|
||||
/* Input parser sequence argument. */
|
||||
struct input_arg {
|
||||
@ -558,6 +510,12 @@ struct input_ctx {
|
||||
size_t len;
|
||||
size_t off;
|
||||
|
||||
struct grid_cell cell; /* current cell data */
|
||||
|
||||
struct grid_cell saved_cell;
|
||||
u_int saved_cx;
|
||||
u_int saved_cy;
|
||||
|
||||
#define MAXSTRINGLEN 1024
|
||||
u_char *string_buf;
|
||||
size_t string_len;
|
||||
@ -566,7 +524,7 @@ struct input_ctx {
|
||||
#define STRING_NAME 1
|
||||
#define STRING_IGNORE 2
|
||||
|
||||
struct utf8_data utf8_buf;
|
||||
u_char utf8_buf[4];
|
||||
u_int utf8_len;
|
||||
u_int utf8_off;
|
||||
|
||||
@ -725,9 +683,7 @@ struct tty {
|
||||
|
||||
struct termios tio;
|
||||
|
||||
u_short attr;
|
||||
u_char fg;
|
||||
u_char bg;
|
||||
struct grid_cell cell;
|
||||
|
||||
u_char acs[UCHAR_MAX + 1];
|
||||
|
||||
@ -737,6 +693,8 @@ struct tty {
|
||||
#define TTY_UTF8 0x8
|
||||
int flags;
|
||||
|
||||
int term_flags;
|
||||
|
||||
struct timeval key_timer;
|
||||
|
||||
size_t ksize; /* maximum key size */
|
||||
@ -1175,65 +1133,85 @@ void input_key(struct window *, int);
|
||||
const char *colour_tostring(u_char);
|
||||
u_char colour_fromstring(const char *);
|
||||
|
||||
/* screen-display.c */
|
||||
void screen_display_get_cell(struct screen *,
|
||||
u_int, u_int, u_char *, u_short *, u_char *, u_char *);
|
||||
void screen_display_set_cell(
|
||||
struct screen *, u_int, u_int, u_char, u_short, u_char, u_char);
|
||||
void screen_display_make_lines(struct screen *, u_int, u_int);
|
||||
void screen_display_free_lines(struct screen *, u_int, u_int);
|
||||
void screen_display_move_lines(struct screen *, u_int, u_int, u_int);
|
||||
void screen_display_fill_area(struct screen *,
|
||||
u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char);
|
||||
void screen_display_scroll_region_up(struct screen *);
|
||||
void screen_display_scroll_region_down(struct screen *);
|
||||
void screen_display_insert_lines(struct screen *, u_int, u_int);
|
||||
void screen_display_insert_lines_region(struct screen *, u_int, u_int);
|
||||
void screen_display_delete_lines(struct screen *, u_int, u_int);
|
||||
void screen_display_delete_lines_region(struct screen *, u_int, u_int);
|
||||
void screen_display_insert_characters(struct screen *, u_int, u_int, u_int);
|
||||
void screen_display_delete_characters(struct screen *, u_int, u_int, u_int);
|
||||
void screen_display_copy_area(struct screen *, struct screen *,
|
||||
u_int, u_int, u_int, u_int, u_int, u_int);
|
||||
/* grid.c */
|
||||
extern const struct grid_cell grid_default_cell;
|
||||
struct grid_data *grid_create(u_int, u_int, u_int);
|
||||
void grid_destroy(struct grid_data *);
|
||||
void grid_reduce_line(struct grid_data *, u_int, u_int);
|
||||
void grid_expand_line(struct grid_data *, u_int, u_int);
|
||||
void grid_scroll_line(struct grid_data *);
|
||||
const struct grid_cell *grid_peek_cell(struct grid_data *, u_int, u_int);
|
||||
struct grid_cell *grid_get_cell(struct grid_data *, u_int, u_int);
|
||||
void grid_set_cell(
|
||||
struct grid_data *, u_int, u_int, const struct grid_cell *);
|
||||
void grid_clear(struct grid_data *, u_int, u_int, u_int, u_int);
|
||||
void grid_fill(struct grid_data *,
|
||||
const struct grid_cell *, u_int, u_int, u_int, u_int);
|
||||
void grid_fill_lines(
|
||||
struct grid_data *, const struct grid_cell *, u_int, u_int);
|
||||
void grid_clear_lines(struct grid_data *, u_int, u_int);
|
||||
void grid_move_lines(struct grid_data *, u_int, u_int, u_int);
|
||||
void grid_clear_cells(struct grid_data *, u_int, u_int, u_int);
|
||||
void grid_move_cells(struct grid_data *, u_int, u_int, u_int, u_int);
|
||||
|
||||
/* grid-view.c */
|
||||
const struct grid_cell *grid_view_peek_cell(struct grid_data *, u_int, u_int);
|
||||
struct grid_cell *grid_view_get_cell(struct grid_data *, u_int, u_int);
|
||||
void grid_view_set_cell(
|
||||
struct grid_data *, u_int, u_int, const struct grid_cell *);
|
||||
void grid_view_clear(struct grid_data *, u_int, u_int, u_int, u_int);
|
||||
void grid_view_fill(struct grid_data *,
|
||||
const struct grid_cell *, u_int, u_int, u_int, u_int);
|
||||
void grid_view_scroll_region_up(struct grid_data *, u_int, u_int);
|
||||
void grid_view_scroll_region_down(struct grid_data *, u_int, u_int);
|
||||
void grid_view_insert_lines(struct grid_data *, u_int, u_int);
|
||||
void grid_view_insert_lines_region(
|
||||
struct grid_data *, u_int, u_int, u_int, u_int);
|
||||
void grid_view_delete_lines(struct grid_data *, u_int, u_int);
|
||||
void grid_view_delete_lines_region(
|
||||
struct grid_data *, u_int, u_int, u_int, u_int);
|
||||
void grid_view_insert_cells(struct grid_data *, u_int, u_int, u_int);
|
||||
void grid_view_delete_cells(struct grid_data *, u_int, u_int, u_int);
|
||||
|
||||
/* screen-write.c */
|
||||
void screen_write_start_window(struct screen_write_ctx *, struct window *);
|
||||
void screen_write_start_client(struct screen_write_ctx *, struct client *);
|
||||
void screen_write_start_session(
|
||||
struct screen_write_ctx *, struct session *);
|
||||
struct screen_write_ctx *, struct session *);
|
||||
void screen_write_start(struct screen_write_ctx *,
|
||||
struct screen *, void (*)(void *, int, ...), void *);
|
||||
struct screen *, void (*)(void *, int, ...), void *);
|
||||
void screen_write_stop(struct screen_write_ctx *);
|
||||
void screen_write_set_title(struct screen_write_ctx *, char *);
|
||||
void screen_write_put_character(struct screen_write_ctx *, u_char);
|
||||
void screen_write_put_utf8(struct screen_write_ctx *, struct utf8_data *);
|
||||
size_t printflike2 screen_write_put_string_rjust(
|
||||
struct screen_write_ctx *, const char *, ...);
|
||||
void printflike2 screen_write_put_string(
|
||||
struct screen_write_ctx *, const char *, ...);
|
||||
void screen_write_set_attributes(
|
||||
struct screen_write_ctx *, u_short, u_char, u_char);
|
||||
void screen_write_set_region(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_cursor_up_scroll(struct screen_write_ctx *);
|
||||
void screen_write_cursor_down_scroll(struct screen_write_ctx *);
|
||||
void screen_write_cursor_up(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursor_down(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursor_left(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursor_right(struct screen_write_ctx *, u_int);
|
||||
void screen_write_delete_lines(struct screen_write_ctx *, u_int);
|
||||
void screen_write_delete_characters(struct screen_write_ctx *, u_int);
|
||||
void screen_write_insert_lines(struct screen_write_ctx *, u_int);
|
||||
void screen_write_insert_characters(struct screen_write_ctx *, u_int);
|
||||
void screen_write_move_cursor(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_fill_end_of_screen(struct screen_write_ctx *);
|
||||
void screen_write_fill_screen(struct screen_write_ctx *);
|
||||
void screen_write_fill_end_of_line(struct screen_write_ctx *);
|
||||
void screen_write_fill_start_of_line(struct screen_write_ctx *);
|
||||
void screen_write_fill_line(struct screen_write_ctx *);
|
||||
void screen_write_set_mode(struct screen_write_ctx *, int);
|
||||
void screen_write_clear_mode(struct screen_write_ctx *, int);
|
||||
void screen_write_copy_area(struct screen_write_ctx *,
|
||||
struct screen *, u_int, u_int, u_int, u_int);
|
||||
void printflike3 screen_write_puts(
|
||||
struct screen_write_ctx *, struct grid_cell *, const char *, ...);
|
||||
void screen_write_putc(
|
||||
struct screen_write_ctx *, struct grid_cell *, u_char);
|
||||
void screen_write_copy(struct screen_write_ctx *,
|
||||
struct screen *, u_int, u_int, u_int, u_int);
|
||||
void screen_write_cursorup(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursordown(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursorright(struct screen_write_ctx *, u_int);
|
||||
void screen_write_cursorleft(struct screen_write_ctx *, u_int);
|
||||
void screen_write_insertcharacter(struct screen_write_ctx *, u_int);
|
||||
void screen_write_deletecharacter(struct screen_write_ctx *, u_int);
|
||||
void screen_write_insertline(struct screen_write_ctx *, u_int);
|
||||
void screen_write_deleteline(struct screen_write_ctx *, u_int);
|
||||
void screen_write_clearline(struct screen_write_ctx *);
|
||||
void screen_write_clearendofline(struct screen_write_ctx *);
|
||||
void screen_write_clearstartofline(struct screen_write_ctx *);
|
||||
void screen_write_cursormove(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_cursormode(struct screen_write_ctx *, int);
|
||||
void screen_write_reverseindex(struct screen_write_ctx *);
|
||||
void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_insertmode(struct screen_write_ctx *, int);
|
||||
void screen_write_mousemode(struct screen_write_ctx *, int);
|
||||
void screen_write_linefeed(struct screen_write_ctx *);
|
||||
void screen_write_carriagereturn(struct screen_write_ctx *);
|
||||
void screen_write_kcursormode(struct screen_write_ctx *, int);
|
||||
void screen_write_kkeypadmode(struct screen_write_ctx *, int);
|
||||
void screen_write_clearendofscreen(struct screen_write_ctx *);
|
||||
void screen_write_clearstartofscreen(struct screen_write_ctx *);
|
||||
void screen_write_clearscreen(struct screen_write_ctx *);
|
||||
void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *);
|
||||
|
||||
/* screen-redraw.c */
|
||||
void screen_redraw_start_window(struct screen_redraw_ctx *, struct window *);
|
||||
@ -1243,14 +1221,11 @@ void screen_redraw_start_session(
|
||||
void screen_redraw_start(struct screen_redraw_ctx *,
|
||||
struct screen *, void (*)(void *, int, ...), void *);
|
||||
void screen_redraw_stop(struct screen_redraw_ctx *);
|
||||
void screen_redraw_move_cursor(struct screen_redraw_ctx *, u_int, u_int);
|
||||
void screen_redraw_set_attributes(
|
||||
struct screen_redraw_ctx *, u_short, u_char, u_char);
|
||||
void printflike2 screen_redraw_write_string(
|
||||
struct screen_redraw_ctx *, const char *, ...);
|
||||
void printflike3 screen_redraw_puts(
|
||||
struct screen_redraw_ctx *, struct grid_cell *, const char *, ...);
|
||||
void screen_redraw_putc(
|
||||
struct screen_redraw_ctx *, struct grid_cell *, u_char);
|
||||
void screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int);
|
||||
void screen_redraw_area(
|
||||
struct screen_redraw_ctx *, u_int, u_int, u_int, u_int);
|
||||
void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int);
|
||||
void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int);
|
||||
|
||||
@ -1258,21 +1233,13 @@ void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int);
|
||||
void screen_init(struct screen *, u_int, u_int, u_int);
|
||||
void screen_reinit(struct screen *);
|
||||
void screen_free(struct screen *);
|
||||
void screen_set_title(struct screen *, const char *);
|
||||
void screen_resize(struct screen *, u_int, u_int);
|
||||
void screen_expand_line(struct screen *, u_int, u_int);
|
||||
void screen_reduce_line(struct screen *, u_int, u_int);
|
||||
void screen_get_cell(struct screen *,
|
||||
u_int, u_int, u_char *, u_short *, u_char *, u_char *);
|
||||
void screen_set_cell(
|
||||
struct screen *, u_int, u_int, u_char, u_short, u_char, u_char);
|
||||
void screen_make_lines(struct screen *, u_int, u_int);
|
||||
void screen_free_lines(struct screen *, u_int, u_int);
|
||||
void screen_move_lines(struct screen *, u_int, u_int, u_int);
|
||||
void screen_fill_area(struct screen *,
|
||||
u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char);
|
||||
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int);
|
||||
void screen_clear_selection(struct screen *);
|
||||
int screen_check_selection(struct screen *, u_int, u_int);
|
||||
void screen_display_copy_area(struct screen *, struct screen *,
|
||||
u_int, u_int, u_int, u_int, u_int, u_int);
|
||||
|
||||
/* window.c */
|
||||
extern struct windows windows;
|
||||
@ -1328,13 +1295,9 @@ int session_select(struct session *, int);
|
||||
int session_last(struct session *);
|
||||
|
||||
/* utf8.c */
|
||||
void utf8_pack(int, u_char *, u_short *);
|
||||
int utf8_unpack(u_char, u_short);
|
||||
void utf8_init(struct utf8_table *, int);
|
||||
void utf8_free(struct utf8_table *);
|
||||
struct utf8_data *utf8_lookup(struct utf8_table *, int);
|
||||
int utf8_search(struct utf8_table *, struct utf8_data *);
|
||||
int utf8_add(struct utf8_table *, struct utf8_data *);
|
||||
u_int utf8_combine(const u_char [4]);
|
||||
void utf8_split(u_int, u_char [4]);
|
||||
int utf8_width(u_int);
|
||||
|
||||
/* buffer.c */
|
||||
struct buffer *buffer_create(size_t);
|
||||
|
804
tty.c
804
tty.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tty.c,v 1.42 2008-09-23 17:54:35 nicm Exp $ */
|
||||
/* $Id: tty.c,v 1.43 2008-09-25 20:08:56 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -39,10 +39,64 @@ void tty_raw(struct tty *, const char *);
|
||||
void tty_puts(struct tty *, const char *);
|
||||
void tty_putc(struct tty *, char);
|
||||
|
||||
void tty_attributes(struct tty *, u_short, u_char, u_char);
|
||||
u_char tty_attributes_fg(struct tty *, u_char);
|
||||
u_char tty_attributes_bg(struct tty *, u_char);
|
||||
char tty_translate(char);
|
||||
void tty_reset(struct tty *);
|
||||
void tty_attributes(struct tty *, const struct grid_cell *);
|
||||
void tty_attributes_fg(struct tty *, const struct grid_cell *);
|
||||
void tty_attributes_bg(struct tty *, const struct grid_cell *);
|
||||
|
||||
void tty_cmd_cursorup(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cursordown(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cursorright(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cursorleft(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_insertcharacter(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_deletecharacter(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_insertline(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_deleteline(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearline(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearendofline(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearstartofline(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cursormove(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cursormode(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_reverseindex(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_scrollregion(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_insertmode(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_mousemode(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_linefeed(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_carriagereturn(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_bell(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearendofscreen(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearstartofscreen(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_clearscreen(struct tty *, struct screen *, va_list);
|
||||
void tty_cmd_cell(struct tty *, struct screen *, va_list);
|
||||
|
||||
void (*tty_cmds[])(struct tty *, struct screen *, va_list) = {
|
||||
tty_cmd_cursorup,
|
||||
tty_cmd_cursordown,
|
||||
tty_cmd_cursorright,
|
||||
tty_cmd_cursorleft,
|
||||
tty_cmd_insertcharacter,
|
||||
tty_cmd_deletecharacter,
|
||||
tty_cmd_insertline,
|
||||
tty_cmd_deleteline,
|
||||
tty_cmd_clearline,
|
||||
tty_cmd_clearendofline,
|
||||
tty_cmd_clearstartofline,
|
||||
tty_cmd_cursormove,
|
||||
tty_cmd_cursormode,
|
||||
tty_cmd_reverseindex,
|
||||
tty_cmd_scrollregion,
|
||||
tty_cmd_insertmode,
|
||||
tty_cmd_mousemode,
|
||||
tty_cmd_linefeed,
|
||||
tty_cmd_carriagereturn,
|
||||
tty_cmd_bell,
|
||||
NULL,
|
||||
NULL,
|
||||
tty_cmd_clearendofscreen,
|
||||
tty_cmd_clearstartofscreen,
|
||||
tty_cmd_clearscreen,
|
||||
tty_cmd_cell,
|
||||
};
|
||||
|
||||
TAILQ_HEAD(, tty_term) tty_terms = TAILQ_HEAD_INITIALIZER(tty_terms);
|
||||
|
||||
@ -55,6 +109,7 @@ tty_init(struct tty *tty, char *path, char *term)
|
||||
else
|
||||
tty->termname = xstrdup(term);
|
||||
tty->flags = 0;
|
||||
tty->term_flags = 0;
|
||||
}
|
||||
|
||||
int
|
||||
@ -74,9 +129,9 @@ tty_open(struct tty *tty, char **cause)
|
||||
if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||
fatal("fcntl");
|
||||
|
||||
if (debug_level > 3) {
|
||||
if (debug_level > 3)
|
||||
tty->log_fd = open("tmux.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
} else
|
||||
else
|
||||
tty->log_fd = -1;
|
||||
|
||||
if ((tty->term = tty_find_term(tty->termname, tty->fd, cause)) == NULL)
|
||||
@ -86,10 +141,7 @@ tty_open(struct tty *tty, char **cause)
|
||||
tty->out = buffer_create(BUFSIZ);
|
||||
|
||||
tty->flags &= TTY_UTF8;
|
||||
|
||||
tty->attr = 0;
|
||||
tty->fg = 8;
|
||||
tty->bg = 8;
|
||||
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
|
||||
|
||||
if (tcgetattr(tty->fd, &tty->tio) != 0)
|
||||
fatal("tcgetattr failed");
|
||||
@ -163,15 +215,17 @@ tty_close(struct tty *tty)
|
||||
fatal("tcsetattr failed");
|
||||
|
||||
tty_raw(tty, tparm(change_scroll_region, 0, ws.ws_row - 1));
|
||||
if (exit_alt_charset_mode != NULL)
|
||||
tty_puts(tty, exit_alt_charset_mode);
|
||||
if (exit_attribute_mode != NULL)
|
||||
tty_raw(tty, exit_attribute_mode);
|
||||
tty_raw(tty, clear_screen);
|
||||
if (keypad_local != NULL)
|
||||
tty_raw(tty, keypad_local);
|
||||
if (exit_ca_mode != NULL)
|
||||
tty_raw(tty, exit_ca_mode);
|
||||
tty_raw(tty, clear_screen);
|
||||
if (cursor_normal != NULL)
|
||||
tty_raw(tty, cursor_normal);
|
||||
if (exit_attribute_mode != NULL)
|
||||
tty_raw(tty, exit_attribute_mode);
|
||||
}
|
||||
|
||||
tty_free_term(tty->term);
|
||||
@ -405,7 +459,7 @@ tty_puts(struct tty *tty, const char *s)
|
||||
void
|
||||
tty_putc(struct tty *tty, char ch)
|
||||
{
|
||||
if (tty->attr & ATTR_CHARSET)
|
||||
if (tty->cell.attr & GRID_ATTR_CHARSET)
|
||||
ch = tty_get_acs(tty, ch);
|
||||
buffer_write8(tty->out, ch);
|
||||
|
||||
@ -429,10 +483,6 @@ tty_set_title(struct tty *tty, const char *title)
|
||||
void
|
||||
tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
|
||||
{
|
||||
struct utf8_data *udat;
|
||||
char ch;
|
||||
u_int i, ua, ub, uc;
|
||||
|
||||
if (tty->flags & TTY_FREEZE)
|
||||
return;
|
||||
|
||||
@ -440,273 +490,493 @@ tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
|
||||
return;
|
||||
set_curterm(tty->term->term);
|
||||
|
||||
switch (cmd) {
|
||||
case TTY_CHARACTER:
|
||||
ch = va_arg(ap, int);
|
||||
|
||||
if (tty->attr & ATTR_PAD)
|
||||
break;
|
||||
if (tty_cmds[cmd] != NULL)
|
||||
tty_cmds[cmd](tty, s, ap);
|
||||
}
|
||||
|
||||
if ((tty->attr & ATTR_UTF8) && (tty->flags & TTY_UTF8)) {
|
||||
udat = utf8_lookup(
|
||||
&s->utf8_table, utf8_unpack(ch, tty->attr));
|
||||
if (udat == NULL)
|
||||
ch = '_';
|
||||
else {
|
||||
if (udat->data[0] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, udat->data[0]);
|
||||
if (udat->data[1] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, udat->data[1]);
|
||||
if (udat->data[2] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, udat->data[2]);
|
||||
if (udat->data[3] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, udat->data[3]);
|
||||
break;
|
||||
}
|
||||
} else if (tty->attr & ATTR_UTF8)
|
||||
ch = '_';
|
||||
void
|
||||
tty_cmd_cursorup(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
switch (ch) {
|
||||
case '\n': /* LF */
|
||||
tty_putc(tty, '\n');
|
||||
break;
|
||||
case '\r': /* CR */
|
||||
tty_puts(tty, carriage_return);
|
||||
break;
|
||||
case '\007': /* BEL */
|
||||
if (bell != NULL)
|
||||
tty_puts(tty, bell);
|
||||
break;
|
||||
case '\010': /* BS */
|
||||
tty_puts(tty, cursor_left);
|
||||
break;
|
||||
default:
|
||||
tty_putc(tty, ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORUP:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_up_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_up_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_up);
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORDOWN:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_down_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_down_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_down);
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORRIGHT:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_right_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_right_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_right);
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORLEFT:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_left_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_left_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_left);
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORMOVE:
|
||||
ua = va_arg(ap, u_int);
|
||||
ub = va_arg(ap, u_int);
|
||||
tty_puts(tty, tparm(cursor_address, ua, ub));
|
||||
break;
|
||||
case TTY_CLEARENDOFLINE:
|
||||
if (clr_eol != NULL)
|
||||
tty_puts(tty, clr_eol);
|
||||
else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
for (i = s->cx; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
break;
|
||||
case TTY_CLEARSTARTOFLINE:
|
||||
if (clr_bol != NULL)
|
||||
tty_puts(tty, clr_bol);
|
||||
else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
for (i = 0; i < s->cx + 1; i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
break;
|
||||
case TTY_CLEARLINE:
|
||||
if (clr_eol != NULL) {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
tty_puts(tty, clr_eol);
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
} else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
for (i = 0; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
break;
|
||||
case TTY_INSERTLINE:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_insert_line != NULL)
|
||||
tty_puts(tty, tparm(parm_insert_line, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, insert_line);
|
||||
}
|
||||
break;
|
||||
case TTY_DELETELINE:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_delete_line != NULL)
|
||||
tty_puts(tty, tparm(parm_delete_line, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, delete_line);
|
||||
}
|
||||
break;
|
||||
case TTY_INSERTCHARACTER:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_ich != NULL)
|
||||
tty_puts(tty, tparm(parm_ich, ua));
|
||||
else if (insert_character != NULL) {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, insert_character);
|
||||
} else if (enter_insert_mode != NULL) {
|
||||
tty_puts(tty, enter_insert_mode);
|
||||
while (ua-- > 0)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, exit_insert_mode);
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
break;
|
||||
case TTY_DELETECHARACTER:
|
||||
ua = va_arg(ap, u_int);
|
||||
if (parm_dch != NULL)
|
||||
tty_puts(tty, tparm(parm_dch, ua));
|
||||
else if (delete_character != NULL) {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, delete_character);
|
||||
} else {
|
||||
while (ua-- > 0)
|
||||
tty_putc(tty, '\010');
|
||||
}
|
||||
break;
|
||||
case TTY_CURSORON:
|
||||
if (!(tty->flags & TTY_NOCURSOR) && cursor_normal != NULL)
|
||||
tty_puts(tty, cursor_normal);
|
||||
break;
|
||||
case TTY_CURSOROFF:
|
||||
if (cursor_invisible != NULL)
|
||||
tty_puts(tty, cursor_invisible);
|
||||
break;
|
||||
case TTY_REVERSEINDEX:
|
||||
tty_puts(tty, scroll_reverse);
|
||||
break;
|
||||
case TTY_SCROLLREGION:
|
||||
ua = va_arg(ap, u_int);
|
||||
ub = va_arg(ap, u_int);
|
||||
tty_puts(tty, tparm(change_scroll_region, ua, ub));
|
||||
break;
|
||||
#if 0
|
||||
case TTY_INSERTON:
|
||||
if (enter_insert_mode != NULL)
|
||||
tty_puts(tty, enter_insert_mode);
|
||||
break;
|
||||
case TTY_INSERTOFF:
|
||||
if (exit_insert_mode != NULL)
|
||||
tty_puts(tty, exit_insert_mode);
|
||||
break;
|
||||
#endif
|
||||
case TTY_MOUSEOFF:
|
||||
if (key_mouse != NULL)
|
||||
tty_puts(tty, "\033[?1000l");
|
||||
break;
|
||||
case TTY_MOUSEON:
|
||||
if (key_mouse != NULL)
|
||||
tty_puts(tty, "\033[?1000h");
|
||||
break;
|
||||
case TTY_ATTRIBUTES:
|
||||
ua = va_arg(ap, u_int);
|
||||
ub = va_arg(ap, u_int);
|
||||
uc = va_arg(ap, u_int);
|
||||
tty_attributes(tty, ua, ub, uc);
|
||||
break;
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
if (parm_up_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_up_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_up);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_attributes(struct tty *tty, u_short attr, u_char fg, u_char bg)
|
||||
tty_cmd_cursordown(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
if (attr == tty->attr && fg == tty->fg && bg == tty->bg)
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
if (parm_down_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_down_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_down);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_cursorright(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
if (parm_right_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_right_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_right);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_cursorleft(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
if (parm_left_cursor != NULL)
|
||||
tty_puts(tty, tparm(parm_left_cursor, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, cursor_left);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_insertcharacter(struct tty *tty, struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (parm_ich != NULL)
|
||||
tty_puts(tty, tparm(parm_ich, ua));
|
||||
else if (insert_character != NULL) {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, insert_character);
|
||||
} else if (enter_insert_mode != NULL) {
|
||||
tty_puts(tty, enter_insert_mode);
|
||||
while (ua-- > 0)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, exit_insert_mode);
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_deletecharacter(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (parm_dch != NULL)
|
||||
tty_puts(tty, tparm(parm_dch, ua));
|
||||
else if (delete_character != NULL) {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, delete_character);
|
||||
} else {
|
||||
while (ua-- > 0)
|
||||
tty_putc(tty, '\010');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_insertline(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (parm_insert_line != NULL)
|
||||
tty_puts(tty, tparm(parm_insert_line, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, insert_line);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_deleteline(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (parm_delete_line != NULL)
|
||||
tty_puts(tty, tparm(parm_delete_line, ua));
|
||||
else {
|
||||
while (ua-- > 0)
|
||||
tty_puts(tty, delete_line);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearline(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (clr_eol != NULL) {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
tty_puts(tty, clr_eol);
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
} else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
for (i = 0; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearendofline(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (clr_eol != NULL)
|
||||
tty_puts(tty, clr_eol);
|
||||
else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
for (i = s->cx; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearstartofline(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (clr_bol != NULL)
|
||||
tty_puts(tty, clr_bol);
|
||||
else {
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
for (i = 0; i < s->cx + 1; i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_cursormove(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua, ub;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
ub = va_arg(ap, u_int);
|
||||
|
||||
tty_puts(tty, tparm(cursor_address, ub, ua));
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_cursormode(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
if (cursor_normal == NULL || cursor_invisible == NULL)
|
||||
return;
|
||||
|
||||
/* If any bits are being cleared, reset everything. */
|
||||
if (tty->attr & ~attr) {
|
||||
if ((tty->attr & ATTR_CHARSET) && exit_alt_charset_mode != NULL)
|
||||
tty_puts(tty, exit_alt_charset_mode);
|
||||
tty_puts(tty, exit_attribute_mode);
|
||||
tty->fg = 8;
|
||||
tty->bg = 8;
|
||||
tty->attr = 0;
|
||||
}
|
||||
ua = va_arg(ap, int);
|
||||
|
||||
if (ua && !(tty->flags & TTY_NOCURSOR))
|
||||
tty_puts(tty, cursor_normal);
|
||||
else
|
||||
tty_puts(tty, cursor_invisible);
|
||||
}
|
||||
|
||||
/* Filter out attribute bits already set. */
|
||||
attr &= ~tty->attr;
|
||||
tty->attr |= attr;
|
||||
void
|
||||
tty_cmd_reverseindex(
|
||||
struct tty *tty, unused struct screen *s, unused va_list ap)
|
||||
{
|
||||
tty_reset(tty);
|
||||
tty_puts(tty, scroll_reverse);
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_scrollregion(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua, ub;
|
||||
|
||||
ua = va_arg(ap, u_int);
|
||||
ub = va_arg(ap, u_int);
|
||||
|
||||
tty_puts(tty, tparm(change_scroll_region, ua, ub));
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_insertmode(unused struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
if (enter_insert_mode == NULL || exit_insert_mode == NULL)
|
||||
return;
|
||||
|
||||
ua = va_arg(ap, int);
|
||||
|
||||
#if 0
|
||||
if (ua)
|
||||
tty_puts(tty, enter_insert_mode);
|
||||
else
|
||||
tty_puts(tty, exit_insert_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_mousemode(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
u_int ua;
|
||||
|
||||
if (key_mouse == NULL)
|
||||
return;
|
||||
|
||||
ua = va_arg(ap, int);
|
||||
|
||||
if (ua)
|
||||
tty_puts(tty, "\033[?1000h");
|
||||
else
|
||||
tty_puts(tty, "\033[?1000l");
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_linefeed(struct tty *tty, unused struct screen *s, unused va_list ap)
|
||||
{
|
||||
tty_reset(tty);
|
||||
|
||||
tty_putc(tty, '\n');
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_carriagereturn(
|
||||
struct tty *tty, unused struct screen *s, unused va_list ap)
|
||||
{
|
||||
tty_reset(tty);
|
||||
|
||||
if (carriage_return)
|
||||
tty_puts(tty, carriage_return);
|
||||
else
|
||||
tty_putc(tty, '\r');
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_bell(struct tty *tty, unused struct screen *s, unused va_list ap)
|
||||
{
|
||||
if (bell)
|
||||
tty_puts(tty, bell);
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearendofscreen(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (clr_eol != NULL) {
|
||||
for (i = s->cy; i < screen_size_y(s); i++) {
|
||||
tty_puts(tty, clr_eol);
|
||||
tty_puts(tty, cursor_down);
|
||||
}
|
||||
} else {
|
||||
for (i = s->cx; i < screen_size_y(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
for (j = s->cy; j < screen_size_y(s); j++) {
|
||||
for (i = 0; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
}
|
||||
}
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearstartofscreen(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
tty_puts(tty, tparm(cursor_address, 0, 0));
|
||||
if (clr_eol) {
|
||||
for (i = 0; i < s->cy; i++)
|
||||
tty_puts(tty, clr_eol);
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, 0));
|
||||
} else {
|
||||
for (j = 0; j < s->cy; j++) {
|
||||
for (i = 0; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
}
|
||||
}
|
||||
for (i = 0; i < s->cx; i++)
|
||||
tty_putc(tty, ' ');
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_clearscreen(struct tty *tty, struct screen *s, unused va_list ap)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
tty_reset(tty);
|
||||
|
||||
if (clr_eol) {
|
||||
tty_puts(tty, tparm(cursor_address, 0, 0));
|
||||
for (i = 0; i < screen_size_y(s); i++) {
|
||||
tty_puts(tty, clr_eol);
|
||||
tty_puts(tty, cursor_down);
|
||||
}
|
||||
} else {
|
||||
tty_puts(tty, tparm(cursor_address, 0, 0));
|
||||
for (j = 0; j < screen_size_y(s); j++) {
|
||||
for (i = 0; i < screen_size_x(s); i++)
|
||||
tty_putc(tty, ' ');
|
||||
}
|
||||
}
|
||||
tty_puts(tty, tparm(cursor_address, s->cy, s->cx));
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_cell(struct tty *tty, unused struct screen *s, va_list ap)
|
||||
{
|
||||
struct grid_cell *gc;
|
||||
u_int i, width;
|
||||
u_char out[4];
|
||||
|
||||
gc = va_arg(ap, struct grid_cell *);
|
||||
|
||||
/* If this is a padding character, do nothing. */
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
return;
|
||||
|
||||
/* Handle special characters. Should never come into this function.*/
|
||||
if (gc->data < 0x20 || gc->data == 0x7f)
|
||||
return;
|
||||
|
||||
/* Set the attributes. */
|
||||
if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL)
|
||||
tty_attributes(tty, gc);
|
||||
|
||||
/* If not UTF8 multibyte, write directly. */
|
||||
if (gc->data < 0xff) {
|
||||
tty_putc(tty, gc->data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the terminal doesn't support UTF8, write _s. */
|
||||
if (!(tty->flags & TTY_UTF8)) {
|
||||
width = utf8_width(gc->data);
|
||||
while (width-- > 0)
|
||||
tty_putc(tty, '_');
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unpack UTF-8 and write it. */
|
||||
utf8_split(gc->data, out);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (out[i] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_reset(struct tty *tty)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
|
||||
tc->data = grid_default_cell.data;
|
||||
if (memcmp(tc, &grid_default_cell, sizeof *tc) == 0)
|
||||
return;
|
||||
|
||||
if (exit_alt_charset_mode != NULL && tc->attr & GRID_ATTR_CHARSET)
|
||||
tty_puts(tty, exit_alt_charset_mode);
|
||||
tty_puts(tty, exit_attribute_mode);
|
||||
memcpy(tc, &grid_default_cell, sizeof *tc);
|
||||
}
|
||||
|
||||
void
|
||||
tty_attributes(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
u_char changed;
|
||||
|
||||
/* If any bits are being cleared, reset everything. */
|
||||
if (tc->attr & ~gc->attr)
|
||||
tty_reset(tty);
|
||||
|
||||
/* Filter out attribute bits already set. */
|
||||
changed = gc->attr & ~tc->attr;
|
||||
tc->attr = gc->attr;
|
||||
|
||||
/* Set the attributes. */
|
||||
if ((changed & GRID_ATTR_BRIGHT) && enter_bold_mode != NULL)
|
||||
tty_puts(tty, enter_bold_mode);
|
||||
if ((attr & ATTR_DIM) && enter_dim_mode != NULL)
|
||||
if ((changed & GRID_ATTR_DIM) && enter_dim_mode != NULL)
|
||||
tty_puts(tty, enter_dim_mode);
|
||||
if ((attr & ATTR_ITALICS) && enter_standout_mode != NULL)
|
||||
if ((changed & GRID_ATTR_ITALICS) && enter_standout_mode != NULL)
|
||||
tty_puts(tty, enter_standout_mode);
|
||||
if ((attr & ATTR_UNDERSCORE) && enter_underline_mode != NULL)
|
||||
if ((changed & GRID_ATTR_UNDERSCORE) && enter_underline_mode != NULL)
|
||||
tty_puts(tty, enter_underline_mode);
|
||||
if ((attr & ATTR_BLINK) && enter_blink_mode != NULL)
|
||||
if ((changed & GRID_ATTR_BLINK) && enter_blink_mode != NULL)
|
||||
tty_puts(tty, enter_blink_mode);
|
||||
if ((attr & ATTR_REVERSE) && enter_reverse_mode != NULL)
|
||||
if ((changed & GRID_ATTR_REVERSE) && enter_reverse_mode != NULL)
|
||||
tty_puts(tty, enter_reverse_mode);
|
||||
if ((attr & ATTR_HIDDEN) && enter_secure_mode != NULL)
|
||||
if ((changed & GRID_ATTR_HIDDEN) && enter_secure_mode != NULL)
|
||||
tty_puts(tty, enter_secure_mode);
|
||||
if ((attr & ATTR_CHARSET) && enter_alt_charset_mode != NULL)
|
||||
if ((changed & GRID_ATTR_CHARSET) && enter_alt_charset_mode != NULL)
|
||||
tty_puts(tty, enter_alt_charset_mode);
|
||||
|
||||
/* Set foreground colour. */
|
||||
if (fg != tty->fg || attr & ATTR_FG256)
|
||||
tty->fg = tty_attributes_fg(tty, fg);
|
||||
|
||||
if (gc->fg != tc->fg ||
|
||||
(gc->flags & GRID_FLAG_FG256) != (tc->flags & GRID_FLAG_FG256)) {
|
||||
tty_attributes_fg(tty, gc);
|
||||
tc->fg = gc->fg;
|
||||
}
|
||||
|
||||
/* Set background colour. */
|
||||
if (bg != tty->bg || attr & ATTR_BG256)
|
||||
tty->bg = tty_attributes_bg(tty, bg);
|
||||
if (gc->bg != tc->bg ||
|
||||
(gc->flags & GRID_FLAG_BG256) != (tc->flags & GRID_FLAG_BG256)) {
|
||||
tty_attributes_bg(tty, gc);
|
||||
tc->bg = gc->bg;
|
||||
}
|
||||
}
|
||||
|
||||
u_char
|
||||
tty_attributes_fg(struct tty *tty, u_char fg)
|
||||
void
|
||||
tty_attributes_fg(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
char s[32];
|
||||
u_char fg = gc->fg;
|
||||
|
||||
if (tty->attr & ATTR_FG256) {
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
if (gc->flags & GRID_FLAG_FG256) {
|
||||
if ((tty->term->flags & TERM_256COLOURS) ||
|
||||
(tty->term_flags & TERM_256COLOURS)) {
|
||||
xsnprintf(s, sizeof s, "\033[38;5;%hhum", fg);
|
||||
tty_puts(tty, s);
|
||||
return (fg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fg > 15)
|
||||
@ -715,25 +985,28 @@ tty_attributes_fg(struct tty *tty, u_char fg)
|
||||
fg -= 8;
|
||||
}
|
||||
|
||||
if (fg == 8 && !(tty->term->flags & TERM_HASDEFAULTS))
|
||||
if (fg == 8 &&
|
||||
!(tty->term->flags & TERM_HASDEFAULTS) &&
|
||||
!(tty->term_flags & TERM_HASDEFAULTS))
|
||||
fg = 7;
|
||||
if (fg == 8)
|
||||
tty_puts(tty, "\033[39m");
|
||||
else if (set_a_foreground != NULL)
|
||||
tty_puts(tty, tparm(set_a_foreground, fg));
|
||||
return (fg);
|
||||
}
|
||||
|
||||
u_char
|
||||
tty_attributes_bg(struct tty *tty, u_char bg)
|
||||
void
|
||||
tty_attributes_bg(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
char s[32];
|
||||
u_char bg = gc->bg;
|
||||
|
||||
if (tty->attr & ATTR_BG256) {
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
if (gc->flags & GRID_FLAG_BG256) {
|
||||
if ((tty->term->flags & TERM_256COLOURS) ||
|
||||
(tty->term_flags & TERM_256COLOURS)) {
|
||||
xsnprintf(s, sizeof s, "\033[48;5;%hhum", bg);
|
||||
tty_puts(tty, s);
|
||||
return (bg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bg > 15)
|
||||
@ -742,11 +1015,12 @@ tty_attributes_bg(struct tty *tty, u_char bg)
|
||||
bg -= 8;
|
||||
}
|
||||
|
||||
if (bg == 8 && !(tty->term->flags & TERM_HASDEFAULTS))
|
||||
if (bg == 8 &&
|
||||
!(tty->term->flags & TERM_HASDEFAULTS) &&
|
||||
!(tty->term_flags & TERM_HASDEFAULTS))
|
||||
bg = 0;
|
||||
if (bg == 8)
|
||||
tty_puts(tty, "\033[49m");
|
||||
else if (set_a_background != NULL)
|
||||
tty_puts(tty, tparm(set_a_background, bg));
|
||||
return (bg);
|
||||
}
|
||||
|
139
utf8.c
139
utf8.c
@ -1,4 +1,4 @@
|
||||
/* $Id: utf8.c,v 1.1 2008-09-09 22:16:37 nicm Exp $ */
|
||||
/* $Id: utf8.c,v 1.2 2008-09-25 20:08:56 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -22,93 +22,66 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* UTF8 data structures. Just crappy array + linear search for now.
|
||||
*/
|
||||
|
||||
/* Pack UTF8 index into attr, data. */
|
||||
void
|
||||
utf8_pack(int idx, u_char *data, u_short *attr)
|
||||
u_int
|
||||
utf8_combine(const u_char data[4])
|
||||
{
|
||||
*data = idx & 0xff;
|
||||
u_int uv;
|
||||
|
||||
*attr &= ~(ATTR_UTF8b8|ATTR_UTF8b9);
|
||||
if (idx & 0x100)
|
||||
*attr |= ATTR_UTF8b8;
|
||||
if (idx & 0x200)
|
||||
*attr |= ATTR_UTF8b9;
|
||||
if (idx & 0x400)
|
||||
*attr |= ATTR_UTF8b10;
|
||||
if (idx & 0x800)
|
||||
*attr |= ATTR_UTF8b11;
|
||||
}
|
||||
|
||||
/* Unpack UTF8 index from attr, data. */
|
||||
int
|
||||
utf8_unpack(u_char data, u_short attr)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = data;
|
||||
if (attr & ATTR_UTF8b8)
|
||||
idx |= 0x100;
|
||||
if (attr & ATTR_UTF8b9)
|
||||
idx |= 0x200;
|
||||
if (attr & ATTR_UTF8b10)
|
||||
idx |= 0x400;
|
||||
if (attr & ATTR_UTF8b11)
|
||||
idx |= 0x800;
|
||||
|
||||
return (idx);
|
||||
}
|
||||
|
||||
void
|
||||
utf8_init(struct utf8_table *utab, int limit)
|
||||
{
|
||||
utab->limit = limit;
|
||||
ARRAY_INIT(&utab->array);
|
||||
}
|
||||
|
||||
void
|
||||
utf8_free(struct utf8_table *utab)
|
||||
{
|
||||
ARRAY_FREE(&utab->array);
|
||||
}
|
||||
|
||||
struct utf8_data *
|
||||
utf8_lookup(struct utf8_table *utab, int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= (int) ARRAY_LENGTH(&utab->array))
|
||||
return (NULL);
|
||||
return (&ARRAY_ITEM(&utab->array, idx));
|
||||
}
|
||||
|
||||
int
|
||||
utf8_search(struct utf8_table *utab, struct utf8_data *udat)
|
||||
{
|
||||
u_int idx;
|
||||
|
||||
for (idx = 0; idx < ARRAY_LENGTH(&utab->array); idx++) {
|
||||
if (memcmp(udat->data,
|
||||
ARRAY_ITEM(&utab->array, idx).data, sizeof udat->data) == 0)
|
||||
return (idx);
|
||||
if (data[1] == 0xff)
|
||||
uv = data[0];
|
||||
else if (data[2] == 0xff) {
|
||||
uv = data[1] & 0x3f;
|
||||
uv |= (data[0] & 0x1f) << 6;
|
||||
} else if (data[3] == 0xff) {
|
||||
uv = data[2] & 0x3f;
|
||||
uv |= (data[1] & 0x3f) << 6;
|
||||
uv |= (data[0] & 0x0f) << 12;
|
||||
} else {
|
||||
uv = data[3] & 0x3f;
|
||||
uv |= (data[2] & 0x3f) << 6;
|
||||
uv |= (data[1] & 0x3f) << 12;
|
||||
uv |= (data[0] & 0x3f) << 18;
|
||||
}
|
||||
return (uv);
|
||||
}
|
||||
|
||||
void
|
||||
utf8_split(u_int uv, u_char data[4])
|
||||
{
|
||||
memset(data, 0xff, sizeof data);
|
||||
|
||||
if (uv <= 0x7f)
|
||||
data[0] = uv;
|
||||
else if (uv > 0x7f && uv <= 0x7ff) {
|
||||
data[0] = (uv >> 6) | 0xc0;
|
||||
data[1] = (uv & 0x3f) | 0x80;
|
||||
} else if (uv > 0x7ff && uv <= 0xffff) {
|
||||
data[0] = (uv >> 12) | 0xe0;
|
||||
data[1] = ((uv >> 6) & 0x3f) | 0x80;
|
||||
data[2] = (uv & 0x3f) | 0x80;
|
||||
} else if (uv > 0xffff && uv <= 0x10ffff) {
|
||||
data[0] = (uv >> 18) | 0xf0;
|
||||
data[1] = ((uv >> 12) & 0x3f) | 0x80;
|
||||
data[2] = ((uv >> 6) & 0x3f) | 0x80;
|
||||
data[3] = (uv & 0x3f) | 0x80;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
utf8_add(struct utf8_table *utab, struct utf8_data *udat)
|
||||
utf8_width(u_int uv)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (ARRAY_LENGTH(&utab->array) == utab->limit)
|
||||
return (-1);
|
||||
|
||||
if ((idx = utf8_search(utab, udat)) != -1)
|
||||
return (idx);
|
||||
|
||||
ARRAY_EXPAND(&utab->array, 1);
|
||||
memcpy(
|
||||
&ARRAY_LAST(&utab->array), udat, sizeof ARRAY_LAST(&utab->array));
|
||||
return (ARRAY_LENGTH(&utab->array) - 1);
|
||||
if ((uv >= 0x1100 && uv <= 0x115f) ||
|
||||
uv == 0x2329 ||
|
||||
uv == 0x232a ||
|
||||
(uv >= 0x2e80 && uv <= 0xa4cf && uv != 0x303f) ||
|
||||
(uv >= 0xac00 && uv <= 0xd7a3) ||
|
||||
(uv >= 0xf900 && uv <= 0xfaff) ||
|
||||
(uv >= 0xfe10 && uv <= 0xfe19) ||
|
||||
(uv >= 0xfe30 && uv <= 0xfe6f) ||
|
||||
(uv >= 0xff00 && uv <= 0xff60) ||
|
||||
(uv >= 0xffe0 && uv <= 0xffe6) ||
|
||||
(uv >= 0x20000 && uv <= 0x2fffd) ||
|
||||
(uv >= 0x30000 && uv <= 0x3fffd))
|
||||
return (2);
|
||||
return (1);
|
||||
}
|
||||
|
262
window-copy.c
262
window-copy.c
@ -1,4 +1,4 @@
|
||||
/* $Id: window-copy.c,v 1.30 2008-09-10 19:15:04 nicm Exp $ */
|
||||
/* $Id: window-copy.c,v 1.31 2008-09-25 20:08:57 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -44,6 +44,7 @@ int window_copy_update_selection(struct window *);
|
||||
void window_copy_copy_selection(struct window *, struct client *);
|
||||
void window_copy_copy_line(
|
||||
struct window *, char **, size_t *, u_int, u_int, u_int);
|
||||
int window_copy_is_space(struct window *, u_int, u_int);
|
||||
u_int window_copy_find_length(struct window *, u_int);
|
||||
void window_copy_cursor_start_of_line(struct window *);
|
||||
void window_copy_cursor_end_of_line(struct window *);
|
||||
@ -58,10 +59,6 @@ void window_copy_scroll_right(struct window *, u_int);
|
||||
void window_copy_scroll_up(struct window *, u_int);
|
||||
void window_copy_scroll_down(struct window *, u_int);
|
||||
|
||||
const char *space_characters = " -_@";
|
||||
#define window_copy_is_space(w, x, y) \
|
||||
(strchr(space_characters, (w)->base.grid_data[y][x]) != NULL)
|
||||
|
||||
const struct window_mode window_copy_mode = {
|
||||
window_copy_init,
|
||||
window_copy_free,
|
||||
@ -104,7 +101,7 @@ window_copy_init(struct window *w)
|
||||
screen_write_start(&ctx, s, NULL, NULL);
|
||||
for (i = 0; i < screen_size_y(s); i++)
|
||||
window_copy_write_line(w, &ctx, i);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
return (s);
|
||||
@ -124,10 +121,12 @@ window_copy_resize(struct window *w, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
screen_resize(s, sx, sy);
|
||||
screen_display_copy_area(&data->screen, &w->base,
|
||||
0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
|
||||
screen_write_start(&ctx, s, NULL, NULL);
|
||||
window_copy_write_lines(w, &ctx, 0, screen_size_y(s) - 1);
|
||||
screen_write_stop(&ctx);
|
||||
window_copy_update_selection(w);
|
||||
}
|
||||
|
||||
@ -156,8 +155,8 @@ window_copy_key(struct window *w, struct client *c, int key)
|
||||
window_copy_cursor_down(w);
|
||||
return;
|
||||
case MODEKEY_PPAGE:
|
||||
if (data->oy + screen_size_y(s) > w->base.hsize)
|
||||
data->oy = w->base.hsize;
|
||||
if (data->oy + screen_size_y(s) > screen_hsize(&w->base))
|
||||
data->oy = screen_hsize(&w->base);
|
||||
else
|
||||
data->oy += screen_size_y(s);
|
||||
window_copy_update_selection(w);
|
||||
@ -202,44 +201,38 @@ window_copy_key(struct window *w, struct client *c, int key)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_write_line(
|
||||
struct window *w, struct screen_write_ctx *ctx, u_int py)
|
||||
window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
|
||||
{
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct grid_cell gc;
|
||||
char hdr[32];
|
||||
size_t size;
|
||||
|
||||
if (py == 0) {
|
||||
screen_write_set_attributes(
|
||||
ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
|
||||
screen_write_move_cursor(ctx, 0, 0);
|
||||
size = screen_write_put_string_rjust(
|
||||
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
|
||||
screen_write_set_attributes(ctx, 0, 8, 8);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
size = xsnprintf(hdr, sizeof hdr,
|
||||
"[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base));
|
||||
gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
|
||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||
gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
|
||||
} else
|
||||
size = 0;
|
||||
screen_write_move_cursor(ctx, 0, py);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
|
||||
|
||||
screen_write_cursormove(ctx, 0, py);
|
||||
screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) -
|
||||
data->oy) + py, screen_size_x(s) - size, 1);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_write_lines(
|
||||
struct window *w, struct screen_write_ctx *ctx, u_int py, u_int ny)
|
||||
{
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
u_int yy;
|
||||
|
||||
if (py == 0) {
|
||||
window_copy_write_line(w, ctx, 0);
|
||||
if (ny == 1)
|
||||
return;
|
||||
py++;
|
||||
ny--;
|
||||
}
|
||||
screen_write_move_cursor(ctx, 0, py);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, screen_size_x(s), ny, data->ox, data->oy);
|
||||
for (yy = py; yy < py + ny; yy++)
|
||||
window_copy_write_line(w, ctx, py);
|
||||
}
|
||||
|
||||
void
|
||||
@ -249,21 +242,19 @@ window_copy_write_column(
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
screen_write_move_cursor(ctx, px, 0);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
|
||||
screen_write_cursormove(ctx, px, 0);
|
||||
screen_write_copy(ctx, &w->base,
|
||||
data->ox, screen_hsize(&w->base) - data->oy, 1, screen_size_y(s));
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_write_columns(
|
||||
struct window *w, struct screen_write_ctx *ctx, u_int px, u_int nx)
|
||||
{
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
u_int xx;
|
||||
|
||||
screen_write_move_cursor(ctx, px, 0);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, nx, screen_size_y(s), data->ox, data->oy);
|
||||
for (xx = px; xx < px + nx; xx++)
|
||||
window_copy_write_column(w, ctx, px);
|
||||
}
|
||||
|
||||
void
|
||||
@ -276,7 +267,7 @@ window_copy_redraw_lines(struct window *w, u_int py, u_int ny)
|
||||
screen_write_start_window(&ctx, w);
|
||||
for (i = py; i < py + ny; i++)
|
||||
window_copy_write_line(w, &ctx, i);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
@ -295,7 +286,7 @@ window_copy_update_cursor(struct window *w)
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
@ -305,8 +296,8 @@ window_copy_start_selection(struct window *w)
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
data->selx = screen_x(&w->base, data->cx) + data->ox;
|
||||
data->sely = screen_y(&w->base, data->cy) - data->oy;
|
||||
data->selx = data->cx + data->ox;
|
||||
data->sely = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
|
||||
s->sel.flag = 1;
|
||||
window_copy_update_selection(w);
|
||||
@ -323,8 +314,8 @@ window_copy_update_selection(struct window *w)
|
||||
return (0);
|
||||
|
||||
/* Find top-left of screen. */
|
||||
tx = screen_x(&w->base, 0) + data->ox;
|
||||
ty = screen_y(&w->base, 0) - data->oy;
|
||||
tx = data->ox;
|
||||
ty = screen_hsize(&w->base) - data->oy;
|
||||
|
||||
/* Adjust the selection. */
|
||||
sx = data->selx;
|
||||
@ -333,28 +324,26 @@ window_copy_update_selection(struct window *w)
|
||||
/* Above it. */
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
} else if (sy > ty + screen_last_y(s)) {
|
||||
} else if (sy > ty + screen_size_y(s) - 1) {
|
||||
/* Below it. */
|
||||
sx = screen_last_x(s);
|
||||
sy = screen_last_y(s);
|
||||
sx = screen_size_x(s) - 1;
|
||||
sy = screen_size_y(s) - 1;
|
||||
} else if (sx < tx) {
|
||||
/* To the left. */
|
||||
sx = 0;
|
||||
} else if (sx > tx + screen_last_x(s)) {
|
||||
} else if (sx > tx + screen_size_x(s) - 1) {
|
||||
/* To the right. */
|
||||
sx = 0;
|
||||
sy++;
|
||||
if (sy > screen_last_y(s))
|
||||
sy = screen_last_y(s);
|
||||
if (sy > screen_size_y(s) - 1)
|
||||
sy = screen_size_y(s) - 1;
|
||||
} else {
|
||||
sx -= tx;
|
||||
sy -= ty;
|
||||
}
|
||||
sx = screen_x(s, sx);
|
||||
sy = screen_x(s, sy);
|
||||
sy = screen_hsize(s) + sy;
|
||||
|
||||
screen_set_selection(
|
||||
s, sx, sy, screen_x(s, data->cx), screen_y(s, data->cy));
|
||||
screen_set_selection(s, sx, sy, data->cx, screen_hsize(s) + data->cy);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -381,8 +370,8 @@ window_copy_copy_selection(struct window *w, struct client *c)
|
||||
*/
|
||||
|
||||
/* Find start and end. */
|
||||
xx = screen_x(&w->base, data->cx) + data->ox;
|
||||
yy = screen_y(&w->base, data->cy) - data->oy;
|
||||
xx = data->cx + data->ox;
|
||||
yy = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
if (xx < data->selx || (yy == data->sely && xx < data->selx)) {
|
||||
sx = xx; sy = yy;
|
||||
ex = data->selx; ey = data->sely;
|
||||
@ -425,7 +414,8 @@ void
|
||||
window_copy_copy_line(
|
||||
struct window *w, char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
||||
{
|
||||
u_char i, xx;
|
||||
const struct grid_cell *gc;
|
||||
u_char i, j, xx, data[4];
|
||||
|
||||
if (sx > ex)
|
||||
return;
|
||||
@ -438,9 +428,15 @@ window_copy_copy_line(
|
||||
|
||||
if (sx < ex) {
|
||||
for (i = sx; i < ex; i++) {
|
||||
*buf = xrealloc(*buf, 1, (*off) + 1);
|
||||
(*buf)[*off] = w->base.grid_data[sy][i];
|
||||
(*off)++;
|
||||
gc = grid_peek_cell(w->base.grid, i, sy);
|
||||
utf8_split(gc->data, data);
|
||||
|
||||
*buf = xrealloc(*buf, 1, (*off) + 4);
|
||||
for (j = 0; j < sizeof data; j++) {
|
||||
if (data[j] == 0xff)
|
||||
break;
|
||||
(*buf)[(*off)++] = data[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,14 +445,33 @@ window_copy_copy_line(
|
||||
(*off)++;
|
||||
}
|
||||
|
||||
int
|
||||
window_copy_is_space(struct window *w, u_int px, u_int py)
|
||||
{
|
||||
const struct grid_cell *gc;
|
||||
const char *spaces = " -_@";
|
||||
|
||||
gc = grid_peek_cell(w->base.grid, px, py);
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
return (0);
|
||||
if (gc->data == 0x00 || gc->data > 0xff)
|
||||
return (0);
|
||||
return (strchr(spaces, gc->data) != NULL);
|
||||
}
|
||||
|
||||
u_int
|
||||
window_copy_find_length(struct window *w, u_int py)
|
||||
{
|
||||
u_int px;
|
||||
const struct grid_cell *gc;
|
||||
u_int px;
|
||||
|
||||
px = w->base.grid_size[py];
|
||||
while (px > 0 && w->base.grid_data[py][px - 1] == ' ')
|
||||
px = w->base.grid->size[py];
|
||||
while (px > 0) {
|
||||
gc = grid_peek_cell(w->base.grid, px - 1, py);
|
||||
if (gc->data != 0x20)
|
||||
break;
|
||||
px--;
|
||||
}
|
||||
return (px);
|
||||
}
|
||||
|
||||
@ -482,32 +497,32 @@ window_copy_cursor_end_of_line(struct window *w)
|
||||
struct screen *s = &data->screen;
|
||||
u_int px, py;
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
px = window_copy_find_length(w, py);
|
||||
|
||||
/* On screen. */
|
||||
if (px > data->ox && px <= data->ox + screen_last_x(s))
|
||||
if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
|
||||
data->cx = px - data->ox;
|
||||
|
||||
/* Off right of screen. */
|
||||
if (px > data->ox + screen_last_x(s)) {
|
||||
if (px > data->ox + screen_size_x(s) - 1) {
|
||||
/* Move cursor to last and scroll screen. */
|
||||
window_copy_scroll_left(w,
|
||||
px - data->ox - screen_last_x(s));
|
||||
data->cx = screen_last_x(s);
|
||||
window_copy_scroll_left(
|
||||
w, px - data->ox - (screen_size_x(s) - 1));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
|
||||
/* Off left of screen. */
|
||||
if (px <= data->ox) {
|
||||
if (px < screen_last_x(s)) {
|
||||
if (px < screen_size_x(s) - 1) {
|
||||
/* Short enough to fit on screen. */
|
||||
window_copy_scroll_right(w, data->ox);
|
||||
data->cx = px;
|
||||
} else {
|
||||
/* Too long to fit on screen. */
|
||||
window_copy_scroll_right(
|
||||
w, data->ox - (px - screen_last_x(s)));
|
||||
data->cx = screen_last_x(s);
|
||||
w, data->ox - (px - (screen_size_x(s) - 1)));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -544,7 +559,7 @@ window_copy_cursor_right(struct window *w)
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
u_int px, py;
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
px = window_copy_find_length(w, py);
|
||||
|
||||
if (data->cx >= px) {
|
||||
@ -565,7 +580,7 @@ window_copy_cursor_up(struct window *w)
|
||||
struct window_copy_mode_data *data = w->modedata;
|
||||
u_int ox, oy, px, py;
|
||||
|
||||
oy = screen_y(&w->base, data->cy) - data->oy;
|
||||
oy = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(w, oy);
|
||||
|
||||
if (data->cy == 0)
|
||||
@ -578,7 +593,7 @@ window_copy_cursor_up(struct window *w)
|
||||
window_copy_update_cursor(w);
|
||||
}
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
px = window_copy_find_length(w, py);
|
||||
|
||||
if (data->cx + data->ox >= px || data->cx + data->ox >= ox)
|
||||
@ -592,10 +607,10 @@ window_copy_cursor_down(struct window *w)
|
||||
struct screen *s = &data->screen;
|
||||
u_int ox, oy, px, py;
|
||||
|
||||
oy = screen_y(&w->base, data->cy) - data->oy;
|
||||
oy = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(w, oy);
|
||||
|
||||
if (data->cy == screen_last_y(s))
|
||||
if (data->cy == screen_size_y(s) - 1)
|
||||
window_copy_scroll_up(w, 1);
|
||||
else {
|
||||
data->cy++;
|
||||
@ -605,7 +620,7 @@ window_copy_cursor_down(struct window *w)
|
||||
window_copy_update_cursor(w);
|
||||
}
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
px = window_copy_find_length(w, py);
|
||||
|
||||
if (data->cx + data->ox >= px || data->cx + data->ox >= ox)
|
||||
@ -620,7 +635,7 @@ window_copy_cursor_next_word(struct window *w)
|
||||
u_int px, py, xx, skip;
|
||||
|
||||
px = data->ox + data->cx;
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(w, py);
|
||||
|
||||
skip = 1;
|
||||
@ -638,7 +653,7 @@ window_copy_cursor_next_word(struct window *w)
|
||||
}
|
||||
|
||||
while (px >= xx) {
|
||||
if (data->cy == screen_last_y(s)) {
|
||||
if (data->cy == screen_size_y(s) - 1) {
|
||||
if (data->oy == 0)
|
||||
goto out;
|
||||
}
|
||||
@ -646,7 +661,8 @@ window_copy_cursor_next_word(struct window *w)
|
||||
px = 0;
|
||||
window_copy_cursor_down(w);
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py =screen_hsize(
|
||||
&w->base) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(w, py);
|
||||
}
|
||||
}
|
||||
@ -666,28 +682,28 @@ window_copy_cursor_next_word(struct window *w)
|
||||
out:
|
||||
|
||||
/* On screen. */
|
||||
if (px > data->ox && px <= data->ox + screen_last_x(s))
|
||||
if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
|
||||
data->cx = px - data->ox;
|
||||
|
||||
/* Off right of screen. */
|
||||
if (px > data->ox + screen_last_x(s)) {
|
||||
if (px > data->ox + screen_size_x(s) - 1) {
|
||||
/* Move cursor to last and scroll screen. */
|
||||
window_copy_scroll_left(w,
|
||||
px - data->ox - screen_last_x(s));
|
||||
data->cx = screen_last_x(s);
|
||||
window_copy_scroll_left(
|
||||
w, px - data->ox - (screen_size_x(s) - 1));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
|
||||
/* Off left of screen. */
|
||||
if (px <= data->ox) {
|
||||
if (px < screen_last_x(s)) {
|
||||
if (px < screen_size_x(s) - 1) {
|
||||
/* Short enough to fit on screen. */
|
||||
window_copy_scroll_right(w, data->ox);
|
||||
data->cx = px;
|
||||
} else {
|
||||
/* Too long to fit on screen. */
|
||||
window_copy_scroll_right(
|
||||
w, data->ox - (px - screen_last_x(s)));
|
||||
data->cx = screen_last_x(s);
|
||||
w, data->ox - (px - (screen_size_x(s) - 1)));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -705,7 +721,7 @@ window_copy_cursor_previous_word(struct window *w)
|
||||
u_int ox, px, py, skip;
|
||||
|
||||
ox = px = data->ox + data->cx;
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(&w->base) + data->cy - data->oy;
|
||||
|
||||
skip = 1;
|
||||
if (px != 0) {
|
||||
@ -719,13 +735,15 @@ window_copy_cursor_previous_word(struct window *w)
|
||||
break;
|
||||
|
||||
while (px == 0) {
|
||||
if (data->cy == 0 && (w->base.hsize == 0 ||
|
||||
data->oy >= w->base.hsize - 1))
|
||||
if (data->cy == 0 &&
|
||||
(screen_hsize(&w->base) == 0 ||
|
||||
data->oy >= screen_hsize(&w->base) - 1))
|
||||
goto out;
|
||||
|
||||
window_copy_cursor_up(w);
|
||||
|
||||
py = screen_y(&w->base, data->cy) - data->oy;
|
||||
py = screen_hsize(
|
||||
&w->base) + data->cy - data->oy;
|
||||
px = window_copy_find_length(w, py);
|
||||
}
|
||||
goto out;
|
||||
@ -746,28 +764,28 @@ window_copy_cursor_previous_word(struct window *w)
|
||||
out:
|
||||
|
||||
/* On screen. */
|
||||
if (px > data->ox && px <= data->ox + screen_last_x(s))
|
||||
if (px > data->ox && px <= data->ox + screen_size_x(s) - 1)
|
||||
data->cx = px - data->ox;
|
||||
|
||||
/* Off right of screen. */
|
||||
if (px > data->ox + screen_last_x(s)) {
|
||||
if (px > data->ox + screen_size_x(s) - 1) {
|
||||
/* Move cursor to last and scroll screen. */
|
||||
window_copy_scroll_left(w,
|
||||
px - data->ox - screen_last_x(s));
|
||||
data->cx = screen_last_x(s);
|
||||
window_copy_scroll_left(
|
||||
w, px - data->ox - (screen_size_x(s) - 1));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
|
||||
/* Off left of screen. */
|
||||
if (px <= data->ox) {
|
||||
if (px < screen_last_x(s)) {
|
||||
if (px < screen_size_x(s) - 1) {
|
||||
/* Short enough to fit on screen. */
|
||||
window_copy_scroll_right(w, data->ox);
|
||||
data->cx = px;
|
||||
} else {
|
||||
/* Too long to fit on screen. */
|
||||
window_copy_scroll_right(
|
||||
w, data->ox - (px - screen_last_x(s)));
|
||||
data->cx = screen_last_x(s);
|
||||
w, data->ox - (px - (screen_size_x(s) - 1)));
|
||||
data->cx = screen_size_x(s) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -794,8 +812,8 @@ window_copy_scroll_left(struct window *w, u_int nx)
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
for (i = 1; i < screen_size_y(s); i++) {
|
||||
screen_write_move_cursor(&ctx, 0, i);
|
||||
screen_write_delete_characters(&ctx, nx);
|
||||
screen_write_cursormove(&ctx, 0, i);
|
||||
screen_write_deletecharacter(&ctx, nx);
|
||||
}
|
||||
window_copy_write_columns(w, &ctx, screen_size_x(s) - nx, nx);
|
||||
window_copy_write_line(w, &ctx, 0);
|
||||
@ -803,7 +821,7 @@ window_copy_scroll_left(struct window *w, u_int nx)
|
||||
window_copy_update_selection(w);
|
||||
window_copy_write_lines(w, &ctx, data->cy, 1);
|
||||
}
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
@ -824,14 +842,14 @@ window_copy_scroll_right(struct window *w, u_int nx)
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
for (i = 1; i < screen_size_y(s); i++) {
|
||||
screen_write_move_cursor(&ctx, 0, i);
|
||||
screen_write_insert_characters(&ctx, nx);
|
||||
screen_write_cursormove(&ctx, 0, i);
|
||||
screen_write_insertcharacter(&ctx, nx);
|
||||
}
|
||||
window_copy_write_columns(w, &ctx, 0, nx);
|
||||
window_copy_write_line(w, &ctx, 0);
|
||||
if (s->sel.flag)
|
||||
window_copy_write_lines(w, &ctx, data->cy, 1);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
window_copy_write_line(w, &ctx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
@ -850,13 +868,13 @@ window_copy_scroll_up(struct window *w, u_int ny)
|
||||
window_copy_update_selection(w);
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_delete_lines(&ctx, ny);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_deleteline(&ctx, ny);
|
||||
window_copy_write_lines(w, &ctx, screen_size_y(s) - ny, ny);
|
||||
window_copy_write_line(w, &ctx, 0);
|
||||
if (s->sel.flag && screen_size_y(s) > ny)
|
||||
window_copy_write_lines(w, &ctx, screen_size_y(s) - ny - 1, 1);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
window_copy_write_line(w, &ctx, screen_size_y(s) - ny - 1);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
@ -867,24 +885,24 @@ window_copy_scroll_down(struct window *w, u_int ny)
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (ny > w->base.hsize)
|
||||
if (ny > screen_hsize(&w->base))
|
||||
return;
|
||||
|
||||
if (data->oy > w->base.hsize - ny)
|
||||
ny = w->base.hsize - data->oy;
|
||||
if (data->oy > screen_hsize(&w->base) - ny)
|
||||
ny = screen_hsize(&w->base) - data->oy;
|
||||
if (ny == 0)
|
||||
return;
|
||||
data->oy += ny;
|
||||
window_copy_update_selection(w);
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_insert_lines(&ctx, ny);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_insertline(&ctx, ny);
|
||||
window_copy_write_lines(w, &ctx, 0, ny);
|
||||
if (s->sel.flag && screen_size_y(s) > ny)
|
||||
window_copy_write_lines(w, &ctx, ny, 1);
|
||||
window_copy_write_line(w, &ctx, ny);
|
||||
else if (ny == 1) /* nuke position */
|
||||
window_copy_write_line(w, &ctx, 1);
|
||||
screen_write_move_cursor(&ctx, data->cx, data->cy);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: window-more.c,v 1.18 2008-09-10 19:15:04 nicm Exp $ */
|
||||
/* $Id: window-more.c,v 1.19 2008-09-25 20:08:57 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -62,7 +62,7 @@ window_more_vadd(struct window *w, const char *fmt, va_list ap)
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
size = ARRAY_LENGTH(&data->list) - 1;
|
||||
if (size >= data->top && size <= data->top + screen_last_y(s)) {
|
||||
if (size >= data->top && size <= data->top + screen_size_y(s) - 1) {
|
||||
window_more_write_line(w, &ctx, size - data->top);
|
||||
if (size != data->top)
|
||||
window_more_write_line(w, &ctx, 0);
|
||||
@ -164,27 +164,30 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
|
||||
{
|
||||
struct window_more_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
char *msg;
|
||||
struct grid_cell gc;
|
||||
char *msg, hdr[32];
|
||||
size_t size;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
|
||||
if (py == 0) {
|
||||
screen_write_set_attributes(
|
||||
ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
|
||||
screen_write_move_cursor(ctx, 0, 0);
|
||||
size = screen_write_put_string_rjust(
|
||||
ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
|
||||
size = xsnprintf(hdr, sizeof hdr,
|
||||
"[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
|
||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||
gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
|
||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||
gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
|
||||
} else
|
||||
size = 0;
|
||||
|
||||
screen_write_set_attributes(ctx, 0, 8, 8);
|
||||
screen_write_move_cursor(ctx, 0, py);
|
||||
screen_write_cursormove(ctx, 0, py);
|
||||
if (data->top + py < ARRAY_LENGTH(&data->list)) {
|
||||
msg = ARRAY_ITEM(&data->list, data->top + py);
|
||||
screen_write_put_string(
|
||||
ctx, "%.*s", (int) (screen_size_x(s) - size), msg);
|
||||
screen_write_puts(
|
||||
ctx, &gc, "%.*s", (int) (screen_size_x(s) - size), msg);
|
||||
}
|
||||
while (s->cx < screen_size_x(s) - size)
|
||||
screen_write_put_character(ctx, ' ');
|
||||
screen_write_putc(ctx, &gc, ' ');
|
||||
}
|
||||
|
||||
void
|
||||
@ -212,8 +215,8 @@ window_more_scroll_up(struct window *w)
|
||||
data->top--;
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_insert_lines(&ctx, 1);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_insertline(&ctx, 1);
|
||||
window_more_write_line(w, &ctx, 0);
|
||||
window_more_write_line(w, &ctx, 1);
|
||||
screen_write_stop(&ctx);
|
||||
@ -231,9 +234,9 @@ window_more_scroll_down(struct window *w)
|
||||
data->top++;
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_delete_lines(&ctx, 1);
|
||||
window_more_write_line(w, &ctx, screen_last_y(s));
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_deleteline(&ctx, 1);
|
||||
window_more_write_line(w, &ctx, screen_size_y(s) - 1);
|
||||
window_more_write_line(w, &ctx, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: window-scroll.c,v 1.23 2008-09-10 19:15:05 nicm Exp $ */
|
||||
/* $Id: window-scroll.c,v 1.24 2008-09-25 20:08:57 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -90,10 +90,14 @@ window_scroll_resize(struct window *w, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_scroll_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
u_int i;
|
||||
|
||||
screen_resize(s, sx, sy);
|
||||
screen_display_copy_area(&data->screen, &w->base,
|
||||
0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy);
|
||||
screen_write_start(&ctx, s, NULL, NULL);
|
||||
for (i = 0; i < screen_size_y(s); i++)
|
||||
window_scroll_write_line(w, &ctx, i);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
@ -121,8 +125,8 @@ window_scroll_key(struct window *w, struct client *c, int key)
|
||||
window_scroll_scroll_down(w);
|
||||
break;
|
||||
case MODEKEY_PPAGE:
|
||||
if (data->oy + screen_size_y(s) > w->base.hsize)
|
||||
data->oy = w->base.hsize;
|
||||
if (data->oy + screen_size_y(s) > screen_hsize(&w->base))
|
||||
data->oy = screen_hsize(&w->base);
|
||||
else
|
||||
data->oy += screen_size_y(s);
|
||||
window_scroll_redraw_screen(w);
|
||||
@ -145,19 +149,24 @@ window_scroll_write_line(
|
||||
{
|
||||
struct window_scroll_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct grid_cell gc;
|
||||
char hdr[32];
|
||||
size_t size;
|
||||
|
||||
if (py == 0) {
|
||||
screen_write_set_attributes(
|
||||
ctx, ATTR_BRIGHT|ATTR_REVERSE, 8, 8);
|
||||
screen_write_move_cursor(ctx, 0, 0);
|
||||
size = screen_write_put_string_rjust(
|
||||
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
size = xsnprintf(hdr, sizeof hdr,
|
||||
"[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base));
|
||||
gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE;
|
||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||
gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE);
|
||||
} else
|
||||
size = 0;
|
||||
screen_write_move_cursor(ctx, 0, py);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy);
|
||||
|
||||
screen_write_cursormove(ctx, 0, py);
|
||||
screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) -
|
||||
data->oy) + py, screen_size_x(s) - size, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -167,9 +176,9 @@ window_scroll_write_column(
|
||||
struct window_scroll_mode_data *data = w->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
screen_write_move_cursor(ctx, px, 0);
|
||||
screen_write_copy_area(
|
||||
ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy);
|
||||
screen_write_cursormove(ctx, px, 0);
|
||||
screen_write_copy(ctx, &w->base, data->ox + px,
|
||||
screen_hsize(&w->base) - data->oy, 1, screen_size_y(s));
|
||||
}
|
||||
|
||||
void
|
||||
@ -192,13 +201,13 @@ window_scroll_scroll_up(struct window *w)
|
||||
struct window_scroll_mode_data *data = w->modedata;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (data->oy >= w->base.hsize)
|
||||
if (data->oy >= screen_hsize(&w->base))
|
||||
return;
|
||||
data->oy++;
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_insert_lines(&ctx, 1);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_insertline(&ctx, 1);
|
||||
window_scroll_write_line(w, &ctx, 0);
|
||||
window_scroll_write_line(w, &ctx, 1);
|
||||
screen_write_stop(&ctx);
|
||||
@ -216,9 +225,9 @@ window_scroll_scroll_down(struct window *w)
|
||||
data->oy--;
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
screen_write_move_cursor(&ctx, 0, 0);
|
||||
screen_write_delete_lines(&ctx, 1);
|
||||
window_scroll_write_line(w, &ctx, screen_last_y(s));
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_deleteline(&ctx, 1);
|
||||
window_scroll_write_line(w, &ctx, screen_size_y(s) - 1);
|
||||
window_scroll_write_line(w, &ctx, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
@ -237,10 +246,10 @@ window_scroll_scroll_right(struct window *w)
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
for (i = 1; i < screen_size_y(s); i++) {
|
||||
screen_write_move_cursor(&ctx, 0, i);
|
||||
screen_write_delete_characters(&ctx, 1);
|
||||
screen_write_cursormove(&ctx, 0, i);
|
||||
screen_write_deletecharacter(&ctx, 1);
|
||||
}
|
||||
window_scroll_write_column(w, &ctx, screen_last_x(s));
|
||||
window_scroll_write_column(w, &ctx, screen_size_x(s) - 1);
|
||||
window_scroll_write_line(w, &ctx, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
@ -259,8 +268,8 @@ window_scroll_scroll_left(struct window *w)
|
||||
|
||||
screen_write_start_window(&ctx, w);
|
||||
for (i = 1; i < screen_size_y(s); i++) {
|
||||
screen_write_move_cursor(&ctx, 0, i);
|
||||
screen_write_insert_characters(&ctx, 1);
|
||||
screen_write_cursormove(&ctx, 0, i);
|
||||
screen_write_insertcharacter(&ctx, 1);
|
||||
}
|
||||
window_scroll_write_column(w, &ctx, 0);
|
||||
window_scroll_write_line(w, &ctx, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user