On some machines (in my case Linux 2.4.0-test5) the last
tickmark of a scale is missing. The following code shows
this problem:
wm geometry . 300x100+50+50
scale .h -orient horizontal -from 0 -to 20 -length 284 \
-tickinterval 4 -resolution 0.08
pack .h
The tickmarks go only up to 16.00 and not up to 20.00.
As far as I could see this bug is due to a problematic floating point comparison in the functions DisplayVerticalScale() and DisplayHorizontalScale() in
tkUnixScale.c in mTk/generic (I'm not sure about the exact directory because I only have the perl Tk sources).
Here are the diffs for a patch for the three files
tkUnixScale.c, tkScale.c and tkScale.h:
############################################################
*** tkUnixScale.c.orig Thu Nov 16 09:27:29 2000
--- tkUnixScale.c Thu Nov 16 09:22:16 2000
***************
*** 112,115 ****
--- 112,116 ----
Tk_Tile tile;
GC gc;
+ int numTicks, i;
/*
***************
*** 169,174 ****
if (scalePtr->tickInterval != 0) {
! for (tickValue = scalePtr->fromValue; ;
! tickValue += scalePtr->tickInterval) {
/*
* The TkRoundToResolution call gets rid of accumulated
--- 170,176 ----
if (scalePtr->tickInterval != 0) {
! numTicks = TkCalculateNumberOfTicks(scalePtr);
! for (tickValue = scalePtr->fromValue, i = 0; i < numTicks;
! tickValue += scalePtr->tickInterval, i++) {
/*
* The TkRoundToResolution call gets rid of accumulated
***************
*** 177,189 ****
tickValue = TkRoundToResolution(scalePtr, tickValue);
- if (scalePtr->toValue >= scalePtr->fromValue) {
- if (tickValue > scalePtr->toValue) {
- break;
- }
- } else {
- if (tickValue < scalePtr->toValue) {
- break;
- }
- }
DisplayVerticalValue(scalePtr, drawable, tickValue,
scalePtr->vertTickRightX);
--- 179,182 ----
***************
*** 417,420 ****
--- 410,414 ----
Tk_Tile tile;
GC gc;
+ int numTicks, i;
/*
***************
*** 438,443 ****
if (scalePtr->tickInterval != 0) {
! for (tickValue = scalePtr->fromValue; ;
! tickValue += scalePtr->tickInterval) {
/*
* The TkRoundToResolution call gets rid of accumulated
--- 432,438 ----
if (scalePtr->tickInterval != 0) {
! numTicks = TkCalculateNumberOfTicks(scalePtr);
! for (tickValue = scalePtr->fromValue, i = 0; i < numTicks;
! tickValue += scalePtr->tickInterval, i++) {
/*
* The TkRoundToResolution call gets rid of accumulated
***************
*** 446,458 ****
tickValue = TkRoundToResolution(scalePtr, tickValue);
- if (scalePtr->toValue >= scalePtr->fromValue) {
- if (tickValue > scalePtr->toValue) {
- break;
- }
- } else {
- if (tickValue < scalePtr->toValue) {
- break;
- }
- }
DisplayHorizontalValue(scalePtr, drawable, tickValue,
scalePtr->horizTickY);
--- 441,444 ----
###########################################################
*** tkScale.c.orig Thu Nov 16 09:27:11 2000
--- tkScale.c Thu Nov 16 10:45:08 2000
***************
*** 1173,1176 ****
--- 1173,1211 ----
/*
+ *--------------------------------------------------------------
+ *
+ * TkCalculateNumberOfTicks --
+ *
+ * Calculates the number of ticks needed for the scale, based
+ * on the scale's resolution setting.
+ *
+ * Results:
+ * The return value is the number of ticks needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+ int
+ TkCalculateNumberOfTicks(scalePtr)
+ TkScale *scalePtr; /* Information about scale widget. */
+ {
+ double new, rem;
+ double interval = scalePtr->toValue-scalePtr->fromValue;
+ int numTicks;
+
+ numTicks = (int) floor(interval / scalePtr->tickInterval) + 1;
+
+ if (scalePtr->resolution > 0)
+ while (numTicks * fabs(scalePtr->tickInterval) <
+ fabs(interval) + scalePtr->resolution / 2)
+ numTicks++;
+
+ return numTicks;
+ }
+
+ /*
*----------------------------------------------------------------------
*
############################################################
*** tkScale.h.orig Thu Nov 16 09:27:18 2000
--- tkScale.h Wed Nov 15 09:51:25 2000
***************
*** 218,221 ****
--- 218,222 ----
EXTERN double TkRoundToResolution _ANSI_ARGS_((TkScale *scalePtr,
double value));
+ EXTERN int TkCalculateNumberOfTicks _ANSI_ARGS_((TkScale *scalePtr));
EXTERN TkScale * TkpCreateScale _ANSI_ARGS_((Tk_Window tkwin));
EXTERN void TkpDestroyScale _ANSI_ARGS_((TkScale *scalePtr));
############################################################
Please feel free to email me if you need more expanations etc.
Jens
--
_ _____ _____
| ||_ _||_ _| Jens.Toerring@physik.fu-berlin.de
_ | | | | | | AG Moebius, Institut fuer Molekuelphysik
| |_| | | | | | Fachbereich Physik, Freie Universitaet Berlin
\___/ens|_|homs|_|oerring Tel: ++49 (0)30 838 - 53394 / FAX: - 56046
Logged In: YES
user_id=80530
still valid?
Logged In: YES
user_id=456242
I just found this with TclTk 8.4.7 on Linux (Fedora Core 2)
-- so yes, still valid