summaryrefslogtreecommitdiffstats
path: root/window.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2007-10-26 12:29:07 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2007-10-26 12:29:07 +0000
commit4ba3cf60beea7be93a1de674226f412e5fec1105 (patch)
tree9a86ea8ba56e33233e28217d36446605ddab4be8 /window.c
parent9f06104c3a56ad5ea2070317b776dfa84f213ffb (diff)
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.
Diffstat (limited to 'window.c')
-rw-r--r--window.c263
1 files changed, 110 insertions, 153 deletions
diff --git a/window.c b/window.c
index 9420dab1..5965b5ed 100644
--- a/window.c
+++ b/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)
+window_destroy(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)
-{
+ 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);
-}