static char rcsid[] = "@(#)$Id: context.c,v 1.10 2006/04/09 07:37:37 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.10 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
*****************************************************************************/
#include "def_screen.h"
DEBUG_VAR(Debug,__FILE__,"screen");
struct menu_context ROOT_MENU = {
MENU_CONTEXT_magic,
&CURSES_ROUTINES, /* menu_draw_routine */
NULL, NULL, /* subpages, container */
0,0, /* lines, columns */
0,0, /* changed, redraw */
0, /* modes */
0,0, /* row,col */
NULL, /* dummy */
NULL /* prev */,
NULL /* next */
};
struct menu_context COOKED_MENU = {
MENU_CONTEXT_magic,
&CURSES_ROUTINES, /* menu_draw_routine */
NULL, NULL, /* subpages, container */
0,0, /* lines, columns */
0,0, /* changed, redraw */
0, /* modes */
0,0, /* row,col */
NULL, /* dummy */
NULL /* prev */,
NULL /* next */
};
struct menu_context * default_context = &COOKED_MENU;
struct menu_context * new_menu_type(T)
struct menu_draw_routine *T;
{
struct menu_context *ret = safe_malloc(sizeof (*ret));
if (MENU_DRAW_magic != T->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"new_menu_type",
"Bad routine magic number",0);
/* bzero is defined hdrs/defs.h */
bzero((void *)ret,sizeof (*ret));
ret->magic = MENU_CONTEXT_magic;
ret->routine = T;
ret->subpages = NULL;
ret->container = NULL;
ret->lines = 0;
ret->columns = 0;
ret->changed = 0;
ret->redraw = 0;
ret->modes = 0;
ret->row = 0;
ret->col = 0;
ret->u.dummy = NULL;
T->wra_init(ret);
return ret;
}
struct menu_context * new_menu_context()
{
struct menu_context *ret = new_menu_type(&CURSES_ROUTINES);
/* Take data from root menu */
ret->lines = ROOT_MENU.lines;
ret->columns = ROOT_MENU.columns;
ret->changed = ROOT_MENU.changed;
ret->redraw = ROOT_MENU.redraw;
ret->modes = ROOT_MENU.modes;
ret->row = ROOT_MENU.row;
ret->col = ROOT_MENU.col;
/* chain to list */
ret->next_menu = ROOT_MENU.next_menu;
ROOT_MENU.next_menu = ret;
ret->prev_menu = &ROOT_MENU;
if (ret->next_menu)
ret->next_menu->prev_menu = ret;
if (default_context == &COOKED_MENU) {
DPRINT(Debug,1, (&Debug,
"new_menu_context: On COOKED MENU, not changing default context\n"));
} else {
default_context = ret;
DPRINT(Debug,9, (&Debug,
"new_menu_context: default context to %p\n",
default_context));
Syncronize(default_context);
}
return ret;
}
void erase_menu_context(ptr)
struct menu_context **ptr;
{
struct menu_subpages *list, *next = NULL;
if ((*ptr)->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"Bad type magic number",0);
if (&ROOT_MENU == *ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"attempt to erase root menu",0);
if (&COOKED_MENU == *ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"attempt to erase cooked menu",0);
if (MENU_DRAW_magic != (*ptr)->routine->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"Bad routine magic number",0);
EndSyncronize(*ptr);
if ((*ptr)->container)
detach_subpage(*ptr);
if ((*ptr)->subpages) {
DPRINT(Debug,1, (&Debug,
"erase_menu_context: %p: WARNING: subpages not erased / detached\n",
*ptr));
for (list = (*ptr)->subpages; list; list = next) {
if (MENU_CONTAINER_magic != list->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"Bad subpage type magic number",0);
if (list->parent != *ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"Bad parent pointer on subpage",0);
next = list->next;
if (list->subpage) {
if (list != list->subpage->container)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"Bad container pointer on subpage",0);
/* Reset congtainer pointer so that erase menu
content do not call detach_subpage()
*/
list->subpage->container = NULL;
erase_menu_context( & (list->subpage) );
}
list->prev = NULL;
list->next = NULL;
list->magic = 0; /* Invalidate */
free(list);
}
(*ptr)->subpages = NULL;
}
if (default_context == (*ptr)) {
default_context = (*ptr)->prev_menu;
DPRINT(Debug,9, (&Debug,
"erase_menu_context: default context to %p\n",
default_context));
}
if (!default_context)
panic("SCREEN PANIC",__FILE__,__LINE__,"erase_menu_context",
"no default content",0);
Syncronize(default_context);
if ((*ptr)->next_menu)
(*ptr)->next_menu->prev_menu = (*ptr)->prev_menu;
if ((*ptr)->prev_menu)
(*ptr)->prev_menu->next_menu = (*ptr)->next_menu;
(*ptr)->routine->wra_free(*ptr);
if ((*ptr)->u.dummy) {
DPRINT(Debug,1, (&Debug,
"erase_menu_context: Data not free'ed\n"));
}
(*ptr)->magic = 0; /* Invalidate */
free(*ptr);
*ptr = NULL;
}
void attach_subpage(parent,subpage, first_line, last_line)
struct menu_context *parent;
struct menu_context *subpage;
/* absolute screen cordinates */
int first_line, last_line;
{
struct menu_subpages * X;
if (MENU_CONTEXT_magic != parent->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"attach_subpage",
"Bad parent type magic number",0);
if (MENU_CONTEXT_magic != subpage->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"attach_subpage",
"Bad subpage type magic number",0);
X = safe_malloc(sizeof (*X));
/* bzero is defined hdrs/defs.h */
bzero((void *)X,sizeof (*X));
X->magic = MENU_CONTAINER_magic;
X->location.first_line = first_line;
X->location.last_line = last_line;
X->location.gone_out = 0;
subpage->lines = last_line - first_line + 1;
subpage->columns = parent->columns;
subpage->redraw = 1;
subpage->container = X;
X->subpage = subpage;
X->parent = parent;
X->next = parent->subpages;
X->prev = NULL;
if (parent->subpages) {
if (parent->subpages->prev)
panic("SCREEN PANIC",__FILE__,__LINE__,"attach_subpage",
"parent's subpage list do not point to first item",0);
parent->subpages->prev = X;
}
parent->subpages = X;
}
extern void detach_subpage(subpage)
struct menu_context *subpage;
{
if (MENU_CONTEXT_magic != subpage->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad subpage type magic number",0);
if (MENU_CONTAINER_magic != subpage->container->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad container type magic number",0);
if (MENU_CONTEXT_magic != subpage->container->parent->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad parent type magic number",0);
if (subpage->container->subpage != subpage)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad subpage of container",0);
/* Remove from list */
if (subpage->container->prev) {
if (subpage->container != subpage->container->prev->next)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad prev of container",0);
subpage->container->prev->next = subpage->container->next;
} else {
if (subpage->container != subpage->container->parent->subpages)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad subpages of parent",0);
subpage->container->parent->subpages = subpage->container->next;
}
if (subpage->container->next) {
if (subpage->container != subpage->container->next->prev)
panic("SCREEN PANIC",__FILE__,__LINE__,"detach_subpage",
"Bad next of container",0);
subpage->container->next->prev = subpage->container->prev;
}
subpage->container->subpage = NULL;
subpage->container->magic = 0; /* Invalidate */
free(subpage->container);
subpage->container = NULL;
}
static struct menu_context * get_root_menu P_((struct menu_context *ptr,
int *pending_redraw));
static struct menu_context * get_root_menu(ptr,pending_redraw)
struct menu_context *ptr;
int *pending_redraw;
{
struct menu_context *pptr = ptr;
while (pptr->container) {
if (MENU_CONTAINER_magic != pptr->container->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"get_root_menu",
"Bad subpage container type magic number",0);
pptr = pptr->container->parent;
if (pptr->redraw)
(*pending_redraw) ++;
if (pptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"get_root_menu",
"Bad parent type magic number",0);
}
if (pptr != default_context) {
DPRINT(Debug,7, (&Debug,
"get_root_menu(%p): root %p is not default context %p\n",
ptr,pptr,default_context));
}
return pptr;
}
int menu_resized(ptr)
struct menu_context *ptr;
{
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_resized",
"Bad type magic number",0);
check_changes();
if (ptr->changed) {
struct menu_subpages *list, *next = NULL;
if (MENU_DRAW_magic != ptr->routine->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_resized",
"Bad routine magic number",0);
ptr->routine->wra_resized(ptr);
/* Turn changed flag for subpages ... */
for (list = ptr->subpages; list; list = list->next) {
if (MENU_CONTAINER_magic != list->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_resized",
"Bad subpage container type magic number",0);
if (list->parent != ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_resized",
"Bad parent pointer on subpage",0);
if (list->subpage) {
if (MENU_CONTEXT_magic != list->subpage->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_resized",
"Bad subpage type magic number",0);
list->subpage->changed = 1;
}
}
return 1;
}
return 0;
}
void menu_get_sizes(ptr,lines,columns)
struct menu_context *ptr;
int *lines;
int *columns;
{
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_get_sizes",
"Bad type magic number",0);
*lines = ptr->lines;
*columns = ptr->columns;
}
int menu_need_redraw(ptr)
struct menu_context *ptr;
{
struct menu_context *pptr;
int pending_redraw = 0;
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_need_redraw",
"Bad type magic number",0);
check_changes();
/* Check parents */
pptr = get_root_menu(ptr,&pending_redraw);
if (pending_redraw) {
DPRINT(Debug,7, (&Debug,
"menu_need_redraw(%p): pending redraw on parent\n",
ptr));
ptr->redraw = 1;
}
if (pptr->routine != &CURSES_ROUTINES) {
DPRINT(Debug,1, (&Debug,
"menu_need_redraw(%p): ERROR -- parent %p not main manu (not connected) -- quiting%s\n",
ptr,pptr,
ptr->redraw ? " (returning redraw)": ""));
return ptr->redraw;
}
if (pptr != default_context) {
DPRINT(Debug,9, (&Debug,
"menu_need_redraw: default context to %p (redraw needed)\n",
pptr));
default_context = pptr;
Syncronize(default_context);
pptr->redraw = 1;
ptr->redraw = 1;
}
if (ptr->redraw) {
struct menu_subpages *list;
int r;
if (MENU_DRAW_magic != ptr->routine->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_need_redraw",
"Bad routine magic number",0);
/* Reset ptr->redraw .... */
ptr->routine->wra_reset_redraw(ptr);
/* Turn redraw flag for subpages ... */
for (list = ptr->subpages; list; list = list->next) {
if (MENU_CONTAINER_magic != list->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_need_redraw",
"Bad subpage container type magic number",0);
if (list->parent != ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_need_redraw",
"Bad parent pointer on subpage",0);
if (list->subpage)
menu_trigger_redraw(list->subpage);
}
r = ptr->routine->wra_do_redraw(ptr);
if (r) {
DPRINT(Debug,7, (&Debug,
"menu_need_redraw(%p): redraw done\n", ptr));
} else {
DPRINT(Debug,7, (&Debug,
"menu_need_redraw(%p): returning redraw\n",
ptr));
return 1;
}
}
return 0;
}
/* Call refresh routines of children */
void menu_redraw_children(ptr)
struct menu_context *ptr;
{
struct menu_subpages *list;
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_redraw_children",
"Bad type magic number",0);
for (list = ptr->subpages; list; list = list->next) {
if (MENU_CONTAINER_magic != list->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_redraw_children",
"Bad subpage container type magic number",0);
if (list->parent != ptr)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_redraw_children",
"Bad parent pointer on subpage",0);
if (list->subpage) {
struct menu_context *ptr1 = list->subpage;
int r;
if (ptr1->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_redraw_children",
"Bad type magic number",0);
if (MENU_DRAW_magic != ptr1->routine->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_redraw_children",
"Bad routine magic number",0);
r = ptr1->routine->wra_do_redraw(ptr1);
if (r) {
DPRINT(Debug,7, (&Debug,
"menu_redraw_children(%p): %p: redraw done\n",
ptr,ptr1));
} else
ptr1->redraw = 1;
}
}
}
void menu_trigger_redraw(ptr)
struct menu_context *ptr;
{
struct menu_context *pptr;
int pending_redraw = 0;
int r;
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_trigger_redraw",
"Bad type magic number",0);
DPRINT(Debug,7, (&Debug,
"menu_trigger_redraw(%p): triggering redraw\n",
ptr));
if (MENU_DRAW_magic != ptr->routine->magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"menu_trigger_redraw",
"Bad routine magic number",0);
/* Check parents */
pptr = get_root_menu(ptr,&pending_redraw);
if (pptr == default_context) {
/* Is active */
if (pending_redraw) {
DPRINT(Debug,7, (&Debug,
"menu_trigger_redraw(%p): pending redraw on parent\n",
ptr));
ptr->redraw = 1;
} else {
r = ptr->routine->wra_do_redraw(ptr);
if (r) {
DPRINT(Debug,7, (&Debug,
"menu_trigger_redraw(%p): redraw done\n",
ptr));
} else
ptr->redraw = 1;
}
} else {
DPRINT(Debug,7, (&Debug,
"menu_trigger_redraw(%p): parent %p not active\n",
ptr,pptr));
ptr->redraw = 1;
}
}
static VOLATILE int resize_screen = 0; /** SIGWINCH occured? **/
static VOLATILE int redraw_screen = 0; /** Elm suspended? **/
/* called from signal handler */
void menu_context_resize()
{
resize_screen = 1;
redraw_screen = 1;
ROOT_MENU.changed = 1; /* Indicate that ROOT_MENU is invalid
not really needed */
}
/* called from signal handler */
void menu_context_redraw()
{
redraw_screen = 1;
ROOT_MENU.redraw = 1; /* not really needed */
}
void set_root_menu(lines,columns)
int lines;
int columns;
{
int size = 0;
if (lines != ROOT_MENU.lines &&
-1 != lines) {
ROOT_MENU.lines = lines;
COOKED_MENU.lines = lines;
size ++;
}
if (columns != ROOT_MENU.columns &&
-1 != columns) {
ROOT_MENU.columns = columns;
COOKED_MENU.columns = columns;
size++;
}
if (size) {
struct menu_context *ptr;
for (ptr = ROOT_MENU.next_menu; ptr; ptr = ptr->next_menu) {
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"set_root_menu",
"Bad type magic number",0);
ptr->changed = 1;
}
}
}
void check_changes()
{
if (resize_screen || redraw_screen) {
int size = resize_screen;
int draw = redraw_screen;
struct menu_context *ptr;
int lines, columns;
resize_screen = 0;
redraw_screen = 0;
/* Real lines .. not lines-1 !!! */
cur_ScreenSize(&lines,&columns);
if (lines > 0 && columns > 0) {
/* Check that is size changed when
Elm ME+ was suspended
*/
if (lines != ROOT_MENU.lines ||
columns != ROOT_MENU.columns)
size++;
ROOT_MENU.lines = lines;
ROOT_MENU.columns = columns;
ROOT_MENU.changed = 0; /* Values valid */
COOKED_MENU.lines = lines;
COOKED_MENU.columns = columns;
} else {
DPRINT(Debug,1, (&Debug,
"check_changes: cur_ScreenSize returned bad sizes: lines=%d columns=%d\n",
lines,columns));
}
if (size && default_context == &COOKED_MENU)
COOKED_MENU.changed = 1;
ROOT_MENU.redraw = draw; /* ? ? ? */
if (draw && default_context == &COOKED_MENU)
COOKED_MENU.redraw = 1;
for (ptr = ROOT_MENU.next_menu; ptr; ptr = ptr->next_menu) {
if (ptr->magic != MENU_CONTEXT_magic)
panic("SCREEN PANIC",__FILE__,__LINE__,"check_changes",
"Bad type magic number",0);
if (size)
ptr->changed = 1;
if (draw)
ptr->redraw = 1;
}
}
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1