Move command handling into the server and tidy up some bits.

This commit is contained in:
Nicholas Marriott 2007-10-03 10:18:32 +00:00
parent 7ccdbf392d
commit 9bb907f2a7
15 changed files with 353 additions and 451 deletions

View File

@ -1,3 +1,8 @@
03 October 2007
* (nicm) Move command parsing into the client. Also rename some messages and
tidy up a few bits. Lots more tidying up needed :-/.
02 October 2007
* (nicm) Redraw client status lines on rename.
@ -90,5 +95,5 @@
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
$Id: CHANGES,v 1.22 2007-10-02 17:45:05 nicm Exp $
$Id: CHANGES,v 1.23 2007-10-03 10:18:31 nicm Exp $

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.10 2007-10-03 00:13:46 nicm Exp $
# $Id: Makefile,v 1.11 2007-10-03 10:18:31 nicm Exp $
.SUFFIXES: .c .o .y .h
.PHONY: clean
@ -17,8 +17,8 @@ DEBUG=
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 window.c \
session.c local.c log.c client.c client-msg.c client-cmd.c op.c op-list.c
xmalloc.c xmalloc-debug.c cmd.c input.c input-keys.c screen.c window.c \
session.c local.c log.c client.c client-msg.c client-fn.c op.c op-list.c
YACC= yacc -d

5
TODO
View File

@ -27,8 +27,8 @@
- 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 tty fd up to server and then do nothing. what problems
would this cause?
- 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
IPC is arse-about-face: too much overhead. 8-byte header for each
packet... hrm. already scanning output for \e, could add an extra
@ -52,3 +52,4 @@
- fix resize (width problems with multiple clients?)
- handle tmux in tmux (check $TMUX and abort)
- check for some reqd terminfo caps on startup
- sort out the pause mess

View File

@ -1,119 +0,0 @@
/* $Id: client-cmd.c,v 1.7 2007-10-02 15:38:09 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 "tmux.h"
int client_cmd_prefix = META;
int client_cmd_fn_msg(int, struct client_ctx *, char **);
int client_cmd_fn_select(int, struct client_ctx *, char **);
int client_cmd_fn_detach(int, struct client_ctx *, char **);
int client_cmd_fn_meta(int, struct client_ctx *, char **);
struct cmd {
int key;
int (*fn)(int, struct client_ctx *, char **);
int arg;
};
struct cmd client_cmd_table[] = {
{ '0', client_cmd_fn_select, 0 },
{ '1', client_cmd_fn_select, 1 },
{ '2', client_cmd_fn_select, 2 },
{ '3', client_cmd_fn_select, 3 },
{ '4', client_cmd_fn_select, 4 },
{ '5', client_cmd_fn_select, 5 },
{ '6', client_cmd_fn_select, 6 },
{ '7', client_cmd_fn_select, 7 },
{ '8', client_cmd_fn_select, 8 },
{ '9', client_cmd_fn_select, 9 },
{ 'C', client_cmd_fn_msg, MSG_CREATE },
{ 'c', client_cmd_fn_msg, MSG_CREATE },
{ 'D', client_cmd_fn_detach, 0 },
{ 'd', client_cmd_fn_detach, 0 },
{ 'N', client_cmd_fn_msg, MSG_NEXT },
{ 'n', client_cmd_fn_msg, MSG_NEXT },
{ 'P', client_cmd_fn_msg, MSG_PREVIOUS },
{ 'p', client_cmd_fn_msg, MSG_PREVIOUS },
{ 'R', client_cmd_fn_msg, MSG_REFRESH },
{ 'r', client_cmd_fn_msg, MSG_REFRESH },
{ 'L', client_cmd_fn_msg, MSG_LAST },
{ 'l', client_cmd_fn_msg, MSG_LAST },
{ 'W', client_cmd_fn_msg, MSG_WINDOWLIST },
{ 'w', client_cmd_fn_msg, MSG_WINDOWLIST },
{ 'I', client_cmd_fn_msg, MSG_WINDOWINFO },
{ 'i', client_cmd_fn_msg, MSG_WINDOWINFO },
{ META, client_cmd_fn_meta, 0 },
};
#define NCLIENTCMD (sizeof client_cmd_table / sizeof client_cmd_table[0])
int
client_cmd_dispatch(int key, struct client_ctx *cctx, char **error)
{
struct cmd *cmd;
u_int i;
for (i = 0; i < NCLIENTCMD; i++) {
cmd = client_cmd_table + i;
if (cmd->key == key)
return (cmd->fn(cmd->arg, cctx, error));
}
return (0);
}
/* Handle generic command. */
int
client_cmd_fn_msg(int arg, struct client_ctx *cctx, unused char **error)
{
client_write_server(cctx, arg, NULL, 0);
return (0);
}
/* Handle select command. */
int
client_cmd_fn_select(int arg, struct client_ctx *cctx, unused char **error)
{
struct select_data data;
data.idx = arg;
client_write_server(cctx, MSG_SELECT, &data, sizeof data);
return (0);
}
/* Handle detach command. */
int
client_cmd_fn_detach(
unused int arg, unused struct client_ctx *cctx, unused char **error)
{
return (-1);
}
/* Handle meta command. */
int
client_cmd_fn_meta(unused int arg, struct client_ctx *cctx, unused char **error)
{
uint8_t key = META;
client_write_server(cctx, MSG_INPUT, &key, sizeof key);
return (0);
}

67
client-fn.c Normal file
View File

@ -0,0 +1,67 @@
/* $Id: client-fn.c,v 1.1 2007-10-03 10:18:31 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
void
client_fill_sessid(struct sessid *sid, char name[MAXNAMELEN])
{
char *env, *ptr, buf[256];
const char *errstr;
long long ll;
strlcpy(sid->name, name, sizeof sid->name);
sid->pid = -1;
if ((env = getenv("TMUX")) == NULL)
return;
if ((ptr = strchr(env, ',')) == NULL)
return;
if ((size_t) (ptr - env) > sizeof buf)
return;
memcpy(buf, env, ptr - env);
buf[ptr - env] = '\0';
ll = strtonum(ptr + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return;
sid->idx = ll;
ll = strtonum(buf, 0, LLONG_MAX, &errstr);
if (errstr != NULL)
return;
sid->pid = ll;
}
void
client_write_server(
struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (len > 0)
buffer_write(cctx->srv_out, buf, len);
}

View File

@ -1,4 +1,4 @@
/* $Id: client-msg.c,v 1.4 2007-09-29 14:57:07 nicm Exp $ */
/* $Id: client-msg.c,v 1.5 2007-10-03 10:18:31 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,11 +24,11 @@
#include "tmux.h"
int client_msg_fn_output(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_pause(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_done(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exit(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_data(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_detach(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_error(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_okay(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_pause(struct hdr *, struct client_ctx *, char **);
struct client_msg {
enum hdrtype type;
@ -36,11 +36,11 @@ struct client_msg {
int (*fn)(struct hdr *, struct client_ctx *, char **);
};
struct client_msg client_msg_table[] = {
{ MSG_OUTPUT, client_msg_fn_output },
{ MSG_PAUSE, client_msg_fn_pause },
{ MSG_DONE, client_msg_fn_done },
{ MSG_EXIT, client_msg_fn_exit },
{ MSG_DATA, client_msg_fn_data },
{ MSG_DETACH, client_msg_fn_detach },
{ MSG_ERROR, client_msg_fn_error },
{ MSG_OKAY, client_msg_fn_okay },
{ MSG_PAUSE, client_msg_fn_pause },
};
#define NCLIENTMSG (sizeof client_msg_table / sizeof client_msg_table[0])
@ -73,9 +73,9 @@ client_msg_dispatch(struct client_ctx *cctx, char **error)
}
}
/* Output message from server. */
/* Data message from server. */
int
client_msg_fn_output(
client_msg_fn_data(
struct hdr *hdr, struct client_ctx *cctx, unused char **error)
{
local_output(cctx->srv_in, hdr->size);
@ -92,23 +92,13 @@ client_msg_fn_pause(
return (1);
}
/* Exit message from server. */
/* Okay message from server. */
int
client_msg_fn_exit(
client_msg_fn_okay(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXIT size");
return (-1);
}
/* Done message from server. */
int
client_msg_fn_done(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_DONE size");
fatalx("bad MSG_OKAY size");
return (0);
}
@ -125,3 +115,16 @@ client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
return (-1);
}
/* Detach message from server. */
int
client_msg_fn_detach(
struct hdr *hdr, unused struct client_ctx *cctx, char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_DETACH size");
*error = NULL;
return (-1);
}

View File

@ -1,4 +1,4 @@
/* $Id: client.c,v 1.9 2007-09-29 13:22:15 nicm Exp $ */
/* $Id: client.c,v 1.10 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -154,7 +154,7 @@ client_flush(struct client_ctx *cctx)
continue;
buffer_remove(cctx->srv_in, sizeof hdr);
if (hdr.type == MSG_DONE)
if (hdr.type == MSG_OKAY)
return (0);
if (hdr.type == MSG_ERROR) {
if (hdr.size > INT_MAX - 1)
@ -241,49 +241,6 @@ local_dead:
fatalx("local socket dead");
}
void
client_fill_sessid(struct sessid *sid, char name[MAXNAMELEN])
{
char *env, *ptr, buf[256];
const char *errstr;
long long ll;
strlcpy(sid->name, name, sizeof sid->name);
sid->pid = -1;
if ((env = getenv("TMUX")) == NULL)
return;
if ((ptr = strchr(env, ',')) == NULL)
return;
if ((size_t) (ptr - env) > sizeof buf)
return;
memcpy(buf, env, ptr - env);
buf[ptr - env] = '\0';
ll = strtonum(ptr + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return;
sid->idx = ll;
ll = strtonum(buf, 0, LLONG_MAX, &errstr);
if (errstr != NULL)
return;
sid->pid = ll;
}
void
client_write_server(
struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (len > 0)
buffer_write(cctx->srv_out, buf, len);
}
void
client_handle_winch(struct client_ctx *cctx)
{
@ -300,39 +257,22 @@ client_handle_winch(struct client_ctx *cctx)
}
int
client_process_local(struct client_ctx *cctx, char **error)
client_process_local(struct client_ctx *cctx, unused char **error)
{
struct buffer *b;
size_t size;
int n, key;
int key;
n = 0;
b = buffer_create(BUFSIZ);
while ((key = local_key(&size)) != KEYC_NONE) {
log_debug("key code: %d", key);
if (key == client_cmd_prefix) {
if ((key = local_key(NULL)) == KEYC_NONE) {
/* XXX sux */
buffer_reverse_remove(cctx->loc_in, size);
break;
}
n = client_cmd_dispatch(key, cctx, error);
break;
}
input_store8(b, '\e');
input_store16(b, (uint16_t) key /*XXX*/);
}
while ((key = local_key()) != KEYC_NONE)
input_store16(b, (uint16_t) key);
log_debug("transmitting %zu bytes of input", BUFFER_USED(b));
if (BUFFER_USED(b) == 0) {
buffer_destroy(b);
return (n);
if (BUFFER_USED(b) != 0) {
client_write_server(
cctx, MSG_KEYS, BUFFER_OUT(b), BUFFER_USED(b));
}
client_write_server(cctx, MSG_INPUT, BUFFER_OUT(b), BUFFER_USED(b));
buffer_destroy(b);
return (n);
return (0);
}

176
cmd.c Normal file
View File

@ -0,0 +1,176 @@
/* $Id: cmd.c,v 1.1 2007-10-03 10:18:32 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 <stdlib.h>
#include "tmux.h"
int cmd_prefix = META;
void cmd_fn_create(struct client *, int);
void cmd_fn_detach(struct client *, int);
void cmd_fn_last(struct client *, int);
void cmd_fn_meta(struct client *, int);
void cmd_fn_next(struct client *, int);
void cmd_fn_previous(struct client *, int);
void cmd_fn_refresh(struct client *, int);
void cmd_fn_select(struct client *, int);
void cmd_fn_windowinfo(struct client *, int);
struct cmd {
int key;
void (*fn)(struct client *, int);
int arg;
};
struct cmd cmd_table[] = {
{ '0', cmd_fn_select, 0 },
{ '1', cmd_fn_select, 1 },
{ '2', cmd_fn_select, 2 },
{ '3', cmd_fn_select, 3 },
{ '4', cmd_fn_select, 4 },
{ '5', cmd_fn_select, 5 },
{ '6', cmd_fn_select, 6 },
{ '7', cmd_fn_select, 7 },
{ '8', cmd_fn_select, 8 },
{ '9', cmd_fn_select, 9 },
{ 'C', cmd_fn_create, 0 },
{ 'c', cmd_fn_create, 0 },
{ 'D', cmd_fn_detach, 0 },
{ 'd', cmd_fn_detach, 0 },
{ 'N', cmd_fn_next, 0 },
{ 'n', cmd_fn_next, 0 },
{ 'P', cmd_fn_previous, 0 },
{ 'p', cmd_fn_previous, 0 },
{ 'R', cmd_fn_refresh, 0 },
{ 'r', cmd_fn_refresh, 0 },
{ 'L', cmd_fn_last, 0 },
{ 'l', cmd_fn_last, 0 },
{ 'I', cmd_fn_windowinfo, 0 },
{ 'i', cmd_fn_windowinfo, 0 },
{ META, cmd_fn_meta, 0 },
};
#define NCMD (sizeof cmd_table / sizeof cmd_table[0])
void
cmd_dispatch(struct client *c, int key)
{
struct cmd *cmd;
u_int i;
for (i = 0; i < NCMD; i++) {
cmd = cmd_table + i;
if (cmd->key == key)
cmd->fn(c, cmd->arg);
}
}
void
cmd_fn_create(struct client *c, unused int arg)
{
const char *shell;
char *cmd;
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/ksh";
xasprintf(&cmd, "%s -l", shell);
if (session_new(c->session, cmd, c->sx, c->sy) != 0)
fatalx("session_new failed");
xfree(cmd);
server_draw_client(c, 0, c->sy - 1);
}
void
cmd_fn_detach(struct client *c, unused int arg)
{
server_write_client(c, MSG_DETACH, NULL, 0);
}
void
cmd_fn_last(struct client *c, unused int arg)
{
if (session_last(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No last window");
}
void
cmd_fn_meta(struct client *c, unused int arg)
{
window_key(c->session->window, cmd_prefix);
}
void
cmd_fn_next(struct client *c, unused int arg)
{
if (session_next(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No next window");
}
void
cmd_fn_previous(struct client *c, unused int arg)
{
if (session_previous(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No previous window");
}
void
cmd_fn_refresh(struct client *c, unused int arg)
{
server_draw_client(c, 0, c->sy - 1);
}
void
cmd_fn_select(struct client *c, int arg)
{
if (session_select(c->session, arg) == 0)
server_window_changed(c);
else
server_write_message(c, "Window %u not present", arg);
}
void
cmd_fn_windowinfo(struct client *c, unused int arg)
{
struct window *w;
char *buf;
size_t len;
u_int i;
len = c->sx + 1;
buf = xmalloc(len);
w = c->session->window;
window_index(&c->session->windows, w, &i);
xsnprintf(buf, len, "%u:%s \"%s\" (size %u,%u) (cursor %u,%u) "
"(region %u,%u)", i, w->name, w->screen.title, w->screen.sx,
w->screen.sy, w->screen.cx, w->screen.cy, w->screen.ry_upper,
w->screen.ry_lower);
server_write_message(c, "%s", buf);
xfree(buf);
}

12
input.c
View File

@ -1,4 +1,4 @@
/* $Id: input.c,v 1.18 2007-10-03 09:16:59 nicm Exp $ */
/* $Id: input.c,v 1.19 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -171,16 +171,6 @@ input_free(struct input_ctx *ictx)
ARRAY_FREE(&ictx->args);
}
void
input_parse1(struct screen *s, u_char *buf, size_t len, struct buffer *b)
{
struct input_ctx ictx;
input_init(&ictx, s);
input_parse(&ictx, buf, len, b);
input_free(&ictx);
}
void
input_parse(struct input_ctx *ictx, u_char *buf, size_t len, struct buffer *b)
{

View File

@ -1,4 +1,4 @@
/* $Id: local.c,v 1.13 2007-10-02 15:13:59 nicm Exp $ */
/* $Id: local.c,v 1.14 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -349,7 +349,7 @@ local_putp(const char *s)
/* Return waiting keys if any. */
int
local_key(size_t *used)
local_key(void)
{
struct local_key *lk;
u_int i;
@ -368,8 +368,6 @@ local_key(size_t *used)
log_debug("got key: "
"%s %d \"%s\"", lk->name, lk->code, lk->string);
buffer_remove(local_in, lk->size);
if (used != NULL)
*used = lk->size;
return (lk->code);
}
@ -377,8 +375,6 @@ local_key(size_t *used)
lk = local_keys + i;
}
if (used != NULL)
*used = 1;
return (input_extract8(local_in));
}

View File

@ -1,4 +1,4 @@
/* $Id: server-fn.c,v 1.11 2007-10-02 17:45:05 nicm Exp $ */
/* $Id: server-fn.c,v 1.12 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -164,10 +164,9 @@ server_draw_client(struct client *c, u_int py_upper, u_int py_lower)
size = BUFFER_USED(c->out) - size;
log_debug("redrawing screen, %zu bytes", size);
if (size != 0) {
hdr.type = MSG_OUTPUT;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(
BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
} else
buffer_reverse_add(c->out, sizeof hdr);
@ -191,7 +190,7 @@ server_draw_status(struct client *c)
status_write(c);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_OUTPUT;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
}
@ -237,7 +236,7 @@ server_write_message(struct client *c, const char *fmt, ...)
xfree(msg);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_OUTPUT;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
@ -256,7 +255,7 @@ server_write_message(struct client *c, const char *fmt, ...)
status_write(c);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_OUTPUT;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
}

View File

@ -1,4 +1,4 @@
/* $Id: server-msg.c,v 1.15 2007-10-03 09:17:00 nicm Exp $ */
/* $Id: server-msg.c,v 1.16 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -25,19 +25,12 @@
#include "tmux.h"
int server_msg_fn_attach(struct hdr *, struct client *);
int server_msg_fn_create(struct hdr *, struct client *);
int server_msg_fn_input(struct hdr *, struct client *);
int server_msg_fn_last(struct hdr *, struct client *);
int server_msg_fn_keys(struct hdr *, struct client *);
int server_msg_fn_new(struct hdr *, struct client *);
int server_msg_fn_next(struct hdr *, struct client *);
int server_msg_fn_previous(struct hdr *, struct client *);
int server_msg_fn_refresh(struct hdr *, struct client *);
int server_msg_fn_rename(struct hdr *, struct client *);
int server_msg_fn_select(struct hdr *, struct client *);
int server_msg_fn_sessions(struct hdr *, struct client *);
int server_msg_fn_size(struct hdr *, struct client *);
int server_msg_fn_windowlist(struct hdr *, struct client *);
int server_msg_fn_windowinfo(struct hdr *, struct client *);
int server_msg_fn_windows(struct hdr *, struct client *);
struct server_msg {
@ -47,19 +40,12 @@ struct server_msg {
};
const struct server_msg server_msg_table[] = {
{ MSG_ATTACH, server_msg_fn_attach },
{ MSG_CREATE, server_msg_fn_create },
{ MSG_INPUT, server_msg_fn_input },
{ MSG_LAST, server_msg_fn_last },
{ MSG_KEYS, server_msg_fn_keys },
{ MSG_NEW, server_msg_fn_new },
{ MSG_NEXT, server_msg_fn_next },
{ MSG_PREVIOUS, server_msg_fn_previous },
{ MSG_REFRESH, server_msg_fn_refresh },
{ MSG_RENAME, server_msg_fn_rename },
{ MSG_SELECT, server_msg_fn_select },
{ MSG_SESSIONS, server_msg_fn_sessions },
{ MSG_SIZE, server_msg_fn_size },
{ MSG_WINDOWLIST, server_msg_fn_windowlist },
{ MSG_WINDOWINFO, server_msg_fn_windowinfo },
{ MSG_WINDOWS, server_msg_fn_windows },
};
#define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0])
@ -134,7 +120,7 @@ server_msg_fn_new(struct hdr *hdr, struct client *c)
fatalx("session_create failed");
xfree(cmd);
server_write_client(c, MSG_DONE, NULL, 0);
server_write_client(c, MSG_OKAY, NULL, 0);
server_draw_client(c, 0, c->sy - 1);
return (0);
@ -174,65 +160,6 @@ server_msg_fn_attach(struct hdr *hdr, struct client *c)
return (0);
}
/* Create message from client. */
int
server_msg_fn_create(struct hdr *hdr, struct client *c)
{
const char *shell;
char *cmd;
if (c->session == NULL)
return (0);
if (hdr->size != 0)
fatalx("bad MSG_CREATE size");
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/ksh";
xasprintf(&cmd, "%s -l", shell);
if (session_new(c->session, cmd, c->sx, c->sy) != 0)
fatalx("session_new failed");
xfree(cmd);
server_draw_client(c, 0, c->sy - 1);
return (0);
}
/* Next message from client. */
int
server_msg_fn_next(struct hdr *hdr, struct client *c)
{
if (c->session == NULL)
return (0);
if (hdr->size != 0)
fatalx("bad MSG_NEXT size");
if (session_next(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No next window");
return (0);
}
/* Previous message from client. */
int
server_msg_fn_previous(struct hdr *hdr, struct client *c)
{
if (c->session == NULL)
return (0);
if (hdr->size != 0)
fatalx("bad MSG_PREVIOUS size");
if (session_previous(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No previous window");
return (0);
}
/* Size message from client. */
int
server_msg_fn_size(struct hdr *hdr, struct client *c)
@ -261,52 +188,34 @@ server_msg_fn_size(struct hdr *hdr, struct client *c)
return (0);
}
/* Input message from client. */
/* Keys message from client. */
int
server_msg_fn_input(struct hdr *hdr, struct client *c)
server_msg_fn_keys(struct hdr *hdr, struct client *c)
{
if (c->session == NULL)
return (0);
window_input(c->session->window, c->in, hdr->size);
return (0);
}
/* Refresh message from client. */
int
server_msg_fn_refresh(struct hdr *hdr, struct client *c)
{
struct refresh_data data;
int key;
size_t size;
if (c->session == NULL)
return (0);
if (hdr->size != 0 && hdr->size != sizeof data)
fatalx("bad MSG_REFRESH size");
if (hdr->size & 0x1)
fatalx("bad MSG_KEYS size");
server_draw_client(c, 0, c->sy - 1);
size = hdr->size;
while (size != 0) {
key = input_extract16(c->in);
size -= 2;
return (0);
}
if (c->prefix) {
cmd_dispatch(c, key);
c->prefix = 0;
continue;
}
/* Select message from client. */
int
server_msg_fn_select(struct hdr *hdr, struct client *c)
{
struct select_data data;
if (c->session == NULL)
return (0);
if (hdr->size != sizeof data)
fatalx("bad MSG_SELECT size");
buffer_read(c->in, &data, hdr->size);
if (c->session == NULL)
return (0);
if (session_select(c->session, data.idx) == 0)
server_window_changed(c);
else
server_write_message(c, "Window %u not present", data.idx);
if (key == cmd_prefix)
c->prefix = 1;
else
window_key(c->session->window, key);
}
return (0);
}
@ -429,7 +338,7 @@ server_msg_fn_rename(struct hdr *hdr, struct client *c)
strlcpy(w->name, data.newname, sizeof w->name);
server_write_client(c, MSG_DONE, NULL, 0);
server_write_client(c, MSG_OKAY, NULL, 0);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session != NULL) {
@ -441,23 +350,6 @@ server_msg_fn_rename(struct hdr *hdr, struct client *c)
return (0);
}
/* Last window message from client */
int
server_msg_fn_last(struct hdr *hdr, struct client *c)
{
if (c->session == NULL)
return (0);
if (hdr->size != 0)
fatalx("bad MSG_LAST size");
if (session_last(c->session) == 0)
server_window_changed(c);
else
server_write_message(c, "No last window");
return (0);
}
/* Window list message from client */
int
server_msg_fn_windowlist(struct hdr *hdr, struct client *c)
@ -492,33 +384,3 @@ server_msg_fn_windowlist(struct hdr *hdr, struct client *c)
return (0);
}
/* Window info message from client */
int
server_msg_fn_windowinfo(struct hdr *hdr, struct client *c)
{
struct window *w;
char *buf;
size_t len;
u_int i;
if (c->session == NULL)
return (0);
if (hdr->size != 0)
fatalx("bad MSG_WINDOWINFO size");
len = c->sx + 1;
buf = xmalloc(len);
w = c->session->window;
window_index(&c->session->windows, w, &i);
xsnprintf(buf, len, "%u:%s \"%s\" (size %u,%u) (cursor %u,%u) "
"(region %u,%u)", i, w->name, w->screen.title, w->screen.sx,
w->screen.sy, w->screen.cx, w->screen.cy, w->screen.ry_upper,
w->screen.ry_lower);
server_write_message(c, "%s", buf);
xfree(buf);
return (0);
}

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.16 2007-09-29 09:53:25 nicm Exp $ */
/* $Id: server.c,v 1.17 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -315,11 +315,10 @@ server_handle_window(struct window *w)
u_int i, j, p;
b = buffer_create(BUFSIZ);
window_output(w, b);
window_data(w, b);
if (BUFFER_USED(b) != 0) {
server_write_clients(
w, MSG_OUTPUT, BUFFER_OUT(b), BUFFER_USED(b));
w, MSG_DATA, BUFFER_OUT(b), BUFFER_USED(b));
}
buffer_destroy(b);
@ -341,7 +340,7 @@ server_handle_window(struct window *w)
if (s->window != w)
server_write_message(c, "Bell in window %u", p);
*/
server_write_client(c, MSG_OUTPUT, "\007", 1);
server_write_client(c, MSG_DATA, "\007", 1);
}
}

37
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.33 2007-10-02 17:45:05 nicm Exp $ */
/* $Id: tmux.h,v 1.34 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -260,23 +260,17 @@ struct buffer {
/* Message codes. */
enum hdrtype {
MSG_ATTACH,
MSG_CREATE,
MSG_DONE,
MSG_DATA,
MSG_DETACH,
MSG_ERROR,
MSG_EXIT,
MSG_INPUT,
MSG_LAST,
MSG_KEYS,
MSG_NEW,
MSG_NEXT,
MSG_OUTPUT,
MSG_OKAY,
MSG_PAUSE,
MSG_PREVIOUS,
MSG_REFRESH,
MSG_RENAME,
MSG_SELECT,
MSG_SESSIONS,
MSG_SIZE,
MSG_WINDOWINFO,
MSG_WINDOWLIST,
MSG_WINDOWS,
};
@ -482,6 +476,8 @@ struct client {
u_int sx;
u_int sy;
int prefix; /* waiting for command */
struct session *session;
};
ARRAY_DECL(clients, struct client *);
@ -522,15 +518,17 @@ int op_list_windows(char *, int, char **);
int client_init(char *, struct client_ctx *, int);
int client_flush(struct client_ctx *);
int client_main(struct client_ctx *);
void client_write_server(struct client_ctx *, enum hdrtype, void *, size_t);
void client_fill_sessid(struct sessid *, char [MAXNAMELEN]);
/* client-msg.c */
int client_msg_dispatch(struct client_ctx *, char **);
/* command.c */
extern int client_cmd_prefix;
int client_cmd_dispatch(int, struct client_ctx *, char **);
/* client-fn.c */
void client_write_server(struct client_ctx *, enum hdrtype, void *, size_t);
void client_fill_sessid(struct sessid *, char [MAXNAMELEN]);
/* cmd.c */
extern int cmd_prefix;
void cmd_dispatch(struct client *, int);
/* server.c */
extern struct clients clients;
@ -559,7 +557,6 @@ void status_write(struct client *c);
/* input.c */
void input_init(struct input_ctx *, struct screen *);
void input_free(struct input_ctx *);
void input_parse1(struct screen *, u_char *, size_t, struct buffer *);
void input_parse(struct input_ctx *, u_char *, size_t, struct buffer *);
uint8_t input_extract8(struct buffer *);
uint16_t input_extract16(struct buffer *);
@ -602,7 +599,7 @@ void screen_fill_start_of_line(
/* local.c */
int local_init(struct buffer **, struct buffer **);
void local_done(void);
int local_key(size_t *);
int local_key(void);
void local_output(struct buffer *, size_t);
/* window.c */
@ -617,8 +614,8 @@ 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_input(struct window *, struct buffer *, size_t);
void window_output(struct window *, struct buffer *);
void window_key(struct window *, int);
void window_data(struct window *, struct buffer *);
/* session.c */
extern struct sessions sessions;

View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.15 2007-10-01 14:15:48 nicm Exp $ */
/* $Id: window.c,v 1.16 2007-10-03 10:18:32 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -288,25 +288,11 @@ window_poll(struct window *w, struct pollfd *pfd)
return (0);
}
/* Process window input. */
/* Process window key. */
void
window_input(struct window *w, struct buffer *b, size_t size)
window_key(struct window *w, int key)
{
int key;
while (size != 0) {
if (size < 1)
break;
size--;
key = input_extract8(b);
if (key == '\e') {
if (size < 2)
fatalx("underflow");
size -= 2;
key = (int16_t) input_extract16(b);
}
input_translate_key(w->out, key);
}
input_translate_key(w->out, key);
}
/*
@ -314,7 +300,7 @@ window_input(struct window *w, struct buffer *b, size_t size)
* sequences and strings and returned.
*/
void
window_output(struct window *w, struct buffer *b)
window_data(struct window *w, struct buffer *b)
{
FILE *f;