/** \file param.c * Handle all the dialog box creation stuff. */ /* XTrkCad - Model Railroad CAD * Copyright (C) 2005 Dave Bullis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" #include "compound.h" #include "custom.h" #include "fileio.h" #include "misc.h" #include "param.h" #include "track.h" #include "common-ui.h" EXPORT int paramHiliteFast = FALSE; /* Bogus reg vars */ EXPORT int paramLevel = 1; EXPORT int paramLen; EXPORT unsigned long paramKey; EXPORT char paramId[100]; EXPORT BOOL_T paramTogglePlaybackHilite; EXPORT char *PREFSECT = "DialogItem"; static int paramCheckErrorCount = 0; static BOOL_T paramCheckShowErrors = FALSE; static int log_paramLayout = 0; static int log_paraminput = 0; /***************************************************************************** * * * */ static char * getNumberError; static char decodeErrorStr[STR_SIZE]; static int GetDigitStr( char ** cpp, long * numP, int * lenP ) { char *cp=*cpp, *cq; size_t len; *numP = 0; if ( cp == NULL ) { getNumberError = N_("Unexpected End Of String"); return FALSE; } while ( isspace((unsigned char)*cp) ) cp++; *numP = strtol( cp, &cq, 10 ); if ( cp==cq ) { *cpp = cp; getNumberError = N_("Expected digit"); return FALSE; } len = cq-cp; if ( lenP ) *lenP = (int)len; if ( len > 9 ) { getNumberError = N_("Overflow"); return FALSE; } while ( isspace((unsigned char)*cq) ) cq++; *cpp = cq; return TRUE; } static int GetNumberStr( char ** cpp, FLOAT_T * numP, BOOL_T * hasFract ) { long n0=0, f1, f2; int l1; char * cp = NULL; struct lconv *lc; while ( isspace((unsigned char)**cpp) ) (*cpp)++; /* Find out the decimal separator of the current locale */ lc = localeconv(); if ( **cpp != lc->decimal_point[0] && !GetDigitStr( cpp, &n0, NULL ) ) return FALSE; if ( **cpp == lc->decimal_point[0] ) { (*cpp)++; if ( !isdigit((unsigned char)**cpp) ) { *hasFract = FALSE; *numP = (FLOAT_T)n0; return TRUE; } if ( !GetDigitStr( cpp, &f1, &l1 ) ) return FALSE; for ( f2=1; l1>0; l1-- ) f2 *= 10; *numP = ((FLOAT_T)n0)+((FLOAT_T)f1)/((FLOAT_T)f2); *hasFract = TRUE; return TRUE; /* 999.999 */ } if ( isdigit( (unsigned char)**cpp ) ) { cp = *cpp; if ( !GetDigitStr( cpp, &f1, NULL ) ) return FALSE; } else { f1 = n0; n0 = 0; } if ( **cpp == '/' ) { (*cpp)++; if ( !GetDigitStr( cpp, &f2, &l1 ) ) return FALSE; if ( f2 == 0 ) { (*cpp) -= l1; getNumberError = N_("Divide by 0"); return FALSE; /* div by 0 */ } *numP = ((FLOAT_T)n0)+((FLOAT_T)f1)/((FLOAT_T)f2); *hasFract = TRUE; } else { if ( cp != NULL ) { *cpp = cp; getNumberError = N_("Expected /"); return FALSE; /* 999 999 ?? */ } else { *hasFract = FALSE; *numP = f1; } } return TRUE; } //extern wIndex_t distanceFormatInx; // distanceFormatInx static BOOL_T GetDistance(char ** cpp, FLOAT_T * distP) { FLOAT_T n1, n2; BOOL_T neg = FALSE; BOOL_T hasFract; BOOL_T expectInch = FALSE; long distanceFormat; while (isspace((unsigned char)**cpp)) { (*cpp)++; } if ((*cpp)[0] == '\0') { *distP = 0.0; return TRUE; } if ((*cpp)[0] == '-') { neg = TRUE; (*cpp)++; } if (!GetNumberStr(cpp, &n1, &hasFract)) { return FALSE; } distanceFormat = GetDistanceFormat(); if ((*cpp)[0] == '\0') { /* EOL */ if (units==UNITS_METRIC) { n1 = n1/2.54; if ((distanceFormat & DISTFMT_FMT) == DISTFMT_FMT_MM) { n1 /= 10; } if ((distanceFormat & DISTFMT_FMT) == DISTFMT_FMT_M) { n1 *= 100; } } if (neg) { n1 = -n1; } *distP = n1; return TRUE; } if ((*cpp)[0] == '\'') { n1 *= 12.0; (*cpp) += 1; expectInch = !hasFract; } else if (tolower((unsigned char)(*cpp)[0]) == 'f' && tolower((unsigned char)(*cpp)[1]) == 't') { n1 *= 12.0; (*cpp) += 2; expectInch = !hasFract; } else if (tolower((unsigned char)(*cpp)[0]) == 'c' && tolower((unsigned char)(*cpp)[1]) == 'm') { n1 /= 2.54; (*cpp) += 2; } else if (tolower((unsigned char)(*cpp)[0]) == 'm' && tolower((unsigned char)(*cpp)[1]) == 'm') { n1 /= 25.4; (*cpp) += 2; } else if (tolower((unsigned char)(*cpp)[0]) == 'm') { n1 *= 100.0/2.54; (*cpp) += 1; } else if ((*cpp)[0] == '"') { (*cpp) += 1; } else if (tolower((unsigned char)(*cpp)[0]) == 'i' && tolower((unsigned char)(*cpp)[1]) == 'n') { (*cpp) += 2; } else { getNumberError = N_("Invalid Units Indicator"); return FALSE; } while (isspace((unsigned char)**cpp)) { (*cpp)++; } if (expectInch && isdigit((unsigned char)**cpp)) { if (!GetNumberStr(cpp, &n2, &hasFract)) { return FALSE; } n1 += n2; if ((*cpp)[0] == '"') { (*cpp) += 1; } else if (tolower((unsigned char)(*cpp)[0]) == 'i' && tolower((unsigned char)(*cpp)[1]) == 'n') { (*cpp) += 2; } while (isspace((unsigned char)**cpp)) { (*cpp)++; } } if (**cpp) { getNumberError = N_("Expected End Of String"); return FALSE; } if (neg) { n1 = -n1; } *distP = n1; return TRUE; } EXPORT FLOAT_T DecodeFloat( wString_p strCtrl, BOOL_T * validP ) { FLOAT_T valF; const char *cp0, *cp1; char *cp2; cp0 = cp1 = wStringGetValue( strCtrl ); while (isspace((unsigned char)*cp1)) cp1++; if ( *cp1 ) { valF = strtod( cp1, &cp2 ); if ( *cp2 != 0 ) { /*wStringSetHilight( strCtrl, cp2-cp0, -1 );*/ snprintf( decodeErrorStr, sizeof(decodeErrorStr), _("Invalid Number") ); *validP = FALSE; return 0.0; } *validP = TRUE; return valF; } else { *validP = TRUE; return 0.0; } } FLOAT_T DecodeDistance( wString_p strCtrl, BOOL_T * validP) { FLOAT_T valF; char *cp0, *cp1, *cpN, c1; // CAST_AWAY_CONST: we temporarily replace *cpN with a NULL and later restore cp0 = cp1 = cpN = CAST_AWAY_CONST wStringGetValue(strCtrl); cpN += strlen(cpN)-1; while (cpN > cp1 && isspace((unsigned char)*cpN)) { cpN--; } c1 = *cpN; switch (c1) { case '=': case 's': case 'S': case 'p': case 'P': *cpN = '\0'; break; default: cpN = NULL; } *validP = (GetDistance(&cp1, &valF)); if (cpN) { *cpN = c1; } if (*validP) { if (c1 == 's' || c1 == 'S') { valF *= curScaleRatio; } else if (c1 == 'p' || c1 == 'P') { valF /= curScaleRatio; } if (cpN) { wStringSetValue(strCtrl, FormatDistance(valF)); } } else { snprintf(decodeErrorStr, sizeof(decodeErrorStr), "%s @ %s", _(getNumberError), *cp1?cp1:_("End Of String")); valF = 0.0; } return valF; } #define N_STRING (10) static int formatStringInx; //Index ahead in case of overwrite static char formatStrings[N_STRING+1][80]; //Add safety EXPORT char * FormatLong( long valL ) { if ( ++formatStringInx >= N_STRING ) formatStringInx = 0; sprintf( formatStrings[formatStringInx], "%ld", valL ); return formatStrings[formatStringInx]; } EXPORT char * FormatFloat( FLOAT_T valF ) { if ( ++formatStringInx >= N_STRING ) formatStringInx = 0; sprintf( formatStrings[formatStringInx], "%0.3f", valF ); return formatStrings[formatStringInx]; } static void FormatFraction( char ** cpp, BOOL_T printZero, int digits, BOOL_T rational, FLOAT_T valF, char * unitFmt ) { char * cp = *cpp; long integ; long f1, f2; char * space = ""; if ( !rational ) { sprintf( cp, "%0.*f", digits, valF ); cp += strlen(cp); } else { integ = (long)floor(valF); valF -= (FLOAT_T)integ; for ( f2=1; digits>0; digits--,f2*=2 ); f1 = (long)floor( (valF*(FLOAT_T)f2) + 0.5 ); if ( f1 >= f2 ) { f1 -= f2; integ++; } if ( integ != 0 || !printZero ) { sprintf( cp, "%ld", integ ); cp += strlen(cp); printZero = FALSE; space = " "; } if ( f2 > 1 && f1 != 0 ) { while ( (f1&1) == 0 ) { f1 /= 2; f2 /= 2; } sprintf( cp, "%s%ld/%ld", space, f1, f2 ); cp += strlen(cp); } else if ( printZero ) { *cp++ = '0'; *cp = '\0'; } } if ( cp != *cpp ) { strcpy( cp, unitFmt ); cp += strlen(cp); *cpp = cp; } } EXPORT char * FormatDistanceEx( FLOAT_T valF, long distanceFormat ) { char * cp; int digits; long feet; char * metricInd; if ( ++formatStringInx >= N_STRING ) formatStringInx = 0; cp = formatStrings[formatStringInx]; digits = (int)(distanceFormat&DISTFMT_DECS); valF = PutDim(valF); if ( valF < 0 ) { *cp++ = '-'; valF = -valF; } if ( (distanceFormat&DISTFMT_FMT) == DISTFMT_FMT_NONE ) { FormatFraction( &cp, FALSE, digits, (distanceFormat&DISTFMT_FRACT) == DISTFMT_FRACT_FRC, valF, "" ); return formatStrings[formatStringInx]; } else if ( units == UNITS_ENGLISH ) { feet = (long)(floor)(valF/12.0); valF -= feet*12.0; if ( feet != 0 ) { sprintf( cp, "%ld%s", feet, (distanceFormat&DISTFMT_FMT)==DISTFMT_FMT_SHRT?"' ":"ft " ); cp += strlen(cp); } if ( feet==0 || valF != 0 ) { FormatFraction( &cp, feet==0, digits, (distanceFormat&DISTFMT_FRACT) == DISTFMT_FRACT_FRC, valF, (distanceFormat&DISTFMT_FMT)==DISTFMT_FMT_SHRT?"\"":"in" ); } } else { if ( (distanceFormat&DISTFMT_FMT)==DISTFMT_FMT_M ) { valF = valF/100.0; metricInd = "m"; } else if ( (distanceFormat&DISTFMT_FMT)==DISTFMT_FMT_MM ) { valF = valF*10.0; metricInd = "mm"; } else { metricInd = "cm"; } FormatFraction( &cp, FALSE, digits, (distanceFormat&DISTFMT_FRACT) == DISTFMT_FRACT_FRC, valF, metricInd ); } return formatStrings[formatStringInx]; } EXPORT char * FormatDistance( FLOAT_T valF ) { return FormatDistanceEx( valF, GetDistanceFormat() ); } EXPORT char * FormatSmallDistance( FLOAT_T valF ) { long format = GetDistanceFormat(); format &= ~(DISTFMT_FRACT_FRC|DISTFMT_DECS); format |= 3; return FormatDistanceEx( valF, format ); } /***************************************************************************** * * * */ static wBool_t ParamIntegerRangeCheck( paramData_p p, long valL ); static wBool_t ParamFloatRangeCheck( paramData_p p, FLOAT_T valF ); EXPORT void ParamControlActive( paramGroup_p pg, int inx, BOOL_T active ) { paramData_p p = &pg->paramPtr[inx]; if ( p->control ) wControlActive( p->control, active ); } EXPORT void ParamLoadMessage( paramGroup_p pg, int inx, char * message ) { paramData_p p = &pg->paramPtr[inx]; if ( p->control ) { if ( p->type == PD_MESSAGE ) wMessageSetValue( (wMessage_p)p->control, message ); else if ( p->type == PD_STRING ) wStringSetValue( (wString_p)p->control, message ); else AbortProg( "paramLoadMessage: not a PD_MESSAGE or PD_STRING" ); } } EXPORT void ParamLoadControl( paramGroup_p pg, int inx ) { paramData_p p = &pg->paramPtr[inx]; FLOAT_T tmpR; char * valS; if ( (p->option&PDO_DLGIGNORE) != 0 ) { p->bInvalid = FALSE; return; } if (p->control == NULL || p->valueP == NULL) return; switch ( p->type ) { case PD_LONG: wStringSetValue( (wString_p)p->control, FormatLong( *(long*)p->valueP ) ); if ( !ParamIntegerRangeCheck( p, *(long*)p->valueP ) ) return; p->oldD.l = *(long*)p->valueP; break; case PD_RADIO: wRadioSetValue( (wChoice_p)p->control, *(long*)p->valueP ); p->oldD.l = *(long*)p->valueP; break; case PD_TOGGLE: wToggleSetValue( (wChoice_p)p->control, *(long*)p->valueP ); p->oldD.l = *(long*)p->valueP; break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: wListSetIndex( (wList_p)p->control, *(wIndex_t*)p->valueP ); p->oldD.l = *(wIndex_t*)p->valueP; break; case PD_COLORLIST: wColorSelectButtonSetColor( (wButton_p)p->control, *(wDrawColor*)p->valueP ); p->oldD.dc = *(wDrawColor*)p->valueP; break; case PD_FLOAT: tmpR = *(FLOAT_T*)p->valueP; if (p->option&PDO_DIM) { if (p->option&PDO_SMALLDIM) valS = FormatSmallDistance( tmpR ); else valS = FormatDistance( tmpR ); } else { if (p->option&PDO_ANGLE) tmpR = NormalizeAngle( (angleSystem==ANGLE_POLAR)?tmpR:-tmpR ); valS = FormatFloat( tmpR ); } wStringSetValue( (wString_p)p->control, valS ); if ( !ParamFloatRangeCheck( p, tmpR ) ) break; p->oldD.f = tmpR; break; case PD_STRING: if (p->oldD.s) MyFree( p->oldD.s ); ASSERT( p->max_string > 0 ); if (p->max_string) { p->oldD.s = MyMalloc(p->max_string); strncpy(p->oldD.s, (char*)p->valueP, p->max_string-1); *(p->oldD.s + (uint32_t)p->max_string - 1) = '\0'; wStringSetValue((wString_p)p->control, (char*)p->oldD.s); } else { p->oldD.s = MyStrdup((char *)p->valueP); wStringSetValue((wString_p)p->control, (char*)p->valueP); } if ( (p->option & PDO_NOTBLANK) && strlen( p->oldD.s ) == 0 ) { ParamHilite( p->group->win, p->control, TRUE ); p->bInvalid = TRUE; } break; case PD_MESSAGE: wMessageSetValue( (wMessage_p)p->control, _((char*)p->valueP) ); break; case PD_TEXT: wTextClear( (wText_p)p->control ); wTextAppend( (wText_p)p->control, (char*)p->valueP ); break; case PD_BUTTON: case PD_DRAW: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } /** Load all the controls in a parameter group. * \param IN pointer to parameter group to be loaded */ EXPORT void ParamLoadControls( paramGroup_p pg ) { int inx; LOG( log_paraminput, 1, ( "ParamLoadControls( %s )\n", pg->nameStr ) ); for ( inx=0; inxparamCnt; inx++ ) ParamLoadControl( pg, inx ); } EXPORT long ParamUpdate( paramGroup_p pg ) { long longV; FLOAT_T floatV; const char * stringV; wDrawColor dc; long change = 0; int inx; paramData_p p; BOOL_T valid; for ( p=pg->paramPtr,inx=0; p<&pg->paramPtr[pg->paramCnt]; p++,inx++ ) { if ( (p->option&PDO_DLGIGNORE) != 0 ) continue; if ( p->control == NULL ) continue; if ( p->bInvalid == TRUE ) break; switch ( p->type ) { case PD_LONG: stringV = wStringGetValue( (wString_p)p->control ); longV = atol( stringV ); if ( ! ParamIntegerRangeCheck( p, longV ) ) break; if (longV != p->oldD.l) { p->oldD.l = longV; if ( p->valueP) *(long*)p->valueP = longV; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) pg->changeProc( pg, inx, &longV ); change |= (1L<control ); if (longV != p->oldD.l) { p->oldD.l = longV; if ( p->valueP) *(long*)p->valueP = longV; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) pg->changeProc( pg, inx, &longV ); change |= (1L<control ); if (longV != p->oldD.l) { p->oldD.l = longV; if ( p->valueP) *(long*)p->valueP = longV; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) pg->changeProc( pg, inx, &longV ); change |= (1L<control ); if (longV != p->oldD.l) { p->oldD.l = longV; if ( p->valueP) *(wIndex_t*)p->valueP = (wIndex_t)longV; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) pg->changeProc( pg, inx, &longV ); change |= (1L<control ); if (dc != p->oldD.dc) { p->oldD.dc = dc; if ( p->valueP) *(wDrawColor*)p->valueP = dc; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) { pg->changeProc( pg, inx, &longV ); /* COLORNOP */ } change |= (1L<option & PDO_DIM) { floatV = DecodeDistance( (wString_p)p->control, &valid ); } else { floatV = DecodeFloat( (wString_p)p->control, &valid ); if (valid && (p->option & PDO_ANGLE) ) floatV = NormalizeAngle( (angleSystem==ANGLE_POLAR)?floatV:-floatV ); } if ( !valid ) break; if ( ! ParamFloatRangeCheck( p, floatV ) ) break; if (floatV != p->oldD.f) { p->oldD.f = floatV; if ( p->valueP) *(FLOAT_T*)p->valueP = floatV; if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) pg->changeProc( pg, inx, &floatV ); change |= (1L<control ); if ( (p->option & PDO_NOTBLANK) && stringV [0] == '\0' ) { p->bInvalid = TRUE; break; } if ( strcmp( stringV, p->oldD.s ) != 0 ) { if (p->oldD.s) MyFree( p->oldD.s ); p->oldD.s = MyStrdup( stringV ); if ( p->valueP ) { strncpy((char*)p->valueP, stringV, p->max_string-1); ((char *)p->valueP)[p->max_string - 1] = '\0'; if (strlen(stringV) > p->max_string-1) { NoticeMessage2(0, MSG_ENTERED_STRING_TRUNCATED, _("Ok"), NULL, p->max_string-1); } } if ( (p->option&PDO_NOUPDACT)==0 && pg->changeProc) // CAST_AWAY_CONST: param 3 should be const but its a big change pg->changeProc( pg, inx, CAST_AWAY_CONST stringV ); change |= (1L<proc) pg->proc( PGACT_UPDATE, change ); #endif return change; } void ParamLoadData( paramGroup_p pg) { FLOAT_T floatV; const char * stringV; paramData_p p; BOOL_T valid; BOOL_T inRange; for (p=pg->paramPtr; p<&pg->paramPtr[pg->paramCnt]; p++) { if ((p->option&PDO_DLGIGNORE) != 0) { continue; } if (p->control == NULL || p->valueP == NULL) { continue; } switch (p->type) { long longV; case PD_LONG: longV = atol(wStringGetValue((wString_p)p->control)); if (p->winData) { inRange = (longV <= ((paramIntegerRange_t *)p->winData)->high) && (longV >= ((paramIntegerRange_t *)p->winData)->low); } else { inRange = TRUE; } if (inRange) { *(long*)p->valueP = longV; } break; case PD_RADIO: *(long*)p->valueP = wRadioGetValue((wChoice_p)p->control); break; case PD_TOGGLE: *(long*)p->valueP = wToggleGetValue((wChoice_p)p->control); break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: *(wIndex_t*)p->valueP = wListGetIndex((wList_p)p->control); break; case PD_COLORLIST: *(wDrawColor*)p->valueP = wColorSelectButtonGetColor((wButton_p)p->control); break; case PD_FLOAT: if (p->option & PDO_DIM) { floatV = DecodeDistance((wString_p)p->control, &valid); } else { floatV = DecodeFloat((wString_p)p->control, &valid); if (valid && (p->option & PDO_ANGLE)) { floatV = NormalizeAngle((angleSystem==ANGLE_POLAR)?floatV:-floatV); } } if (p->winData) { inRange = (floatV <= ((paramFloatRange_t *)p->winData)->high) && (floatV >= ((paramFloatRange_t *)p->winData)->low); } else { inRange = TRUE; } if (valid && inRange) { *(FLOAT_T*)p->valueP = floatV; } break; case PD_STRING: stringV = wStringGetValue((wString_p)p->control); strcpy((char*)p->valueP, stringV); break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } } static long ParamIntRestore( paramGroup_p pg, int class ) { long change = 0; int inx; paramData_p p; FLOAT_T valR; char * valS; paramOldData_t * oldP; for ( p=pg->paramPtr,inx=0; p<&pg->paramPtr[pg->paramCnt]; p++,inx++ ) { oldP = (class==0)?&p->oldD:&p->demoD; if ( (p->option&PDO_DLGIGNORE) != 0 ) continue; if (p->valueP == NULL) continue; switch ( p->type ) { case PD_LONG: if ( *(long*)p->valueP != oldP->l ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(long*)p->valueP = oldP->l; if (p->control) { wStringSetValue( (wString_p)p->control, FormatLong( oldP->l ) ); } change |= (1L<valueP != oldP->l ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(long*)p->valueP = oldP->l; if (p->control) wRadioSetValue( (wChoice_p)p->control, oldP->l ); change |= (1L<valueP != oldP->l ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(long*)p->valueP = oldP->l; if (p->control) wToggleSetValue( (wChoice_p)p->control, oldP->l ); change |= (1L<valueP != (wIndex_t)oldP->l ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(wIndex_t*)p->valueP = (wIndex_t)oldP->l; if (p->control) wListSetIndex( (wList_p)p->control, (wIndex_t)oldP->l ); change |= (1L<valueP != oldP->dc ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(wDrawColor*)p->valueP = oldP->dc; if (p->control) wColorSelectButtonSetColor( (wButton_p)p->control, oldP->dc ); /* COLORNOP */ change |= (1L<valueP != oldP->f ) { /*if ((p->option&PDO_NORSTUPD)==0)*/ *(FLOAT_T*)p->valueP = oldP->f; if (p->control) { valR = oldP->f; if (p->option & PDO_DIM) { if (p->option & PDO_SMALLDIM) valS = FormatSmallDistance( valR ); else valS = FormatDistance( valR ); } else { if (p->option & PDO_ANGLE) valR = NormalizeAngle( (angleSystem==ANGLE_POLAR)?valR:-valR ); valS = FormatFloat( valR ); } wStringSetValue( (wString_p)p->control, valS ); } change |= (1L<s && strcmp((char*)p->valueP,oldP->s) != 0 ) { ((char*)p->valueP)[0] = '\0'; strncat((char*)p->valueP,oldP->s,p->max_string-1); if (p->control) wStringSetValue( (wString_p)p->control, (char*)p->valueP ); change |= (1L<proc) pg->proc( PGACT_RESTORE, change ); #endif return change; } static void ParamIntSave( paramGroup_p pg, int class ) { paramData_p p; paramOldData_t * oldP; for ( p=pg->paramPtr; p<&pg->paramPtr[pg->paramCnt]; p++ ) { oldP = (class==0)?&p->oldD:&p->demoD; if (p->valueP) { switch (p->type) { case PD_LONG: case PD_RADIO: case PD_TOGGLE: oldP->l = *(long*)p->valueP; break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: oldP->l = *(wIndex_t*)p->valueP; break; case PD_COLORLIST: oldP->dc = *(wDrawColor*)p->valueP; break; case PD_FLOAT: oldP->f = *(FLOAT_T*)p->valueP; break; case PD_STRING: if (oldP->s) MyFree(oldP->s); oldP->s = MyStrdup( (char*)p->valueP ); break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } } } #ifdef LATER static void ParamSave( paramGroup_p pg ) { ParamIntSave( pg, 0 ); } static long ParamRestore( paramGroup_p pg ) { return ParamIntRestore( pg, 0 ); } #endif /**************************************************************************** * * * */ static dynArr_t paramGroups_da; #define paramGroups(N) DYNARR_N( paramGroup_p, paramGroups_da, N ) static BOOL_T paramGroups_init = FALSE; EXPORT void ParamRegister( paramGroup_p pg ) { paramData_t * p; const char * cp; WDOUBLE_T tmpR; long valL; long rgb; char prefName1[STR_SHORT_SIZE]; const char *prefSect2, *prefName2; if (!paramGroups_init) ParamInit(); DYNARR_APPEND( paramGroup_p, paramGroups_da, 10 ); paramGroups(paramGroups_da.cnt-1) = pg; int i; for ( i=0, p=pg->paramPtr; i<(pg->paramCnt); p++, i++ ) { p->group = pg; if ( p->nameStr == NULL ) continue; snprintf( prefName1, sizeof(prefName1), "%s-%s", pg->nameStr, p->nameStr ); if ( p->type != PD_MENUITEM ) { (void)GetBalloonHelpStr( prefName1 ); } if (p->valueP == NULL || (p->option&PDO_NOPREF) != 0) continue; prefSect2 = PREFSECT; prefName2 = prefName1; if ( (p->option&PDO_MISC) ) { prefSect2 = "misc"; prefName2 = p->nameStr; } else if ( (p->option&PDO_DRAW) ) { prefSect2 = "draw"; prefName2 = p->nameStr; } else if ( (p->option&PDO_FILE) ) { prefSect2 = "file"; prefName2 = p->nameStr; } else if ( (pg->options&PGO_PREFGROUP) ) { prefSect2 = pg->nameStr; prefName2 = p->nameStr; } else if ( (pg->options&PGO_PREFMISC) ) { prefSect2 = "misc"; prefName2 = p->nameStr; } else if ( (pg->options&PGO_PREFMISCGROUP) ) { prefSect2 = "misc"; } else if ( (pg->options&PGO_PREFDRAWGROUP) ) { prefSect2 = "draw"; } cp = strchr( p->nameStr, '\t' ); if ( cp ) { /* *cp++ = 0; */ prefSect2 = cp; cp = strchr( cp, '\t' ); if ( cp ) { /* *cp++ = 0; */ prefName2 = cp; } } switch (p->type) { case PD_LONG: case PD_RADIO: case PD_TOGGLE: if ( !wPrefGetInteger( PREFSECT, prefName1, p->valueP, *(long*)p->valueP )) wPrefGetInteger( prefSect2, prefName2, p->valueP, *(long*)p->valueP ); break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: if ( (p->option&PDO_LISTINDEX) ) { if (!wPrefGetInteger( PREFSECT, prefName1, &valL, *(wIndex_t*)p->valueP )) wPrefGetInteger( prefSect2, prefName2, &valL, valL ); if ( p->control ) wListSetIndex( (wList_p)p->control, (wIndex_t)valL ); *(wIndex_t*)p->valueP = (wIndex_t)valL; } else { if (!p->control) break; cp = wPrefGetString( PREFSECT, prefName1 ); if ( !cp ) cp = wPrefGetString( prefSect2, prefName2 ); if ( !cp ) break; *(wIndex_t*)p->valueP = wListFindValue( (wList_p)p->control, cp ); } break; case PD_COLORLIST: rgb = wDrawGetRGB( *(wDrawColor*)p->valueP ); if (!wPrefGetInteger( PREFSECT, prefName1, &rgb, rgb )) wPrefGetInteger( prefSect2, prefName2, &rgb, rgb ); *(wDrawColor*)p->valueP = wDrawFindColor( rgb ); break; case PD_FLOAT: if (!wPrefGetFloat( PREFSECT, prefName1, &tmpR, *(FLOAT_T*)p->valueP )) wPrefGetFloat( prefSect2, prefName2, &tmpR, *(FLOAT_T*)p->valueP ); *(FLOAT_T*)p->valueP = tmpR; break; case PD_STRING: cp = wPrefGetString( PREFSECT, prefName1 ); if (!cp) wPrefGetString( prefSect2, prefName2 ); if (cp) strcpy( p->valueP, cp ); else ((char*)p->valueP)[0] = '\0'; break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } } EXPORT void ParamUpdatePrefs( void ) { int inx; paramGroup_p pg; paramData_p p; long rgb; char prefName[STR_SHORT_SIZE]; size_t len; int col; char * cp; static wWinPix_t * colWidths; static int maxColCnt = 0; paramListData_t * listDataP; for ( inx=0; inxnameStr == NULL) continue; for ( p=pg->paramPtr; p<&pg->paramPtr[pg->paramCnt]; p++ ) { if (p->valueP == NULL || p->nameStr == NULL || (p->option&PDO_NOPREF)!=0 ) continue; if ( (p->option&PDO_DLGIGNORE) != 0 ) continue; snprintf( prefName, sizeof(prefName), "%s-%s", pg->nameStr, p->nameStr ); switch ( p->type ) { case PD_LONG: case PD_RADIO: case PD_TOGGLE: wPrefSetInteger( PREFSECT, prefName, *(long*)p->valueP ); break; case PD_LIST: listDataP = (paramListData_t*)p->winData; if ( p->control && listDataP->colCnt > 0 ) { if ( maxColCnt < listDataP->colCnt ) { if ( maxColCnt == 0 ) colWidths = (wWinPix_t*)MyMalloc( listDataP->colCnt * sizeof * colWidths ); else colWidths = (wWinPix_t*)MyRealloc( colWidths, listDataP->colCnt * sizeof * colWidths ); maxColCnt = listDataP->colCnt; } len = wListGetColumnWidths( (wList_p)p->control, listDataP->colCnt, colWidths ); cp = message; for ( col=0; coloption&PDO_LISTINDEX) ) { wPrefSetInteger( PREFSECT, prefName, *(wIndex_t*)p->valueP ); } else { if (p->control) { wListGetValues( (wList_p)p->control, message, sizeof message, NULL, NULL ); wPrefSetString( PREFSECT, prefName, message ); } } break; case PD_COLORLIST: rgb = wDrawGetRGB( *(wDrawColor*)p->valueP ); wPrefSetInteger( PREFSECT, prefName, rgb ); break; case PD_FLOAT: wPrefSetFloat( PREFSECT, prefName, *(FLOAT_T*)p->valueP ); break; case PD_STRING: wPrefSetString( PREFSECT, prefName, (char*)p->valueP ); break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } } } EXPORT void ParamGroupRecord( paramGroup_p pg ) { paramData_p p; long rgb; if (recordF == NULL) return; for ( p=pg->paramPtr; p<&pg->paramPtr[pg->paramCnt]; p++ ) { if ( (p->option&PDO_NORECORD) != 0 || p->valueP == NULL || p->nameStr == NULL ) continue; if ( (p->option&PDO_DLGIGNORE) != 0 ) continue; switch ( p->type ) { case PD_LONG: case PD_RADIO: case PD_TOGGLE: fprintf( recordF, "PARAMETER %s %s %ld\n", pg->nameStr, p->nameStr, *(long*)p->valueP ); break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: if (p->control) wListGetValues( (wList_p)p->control, message, sizeof message, NULL, NULL ); else message[0] = '\0'; fprintf( recordF, "PARAMETER %s %s %d %s\n", pg->nameStr, p->nameStr, *(wIndex_t*)p->valueP, message ); break; case PD_COLORLIST: rgb = wDrawGetRGB( *(wDrawColor*)p->valueP ); fprintf( recordF, "PARAMETER %s %s %ld\n", pg->nameStr, p->nameStr, rgb ); break; case PD_FLOAT: fprintf( recordF, "PARAMETER %s %s %0.3f\n", pg->nameStr, p->nameStr, *(FLOAT_T*)p->valueP ); break; case PD_STRING: fprintf( recordF, "PARAMETER %s %s %s\n", pg->nameStr, p->nameStr, (char*)p->valueP ); break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } } if (pg->nameStr) fprintf( recordF, "PARAMETER GROUP %s\n", pg->nameStr ); fflush( recordF ); } EXPORT void ParamStartRecord( void ) { int inx; paramGroup_p pg; if (recordF == NULL) return; for ( inx=0; inxoptions&PGO_RECORD) { ParamGroupRecord( pg ); } } } EXPORT void ParamRestoreAll( void ) { int inx; paramGroup_p pg; for ( inx=0; inx 0 ) { NoticeMessage( "PARAMCHECK: %d errors", "Ok", NULL, paramCheckErrorCount ); } } EXPORT void ParamSaveAll( void ) { int inx; for ( inx=0; inxaction = 0; } paramCheckErrorCount = 0; } static void ParamButtonPush( void * dp ) { paramData_p p = (paramData_p)dp; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s\n", p->group->nameStr, p->nameStr ); fflush( recordF ); } if ( (p->option&PDO_NOPSHACT)==0 ) { if ( p->valueP ) ((wButtonCallBack_p)(p->valueP))( p->context ); else if ( p->group->changeProc) p->group->changeProc( p->group, (int)(p-p->group->paramPtr), NULL); } } static void ParamChoicePush( long valL, void * dp ) { paramData_p p = (paramData_p)dp; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, valL ); fflush( recordF ); } if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) *((long*)(p->valueP)) = valL; if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc) p->group->changeProc( p->group, (int)(p-p->group->paramPtr), &valL); } static wBool_t ParamIntegerRangeCheck( paramData_p p, long valL ) { if ( inPlayback ) return TRUE; paramIntegerRange_t * irangeP = (paramIntegerRange_t*)p->winData; wBool_t bInvalid = p->bInvalid; if ( ( (irangeP->rangechecks&PDO_NORANGECHECK_HIGH) == 0 && valL > irangeP->high ) || ( (irangeP->rangechecks&PDO_NORANGECHECK_LOW) == 0 && valL < irangeP->low ) ) { if ( (irangeP->rangechecks&(PDO_NORANGECHECK_HIGH|PDO_NORANGECHECK_LOW)) == PDO_NORANGECHECK_HIGH ) sprintf( message, _("Enter a value > %ld"), irangeP->low ); else if ( (irangeP->rangechecks&(PDO_NORANGECHECK_HIGH|PDO_NORANGECHECK_LOW)) == PDO_NORANGECHECK_LOW ) sprintf( message, _("Enter a value < %ld"), irangeP->high ); else sprintf( message, _("Enter a value between %ld and %ld"), irangeP->low, irangeP->high ); wWinPix_t h = wControlGetHeight(p->control); wControlSetBalloon( p->control, 0, -h*3/4, message ); p->bInvalid = TRUE; LOG( log_paraminput, 1, ( " -> RangeError\n" ) ); ParamHilite( p->group->win, p->control, p->bInvalid ); return FALSE; } p->bInvalid = FALSE; return TRUE; } static void ParamIntegerPush( const char * val, void * dp ) { paramData_p p = (paramData_p)dp; long valL; char * cp; const char * value; wBool_t bInvalid = p->bInvalid; if (strlen(val) == 1 && val[strlen(val)-1] == '\n') { value = wStringGetValue((wString_p)p->control); p->enter_pressed = TRUE; } else { value = val; p->enter_pressed = FALSE; } LOG( log_paraminput, 1, ( "ParamIntegerPush( %s Enter:%d Val:%s )\n", p->nameStr, p->enter_pressed, value ) ); valL = strtol( value, &cp, 10 ); for ( ; isspace( (unsigned char)*cp); cp++ ); if ( *cp != '\0' ) { wWinPix_t h = wControlGetHeight(p->control); wControlSetBalloon( p->control, 0, -h*3/4, _("Invalid Number") ); p->bInvalid = TRUE; LOG( log_paraminput, 1, ( " -> InvalidNumber\n" ) ); ParamHilite( p->group->win, p->control, p->bInvalid ); return; } if ( ! ParamIntegerRangeCheck( p, valL ) ) return; wControlSetBalloon( p->control, 0, 0, NULL ); p->bInvalid = FALSE; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, valL ); fflush( recordF ); } if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) *((long*)(p->valueP)) = valL; if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc) p->group->changeProc( p->group, (int)(p-p->group->paramPtr), &valL); ParamHilite( p->group->win, p->control, p->bInvalid ); LOG( log_paraminput, 1, ( " -> %ld\n", valL ) ); } static wBool_t ParamFloatRangeCheck( paramData_p p, FLOAT_T valF ) { if ( inPlayback ) return TRUE; paramFloatRange_t * frangeP = (paramFloatRange_t*)p->winData; wBool_t bInvalid = p->bInvalid; if ( ( (frangeP->rangechecks&PDO_NORANGECHECK_HIGH) == 0 && valF > frangeP->high ) || ( (frangeP->rangechecks&PDO_NORANGECHECK_LOW) == 0 && valF < frangeP->low ) ) { if ( (frangeP->rangechecks&(PDO_NORANGECHECK_HIGH|PDO_NORANGECHECK_LOW)) == PDO_NORANGECHECK_HIGH ) sprintf( message, _("Enter a value > %s"), (p->option&PDO_DIM)?FormatDistance(frangeP->low):FormatFloat(frangeP->low) ); else if ( (frangeP->rangechecks&(PDO_NORANGECHECK_HIGH|PDO_NORANGECHECK_LOW)) == PDO_NORANGECHECK_LOW ) sprintf( message, _("Enter a value < %s"), (p->option&PDO_DIM)?FormatDistance(frangeP->high):FormatFloat(frangeP->high) ); else sprintf( message, _("Enter a value between %s and %s"), (p->option&PDO_DIM)?FormatDistance(frangeP->low):FormatFloat(frangeP->low), (p->option&PDO_DIM)?FormatDistance(frangeP->high):FormatFloat(frangeP->high) ); wWinPix_t h = wControlGetHeight(p->control); wControlSetBalloon( p->control, 0, -h*3/4, message ); p->bInvalid = TRUE; ParamHilite( p->group->win, p->control, p->bInvalid ); return FALSE; } p->bInvalid = FALSE; return TRUE; } /** * Checks the entered value in a float field. Accepts data entered in the different * formats for dimensions. Compares the value against limits if specified in that * entry field description. * * \param val IN the vale to check * \param dp IN the field description */ static void ParamFloatPush( const char * val, void * dp ) { paramData_p p = (paramData_p)dp; FLOAT_T valF; BOOL_T valid; const char * value; wBool_t bInvalid = p->bInvalid; if (strlen(val) == 1 && val[strlen(val)-1] == '\n') { value = wStringGetValue((wString_p)p->control); p->enter_pressed = TRUE; } else { value = val; p->enter_pressed = FALSE; } LOG( log_paraminput, 1, ( "ParamFloatPush( %s: Enter:%d Val:%s )\n", p->nameStr, p->enter_pressed, value ) ); if (p->option & PDO_DIM) { valF = DecodeDistance( (wString_p)p->control, &valid ); } else { valF = DecodeFloat( (wString_p)p->control, &valid ); if (p->option & PDO_ANGLE) valF = NormalizeAngle( (angleSystem==ANGLE_POLAR)?valF:-valF ); } if ( !valid ) { wWinPix_t h = wControlGetHeight(p->control); wControlSetBalloon( p->control, 0, -h*3/4, decodeErrorStr ); p->bInvalid = TRUE; ParamHilite( p->group->win, p->control, p->bInvalid ); return; } if ( !ParamFloatRangeCheck( p, valF ) ) return; wControlSetBalloon( p->control, 0, 0, NULL ); p->bInvalid = FALSE; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %0.6f\n", p->group->nameStr, p->nameStr, valF ); fflush( recordF ); } if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) *((FLOAT_T*)(p->valueP)) = valF; if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc && strlen( value )) p->group->changeProc( p->group, (int)(p-p->group->paramPtr), &valF ); ParamHilite( p->group->win, p->control, p->bInvalid ); } static void ParamStringPush( const char * val, void * dp ) { paramData_p p = (paramData_p)dp; const char * value; wBool_t bInvalid = p->bInvalid; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %s\n", p->group->nameStr, p->nameStr, val ); fflush( recordF ); } if (strlen(val) == 1 && val[strlen(val)-1] == '\n' ) { value = wStringGetValue((wString_p)p->control); p->enter_pressed = TRUE; } else { value = val; p->enter_pressed = FALSE; } LOG( log_paraminput, 1, ( "ParamStringPush( %s: Enter:%d Val:%s )\n", p->nameStr, p->enter_pressed, value ) ); if ( ((!inPlayback) && p->option & PDO_NOTBLANK) && value[0] == '\0' ) { p->bInvalid = TRUE; wControlSetBalloon( p->control, 0, 0, NULL ); wWinPix_t h = wControlGetHeight(p->control); wControlSetBalloon( p->control, 0, -h*3/4, _("String cannot be blank") ); ParamHilite( p->group->win, p->control, TRUE ); return; } wControlSetBalloon( p->control, 0, 0, NULL ); p->bInvalid = FALSE; ParamHilite( p->group->win, p->control, FALSE ); if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) strcpy( (char*)p->valueP, value ); if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc) // CAST_AWAY_CONST: param 3 should be const but its a big change p->group->changeProc( p->group, (int)(p-p->group->paramPtr), CAST_AWAY_CONST value ); } static void ParamListPush( wIndex_t inx, const char * val, wIndex_t op, void * dp, void * itemContext ) { paramData_p p = (paramData_p)dp; long valL; switch (p->type) { case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %d %s\n", p->group->nameStr, p->nameStr, inx, val ); fflush( recordF ); } if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) *(wIndex_t*)(p->valueP) = inx; if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc ) { valL = inx; p->group->changeProc( p->group, (int)(p-p->group->paramPtr), &valL ); } break; default: ; } } EXPORT void ParamMenuPush( void * dp ) { paramData_p p = (paramData_p)dp; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s\n", p->group->nameStr, p->nameStr ); fflush( recordF ); } if ( (p->option&PDO_NOPSHACT)==0 && p->valueP ) ((wMenuCallBack_p)(p->valueP))( p->context ); } static void ParamColorSelectPush( void * dp, wDrawColor dc ) { paramData_p p = (paramData_p)dp; long rgb = wDrawGetRGB( dc ); while ( dc == drawColorPreviewSelected || dc == drawColorPreviewUnselected ) { // The user picked a special color, tweak it rgb -= 1; // Make it very close but different if ( ( rgb & 0xFF ) == 0 ) // Ran out of room - bail break; dc = wDrawFindColor( rgb ); } if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, wDrawGetRGB(dc) ); fflush( recordF ); } if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP) *(wDrawColor*)(p->valueP) = dc; if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc ) p->group->changeProc( p->group, (int)(p-p->group->paramPtr), &dc ); } static void ParamDrawRedraw( wDraw_p d, void * dp, wWinPix_t w, wWinPix_t h ) { paramData_p p = (paramData_p)dp; paramDrawData_t * ddp = (paramDrawData_t*)p->winData; if ( ddp->redraw ) ddp->redraw( d, p->context, w, h ); } static void ParamDrawAction( wDraw_p d, void * dp, wAction_t a, wDrawPix_t w, wDrawPix_t h ) { paramData_p p = (paramData_p)dp; paramDrawData_t * ddp = (paramDrawData_t*)p->winData; coOrd pos; ddp->d->Pix2CoOrd( ddp->d, w, h, &pos ); if ( recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %d %0.3f %0.3f\n", p->group->nameStr, p->nameStr, a, pos.x, pos.y ); fflush( recordF ); } if ( (p->option&PDO_NOPSHACT)== 0 && ddp->action ) ddp->action( a, pos ); } EXPORT wBool_t ParamCheckInputs( paramGroup_p group, wControl_p b ) { wBool_t bInvalid = FALSE; // Check for invalid entries for ( paramData_p p = group->paramPtr; p < &group->paramPtr[group->paramCnt]; p++ ) { ParamHilite( group->win, p->control, p->bInvalid ); if ( p->bInvalid == FALSE ) continue; LOG( log_paraminput, 1, ( " %s: Invalid\n", p->nameStr ) ); bInvalid = TRUE; } if ( bInvalid ) { // At least 1 invalid entry LOG( log_paraminput, 1, ( " Group %s Invalid\n", group->nameStr ) ); wControlSetBalloon( b, 0, -29, _("Invalid input(s), please correct the hilighted field(s)") ); wFlush(); return FALSE; } return TRUE; } static void ParamButtonOk( void * groupVP ) { paramGroup_p group = groupVP; wFlush(); LOG( log_paraminput, 1, ( "ParamButtonOk: %s\n", group->nameStr ) ); if ( ! ParamCheckInputs( group, (wControl_p)group->okB ) ) return; if ( recordF && group->nameStr ) fprintf( recordF, "PARAMETER %s %s\n", group->nameStr, "ok" ); { fflush( recordF ); } if ( group->okProc ) group->okProc( group ); wControlSetBalloon( (wControl_p)group->okB, 0, 0, NULL ); wFlush(); LOG( log_paraminput, 1, ( "ParamButtonOk -> Ok\n" ) ); } static void ParamButtonCancel( void * groupVP ) { paramGroup_p group = groupVP; if ( recordF && group->nameStr ) { fprintf( recordF, "PARAMETER %s %s\n", group->nameStr, "cancel" ); fflush( recordF ); } if ( group->cancelProc ) group->cancelProc( group->win ); } #ifdef LATER EXPORT void ParamChange( paramData_p p ) { FLOAT_T tmpR; if (p->valueP==NULL) return; switch (p->type) { case PD_LONG: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, *(long*)p->valueP ); #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) { wStringSetValue( (wString_p)p->control, FormatLong( *(long*)p->valueP ) ); } #endif break; case PD_RADIO: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, *(long*)p->valueP ); #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) wRadioSetValue( (wChoice_p)p->control, *(long*)p->valueP ); #endif break; case PD_TOGGLE: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, *(long*)p->valueP ); #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) wToggleSetValue( (wChoice_p)p->control, *(long*)p->valueP ); #endif break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) { fprintf( recordF, "PARAMETER %s %s %d %s\n", p->group->nameStr, p->nameStr, *(wIndex_t*)p->valueP, "???" ); } #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) wListSetIndex( (wList_p)p->control, *(wIndex_t*)p->valueP ); #endif break; case PD_COLORLIST: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, rgb ); break; case PD_FLOAT: tmpR = *(FLOAT_T*)p->valueP; if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %0.6f\n", p->group->nameStr, p->nameStr, tmpR ); #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) { if (p->option&PDO_DIM) #endif if (p->option&PDO_ANGLE) tmpR = NormalizeAngle( (angleSystem==ANGLE_POLAR)?tmpR:-tmpR ); wStringSetValue( (wString_p)p->control, tmpR ); } break; case PD_STRING: if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) fprintf( recordF, "PARAMETER %s %s %s\n", p->group->nameStr, p->nameStr, (char*)p->valueP ); #ifdef LATER if ( p->control && (p->option&PDO_NOCONTUPD) == 0 ) wStringSetValue( (wString_p)p->control, (char*)p->valueP ); #endif break; case PD_MESSAGE: case PD_BUTTON: case PD_DRAW: case PD_TEXT: case PD_MENU: case PD_MENUITEM: break; } } #endif EXPORT void ParamHilite( wWin_p win, wControl_p control, BOOL_T hilite ) { if ( control == NULL ) return; LOG(log_paraminput, 2, ("ParamHilite %s\n", hilite?"Set":"Clr" )); if ( hilite ) { wControlHilite( control, TRUE ); wFlush(); if ( inPlayback && !paramHiliteFast ) wPause(500); } else { // if ( inPlayback && !paramHiliteFast ) // wPause(500); wControlHilite( control, FALSE ); } } EXPORT void ParamResetInvalid( wWin_p win ) { for ( int inx=0; inxwin == win ) { LOG( log_paraminput, 1, ( "Reset Invalid: %s\n", pg->nameStr ) ); for ( paramData_p p = &pg->paramPtr[0]; p < &pg->paramPtr[pg->paramCnt]; p++ ) { if ( p->bInvalid ) LOG( log_paraminput, 1, ( " %s Invalid\n", p->nameStr ) ); ParamHilite( win, p->control, FALSE ); wControlSetBalloon( p->control, 0, 0, NULL ); p->bInvalid = FALSE; } break; } } } static void ParamPlayback( char * line ) { paramGroup_p pg; paramData_p p; long valL; FLOAT_T valF, valF1; size_t len, len1, len2; wIndex_t inx; void * listContext, * itemContext; long rgb; wDrawColor dc; wButton_p button; paramDrawData_t * ddp; wAction_t a; coOrd pos; char * valS; if ( strncmp( line, "GROUP ", 6 ) == 0 ) { #ifdef PGPROC for ( inx=0; inxname && strncmp( line+6, pg->name, strlen( pg->name ) ) == 0 ) { if ( pg->proc ) { pg->proc( PGACT_PARAM, pg->action ); } pg->action = 0; } } #endif return; } for ( inx=0; inxnameStr == NULL ) continue; len1 = strlen( pg->nameStr ); if ( strncmp( pg->nameStr, line, len1 ) != 0 || line[len1] != ' ' ) continue; for ( p=pg->paramPtr,inx=0; inxparamCnt; p++,inx++ ) { if ( p->nameStr == NULL ) continue; len2 = strlen( p->nameStr ); if ( strncmp(p->nameStr, line+len1+1, len2) != 0 || (line[len1+1+len2] != ' ' && line[len1+1+len2] != '\0') ) continue; len = len1 + 1 + len2 + 1; if ( p->type != PD_DRAW && p->type != PD_MESSAGE && p->type != PD_MENU && p->type != PD_MENUITEM ) ParamHilite( p->group->win, p->control, TRUE ); switch (p->type) { case PD_BUTTON: if (p->valueP) ((wButtonCallBack_p)(p->valueP))( p->context ); if (playbackTimer == 0 && p->control) { wButtonSetBusy( (wButton_p)p->control, TRUE ); wFlush(); wPause( 500 ); wButtonSetBusy( (wButton_p)p->control, FALSE ); wFlush(); } break; case PD_LONG: valL = atol( line+len ); if (p->valueP) *(long*)p->valueP = valL; if (p->control) { wStringSetValue( (wString_p)p->control, FormatLong( valL ) ); wFlush(); } if (pg->changeProc) pg->changeProc( pg, inx, &valL ); break; case PD_RADIO: valL = atol( line+len ); if (p->valueP) *(long*)p->valueP = valL; if (p->control) { wRadioSetValue( (wChoice_p)p->control, valL ); wFlush(); } if (pg->changeProc) pg->changeProc( pg, inx, &valL ); break; case PD_TOGGLE: valL = atol( line+len ); if (p->valueP) *(long*)p->valueP = valL; if (p->control) { wToggleSetValue( (wChoice_p)p->control, valL ); wFlush(); } if (pg->changeProc) pg->changeProc( pg, inx, &valL ); break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: line += len; valL = strtol( line, &valS, 10 ); if ( valS ) valS++; else valS = ""; if ( p->control != NULL ) { if ( (p->option&PDO_LISTINDEX) == 0 ) { if ( valL < 0 ) { wListSetValue( (wList_p)p->control, valS ); } else { valL = wListFindValue( (wList_p)p->control, valS ); if (valL < 0) { NoticeMessage( MSG_PLAYBACK_LISTENTRY, _("Ok"), NULL, line ); break; } wListSetIndex( (wList_p)p->control, (wIndex_t)valL ); } } else { wListSetIndex( (wList_p)p->control, (wIndex_t)valL ); } wFlush(); wListGetValues( (wList_p)p->control, message, sizeof message, &listContext, &itemContext ); } else if ( (p->option&PDO_LISTINDEX) == 0 ) { break; } if (p->valueP) *(wIndex_t*)p->valueP = (wIndex_t)valL; if (pg->changeProc) { pg->changeProc( pg, inx, &valL ); } break; case PD_COLORLIST: line += len; rgb = atol( line ); dc = wDrawFindColor( rgb ); if ( p->control) wColorSelectButtonSetColor( (wButton_p)p->control, dc ); if (p->valueP) *(wDrawColor*)p->valueP = dc; if (pg->changeProc) { /* COLORNOP */ pg->changeProc( pg, inx, &valL ); } break; case PD_FLOAT: SetCLocale(); valF = valF1 = atof( line+len ); SetUserLocale(); if (p->valueP) *(FLOAT_T*)p->valueP = valF; if (p->option&PDO_DIM) { if ( p->option&PDO_SMALLDIM ) valS = FormatSmallDistance( valF ); else valS = FormatDistance( valF ); } else { if (p->option&PDO_ANGLE) valF1 = NormalizeAngle( (angleSystem==ANGLE_POLAR)?valF1:-valF1 ); valS = FormatFloat( valF ); } if (p->control) { wStringSetValue( (wString_p)p->control, valS ); wFlush(); } if (pg->changeProc) pg->changeProc( pg, inx, &valF ); break; case PD_STRING: case PD_TEXT: line += len; while ( *line == ' ' ) line++; Stripcr( line ); if (p->valueP) strcpy( (char*)p->valueP, line ); if (p->control) { if (p->type == PD_STRING) { wStringSetValue((wString_p)p->control, line); } else { wTextClear((wText_p)p->control); wTextAppend((wText_p)p->control, line); } wFlush(); } if (pg->changeProc) pg->changeProc( pg, inx, line ); break; case PD_DRAW: ddp = (paramDrawData_t*)p->winData; if ( ddp->action == NULL ) break; a = (wAction_t)strtol( line+len, &line, 10 ); pos.x = strtod( line, &line ); pos.y = strtod( line, NULL ); PlaybackMouse( ddp->action, ddp->d, a, pos, drawColorBlack ); break; case PD_MESSAGE: case PD_MENU: case PD_BITMAP: break; case PD_MENUITEM: if (p->valueP) { if ( (p->option&IC_PLAYBACK_PUSH) != 0 ) PlaybackButtonMouse( (wIndex_t)VP2L(p->context) ); ((wButtonCallBack_p)(p->valueP))( p->context ); } break; } if ( p->type != PD_DRAW && p->type != PD_MESSAGE && p->type != PD_MENU && p->type != PD_MENUITEM ) ParamHilite( p->group->win, p->control, FALSE ); #ifdef HUH pg->action |= p->change; #endif return; } button = NULL; if ( strcmp("ok", line+len1+1) == 0 ) { ParamHilite( pg->win, (wControl_p)pg->okB, TRUE ); if ( pg->okProc ) pg->okProc( pg ); button = pg->okB; } else if ( strcmp("cancel", line+len1+1) == 0 ) { ParamHilite( pg->win, (wControl_p)pg->cancelB, TRUE ); if ( pg->cancelProc ) pg->cancelProc( pg->win ); button = pg->cancelB; } if ( playbackTimer == 0 && button ) { wButtonSetBusy( button, TRUE ); wFlush(); wPause( 500 ); wButtonSetBusy( button, FALSE ); wFlush(); } ParamHilite( pg->win, (wControl_p)button, FALSE ); if ( !button ) NoticeMessage( "Unknown PARAM: %s", _("Ok"), NULL, line ); return; } NoticeMessage( "Unknown PARAM: %s", _("Ok"), NULL, line ); } static void ParamCheck( char * line ) { paramGroup_p pg; paramData_p p; long valL; FLOAT_T valF, diffF; size_t len, len1, len2; wIndex_t inx; void * listContext, * itemContext; char * valS; char * expVal=NULL, * actVal=NULL; char expNum[20], actNum[20]; BOOL_T hasError = FALSE; FILE * f; for ( inx=0; inxnameStr == NULL ) continue; len1 = strlen( pg->nameStr ); if ( strncmp( pg->nameStr, line, len1 ) != 0 || line[len1] != ' ' ) continue; for ( p=pg->paramPtr,inx=0; inxparamCnt; p++,inx++ ) { if ( p->nameStr == NULL ) continue; len2 = strlen( p->nameStr ); if ( strncmp(p->nameStr, line+len1+1, len2) != 0 || (line[len1+1+len2] != ' ' && line[len1+1+len2] != '\0') ) continue; if ( p->valueP == NULL ) return; len = len1 + 1 + len2 + 1; switch (p->type) { case PD_BUTTON: break; case PD_LONG: case PD_RADIO: case PD_TOGGLE: valL = atol( line+len ); if ( *(long*)p->valueP != valL ) { sprintf( expNum, "%ld", valL ); sprintf( actNum, "%ld", *(long*)p->valueP ); expVal = expNum; actVal = actNum; hasError = TRUE; } break; case PD_LIST: case PD_DROPLIST: case PD_COMBOLIST: line += len; if ( p->control == NULL ) break; valL = strtol( line, &valS, 10 ); if ( valS ) { if ( valS[0] == ' ' ) valS++; } else { valS = ""; } if ( (p->option&PDO_LISTINDEX) != 0 ) { if ( *(long*)p->valueP != valL ) { sprintf( expNum, "%ld", valL ); sprintf( actNum, "%d", *(wIndex_t*)p->valueP ); expVal = expNum; actVal = actNum; hasError = TRUE; } } else { wListGetValues( (wList_p)p->control, message, sizeof message, &listContext, &itemContext ); if ( strcasecmp( message, valS ) != 0 ) { expVal = valS; actVal = message; hasError = TRUE; } } break; case PD_COLORLIST: break; case PD_FLOAT: valF = atof( line+len ); diffF = fabs( *(FLOAT_T*)p->valueP - valF ); if ( diffF > 0.001 ) { sprintf( expNum, "%0.3f", valF ); sprintf( actNum, "%0.3f", *(FLOAT_T*)p->valueP ); expVal = expNum; actVal = actNum; hasError = TRUE; } break; case PD_STRING: line += len; while ( *line == ' ' ) line++; wStringGetValue( (wString_p)p->control ); if ( strcasecmp( line, (char*)p->valueP ) != 0 ) { expVal = line; actVal = (char*)p->valueP; hasError = TRUE; } break; case PD_DRAW: case PD_MESSAGE: case PD_TEXT: case PD_MENU: case PD_MENUITEM: case PD_BITMAP: break; } if ( hasError ) { f = fopen( "error.log", "a" ); if ( f==NULL ) { NoticeMessage( MSG_OPEN_FAIL, _("Continue"), NULL, "PARAMCHECK LOG", "error.log", strerror(errno) ); } else { fprintf( f, "CHECK: %s:%d: %s-%s: exp: %s, act=%s\n", paramFileName, paramLineNum, pg->nameStr, p->nameStr, expVal, actVal ); fclose( f ); } if ( paramCheckShowErrors ) NoticeMessage( "CHECK: %d: %s-%s: exp: %s, act=%s", _("Ok"), NULL, paramLineNum, pg->nameStr, p->nameStr, expVal, actVal ); paramCheckErrorCount++; } return; } } NoticeMessage( "Unknown PARAMCHECK: %s", _("Ok"), NULL, line ); } /* * */ static void ParamCreateControl( paramData_p pd, char * helpStr, wWinPix_t xx, wWinPix_t yy ) { const paramFloatRange_t * floatRangeP; const paramIntegerRange_t * integerRangeP; const paramDrawData_t * drawDataP; const paramTextData_t * textDataP; paramListData_t * listDataP; const struct wIcon_t * iconP; wWin_p win; wWinPix_t w; wWinPix_t colWidth; static wWinPix_t *colWidths; static wBool_t *colRightJust; static wBool_t maxColCnt = 0; int col; const char *cp; char *cq; static wMenu_p menu = NULL; if ( ( win = pd->group->win ) == NULL ) win = mainW; switch (pd->type) { case PD_FLOAT: floatRangeP = pd->winData; w = floatRangeP->width?floatRangeP->width:100; pd->control = (wControl_p)wStringCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, w, NULL, 0, ParamFloatPush, pd ); break; case PD_LONG: integerRangeP = pd->winData; w = integerRangeP->width?integerRangeP->width:100; pd->control = (wControl_p)wStringCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, w, NULL, 0, ParamIntegerPush, pd ); break; case PD_STRING: w = pd->winData?(wWinPix_t)VP2L(pd->winData):(wWinPix_t)250; pd->control = (wControl_p)wStringCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, w, (pd->option&PDO_NOPSHUPD)?NULL:pd->valueP, 0, ParamStringPush, pd ); break; case PD_RADIO: pd->control = (wControl_p)wRadioCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, pd->winData, NULL, ParamChoicePush, pd ); break; case PD_TOGGLE: pd->control = (wControl_p)wToggleCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, pd->winData, NULL, ParamChoicePush, pd ); break; case PD_LIST: listDataP = (paramListData_t*)pd->winData; if ( listDataP->colCnt > 1 ) { if ( maxColCnt < listDataP->colCnt ) { if ( maxColCnt == 0 ) { colWidths = (wWinPix_t*)MyMalloc( listDataP->colCnt * sizeof *colWidths ); colRightJust = (wBool_t*)MyMalloc( listDataP->colCnt * sizeof *colRightJust ); } else { colWidths = (wWinPix_t*)MyRealloc( colWidths, listDataP->colCnt * sizeof *colWidths ); colRightJust = (wBool_t*)MyRealloc( colRightJust, listDataP->colCnt * sizeof *colRightJust ); } maxColCnt = listDataP->colCnt; } for ( col=0; colcolCnt; col++ ) { colRightJust[col] = listDataP->colWidths[col]<0; colWidths[col] = labs(listDataP->colWidths[col]); } sprintf( message, "%s-%s-%s", pd->group->nameStr, pd->nameStr, "columnwidths" ); cp = wPrefGetString( PREFSECT, message ); if ( cp != NULL ) { for ( col=0; colcolCnt; col++ ) { colWidth = (wWinPix_t)strtol( cp, &cq, 10 ); if ( cp == cq ) break; colWidths[col] = colWidth; cp = cq; } } } pd->control = (wControl_p)wListCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, listDataP->number, listDataP->width, listDataP->colCnt, (listDataP->colCnt>1?colWidths:NULL), (listDataP->colCnt>1?colRightJust:NULL), listDataP->colTitles, NULL, ParamListPush, pd ); listDataP->height = wControlGetHeight( pd->control ); break; case PD_DROPLIST: w = pd->winData?(wWinPix_t)VP2L(pd->winData):(wWinPix_t)100; pd->control = (wControl_p)wDropListCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, 10, w, NULL, ParamListPush, pd ); break; case PD_COMBOLIST: listDataP = (paramListData_t*)pd->winData; pd->control = (wControl_p)wComboListCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, listDataP->number, listDataP->width, NULL, ParamListPush, pd ); listDataP->height = wControlGetHeight( pd->control ); break; case PD_COLORLIST: pd->control = (wControl_p)wColorSelectButtonCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, 0, NULL, ParamColorSelectPush, pd ); break; case PD_MESSAGE: if ( pd->winData != 0 ) w = (wWinPix_t)VP2L(pd->winData); else if (pd->valueP) w = wLabelWidth( _(pd->valueP) ); else w = 150; pd->control = (wControl_p)wMessageCreateEx( win, xx, yy, _(pd->winLabel), w, pd->valueP?_(pd->valueP):" ", pd->winOption ); break; case PD_BUTTON: pd->control = (wControl_p)wButtonCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption, 0, ParamButtonPush, pd ); break; case PD_MENU: menu = wMenuCreate( win, xx, yy, helpStr, _(pd->winLabel), pd->winOption ); pd->control = (wControl_p)menu; break; case PD_MENUITEM: pd->control = (wControl_p)wMenuPushCreate( menu, helpStr, _(pd->winLabel), 0, ParamMenuPush, pd ); break; case PD_DRAW: drawDataP = pd->winData; pd->control = (wControl_p)wDrawCreate( win, xx, yy, helpStr, pd->winOption, drawDataP->width, drawDataP->height, pd, ParamDrawRedraw, ParamDrawAction ); if ( drawDataP->d ) { drawDataP->d->d = (wDraw_p)pd->control; drawDataP->d->dpi = wDrawGetDPI( drawDataP->d->d ); } break; case PD_TEXT: textDataP = pd->winData; pd->control = (wControl_p)wTextCreate( win, xx, yy, helpStr, NULL, pd->winOption, textDataP->width, textDataP->height ); if ( (pd->winOption&BO_READONLY) == 0 ) wTextSetReadonly( (wText_p)pd->control, FALSE ); break; case PD_BITMAP: iconP = pd->winData; pd->control = (wControl_p)wBitmapCreate( win, xx, yy, pd->winOption, iconP ); break; default: AbortProg( "paramCreatePG" ); } } static void ParamPositionControl( paramData_p pd, char * helpStr, wWinPix_t xx, wWinPix_t yy ) { const paramDrawData_t * drawDataP; const paramTextData_t * textDataP; const paramListData_t * listDataP; wWinPix_t winW, winH, ctlW, ctlH; if ( pd->type != PD_MENUITEM ) wControlSetPos( pd->control, xx, yy ); if ( pd->option&PDO_DLGRESIZE ) { wWinGetSize( pd->group->win, &winW, &winH ); switch (pd->type) { case PD_LIST: case PD_COMBOLIST: case PD_DROPLIST: if ( pd->type == PD_DROPLIST ) { ctlW = pd->winData?(wWinPix_t)VP2L(pd->winData):(wWinPix_t)100; ctlH = wControlGetHeight( pd->control ); } else { listDataP = (paramListData_t*)pd->winData; ctlW = listDataP->width; ctlH = listDataP->height; } if ( (pd->option&PDO_DLGRESIZE) == 0 ) break; if ( (pd->option&PDO_DLGRESIZEW) != 0 ) ctlW = winW - (pd->group->origW-ctlW); if ( (pd->option&PDO_DLGRESIZEH) != 0 ) ctlH = winH - (pd->group->origH-ctlH); wListSetSize( (wList_p)pd->control, ctlW, ctlH ); break; case PD_DRAW: drawDataP = pd->winData; if ( (pd->option&PDO_DLGRESIZEW) ) ctlW = winW - (pd->group->origW-drawDataP->width); else ctlW = wControlGetWidth( pd->control ); if ( (pd->option&PDO_DLGRESIZEH) ) ctlH = winH - (pd->group->origH-drawDataP->height); else ctlH = wControlGetHeight( pd->control ); wDrawSetSize( (wDraw_p)pd->control, ctlW, ctlH, NULL ); if ( drawDataP->redraw ) drawDataP->redraw( (wDraw_p)pd->control, pd->context, ctlW, ctlH ); break; case PD_TEXT: textDataP = pd->winData; ctlW = textDataP->width; ctlH = textDataP->height; if ( (pd->winOption&BT_CHARUNITS) ) wTextComputeSize( (wText_p)pd->control, ctlW, ctlH, &ctlW, &ctlH ); if ( (pd->option&PDO_DLGRESIZEW) ) ctlW = winW - (pd->group->origW-ctlW); else ctlW = wControlGetWidth( pd->control ); if ( (pd->option&PDO_DLGRESIZEH) ) ctlH = winH - (pd->group->origH-ctlH); else ctlH = wControlGetHeight( pd->control ); wTextSetSize( (wText_p)pd->control, ctlW, ctlH ); break; case PD_STRING: ctlW = pd->winData?(wWinPix_t)VP2L(pd->winData):(wWinPix_t)250; if ( (pd->option&PDO_DLGRESIZEW) ) { ctlW = winW - (pd->group->origW-ctlW); wStringSetWidth( (wString_p)pd->control, ctlW ); } break; case PD_MESSAGE: ctlW = pd->winData?(wWinPix_t)VP2L(pd->winData):(wWinPix_t)150; if ( (pd->option&PDO_DLGRESIZEW) ) { ctlW = winW - (pd->group->origW-ctlW); wMessageSetWidth( (wMessage_p)pd->control, ctlW ); } break; default: AbortProg( "paramPositionControl" ); } } } typedef void (*layoutControlsProc)(paramData_p, char *, wWinPix_t, wWinPix_t ); static void LayoutControls( paramGroup_p group, layoutControlsProc proc, wWinPix_t * retW, wWinPix_t * retH ) { struct { struct { wWinPix_t x, y; } orig, term; } controlK, columnK, windowK; wWinPix_t controlSize_x; wWinPix_t controlSize_y; paramData_p pd; wWinPix_t w; BOOL_T hasBox; wWinPix_t boxTop; wWinPix_t boxPos[10]; int boxCnt = 0; int box; int inx; wWinPix_t labelW[100]; int lastLabelPos, currLabelPos; char helpStr[STR_SHORT_SIZE], * helpStrP; BOOL_T inCmdButtons = FALSE; wButton_p lastB = NULL; BOOL_T areCmdButtons = FALSE; strcpy( helpStr, group->nameStr ); helpStrP = helpStr+strlen(helpStr); *helpStrP++ = '-'; *helpStrP = 0; controlK.orig.x = 0; hasBox = FALSE; memset( boxPos, 0, sizeof boxPos ); memset( labelW, 0, sizeof labelW ); lastLabelPos = 0; currLabelPos = 0; for ( pd=group->paramPtr; pd<&group->paramPtr[group->paramCnt]; pd++,currLabelPos++ ) { if ( (pd->option&PDO_DLGIGNORE) != 0 ) continue; if ( (pd->option&PDO_DLGBOXEND) ) hasBox = TRUE; if ( (pd->option&(PDO_DLGRESETMARGIN|PDO_DLGNEWCOLUMN|PDO_DLGCMDBUTTON)) ) { for ( inx=lastLabelPos; inxwinLabel && (pd->option&(PDO_DLGIGNORELABELWIDTH|PDO_DLGHORZ))==0 && pd->type!=PD_BUTTON && pd->type!=PD_MENU && pd->type!=PD_MENUITEM) { w = wLabelWidth( _(pd->winLabel) ); if ( w > controlK.orig.x ) controlK.orig.x = w; } } for ( inx=lastLabelPos; inxparamCnt; inx++ ) labelW[inx] = controlK.orig.x; for ( inx=0; inxparamCnt; inx++ ) if ( (group->paramPtr[inx].option&PDO_DLGNOLABELALIGN) != 0 ) labelW[inx] = 0; LOG( log_paramLayout, 1, ("Layout %s B?=%s\n", group->nameStr, hasBox?"T":"F" ) ) windowK.orig.x = DlgSepLeft + (hasBox?DlgSepFrmLeft:0); windowK.orig.y = DlgSepTop + (hasBox?DlgSepFrmTop:0); windowK.term = windowK.orig; controlK = columnK = windowK; controlK.orig.x += labelW[0]; for ( pd = group->paramPtr,inx=0; pd<&group->paramPtr[group->paramCnt]; pd++,inx++ ) { LOG( log_paramLayout, 1, ("%2d: Col %dx%d..%dx%d Ctl %dx%d..%dx%d\n", inx, columnK.orig.x, columnK.orig.y, columnK.term.x, columnK.term.y, controlK.orig.x, controlK.orig.y, controlK.term.x, controlK.term.y ) ) if ( (pd->option&PDO_DLGIGNORE) != 0 ) goto SkipControl; if ( pd->type == PD_MENUITEM ) { proc( pd, helpStr, 0, 0 ); continue; } /* * Set control orig */ if ( (pd->option&PDO_DLGNEWCOLUMN) ) { columnK.orig.x = columnK.term.x; columnK.orig.x += ((pd->option&PDO_DLGWIDE)?10:DlgSepNarrow); columnK.term.y = columnK.orig.y; controlK.orig.x = columnK.orig.x + labelW[inx]; controlK.orig.y = columnK.orig.y; } else if ( (pd->option&PDO_DLGHORZ) ) { controlK.orig.x = controlK.term.x; if ( (pd->option&PDO_DLGWIDE) ) controlK.orig.x += 10; else if ( (pd->option&PDO_DLGNARROW)== 0) controlK.orig.x += 3; if ( pd->winLabel && ( pd->type!=PD_BUTTON ) ) controlK.orig.x += wLabelWidth( _(pd->winLabel) ); } else if ( inx != 0 ) { controlK.orig.x = columnK.orig.x + labelW[inx]; controlK.orig.y = controlK.term.y; if ( (pd->option&PDO_DLGWIDE) ) controlK.orig.y += 10; else if ( (pd->option&PDO_DLGNARROW)== 0) controlK.orig.y += 3; } if ( (pd->option&PDO_DLGSETY) ) { columnK.term.x = controlK.orig.x; columnK.orig.y = controlK.orig.y; } /* * Custom layout and create/postion control */ if (group->layoutProc) group->layoutProc( pd, inx, columnK.orig.x+labelW[inx], &controlK.orig.x, &controlK.orig.y ); if ( pd->nameStr ) strcpy( helpStrP, pd->nameStr ); proc( pd, helpStr, controlK.orig.x, controlK.orig.y ); /* * Set control term */ controlSize_x = wControlGetWidth( pd->control ); controlSize_y = wControlGetHeight( pd->control ); controlK.term.x = controlK.orig.x+controlSize_x; if ( (pd->option&PDO_DLGHORZ)==0 || controlK.term.y < controlK.orig.y+controlSize_y ) controlK.term.y = controlK.orig.y+controlSize_y; if ( retW && pd->nameStr ) { char * cp; strcpy( message, pd->nameStr ); for ( cp=message; *cp; cp++ ) if ( *cp == '-' ) *cp = '_'; } /* * Set column term */ if ( (pd->option&PDO_DLGIGNOREX) == 0 ) { if ( (pd->option&PDO_DLGUNDERCMDBUTT) == 0 ) { if ( columnK.term.x < controlK.term.x ) columnK.term.x = controlK.term.x; } else { if ( columnK.term.x < controlK.term.x-90 ) columnK.term.x = controlK.term.x-90; } } if ( columnK.term.y < controlK.term.y ) columnK.term.y = controlK.term.y; if ( hasBox ) if ( boxPos[boxCnt] < columnK.term.y+2 ) boxPos[boxCnt] = columnK.term.y+2; if ( (pd->option&PDO_DLGBOXEND) ) { columnK.term.y += 8; boxCnt++; controlK.term.y = columnK.term.y; } /* * Set window term */ if ( windowK.term.x < columnK.term.x ) windowK.term.x = columnK.term.x; if ( windowK.term.y < columnK.term.y ) windowK.term.y = columnK.term.y; if ( (pd[1].option&PDO_DLGCMDBUTTON) ) areCmdButtons = TRUE; SkipControl: if ( (!inCmdButtons) && (pd==&group->paramPtr[group->paramCnt-1] || (pd[1].option&PDO_DLGCMDBUTTON)) ) { columnK.orig.x = columnK.term.x + DlgSepMid; if ( boxCnt ) { boxTop = DlgSepTop; if ( group->boxs == NULL ) { group->boxs = (wBox_p*)MyMalloc( boxCnt * sizeof *(wBox_p*)0 ); for ( box=0; boxboxs[box] = wBoxCreate( group->win, DlgSepLeft, boxTop, NULL, wBoxThickW, columnK.term.x, boxPos[box]-boxTop ); boxTop = boxPos[box] + 4; } } else { for ( box=0; boxboxs[box], DlgSepLeft, boxTop ); wBoxSetSize( group->boxs[box], columnK.term.x, boxPos[box]-boxTop ); boxTop = boxPos[box] + 4; } } columnK.orig.x += DlgSepFrmRight; } columnK.orig.y = columnK.term.y = DlgSepTop; controlK = columnK; if ( group->okB ) { wControlSetPos( (wControl_p)(lastB=group->okB), columnK.orig.x, columnK.orig.y ); controlK.term.y += wControlGetHeight((wControl_p)group->okB); columnK.term.y = controlK.term.y + 3; } inCmdButtons = TRUE; } LOG( log_paramLayout, 1, (" Col %dx%d..%dx%d Ctl %dx%d..%dx%d\n", columnK.orig.x, columnK.orig.y, columnK.term.x, columnK.term.y, controlK.orig.x, controlK.orig.y, controlK.term.x, controlK.term.y ) ) if ( windowK.term.x < columnK.term.x ) windowK.term.x = columnK.term.x; if ( windowK.term.y < columnK.term.y ) windowK.term.y = columnK.term.y; } if ( group->cancelB ) { if ( areCmdButtons ) columnK.term.y += 10; else if ( group->okB ) columnK.term.y += 3; wControlSetPos( (wControl_p)(lastB=group->cancelB), columnK.orig.x, columnK.term.y ); columnK.term.y += wControlGetHeight((wControl_p)group->cancelB); } if ( group->helpB ) { columnK.term.y += 10; wControlSetPos( (wControl_p)(lastB=group->helpB), columnK.orig.x, columnK.term.y ); columnK.term.y += wControlGetHeight((wControl_p)group->helpB); } if ( lastB ) { controlK.term.x = controlK.orig.x + wControlGetWidth((wControl_p)lastB); if ( columnK.term.x < controlK.term.x ) columnK.term.x = controlK.term.x; } if ( windowK.term.x < columnK.term.x ) windowK.term.x = columnK.term.x; if ( windowK.term.y < columnK.term.y ) windowK.term.y = columnK.term.y; if ( retW ) *retW = windowK.term.x; if ( retH ) *retH = windowK.term.y; } static void ParamDlgProc( wWin_p win, winProcEvent e, void * refresh, void * data ) { paramGroup_p pg = (paramGroup_p)data; switch (e) { case wClose_e: if ( pg->changeProc ) pg->changeProc( pg, -1, NULL ); if ( (pg->options&PGO_NODEFAULTPROC) == 0 ) DefaultProc( win, wClose_e, data ); break; case wResize_e: if (win == mapW) pg->changeProc(pg, wResize_e, NULL); else LayoutControls( pg, ParamPositionControl, NULL, NULL ); break; default: break; } } /** * Create a dialog box from data definition. * * \param IN group data definition for the dialog * \param IN title title of the new dialog * \param IN okLabel text for the affirmative button * \param IN okProc subroutine to call when ok is pressed * \param IN cancelProc if not NULL a subroutine for Cancel event. If NULL no cancel button is created * \param IN needHelpButton if TRUE a help button is created * \param IN layoutProc ??? * \param IN winOption ??? * \param IN changeProc ??? */ wWin_p ParamCreateDialog( paramGroup_p group, char * title, char * okLabel, paramActionOkProc okProc, paramActionCancelProc cancelProc, BOOL_T needHelpButton, paramLayoutProc layoutProc, long winOption, paramChangeProc changeProc ) { char helpStr[STR_SHORT_SIZE]; wWinPix_t w0, h0; char * cancelLabel = (winOption&PD_F_ALT_CANCELLABEL?_("Close"):_("Cancel")); winOption &= ~PD_F_ALT_CANCELLABEL; group->okProc = okProc; group->cancelProc = cancelProc; group->layoutProc = layoutProc; group->changeProc = changeProc; group->winOption = winOption; if ( (winOption&F_CENTER) == 0 ) winOption |= F_RECALLPOS; if ( (winOption&F_RESIZE) != 0 ) winOption |= F_RECALLSIZE; group->win = wWinPopupCreate( mainW, DlgSepRight, DlgSepFrmBottom, helpStr, title, group->nameStr, F_AUTOSIZE|winOption, ParamDlgProc, group ); if ( okLabel && okProc ) { sprintf( helpStr, "%s-ok", group->nameStr ); group->okB = wButtonCreate( group->win, 0, 0, helpStr, okLabel, BB_DEFAULT, 0, ParamButtonOk, group ); } if ( group->cancelProc ) { group->cancelB = wButtonCreate( group->win, 0, 0, NULL, cancelLabel, BB_CANCEL, 0, ParamButtonCancel, group ); } if ( needHelpButton ) { sprintf( helpStr, "cmd%s", group->nameStr ); helpStr[3] = toupper((unsigned char)helpStr[3]); group->helpB = wButtonCreate( group->win, 0, 0, NULL, _("Help"), BB_HELP, 0, (wButtonCallBack_p)wHelp, MyStrdup(helpStr) ); } LayoutControls( group, ParamCreateControl, &group->origW, &group->origH ); group->origW += DlgSepRight; group->origH += DlgSepBottom; wWinGetSize( group->win, &w0, &h0 ); if ( (winOption&F_RESIZE) ) { if ( group->origW != w0 || group->origH != h0 ) { LayoutControls( group, ParamPositionControl, NULL, NULL ); } } else { w0 = max(group->origW, w0); h0 = max(group->origH, h0); wWinSetSize( group->win, w0, h0 ); } return group->win; } /** Resize dialog window for the contained fields. * \param IN OUT Prameter Group * */ EXPORT void ParamLayoutDialog( paramGroup_p pg ) { wWinPix_t w, h; LayoutControls( pg, ParamPositionControl, &w, &h ); w += DlgSepRight; h += DlgSepBottom; if ( w != pg->origW || h != pg->origH ) { wWinSetSize( pg->win, w, h ); pg->origW = w; pg->origH = h; } } EXPORT void ParamDialogOkActive( paramGroup_p pg, int active ) { if ( pg->okB ) wControlActive( (wControl_p)pg->okB, active ); } EXPORT void ParamCreateControls( paramGroup_p pg, paramChangeProc changeProc ) { paramData_p pd; char helpStr[STR_SHORT_SIZE], * helpStrP; strcpy( helpStr, pg->nameStr ); helpStrP = helpStr+strlen(helpStr); *helpStrP++ = '-'; for ( pd=pg->paramPtr; pd<&pg->paramPtr[pg->paramCnt]; pd++ ) { pd->group = pg; strcpy( helpStrP, pd->nameStr ); ParamCreateControl( pd, helpStr, 0, 0 ); if ( pd->type != PD_MENUITEM && pd->control ) wControlShow( pd->control, FALSE ); } pg->changeProc = changeProc; } EXPORT void ParamInit( void ) { if (paramGroups_init) return; AddPlaybackProc( "PARAMETER", ParamPlayback, NULL ); AddPlaybackProc( "PARAMCHECK", ParamCheck, NULL ); log_paramLayout = LogFindIndex( "paramlayout" ); log_paraminput = LogFindIndex( "paraminput" ); paramGroups_da.cnt = 0; paramGroups_da.max = 0; paramGroups_da.ptr = NULL; paramGroups_init = TRUE; }