1 #include "lib9.h" 2 #include "draw.h" 3 #include "tk.h" 4 5 #define O(t, e) ((long)(&((t*)0)->e)) 6 7 /* Layout constants */ 8 enum { 9 Triangle = 10, /* Height of scroll bar triangle */ 10 Elembw = 2, /* border around elements (triangles etc.) */ 11 }; 12 13 typedef struct TkScroll TkScroll; 14 struct TkScroll 15 { 16 int activer; 17 int orient; /* Horitontal or Vertical */ 18 int dragpix; /* Scroll delta in button drag */ 19 int dragtop; 20 int dragbot; 21 int jump; /* Jump scroll enable */ 22 int flag; /* Display flags */ 23 int top; /* Top fraction */ 24 int bot; /* Bottom fraction */ 25 int a1; /* Pixel top/left arrow1 */ 26 int t1; /* Pixel top/left trough */ 27 int t2; /* Pixel top/left lower trough */ 28 int a2; /* Pixel top/left arrow2 */ 29 char* cmd; 30 }; 31 32 enum { 33 ActiveA1 = (1<<0), /* Scrollbar control */ 34 ActiveA2 = (1<<1), 35 ActiveB1 = (1<<2), 36 ButtonA1 = (1<<3), 37 ButtonA2 = (1<<4), 38 ButtonB1 = (1<<5), 39 Autorepeat = (1<<6) 40 }; 41 42 static 43 TkOption opts[] = 44 { 45 "activerelief", OPTstab, O(TkScroll, activer), tkrelief, 46 "command", OPTtext, O(TkScroll, cmd), nil, 47 "elementborderwidth", OPTignore, 0, nil, /* deprecated */ 48 "jump", OPTstab, O(TkScroll, jump), tkbool, 49 "orient", OPTstab, O(TkScroll, orient), tkorient, 50 nil 51 }; 52 53 static 54 TkEbind b[] = 55 { 56 {TkLeave, "%W activate {}"}, 57 {TkEnter, "%W activate [%W identify %x %y]"}, 58 {TkMotion, "%W activate [%W identify %x %y]"}, 59 {TkButton1P|TkMotion, "%W tkScrollDrag %x %y"}, 60 {TkButton1P, "%W tkScrolBut1P %x %y"}, 61 {TkButton1P|TkDouble, "%W tkScrolBut1P %x %y"}, 62 {TkButton1R, "%W tkScrolBut1R; %W activate [%W identify %x %y]"}, 63 {TkButton2P, "%W tkScrolBut2P [%W fraction %x %y]"}, 64 }; 65 66 static char* 67 tkinitscroll(Tk *tk) 68 { 69 int gap; 70 TkScroll *tks; 71 72 tks = TKobj(TkScroll, tk); 73 74 gap = 2*tk->borderwidth; 75 if(tks->orient == Tkvertical) { 76 if(tk->req.width == 0) 77 tk->req.width = Triangle + gap; 78 if(tk->req.height == 0) 79 tk->req.height = 2*Triangle + gap + 6*Elembw; 80 } 81 else { 82 if(tk->req.width == 0) 83 tk->req.width = 2*Triangle + gap + 6*Elembw; 84 if(tk->req.height == 0) 85 tk->req.height = Triangle + gap; 86 } 87 88 89 return tkbindings(tk->env->top, tk, b, nelem(b)); 90 } 91 92 char* 93 tkscrollbar(TkTop *t, char *arg, char **ret) 94 { 95 Tk *tk; 96 char *e; 97 TkName *names; 98 TkScroll *tks; 99 TkOptab tko[3]; 100 101 tk = tknewobj(t, TKscrollbar, sizeof(Tk)+sizeof(TkScroll)); 102 if(tk == nil) 103 return TkNomem; 104 105 tks = TKobj(TkScroll, tk); 106 107 tk->relief = TKsunken; 108 tk->borderwidth = 2; 109 tks->activer = TKraised; 110 tks->orient = Tkvertical; 111 112 tko[0].ptr = tk; 113 tko[0].optab = tkgeneric; 114 tko[1].ptr = tks; 115 tko[1].optab = opts; 116 tko[2].ptr = nil; 117 118 names = nil; 119 e = tkparse(t, arg, tko, &names); 120 if(e != nil) { 121 tkfreeobj(tk); 122 return e; 123 } 124 tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); 125 126 e = tkinitscroll(tk); 127 if(e != nil) { 128 tkfreeobj(tk); 129 return e; 130 } 131 132 e = tkaddchild(t, tk, &names); 133 tkfreename(names); 134 if(e != nil) { 135 tkfreeobj(tk); 136 return e; 137 } 138 tk->name->link = nil; 139 140 return tkvalue(ret, "%s", tk->name->name); 141 } 142 143 static char* 144 tkscrollcget(Tk *tk, char *arg, char **val) 145 { 146 TkOptab tko[3]; 147 TkScroll *tks = TKobj(TkScroll, tk); 148 149 tko[0].ptr = tk; 150 tko[0].optab = tkgeneric; 151 tko[1].ptr = tks; 152 tko[1].optab = opts; 153 tko[2].ptr = nil; 154 155 return tkgencget(tko, arg, val, tk->env->top); 156 } 157 158 void 159 tkfreescrlb(Tk *tk) 160 { 161 TkScroll *tks = TKobj(TkScroll, tk); 162 163 if(tks->cmd != nil) 164 free(tks->cmd); 165 } 166 167 static void 168 tkvscroll(Tk *tk, TkScroll *tks, Image *i, Point size) 169 { 170 TkEnv *e; 171 Rectangle r; 172 Point p[3], o; 173 Image *d, *l, *t; 174 int bo, w, h, triangle, bgnd; 175 176 e = tk->env; 177 178 triangle = tk->act.width - Elembw; 179 180 bo = tk->borderwidth + Elembw; 181 p[0].x = size.x/2; 182 p[0].y = bo; 183 p[1].x = p[0].x - triangle/2; 184 p[1].y = p[0].y + triangle; 185 p[2].x = p[0].x + triangle/2; 186 p[2].y = p[0].y + triangle; 187 188 bgnd = TkCbackgnd; 189 if(tks->flag & (ActiveA1|ButtonA1)) { 190 bgnd = TkCactivebgnd; 191 fillpoly(i, p, 3, ~0, tkgc(e, bgnd), p[0]); 192 } 193 194 l = tkgc(e, bgnd+TkLightshade); 195 d = tkgc(e, bgnd+TkDarkshade); 196 if(tks->flag & ButtonA1) { 197 t = d; 198 d = l; 199 l = t; 200 } 201 line(i, p[1], p[2], 0, 0, 1, d, p[1]); 202 line(i, p[2], p[0], 0, 0, 1, d, p[2]); 203 line(i, p[0], p[1], 0, 0, 1, l, p[0]); 204 205 tks->a1 = p[2].y; 206 h = p[2].y + Elembw; 207 208 p[0].y = size.y - bo - 1; 209 p[1].y = p[0].y - triangle; 210 p[2].y = p[0].y - triangle; 211 212 bgnd = TkCbackgnd; 213 if(tks->flag & (ActiveA2|ButtonA2)) { 214 bgnd = TkCactivebgnd; 215 fillpoly(i, p, 3, ~0, tkgc(e, bgnd), p[0]); 216 } 217 218 l = tkgc(e, bgnd+TkLightshade); 219 d = tkgc(e, bgnd+TkDarkshade); 220 if(tks->flag & ButtonA2) { 221 t = d; 222 d = l; 223 l = t; 224 } 225 line(i, p[1], p[2], 0, 0, 1, l, p[1]); 226 line(i, p[2], p[0], 0, 0, 1, d, p[2]); 227 line(i, p[0], p[1], 0, 0, 1, l, p[0]); 228 229 tks->a2 = p[2].y; 230 231 o.x = tk->borderwidth ; 232 o.y = bo + triangle + 2*Elembw; 233 w = size.x - 2*bo; 234 h = p[2].y - 2*Elembw - h - 2*tk->borderwidth; 235 236 o.y += TKF2I(tks->top*h); 237 h *= tks->bot - tks->top; 238 h = TKF2I(h); 239 240 bgnd = TkCbackgnd; 241 if(tks->flag & (ActiveB1|ButtonB1)) { 242 r.min = o; 243 r.max.x = o.x + w + 2*2; 244 r.max.y = o.y + h + 2*2; 245 bgnd = TkCactivebgnd; 246 draw(i, r, tkgc(e, bgnd), nil, ZP); 247 } 248 249 tks->t1 = o.y - Elembw; 250 tks->t2 = o.y + h + Elembw; 251 l = tkgc(e, bgnd+TkLightshade); 252 d = tkgc(e, bgnd+TkDarkshade); 253 if(tks->flag & ButtonB1) 254 tkbevel(i, o, w, h, 2, d, l); 255 else 256 tkbevel(i, o, w, h, 2, l, d); 257 } 258 259 static void 260 tkhscroll(Tk *tk, TkScroll *tks, Image *i, Point size) 261 { 262 TkEnv *e; 263 Rectangle r; 264 Point p[3], o; 265 Image *d, *l, *t; 266 int bo, w, h, triangle, bgnd; 267 268 e = tk->env; 269 270 triangle = tk->act.height - Elembw; 271 272 bo = tk->borderwidth + Elembw; 273 p[0].x = bo; 274 p[0].y = size.y/2; 275 p[1].x = p[0].x + triangle; 276 p[1].y = p[0].y - triangle/2 + 1; 277 p[2].x = p[0].x + triangle; 278 p[2].y = p[0].y + triangle/2 - 2; 279 280 bgnd = TkCbackgnd; 281 if(tks->flag & (ActiveA1|ButtonA1)) { 282 bgnd = TkCactivebgnd; 283 fillpoly(i, p, 3, ~0, tkgc(e, bgnd), p[0]); 284 } 285 286 l = tkgc(e, bgnd+TkLightshade); 287 d = tkgc(e, bgnd+TkDarkshade); 288 289 if(tks->flag & ButtonA1) { 290 t = d; 291 d = l; 292 l = t; 293 } 294 line(i, p[1], p[2], 0, 0, 1, d, p[1]); 295 line(i, p[2], p[0], 0, 0, 1, d, p[2]); 296 line(i, p[0], p[1], 0, 0, 1, l, p[0]); 297 298 tks->a1 = p[2].x; 299 w = p[2].x + Elembw; 300 301 p[0].x = size.x - bo - 1; 302 p[1].x = p[0].x - triangle; 303 p[2].x = p[0].x - triangle; 304 305 bgnd = TkCbackgnd; 306 if(tks->flag & (ActiveA2|ButtonA2)) { 307 bgnd = TkCactivebgnd; 308 fillpoly(i, p, 3, ~0, tkgc(e, bgnd), p[0]); 309 } 310 311 l = tkgc(e, bgnd+TkLightshade); 312 d = tkgc(e, bgnd+TkDarkshade); 313 if(tks->flag & ButtonA2) { 314 t = d; 315 d = l; 316 l = t; 317 } 318 line(i, p[1], p[2], 0, 0, 1, l, p[1]); 319 line(i, p[2], p[0], 0, 0, 1, d, p[2]); 320 line(i, p[0], p[1], 0, 0, 1, l, p[0]); 321 322 tks->a2 = p[2].x; 323 324 o.x = bo + triangle + 2*Elembw; 325 o.y = tk->borderwidth; 326 w = p[2].x - 2*Elembw - w - 2*tk->borderwidth; 327 h = size.y - 2*bo; 328 329 o.x += TKF2I(tks->top*w); 330 w *= tks->bot - tks->top; 331 w = TKF2I(w); 332 333 bgnd = TkCbackgnd; 334 if(tks->flag & (ActiveB1|ButtonB1)) { 335 r.min = o; 336 r.max.x = o.x + w + 2*2; 337 r.max.y = o.y + h + 2*2; 338 bgnd = TkCactivebgnd; 339 draw(i, r, tkgc(e, bgnd), nil, ZP); 340 } 341 342 tks->t1 = o.x - Elembw; 343 tks->t2 = o.x + w + Elembw; 344 l = tkgc(e, bgnd+TkLightshade); 345 d = tkgc(e, bgnd+TkDarkshade); 346 if(tks->flag & ButtonB1) 347 tkbevel(i, o, w, h, 2, d, l); 348 else 349 tkbevel(i, o, w, h, 2, l, d); 350 } 351 352 char* 353 tkdrawscrlb(Tk *tk, Point orig) 354 { 355 Point p; 356 TkEnv *e; 357 Rectangle r; 358 Image *i, *dst; 359 TkScroll *tks = TKobj(TkScroll, tk); 360 361 e = tk->env; 362 363 dst = tkimageof(tk); 364 if(dst == nil) 365 return nil; 366 367 r.min = ZP; 368 r.max.x = tk->act.width + 2*tk->borderwidth; 369 r.max.y = tk->act.height + 2*tk->borderwidth; 370 371 i = tkitmp(e, r.max, TkCbackgnd); 372 if(i == nil) 373 return nil; 374 375 if(tks->orient == Tkvertical) 376 tkvscroll(tk, tks, i, r.max); 377 else 378 tkhscroll(tk, tks, i, r.max); 379 380 tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief); 381 382 p.x = tk->act.x + orig.x; 383 p.y = tk->act.y + orig.y; 384 r = rectaddpt(r, p); 385 draw(dst, r, i, nil, ZP); 386 387 return nil; 388 } 389 390 /* Widget Commands (+ means implemented) 391 +activate 392 +cget 393 +configure 394 +delta 395 +fraction 396 +get 397 +identify 398 +set 399 */ 400 401 static char* 402 tkscrollconf(Tk *tk, char *arg, char **val) 403 { 404 char *e; 405 TkGeom g; 406 int bd; 407 TkOptab tko[3]; 408 TkScroll *tks = TKobj(TkScroll, tk); 409 410 tko[0].ptr = tk; 411 tko[0].optab = tkgeneric; 412 tko[1].ptr = tks; 413 tko[1].optab = opts; 414 tko[2].ptr = nil; 415 416 if(*arg == '\0') 417 return tkconflist(tko, val); 418 419 g = tk->req; 420 bd = tk->borderwidth; 421 e = tkparse(tk->env->top, arg, tko, nil); 422 tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); 423 tkgeomchg(tk, &g, bd); 424 425 tk->dirty = tkrect(tk, 1); 426 return e; 427 } 428 429 static char* 430 tkscrollactivate(Tk *tk, char *arg, char **val) 431 { 432 int s, gotarg; 433 char buf[Tkmaxitem]; 434 TkScroll *tks = TKobj(TkScroll, tk); 435 436 USED(val); 437 tkword(tk->env->top, arg, buf, buf+sizeof(buf), &gotarg); 438 s = tks->flag; 439 if (!gotarg) { 440 char *a; 441 if (s & ActiveA1) 442 a = "arrow1"; 443 else if (s & ActiveA2) 444 a = "arrow2"; 445 else if (s & ActiveB1) 446 a = "slider"; 447 else 448 a = ""; 449 return tkvalue(val, a); 450 } 451 tks->flag &= ~(ActiveA1 | ActiveA2 | ActiveB1); 452 if(strcmp(buf, "arrow1") == 0) 453 tks->flag |= ActiveA1; 454 else 455 if(strcmp(buf, "arrow2") == 0) 456 tks->flag |= ActiveA2; 457 else 458 if(strcmp(buf, "slider") == 0) 459 tks->flag |= ActiveB1; 460 461 if(s ^ tks->flag) 462 tk->dirty = tkrect(tk, 1); 463 return nil; 464 } 465 466 static char* 467 tkscrollset(Tk *tk, char *arg, char **val) 468 { 469 TkTop *t; 470 char *e; 471 TkScroll *tks = TKobj(TkScroll, tk); 472 473 USED(val); 474 t = tk->env->top; 475 e = tkfracword(t, &arg, &tks->top, nil); 476 if (e != nil) 477 return e; 478 e = tkfracword(t, &arg, &tks->bot, nil); 479 if (e != nil) 480 return e; 481 if(tks->top < 0) 482 tks->top = 0; 483 if(tks->top > TKI2F(1)) 484 tks->top = TKI2F(1); 485 if(tks->bot < 0) 486 tks->bot = 0; 487 if(tks->bot > TKI2F(1)) 488 tks->bot = TKI2F(1); 489 490 tk->dirty = tkrect(tk, 1); 491 return nil; 492 } 493 494 static char* 495 tkscrolldelta(Tk *tk, char *arg, char **val) 496 { 497 int l, delta; 498 char buf[Tkmaxitem]; 499 TkScroll *tks = TKobj(TkScroll, tk); 500 501 arg = tkitem(buf, arg); 502 if(tks->orient == Tkvertical) 503 tkitem(buf, arg); 504 if(*arg == '\0' || *buf == '\0') 505 return TkBadvl; 506 507 l = tks->a2-tks->a1-4*Elembw; 508 delta = TKI2F(1); 509 if(l != 0) 510 delta = TKI2F(atoi(buf)) / l; 511 tkfprint(buf, delta); 512 513 return tkvalue(val, "%s", buf); 514 } 515 516 static char* 517 tkscrollget(Tk *tk, char *arg, char **val) 518 { 519 char *v, buf[Tkmaxitem]; 520 TkScroll *tks = TKobj(TkScroll, tk); 521 522 USED(arg); 523 v = tkfprint(buf, tks->top); 524 *v++ = ' '; 525 tkfprint(v, tks->bot); 526 527 return tkvalue(val, "%s", buf); 528 } 529 530 static char* 531 tkscrollidentify(Tk *tk, char *arg, char **val) 532 { 533 int gotarg; 534 TkTop *t; 535 char *v, buf[Tkmaxitem]; 536 Point p; 537 TkScroll *tks = TKobj(TkScroll, tk); 538 539 t = tk->env->top; 540 arg = tkword(t, arg, buf, buf+sizeof(buf), &gotarg); 541 if (!gotarg) 542 return TkBadvl; 543 p.x = atoi(buf); 544 tkword(t, arg, buf, buf+sizeof(buf), &gotarg); 545 if (!gotarg) 546 return TkBadvl; 547 p.y = atoi(buf); 548 if (!ptinrect(p, tkrect(tk, 0))) 549 return nil; 550 if (tks->orient == Tkvertical) 551 p.x = p.y; 552 p.x += tk->borderwidth; 553 554 v = ""; 555 if(p.x <= tks->a1) 556 v = "arrow1"; 557 if(p.x > tks->a1 && p.x <= tks->t1) 558 v = "trough1"; 559 if(p.x > tks->t1 && p.x < tks->t2) 560 v = "slider"; 561 if(p.x >= tks->t2 && p.x < tks->a2) 562 v = "trough2"; 563 if(p.x >= tks->a2) 564 v = "arrow2"; 565 return tkvalue(val, "%s", v); 566 } 567 568 static char* 569 tkscrollfraction(Tk *tk, char *arg, char **val) 570 { 571 int len, frac, pos; 572 char buf[Tkmaxitem]; 573 TkScroll *tks = TKobj(TkScroll, tk); 574 575 arg = tkitem(buf, arg); 576 if(tks->orient == Tkvertical) 577 tkitem(buf, arg); 578 if(*arg == '\0' || *buf == '\0') 579 return TkBadvl; 580 581 pos = atoi(buf); 582 if(pos < tks->a1) 583 pos = tks->a1; 584 if(pos > tks->a2) 585 pos = tks->a2; 586 len = tks->a2 - tks->a1 - 4*Elembw; 587 frac = TKI2F(1); 588 if(len != 0) 589 frac = TKI2F(pos-tks->a1)/len; 590 tkfprint(buf, frac); 591 return tkvalue(val, "%s", buf); 592 } 593 594 static char* 595 tkScrolBut1R(Tk *tk, char *arg, char **val) 596 { 597 TkScroll *tks = TKobj(TkScroll, tk); 598 599 USED(val); 600 USED(arg); 601 tkcancelrepeat(tk); 602 tks->flag &= ~(ActiveA1|ActiveA2|ActiveB1|ButtonA1|ButtonA2|ButtonB1|Autorepeat); 603 tk->dirty = tkrect(tk, 1); 604 return nil; 605 } 606 607 /* tkScrolBut2P fraction */ 608 static char* 609 tkScrolBut2P(Tk *tk, char *arg, char **val) 610 { 611 TkTop *t; 612 char *e, buf[Tkmaxitem], fracbuf[Tkmaxitem]; 613 TkScroll *tks = TKobj(TkScroll, tk); 614 615 616 USED(val); 617 t = tk->env->top; 618 619 if(arg[0] == '\0') 620 return TkBadvl; 621 622 tkword(t, arg, fracbuf, fracbuf+sizeof(fracbuf), nil); 623 624 e = nil; 625 if(tks->cmd != nil) { 626 snprint(buf, sizeof(buf), "%s moveto %s", tks->cmd, fracbuf); 627 e = tkexec(t, buf, nil); 628 } 629 return e; 630 } 631 632 static void 633 sbrepeat(Tk *tk, void *v, int cancelled) 634 { 635 char *e, buf[Tkmaxitem]; 636 TkScroll *tks = TKobj(TkScroll, tk); 637 char *fmt = (char *)v; 638 639 if (cancelled) { 640 tks->flag &= ~Autorepeat; 641 return; 642 } 643 644 if(tks->cmd != nil && fmt != nil) { 645 snprint(buf, sizeof(buf), fmt, tks->cmd); 646 e = tkexec(tk->env->top, buf, nil); 647 if (e != nil) { 648 tks->flag &= ~Autorepeat; 649 tkcancelrepeat(tk); 650 } else 651 tkupdate(tk->env->top); 652 } 653 } 654 655 /* tkScrolBut1P %x %y */ 656 static char* 657 tkScrolBut1P(Tk *tk, char *arg, char **val) 658 { 659 int pix; 660 TkTop *t; 661 char *e, *fmt, buf[Tkmaxitem]; 662 TkScroll *tks = TKobj(TkScroll, tk); 663 664 USED(val); 665 t = tk->env->top; 666 667 if (tks->flag & Autorepeat) 668 return nil; 669 arg = tkword(t, arg, buf, buf+sizeof(buf), nil); 670 if(tks->orient == Tkvertical) 671 tkword(t, arg, buf, buf+sizeof(buf), nil); 672 if(buf[0] == '\0') 673 return TkBadvl; 674 675 pix = atoi(buf); 676 677 tks->dragpix = pix; 678 tks->dragtop = tks->top; 679 tks->dragbot = tks->bot; 680 681 pix += tk->borderwidth; 682 683 fmt = nil; 684 e = nil; 685 if(pix <= tks->a1) { 686 fmt = "%s scroll -1 unit"; 687 tks->flag |= ButtonA1; 688 } 689 if(pix > tks->a1 && pix <= tks->t1) 690 fmt = "%s scroll -1 page"; 691 if(pix > tks->t1 && pix < tks->t2) 692 tks->flag |= ButtonB1; 693 if(pix >= tks->t2 && pix < tks->a2) 694 fmt = "%s scroll 1 page"; 695 if(pix >= tks->a2) { 696 fmt = "%s scroll 1 unit"; 697 tks->flag |= ButtonA2; 698 } 699 if(tks->cmd != nil && fmt != nil) { 700 snprint(buf, sizeof(buf), fmt, tks->cmd); 701 e = tkexec(t, buf, nil); 702 tks->flag |= Autorepeat; 703 tkrepeat(tk, sbrepeat, fmt, TkRptpause, TkRptinterval); 704 } 705 tk->dirty = tkrect(tk, 1); 706 return e; 707 } 708 709 /* tkScrolDrag %x %y */ 710 static char* 711 tkScrollDrag(Tk *tk, char *arg, char **val) 712 { 713 TkTop *t; 714 int pix, delta; 715 char frac[32], buf[Tkmaxitem]; 716 TkScroll *tks = TKobj(TkScroll, tk); 717 718 USED(val); 719 t = tk->env->top; 720 721 if (tks->flag & Autorepeat) 722 return nil; 723 if((tks->flag & ButtonB1) == 0) 724 return nil; 725 726 arg = tkword(t, arg, buf, buf+sizeof(buf), nil); 727 if(tks->orient == Tkvertical) 728 tkword(t, arg, buf, buf+sizeof(buf), nil); 729 if(buf[0] == '\0') 730 return TkBadvl; 731 732 pix = atoi(buf); 733 734 delta = TKI2F(pix-tks->dragpix); 735 if ( tks->a2 == tks->a1 ) 736 return TkBadvl; 737 delta = delta/(tks->a2-tks->a1-4*Elembw); 738 if(tks->jump == BoolT) { 739 if(tks->dragtop+delta >= 0 && 740 tks->dragbot+delta <= TKI2F(1)) { 741 tks->top = tks->dragtop+delta; 742 tks->bot = tks->dragbot+delta; 743 } 744 return nil; 745 } 746 if(tks->cmd != nil) { 747 delta += tks->dragtop; 748 if(delta < 0) 749 delta = 0; 750 if(delta > TKI2F(1)) 751 delta = TKI2F(1); 752 tkfprint(frac, delta); 753 snprint(buf, sizeof(buf), "%s moveto %s", tks->cmd, frac); 754 return tkexec(t, buf, nil); 755 } 756 return nil; 757 } 758 759 TkCmdtab tkscrlbcmd[] = 760 { 761 "activate", tkscrollactivate, 762 "cget", tkscrollcget, 763 "configure", tkscrollconf, 764 "delta", tkscrolldelta, 765 "fraction", tkscrollfraction, 766 "get", tkscrollget, 767 "identify", tkscrollidentify, 768 "set", tkscrollset, 769 "tkScrollDrag", tkScrollDrag, 770 "tkScrolBut1P", tkScrolBut1P, 771 "tkScrolBut1R", tkScrolBut1R, 772 "tkScrolBut2P", tkScrolBut2P, 773 nil 774 }; 775 776 TkMethod scrollbarmethod = { 777 "scrollbar", 778 tkscrlbcmd, 779 tkfreescrlb, 780 tkdrawscrlb 781 }; 782