/*****************************************************************************
  FILE           : ui_remoteP.c
  SHORTNAME      : remoteP.c
  SNNS VERSION   : 3.2

  PURPOSE        : routines to control learning, updating the net
  NOTES          : Most of this routines are callbacks of buttons in the remote-
                   panel.

  AUTHOR         : Tilman Sommer
  DATE           : 18.7.1990

  CHANGED BY     : Michael Vogt, Guenter Mamier
  IDENTIFICATION : @(#)ui_remoteP.c	1.33 4/18/94
  SCCS VERSION   : 1.33 
  LAST CHANGE    : 4/18/94  

             Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG
             
******************************************************************************/


#include <stdio.h>

#include "ui.h"
#include "ui_mainP.h"
#include "ui_utilP.h"
#include "ui_selection.h"
#include "ui_netUpdate.h"

#include "glob_typ.h"
#include "kr_ui.h"

#include "ui_fileP.h"
#include "ui_confirmer.h"
#include "ui_textP.h"
#include "ui_xWidgets.h"
#include "ui_display.h"
#include "ui_action.h"
#include "ui_remote.h"
#include "ui_status.h"
#include "ui_infoP.h"
#include "d3_main.h"
#include "net_analyzer.h"

#include "kr_typ.h"
#include "cc_rcc.h"
#include "cc_main.h"
#include "dlvq_learn.h"
#include "ui_inversion.h"
#include "ui_kohonen.h"


#include "o_graph.h"
#include "ui_main.h"
#include "ui_event.h"

#include <X11/Xaw/Form.h>
#include <X11/Shell.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#include <X11/Intrinsic.h>

#include "ui_remoteP.ph"


/*****************************************************************************
  FUNCTION : ui_rem_displayCounter

  PURPOSE  : displays the value in ui_numberOfStepsDone in the remote panel
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/
static void ui_rem_displayCounter (void)
{
    char  buf[50];
    if (NOT ui_remoteIsCreated) return;

    sprintf(buf,"%d", ui_numberOfStepsDone);
    ui_xSetLabel(ui_numberOfStepsDoneWidget, buf);
}


/*****************************************************************************
  FUNCTION : ui_rem_displayPatternNumber

  PURPOSE  : displays the value in ui_numberOfCurrentPattern in the 
             remote panel
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_displayPatternNumber (void)
{
    char  buf[50];

    if (NOT ui_remoteIsCreated) return;

    sprintf(buf,"%d", ui_noOfCurrentPattern);
    ui_xSetString(ui_numberOfPatternWidget, buf);
    ui_xSetLabel(ui_showPattFile, PATTERN_SET_FILE[CURR_PATTERN_SET]);
}



/*****************************************************************************
  FUNCTION : ui_rem_resetCounter()

  PURPOSE  : set counter to 0
  RETURNS  : VOID
  NOTES    :

  UPDATE   : 30.7.1990
******************************************************************************/
void ui_rem_resetCounter (void)
{
    ui_numberOfStepsDone = 0;
    ui_rem_displayCounter();
}



/*****************************************************************************
  FUNCTION : ui_rem_incCounter()

  PURPOSE  : increment counter by 1
  RETURNS  :
  NOTES    :

  UPDATE   : 30.7.1990
******************************************************************************/
static void ui_rem_incCounter (void)
{
    ui_numberOfStepsDone += 1;
    ui_rem_displayCounter();
}


/*****************************************************************************
  FUNCTION : ui_rem_resetNet

  PURPOSE  : Resets the net to the initial activation and resets the counter
  NOTES    :

  UPDATE   : 24.8.1990
******************************************************************************/
void ui_rem_resetNet (Widget w, XtPointer button, caddr_t call_data)
{
    ui_sel_reshowItems(ui_currentDisplay, UI_GLOBAL);
    ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_ERASE);
    krui_resetNet();
    ui_rem_resetCounter();
    ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_DRAW);
    ui_sel_reshowItems(ui_currentDisplay, UI_GLOBAL);
}


/*****************************************************************************
  FUNCTION : ui_rem_doInitialization

  PURPOSE  : get the parameters and call the kernel
  RETURNS  : void
  NOTES    : 

  UPDATE   : 18.3.1991
******************************************************************************/
void ui_rem_doInitialization (Widget w, caddr_t client_data, caddr_t call_data)
{
    int i;
 
    if(o_open){
      o_CurveNo += ((o_CurveLengths[o_CurveNo] != 0) && 
		    (o_CurveNo < MAX_CURVE_NO-1)) ? (1) : (0);
      o_InitCurve();
      o_LearnStepCount = 0;
    }
 
    for (i=0; i< UI_NO_INIT_PARAMS; i++) {
	ui_initParameters[i] =
	    ui_xFloatFromAsciiWidget(ui_initParameterWidgets[i]);
    }
    ui_checkError(krui_initializeNet(ui_initParameters, UI_NO_INIT_PARAMS));
    if (ui_displ_isSomeWhereToShowWeights())
	ui_net_completeRefresh(NULL, UI_GLOBAL);
    else {
        ui_net_completeRefresh(NULL, UI_GLOBAL);
	ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_DRAW);  
    }
    ui_sel_reshowItems(ui_currentDisplay, UI_GLOBAL);
}


/*****************************************************************************
  FUNCTION : ui_rem_deleteNet

  PURPOSE  : clear SNNS kernel
  RETURNS  : void
  NOTES    : 

  UPDATE   : 18.3.1991
******************************************************************************/

void ui_rem_deleteNet (Widget w, caddr_t client_data, caddr_t call_data)

{
    if (ui_confirmYes
	("CLEAR: The network and all patterns will be lost. Clear?")) {
	/* reset kernel */
	krui_deleteNet();
	/* reset gui */
	ui_sel_resetList();       /* reset selections */
	ui_net_completeRefresh(NULL, UI_GLOBAL); /* show net */
	ui_printMessage("");
	ui_stat_displayStatus(ui_gridPosMouse);
	ui_file_updateShellLabels();
	ui_info_makeUnitInfoPanelConsistent();	
        d3_clear_xyTranslationTable ();
	if (INVERS_CREATED) {
           XtDestroyWidget(ui_InvRootWidget);
           INVERS_CREATED = 0;
       }
    }
}


/*****************************************************************************
  FUNCTION : ui_rem_finishSteps

  PURPOSE  : finish performing update steps
  RETURNS  : void
  NOTES    :

  UPDATE   : 1.2.1990
******************************************************************************/

static void ui_rem_finishSteps (void)

{
    ui_printMessage("");

    /* reshow selection markers */
    ui_sel_reshowItems(ui_currentDisplay, UI_GLOBAL); 
}


/*****************************************************************************
  FUNCTION : ui_rem_performStep

  PURPOSE  : called by pressing the button STEPS
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/

static Boolean ui_rem_performStep (caddr_t client_data)

{
    if (ui_numberOfWorkCycles-- < 1) {
	ui_rem_finishSteps();
	if (NA_ContinueTest()) 
	    ui_rem_testProc (NULL, NULL, NULL) ; 
	return(TRUE);
    }
    /* erase the units first, if they have to be drawn with their values
       in numerical form at the bottom (setup parameter) */
    if (ui_displ_isSomeWhereToShowValues())
	ui_net_updateWhole(NULL, UI_GLOBAL, 
			   UI_DRAW_UNITS, UI_ERASE_BOTTOM);
    ui_checkError(krui_updateNet(ui_updateParameters, UI_NO_UPDATE_PARAMS));
    ui_rem_incCounter();
    ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_DRAW);
    NA_DrawNextPoint () ;
    return(FALSE);
}


/*****************************************************************************
  FUNCTION : ui_rem_stepsProc

  PURPOSE  : perform one or more steps, depending on the PANEL_CLIENT_DATA
             if STEP is pressed one update step in the current mode
	     if STEPS is pressed: get the number of steps to perform
	     from the panel and go.
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/

void  ui_rem_stepsProc (Widget widget, Bool multiStepPressed, caddr_t call_data)

{ 
    char   buf[80];
    int    i;

    if (multiStepPressed) 
	/* MultiSTEPS button */
	if ((ui_numberOfWorkCycles = 
	     ui_xIntFromAsciiWidget(ui_numberOfStepsWidget)) <= 0)
	    return;
	
    sprintf(buf,"%d steps. Calculating ...", ui_numberOfWorkCycles);
    ui_printMessage(buf);
   

    for (i=0; i<UI_NO_UPDATE_PARAMS; i++)
	ui_updateParameters[i] = (float) 
	    ui_xFloatFromAsciiWidget(ui_updateParameterWidgets[i]);  

    /* erase selection markers */
    ui_sel_reshowItems(ui_currentDisplay, UI_GLOBAL); 

   /* Get new Activation Parameter for Kohonen */
   if (kohonen_open) 
     kohonen_SetExtraParameter(ui_xIntFromAsciiWidget(ui_LayerWidget)); 

    if (ui_workProcId)
	XtRemoveWorkProc(ui_workProcId); /* kill old workProc */
    ui_workType = UI_STEPS;
    ui_workProcId = 
	XtAppAddWorkProc(ui_appContext, (XtWorkProc) ui_rem_performStep, NULL);

}


/*****************************************************************************
  FUNCTION : ui_rem_moveInPatternsProc             

  PURPOSE  : callback. Called when clicked on a cursor button or the GOTO 
             button.
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_moveInPatternsProc (Widget w, int moveType, caddr_t call_data)
{
    int   temp;

    Bool  doMove = FALSE;

    if (krui_getNoOfPatterns() <= 0) {
	ui_confirmOk("No patterns in memory!");
	return;
    }

    /* there are patterns */
    switch (moveType) {
      case UI_JUMP: 
	temp = ui_xIntFromAsciiWidget(ui_numberOfPatternWidget);
	if ((temp > 0) AND (temp <= krui_getNoOfPatterns())) {
	    ui_noOfCurrentPattern = temp;
	    ui_rem_displayPatternNumber();
	    doMove = TRUE;
	} else
	    ui_confirmOk("pattern goto: invalid number!");
	break;
      case UI_FIRST:
	ui_noOfCurrentPattern = 1;
	ui_rem_displayPatternNumber();
	doMove = TRUE;
	break;
      case UI_LAST:
	ui_noOfCurrentPattern = krui_getNoOfPatterns();
	ui_rem_displayPatternNumber();
	doMove = TRUE;
	break;
      case UI_NEXT:
	if (++ui_noOfCurrentPattern > krui_getNoOfPatterns())
	    ui_noOfCurrentPattern = 1;
	ui_rem_displayPatternNumber();
	doMove = TRUE;
	break;
      case UI_PREVIOUS:
	if (--ui_noOfCurrentPattern < 1)
	    ui_noOfCurrentPattern = krui_getNoOfPatterns();
	ui_rem_displayPatternNumber();
	doMove = TRUE;
	break;
    }
    
    if (doMove) {
	/* new pattern: reset */

	krui_setPatternNo(ui_noOfCurrentPattern);
	ui_rem_getSubPatPanel();
	ui_rem_resetSubPat();
	ui_checkError(krui_DefShowSubPat(subIPatSize,subOPatSize,
					 subIPatPos,subOPatPos));
	ui_rem_resetCounter();

	ui_checkError(krui_showPattern(ui_patternLoadMode));
	ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_DRAW);
    }
}


/*****************************************************************************
  FUNCTION : ui_rem_moveInSubPattProc             

  PURPOSE  : callback. Called when clicked on a cursor button of the supattern 
             panel.
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/

void ui_rem_moveInSubPattProc (Widget w, int moveParam, caddr_t call_data)
{
    int dim, moveType;
    int i;
    pattern_set_info patt_info;
    pattern_descriptor descrip;
    char buf[3];
    krui_err error;
    int i_temp, o_temp, i_save, o_save;
    int maxNpos;      /* value not used */

    /* Get information about current pattern set */

    if((error = krui_GetPatInfo(&patt_info, &descrip)) < 0){
	ui_checkError(error);
	return;
    }

    /* extract parameters */

    dim = moveParam / 10;
    moveType = moveParam % 10;


    /* get subpattern information */

    for (i=0; i< subIPatDims; i++) {
	subIPatSize[i] = (int)ui_xIntFromAsciiWidget(subIPatSizeW[i]);
	subIPatStep[i] = (int)ui_xIntFromAsciiWidget(subIPatStepW[i]);
    }
    for (i=0; i< subOPatDims; i++) {
	subOPatSize[i] = (int)ui_xIntFromAsciiWidget(subOPatSizeW[i]);
	subOPatStep[i] = (int)ui_xIntFromAsciiWidget(subOPatStepW[i]);
    }


    /* compute the new subpattern positions */

    switch (moveType) {
      case SP_FIRST:
	i_temp = 1;
	o_temp = 1;
	break;
      case SP_LAST:
	i_temp = descrip.input_dim_sizes[dim] - subIPatSize[dim]+1;
	o_temp = descrip.output_dim_sizes[dim] - subOPatSize[dim]+1;
	break;
      case SP_NEXT:
	if(subIPatPos[dim]+subIPatStep[dim] <= 
	                      descrip.input_dim_sizes[dim]-subIPatSize[dim]+1)
	    i_temp = subIPatPos[dim] + subIPatStep[dim];
	else
	    i_temp = subIPatPos[dim];
	if(subOPatPos[dim]+subOPatStep[dim] <= 
	                      descrip.output_dim_sizes[dim]-subOPatSize[dim]+1)
	    o_temp = subOPatPos[dim] + subOPatStep[dim];
	else
	    o_temp = subOPatPos[dim];
	break;
      case SP_PREVIOUS:
	i_temp = subIPatPos[dim] - subIPatStep[dim];
	if(i_temp < 1)i_temp = 1;
	o_temp = subOPatPos[dim] - subOPatStep[dim];
	if(o_temp < 1)o_temp = 1;
	break;
    }

    /* perform the move */
    subIPatPos[dim] = i_temp;
    subOPatPos[dim] = o_temp;

    /* validate the desired move */
    ui_checkError(krui_DefTrainSubPat(subIPatSize,subOPatSize,		
				      subIPatStep,subOPatStep,&maxNpos));
    ui_checkError(krui_AlignSubPat(subIPatPos,subOPatPos,&subIPatNo));

    if((error = krui_DefShowSubPat(subIPatSize,subOPatSize,
				   subIPatPos,subOPatPos)) < 0){
	ui_checkError(error);
	return;
    }
    if((error = krui_showPattern(ui_patternLoadMode)) < 0){
	ui_checkError(error);
	return;
    }
    ui_net_updateWhole(NULL, UI_GLOBAL, UI_DRAW_UNITS, UI_DRAW);

    /* reset labels if move was successful */
    for (i=0; i< subIPatDims; i++) {
	sprintf(buf," %d",subIPatPos[i]);
	ui_xSetLabel(subIPatPosW[i],buf);
    }
    for (i=0; i< subOPatDims; i++){
	sprintf(buf," %d",subOPatPos[i]);
	ui_xSetLabel(subOPatPosW[i],buf);
    }
}


/*****************************************************************************
  FUNCTION : ui_rem_testProc

  PURPOSE  : load the next (or first) pattern and perform the number of steps
             specified in the remote panel in "no of steps"
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/

void ui_rem_testProc (Widget w, XtPointer button, caddr_t call_data)

{

    static int npos = 1;
    int        maxNpos;


    if (krui_getNoOfPatterns() == 0) {
	char buf[80];
	sprintf(buf,"No patterns present.");
	ui_printMessage(buf);
	return;
    }

    /* there are patterns */

    if (ui_noOfCurrentPattern > krui_getNoOfPatterns() - 1)
	ui_noOfCurrentPattern = 0; /* set before first pattern */

    rcc_currentPattern = ui_noOfCurrentPattern;

    /* new pattern: reset */
    ui_rem_resetCounter();

    ui_rem_getSubPatPanel();
    ui_checkError(krui_DefTrainSubPat(subIPatSize,subOPatSize,
				      subIPatStep,subOPatStep,&maxNpos));
    ui_checkError(krui_AlignSubPat(subIPatPos,subOPatPos,&npos));
    if(++npos > maxNpos){
	ui_checkError(krui_setPatternNo(++ui_noOfCurrentPattern));
	ui_checkError(krui_DefTrainSubPat(subIPatSize,subOPatSize,
					  subIPatStep,subOPatStep,&maxNpos));
	npos = 1;
	ui_rem_resetSubPat();
    }
    ui_checkError(krui_GetShapeOfSubPattern(subIPatSize,subOPatSize,
					    subIPatPos,subOPatPos,npos));
    ui_checkError(krui_DefShowSubPat(subIPatSize,subOPatSize,
				     subIPatPos,subOPatPos));
    ui_rem_setSubPatPanel();

    ui_checkError(krui_showPattern(ui_patternLoadMode));
    ui_rem_displayPatternNumber();

    if (ui_xIntFromAsciiWidget(ui_numberOfStepsWidget) < 1)
	ui_net_updateWhole(NULL, UI_GLOBAL, 
			   UI_DRAW_UNITS, UI_DRAW);
    else
	ui_rem_stepsProc(NULL, TRUE, NULL); /* multistep */
}


/*****************************************************************************
  FUNCTION : ui_rem_deleteAllPatternsProc

  PURPOSE  : delete all patterns in main memory. The contents of the current
             pattern file (if any) is left unchanged 
  RETURNS  : void
  NOTES    :

  UPDATE   : 24.8.1990
******************************************************************************/

void ui_rem_deleteAllPatternsProc (Widget w, XtPointer button, 
					caddr_t call_data)

{
    if (ui_confirmYes("Delete all patterns. Are you sure?")) {
	krui_deleteAllPatterns();
	ui_noOfCurrentPattern = 0;
	ui_rem_displayPatternNumber();
    }
}


/*****************************************************************************
  FUNCTION : ui_rem_modifyPatternProc

  PURPOSE  : calls the kernal in order to store the current visible pattern
             replacing the current pattern. 
  RETURNS  : void 
  NOTES    :

  UPDATE   : 18.3.1991
******************************************************************************/
void ui_rem_modifyPatternProc (Widget w, XtPointer button, caddr_t call_data)
{
    int temp = ui_xIntFromAsciiWidget(ui_numberOfPatternWidget);

    newPatternsLoaded = 1;

    if ((temp > 0) AND (temp <= krui_getNoOfPatterns())) {
	ui_noOfCurrentPattern = temp;
	krui_setPatternNo(ui_noOfCurrentPattern);
	ui_checkError(krui_modifyPattern());
	if (ui_noOfCurrentPattern > krui_getNoOfPatterns()) {
	    ui_noOfCurrentPattern = krui_getNoOfPatterns();
	    ui_rem_displayPatternNumber();
	} 
    } else
	ui_confirmOk("modify pattern: invalid pattern number!");
}


/*****************************************************************************
  FUNCTION : ui_rem_deletePatternProc

  PURPOSE  : calls the kernal in order to delete the current visible pattern.
  RETURNS  : void
  NOTES    :

  UPDATE   : 18.3.1991
******************************************************************************/
void ui_rem_deletePatternProc (Widget w, XtPointer button, caddr_t call_data)
{
    int temp = ui_xIntFromAsciiWidget(ui_numberOfPatternWidget);

    newPatternsLoaded = 1;

    if ((temp > 0) AND (temp <= krui_getNoOfPatterns())) {
	ui_noOfCurrentPattern = temp;
	krui_setPatternNo(ui_noOfCurrentPattern);
	ui_checkError(krui_deletePattern());
	if (ui_noOfCurrentPattern > krui_getNoOfPatterns()) {
	    ui_noOfCurrentPattern = krui_getNoOfPatterns();
	    ui_rem_displayPatternNumber();
	} 
    } else
	ui_confirmOk("delete pattern: invalid pattern number!");
}


/*****************************************************************************
  FUNCTION : ui_rem_newPatternProc

  PURPOSE  : calls the kernel in order to store the current visible pattern
             as a new one. This new pattern will be appended.
  RETURNS  : void
  NOTES    :

  UPDATE   : 24.8.1990
******************************************************************************/
void ui_rem_newPatternProc (Widget w, XtPointer button, caddr_t call_data)
{
    pattern_set_info   patt_info;
    pattern_descriptor descrip;
    int error,setNo;

    if(NO_OF_PATTERN_SETS == 0){
	if((error = krui_allocNewPatternSet(&setNo)) < 0){
	    ui_checkError(error);
	    return;
	}
	ui_noOfCurrentPattern = 1;
	NO_OF_PATTERN_SETS = 1;
	CURR_PATTERN_SET = setNo;

	/* set the widgets labels */
	PATTERN_SET_FILE[CURR_PATTERN_SET] = (char *)malloc(8);
	strcpy(PATTERN_SET_FILE[CURR_PATTERN_SET],"New Set");
	ui_rem_updatePattList();

    }else if(krui_getNoOfPatterns() > 0){
	if((error = krui_GetPatInfo(&patt_info, &descrip)) < 0){
	    ui_checkError(error);
	    return;
	}
	if(patt_info.in_number_of_dims>0 || patt_info.out_number_of_dims>0){
	    ui_confirmOk("NEW not allowed with variable sized patterns!");
	    return;
	}
    }

    newPatternsLoaded = 1;
    ui_checkError(krui_newPattern());
    ui_noOfCurrentPattern = krui_getNoOfPatterns();
    ui_rem_displayPatternNumber();
}



/*****************************************************************************
  FUNCTION : ui_rem_printLearnInfo

  PURPOSE  : print information about last learning cycle
  RETURNS  : void
  NOTES    : Kohonen requires additional information to be displayed during
             learning. Therefore a special section is included here.

  UPDATE   : 23.03.94 by Sven Doering
******************************************************************************/
static void ui_rem_printLearnInfo (void)
{
    char    buf[MAX_NAME_LENGTH];
    int     i,j;
    static float temp1, temp2;
    static int times = 1;
    int pats;

    if(strcmp("Kohonen",krui_getLearnFunc()) == 0){
	if(INIT_KOHONEN_PRINT == 1){
	    times = 1;
	    INIT_KOHONEN_PRINT = 0; /* The variable is set when pressing the
				       ALL and SINGLE Buttons in the remote */
	    temp1 =(float)ui_xFloatFromAsciiWidget(ui_learnParameterWidgets[0]);
	    temp2 =(float)ui_xFloatFromAsciiWidget(ui_learnParameterWidgets[1]);
	}else{
	    times = ui_numberOfLearnCycles DIV 10;
	}
	pats = krui_getNoOfPatterns();
	for(j=1; j<= times; j++)
	    for(i=1; i<=pats; i++){
		/* this is a copy of the adaption process in the kernel for
		   display reasons */
		temp1 *= ui_learnParameters[2];
		temp2 *= ui_learnParameters[3];
	    }
	/* Adapt the displayed values of the first two learning parameters 
	   in the remote panel */
	sprintf(buf,"%7.5f",temp1);
	strncpy(buf,buf,7);
	ui_xSetString(ui_learnParameterWidgets[0], buf);
	sprintf(buf,"%7.5f",temp2);
	strncpy(buf,buf,7);
	ui_xSetString(ui_learnParameterWidgets[1], buf);
    }

    sprintf(buf,"  %5d:", ui_numberOfWorkCycles + 1);
    ui_tw_printMessage(buf);
    sprintf(buf,"    %10.5f",ui_errorArray[0]);
    ui_tw_printMessage(buf);
    sprintf(buf,"     %10.5f",(ui_errorArray[0]/krui_getNoOfPatterns()));
    ui_tw_printMessage(buf);
    if (krui_getNoOfOutputUnits() > 0) {
	sprintf(buf,"        %10.5f\n", 
		(ui_errorArray[0]/krui_getNoOfOutputUnits()));
	ui_tw_printMessage(buf);
    } else
	ui_tw_printMessage("\n");
}


/*****************************************************************************
  FUNCTION : ui_rem_finishLearning

  PURPOSE  : finish performing learning cycles
  RETURNS  : void
  NOTES    :

  UPDATE   : 1.2.1990
******************************************************************************/

static void ui_rem_finishLearning (void)

{
    /* bring the patterns back into their old order before shuffling was done */
    if (ui_shuffleFlg) 
	ui_checkError(krui_shufflePatterns(FALSE));
    if (ui_shuffleSubPatFlg) 
	ui_checkError(krui_shuffleSubPatterns(FALSE));
    
    if (ui_displ_isSomeWhereToShowWeights())
	ui_net_completeRefresh(NULL, UI_GLOBAL);
    else {
          cc_updatePosOfSpecialUnits();
          ui_net_completeRefresh(NULL, UI_GLOBAL);
	ui_net_updateWhole(NULL, UI_GLOBAL, 
			   UI_DRAW_UNITS, UI_DRAW);
	}
}


/*****************************************************************************
  FUNCTION : ui_rem_performLearn

  PURPOSE  : perform learning cycles
  RETURNS  :
  NOTES    :

  UPDATE   : 1.2.1990
******************************************************************************/

static Boolean ui_rem_performLearn (int learnType)

{
    krui_err err;

    dlvq_numberOfLearnCycles = ui_numberOfLearnCycles; 

    if (ui_numberOfWorkCycles-- < 1) {
	ui_rem_finishLearning();
	return(TRUE);
    }

    switch (learnType) {
      case UI_LEARN_ALL:
	if (ui_shuffleFlg) 
	    ui_checkError(krui_shufflePatterns(TRUE));
	if (ui_shuffleSubPatFlg) 
	    ui_checkError(krui_shuffleSubPatterns(TRUE));
	ui_checkError(err = krui_learnAllPatterns(ui_learnParameters, 
				   UI_NO_LEARN_PARAMS+UI_NO_OF_CASCADE_PARAMS,
					    &ui_errorArray,
					    &ui_noErrorArrayElements));
        if (err != KRERR_NO_ERROR)
            return (TRUE);
	break;
      case UI_LEARN_SINGLE:
	if ((ui_noOfCurrentPattern <= krui_getNoOfPatterns()) AND
	    (ui_noOfCurrentPattern > 0)) {
	    ui_checkError(err = krui_learnSinglePattern(ui_noOfCurrentPattern,
						  ui_learnParameters,
				  UI_NO_LEARN_PARAMS+UI_NO_OF_CASCADE_PARAMS,
						  &ui_errorArray,
						  &ui_noErrorArrayElements));
            if (err != KRERR_NO_ERROR)
                return (TRUE);
	} else
	    ui_confirmOk("Can't learn current pattern.");
	break;
    }

    if ((ui_numberOfWorkCycles == ui_numberOfLearnCycles) or
	(ui_numberOfWorkCycles == 0) or
	(ui_numberOfLearnCycles <= 10) or
	(((ui_numberOfWorkCycles+1) MOD (ui_numberOfLearnCycles DIV 10)) == 0)){
	ui_rem_printLearnInfo();
        ui_displWeightsFromUpdate();
    }

    if(o_open){
      o_draw(ui_errorArray[0]/krui_getNoOfOutputUnits());
      if(ui_numberOfWorkCycles == 0){
        o_PressPossible = 1;
      }
    }
    return(FALSE);
}


/*****************************************************************************
  FUNCTION : ui_rem_learnProc

  PURPOSE  : call the learn procedure of the kernel. The number of learn cycles
             is determined by the user and also the learn parameter.
  RETURNS  : implicite alteration of the network
  NOTES    : 

  UPDATE   :
*****************************************************************************/

void ui_rem_learnProc (Widget w, int learnType, caddr_t call_data)

{
    char  buf[MAX_NAME_LENGTH];
    int   i, maxNpos;
    
    o_PressPossible = 0;

      cc_readElements();
      cc_allButtonIsPressed = 1;

    /* check now for errors and react ! */
    if (krui_getNoOfPatterns == 0) {
	ui_confirmOk("No patterns loaded/created!");
	return;
    }

    ui_rem_getSubPatPanel ();
    ui_rem_resetSubPat();
    ui_checkError(krui_DefTrainSubPat(subIPatSize,subOPatSize,
				      subIPatStep,subOPatStep,&maxNpos));

    ui_numberOfWorkCycles = /* this value will be decreased */
	ui_xIntFromAsciiWidget(ui_numberOfCyclesWidget);
    ui_numberOfLearnCycles = /* this value stays constant */
	ui_numberOfWorkCycles;
    for (i=0; i<UI_NO_LEARN_PARAMS; i++)
	ui_learnParameters[i] = (float) 
	    ui_xFloatFromAsciiWidget(ui_learnParameterWidgets[i]);
    
    if (learnType == UI_LEARN_ALL)
	ui_tw_printMessage("\nLearning all patterns:\n");
    else
	ui_tw_printMessage("\nLearning current pattern:\n");

    sprintf(buf,
	    "  epochs   : %d\n  parameter: %8.5f\n  #o-units : %d\n  #patterns: %d\n", 
	    ui_numberOfWorkCycles, ui_learnParameters[0], 
	    krui_getNoOfOutputUnits(),krui_getNoOfPatterns());
    ui_tw_printMessage(buf);
    sprintf(buf,
	    "\n  epoch:         SSE            MSE            SSE/o-units\n\n");
    ui_tw_printMessage(buf);
    INIT_KOHONEN_PRINT = 1; /*Enables the print kommands for kohonen */
    
    NA_StopTest () ;
    if (ui_workProcId)
	XtRemoveWorkProc(ui_workProcId); /* kill old workProc */
    ui_workType = UI_LEARN;
    ui_workProcId = XtAppAddWorkProc(ui_appContext, 
				     (XtWorkProc) ui_rem_performLearn, 
				     (XtPointer) learnType); 

}


/*****************************************************************************
  FUNCTION : ui_rem_stopProc

  PURPOSE  : callback. Called after click on STOP button
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/

void  ui_rem_stopProc (Widget widget, caddr_t client_data, caddr_t call_data)

{ 
    if (ui_workProcId) { 
	switch (ui_workType) { 
	  case UI_STEPS: 
		ui_rem_finishSteps(); break;
	  case UI_LEARN:
	    ui_rem_finishLearning();
	    ui_rem_printLearnInfo();
	    break;
	}
	NA_StopTest () ;
	XtRemoveWorkProc(ui_workProcId); /* kill workProc */
	ui_workProcId = 0;
	ui_numberOfWorkCycles = 0;
    }
    o_PressPossible = 1;
}


/*****************************************************************************
  FUNCTION : ui_rem_shuffleProc

  PURPOSE  : notify procedure of the toggle item, to remember the status of
             it.
  RETURNS  : changes the flag ui_shuffleFlg
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_shuffleProc (Widget w, caddr_t client, caddr_t call)
{
    ui_shuffleFlg = ui_xGetToggleState(w);
}


/*****************************************************************************
  FUNCTION : ui_rem_showModeProc

  PURPOSE  : notify procedure of the panel cycle.
  RETURNS  : sets the variable ui_patternLoadMode
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_showModeProc (Widget w, int value, caddr_t call_data)
{    
    ui_patternLoadMode = (int) value;
    switch (value) {
      case OUTPUT_NOTHING:
	ui_xSetLabel(ui_showModeLabel, "none");
	break;
      case OUTPUT_OUT:
	ui_xSetLabel(ui_showModeLabel, "output");
	break;
      case OUTPUT_ACT:
	ui_xSetLabel(ui_showModeLabel, "activation");
	break;
    }
}


/*****************************************************************************
  FUNCTION : ui_rem_setRandomWeights

  PURPOSE  : set weights of all links randomly
  RETURNS  : void
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_setRandomWeights (Widget w, int randomType, caddr_t call_data)
{    
    FlintType  low, high, temp;

    low  = (FlintType) ui_xFloatFromAsciiWidget(ui_lowLimitWidget);
    high = (FlintType) ui_xFloatFromAsciiWidget(ui_highLimitWidget);
    if (low > high) {
	temp = low;
	low  = high;
	high = temp;
    }

    switch (randomType) {
      case UI_RANDOM:
	/* krui_randomizeWeights(low, high); */	   
	break;
      case UI_JOG:
	krui_jogWeights(low, high);
	break;
    }
    if (ui_displ_isSomeWhereToShowWeights())
	ui_net_completeRefresh(NULL, UI_GLOBAL);
}


/*****************************************************************************
  FUNCTION : ui_rem_getKernelInfo

  PURPOSE  : get some info from the kernel. Output to text window
  RETURNS  : void
  NOTES    :

  UPDATE   : 1.2.1990
******************************************************************************/
void ui_rem_getKernelInfo (Widget w, XtPointer button, caddr_t call_data)
{
    char   buf[127];
    int    no_of_sites, no_of_links, no_of_STable_entries, no_of_FTable_entries;
    int    unit_bytes, site_bytes, link_bytes, 
           NTable_bytes, STable_bytes, FTable_bytes;

    sprintf(buf,"\n%s :\n\n", krui_getVersion());
    ui_tw_printMessage(buf);

    krui_getNetInfo(&no_of_sites, &no_of_links,
		    &no_of_STable_entries, &no_of_FTable_entries);

    sprintf(buf,"#input  units: %6d\n#output units: %6d\n#patterns    : %6d\n",
	    krui_getNoOfInputUnits(), krui_getNoOfOutputUnits(), 
	    krui_getNoOfPatterns());
    ui_tw_printMessage(buf);
    sprintf(buf,"#sites       : %6d\n#links       : %6d\n",
	    no_of_sites, no_of_links);
    ui_tw_printMessage(buf);
    sprintf(buf,"#STable entr.: %6d\n#FTable-Entr.: %6d\n\n",
	    no_of_STable_entries, no_of_FTable_entries);
    ui_tw_printMessage(buf);

    ui_tw_printMessage("sizes in bytes:\n");
    krui_getMemoryManagerInfo(&unit_bytes, &site_bytes, &link_bytes,
			      &NTable_bytes, &STable_bytes, &FTable_bytes);
    sprintf(buf,"units        : %7d\nsites        : %7d\nlinks        : %7d\n",
	    unit_bytes, site_bytes, link_bytes);
    ui_tw_printMessage(buf);
    sprintf(buf,"NTable       : %7d\nSTable       : %7d\nFTable       : %7d\n\n"
	    ,NTable_bytes, STable_bytes, FTable_bytes);
    ui_tw_printMessage(buf);
    sprintf(buf,"learning function  : %s\n", krui_getLearnFunc());
    ui_tw_printMessage(buf);
    sprintf(buf,"update function    : %s\n", krui_getUpdateFunc());
    ui_tw_printMessage(buf);
    sprintf(buf,"initialize function: %s\n", krui_getInitialisationFunc());
    ui_tw_printMessage(buf);

    ui_tw_printMessage("\n\n");
}


/*****************************************************************************
  FUNCTION : ui_rem_shuffleSubPatProc

  PURPOSE  : notify procedure of the toggle item, to remember the status of
             it.
  RETURNS  : changes the flag ui_shuffleSubPatFlg
  NOTES    :

  UPDATE   :
*****************************************************************************/
void ui_rem_shuffleSubPatProc (Widget w, caddr_t client, caddr_t call)
{
    ui_shuffleSubPatFlg = ui_xGetToggleState(w);
}


/*****************************************************************************
  FUNCTION : ui_rem_defSubPat

  PURPOSE  : creates the panel to handle sub patterns 
  RETURNS  : void
  NOTES    :

  UPDATE   : 16.09.1993
******************************************************************************/
void ui_rem_defSubPat (Widget button, int refreshType, caddr_t call_data)
{
    Widget             sbutton,lab1,ui_pop_exit,ui_pop,above,
                       isize,istep,itot,otot,osize,ostep;
    static Widget      form,title1,title2,left,subPatDoneW,
                       input,output,ipos,opos;
    Arg                args[5];
    Position           x, y;
    Dimension          width, height;
    Cardinal           n;
    char               buf[120];
    int                i;
    krui_err           error;
    pattern_set_info   patt_info;
    pattern_descriptor descrip;
    Window             rdummy;
    int                x1, y1, border;
    unsigned int       wdummy, hdummy, bdummy, ddummy;


    /* Get information about current pattern set */

    if(NO_OF_PATTERN_SETS == 0){
	if(refreshType == 0){
	    ui_confirmOk("No Patterns present !");
	    return;
	}else{
	    /* call came from ui_rem_delPatSet which deleted last pattern */
	    /* set. Therefore destroy panel                               */
	    XtCallCallbacks(subPatDoneW,XtNcallback,
			    (caddr_t) UI_POPUP_SUBPATTERN);
	    return;
	}
    }


    if((refreshType == 1) && (SubPatPanel < 1))
	/* can't refresh, if panel was never created yet */
	return;

    if((error = krui_GetPatInfo(&patt_info, &descrip)) < 0){
	ui_checkError(error);
	return;
    }

    if(patt_info.in_number_of_dims == 0){
	if(SubPatPanel < 1){
	    ui_confirmOk("Pattern has no variable dimension !");
	    return;
	}else{
	    /* New pattern set does not allow this panel */
	    XtCallCallbacks(subPatDoneW,XtNcallback,
			    (caddr_t) UI_POPUP_SUBPATTERN);
	    return;
	}

    }

    if(refreshType == 0){ /*panel has to be created */

	if(SubPatPanel == 1)
	    /* panel was supposed to be created but exists already */
	    return;

	/* Upper left corner will be in the center of the calling button */

	ui_xGetDimensions(button, &width, &height);
	XtTranslateCoords(button, (Position) (width / 2), 
			  (Position) (height / 2),&x, &y);
    
	n = 0;
	XtSetArg(args[n], XtNx, x); n++;
	XtSetArg(args[n], XtNy, y); n++;

	/* Now create Popup */
    
	ui_popPattern =
	    XtCreatePopupShell("Sub Pattern Handling", 
				topLevelShellWidgetClass,ui_toplevel,args,n);
    }else{

	/* Recreate the panel */

	n = 0;
	XtSetArg(args[n], XtNx, &x); n++;
	XtSetArg(args[n], XtNy, &y); n++;
	XtSetArg(args[n], XtNborderWidth, &border); n++;
	XtGetValues(ui_popPattern, args, n);
	XGetGeometry(ui_display, (*ui_popPattern).core.window, &rdummy, 
		     &x1, &y1, &wdummy, &hdummy, &bdummy, &ddummy);
	XtDestroyWidget(ui_popPattern);

	n = 0;
	XtSetArg(args[n], XtNx, x-x1-bdummy-1); n++;
	XtSetArg(args[n], XtNy, y-y1-bdummy-1); n++;
    	ui_popPattern =
	    XtCreatePopupShell("Sub Pattern Handling", 
				transientShellWidgetClass,ui_toplevel,args,n);
    }
    ui_pop = 
	XtCreateManagedWidget("frame",formWidgetClass,ui_popPattern,
			      NULL,0);
    
    XtSetArg(args[n], XtNborderWidth, 1); 
    form = XtCreateManagedWidget("form", formWidgetClass, ui_pop, args, 1);
    
    sprintf(buf,"                               Input");
    title1 = ui_xCreateLabelItem(buf,form,41*8,NULL,NULL);
    sprintf(buf,"       Output");
    title2 = ui_xCreateLabelItem(buf,form,14*8,title1,NULL);
    
    n = 0;
    XtSetArg(args[n], XtNborderWidth,  0); n++;
    XtSetArg(args[n], XtNfromHoriz, NULL); n++;
    XtSetArg(args[n], XtNfromVert, title1); n++;
    left = XtCreateManagedWidget("left", formWidgetClass, form, args, n);
    sprintf(buf,"     ");
    title1 = ui_xCreateLabelItem(buf,left,9*8,NULL,NULL);

    sbutton = ui_xCreateToggleItem("shuffle", left, NULL, title1, NULL);
    XtAddCallback(sbutton, XtNcallback, 
		  (XtCallbackProc) ui_rem_shuffleSubPatProc, NULL);

    subIPatDims = patt_info.in_number_of_dims;
    subOPatDims = patt_info.out_number_of_dims;

    above = sbutton;

    for (i=0; i< subIPatDims; i++) {
        sprintf(buf,"dim %d :",i+1);
	lab1 = ui_xCreateLabelItem(buf, left, 7*8, NULL, above);

	sbutton = ui_xCreateButtonItem("first",left,lab1,above);
	XtAddCallback(sbutton, XtNcallback, 
		      (XtCallbackProc)ui_rem_moveInSubPattProc,
		      (caddr_t)(SP_FIRST + i*10));
	
	sbutton = ui_xCreateButtonItem("prev",left, sbutton, above);
	XtAddCallback(sbutton, XtNcallback, 
		      (XtCallbackProc)ui_rem_moveInSubPattProc,
		      (caddr_t)(SP_PREVIOUS + i*10));

	sbutton = ui_xCreateButtonItem("next",left, sbutton, above);
	XtAddCallback(sbutton, XtNcallback, 
		      (XtCallbackProc) ui_rem_moveInSubPattProc,
		      (caddr_t) (SP_NEXT + i*10));

	sbutton = ui_xCreateButtonItem("last",left, sbutton, above);
	XtAddCallback(sbutton, XtNcallback,
		      (XtCallbackProc) ui_rem_moveInSubPattProc,
		      (caddr_t) (SP_LAST + i*10));
	
	above = lab1;
    }

    n = 0;
    XtSetArg(args[n], XtNborderWidth,  1); n++;
    XtSetArg(args[n], XtNfromHoriz, left); n++;
    XtSetArg(args[n], XtNfromVert, title1); n++;
    input  = XtCreateManagedWidget("input", formWidgetClass, form, args, n);
    ipos  = ui_xCreateLabelItem("Pos ",input,4*8,NULL,NULL);
    itot  = ui_xCreateLabelItem("Tot ",input,4*8,ipos,NULL);
    isize = ui_xCreateLabelItem("Size",input,4*8,itot,NULL);
    istep = ui_xCreateLabelItem("Step",input,4*8,isize,NULL);

    above = ipos;

    for (i=0; i< subIPatDims; i++) {
        sprintf(buf," %d",subIPatPos[i]);
	subIPatPosW[i] = ui_xCreateLabelItem(buf,input,4*8,NULL,above);

        sprintf(buf," %d",descrip.input_dim_sizes[i]);
	in_dim_widgets[i] = ui_xCreateLabelItem(buf,input,5*8,
						   subIPatPosW[i],above);
        sprintf(buf,"%d",subIPatSize[i]);
        subIPatSizeW[i] = ui_xCreateDialogItem("param",input,buf,4*8,
					       in_dim_widgets[i],above);

        sprintf(buf,"%d",subIPatStep[i]);
	subIPatStepW[i] = ui_xCreateDialogItem("param",input,buf,4*8, 
					       subIPatSizeW[i],above);

	above = subIPatPosW[i];

    }

    n = 0;
    XtSetArg(args[n], XtNborderWidth,  1); n++;
    XtSetArg(args[n], XtNfromHoriz, input); n++;
    XtSetArg(args[n], XtNfromVert, title2); n++;
    output = XtCreateManagedWidget("output",formWidgetClass,form,args,n);
    opos  = ui_xCreateLabelItem("Pos ",output,4*8,NULL,NULL);
    otot  = ui_xCreateLabelItem("Tot ",output,4*8,opos,NULL);
    osize = ui_xCreateLabelItem("Size",output,4*8,otot,NULL);
    ostep = ui_xCreateLabelItem("Step",output,4*8,osize,NULL);
    
    above = opos;

    for (i=0; i<subOPatDims; i++) {
        sprintf(buf," %d",subOPatPos[i]);
	subOPatPosW[i]  = ui_xCreateLabelItem(buf,output,4*8,NULL,above);

        sprintf(buf," %d",descrip.output_dim_sizes[i]);
        out_dim_widgets[i] = ui_xCreateLabelItem(buf,output,5*8,
						    subOPatPosW[i],above);
        sprintf(buf,"%d",subOPatSize[i]);
        subOPatSizeW[i] = ui_xCreateDialogItem("param",output,buf,4*8,
					       out_dim_widgets[i],above);

        sprintf(buf,"%d",subOPatStep[i]);
        subOPatStepW[i] = ui_xCreateDialogItem("param",output,buf,4*8, 
					       subOPatSizeW[i],above);

	above = subOPatStepW[i];

    }

    
    subPatDoneW = ui_xCreateButtonItem("done", ui_pop, NULL, form);
    XtAddCallback(subPatDoneW, XtNcallback, (XtCallbackProc) ui_popupDone, 
		  (caddr_t) UI_POPUP_SUBPATTERN);
                  /*!*/  /* constant name is meaningless ! */

    ui_checkWindowPosition(ui_popPattern);
    XtPopup(ui_popPattern, XtGrabNone);
    ui_xDontResizeWidget(ui_popPattern); 
    SubPatPanel = 1;
}




/*****************************************************************************
  FUNCTION : ui_rem_usePattSet

  PURPOSE  : Switches between different pattern sets
  RETURNS  : void
  NOTES    :

  UPDATE   : 13.09.1991
******************************************************************************/
void ui_rem_usePattSet (Widget button, int setNo, caddr_t call_data)
{
    int error;


    if(CURR_PATTERN_SET == setNo)
	return;

    if((error = krui_setCurrPatSet(setNo)) < 0){
	ui_checkError(error);
	return;
    }

    CURR_PATTERN_SET = setNo;
    ui_noOfCurrentPattern = 1;
    ui_xSetLabel(ui_showPattFile, PATTERN_SET_FILE[CURR_PATTERN_SET]);


    /* refresh the subpattern panel */
    ui_rem_defSubPat(button,1,(caddr_t)1);

    /* refresh the pattern panel */
    ui_rem_displayPatternNumber();
}




/*****************************************************************************
  FUNCTION : ui_rem_delPattSet

  PURPOSE  : deletes a pattern set
  RETURNS  : void
  NOTES    : DELPattFileWidget[0] and USEPattFileWidget[0] ALWAYS have 
             callbacks defined, even when the label shows "No Files" !
	     This function has to take care that nothing happens in case no 
	     files are present

  UPDATE   : 11.11.1991
******************************************************************************/
void ui_rem_delPattSet (Widget button, int setNo, caddr_t call_data)
{
    Arg arg[10];
    char buf[80];
    int  i;
    Widget tempWidget;


    if(NO_OF_PATTERN_SETS == 0)
	return;

    /* check whether the pattern to be deleted is the current one */

    NO_OF_PATTERN_SETS--;
    if(CURR_PATTERN_SET == setNo){
	if(CURR_PATTERN_SET == NO_OF_PATTERN_SETS)
	    CURR_PATTERN_SET = 0;          /* make the first one current */
	else
	    CURR_PATTERN_SET = NO_OF_PATTERN_SETS;
	                                   /* make the last one current */
	if(NO_OF_PATTERN_SETS == 0){       /* it was the only one        */
	    sprintf(buf,"Patternfile ?");
	    ui_xSetLabel(ui_showPattFile, buf);
	    PATTERN_SET_FILE[0] = NULL;
	    XtRemoveAllCallbacks(USEPattFileWidget[0],XtNcallback);
	    XtRemoveAllCallbacks(DELPattFileWidget[0],XtNcallback);
	    tempWidget = XtParent(USEPattFileWidget[0]);
	    XtDestroyWidget(USEPattFileWidget[0]);
	    USEPattFileWidget[0] = 
		XtCreateManagedWidget("No Files", smeBSBObjectClass, 
				      tempWidget, NULL, 0);
	    XtAddCallback(USEPattFileWidget[0], XtNcallback, 
			  (XtCallbackProc)ui_rem_usePattSet,(caddr_t)0);
	    tempWidget = XtParent(DELPattFileWidget[0]);
	    XtDestroyWidget(DELPattFileWidget[0]);
	    DELPattFileWidget[0] = 
		XtCreateManagedWidget("No Files", smeBSBObjectClass, 
				      tempWidget, NULL, 0);
	    XtAddCallback(DELPattFileWidget[0], XtNcallback, 
			  (XtCallbackProc)ui_rem_delPattSet,(caddr_t)0);
	    if(SubPatPanel == 1)
		ui_popupDone(tempWidget, UI_POPUP_SUBPATTERN , (caddr_t) 0);

	}else{
	    sprintf(buf,"%s",PATTERN_SET_FILE[CURR_PATTERN_SET]);
	}
	ui_xSetLabel(ui_showPattFile, buf);
    }

    /* delete the pattern set now */

    ui_checkError(krui_deletePatSet(setNo));

    if(NO_OF_PATTERN_SETS == 0)	return;

    /* kernel needs resetting of current pattern */
    if(CURR_PATTERN_SET < setNo)
	krui_setCurrPatSet(CURR_PATTERN_SET);
    else
	krui_setCurrPatSet(--CURR_PATTERN_SET);


    /* refresh the subpattern panel */
	
    ui_rem_defSubPat(button,1,(caddr_t)1);


    /* Compact the array of pattern file names and relabel the menus*/

    for(i=setNo; i<NO_OF_PATTERN_SETS; i++){
	strcpy(PATTERN_SET_FILE[i],PATTERN_SET_FILE[i+1]);
	XtSetArg(arg[0],XtNlabel,PATTERN_SET_FILE[i]);
	XtSetValues(USEPattFileWidget[i],arg,1);
	XtSetValues(DELPattFileWidget[i],arg,1);
    }

    /* destroy the widgets corresponding to the deleted pattern */

    if(NO_OF_PATTERN_SETS > 0){
	XtRemoveAllCallbacks(USEPattFileWidget[NO_OF_PATTERN_SETS],XtNcallback);
	XtRemoveAllCallbacks(DELPattFileWidget[NO_OF_PATTERN_SETS],XtNcallback);
	XtDestroyWidget(USEPattFileWidget[NO_OF_PATTERN_SETS]);
	XtDestroyWidget(DELPattFileWidget[NO_OF_PATTERN_SETS]);
	USEPattFileWidget[NO_OF_PATTERN_SETS] = NULL;
	DELPattFileWidget[NO_OF_PATTERN_SETS] = NULL;
    }

}



/*****************************************************************************
  FUNCTION : ui_rem_updatePattList

  PURPOSE  : Updates the lists of available pattern sets.
             Both the list under the DEL and the USE button are updated.
  RETURNS  : void
  NOTES    : Remote panel has to be created before the call to this function

  UPDATE   : 13.09.1991
******************************************************************************/
void ui_rem_updatePattList (void)
{

    Widget entry;
    int i;
    int n = 1;
    Arg arg[10];
    char temp[80];


    /* check whether any pattern files are loaded */
 
    if(PATTERN_SET_FILE[CURR_PATTERN_SET] != NULL){

	for(i=0; i<NO_OF_PATTERN_SETS;i++){       /* for all available files */
	    XtSetArg(arg[0],XtNlabel,PATTERN_SET_FILE[i]);

	    /* if the widgets do not exist already, create them now */
	    /* else update only their labels                        */

	    if(USEPattFileWidget[i] == NULL){
		USEPattFileWidget[i] = 
		    XtCreateManagedWidget(PATTERN_SET_FILE[i],
					  smeBSBObjectClass,
					  REM_UFileMenu,NULL,0);
		XtAddCallback(USEPattFileWidget[i], XtNcallback, 
			      (XtCallbackProc)ui_rem_usePattSet,(caddr_t)i);
	    }else{
		XtSetValues(USEPattFileWidget[i],arg,n);
	    }

	    if(DELPattFileWidget[i] == NULL){
		DELPattFileWidget[i] = 
		    XtCreateManagedWidget(PATTERN_SET_FILE[i],
					  smeBSBObjectClass,
 					  REM_DFileMenu,NULL,0);
		XtAddCallback(DELPattFileWidget[i], XtNcallback, 
			      (XtCallbackProc)ui_rem_delPattSet,(caddr_t)i);
	    }else{
		XtSetValues(DELPattFileWidget[i],arg,n);
	    }
	}

    }else{

	/* if no files are loaded make a comment */
	USEPattFileWidget[0] = 
	    XtCreateManagedWidget("No Files",smeBSBObjectClass, 
				  REM_DFileMenu, NULL, 0);
    }
}



/*****************************************************************************
  FUNCTION : ui_rem_resetSubPat

  PURPOSE  : resets the values of the subpattern panel
  RETURNS  : void
  NOTES    :

  UPDATE   : 16.09.1993
******************************************************************************/
static void ui_rem_resetSubPat (void)
{

    int                i;

    for(i=0; i< subIPatDims; i++) subIPatPos[i] = 1;
    for(i=0; i< subOPatDims; i++) subOPatPos[i] = 1;
    
    ui_rem_setSubPatPanel();

}


/*****************************************************************************
  FUNCTION : ui_rem_setSubPatPanel

  PURPOSE  : sets all values for the subpattern panel
  RETURNS  : void
  NOTES    :

  UPDATE   : 16.09.1993
******************************************************************************/
static void ui_rem_setSubPatPanel (void)
{

    char               buf[20];
    int                i;
    pattern_set_info   patt_info;
    pattern_descriptor descrip;
    krui_err           error;

    if(SubPatPanel == 1){
	if((error = krui_GetPatInfo(&patt_info, &descrip))< 0){
	    ui_checkError(error);
	    return;
	}
	for (i=0; i< subIPatDims; i++) {
	    sprintf(buf," %d",subIPatPos[i]);
	    ui_xSetLabel(subIPatPosW[i],buf);
	    sprintf(buf," %d",subIPatStep[i]);
	    ui_xSetLabel(subIPatStepW[i],buf);
	    sprintf(buf," %d",descrip.input_dim_sizes[i]);
	    ui_xSetLabel(in_dim_widgets[i],buf);
	} 
	for (i=0; i< subOPatDims; i++) {
	    sprintf(buf," %d",subOPatPos[i]);
	    ui_xSetLabel(subOPatPosW[i],buf);
	    sprintf(buf," %d",subOPatStep[i]);
	    ui_xSetLabel(subOPatStepW[i],buf);
	    sprintf(buf," %d",descrip.output_dim_sizes[i]);
	    ui_xSetLabel(out_dim_widgets[i],buf);
	} 
    }


}

/*****************************************************************************
  FUNCTION : ui_rem_getSubPatPanel

  PURPOSE  : read all values from the subpattern panel
  RETURNS  : void
  NOTES    :

  UPDATE   : 16.09.1993
******************************************************************************/
void ui_rem_getSubPatPanel (void)
{
    int i;

    if(SubPatPanel == 1){
	for(i=0; i<subIPatDims; i++) {
	    subIPatStep[i] = ui_xIntFromAsciiWidget(subIPatStepW[i]);
	    subIPatSize[i] = ui_xIntFromAsciiWidget(subIPatSizeW[i]);
	}
	for(i=0; i<subOPatDims; i++) {
	    subOPatStep[i] = ui_xIntFromAsciiWidget(subOPatStepW[i]);
	    subOPatSize[i] = ui_xIntFromAsciiWidget(subOPatSizeW[i]);
	}
    }
}
/* end of file */
/* lines: 1656 */


