mirror of
https://github.com/tmate-io/tmate.git
synced 2024-12-31 19:18:49 +01:00
Reorg window data structures. Add an intermediate data type (struct winlink) to hold index and make sessions hold a RB tree of them rather than a fixed array.
This commit is contained in:
parent
9f06104c3a
commit
4ba3cf60be
9
CHANGES
9
CHANGES
@ -1,3 +1,10 @@
|
||||
26 October 2007
|
||||
|
||||
* (nicm) Redo window data structures. The global array remains, but each per-
|
||||
session list is now a RB tree of winlink structures. This disassociates the
|
||||
window index from the array size (allowing arbitrary indexes) which still
|
||||
allowing windows to have multiple indexes.
|
||||
|
||||
25 October 2007
|
||||
|
||||
* (nicm) has-session command: checks if session exists.
|
||||
@ -163,5 +170,5 @@
|
||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||
customisation.
|
||||
|
||||
$Id: CHANGES,v 1.51 2007-10-25 17:44:24 nicm Exp $
|
||||
$Id: CHANGES,v 1.52 2007-10-26 12:29:07 nicm Exp $
|
||||
|
||||
|
3
TODO
3
TODO
@ -1,4 +1,3 @@
|
||||
- decide if TIOCPKT is necessary and either handle it or remove the code
|
||||
- it would be nice if there wasn't so much copying buffers about, audit uses
|
||||
- useful env vars like WINDOW
|
||||
- sort out who controls the buffers in local.c a bit
|
||||
@ -20,8 +19,6 @@
|
||||
- profile/optimise, particularly (i suspect) input.c
|
||||
- tidy up input.c a bit
|
||||
- decide about customised status line
|
||||
- rethink data structures. window->index is O(n), could have a w->idx member
|
||||
or use queues/trees and avoid NULLs?
|
||||
- client could pass term/tty fd up to server and then do nothing. what problems
|
||||
would this cause? -- need access to all terminfo data at once... signals?
|
||||
- cleanup/redesign IPC
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-kill-window.c,v 1.1 2007-10-19 11:10:35 nicm Exp $ */
|
||||
/* $Id: cmd-kill-window.c,v 1.2 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -92,7 +92,7 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
struct cmd_kill_window_data *data = ptr, std = { -1 };
|
||||
struct client *c = ctx->client;
|
||||
struct session *s = ctx->session;
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
u_int i;
|
||||
int destroyed;
|
||||
|
||||
@ -100,13 +100,13 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
data = &std;
|
||||
|
||||
if (data->idx == -1)
|
||||
w = s->window;
|
||||
else if ((w = window_at(&s->windows, data->idx)) == NULL) {
|
||||
wl = s->curw;
|
||||
else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) {
|
||||
ctx->error(ctx, "no window %u", data->idx);
|
||||
return;
|
||||
}
|
||||
|
||||
destroyed = session_detach(s, w);
|
||||
destroyed = session_detach(s, wl);
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c == NULL || c->session != s)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-sessions.c,v 1.6 2007-10-23 09:36:07 nicm Exp $ */
|
||||
/* $Id: cmd-list-sessions.c,v 1.7 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -45,8 +45,9 @@ cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct client *c = ctx->client;
|
||||
struct session *s = ctx->session;
|
||||
struct winlink *wl;
|
||||
char *tim;
|
||||
u_int i, j, n;
|
||||
u_int i, n;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||
s = ARRAY_ITEM(&sessions, i);
|
||||
@ -54,10 +55,8 @@ cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx)
|
||||
continue;
|
||||
|
||||
n = 0;
|
||||
for (j = 0; j < ARRAY_LENGTH(&s->windows); j++) {
|
||||
if (ARRAY_ITEM(&s->windows, j) != NULL)
|
||||
n++;
|
||||
}
|
||||
RB_FOREACH(wl, winlinks, &s->windows)
|
||||
n++;
|
||||
tim = ctime(&s->tim);
|
||||
*strchr(tim, '\n') = '\0';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-windows.c,v 1.3 2007-10-23 09:36:07 nicm Exp $ */
|
||||
/* $Id: cmd-list-windows.c,v 1.4 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -44,17 +44,14 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct client *c = ctx->client;
|
||||
struct session *s = ctx->session;
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) {
|
||||
w = ARRAY_ITEM(&s->windows, i);
|
||||
if (w == NULL)
|
||||
continue;
|
||||
|
||||
ctx->print(ctx,
|
||||
"%u: %s \"%s\" (%s) [%ux%u]", i, w->name, w->screen.title,
|
||||
ttyname(w->fd), w->screen.sx, w->screen.sy);
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
w = wl->window;
|
||||
ctx->print(ctx, "%u: %s \"%s\" (%s) [%ux%u]", wl->idx,
|
||||
w->name, w->screen.title, ttyname(w->fd),
|
||||
w->screen.sx, w->screen.sy);
|
||||
}
|
||||
|
||||
if (!(ctx->flags & CMD_KEY))
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-new-session.c,v 1.13 2007-10-19 17:15:29 nicm Exp $ */
|
||||
/* $Id: cmd-new-session.c,v 1.14 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -133,8 +133,8 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
if (c->session == NULL)
|
||||
fatalx("session_create failed");
|
||||
if (data->winname != NULL) {
|
||||
xfree(c->session->window->name);
|
||||
c->session->window->name = xstrdup(data->winname);
|
||||
xfree(c->session->curw->window->name);
|
||||
c->session->curw->window->name = xstrdup(data->winname);
|
||||
}
|
||||
|
||||
if (data->flag_detached)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-new-window.c,v 1.9 2007-10-19 09:21:25 nicm Exp $ */
|
||||
/* $Id: cmd-new-window.c,v 1.10 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -35,11 +36,12 @@ void cmd_new_window_free(void *);
|
||||
struct cmd_new_window_data {
|
||||
char *name;
|
||||
char *cmd;
|
||||
int idx;
|
||||
int flag_detached;
|
||||
};
|
||||
|
||||
const struct cmd_entry cmd_new_window_entry = {
|
||||
"new-window", "neww", "[-d] [-n name] [command]",
|
||||
"new-window", "neww", "[-d] [-i index] [-n name] [command]",
|
||||
0,
|
||||
cmd_new_window_parse,
|
||||
cmd_new_window_exec,
|
||||
@ -52,15 +54,24 @@ int
|
||||
cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause)
|
||||
{
|
||||
struct cmd_new_window_data *data;
|
||||
const char *errstr;
|
||||
int opt;
|
||||
|
||||
*ptr = data = xmalloc(sizeof *data);
|
||||
data->idx = -1;
|
||||
data->flag_detached = 0;
|
||||
data->name = NULL;
|
||||
data->cmd = NULL;
|
||||
|
||||
while ((opt = getopt(argc, argv, "dn:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "di:n:")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
data->idx = strtonum(optarg, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
xasprintf(cause, "index %s", errstr);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
data->name = xstrdup(optarg);
|
||||
break;
|
||||
@ -85,6 +96,7 @@ usage:
|
||||
usage(cause, "%s %s",
|
||||
cmd_new_window_entry.name, cmd_new_window_entry.usage);
|
||||
|
||||
error:
|
||||
cmd_new_window_free(data);
|
||||
return (-1);
|
||||
}
|
||||
@ -92,11 +104,12 @@ usage:
|
||||
void
|
||||
cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_new_window_data *data = ptr, std = { NULL, NULL, 0 };
|
||||
struct cmd_new_window_data *data = ptr;
|
||||
struct cmd_new_window_data std = { NULL, NULL, -1, 0 };
|
||||
struct client *c = ctx->client;
|
||||
struct session *s = ctx->session;
|
||||
struct winlink *wl;
|
||||
char *cmd;
|
||||
u_int i;
|
||||
|
||||
if (data == NULL)
|
||||
data = &std;
|
||||
@ -105,12 +118,14 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
if (cmd == NULL)
|
||||
cmd = default_command;
|
||||
|
||||
if (session_new(s, data->name, cmd, &i) != 0) {
|
||||
if (data->idx < 0)
|
||||
data->idx = -1;
|
||||
if ((wl = session_new(s, data->name, cmd, data->idx)) == NULL) {
|
||||
ctx->error(ctx, "command failed: %s", cmd);
|
||||
return;
|
||||
}
|
||||
if (!data->flag_detached) {
|
||||
session_select(s, i);
|
||||
session_select(s, wl->idx);
|
||||
server_redraw_session(s);
|
||||
} else
|
||||
server_status_session(s);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-rename-window.c,v 1.7 2007-10-19 17:15:29 nicm Exp $ */
|
||||
/* $Id: cmd-rename-window.c,v 1.8 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -96,19 +96,19 @@ cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
struct cmd_rename_window_data *data = ptr;
|
||||
struct client *c = ctx->client;
|
||||
struct session *s = ctx->session;
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (data->idx == -1)
|
||||
w = s->window;
|
||||
else if ((w = window_at(&s->windows, data->idx)) == NULL) {
|
||||
wl = s->curw;
|
||||
else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) {
|
||||
ctx->error(ctx, "no window %u", data->idx);
|
||||
return;
|
||||
}
|
||||
xfree(w->name);
|
||||
w->name = xstrdup(data->newname);
|
||||
xfree(wl->window->name);
|
||||
wl->window->name = xstrdup(data->newname);
|
||||
|
||||
server_status_session(s);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-select-window.c,v 1.4 2007-10-19 09:21:26 nicm Exp $ */
|
||||
/* $Id: cmd-select-window.c,v 1.5 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -108,10 +108,16 @@ cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx)
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (session_select(s, data->idx) == 0)
|
||||
switch (session_select(s, data->idx)) {
|
||||
case 0:
|
||||
server_redraw_session(s);
|
||||
else
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
ctx->error(ctx, "no window %u", data->idx);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(ctx->flags & CMD_KEY))
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-send-prefix.c,v 1.2 2007-10-19 23:33:20 nicm Exp $ */
|
||||
/* $Id: cmd-send-prefix.c,v 1.3 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -49,5 +49,5 @@ cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
window_key(c->session->window, prefix_key);
|
||||
input_translate_key(c->session->curw->window->out, prefix_key);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: key-bindings.c,v 1.11 2007-10-23 10:25:57 nicm Exp $ */
|
||||
/* $Id: key-bindings.c,v 1.12 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -177,7 +177,7 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||
|
||||
if (!(c->flags & CLIENT_HOLD)) {
|
||||
input_store_zero(c->out, CODE_CURSOROFF);
|
||||
for (i = 0; i < c->session->window->screen.sy; i++) {
|
||||
for (i = 0; i < c->session->curw->window->screen.sy; i++) {
|
||||
input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1);
|
||||
input_store_zero(c->out, CODE_CLEARLINE);
|
||||
}
|
||||
|
21
server-fn.c
21
server-fn.c
@ -1,4 +1,4 @@
|
||||
/* $Id: server-fn.c,v 1.22 2007-10-23 10:48:23 nicm Exp $ */
|
||||
/* $Id: server-fn.c,v 1.23 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -114,7 +114,7 @@ server_write_window_cur(
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL &&
|
||||
c->session != NULL && c->session->window == w) {
|
||||
c->session != NULL && c->session->curw->window == w) {
|
||||
if (c->flags & CLIENT_HOLD) /* XXX OUTPUT only */
|
||||
continue;
|
||||
server_write_client(c, type, buf, len);
|
||||
@ -165,7 +165,7 @@ server_status_client(struct client *c)
|
||||
void
|
||||
server_clear_client(struct client *c)
|
||||
{
|
||||
struct screen *s = &c->session->window->screen;
|
||||
struct screen *s = &c->session->curw->window->screen;
|
||||
struct hdr hdr;
|
||||
size_t size;
|
||||
u_int i;
|
||||
@ -192,7 +192,7 @@ server_clear_client(struct client *c)
|
||||
void
|
||||
server_redraw_client(struct client *c)
|
||||
{
|
||||
struct screen *s = &c->session->window->screen;
|
||||
struct screen *s = &c->session->curw->window->screen;
|
||||
struct hdr hdr;
|
||||
size_t size;
|
||||
|
||||
@ -248,7 +248,8 @@ server_clear_window_cur(struct window *w)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL && c->session != NULL && c->session->window == w)
|
||||
if (c != NULL &&
|
||||
c->session != NULL && c->session->curw->window == w)
|
||||
server_clear_client(c);
|
||||
}
|
||||
}
|
||||
@ -276,7 +277,8 @@ server_redraw_window_cur(struct window *w)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL && c->session != NULL && c->session->window == w)
|
||||
if (c != NULL &&
|
||||
c->session != NULL && c->session->curw->window == w)
|
||||
server_redraw_client(c);
|
||||
}
|
||||
}
|
||||
@ -304,7 +306,8 @@ server_status_window_cur(struct window *w)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL && c->session != NULL && c->session->window == w)
|
||||
if (c != NULL &&
|
||||
c->session != NULL && c->session->curw->window == w)
|
||||
server_status_client(c);
|
||||
}
|
||||
}
|
||||
@ -327,6 +330,7 @@ server_status_window_all(struct window *w)
|
||||
void
|
||||
server_write_message(struct client *c, const char *fmt, ...)
|
||||
{
|
||||
struct screen *s = &c->session->curw->window->screen;
|
||||
struct hdr hdr;
|
||||
va_list ap;
|
||||
char *msg;
|
||||
@ -364,8 +368,7 @@ server_write_message(struct client *c, const char *fmt, ...)
|
||||
size = BUFFER_USED(c->out);
|
||||
|
||||
if (status_lines == 0) {
|
||||
screen_draw(
|
||||
&c->session->window->screen, c->out, c->sy - 1, c->sy - 1);
|
||||
screen_draw(s, c->out, c->sy - 1, c->sy - 1);
|
||||
} else
|
||||
status_write(c);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: server-msg.c,v 1.29 2007-10-23 10:48:23 nicm Exp $ */
|
||||
/* $Id: server-msg.c,v 1.30 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -223,7 +223,7 @@ server_msg_fn_keys(struct hdr *hdr, struct client *c)
|
||||
if (key == prefix_key)
|
||||
c->flags |= CLIENT_PREFIX;
|
||||
else
|
||||
window_key(c->session->window, key);
|
||||
input_translate_key(c->session->curw->window->out, key);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
34
server.c
34
server.c
@ -1,4 +1,4 @@
|
||||
/* $Id: server.c,v 1.34 2007-10-24 11:30:02 nicm Exp $ */
|
||||
/* $Id: server.c,v 1.35 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -228,7 +228,7 @@ server_handle_windows(struct pollfd **pfd)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||
if ((w = ARRAY_ITEM(&windows, i)) != NULL) {
|
||||
if (window_poll(w, *pfd) != 0)
|
||||
if (buffer_poll(*pfd, w->in, w->out) != 0)
|
||||
server_lost_window(w);
|
||||
else
|
||||
server_handle_window(w);
|
||||
@ -259,14 +259,14 @@ server_fill_clients(struct pollfd **pfd)
|
||||
|
||||
/* Handle client pollfds. */
|
||||
void
|
||||
server_handle_clients(struct pollfd *(*pfd))
|
||||
server_handle_clients(struct pollfd **pfd)
|
||||
{
|
||||
struct client *c;
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
if ((c = ARRAY_ITEM(&clients, i)) != NULL) {
|
||||
if (buffer_poll((*pfd), c->in, c->out) != 0)
|
||||
if (buffer_poll(*pfd, c->in, c->out) != 0)
|
||||
server_lost_client(c);
|
||||
else
|
||||
server_msg_dispatch(c);
|
||||
@ -345,7 +345,7 @@ server_handle_window(struct window *w)
|
||||
u_int i;
|
||||
|
||||
b = buffer_create(BUFSIZ);
|
||||
window_data(w, b);
|
||||
input_parse(w, b);
|
||||
if (BUFFER_USED(b) != 0) {
|
||||
server_write_window_cur(
|
||||
w, MSG_DATA, BUFFER_OUT(b), BUFFER_USED(b));
|
||||
@ -368,7 +368,7 @@ server_handle_window(struct window *w)
|
||||
case BELL_CURRENT:
|
||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||
s = ARRAY_ITEM(&sessions, i);
|
||||
if (s != NULL && s->window == w)
|
||||
if (s != NULL && s->curw->window == w)
|
||||
server_write_session(s, MSG_DATA, "\007", 1);
|
||||
}
|
||||
break;
|
||||
@ -384,6 +384,7 @@ server_lost_window(struct window *w)
|
||||
{
|
||||
struct client *c;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
u_int i, j;
|
||||
int destroyed;
|
||||
|
||||
@ -397,16 +398,23 @@ server_lost_window(struct window *w)
|
||||
continue;
|
||||
|
||||
/* Detach window and either redraw or kill clients. */
|
||||
destroyed = session_detach(s, w);
|
||||
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
||||
c = ARRAY_ITEM(&clients, j);
|
||||
if (c == NULL || c->session != s)
|
||||
restart:
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (wl->window != w)
|
||||
continue;
|
||||
if (destroyed) {
|
||||
destroyed = session_detach(s, wl);
|
||||
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
||||
c = ARRAY_ITEM(&clients, j);
|
||||
if (c == NULL || c->session != s)
|
||||
continue;
|
||||
if (!destroyed) {
|
||||
server_redraw_client(c);
|
||||
continue;
|
||||
}
|
||||
c->session = NULL;
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
} else
|
||||
server_redraw_client(c);
|
||||
}
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
|
173
session.c
173
session.c
@ -1,4 +1,4 @@
|
||||
/* $Id: session.c,v 1.24 2007-10-24 11:05:59 nicm Exp $ */
|
||||
/* $Id: session.c,v 1.25 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -29,33 +29,41 @@
|
||||
struct sessions sessions;
|
||||
|
||||
void
|
||||
session_cancelbell(struct session *s, struct window *w)
|
||||
session_cancelbell(struct session *s, struct winlink *wl)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (window_index(&s->bells, w, &i) == 0)
|
||||
window_remove(&s->bells, w);
|
||||
for (i = 0; i < ARRAY_LENGTH(&s->bells); i++) {
|
||||
if (ARRAY_ITEM(&s->bells, i) == wl) {
|
||||
ARRAY_REMOVE(&s->bells, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
session_addbell(struct session *s, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
struct winlink *wl;
|
||||
|
||||
/* Never bell in the current window. */
|
||||
if (w == s->window || !session_has(s, w))
|
||||
return;
|
||||
|
||||
if (window_index(&s->bells, w, &i) != 0)
|
||||
window_add(&s->bells, w);
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (wl == s->curw)
|
||||
continue;
|
||||
if (wl->window == w && !session_hasbell(s, wl))
|
||||
ARRAY_ADD(&s->bells, wl);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
session_hasbell(struct session *s, struct window *w)
|
||||
session_hasbell(struct session *s, struct winlink *wl)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
return (window_index(&s->bells, w, &i) == 0);
|
||||
for (i = 0; i < ARRAY_LENGTH(&s->bells); i++) {
|
||||
if (ARRAY_ITEM(&s->bells, i) == wl)
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Find session by name. */
|
||||
@ -83,8 +91,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
|
||||
|
||||
s = xmalloc(sizeof *s);
|
||||
s->tim = time(NULL);
|
||||
s->window = s->last = NULL;
|
||||
ARRAY_INIT(&s->windows);
|
||||
s->curw = s->lastw = NULL;
|
||||
RB_INIT(&s->windows);
|
||||
ARRAY_INIT(&s->bells);
|
||||
|
||||
s->sx = sx;
|
||||
@ -103,7 +111,7 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
|
||||
s->name = xstrdup(name);
|
||||
else
|
||||
xasprintf(&s->name, "%u", i);
|
||||
if (session_new(s, NULL, cmd, &i) != 0) {
|
||||
if (session_new(s, NULL, cmd, -1) == NULL) {
|
||||
session_destroy(s);
|
||||
return (NULL);
|
||||
}
|
||||
@ -116,7 +124,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
|
||||
void
|
||||
session_destroy(struct session *s)
|
||||
{
|
||||
u_int i;
|
||||
struct winlink *wl;
|
||||
u_int i;
|
||||
|
||||
if (session_index(s, &i) != 0)
|
||||
fatalx("session not found");
|
||||
@ -124,11 +133,11 @@ session_destroy(struct session *s)
|
||||
while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL)
|
||||
ARRAY_TRUNC(&sessions, 1);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) {
|
||||
if (ARRAY_ITEM(&s->windows, i) != NULL)
|
||||
window_remove(&s->windows, ARRAY_ITEM(&s->windows, i));
|
||||
while (!RB_EMPTY(&s->windows)) {
|
||||
wl = RB_ROOT(&s->windows);
|
||||
RB_REMOVE(winlinks, &s->windows, wl);
|
||||
winlink_remove(&s->windows, wl);
|
||||
}
|
||||
ARRAY_FREE(&s->windows);
|
||||
|
||||
xfree(s->name);
|
||||
xfree(s);
|
||||
@ -146,44 +155,43 @@ session_index(struct session *s, u_int *i)
|
||||
}
|
||||
|
||||
/* Create a new window on a session. */
|
||||
int
|
||||
session_new(struct session *s, const char *name, const char *cmd, u_int *i)
|
||||
struct winlink *
|
||||
session_new(struct session *s, const char *name, const char *cmd, int idx)
|
||||
{
|
||||
struct window *w;
|
||||
const char *environ[] = { NULL, "TERM=screen", NULL };
|
||||
char buf[256];
|
||||
u_int i;
|
||||
|
||||
if (session_index(s, i) != 0)
|
||||
if (session_index(s, &i) != 0)
|
||||
fatalx("session not found");
|
||||
xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), *i);
|
||||
xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i);
|
||||
environ[0] = buf;
|
||||
|
||||
if ((w = window_create(name, cmd, environ, s->sx, s->sy)) == NULL)
|
||||
return (-1);
|
||||
session_attach(s, w);
|
||||
|
||||
window_index(&s->windows, w, i);
|
||||
return (0);
|
||||
return (NULL);
|
||||
return (session_attach(s, w, idx));
|
||||
}
|
||||
|
||||
/* Attach a window to a session. */
|
||||
void
|
||||
session_attach(struct session *s, struct window *w)
|
||||
struct winlink *
|
||||
session_attach(struct session *s, struct window *w, int idx)
|
||||
{
|
||||
window_add(&s->windows, w);
|
||||
return (winlink_add(&s->windows, w, idx));
|
||||
}
|
||||
|
||||
/* Detach a window from a session. */
|
||||
int
|
||||
session_detach(struct session *s, struct window *w)
|
||||
session_detach(struct session *s, struct winlink *wl)
|
||||
{
|
||||
if (s->window == w && session_last(s) != 0 && session_previous(s) != 0)
|
||||
if (s->curw == wl && session_last(s) != 0 && session_previous(s) != 0)
|
||||
session_next(s);
|
||||
if (s->last == w)
|
||||
s->last = NULL;
|
||||
if (s->lastw == wl)
|
||||
s->lastw = NULL;
|
||||
|
||||
window_remove(&s->windows, w);
|
||||
if (ARRAY_EMPTY(&s->windows)) {
|
||||
session_cancelbell(s, wl);
|
||||
winlink_remove(&s->windows, wl);
|
||||
if (RB_EMPTY(&s->windows)) {
|
||||
session_destroy(s);
|
||||
return (1);
|
||||
}
|
||||
@ -194,34 +202,32 @@ session_detach(struct session *s, struct window *w)
|
||||
int
|
||||
session_has(struct session *s, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
struct winlink *wl;
|
||||
|
||||
return (window_index(&s->windows, w, &i) == 0);
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (wl->window == w)
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Move session to next window. */
|
||||
int
|
||||
session_next(struct session *s)
|
||||
{
|
||||
struct window *w;
|
||||
u_int n;
|
||||
struct winlink *wl;
|
||||
|
||||
if (s->window == NULL)
|
||||
if (s->curw == NULL)
|
||||
return (-1);
|
||||
|
||||
w = window_next(&s->windows, s->window);
|
||||
if (w == NULL) {
|
||||
n = 0;
|
||||
while ((w = ARRAY_ITEM(&s->windows, n)) == NULL)
|
||||
n++;
|
||||
if (w == s->window)
|
||||
return (1);
|
||||
}
|
||||
if (w == s->window)
|
||||
return (0);
|
||||
s->last = s->window;
|
||||
s->window = w;
|
||||
session_cancelbell(s, w);
|
||||
wl = winlink_next(&s->windows, s->curw);
|
||||
if (wl == NULL)
|
||||
wl = RB_MIN(winlinks, &s->windows);
|
||||
if (wl == s->curw)
|
||||
return (1);
|
||||
s->lastw = s->curw;
|
||||
s->curw = wl;
|
||||
session_cancelbell(s, wl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -229,22 +235,19 @@ session_next(struct session *s)
|
||||
int
|
||||
session_previous(struct session *s)
|
||||
{
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
|
||||
if (s->window == NULL)
|
||||
if (s->curw == NULL)
|
||||
return (-1);
|
||||
|
||||
w = window_previous(&s->windows, s->window);
|
||||
if (w == NULL) {
|
||||
w = ARRAY_LAST(&s->windows);
|
||||
if (w == s->window)
|
||||
return (1);
|
||||
}
|
||||
if (w == s->window)
|
||||
return (0);
|
||||
s->last = s->window;
|
||||
s->window = w;
|
||||
session_cancelbell(s, w);
|
||||
wl = winlink_previous(&s->windows, s->curw);
|
||||
if (wl == NULL)
|
||||
wl = RB_MAX(winlinks, &s->windows);
|
||||
if (wl == s->curw)
|
||||
return (1);
|
||||
s->lastw = s->curw;
|
||||
s->curw = wl;
|
||||
session_cancelbell(s, wl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -252,16 +255,16 @@ session_previous(struct session *s)
|
||||
int
|
||||
session_select(struct session *s, u_int i)
|
||||
{
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
|
||||
w = window_at(&s->windows, i);
|
||||
if (w == NULL)
|
||||
wl = winlink_find_by_index(&s->windows, i);
|
||||
if (wl == NULL)
|
||||
return (-1);
|
||||
if (w == s->window)
|
||||
return (0);
|
||||
s->last = s->window;
|
||||
s->window = w;
|
||||
session_cancelbell(s, w);
|
||||
if (wl == s->curw)
|
||||
return (1);
|
||||
s->lastw = s->curw;
|
||||
s->curw = wl;
|
||||
session_cancelbell(s, wl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -269,16 +272,16 @@ session_select(struct session *s, u_int i)
|
||||
int
|
||||
session_last(struct session *s)
|
||||
{
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
|
||||
w = s->last;
|
||||
if (w == NULL)
|
||||
wl = s->lastw;
|
||||
if (wl == NULL)
|
||||
return (-1);
|
||||
if (w == s->window)
|
||||
if (wl == s->curw)
|
||||
return (1);
|
||||
|
||||
s->last = s->window;
|
||||
s->window = w;
|
||||
session_cancelbell(s, w);
|
||||
s->lastw = s->curw;
|
||||
s->curw = wl;
|
||||
session_cancelbell(s, wl);
|
||||
return (0);
|
||||
}
|
||||
|
22
status.c
22
status.c
@ -1,4 +1,4 @@
|
||||
/* $Id: status.c,v 1.6 2007-10-12 12:37:48 nicm Exp $ */
|
||||
/* $Id: status.c,v 1.7 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -27,11 +27,10 @@ void status_print(struct buffer *, size_t *, const char *, ...);
|
||||
void
|
||||
status_write(struct client *c)
|
||||
{
|
||||
struct screen *s = &c->session->window->screen;
|
||||
struct screen *s = &c->session->curw->window->screen;
|
||||
struct buffer *b = c->out;
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
size_t size;
|
||||
u_int i;
|
||||
char flag;
|
||||
|
||||
input_store_zero(b, CODE_CURSOROFF);
|
||||
@ -39,19 +38,16 @@ status_write(struct client *c)
|
||||
input_store_two(b, CODE_ATTRIBUTES, 0, status_colour);
|
||||
|
||||
size = c->sx;
|
||||
for (i = 0; i < ARRAY_LENGTH(&c->session->windows); i++) {
|
||||
w = ARRAY_ITEM(&c->session->windows, i);
|
||||
if (w == NULL)
|
||||
continue;
|
||||
|
||||
RB_FOREACH(wl, winlinks, &c->session->windows) {
|
||||
flag = ' ';
|
||||
if (w == c->session->last)
|
||||
if (wl == c->session->lastw)
|
||||
flag = '-';
|
||||
if (w == c->session->window)
|
||||
if (wl == c->session->curw)
|
||||
flag = '*';
|
||||
if (session_hasbell(c->session, w))
|
||||
if (session_hasbell(c->session, wl))
|
||||
flag = '!';
|
||||
status_print(b, &size, "%u:%s%c ", i, w->name, flag);
|
||||
status_print(
|
||||
b, &size, "%u:%s%c ", wl->idx, wl->window->name, flag);
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
60
tmux.h
60
tmux.h
@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.h,v 1.70 2007-10-25 17:44:24 nicm Exp $ */
|
||||
/* $Id: tmux.h,v 1.71 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -19,6 +19,9 @@
|
||||
#ifndef TMUX_H
|
||||
#define TMUX_H
|
||||
|
||||
/* Shut up gcc warnings about empty if bodies. */
|
||||
#define RB_AUGMENT(x) do {} while (0)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/queue.h>
|
||||
@ -385,9 +388,6 @@ struct input_ctx {
|
||||
ARRAY_DECL(, struct input_arg) args;
|
||||
};
|
||||
|
||||
/* Input context macros. */
|
||||
#define INPUT_FLAGS(ictx) ((ictx)->flags)
|
||||
|
||||
/* Window structure. */
|
||||
struct window {
|
||||
char *name;
|
||||
@ -396,17 +396,26 @@ struct window {
|
||||
struct buffer *in;
|
||||
struct buffer *out;
|
||||
|
||||
u_int references;
|
||||
|
||||
struct input_ctx ictx;
|
||||
|
||||
int flags;
|
||||
#define WINDOW_BELL 0x1
|
||||
|
||||
struct screen screen;
|
||||
|
||||
u_int references;
|
||||
};
|
||||
ARRAY_DECL(windows, struct window *);
|
||||
|
||||
/* Entry on local window list. */
|
||||
struct winlink {
|
||||
int idx;
|
||||
struct window *window;
|
||||
|
||||
RB_ENTRY(winlink) entry;
|
||||
};
|
||||
RB_HEAD(winlinks, winlink);
|
||||
|
||||
/* Client session. */
|
||||
struct session {
|
||||
char *name;
|
||||
@ -415,11 +424,11 @@ struct session {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
struct window *window;
|
||||
struct window *last;
|
||||
struct windows windows;
|
||||
struct winlink *curw;
|
||||
struct winlink *lastw;
|
||||
struct winlinks windows;
|
||||
|
||||
struct windows bells; /* windows with bells */
|
||||
ARRAY_DECL(, struct winlink *) bells; /* windows with bells */
|
||||
|
||||
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
||||
int flags;
|
||||
@ -665,33 +674,34 @@ void local_output(struct buffer *, size_t);
|
||||
|
||||
/* window.c */
|
||||
extern struct windows windows;
|
||||
int window_cmp(struct window *, struct window *);
|
||||
int winlink_cmp(struct winlink *, struct winlink *);
|
||||
RB_PROTOTYPE(windows, window, entry, window_cmp);
|
||||
RB_PROTOTYPE(winlinks, winlink, entry, winlink_cmp);
|
||||
struct winlink *winlink_find_by_index(struct winlinks *, int);
|
||||
struct winlink *winlink_find_by_window(struct winlinks *, struct window *);
|
||||
int winlink_next_index(struct winlinks *);
|
||||
struct winlink *winlink_add(struct winlinks *, struct window *, int);
|
||||
void winlink_remove(struct winlinks *, struct winlink *);
|
||||
struct winlink *winlink_next(struct winlinks *, struct winlink *);
|
||||
struct winlink *winlink_previous(struct winlinks *, struct winlink *);
|
||||
struct window *window_create(
|
||||
const char *, const char *, const char **, u_int, u_int);
|
||||
int window_index(struct windows *, struct window *, u_int *);
|
||||
void window_add(struct windows *, struct window *);
|
||||
void window_remove(struct windows *, struct window *);
|
||||
void window_destroy(struct window *);
|
||||
struct window *window_next(struct windows *, struct window *);
|
||||
struct window *window_previous(struct windows *, struct window *);
|
||||
struct window *window_at(struct windows *, u_int);
|
||||
int window_resize(struct window *, u_int, u_int);
|
||||
int window_poll(struct window *, struct pollfd *);
|
||||
void window_key(struct window *, int);
|
||||
void window_data(struct window *, struct buffer *);
|
||||
|
||||
/* session.c */
|
||||
extern struct sessions sessions;
|
||||
void session_cancelbell(struct session *, struct window *);
|
||||
void session_cancelbell(struct session *, struct winlink *);
|
||||
void session_addbell(struct session *, struct window *);
|
||||
int session_hasbell(struct session *, struct window *);
|
||||
int session_hasbell(struct session *, struct winlink *);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_create(const char *, const char *, u_int, u_int);
|
||||
void session_destroy(struct session *);
|
||||
int session_index(struct session *, u_int *);
|
||||
int session_new(
|
||||
struct session *, const char *, const char *, u_int *);
|
||||
void session_attach(struct session *, struct window *);
|
||||
int session_detach(struct session *, struct window *);
|
||||
struct winlink *session_new(struct session *, const char *, const char *, int);
|
||||
struct winlink *session_attach(struct session *, struct window *, int);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
int session_has(struct session *, struct window *);
|
||||
int session_next(struct session *);
|
||||
int session_previous(struct session *);
|
||||
|
265
window.c
265
window.c
@ -1,4 +1,4 @@
|
||||
/* $Id: window.c,v 1.23 2007-10-24 15:29:29 nicm Exp $ */
|
||||
/* $Id: window.c,v 1.24 2007-10-26 12:29:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -22,6 +22,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
@ -47,15 +48,109 @@
|
||||
* Each window also has a "virtual" screen (screen.c) which contains the
|
||||
* current state and is redisplayed when the window is reattached to a client.
|
||||
*
|
||||
* A global list of windows is maintained, and a window may also be a member
|
||||
* of any number of sessions. A reference count is maintained and a window
|
||||
* removed from the global list and destroyed when it reaches zero.
|
||||
* Windows are stored directly on a global array and wrapped in any number of
|
||||
* winlink structs to be linked onto local session RB trees A reference count
|
||||
* is maintained and a window removed from the global list and destroyed when
|
||||
* it reaches zero
|
||||
*/
|
||||
|
||||
/* Global window list. */
|
||||
struct windows windows;
|
||||
struct windows windows;
|
||||
|
||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
||||
|
||||
int
|
||||
winlink_cmp(struct winlink *wl1, struct winlink *wl2)
|
||||
{
|
||||
return (wl1->idx - wl2->idx);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_find_by_index(struct winlinks *wwl, int idx)
|
||||
{
|
||||
struct winlink wl;
|
||||
|
||||
if (idx < 0)
|
||||
fatalx("bad index");
|
||||
|
||||
wl.idx = idx;
|
||||
return (RB_FIND(winlinks, wwl, &wl));
|
||||
}
|
||||
|
||||
int
|
||||
winlink_next_index(struct winlinks *wwl)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < INT_MAX; i++) {
|
||||
if (winlink_find_by_index(wwl, i) == NULL)
|
||||
return (i);
|
||||
}
|
||||
|
||||
fatalx("no free indexes");
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_add(struct winlinks *wwl, struct window *w, int idx)
|
||||
{
|
||||
struct winlink *wl;
|
||||
|
||||
if (idx == -1)
|
||||
idx = winlink_next_index(wwl);
|
||||
else if (winlink_find_by_index(wwl, idx) != NULL)
|
||||
return (NULL);
|
||||
|
||||
if (idx < 0)
|
||||
fatalx("bad index");
|
||||
|
||||
wl = xcalloc(1, sizeof *wl);
|
||||
wl->idx = idx;
|
||||
wl->window = w;
|
||||
RB_INSERT(winlinks, wwl, wl);
|
||||
|
||||
w->references++;
|
||||
|
||||
return (wl);
|
||||
}
|
||||
|
||||
void
|
||||
winlink_remove(struct winlinks *wwl, struct winlink *wl)
|
||||
{
|
||||
struct window *w = wl->window;
|
||||
|
||||
RB_REMOVE(winlinks, wwl, wl);
|
||||
xfree(wl);
|
||||
|
||||
if (w->references == 0)
|
||||
fatal("bad reference count");
|
||||
w->references--;
|
||||
if (w->references == 0)
|
||||
window_destroy(w);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_next(unused struct winlinks *wwl, struct winlink *wl)
|
||||
{
|
||||
return (RB_NEXT(winlinks, wwl, wl));
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_previous(struct winlinks *wwl, struct winlink *wl)
|
||||
{
|
||||
struct winlink *wk;
|
||||
int idx = wl->idx;
|
||||
|
||||
wk = NULL;
|
||||
wl = RB_MIN(winlinks, wwl);
|
||||
while (wl != NULL && wl->idx < idx) {
|
||||
wk = wl;
|
||||
wl = RB_NEXT(winlinks, wwl, wl);
|
||||
}
|
||||
if (wl == NULL)
|
||||
return (NULL);
|
||||
return (wk);
|
||||
}
|
||||
|
||||
/* Create a new window. */
|
||||
struct window *
|
||||
window_create(
|
||||
const char *name, const char *cmd, const char **environ, u_int sx, u_int sy)
|
||||
@ -92,10 +187,6 @@ window_create(
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
fatal("fcntl failed");
|
||||
|
||||
mode = 1;
|
||||
if (ioctl(fd, TIOCPKT, &mode) == -1)
|
||||
fatal("ioctl failed");
|
||||
|
||||
w = xmalloc(sizeof *w);
|
||||
w->fd = fd;
|
||||
w->in = buffer_create(BUFSIZ);
|
||||
@ -126,60 +217,23 @@ window_create(
|
||||
} else
|
||||
w->name = xstrdup(name);
|
||||
|
||||
window_add(&windows, w);
|
||||
w->references = 1;
|
||||
ARRAY_ADD(&windows, w);
|
||||
w->references = 0;
|
||||
|
||||
return (w);
|
||||
}
|
||||
|
||||
/* Find window index in list. */
|
||||
int
|
||||
window_index(struct windows *ww, struct window *w, u_int *i)
|
||||
{
|
||||
for (*i = 0; *i < ARRAY_LENGTH(ww); (*i)++) {
|
||||
if (w == ARRAY_ITEM(ww, *i))
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Add a window to a list. */
|
||||
void
|
||||
window_add(struct windows *ww, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (window_index(ww, NULL, &i) != 0)
|
||||
ARRAY_ADD(ww, w);
|
||||
else
|
||||
ARRAY_SET(ww, i, w);
|
||||
|
||||
w->references++;
|
||||
}
|
||||
|
||||
/* Remove a window from a list. */
|
||||
void
|
||||
window_remove(struct windows *ww, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (window_index(ww, w, &i) != 0)
|
||||
fatalx("window not found");
|
||||
ARRAY_SET(ww, i, NULL);
|
||||
while (!ARRAY_EMPTY(ww) && ARRAY_LAST(ww) == NULL)
|
||||
ARRAY_TRUNC(ww, 1);
|
||||
|
||||
w->references--;
|
||||
if (w->references == 0)
|
||||
window_destroy(w);
|
||||
if (w->references == 1)
|
||||
window_remove(&windows, w);
|
||||
}
|
||||
|
||||
/* Destroy a window. */
|
||||
void
|
||||
window_destroy(struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||
if (ARRAY_ITEM(&windows, i) == w)
|
||||
break;
|
||||
}
|
||||
ARRAY_REMOVE(&windows, i);
|
||||
|
||||
close(w->fd);
|
||||
|
||||
input_free(w);
|
||||
@ -193,55 +247,6 @@ window_destroy(struct window *w)
|
||||
xfree(w);
|
||||
}
|
||||
|
||||
/* Locate next window in list. */
|
||||
struct window *
|
||||
window_next(struct windows *ww, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (window_index(ww, w, &i) != 0)
|
||||
fatalx("window not found");
|
||||
|
||||
if (i == ARRAY_LENGTH(ww) - 1)
|
||||
return (NULL);
|
||||
do {
|
||||
i++;
|
||||
w = window_at(ww, i);
|
||||
if (w != NULL)
|
||||
return (w);
|
||||
} while (i != ARRAY_LENGTH(ww) - 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Locate previous window in list. */
|
||||
struct window *
|
||||
window_previous(struct windows *ww, struct window *w)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (window_index(ww, w, &i) != 0)
|
||||
fatalx("window not found");
|
||||
if (i == 0)
|
||||
return (NULL);
|
||||
do {
|
||||
i--;
|
||||
w = window_at(ww, i);
|
||||
if (w != NULL)
|
||||
return (w);
|
||||
} while (i != 0);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Locate window at specific position in list. */
|
||||
struct window *
|
||||
window_at(struct windows *ww, u_int i)
|
||||
{
|
||||
if (i >= ARRAY_LENGTH(ww))
|
||||
return (NULL);
|
||||
return (ARRAY_ITEM(ww, i));
|
||||
}
|
||||
|
||||
/* Resize a window. */
|
||||
int
|
||||
window_resize(struct window *w, u_int sx, u_int sy)
|
||||
{
|
||||
@ -261,51 +266,3 @@ window_resize(struct window *w, u_int sx, u_int sy)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Handle window poll results. This is special because of TIOCPKT. */
|
||||
int
|
||||
window_poll(struct window *w, struct pollfd *pfd)
|
||||
{
|
||||
struct termios tio;
|
||||
size_t size;
|
||||
u_char *ptr;
|
||||
|
||||
size = BUFFER_USED(w->in);
|
||||
if (buffer_poll(pfd, w->in, w->out) != 0)
|
||||
return (-1);
|
||||
|
||||
if (BUFFER_USED(w->in) == size)
|
||||
return (0);
|
||||
ptr = BUFFER_IN(w->in) - (BUFFER_USED(w->in) - size);
|
||||
|
||||
log_debug("window packet: %hhu", *ptr);
|
||||
switch (*ptr) {
|
||||
case TIOCPKT_DATA:
|
||||
case TIOCPKT_FLUSHREAD:
|
||||
case TIOCPKT_FLUSHWRITE:
|
||||
case TIOCPKT_STOP:
|
||||
case TIOCPKT_START:
|
||||
case TIOCPKT_DOSTOP:
|
||||
case TIOCPKT_NOSTOP:
|
||||
buffer_delete_range(w->in, size, 1);
|
||||
break;
|
||||
case TIOCPKT_IOCTL:
|
||||
buffer_delete_range(w->in, size, 1 + sizeof tio);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Process window key. */
|
||||
void
|
||||
window_key(struct window *w, int key)
|
||||
{
|
||||
input_translate_key(w->out, key);
|
||||
}
|
||||
|
||||
/* Process output data from child process. */
|
||||
void
|
||||
window_data(struct window *w, struct buffer *b)
|
||||
{
|
||||
input_parse(w, b);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user