static char rcsid[] = "@(#)$Id: scommon.c,v 1.7 2006/04/09 07:37:37 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.7 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *****************************************************************************/

#include "def_screen.h"
#include "def_scommon.h"

DEBUG_VAR(Debug,__FILE__,"screen");

#define MENU_SCOMMON_magic      0xF805

void scommon_zero(c)
     struct subpage_common *c;
{

     c->magic          = MENU_SCOMMON_magic;
     c->rel_start_line = 0;
     c->param_ptr      = NULL;
}

void scommon_clear(c)
     struct subpage_common *c;
{
     c->magic           = 0;    /* Invalidate */
}

void calculate_printing_area(ctx)
     struct menu_context *ctx;
{
    struct menu_context *parent;
    int startline = 0;
    int endline;

    int S, E;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"calculate_printing_area",
	      "Bad container magic number",0);
	      
    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"calculate_printing_area",
	      "Bad parent draw magic number",0);
    
    /* Need to calculate absolute from relative position */
    
    parent->routine->wra_calculate_line(parent,
					ctx->u.common->rel_start_line,
					&startline);

    endline = startline + ctx->lines -1;

    parent->routine->wra_get_linelimit(parent,&S,&E);

    if (startline < S)
	startline = S;
    if (endline > E)
	endline = E;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"calculate_printing_area",
	      "Bad container magic number",0);

    ctx->container->location.first_line  = startline;
    ctx->container->location.last_line   = endline; 

    DPRINT(Debug,11, (&Debug, 
		      "calculate_printing_area(%p): startline=%d endline=%d\n",
		      ctx,startline,endline));
}

void scommon_Writechar(ctx,ch)
     struct menu_context * ctx; 
     int ch;
{
    int remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_Writechar",
	      "Bad container magic number",0);
	
    DPRINT(Debug,11, (&Debug, "scommon_Writechar(%p,%d)\n",ctx,ch));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     

    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */
    
    cur_MoveCursor(ctx->row, ctx->col,& (ctx->container->location));   /* syncronize position */
    if (ctx->container->location.gone_out)
	return;                                                        /* Not in drawing area */

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);

    cur_Writechar(ch, & (ctx->container->location));

    cur_GetXYLocation(& ctx->row,& ctx->col);
}

void scommon_PutLineS(ctx,text)
     struct menu_context * ctx;
     struct string *text;
{
    int remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLineS",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_putlineS(%p,\"%S\")\n",ctx,text));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
	
    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */
    
    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));   /* syncronize position */
    if (ctx->container->location.gone_out)
	return;                                                        /* Not in drawing area */

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);

    cur_PutLineS(text, & (ctx->container->location));      

    cur_GetXYLocation(& ctx->row,& ctx->col);
}

void scommon_PutLine0(ctx,row,col,line)
     struct menu_context * ctx;
     int row; 
     int col;
     CONST char *line;
{
    int rline, remove;
    struct menu_context * parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLine0",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_Putline0(%p,%d,%d,\"%s\")\n",
		      ctx,row,col,line));

	      
    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLine0",
	      "Bad parent draw magic number",0);
        
    if (MENU_SCOMMON_magic != ctx->u.common->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLine0",
	      "Bad subpage magic number",0);

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
    
    /* Need to calculate absolute from relative position */
    
    parent->routine->wra_calculate_line(parent,
					ctx->u.common->rel_start_line + row,
					&rline);
    ctx->row = rline;
    ctx->col = col;

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);

    
    cur_PutLine0(rline,col,line, & (ctx->container->location));
    
    cur_GetXYLocation(& ctx->row,& ctx->col);
}

void scommon_CleartoEOLN(ctx)
     struct menu_context * ctx;
{
    int remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLineS",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_CleartoEOLN(%p)\n",ctx));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
	
    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */
    
    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));   /* syncronize position */
    if (ctx->container->location.gone_out)
	return;                                                        /* Not in drawing area */

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);

    cur_CleartoEOLN();

    /* CleartoEOLN do not move cursor ... */
}
	
void scommon_CleartoEOS(ctx)
     struct menu_context * ctx;
{
    int row, remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_PutLineS",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_CleartoEOS(%p)\n",ctx));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
	
    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */
    
    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));   /* syncronize position */
    if (ctx->container->location.gone_out)
	return;                                                        /* Not in drawing area */

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);


    /* Cant use cur_CleartoEOS() -- clear rest of current line*/
    cur_CleartoEOLN();

    /* clear rest of lines */
    for (row = ctx->row+1; row <= ctx->container->location.last_line; row++) {
	cur_MoveCursor(row,0, & (ctx->container->location));   /* syncronize position */
	cur_CleartoEOLN();
    }

    /* CleartoEOS do not move cursor ... */
}

struct charset_state * scommon_ReadCh2(ctx,flags,break_flag)
     struct menu_context *ctx;
     int flags;
     int break_flag;
{
    int remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_ReadCh2",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_ReadCh2(%p,%d,%d)\n",ctx,flags,break_flag));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
	
    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */
    
    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));   /* syncronize position */
    
    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);


    return cur_ReadCh2(flags,break_flag);
}


void scommon_ScreenSize(ctx,lines,columns)
     struct menu_context *ctx;
     int *lines; 
     int *columns;
{

    DPRINT(Debug,11, (&Debug, "scommon_ScreenSize(%p,%p,%p)\n",
		      ctx,lines,columns));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     

    /* ? ? ? */

    *lines   = ctx->lines;
    *columns = ctx->columns;
}
				
void scommon_GetXYLocation(ctx,row,col)
     struct menu_context *ctx;
     int *row; 
     int *col;
{
    struct menu_context * parent;
    int diff;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_GetXYLocation",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_getXYLocation(%p,%p,%p)\n",
		      ctx,row,col));
	      
    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_GetXYLocation",
	      "Bad parent draw magic number",0);
        
    if (MENU_SCOMMON_magic != ctx->u.common->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_GetXYLocation",
	      "Bad subpage magic number",0);
    
    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     

    /* Need to calculate absolute from relative position */
    
    parent->routine->wra_calculate_line(parent,
					ctx->u.common->rel_start_line,
					&diff);

    /* NOTE:   ctx->row, col are absolute  

              therefore needs to call cur_   routines, not
	      parents  routines   for draw
    */


    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));   /* syncronize position */

    *col = ctx->col;
    *row = ctx->row - diff;
}

void scommon_ClearScreen(ctx)
     struct menu_context *ctx;
{
    int row, remove;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_ClearScreen",
	      "Bad container magic number",0);
    
    DPRINT(Debug,11, (&Debug, "scommon_ClearScreen(%p)\n"));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     

    /* cur_ClearScreen() reset redraw flag ... we simulate it also on here */
    ctx->redraw = 0;

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);


    /* clear lines */
    for (row = ctx->container->location.first_line; 
	 row <= ctx->container->location.last_line; 
	 row++) {
	cur_MoveCursor(row, 0, & (ctx->container->location));   /* syncronize position */
	cur_CleartoEOLN();
    }

    /* ClearScreen do not move cursor ... */
}

void scommon_MoveCursor(ctx,row,col)
     struct menu_context *ctx;
     int row; 
     int col;
{
    int rline;
    struct menu_context * parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_MoveCursor",
	      "Bad container magic number",0);
	      
    DPRINT(Debug,11, (&Debug, "scommon_MoveCursor(%p,%d,%d)\n",
		      ctx,row,col));

    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_MoveCursor",
	      "Bad parent draw magic number",0);
        
    if (MENU_SCOMMON_magic != ctx->u.common->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_MoveCursor",
	      "Bad subpage magic number",0);

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     
    
    /* Need to calculate absolute from relative position */
    
    parent->routine->wra_calculate_line(parent,
					ctx->u.common->rel_start_line + row,
					&rline);
    ctx->row = rline;
    ctx->col = col;

    cur_MoveCursor(rline, col, & (ctx->container->location));
}

void scommon_changemode(ctx,start,end)
     struct menu_context *ctx;
     int start; 
     int end;
{
    int remove;

    DPRINT(Debug,11, (&Debug, "scommon_changemode(%p,%d,%d)\n",
		      ctx,start,end));

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    remove &= ~start;
    cur_changemode(&CUR_modes,ctx->modes, remove);

    cur_changemode(&ctx->modes, start, end);

    CUR_modes = ctx->modes;
}

void scommon_SyncEnter(ctx)
     struct menu_context *ctx;
{
    int remove;

    DPRINT(Debug,10, (&Debug, 
		      "scommon_SyncEnter: %p: Setting mode=0x%02x row=%d col=%d\n",
		      ctx,ctx->modes,ctx->row,ctx->col));

    /* recalculate ctx->container->location */
    if (ROOT_MENU.changed || ctx->changed)
	calculate_printing_area(ctx);     

    /* Fix modes */
    remove = CUR_modes & ~(ctx->modes);
    cur_changemode(&CUR_modes,ctx->modes, remove);

    /* Move cursor */
    cur_MoveCursor(ctx->row,ctx->col, & (ctx->container->location));
}

void scommon_SyncLeave(ctx)
     struct menu_context *ctx;
{
    /* disable attributes */
    cur_changemode(&CUR_modes,0,ctx->modes);

    /* Remember cursor location */

    cur_GetXYLocation(&ctx->row, &ctx->col);

    DPRINT(Debug,10, (&Debug, 
		      "scommon_SyncLeave: %p: mode=0x%02x row=%d col=%d\n",
		      ctx,ctx->modes,ctx->row,ctx->col));

}

void scommon_resized(ctx)
     struct menu_context *ctx;
{
    struct menu_context *parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_resized",
	      "Bad container magic number",0);
	      
    DPRINT(Debug,11, (&Debug, "scommon_resized(%p)\n",ctx));

    parent = ctx->container->parent;

    /* FIX:   resizing of lines not supported */

    ctx->columns    = parent->columns;
    ctx->changed    = parent->changed;   /* ? ? ? ? */

    calculate_printing_area(ctx);
}

void scommon_calculate_line(ctx,rel_line,result)
     struct menu_context *ctx;
     int rel_line; 
     int *result;
{
    struct menu_context * parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_calculate_line",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_calculate_line(%p,%d,%p)\n",
		      ctx,rel_line,result));
	      
    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_calculate_line",
	      "Bad parent draw magic number",0);
        
    if (MENU_SCOMMON_magic != ctx->u.common->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_calculate_line",
	      "Bad subpage magic number",0);
    
    /* Need to calculate absolute from relative position */
    
    parent->routine->wra_calculate_line(parent,
					ctx->u.common->rel_start_line + rel_line,
					result);
}

void scommon_get_linelimit(ctx,startline,endline)
     struct menu_context *ctx;
     int *startline; 
     int *endline;
{
    int S, E;
    struct menu_context * parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_get_linelimit",
	      "Bad container magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_get_linelimit(%p,%p,%p)\n",
		      ctx,startline,endline));

    *startline = ctx->container->location.first_line;
    *endline   = ctx->container->location.last_line;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_get_linelimit",
	      "Bad container magic number",0);
	      
    parent = ctx->container->parent;
    
    if (MENU_DRAW_magic  != parent->routine->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_get_linelimit",
	      "Bad parent draw magic number",0);
    
    parent->routine->wra_get_linelimit(parent,&S,&E);

    if (*startline < S)
	*startline = S;

    if (*endline > E)
	*endline = E;
}

/* called by need_redraw() */
void scommon_reset_redraw(ctx)
     struct menu_context *ctx;
{
    struct menu_context *parent;

    if (MENU_CONTAINER_magic != ctx->container->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_reset_redraw",
	      "Bad container magic number",0);
	      
    DPRINT(Debug,11, (&Debug, "scommon_reset_redraw(%p)\n",
		      ctx));

    parent = ctx->container->parent;

    ctx->redraw    = parent->redraw;   /* ? ? ? ? */
}


void scommon_relocate(subpage,parent,rel_start_line,lines)
     struct menu_context  *subpage;
     struct menu_context  *parent;
     int rel_start_line;
     int lines;
{
    if (MENU_CONTEXT_magic != subpage->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_relocate",
	      "Bad subpage magic number",0);

	
    if (MENU_SCOMMON_magic != subpage->u.common->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_relocate",
	      "Bad subpage magic number",0);

    if (MENU_CONTEXT_magic != parent->magic)
	panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_relocate",
	      "Bad parent magic number",0);

    DPRINT(Debug,11, (&Debug, "scommon_relocate(%p,%p,%d,%d)\n",
		      subpage,parent,rel_start_line,lines));
        
    subpage->lines                = lines;
    subpage->columns              = parent->columns;
    subpage->u.common->rel_start_line = rel_start_line;
    
    if (subpage->container) {
	if (MENU_CONTAINER_magic != subpage->container->magic)
	    panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_relocate",
		  "Bad container magic number",0);

	if (parent != subpage->container->parent) {
	    detach_subpage(subpage);
	    goto attach_new;
	}


    } else {
	int rline, lline;

    attach_new:

	if (MENU_DRAW_magic  != parent->routine->magic)
	    panic("SCREEN PANIC",__FILE__,__LINE__,"scommon_relocate",
		  "Bad parent draw magic number",0);


	parent->routine->wra_calculate_line(parent,rel_start_line,&rline);

	lline = rline + lines -1;    /* calculate_printing_area() fixes */
	
	attach_subpage(parent,subpage,rline,lline);
    }

    calculate_printing_area(subpage);
}

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1