/* This file is part of the Project Athena Zephyr Notification System.
 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
 * $Source: /mit/zephyr/src/zwgc/RCS/eval_show.c,v $
 * $Author: eichin $
 *
 *	Copyright (c) 1988 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */
#include <zephyr/mit-copyright.h>
#ifndef lint
static char rcsid[] = "$Header: eval_show.c,v 2.4 88/07/06 16:15:28 eichin Exp $";
#endif lint

#include "ropes.h"
#include "support.h"
#include "comp_types.h"
#include "draw.h"
  
/*
 * fnt stacks
 */
  
#define MRSTK 128
typedef struct _stk
{
  int fnt;
  int sid;
  int isnil;
} stk;

stk stkstack[MRSTK];
int stksptr;			/* initialize to 0 */

init_stkstack()
{
  stksptr = 0;
}

push_stk(md)
     stk md;
{
  /*
   * save the stk handed here onto top of a stack...
   */
  stkstack[stksptr++] = md;
  if(stksptr >= MRSTK)
    {
      printf("zwgc:eval_show font Stack Overfull, squishing...\n");
      stksptr --;
    }
}

int pop_stk()
{
  /*
   * grab the *NEXT* one down to restore from...
   */
  if(stksptr > 1)
    {
      return(stkstack[--stksptr].isnil);
    }
  printf("zwgc:eval_show font Stack Empty, reusing...\n");
  return(FALSE);
}

set_to_stk(d,stt)
     Draw d;
     stk *stt;
{
  xtx_setfont(d, stt->fnt = stkstack[stksptr-1].fnt);
  xtx_setside(d, stt->sid = stkstack[stksptr-1].sid);
}

rope *rope_stack[MRSTK];
int rope_sptr;

void init_ropestack()
{
  rope_sptr = 0;
}

void push_rope(rp)
     rope	*rp;
{
  rope_stack[rope_sptr++] = rp;
  if(rope_sptr >= MRSTK)
    {
      printf("zwgc:eval_show rope Stack Overfull, squishing...\n");
      rope_sptr --;
    }
}
rope *pop_rope()
{
  if(rope_sptr > 0)
    {
      return(rope_stack[--rope_sptr]);
    }
  return(NULL);			/* indicate lack of rope */
}
  
  
/*
 * eval_show(rope *)
 *
 * have fun!
 */
#define NOCURRENTMODE (-99)
rope *rblankmsg;

Window eval_show(rp)
     rope	*rp;
{
  Draw d;
  stk tmpstk;
  int lastfnt = ((int)SHOW_NORMAL-SHOW_BOLD);
  int lastsid = LEFT;

  xtx_draw_init(FALSE);
  init_stkstack();
  init_ropestack();
  
  d = xtx_newdraw();

  tmpstk.fnt = lastfnt;
  tmpstk.sid = lastsid;
  tmpstk.isnil = FALSE;
  push_stk(tmpstk);		/* bufferzone */
  set_to_stk(d,&tmpstk);
  
  lastfnt=lastsid=NOCURRENTMODE;
  
  while(rp->typ != END || (rp=pop_rope()))
    {
      if(rp->typ == END)	/* only from pop_rope... */
	{
	  continue;
	}
      if(rp->typ == NEXT)
	{
	  rp = rp->ind.next;
	  continue;
	}
      switch(rp->typ)
	{
	case RAW:
	  if(raw_table[rp->ind.ex][0]=='\n')
	    {
	      xtx_breakline(d);
	    }
	  else if(is_left(raw_table[rp->ind.ex][0]))
	    {
	      if(NOCURRENTMODE != lastfnt)
		{
		  tmpstk.fnt = lastfnt;
		  push_stk(tmpstk);
		  set_to_stk(d,&tmpstk);
		  lastfnt = NOCURRENTMODE;
		}
	      else if (NOCURRENTMODE != lastsid)
		{
		  tmpstk.sid = lastsid;
		  push_stk(tmpstk);
		  set_to_stk(d,&tmpstk);
		  lastsid = NOCURRENTMODE;
		}
	      else
		{
		  tmpstk.isnil = TRUE;
		  push_stk(tmpstk);
		  xtx_drawtext(d, raw_table[rp->ind.ex]);
		  tmpstk.isnil = FALSE;
		}
	    }
	  else if(is_right(raw_table[rp->ind.ex][0]))
	    {
	      if(pop_stk())
		{
		  xtx_drawtext(d, raw_table[rp->ind.ex]);
		}
	      set_to_stk(d,&tmpstk);
	    }
	  else
	    {
	      xtx_drawtext(d, raw_table[rp->ind.ex]);
	    }
	  break;
	case FIELD:
	  xtx_drawtext(d, strand_field[rp->ind.ex]);
	  break;
	case HEAD:
	  xtx_drawtext(d, strand_head[rp->ind.ex]);
	  break;
	case VAR:
	  /* xtx_drawtext(d, strand_var[rp->ind.ex]); */
	  if(varropes[rp->ind.ex])
	    {
	      push_rope(rp+1);
	      rp = varropes[rp->ind.ex]-1; /* for rp++ at end... */
	    }
	  else			/* unset variable, so... */
	    {
	      xtx_drawtext(d, variables[rp->ind.ex]);
	    }
	  break;
	case ROPE:
	  push_rope(rp+1);
	  rp = rp->ind.next-1;	/* for rp++ at end... */
	  break;
	case SHOW:
	  switch(rp->ind.ex)
	    {
	    case SHOW_LEFT:
	      lastsid = LEFT;
	      break;
	    case SHOW_RIGHT:
	      lastsid = RIGHT;
	      break;
	    case SHOW_CENTER:
	      lastsid = CENTER;
	      break;
	    case SHOW_BOLD:
	    case SHOW_ITALIC:
	    case SHOW_NORMAL:
	    case SHOW_FONT0:
	    case SHOW_FONT1:
	    case SHOW_FONT2:
	    case SHOW_FONT3:
	    case SHOW_FONT4:
	    case SHOW_FONT5:
	    case SHOW_FONT6:
	    case SHOW_FONT7:
	    case SHOW_FONT8:
	    case SHOW_FONT9:
	      lastfnt =  rp->ind.ex-((int)SHOW_BOLD);
	      break;
	    }
	  break;
	default:
	  break;
	}
      rp++;
    }
  {
    Window w;
    w = xtx_postdraw(d);
    if(!w)
      {
	/*
	 * something is wrong, and the window didn't appear.
	 * cursid is used to pass back a signal:
	 * 	-1: pixmap error [don't retry]
	 * 	-2: description error [retry]
	 */
	switch(d->cursid)
	  {
	  case -1:
	    printf("zwgc:eval_show Pixmap creation failed. Message lost.\n");
	    break;
	  case -2:
	    /* Put in some recursion protection here !!! */
	    new_eval(rblankmsg, FALSE);
	    break;
	  default:
	    printf("zwgc:eval_show Unknown error from xtx_postdraw(%d) (ignoring\n",d->cursid);
	    break;
	  }
      }
    else
      {
	/* XSelectInput(dpy, w, ButtonPressMask);  move this to draw.c */
      }
    xtx_dispose_draw(d);
    return(w);
  }
}
