1/* 2 * tkUnixScale.c -- 3 * 4 * This file implements the X specific portion of the scrollbar 5 * widget. 6 * 7 * Copyright (c) 1996 by Sun Microsystems, Inc. 8 * Copyright (c) 1998-2000 by Scriptics Corporation. 9 * 10 * See the file "license.terms" for information on usage and redistribution 11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 * 13 * RCS: @(#) $Id: tkUnixScale.c,v 1.8.4.2 2007/04/29 02:24:01 das Exp $ 14 */ 15 16#include "tkScale.h" 17#include "tkInt.h" 18 19/* 20 * Forward declarations for procedures defined later in this file: 21 */ 22 23static void DisplayHorizontalScale _ANSI_ARGS_((TkScale *scalePtr, 24 Drawable drawable, XRectangle *drawnAreaPtr)); 25static void DisplayHorizontalValue _ANSI_ARGS_((TkScale *scalePtr, 26 Drawable drawable, double value, int top)); 27static void DisplayVerticalScale _ANSI_ARGS_((TkScale *scalePtr, 28 Drawable drawable, XRectangle *drawnAreaPtr)); 29static void DisplayVerticalValue _ANSI_ARGS_((TkScale *scalePtr, 30 Drawable drawable, double value, int rightEdge)); 31 32/* 33 *---------------------------------------------------------------------- 34 * 35 * TkpCreateScale -- 36 * 37 * Allocate a new TkScale structure. 38 * 39 * Results: 40 * Returns a newly allocated TkScale structure. 41 * 42 * Side effects: 43 * None. 44 * 45 *---------------------------------------------------------------------- 46 */ 47 48TkScale * 49TkpCreateScale(tkwin) 50 Tk_Window tkwin; 51{ 52 return (TkScale *) ckalloc(sizeof(TkScale)); 53} 54 55/* 56 *---------------------------------------------------------------------- 57 * 58 * TkpDestroyScale -- 59 * 60 * Destroy a TkScale structure. It's necessary to do this with 61 * Tcl_EventuallyFree to allow the Tcl_Preserve(scalePtr) to work 62 * as expected in TkpDisplayScale. (hobbs) 63 * 64 * Results: 65 * None 66 * 67 * Side effects: 68 * Memory is freed. 69 * 70 *---------------------------------------------------------------------- 71 */ 72 73void 74TkpDestroyScale(scalePtr) 75 TkScale *scalePtr; 76{ 77 Tcl_EventuallyFree((ClientData) scalePtr, TCL_DYNAMIC); 78} 79 80/* 81 *-------------------------------------------------------------- 82 * 83 * DisplayVerticalScale -- 84 * 85 * This procedure redraws the contents of a vertical scale 86 * window. It is invoked as a do-when-idle handler, so it only 87 * runs when there's nothing else for the application to do. 88 * 89 * Results: 90 * There is no return value. If only a part of the scale needs 91 * to be redrawn, then drawnAreaPtr is modified to reflect the 92 * area that was actually modified. 93 * 94 * Side effects: 95 * Information appears on the screen. 96 * 97 *-------------------------------------------------------------- 98 */ 99 100static void 101DisplayVerticalScale(scalePtr, drawable, drawnAreaPtr) 102 TkScale *scalePtr; /* Widget record for scale. */ 103 Drawable drawable; /* Where to display scale (window 104 * or pixmap). */ 105 XRectangle *drawnAreaPtr; /* Initally contains area of window; 106 * if only a part of the scale is 107 * redrawn, gets modified to reflect 108 * the part of the window that was 109 * redrawn. */ 110{ 111 Tk_Window tkwin = scalePtr->tkwin; 112 int x, y, width, height, shadowWidth; 113 double tickValue, tickInterval = scalePtr->tickInterval; 114 Tk_3DBorder sliderBorder; 115 116 /* 117 * Display the information from left to right across the window. 118 */ 119 120 if (!(scalePtr->flags & REDRAW_OTHER)) { 121 drawnAreaPtr->x = scalePtr->vertTickRightX; 122 drawnAreaPtr->y = scalePtr->inset; 123 drawnAreaPtr->width = scalePtr->vertTroughX + scalePtr->width 124 + 2*scalePtr->borderWidth - scalePtr->vertTickRightX; 125 drawnAreaPtr->height -= 2*scalePtr->inset; 126 } 127 Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder, 128 drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width, 129 drawnAreaPtr->height, 0, TK_RELIEF_FLAT); 130 if (scalePtr->flags & REDRAW_OTHER) { 131 /* 132 * Display the tick marks. 133 */ 134 135 if (tickInterval != 0) { 136 double ticks, maxTicks; 137 138 /* 139 * Ensure that we will only draw enough of the tick values 140 * such that they don't overlap 141 */ 142 ticks = fabs((scalePtr->toValue - scalePtr->fromValue) 143 / tickInterval); 144 maxTicks = (double) Tk_Height(tkwin) 145 / (double) scalePtr->fontHeight; 146 if (ticks > maxTicks) { 147 tickInterval *= (ticks / maxTicks); 148 } 149 for (tickValue = scalePtr->fromValue; ; 150 tickValue += tickInterval) { 151 /* 152 * The TkRoundToResolution call gets rid of accumulated 153 * round-off errors, if any. 154 */ 155 156 tickValue = TkRoundToResolution(scalePtr, tickValue); 157 if (scalePtr->toValue >= scalePtr->fromValue) { 158 if (tickValue > scalePtr->toValue) { 159 break; 160 } 161 } else { 162 if (tickValue < scalePtr->toValue) { 163 break; 164 } 165 } 166 DisplayVerticalValue(scalePtr, drawable, tickValue, 167 scalePtr->vertTickRightX); 168 } 169 } 170 } 171 172 /* 173 * Display the value, if it is desired. 174 */ 175 176 if (scalePtr->showValue) { 177 DisplayVerticalValue(scalePtr, drawable, scalePtr->value, 178 scalePtr->vertValueRightX); 179 } 180 181 /* 182 * Display the trough and the slider. 183 */ 184 185 Tk_Draw3DRectangle(tkwin, drawable, 186 scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset, 187 scalePtr->width + 2*scalePtr->borderWidth, 188 Tk_Height(tkwin) - 2*scalePtr->inset, scalePtr->borderWidth, 189 TK_RELIEF_SUNKEN); 190 XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC, 191 scalePtr->vertTroughX + scalePtr->borderWidth, 192 scalePtr->inset + scalePtr->borderWidth, 193 (unsigned) scalePtr->width, 194 (unsigned) (Tk_Height(tkwin) - 2*scalePtr->inset 195 - 2*scalePtr->borderWidth)); 196 if (scalePtr->state == STATE_ACTIVE) { 197 sliderBorder = scalePtr->activeBorder; 198 } else { 199 sliderBorder = scalePtr->bgBorder; 200 } 201 width = scalePtr->width; 202 height = scalePtr->sliderLength/2; 203 x = scalePtr->vertTroughX + scalePtr->borderWidth; 204 y = TkScaleValueToPixel(scalePtr, scalePtr->value) - height; 205 shadowWidth = scalePtr->borderWidth/2; 206 if (shadowWidth == 0) { 207 shadowWidth = 1; 208 } 209 Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width, 210 2*height, shadowWidth, scalePtr->sliderRelief); 211 x += shadowWidth; 212 y += shadowWidth; 213 width -= 2*shadowWidth; 214 height -= shadowWidth; 215 Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, 216 height, shadowWidth, scalePtr->sliderRelief); 217 Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height, 218 width, height, shadowWidth, scalePtr->sliderRelief); 219 220 /* 221 * Draw the label to the right of the scale. 222 */ 223 224 if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) { 225 Tk_FontMetrics fm; 226 227 Tk_GetFontMetrics(scalePtr->tkfont, &fm); 228 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, 229 scalePtr->tkfont, scalePtr->label, 230 scalePtr->labelLength, scalePtr->vertLabelX, 231 scalePtr->inset + (3*fm.ascent)/2); 232 } 233} 234 235/* 236 *---------------------------------------------------------------------- 237 * 238 * DisplayVerticalValue -- 239 * 240 * This procedure is called to display values (scale readings) 241 * for vertically-oriented scales. 242 * 243 * Results: 244 * None. 245 * 246 * Side effects: 247 * The numerical value corresponding to value is displayed with 248 * its right edge at "rightEdge", and at a vertical position in 249 * the scale that corresponds to "value". 250 * 251 *---------------------------------------------------------------------- 252 */ 253 254static void 255DisplayVerticalValue(scalePtr, drawable, value, rightEdge) 256 register TkScale *scalePtr; /* Information about widget in which to 257 * display value. */ 258 Drawable drawable; /* Pixmap or window in which to draw 259 * the value. */ 260 double value; /* Y-coordinate of number to display, 261 * specified in application coords, not 262 * in pixels (we'll compute pixels). */ 263 int rightEdge; /* X-coordinate of right edge of text, 264 * specified in pixels. */ 265{ 266 register Tk_Window tkwin = scalePtr->tkwin; 267 int y, width, length; 268 char valueString[PRINT_CHARS]; 269 Tk_FontMetrics fm; 270 271 Tk_GetFontMetrics(scalePtr->tkfont, &fm); 272 y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2; 273 sprintf(valueString, scalePtr->format, value); 274 length = (int) strlen(valueString); 275 width = Tk_TextWidth(scalePtr->tkfont, valueString, length); 276 277 /* 278 * Adjust the y-coordinate if necessary to keep the text entirely 279 * inside the window. 280 */ 281 282 if ((y - fm.ascent) < (scalePtr->inset + SPACING)) { 283 y = scalePtr->inset + SPACING + fm.ascent; 284 } 285 if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) { 286 y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent; 287 } 288 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, 289 scalePtr->tkfont, valueString, length, rightEdge - width, y); 290} 291 292/* 293 *-------------------------------------------------------------- 294 * 295 * DisplayHorizontalScale -- 296 * 297 * This procedure redraws the contents of a horizontal scale 298 * window. It is invoked as a do-when-idle handler, so it only 299 * runs when there's nothing else for the application to do. 300 * 301 * Results: 302 * There is no return value. If only a part of the scale needs 303 * to be redrawn, then drawnAreaPtr is modified to reflect the 304 * area that was actually modified. 305 * 306 * Side effects: 307 * Information appears on the screen. 308 * 309 *-------------------------------------------------------------- 310 */ 311 312static void 313DisplayHorizontalScale(scalePtr, drawable, drawnAreaPtr) 314 TkScale *scalePtr; /* Widget record for scale. */ 315 Drawable drawable; /* Where to display scale (window 316 * or pixmap). */ 317 XRectangle *drawnAreaPtr; /* Initally contains area of window; 318 * if only a part of the scale is 319 * redrawn, gets modified to reflect 320 * the part of the window that was 321 * redrawn. */ 322{ 323 register Tk_Window tkwin = scalePtr->tkwin; 324 int x, y, width, height, shadowWidth; 325 double tickValue, tickInterval = scalePtr->tickInterval; 326 Tk_3DBorder sliderBorder; 327 328 /* 329 * Display the information from bottom to top across the window. 330 */ 331 332 if (!(scalePtr->flags & REDRAW_OTHER)) { 333 drawnAreaPtr->x = scalePtr->inset; 334 drawnAreaPtr->y = scalePtr->horizValueY; 335 drawnAreaPtr->width -= 2*scalePtr->inset; 336 drawnAreaPtr->height = scalePtr->horizTroughY + scalePtr->width 337 + 2*scalePtr->borderWidth - scalePtr->horizValueY; 338 } 339 Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder, 340 drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width, 341 drawnAreaPtr->height, 0, TK_RELIEF_FLAT); 342 if (scalePtr->flags & REDRAW_OTHER) { 343 /* 344 * Display the tick marks. 345 */ 346 347 if (tickInterval != 0) { 348 char valueString[PRINT_CHARS]; 349 double ticks, maxTicks; 350 351 /* 352 * Ensure that we will only draw enough of the tick values 353 * such that they don't overlap. We base this off the width that 354 * fromValue would take. Not exact, but better than no constraint. 355 */ 356 ticks = fabs((scalePtr->toValue - scalePtr->fromValue) 357 / tickInterval); 358 sprintf(valueString, scalePtr->format, scalePtr->fromValue); 359 maxTicks = (double) Tk_Width(tkwin) 360 / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1); 361 if (ticks > maxTicks) { 362 tickInterval *= (ticks / maxTicks); 363 } 364 for (tickValue = scalePtr->fromValue; ; 365 tickValue += tickInterval) { 366 /* 367 * The TkRoundToResolution call gets rid of accumulated 368 * round-off errors, if any. 369 */ 370 371 tickValue = TkRoundToResolution(scalePtr, tickValue); 372 if (scalePtr->toValue >= scalePtr->fromValue) { 373 if (tickValue > scalePtr->toValue) { 374 break; 375 } 376 } else { 377 if (tickValue < scalePtr->toValue) { 378 break; 379 } 380 } 381 DisplayHorizontalValue(scalePtr, drawable, tickValue, 382 scalePtr->horizTickY); 383 } 384 } 385 } 386 387 /* 388 * Display the value, if it is desired. 389 */ 390 391 if (scalePtr->showValue) { 392 DisplayHorizontalValue(scalePtr, drawable, scalePtr->value, 393 scalePtr->horizValueY); 394 } 395 396 /* 397 * Display the trough and the slider. 398 */ 399 400 y = scalePtr->horizTroughY; 401 Tk_Draw3DRectangle(tkwin, drawable, 402 scalePtr->bgBorder, scalePtr->inset, y, 403 Tk_Width(tkwin) - 2*scalePtr->inset, 404 scalePtr->width + 2*scalePtr->borderWidth, 405 scalePtr->borderWidth, TK_RELIEF_SUNKEN); 406 XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC, 407 scalePtr->inset + scalePtr->borderWidth, 408 y + scalePtr->borderWidth, 409 (unsigned) (Tk_Width(tkwin) - 2*scalePtr->inset 410 - 2*scalePtr->borderWidth), 411 (unsigned) scalePtr->width); 412 if (scalePtr->state == STATE_ACTIVE) { 413 sliderBorder = scalePtr->activeBorder; 414 } else { 415 sliderBorder = scalePtr->bgBorder; 416 } 417 width = scalePtr->sliderLength/2; 418 height = scalePtr->width; 419 x = TkScaleValueToPixel(scalePtr, scalePtr->value) - width; 420 y += scalePtr->borderWidth; 421 shadowWidth = scalePtr->borderWidth/2; 422 if (shadowWidth == 0) { 423 shadowWidth = 1; 424 } 425 Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, 426 x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief); 427 x += shadowWidth; 428 y += shadowWidth; 429 width -= shadowWidth; 430 height -= 2*shadowWidth; 431 Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height, 432 shadowWidth, scalePtr->sliderRelief); 433 Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y, 434 width, height, shadowWidth, scalePtr->sliderRelief); 435 436 /* 437 * Draw the label at the top of the scale. 438 */ 439 440 if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) { 441 Tk_FontMetrics fm; 442 443 Tk_GetFontMetrics(scalePtr->tkfont, &fm); 444 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, 445 scalePtr->tkfont, scalePtr->label, 446 scalePtr->labelLength, scalePtr->inset + fm.ascent/2, 447 scalePtr->horizLabelY + fm.ascent); 448 } 449} 450 451/* 452 *---------------------------------------------------------------------- 453 * 454 * DisplayHorizontalValue -- 455 * 456 * This procedure is called to display values (scale readings) 457 * for horizontally-oriented scales. 458 * 459 * Results: 460 * None. 461 * 462 * Side effects: 463 * The numerical value corresponding to value is displayed with 464 * its bottom edge at "bottom", and at a horizontal position in 465 * the scale that corresponds to "value". 466 * 467 *---------------------------------------------------------------------- 468 */ 469 470static void 471DisplayHorizontalValue(scalePtr, drawable, value, top) 472 register TkScale *scalePtr; /* Information about widget in which to 473 * display value. */ 474 Drawable drawable; /* Pixmap or window in which to draw 475 * the value. */ 476 double value; /* X-coordinate of number to display, 477 * specified in application coords, not 478 * in pixels (we'll compute pixels). */ 479 int top; /* Y-coordinate of top edge of text, 480 * specified in pixels. */ 481{ 482 register Tk_Window tkwin = scalePtr->tkwin; 483 int x, y, length, width; 484 char valueString[PRINT_CHARS]; 485 Tk_FontMetrics fm; 486 487 x = TkScaleValueToPixel(scalePtr, value); 488 Tk_GetFontMetrics(scalePtr->tkfont, &fm); 489 y = top + fm.ascent; 490 sprintf(valueString, scalePtr->format, value); 491 length = (int) strlen(valueString); 492 width = Tk_TextWidth(scalePtr->tkfont, valueString, length); 493 494 /* 495 * Adjust the x-coordinate if necessary to keep the text entirely 496 * inside the window. 497 */ 498 499 x -= (width)/2; 500 if (x < (scalePtr->inset + SPACING)) { 501 x = scalePtr->inset + SPACING; 502 } 503 /* 504 * Check the right border so use starting point +text width 505 * for the check. 506 */ 507 if (x + width >= (Tk_Width(tkwin) - scalePtr->inset)) { 508 x = Tk_Width(tkwin) - scalePtr->inset - SPACING - width; 509 } 510 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, 511 scalePtr->tkfont, valueString, length, x, y); 512} 513 514/* 515 *---------------------------------------------------------------------- 516 * 517 * TkpDisplayScale -- 518 * 519 * This procedure is invoked as an idle handler to redisplay 520 * the contents of a scale widget. 521 * 522 * Results: 523 * None. 524 * 525 * Side effects: 526 * The scale gets redisplayed. 527 * 528 *---------------------------------------------------------------------- 529 */ 530 531void 532TkpDisplayScale(clientData) 533 ClientData clientData; /* Widget record for scale. */ 534{ 535 TkScale *scalePtr = (TkScale *) clientData; 536 Tk_Window tkwin = scalePtr->tkwin; 537 Tcl_Interp *interp = scalePtr->interp; 538 Pixmap pixmap; 539 int result; 540 char string[PRINT_CHARS]; 541 XRectangle drawnArea; 542 543 scalePtr->flags &= ~REDRAW_PENDING; 544 if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) { 545 goto done; 546 } 547 548 /* 549 * Invoke the scale's command if needed. 550 */ 551 Tcl_Preserve((ClientData) scalePtr); 552 if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { 553 Tcl_Preserve((ClientData) interp); 554 sprintf(string, scalePtr->format, scalePtr->value); 555 result = Tcl_VarEval(interp, scalePtr->command, " ", string, 556 (char *) NULL); 557 if (result != TCL_OK) { 558 Tcl_AddErrorInfo(interp, "\n (command executed by scale)"); 559 Tcl_BackgroundError(interp); 560 } 561 Tcl_Release((ClientData) interp); 562 } 563 scalePtr->flags &= ~INVOKE_COMMAND; 564 if (scalePtr->flags & SCALE_DELETED) { 565 Tcl_Release((ClientData) scalePtr); 566 return; 567 } 568 Tcl_Release((ClientData) scalePtr); 569 570#ifndef TK_NO_DOUBLE_BUFFERING 571 /* 572 * In order to avoid screen flashes, this procedure redraws 573 * the scale in a pixmap, then copies the pixmap to the 574 * screen in a single operation. This means that there's no 575 * point in time where the on-sreen image has been cleared. 576 */ 577 578 pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin), 579 Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); 580#else 581 pixmap = Tk_WindowId(tkwin); 582#endif /* TK_NO_DOUBLE_BUFFERING */ 583 drawnArea.x = 0; 584 drawnArea.y = 0; 585 drawnArea.width = Tk_Width(tkwin); 586 drawnArea.height = Tk_Height(tkwin); 587 588 /* 589 * Much of the redisplay is done totally differently for 590 * horizontal and vertical scales. Handle the part that's 591 * different. 592 */ 593 594 if (scalePtr->orient == ORIENT_VERTICAL) { 595 DisplayVerticalScale(scalePtr, pixmap, &drawnArea); 596 } else { 597 DisplayHorizontalScale(scalePtr, pixmap, &drawnArea); 598 } 599 600 /* 601 * Now handle the part of redisplay that is the same for 602 * horizontal and vertical scales: border and traversal 603 * highlight. 604 */ 605 606 if (scalePtr->flags & REDRAW_OTHER) { 607 if (scalePtr->relief != TK_RELIEF_FLAT) { 608 Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder, 609 scalePtr->highlightWidth, scalePtr->highlightWidth, 610 Tk_Width(tkwin) - 2*scalePtr->highlightWidth, 611 Tk_Height(tkwin) - 2*scalePtr->highlightWidth, 612 scalePtr->borderWidth, scalePtr->relief); 613 } 614 if (scalePtr->highlightWidth != 0) { 615 GC gc; 616 617 if (scalePtr->flags & GOT_FOCUS) { 618 gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap); 619 } else { 620 gc = Tk_GCForColor( 621 Tk_3DBorderColor(scalePtr->highlightBorder), pixmap); 622 } 623 Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap); 624 } 625 } 626 627#ifndef TK_NO_DOUBLE_BUFFERING 628 /* 629 * Copy the information from the off-screen pixmap onto the screen, 630 * then delete the pixmap. 631 */ 632 633 XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin), 634 scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width, 635 drawnArea.height, drawnArea.x, drawnArea.y); 636 Tk_FreePixmap(scalePtr->display, pixmap); 637#endif /* TK_NO_DOUBLE_BUFFERING */ 638 639 done: 640 scalePtr->flags &= ~REDRAW_ALL; 641} 642 643/* 644 *---------------------------------------------------------------------- 645 * 646 * TkpScaleElement -- 647 * 648 * Determine which part of a scale widget lies under a given 649 * point. 650 * 651 * Results: 652 * The return value is either TROUGH1, SLIDER, TROUGH2, or 653 * OTHER, depending on which of the scale's active elements 654 * (if any) is under the point at (x,y). 655 * 656 * Side effects: 657 * None. 658 * 659 *---------------------------------------------------------------------- 660 */ 661 662int 663TkpScaleElement(scalePtr, x, y) 664 TkScale *scalePtr; /* Widget record for scale. */ 665 int x, y; /* Coordinates within scalePtr's window. */ 666{ 667 int sliderFirst; 668 669 if (scalePtr->orient == ORIENT_VERTICAL) { 670 if ((x < scalePtr->vertTroughX) 671 || (x >= (scalePtr->vertTroughX + 2*scalePtr->borderWidth + 672 scalePtr->width))) { 673 return OTHER; 674 } 675 if ((y < scalePtr->inset) 676 || (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) { 677 return OTHER; 678 } 679 sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value) 680 - scalePtr->sliderLength/2; 681 if (y < sliderFirst) { 682 return TROUGH1; 683 } 684 if (y < (sliderFirst+scalePtr->sliderLength)) { 685 return SLIDER; 686 } 687 return TROUGH2; 688 } 689 690 if ((y < scalePtr->horizTroughY) 691 || (y >= (scalePtr->horizTroughY + 2*scalePtr->borderWidth + 692 scalePtr->width))) { 693 return OTHER; 694 } 695 if ((x < scalePtr->inset) 696 || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) { 697 return OTHER; 698 } 699 sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value) 700 - scalePtr->sliderLength/2; 701 if (x < sliderFirst) { 702 return TROUGH1; 703 } 704 if (x < (sliderFirst+scalePtr->sliderLength)) { 705 return SLIDER; 706 } 707 return TROUGH2; 708} 709