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