/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */
/*****************************************************************
 ***                                                           ***
 ***              Managing Resources                           ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_RESOURCEGET_C_
#include "EZ_Widget.h"
#include <ctype.h>

/*****************************************************************/
void  EZ_GetAndUseWidgetResources   MY_ANSIARGS((EZ_Widget *widget));
/****************************************************************/
static void  EZ_GetSetWidgetResources   MY_ANSIARGS((EZ_Widget *widget, int lev));
static void  EZ_GetSetWidgetResourcesWork   MY_ANSIARGS((EZ_Widget *widget));
/****************************************************************/
typedef struct lex_unit_
{	
  int  type;    
  char *start;
  int  length; 
  union { int i; float  f; } v;
} lex_unit;

#define  STR_CST   0
#define  INT_CST   1
#define  FLOAT_CST 2
static lex_unit tokens[128];
/****************************************************************/
static int scan_number MY_ANSIARGS((char *str, int tidx));
static int  parseString(str_) char *str_;
{
  register int idx_, c;
  register int tidx;

  for(idx_ = tidx = 0; tidx < 128 && str_[idx_] != '\0'; idx_++) 
    {
      if(isspace(str_[idx_]))  continue;

      tokens[tidx].type = STR_CST;
      tokens[tidx].start = str_ + idx_;
      tokens[tidx].length = 1;

      if(isalpha(str_[idx_]))
	{
	  c = str_[idx_];  
	  while(isalnum(c) || (c) == '_')
	    {
	      tokens[tidx].length++;
	      idx_ ++;
	      c = str_[idx_];  
	    }
	  tokens[tidx].length--;
	}
      else if( (isdigit(str_[idx_]) || str_[idx_] == '.' ) ||
	       (str_[idx_] == '-' && (isdigit(str_[idx_+1]) || str_[idx_+1] == '.' )))
	{
	  tokens[tidx].length = scan_number(&str_[idx_], tidx);
	  idx_ += (tokens[tidx].length - 1);
	}
      tidx++;
    }
  return(tidx);
}
/***************************************************************************/
static int scan_number(str, tidx)   
     char *str; int tidx;
{
  register int count = 0;

  tokens[tidx].type = INT_CST;
  if(str[0] == '-') count++;
  while(isdigit(str[count])) count++;
  if(str[count] == '.')
    {
      tokens[tidx].type = FLOAT_CST;
      while (isdigit(str[++count])) ;
    }
  if(str[count] == 'e' || str[count] == 'E') 
    {
      tokens[tidx].type = FLOAT_CST;
      if(str[++count] == '-') count++;
      if(!isdigit(str[count])) 
	{
	  tokens[tidx].type = STR_CST;
	  while( str[count] && !isspace(str[count])) count++;
	}
      else while(isdigit(str[++count]));
    }
  if(tokens[tidx].type == INT_CST) 
    tokens[tidx].v.i = atoi(str);
  else if(tokens[tidx].type == FLOAT_CST)
    tokens[tidx].v.f = (float) atof(str);
  return(count);
}
/****************************************************************/
static char *copyToken(idx, ret)
     int idx; char *ret;
{
  char *src = tokens[idx].start;
  char *tgt = ret;
  int len = tokens[idx].length;
  while(len > 0)
    {
      *tgt++ = *src++;
      len--;
    }
  *tgt = 0;
  return(ret);
}
/****************************************************************/
static int getTokenIntValue(idx, v_ret)
     int idx, *v_ret;
{
  if(tokens[idx].type == STR_CST)
    {
      char tname[1024];
      if(EZ_RetrieveSymbolicInt(copyToken(idx,tname), v_ret) < 0)
	return(-1);
    }
  else if(tokens[idx].type == INT_CST)
    *v_ret = tokens[idx].v.i;
  else return(-1);
  return(0);
}

static int getTokenFloatValue(idx, v_ret)
     int idx; float *v_ret;
{
  if(tokens[idx].type == STR_CST) 
    {
      char tname[1024];
      if(EZ_RetrieveSymbolicFloat(copyToken(idx,tname), v_ret) < 0)
      return(-1);
    }
  else if(tokens[idx].type == INT_CST)
    *v_ret = (float) tokens[idx].v.i;
  else *v_ret = tokens[idx].v.f;
  return(0);
}
/****************************************************************/
int silenceOnConfigError = 0;
void EZ_GetAndUseWidgetResources(widget) EZ_Widget *widget;
{
  if(widget)
    {
      silenceOnConfigError = 1;
      EZ_GetSetWidgetResources(widget, 0);
      silenceOnConfigError = 0;
      if(EZ_WidgetType(widget) == EZ_WIDGET_LED)
	EZ_LEDStatus(widget) &=  ~LED_BLOCKED;
    }
}
static void EZ_GetSetWidgetResources(widget, level)
  EZ_Widget *widget; int level;
{
  if(widget)
    {
      EZ_Widget *children, *sibling;

      EZ_GetSetWidgetResourcesWork(widget);
      children = EZ_WidgetChildren(widget);
      EZ_GetSetWidgetResources(children, 1);
      if(level)
	{
	  sibling = EZ_WidgetSibling(widget);
	  EZ_GetSetWidgetResources(sibling, 1);	  
	}
      
      if(EZ_WidgetType(widget) == EZ_WIDGET_OPTIONAL_ENTRY)
	EZ_GetSetWidgetResources(EZ_OptEntryPopup(widget), 0);
    }
}
/****************************************************************/
static void EZ_GetSetWidgetResourcesWork(widget)
     EZ_Widget *widget;
{
  EZ_Widget *parent;
  XrmQuark  clist[128], nlist[128], Q_type[2];
  int i, j, position, doitnot, ntokens;
  XrmValue value;
  /* vars needed for EZ_SetWidgetAttributes */
  int       i0,i1,i2,i3,i4;
  void      *p1, *p2;
  float     f1, f2;
  unsigned long ul1, ul2;
  char tmpstr[512];
  
  if(EZ_LookupWidgetFromAllHT(widget) == (EZ_Widget *)NULL) return;

  parent = widget;
  i = 127;
  while(parent)
    {
      clist[i] = EZ_WidgetCName(parent);
      nlist[i] = EZ_WidgetIName(parent);	  
      parent = EZ_WidgetParent(parent);
      i--;
    }
  clist[0] = EZ_ClassQName;
  nlist[0] = EZ_InstanceQName;
  for(j = 1, i = i+1; i < 128; i++, j++)
    {
      clist[j] = clist[i];
      nlist[j] = nlist[i];
    }
  clist[j] = NULLQUARK; clist[j+1] = NULLQUARK;
  nlist[j] = NULLQUARK; nlist[j+1] = NULLQUARK;
  position = j;
  /* path set */

  for(i = 0; i < EZ_WIDGET_CONFIGURE_LAST_OPTION; i++)
    {
      if(EZ_OptionsNQs[i] != NULLQUARK)
	{
	  clist[position] = EZ_OptionsCQs[i];
	  nlist[position] = EZ_OptionsNQs[i];
	  value.addr = NULL;
	  if(XrmQGetResource(EZ_Xrm_db, nlist, clist, Q_type, &value) == True)
	    {
	      i1=i2=i3=i4=0;
	      ul1 = ul2 = 0L;
	      p1 = p2 = NULL;
	      f1 = f2 = 0.0;
	      doitnot = 0;
	      /* now we have to process string value.attr */
	      switch(i)
		{
		case EZ_DND_BUBBLE_STRING:
		case EZ_SELECTION_BACKGROUND:
		case EZ_SELECTION_FOREGROUND:
		case EZ_INDICATOR_COLOR:
		case EZ_FOREGROUND:
		case EZ_TEXT_BACKGROUND:
		case EZ_BACKGROUND:
		case EZ_BITMAP_FILE:
		case EZ_IMAGE_FILE:
		case EZ_FONT_NAME:
		case EZ_BUTTON_SHORTCUT:
		case EZ_BUBBLE_STRING:
		case EZ_LABEL_STRING:
		case EZ_GLOB_PATTERN:
		case EZ_ENTRY_STRING:
		case EZ_NAME:
		case EZ_CLASS:
		case EZ_LCD_BACKGROUND:
		case EZ_LCD_FOREGROUND:
		case EZ_LED_BACKGROUND:
		case EZ_LED_PIXEL_COLOR:
		case EZ_SMETER_BACKGROUND:
		case EZ_SMETER_FOREGROUND:
		case EZ_POPUP_NAME:
		case EZ_WM_WINDOW_NAME:
		case EZ_WM_ICON_NAME:
		case EZ_WM_ICON_XPM_FILE:
		  p1 = value.addr;
		  break;
		case EZ_X:
		case EZ_Y:
		case EZ_SHAPED_WINDOW:
		case EZ_WIDTH:
		case EZ_WIDTH_HINT:
		case EZ_HEIGHT:
		case EZ_HEIGHT_HINT:
		case EZ_INDICATOR_TYPE:
		case EZ_EMBEDER:
		case EZ_BORDER_WIDTH:
		case EZ_BORDER_TYPE:
		case EZ_PADX:
		case EZ_PADY:
		case EZ_IPADX:
		case EZ_IPADY:
		case EZ_STACKING:
		case EZ_SIDE:
		case EZ_LABEL_POSITION:
		case EZ_JUSTIFICATION:
		case EZ_FILL_MODE:
		case EZ_TEXT_SPACING:
		case EZ_FONT_ID:
		case EZ_SLIDER_DISPLAY_VALUE:
		case EZ_SLIDER_LENGTH:
		case EZ_SLIDER_WIDTH:
		case EZ_SLIDER_BORDER_WIDTH:
		case EZ_TEXT_LINE_LENGTH:
		case EZ_INDICATOR_SIZE_ADJUST:
		case EZ_FREELABEL_MOVABLE:
		case EZ_RESERVE_MENU_BUTTON:
		case EZ_BACKING_STORE:
		case EZ_EXPAND:
		case EZ_TRANSIENT:
		case EZ_SCROLLBAR_WIDTH:
		case EZ_SCROLLBAR_BORDER_WIDTH:
		case EZ_PROPAGATE:
		case EZ_ATTACH_INT_DATA:
		case EZ_UNDERLINE:
		case EZ_CHECK_BUTTON_ON_VALUE:
		case EZ_CHECK_BUTTON_OFF_VALUE:
		case EZ_CHECK_BUTTON_ON_OFF:
		case EZ_RADIO_BUTTON_GROUP:
		case EZ_RADIO_BUTTON_VALUE:
		case EZ_OPTIONAL_HSCROLLBAR:
		case EZ_OPTIONAL_VSCROLLBAR:
		case EZ_FANCY_LIST_BOX_TYPE:
		case EZ_FANCY_LIST_BOX_COLUMNS:
		case EZ_TEXT_WIDGET_EDITABLE:
		case EZ_RETURN_VALUE:
		case EZ_OPTIONAL_ENTRY_EDITABLE:
		case EZ_MENU_TEAR_OFF:
		case EZ_OPTIONAL_ENTRY_REMEMBER_HISTORY:
		case EZ_PADB:
		case EZ_LCD_NDIGITS:
		case EZ_LCD_FONT_SIZE:
		case EZ_LED_WIDTH:
		case EZ_LED_HEIGHT:
		case EZ_LED_PIXEL_SIZE:
		case EZ_WMHINTS:
		case EZ_GEOMETRY_MANAGER: 
		case EZ_LABELED_ICON:
		case EZ_HSCROLL_INCREMENT:
		case EZ_VSCROLL_INCREMENT:
		case EZ_SMETER_STOPED:
		case EZ_SMETER_SHOW_VALUE:
		case EZ_SMETER_ORIENTATION:

		case EZ_FORGET_X:
		case EZ_FORGET_Y:
		case EZ_FORGET_W:
		case EZ_FORGET_H:
		case EZ_FORGET_POSITION:
		case EZ_FORGET_SIZE:
		case EZ_FORGET_GEOMETRY:
		case EZ_WM_INITIAL_STATE:
		case EZ_MARK_CLEAN:
		  ntokens = parseString(value.addr);
		  if(ntokens > 0) doitnot = getTokenIntValue(0, &i1);
		  break;
		case  EZ_DND_DRAG_CURSOR:
		case  EZ_CURSOR:		  
		  ul1 = (unsigned long)EZ_GetCursorByName(value.addr);
		  if(ul1 == None) doitnot = 1;
		  break;
		case EZ_GRID_CELL_PLACEMENT:
		case EZ_LOCATION:
		case EZ_SIZE:
		case EZ_SIZE_HINT:
		case EZ_SMETER_STYLE:
		case EZ_WM_ICON_LOCATION:
		case EZ_WM_LOCATION_HINT:
		case EZ_WM_SIZE_HINT:
		case EZ_WM_MAX_SIZE_HINT:
		case EZ_WM_MIN_SIZE_HINT:
		  ntokens = parseString(value.addr);
		  if(ntokens > 1)
		    {
		      doitnot = getTokenIntValue(0, &i1);
		      doitnot += getTokenIntValue(1, &i2);
		    }
		  else doitnot = 1;
		  break; 
		case EZ_GRID_CELL_GEOMETRY:
		case EZ_GRID_ROW_CONSTRAINS:
		case EZ_GRID_COLUMN_CONSTRAINS:
		  ntokens = parseString(value.addr);
		  if(ntokens > 3)
		    {
		      doitnot =  getTokenIntValue(0, &i1);
		      doitnot += getTokenIntValue(1, &i2);
		      doitnot += getTokenIntValue(2, &i3);
		      doitnot += getTokenIntValue(3, &i4);
		    }
		  else doitnot = 1;
		  break;
		case EZ_GEOMETRY:
		  {
		    int bits=0;
		    EZ_ParseGeometry(value.addr, &bits, &i1,&i2,&i3,&i4);
		    if(bits != 15 /*(1|2|4|8)*/) /* all bits must be set */ 
		      doitnot = 1;
		  }
		break;
		case EZ_GRID_CONSTRAINS:		  
		  ntokens = parseString(value.addr);
		  if(ntokens > 4)
		    {
		      doitnot =  getTokenIntValue(0, &i0);
		      doitnot += getTokenIntValue(1, &i1);
		      doitnot += getTokenIntValue(2, &i2);
		      doitnot += getTokenIntValue(3, &i3);
		      doitnot += getTokenIntValue(3, &i4);
		      ul1 = (unsigned long)i0;
		    }
		  else doitnot = 1;
		  break;
		case EZ_SLIDER_RESOLUTION: 
		case EZ_SLIDER_INIT_VALUE:		
		case EZ_SMETER_VALUE:
		  ntokens = parseString(value.addr);
		  if(ntokens > 0)
		    doitnot =  getTokenFloatValue(0, &f1);
		  else doitnot = 1;
		  break;
		case EZ_SMETER_VALUE_N:
		  ntokens = parseString(value.addr);
		  if(ntokens > 1)
		    {
		      int jj;
		      for(jj = 0; jj < ntokens; jj += 2)
			{
			  doitnot =  getTokenIntValue(jj, &i1);
			  doitnot +=  getTokenFloatValue(jj+1, &f1);		      
			  if(!doitnot)
			    EZ_SetWidgetAttributes(widget,i,i1,i2, p1,p2,ul1,ul2,f1,f2, i3,i4);
			}
		    }
		  doitnot = 1;		  
		  break;
		case EZ_SMETER_FOREGROUND_N:
		  ntokens = parseString(value.addr);
		  if(ntokens > 1)
		    {
		      int jj;
		      for(jj = 0; jj < ntokens; jj += 2)
			{
			  doitnot =  getTokenIntValue(jj, &i1);
			  copyToken(jj+1, tmpstr);
			  p1 = tmpstr;
			  if(!doitnot)
			    EZ_SetWidgetAttributes(widget,i,i1,i2, p1,p2,ul1,ul2,f1,f2, i3,i4);
			}
		    }
		  doitnot = 1;
		  break;
		case EZ_SLIDER_RANGE: 
		case EZ_SMETER_RANGE:
		  ntokens = parseString(value.addr);
		  if(ntokens > 1)
		    {
		      doitnot =  getTokenFloatValue(0, &f1);
		      doitnot += getTokenFloatValue(1, &f2);
		    }
		  else doitnot = 1;
		  break;
		case EZ_SMETER_RANGE_N:
		  ntokens = parseString(value.addr);
		  if(ntokens > 2)
		    {
		      int jj;
		      for(jj = 0; jj < ntokens; jj += 3)
			{
			  doitnot =  getTokenIntValue(jj, &i1);
			  doitnot +=  getTokenFloatValue(jj+1, &f1);
			  doitnot += getTokenFloatValue(jj+2, &f2);
			  if(!doitnot)
			    EZ_SetWidgetAttributes(widget,i,i1,i2, p1,p2,ul1,ul2,f1,f2, i3,i4);
			}
		    } 
		  doitnot = 1;
		  break;
		default:
		  doitnot = 1;
		  break;
		}
	      if(doitnot == 0)
		EZ_SetWidgetAttributes(widget,i,i1,i2, p1,p2,ul1,ul2,f1,f2, i3,i4);
	    }
	}
    }
}
/*****************************************************************/
#undef  STR_ID   
#undef  INT_CST  
#undef  FLOAT_CST
/*****************************************************************/
#undef  _EZ_RESOURCEGET_C_
