/*======================================================================================*/
/* 3DPanel										*/
/*											*/
/* - Status panel									*/
/*											*/
/* AUTHOR:	Gabor Nagy								*/
/* DATE:	1996-Sep-12 22:56:31							*/
/*											*/
/* 3DPanel(TM) and 3DLib(TM) Copyright (C) 1995 By Gabor Nagy. All rights reserved.	*/
/*======================================================================================*/
#include <stdio.h>
#include <stdarg.h>		// For VarArgs

#include <Xe/Label.h>
#include <Xe/Matrix.h>
#include <Xe/PushButton.h>
#include <Xe/Scale.h>

#include <Color/XColor.h>

#include <EGUI/Dialog.h>

#include <E3D/XGUI.h>

#include <E3D/Panel.h>

extern EpCImage		Image_MsgHistory;


static Arg		Args[256];
static Cardinal		ArgCnt;

static unsigned long	E3dp_CurrentMessageID=1;		// For E3dp_PrintMessage

Widget			E3dp_MessageLabelW=NULL, E3d_ProgressScaleW=NULL, E3d_ProcessAbortBW=NULL,
			E3d_LMBLabelW=NULL,
			E3d_MMBLabelW=NULL,
			E3d_RMBLabelW=NULL,
			E3d_MsgHistoryBW=NULL,
			E3d_UndoBufferDisplayW=NULL;


static void		(*E3d_AbortCallback)(EPointer)=NULL;	// For the progress indicator
static EPointer		E3d_AbortClientData=NULL;

#define	E3dpMESSAGE_STACKDEPTH	16

static XeString		E3dp_StatusMessage=NULL;
static XeString		E3dp_MessageStack[E3dpMESSAGE_STACKDEPTH];
static unsigned int	E3dp_MessageStackPtr=0;



/*======================================*/
/* Abort button callback		*/
/*======================================*/
static void E3dCB_Abort(Widget LW, XtPointer LClientData, XtPointer LCallData)
{
 if(E3d_AbortCallback) E3d_AbortCallback(E3d_AbortClientData);
}


/*======================================*/
/* Turn StatusPanel on/off		*/
/*======================================*/
void E3dp_SetStatusPanel(E3dPanel* L3DPanel, EBool LSwitch)
{
 Widget	LStatusPanelW0;

 if(L3DPanel->StatusPanelW==NULL)
 {
  EguiVisual*	LVisual=EGUI_TruecolorVisual;
  XeString	LXeStr;
  Pixel		LToolTipBG=Ec_XGetRGBAiColor(EGUI_Display, DefaultColormap(EGUI_Display, EGUI_ScreenNumber), &EGUI_ToolTipBackgroundRGBAiColor);
  unsigned int	LC;

// Clear Message stack
//
  for(LC=0;LC<E3dpMESSAGE_STACKDEPTH;LC++)
  {
   E3dp_MessageStack[LC]=NULL;
   E3dp_MessageStackPtr=0;
  }


  EXtStart;
  EXtSetArg(XeNshadowThickness, 0);
  EXtSetArg(XeNxSpacing, 0);
  EXtSetArg(XeNmarginWidth, 0);EXtSetArg(XeNmarginHeight, 0);
  EXtSetArg(XeNshadowType, XeSHADOW_OUT);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNorientation, XeHORIZONTAL);
  EXtSetArg(XeNheightAdjustable, False);
  L3DPanel->StatusPanelW=XtCreateWidget("StatusP", xeMatrixWidgetClass, L3DPanel->TopMatrixW, Args, ArgCnt);


  EXtStart;
  EXtSetArg(XeNshadowThickness, 2);EXtSetArg(XeNshadowType, XeSHADOW_OUT);
  EXtSetArg(XeNxSpacing, 4);
  EXtSetArg(XeNmarginWidth, 4);EXtSetArg(XeNmarginHeight, 3);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNadjustEntryWidths, True);
  L3DPanel->StatusPanelPW=LStatusPanelW0=XtCreateManagedWidget("StatusP0", xeMatrixWidgetClass, L3DPanel->StatusPanelW, Args, ArgCnt);


  EXtStart;
  EXtSetArg(XeNmarginWidth, 0);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNforeground, MenuForegroundColor);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
//  EXtSetArg(XeNshadowThickness, 1);EXtSetArg(XeNshadowType, XeSHADOW_IN);
//  EXtSetArg(XeNrecomputeSize, False);
  EXtSetArg(XeNwidthAdjustable, True);
  EXtSetArg(XeNheightAdjustable, False);EXtSetArg(XeNlabelXAlignment, XeALIGN_BEGINNING);EXtSetArg(XeNyAlignment, XeALIGN_CENTER);
  E3dp_MessageLabelW=XtCreateManagedWidget(" ", xeLabelWidgetClass, LStatusPanelW0, Args, ArgCnt);


// Progress indicator
//
  EXtStart;
  EXtSetArg(XeNminimum, 0);EXtSetArg(XeNmaximum, 1000);EXtSetArg(XeNvalue, (int)1000);
  EXtSetArg(XeNorientation, XeHORIZONTAL);
  EXtSetArg(XeNscaleLengthInPixels, 250);EXtSetArg(XeNscaleWidthInPixels, 18);
  EXtSetArg(XeNshadowThickness, 0);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNlabelFontList, EGUI_LabelFontList);
  EXtSetArg(XeNthermoColor, E3dp_ProgressIndicatorColor);
  EXtSetArg(XeNeditable, False);
  EXtSetArg(XeNscaleType, XeTHERMOMETER);EXtSetArg(XeNcreateTextField, False);
  EXtSetArg(XeNwidthAdjustable, False);
  EXtSetArg(XeNheightAdjustable, False);
  EXtSetArg(XeNthermoShadowThickness, 2);
//  E3d_ProgressScaleW=XtCreateWidget("ProgressScaleW", xeScaleWidgetClass, LStatusPanelW0, Args, ArgCnt);
  E3d_ProgressScaleW=XtCreateWidget(NULL, xeScaleWidgetClass, LStatusPanelW0, Args, ArgCnt);


  EXtStart;
  EXtSetArg(XeNmarginLeft, 0);EXtSetArg(XeNmarginRight, 0);EXtSetArg(XeNmarginTop, 0);EXtSetArg(XeNmarginBottom, 0);
  EXtSetArg(XeNbackground, EGUI_ButtonColor);
  EXtSetArg(XeNforeground, EGUI_ForegroundColor);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
  EXtSetArg(XeNmarginWidth, 0);EXtSetArg(XeNmarginHeight, 0);
  EXtSetArg(XeNmarginLeft, 3);EXtSetArg(XeNmarginRight, 4);
  EXtSetArg(XeNwidthAdjustable, False);
  E3d_ProcessAbortBW=XtCreateWidget("Abort", xePushButtonWidgetClass, LStatusPanelW0, Args, ArgCnt);
  XtAddCallback(E3d_ProcessAbortBW, XeNactivateCallback, E3dCB_Abort, (XtPointer)NULL);

/*
  EXtStart;
  EXtSetArg(XeNshadowThickness, 0);EXtSetArg(XeNshadowType, XeSHADOW_IN);
  EXtSetArg(XeNmarginWidth, 3);EXtSetArg(XeNmarginHeight, 1);EXtSetArg(XeNspacing, 1);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNtopShadowColor, MenuTopShadowColor);
  EXtSetArg(XeNbottomShadowColor, MenuBottomShadowColor);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
  EXtSetArg(XeNwidthAdjustable, False);
  if(LVisual)
  {
   EXtSetArg(XeNvisualInfo, LVisual->X_VisualInfo);EXtSetArg(XeNcolormap, LVisual->X_Colormap);
   EXtSetArg(XeNlabelPixmap, EGUI_VaRGBAToPixmap(RGBA8_LMB, XSize_LMB, YSize_LMB, EguiNbackground, &(E3dp_Prefs.MenuRGBAiColor), NULL));
   EXtSetArg(XeNlabelType, XePIXMAP_STRING_HORIZONTAL);
  }
  E3d_LMBLabelW=XtCreateManagedWidget("                              ", xeLabelWidgetClass, LStatusPanelW0, Args, ArgCnt);

  EXtStart;
  EXtSetArg(XeNshadowThickness, 0);EXtSetArg(XeNshadowType, XeSHADOW_IN);
  EXtSetArg(XeNmarginWidth, 3);EXtSetArg(XeNmarginHeight, 1);EXtSetArg(XeNspacing, 1);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNtopShadowColor, MenuTopShadowColor);
  EXtSetArg(XeNbottomShadowColor, MenuBottomShadowColor);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
  EXtSetArg(XeNwidthAdjustable, False);
  if(LVisual)
  {
   EXtSetArg(XeNvisualInfo, LVisual->X_VisualInfo);EXtSetArg(XeNcolormap, LVisual->X_Colormap);
   EXtSetArg(XeNlabelPixmap, EGUI_VaRGBAToPixmap(RGBA8_MMB, XSize_MMB, YSize_MMB, EguiNbackground, &(E3dp_Prefs.MenuRGBAiColor), NULL));
   EXtSetArg(XeNlabelType, XePIXMAP_STRING_HORIZONTAL);
  }
  E3d_MMBLabelW=XtCreateManagedWidget("                              ", xeLabelWidgetClass, LStatusPanelW0, Args, ArgCnt);

  EXtStart;
  EXtSetArg(XeNshadowThickness, 0);EXtSetArg(XeNshadowType, XeSHADOW_IN);
  EXtSetArg(XeNmarginWidth, 3);EXtSetArg(XeNmarginHeight, 1);EXtSetArg(XeNspacing, 1);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNtopShadowColor, MenuTopShadowColor);
  EXtSetArg(XeNbottomShadowColor, MenuBottomShadowColor);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
  EXtSetArg(XeNwidthAdjustable, False);
  if(LVisual)
  {
   EXtSetArg(XeNvisualInfo, LVisual->X_VisualInfo);EXtSetArg(XeNcolormap, LVisual->X_Colormap);
   EXtSetArg(XeNlabelPixmap, EGUI_VaRGBAToPixmap(RGBA8_RMB, XSize_RMB, YSize_RMB, EguiNbackground, &(E3dp_Prefs.MenuRGBAiColor), NULL));
   EXtSetArg(XeNlabelType, XePIXMAP_STRING_HORIZONTAL);
  }
  E3d_RMBLabelW=XtCreateManagedWidget("                              ", xeLabelWidgetClass, LStatusPanelW0, Args, ArgCnt);
*/


  EXtStart;
  EXtSetArg(XeNshadowThickness, 0);
  EXtSetArg(XeNmarginLeft, 8);EXtSetArg(XeNmarginRight, 0);EXtSetArg(XeNmarginTop, 0);EXtSetArg(XeNmarginBottom, 0);
  EXtSetArg(XeNfontList, EGUI_LabelFontList);
  EXtSetArg(XeNmarginWidth, 0);EXtSetArg(XeNmarginHeight, 0);
  EXtSetArg(XeNwidthAdjustable, False);
  if(LVisual)
  {
   EXtSetArg(XeNbackground, TC_MenuBackgroundColor);
   EXtSetArg(XeNforeground, TC_MenuForegroundColor);
   EXtSetArg(XeNvisualInfo, LVisual->X_VisualInfo);EXtSetArg(XeNcolormap, LVisual->X_Colormap);
   EXtSetArg(XeNlabelPixmap, EGUI_VaCImageToPixmap(&(Image_MsgHistory), EguiNbackground, &(E3dp_Prefs.MenuRGBAiColor), NULL));
   EXtSetArg(XeNlabelType, XePIXMAP);
  }

  if((LXeStr=XeStringVaCreate(True, XeSTRING_COMPONENT_CHARSET, "tag1", XeSTRING_COMPONENT_ALIGN, XeSTRING_ALIGN_LEFT, XeSTRING_COMPONENT_TEXT, "Show message history", XeSTRING_COMPONENT_UNKNOWN))!=NULL)
  {
   EXtSetArg(XeNtipBackground, LToolTipBG);
   EXtSetArg(XeNtipFontList, EGUI_LabelFontList);
   EXtSetArg(XeNtipString, LXeStr);
  }
  E3d_MsgHistoryBW=XtCreateManagedWidget("History", xePushButtonWidgetClass, LStatusPanelW0, Args, ArgCnt);
//  XtAddCallback(E3d_MsgHistoryBW, XeNactivateCallback, E3dCB_Abort, (XtPointer)NULL);
  if(LXeStr) XeStringFree(LXeStr);


  EXtStart;
  EXtSetArg(XeNshadowThickness, 2);EXtSetArg(XeNshadowType, XeSHADOW_OUT);
  EXtSetArg(XeNmarginWidth, 3);EXtSetArg(XeNmarginHeight, 1);EXtSetArg(XeNspacing, 1);
  EXtSetArg(XeNhighlightThickness, 0);
  EXtSetArg(XeNscaleWidthInPixels, 18);
  EXtSetArg(XeNbackground, MenuBackgroundColor);
  EXtSetArg(XeNtopShadowColor, MenuTopShadowColor);
  EXtSetArg(XeNbottomShadowColor, MenuBottomShadowColor);
  EXtSetArg(XeNlabelFontList, EGUI_LabelFontList);
  EXtSetArg(XeNminimum, 0);EXtSetArg(XeNmaximum, E3dp_UndoStack.MaxUndoSteps);
  EXtSetArg(XeNvalue, 0);
  EXtSetArg(XeNscaleLengthInPixels, 50);
  EXtSetArg(XeNorientation, XeHORIZONTAL);
  EXtSetArg(XeNscaleType, XeTHERMOMETER);
  EXtSetArg(XeNcreateTextField, False);EXtSetArg(XeNeditable, False);
  EXtSetArg(XeNwidthAdjustable, False);
  EXtSetArg(XeNthermoShadowThickness, 2);
  E3d_UndoBufferDisplayW=XtCreateManagedWidget("Undo:", xeScaleWidgetClass, L3DPanel->StatusPanelW, Args, ArgCnt);
 }


 if(LSwitch) XtManageChild(L3DPanel->StatusPanelW);
 else XtUnmanageChild(L3DPanel->StatusPanelW);

 E3dp_Prefs.StatusPanelOn=LSwitch;
}




XtIntervalId	E3dp_MessageTimerId=(XtIntervalId)NULL;

XeString	E3d_EmptyXeStr=NULL;

/*======================================*/
/* Remove a message			*/
/*======================================*/
void E3dp_RemoveMessageTH(XtPointer LClientData, XtIntervalId* LTID)
{
 E3dp_MessageTimerId=(XtIntervalId)NULL;

 if(E3dp_MessageLabelW)
 {
  if(E3dp_StatusMessage) XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, E3dp_StatusMessage, NULL);
  else
  {
   if(E3d_EmptyXeStr==NULL) E3d_EmptyXeStr=XeStringCreateSimple(" ");
//  printf("CLR\n");fflush(stdout);
   XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, E3d_EmptyXeStr, NULL);
  }
 }
}


/*======================================*/
/* Print a transient message		*/
/*======================================*/
unsigned long E3dp_PrintMessage(int LType, unsigned int LTime, char* LMessage, ...)	// Removal time in milliseconds
{
 XeString	LXeStr;
 char		LTmpStr[4096];
 va_list	LAL;

 if(E3dp_MessageLabelW)
 {
  va_start(LAL, LMessage);				// LMessage is the last argument before the varargs
  vsprintf(LTmpStr, LMessage, LAL);
  va_end(LAL);

  if((LXeStr=XeStringCreateSimple(LTmpStr)))
  {
   XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, LXeStr, NULL);
   XeStringFree(LXeStr);

   if(E3dp_MessageTimerId!=(XtIntervalId)NULL) XtRemoveTimeOut(E3dp_MessageTimerId);

   if(LTime!=0) E3dp_MessageTimerId=XtAppAddTimeOut(E3dp_AppContext, LTime, E3dp_RemoveMessageTH, (XtPointer)NULL);
  }

  E3dp_CurrentMessageID++;
  return(E3dp_CurrentMessageID-1);
 }
 return(0);
}


/*======================================*/
/* Set the current message to NULL	*/
/*======================================*/
void E3dp_ClearCurrentMessage()
{
 if(E3dp_StatusMessage) { XeStringFree(E3dp_StatusMessage);E3dp_StatusMessage=NULL; }

 if(E3d_EmptyXeStr==NULL) E3d_EmptyXeStr=XeStringCreateSimple(" ");
 XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, E3d_EmptyXeStr, NULL);
}


/*======================================*/
/* Set the current message		*/
/*======================================*/
unsigned long E3dp_SetCurrentMessage(int LPushCurrentMessageOnStack, unsigned int LTime, char* LMessage, ...)	// Removal time in milliseconds
{
 XeString	LXeStr;
 char		LTmpStr[4096];
 va_list	LAL;

 if(E3dp_MessageLabelW)
 {
  va_start(LAL, LMessage);
  vsprintf(LTmpStr, LMessage, LAL);
  va_end(LAL);
  if((LXeStr=XeStringCreateSimple(LTmpStr)))
  {
   XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, LXeStr, NULL);

   if(LPushCurrentMessageOnStack)
   {
    E3dp_MessageStack[E3dp_MessageStackPtr]=E3dp_StatusMessage;
    if(E3dp_MessageStackPtr<=E3dpMESSAGE_STACKDEPTH) E3dp_MessageStackPtr++;
    else { printf("Message-stack overflow!\n");fflush(stdout);return(0); }
   }
   else
   {
    if(E3dp_StatusMessage) XeStringFree(E3dp_StatusMessage);
   }

   E3dp_StatusMessage=LXeStr;

   if(E3dp_MessageTimerId!=(XtIntervalId)NULL) XtRemoveTimeOut(E3dp_MessageTimerId);

   if(LTime!=0) E3dp_MessageTimerId=XtAppAddTimeOut(E3dp_AppContext, LTime, E3dp_RemoveMessageTH, (XtPointer)NULL);
  }
  E3dp_CurrentMessageID++;
  return(E3dp_CurrentMessageID-1);
 }
 return(0);
}


/*==============================================================================*/
/* Push current message to the stack and overwrite it with the given message	*/
/*==============================================================================*/
unsigned long E3dp_PushMessage(int LType, unsigned int LTime, char* LMessage, ...)
{
 XeString	LXeStr;
 char		LTmpStr[4096];
 va_list	LAL;

 if(E3dp_MessageLabelW)
 {
  va_start(LAL, LMessage);
  vsprintf(LTmpStr, LMessage, LAL);
  va_end(LAL);

  E3dp_MessageStack[E3dp_MessageStackPtr]=E3dp_StatusMessage;
  if(E3dp_MessageStackPtr<=E3dpMESSAGE_STACKDEPTH) E3dp_MessageStackPtr++;
  else { printf("Message-stack overflow!\n");fflush(stdout);return(0); }

  if((LXeStr=XeStringCreateSimple(LTmpStr)))
  {
   XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, LXeStr, NULL);

   E3dp_StatusMessage=LXeStr;

   if(E3dp_MessageTimerId!=(XtIntervalId)NULL) XtRemoveTimeOut(E3dp_MessageTimerId);

   if(LTime!=0) E3dp_MessageTimerId=XtAppAddTimeOut(E3dp_AppContext, LTime, E3dp_RemoveMessageTH, (XtPointer)NULL);
  }
  E3dp_CurrentMessageID++;
  return(E3dp_CurrentMessageID-1);
 }
 return(0);
}


/*==============================================================================*/
/* Push current message to the stack and overwrite it with the given message	*/
/*==============================================================================*/
unsigned long E3dp_PushXeMessage(int LType, unsigned int LTime, XeString LMessage)
{
 if(E3dp_MessageLabelW)
 {
  E3dp_MessageStack[E3dp_MessageStackPtr]=E3dp_StatusMessage;
  if(E3dp_MessageStackPtr<=E3dpMESSAGE_STACKDEPTH) E3dp_MessageStackPtr++;
  else { printf("Message-stack overflow!\n");fflush(stdout);return(0); }

  XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, LMessage, NULL);

  E3dp_StatusMessage=LMessage;

  if(E3dp_MessageTimerId!=(XtIntervalId)NULL) XtRemoveTimeOut(E3dp_MessageTimerId);

  if(LTime!=0) E3dp_MessageTimerId=XtAppAddTimeOut(E3dp_AppContext, LTime, E3dp_RemoveMessageTH, (XtPointer)NULL);

  E3dp_CurrentMessageID++;
  return(E3dp_CurrentMessageID-1);
 }
 return(0);
}


/*==============================================================================*/
/* Push current message to the stack and overwrite it with the given message	*/
/*==============================================================================*/
unsigned long E3dp_PushHTMLMessage(int LType, unsigned int LTime, char* LMessage, ...)
{
/*
 XeString	LXeStr;
 char		LTmpStr[4096];
 va_list	LAL;

 if(E3dp_MessageLabelW)
 {
  va_start(LAL, LMessage);
  vsprintf(LTmpStr, LMessage, LAL);
  va_end(LAL);

  E3dp_MessageStack[E3dp_MessageStackPtr]=E3dp_StatusMessage;
  if(E3dp_MessageStackPtr<=E3dpMESSAGE_STACKDEPTH) E3dp_MessageStackPtr++;
  else { printf("Message-stack overflow!\n");fflush(stdout);return(0); }

  if((LXeStr=XeStringCreateFromHTML(LTmpStr)))
  {
   XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, LXeStr, NULL);

   E3dp_StatusMessage=LXeStr;

   if(E3dp_MessageTimerId!=(XtIntervalId)NULL) XtRemoveTimeOut(E3dp_MessageTimerId);

   if(LTime!=0) E3dp_MessageTimerId=XtAppAddTimeOut(E3dp_AppContext, LTime, E3dp_RemoveMessageTH, (XtPointer)NULL);
  }
  E3dp_CurrentMessageID++;
  return(E3dp_CurrentMessageID-1);
 }
*/
 return(0);
}


/*======================================================*/
/* Get back pointer mode from the stack			*/
/*======================================================*/
void E3dp_PopMessage()
{
 if(E3dp_MessageStackPtr>0) E3dp_MessageStackPtr--;
 else { printf("Message-stack underflow!\n");fflush(stdout);return; }

 E3dp_StatusMessage=E3dp_MessageStack[E3dp_MessageStackPtr];
 if(E3dp_StatusMessage) XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, E3dp_StatusMessage, NULL);
 else
 {
  if(E3d_EmptyXeStr==NULL) E3d_EmptyXeStr=XeStringCreateSimple(" ");
  XtVaSetValues(E3dp_MessageLabelW, XeNlabelString, E3d_EmptyXeStr, NULL);
 }
}


/*======================================================*/
/* Clear the current message and the message-stack	*/
/*======================================================*/
void E3dp_ResetMessageStack()
{
 E3dp_ClearCurrentMessage();
 E3dp_MessageStackPtr=0;
}


/*======================================*/
/* Set message for the progress-bar	*/
/*======================================*/
void E3dp_SetProgressMessage(char* LMessage, ...)
{
 XeString	LXeStr;
 char		LTmpStr[4096];
 va_list	LAL;

 if(E3d_ProgressScaleW)
 {
  va_start(LAL, LMessage);				// LMessage is the last argument before the varargs
  vsprintf(LTmpStr, LMessage, LAL);
  va_end(LAL);

  if((LXeStr=XeStringCreateSimple(LTmpStr)))
  {
   XtVaSetValues(E3d_ProgressScaleW, XeNlabelString, LXeStr, NULL);
   XeStringFree(LXeStr);
  }
 }
}


/*======================================*/
/* Set progress indicator		*/
/*======================================*/
void E3dp_SetProgressIndicator(int LThousandth, void (*LAbortCallback)(EPointer), EPointer LClientData)
{
 E3d_AbortClientData=LClientData;
 if((E3d_AbortCallback=LAbortCallback)!=NULL) XtManageChild(E3d_ProcessAbortBW);
 else XtUnmanageChild(E3d_ProcessAbortBW);

 if(LThousandth<0) XtUnmanageChild(E3d_ProgressScaleW);
 else
 {
  XtManageChild(E3d_ProgressScaleW);

  XeScaleSetValue(E3d_ProgressScaleW, LThousandth, False);
  E3dp_SyncGUI();
 }
}
