summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-02-23 12:43:26 -0500
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-02-23 12:43:26 -0500
commitd9262fc5897e54f1b1fc1874acf101811bbb5935 (patch)
tree316d4c06ac93bad0e004a16915f5f3c3d9021528
parentc649e67105da3feb4d6d2d48a3d4ec72e484daf4 (diff)
downloadscreen-d9262fc5897e54f1b1fc1874acf101811bbb5935.tar.gz
Update the window-list when necessary.
Update the window-list whenever window ordering/etc. changes. There is an unusual bug where the selection in a list changes automatically when switching windows in another display. Need to investigate this issue. Also, left to do: support nested list, and advanced navigations introduced (e.g. toggle MRU, nestedness etc.)
-rw-r--r--src/help.c39
-rw-r--r--src/list_display.c4
-rw-r--r--src/list_generic.c7
-rw-r--r--src/list_generic.h5
-rw-r--r--src/list_window.c211
5 files changed, 217 insertions, 49 deletions
diff --git a/src/help.c b/src/help.c
index ebcf1d5..be344b7 100644
--- a/src/help.c
+++ b/src/help.c
@@ -50,6 +50,8 @@ extern struct win **wtab;
extern struct term term[];
#endif
+extern struct LayFuncs ListLf;
+
static void PadStr __P((char *, int, int, int));
extern char *wliststr;
@@ -1311,43 +1313,6 @@ struct win *p;
}
#endif
-void
-WListUpdatecv(cv, p)
-struct canvas *cv;
-struct win *p;
-{
-#if 0
- if (cv->c_layer->l_layfn != &WListLf)
- return;
- CV_CALL(cv, WListUpdate(p));
-#endif
-#warning Fixme
-}
-
-void
-WListLinkChanged()
-{
-#if 0
- struct display *olddisplay = display;
- struct canvas *cv;
- struct wlistdata *wlistdata;
-
- for (display = displays; display; display = display->d_next)
- for (cv = D_cvlist; cv; cv = cv->c_next)
- {
- if (!cv->c_layer || cv->c_layer->l_layfn != &WListLf)
- continue;
- wlistdata = (struct wlistdata *)cv->c_layer->l_data;
- if (wlistdata->order != WLIST_MRU)
- continue;
- CV_CALL(cv, WListUpdate(0));
- }
- display = olddisplay;
-#endif
-#warning Fix me too!
-}
-
-
/*
**
** The bindkey help page
diff --git a/src/list_display.c b/src/list_display.c
index 9223fd8..56e7f08 100644
--- a/src/list_display.c
+++ b/src/list_display.c
@@ -42,6 +42,8 @@ extern struct layer *flayer;
extern struct display *display, *displays;
extern struct mchar mchar_blank, mchar_so;
+static char ListID[] = "display";
+
/*
* layout of the displays page is as follows:
@@ -229,7 +231,7 @@ display_displays()
return;
}
- ldata = glist_display(&gl_Display);
+ ldata = glist_display(&gl_Display, ListID);
if (!ldata)
return;
diff --git a/src/list_generic.c b/src/list_generic.c
index 3d93438..61122a5 100644
--- a/src/list_generic.c
+++ b/src/list_generic.c
@@ -37,7 +37,7 @@ static int ListRewrite __P((int, int, int, struct mchar *, int));
static int ListResize __P((int, int));
static void ListRestore __P((void));
-static struct LayFuncs ListLf =
+struct LayFuncs ListLf =
{
ListProcess,
ListAbort,
@@ -50,7 +50,7 @@ static struct LayFuncs ListLf =
/** Returns non-zero on success. */
struct ListData *
-glist_display(struct GenericList *list)
+glist_display(struct GenericList *list, const char *name)
{
struct ListData *ldata;
@@ -58,6 +58,7 @@ glist_display(struct GenericList *list)
return NULL;
ldata = flayer->l_data;
+ ldata->name = name; /* We do not SaveStr, since the strings should be all static literals */
ldata->list_fn = list;
flayer->l_mode = 1;
@@ -243,6 +244,8 @@ glist_display_all(struct ListData *list)
if (!list->top)
list->top = list->root;
+ if (!list->selected)
+ list->selected = list->root;
for (row = list->root; row != list->top; row = row->next)
row->y = -1;
diff --git a/src/list_generic.h b/src/list_generic.h
index c9631ed..3e07c4c 100644
--- a/src/list_generic.h
+++ b/src/list_generic.h
@@ -42,6 +42,7 @@ struct GenericList
struct ListData
{
+ const char *name; /* An identifier for the list */
struct ListRow *root; /* The first item in the list */
struct ListRow *selected; /* The selected row */
struct ListRow *top; /* The topmost visible row */
@@ -51,6 +52,8 @@ struct ListData
void *data; /* List specific data */
};
+extern struct LayFuncs ListLf;
+
struct ListRow * glist_add_row __P((struct ListData *ldata, void *data, struct ListRow *after));
@@ -58,7 +61,7 @@ void glist_remove_rows __P((struct ListData *ldata));
void glist_display_all __P((struct ListData *list));
-struct ListData * glist_display __P((struct GenericList *list));
+struct ListData * glist_display __P((struct GenericList *list, const char *name));
void glist_abort __P((void));
diff --git a/src/list_window.c b/src/list_window.c
index 873e894..05a42b7 100644
--- a/src/list_window.c
+++ b/src/list_window.c
@@ -29,7 +29,7 @@
#include "list_generic.h"
extern struct layer *flayer;
-extern struct display *display;
+extern struct display *display, *displays;
extern char *wlisttit;
extern char *wliststr;
@@ -40,11 +40,14 @@ extern int renditions[];
extern struct win **wtab, *windows;
extern int maxwin;
+static char ListID[] = "window";
+
struct gl_Window_Data
{
- struct win *group; /* Currently displaying this group */
- int order; /* MRU? NESTED? etc. */
+ struct win *group; /* Set only for a W_TYPE_GROUP window */
+ int order; /* MRU? NUM? */
int onblank;
+ int nested;
struct win *fore; /* The foreground window we had. */
};
@@ -85,6 +88,50 @@ gl_Window_rebuild(struct ListData *ldata)
glist_display_all(ldata);
}
+static struct ListRow *
+gl_Window_findrow(struct ListData *ldata, struct win *p)
+{
+ struct ListRow *row = ldata->root;
+ for (; row; row = row->next)
+ {
+ if (row->data == p)
+ break;
+ }
+ return row;
+}
+
+static int
+gl_Window_remove(struct ListData *ldata, struct win *p)
+{
+ struct ListRow *row = gl_Window_findrow(ldata, p);
+ if (!row)
+ return 0;
+
+ /* Remove 'row'. Update 'selected', 'top', 'root' if necessary. */
+ if (row->next)
+ row->next->prev = row->prev;
+ if (row->prev)
+ row->prev->next = row->next;
+ if (row->child)
+ {
+ /* Move the children to row->parent. Make sure the ordering is right. */
+ }
+ if (row->parent && row->parent->child == row)
+ row->parent->child = row->next;
+
+ if (ldata->selected == row)
+ ldata->selected = row->prev ? row->prev : row->next;
+ if (ldata->top == row)
+ ldata->selected = row->prev ? row->prev : row->next;
+ if (ldata->root == row)
+ ldata->root = row->next;
+
+ ldata->list_fn->gl_freerow(ldata, row);
+ free(row);
+
+ return 1;
+}
+
static int
gl_Window_header(struct ListData *ldata)
{
@@ -174,13 +221,20 @@ gl_Window_input(struct ListData *ldata, char **inp, int *len)
if (display && AclCheckPermWin(D_user, ACL_READ, win))
return; /* Not allowed to switch to this window. */
#endif
- glist_abort();
- display = cd;
+ if (!wdata->group)
+ {
+ /* Do not abort the group window. */
+ glist_abort();
+ display = cd;
+ }
SwitchWindow(win->w_number);
+ *len = 0;
break;
case 033: /* escape */
case 007: /* ^G */
+ if (wdata->group)
+ break; /* Do nothing if it's a group window */
if (wdata->onblank)
{
glist_abort();
@@ -232,6 +286,10 @@ display_windows(int onblank, int order, struct win *group)
LMsg(0, "Window size too small for window list page");
return;
}
+
+ if (group)
+ onblank = 0; /* When drawing a group window, ignore 'onblank' */
+
if (onblank)
{
debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
@@ -264,7 +322,7 @@ display_windows(int onblank, int order, struct win *group)
struct ListData *ldata;
struct gl_Window_Data *wdata;
- ldata = glist_display(&gl_Window);
+ ldata = glist_display(&gl_Window, ListID);
if (!ldata)
{
if (onblank && p)
@@ -278,11 +336,148 @@ display_windows(int onblank, int order, struct win *group)
wdata = calloc(1, sizeof(struct gl_Window_Data));
wdata->group = group;
- wdata->order = order;
+ wdata->order = (order & ~WLIST_NESTED);
+ wdata->nested = !!(order & WLIST_NESTED);
wdata->onblank = onblank;
- wdata->fore = p;
+
+ /* Set the most recent window as selected. */
+ wdata->fore = windows;
+ while (wdata->fore && wdata->fore->w_group != group)
+ wdata->fore = wdata->fore->w_next;
+
ldata->data = wdata;
gl_Window_rebuild(ldata);
}
+static void
+WListUpdate(struct win *p, struct ListData *ldata)
+{
+ struct gl_Window_Data *wdata = ldata->data;
+ struct ListRow *row, *rbefore;
+ struct win *before;
+ int d = 0;
+
+ if (!p)
+ {
+ if (ldata->selected)
+ wdata->fore = ldata->selected->data; /* Try to retain the current selection */
+ glist_remove_rows(ldata);
+ gl_Window_rebuild(ldata);
+ return;
+ }
+
+ /* First decide if this window should be displayed at all. */
+ d = 1;
+ if (wdata->order == WLIST_NUM || wdata->order == WLIST_MRU)
+ {
+ if (p->w_group != wdata->group)
+ {
+ if (!wdata->nested)
+ d = 0;
+ else
+ {
+ struct win *g = p->w_group;
+ for (; g; g = g->w_group)
+ if (g->w_group == wdata->group)
+ break;
+ if (!g)
+ d = 0;
+ }
+ }
+ }
+
+ if (!d)
+ {
+ if (gl_Window_remove(ldata, p))
+ glist_display_all(ldata);
+ return;
+ }
+
+ /* OK, so we keep the window in the list. Update the ordering.
+ * First, find the row where this window should go to. Then, either create
+ * a new row for that window, or move the exising row for the window to the
+ * correct place. */
+ before = NULL;
+ if (wdata->order == WLIST_MRU)
+ {
+ if (windows != p)
+ for (before = windows; before; before = before->w_next)
+ if (before->w_next == p)
+ break;
+ }
+ else if (wdata->order == WLIST_NUM)
+ {
+ if (p->w_number != 0)
+ {
+ struct win **w = wtab + p->w_number - 1;
+ for (; w >= wtab; w--)
+ {
+ if (*w && (*w)->w_group == wdata->group)
+ {
+ before = *w;
+ break;
+ }
+ }
+ }
+ }
+
+ if (wdata->nested && before == NULL)
+ {
+ /* TODO: insert after the parent */
+#warning Fix me
+ }
+
+ /* Now, find the row belonging to 'before' */
+ if (before)
+ rbefore = gl_Window_findrow(ldata, before);
+ else
+ rbefore = NULL;
+
+ /* For now, just remove the row containing 'p'. */
+ gl_Window_remove(ldata, p);
+ glist_add_row(ldata, p, rbefore);
+ glist_display_all(ldata);
+}
+
+void
+WListUpdatecv(cv, p)
+struct canvas *cv;
+struct win *p;
+{
+ struct ListData *ldata;
+ struct gl_Window_Data *wdata;
+
+ if (cv->c_layer->l_layfn != &ListLf)
+ return;
+ ldata = cv->c_layer->l_data;
+ if (ldata->name != ListID)
+ return;
+ wdata = ldata->data;
+ CV_CALL(cv, WListUpdate(p, ldata));
+}
+
+void
+WListLinkChanged()
+{
+ struct display *olddisplay = display;
+ struct canvas *cv;
+ struct ListData *ldata;
+ struct gl_Window_Data *wdata;
+
+ for (display = displays; display; display = display->d_next)
+ for (cv = D_cvlist; cv; cv = cv->c_next)
+ {
+ if (!cv->c_layer || cv->c_layer->l_layfn != &ListLf)
+ continue;
+ ldata = cv->c_layer->l_data;
+ if (ldata->name != ListID)
+ continue;
+ wdata = ldata->data;
+ if (!(wdata->order & WLIST_MRU))
+ continue;
+ CV_CALL(cv, WListUpdate(0, ldata));
+ }
+ display = olddisplay;
+}
+