|
|
1.1 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: ! 12: /****************************** Module Header ******************************* ! 13: * Module Name: TSCROLL.C ! 14: * ! 15: * Scrolling and selection routines. ! 16: * ! 17: * Functions: ! 18: * ! 19: * gtab_msg_vscroll() ! 20: * gtab_msg_hscroll() ! 21: * gtab_dovscroll() ! 22: * gtab_dohscroll() ! 23: * gtab_linetorow() ! 24: * gtab_rowtoline() ! 25: * gtab_select() ! 26: * gtab_ytoline() ! 27: * gtab_xtocol() ! 28: * gtab_isborder() ! 29: * gtab_enter() ! 30: * gtab_trackcol() ! 31: * gtab_press() ! 32: * gtab_release() ! 33: * gtab_move() ! 34: * gtab_dblclick() ! 35: * gtab_showsel() ! 36: * gtab_showsel_middle() ! 37: * gtab_changesel() ! 38: * gtab_selhome() ! 39: * gtab_key() ! 40: * ! 41: * Comments: ! 42: * ! 43: * This implementation currently only supports TM_SINGLE, not TM_MANY ! 44: * modes of selection. ! 45: * ! 46: ****************************************************************************/ ! 47: ! 48: #include <windows.h> ! 49: #include <commdlg.h> ! 50: ! 51: #include "gutils.h" ! 52: #include "table.h" ! 53: #include "tpriv.h" ! 54: ! 55: /*************************************************************************** ! 56: * Function: gtab_msg_vscroll ! 57: * ! 58: * Purpose: ! 59: * ! 60: * Handle a vscroll message ! 61: */ ! 62: void ! 63: gtab_msg_vscroll(HWND hwnd, lpTable ptab, int opcode, int pos) ! 64: { ! 65: long change; ! 66: ! 67: switch(opcode) { ! 68: case SB_THUMBPOSITION: ! 69: change = (pos * ptab->scrollscale) - ptab->toprow; ! 70: break; ! 71: ! 72: case SB_LINEUP: ! 73: change = -1; ! 74: break; ! 75: ! 76: case SB_LINEDOWN: ! 77: change = 1; ! 78: break; ! 79: ! 80: case SB_PAGEUP: ! 81: change = - (ptab->nlines - 3); ! 82: break; ! 83: ! 84: case SB_PAGEDOWN: ! 85: change = (ptab->nlines - 3); ! 86: break; ! 87: ! 88: default: ! 89: return; ! 90: } ! 91: gtab_dovscroll(hwnd, ptab, change); ! 92: } ! 93: ! 94: /*************************************************************************** ! 95: * Function: gtab_msg_hscroll ! 96: * ! 97: * Purpose: ! 98: * ! 99: * Handle a hscroll message ! 100: */ ! 101: void ! 102: gtab_msg_hscroll(HWND hwnd, lpTable ptab, int opcode, int pos) ! 103: { ! 104: int change; ! 105: ! 106: switch(opcode) { ! 107: case SB_THUMBPOSITION: ! 108: change = pos - ptab->scroll_dx; ! 109: break; ! 110: ! 111: case SB_LINEUP: ! 112: change = -(ptab->avewidth); ! 113: break; ! 114: ! 115: case SB_LINEDOWN: ! 116: change = ptab->avewidth; ! 117: break; ! 118: ! 119: case SB_PAGEUP: ! 120: change = - (ptab->winwidth * 2 / 3); ! 121: break; ! 122: ! 123: case SB_PAGEDOWN: ! 124: change = (ptab->winwidth * 2 / 3); ! 125: break; ! 126: ! 127: default: ! 128: return; ! 129: } ! 130: gtab_dohscroll(hwnd, ptab, change); ! 131: } ! 132: ! 133: ! 134: ! 135: /*************************************************************************** ! 136: * Function: gtab_dovscroll ! 137: * ! 138: * Purpose: ! 139: * ! 140: * Set new vertical scroll pos, ! 141: * adjust linedata array ! 142: * set line win-relative start posns & clip top/bottom posns ! 143: * revise display. ! 144: */ ! 145: void ! 146: gtab_dovscroll(HWND hwnd, lpTable ptab, long change) ! 147: { ! 148: int cury, i; ! 149: long ncopy; ! 150: lpCellPos cp; ! 151: LineData ldtemp; ! 152: RECT rc, rcpaint; ! 153: long range; ! 154: long newtop; ! 155: int newpos; ! 156: ! 157: ! 158: range = ptab->hdr.nrows - (ptab->nlines - 1); ! 159: newtop = ptab->toprow + change; ! 160: if (range < 0) { ! 161: range = 0; ! 162: } ! 163: if (newtop > range) { ! 164: change = range - ptab->toprow; ! 165: } else if (newtop < 0) { ! 166: change = -(ptab->toprow); ! 167: } ! 168: ptab->toprow += change; ! 169: ! 170: newpos = (int) (newtop / ptab->scrollscale); ! 171: SetScrollPos(hwnd, SB_VERT, newpos, TRUE); ! 172: ! 173: if (ptab->hdr.sendscroll) { ! 174: gtab_sendtq(hwnd, TQ_SCROLL, ptab->toprow); ! 175: } ! 176: ! 177: /* adjust data ptrs rather than invalidate, to retain the ! 178: * data we know is still valid ! 179: */ ! 180: if (abs(change) >= ptab->nlines) { ! 181: gtab_invallines(hwnd, ptab, ptab->hdr.fixedrows, ! 182: ptab->nlines - ptab->hdr.fixedrows); ! 183: InvalidateRect(hwnd, NULL, TRUE); ! 184: change = 0; ! 185: } else if (change < 0) { ! 186: /* copy data down */ ! 187: ncopy = (ptab->nlines - ptab->hdr.fixedrows) - abs(change); ! 188: for (i = ptab->nlines - 1; ! 189: i >= (ptab->hdr.fixedrows + abs(change)); i--) { ! 190: ldtemp = ptab->pdata[i - abs(change)]; ! 191: ptab->pdata[i - abs(change)] = ptab->pdata[i]; ! 192: ptab->pdata[i] = ldtemp; ! 193: } ! 194: gtab_invallines(hwnd, ptab, ! 195: ptab->hdr.fixedrows, (int) abs(change)); ! 196: } else if (change > 0) { ! 197: ncopy = (ptab->nlines - ptab->hdr.fixedrows) - change; ! 198: for (i = ptab->hdr.fixedrows; ! 199: i < (ncopy + ptab->hdr.fixedrows); i++) { ! 200: ldtemp = ptab->pdata[i + change]; ! 201: ptab->pdata[i + change] = ptab->pdata[i]; ! 202: ptab->pdata[i] = ldtemp; ! 203: } ! 204: gtab_invallines(hwnd, ptab, ! 205: (int) ncopy + ptab->hdr.fixedrows, (int) change); ! 206: } ! 207: ! 208: /* scroll window */ ! 209: GetClientRect(hwnd, &rc); ! 210: rcpaint = rc; ! 211: if (change > 0) { ! 212: rc.top += (int) (change + ptab->hdr.fixedrows) * ptab->rowheight; ! 213: rcpaint.top = (ptab->hdr.fixedrows * ptab->rowheight); ! 214: rcpaint.top += rc.bottom - rc.top; ! 215: } else if (change < 0) { ! 216: rc.top += (ptab->hdr.fixedrows * ptab->rowheight); ! 217: rc.bottom -= (int) (change * ptab->rowheight); ! 218: rcpaint.bottom -= rc.bottom - rc.top; ! 219: } ! 220: ! 221: /* loop through each line setting relative posn and clipping */ ! 222: ! 223: /* set up all rows - the fixed/moveable difference for ! 224: * rows is made at fetch-time during painting, when we remember ! 225: * which absolute row nr to ask for, for a given screen line ! 226: */ ! 227: cury = 0; ! 228: for (i = 0; i < ptab->nlines; i++) { ! 229: cp = &ptab->pdata[i].linepos; ! 230: cp->start = cury; ! 231: cp->clipstart = cury; ! 232: cp->clipend = cury + cp->size; ! 233: cury += cp->size; ! 234: } ! 235: ! 236: /* now move and repaint the window */ ! 237: if (change != 0) { ! 238: if (rc.top < rc.bottom) { ! 239: ScrollWindow(hwnd, 0, (int) -(change * ptab->rowheight), ! 240: &rc, NULL); ! 241: ! 242: } ! 243: ! 244: /* force repaint now, not just post message for later, ! 245: * since we want to repaint that line before the next ! 246: * scroll down occurs ! 247: */ ! 248: RedrawWindow(hwnd, &rcpaint, NULL, ! 249: RDW_ERASE | RDW_INVALIDATE|RDW_UPDATENOW); ! 250: } ! 251: } ! 252: ! 253: /*************************************************************************** ! 254: * Function: gtab_dohscroll ! 255: * ! 256: * Purpose: ! 257: * ! 258: * Set new horizontal scroll pos, ! 259: * set col win-relative start posns & clip left/right posns ! 260: * revise display. ! 261: */ ! 262: void ! 263: gtab_dohscroll(HWND hwnd, lpTable ptab, long change) ! 264: { ! 265: int curx, i; ! 266: int moveable; ! 267: lpCellPos cp; ! 268: int newdx, range; ! 269: ! 270: ! 271: /* check that the new scroll pos is still within the valid range */ ! 272: range = ptab->rowwidth - ptab->winwidth; ! 273: newdx = ptab->scroll_dx + (int) change; ! 274: if (range < 0) { ! 275: range = 0; ! 276: } ! 277: if (newdx > range) { ! 278: change = range - ptab->scroll_dx; ! 279: } else if (newdx < 0) { ! 280: change = -(ptab->scroll_dx); ! 281: } ! 282: ptab->scroll_dx += (int) change; ! 283: ! 284: SetScrollPos(hwnd, SB_HORZ, ptab->scroll_dx, TRUE); ! 285: InvalidateRect(hwnd, NULL, TRUE); ! 286: ! 287: /* loop through each col setting relative posn and clipping */ ! 288: /* clip off 1 pixel left and right (we added 2 on to size for this) */ ! 289: ! 290: /* first set up fixed columns */ ! 291: curx = 0; ! 292: for (i = 0; i < ptab->hdr.fixedcols; i++) { ! 293: cp = &ptab->pcellpos[i]; ! 294: cp->start = curx + 1; ! 295: cp->clipstart = cp->start; ! 296: cp->clipend = cp->start + cp->size - 2; ! 297: curx += cp->size; ! 298: } ! 299: ! 300: /* now moveable columns. remember start of moveable cols */ ! 301: moveable = curx; ! 302: curx = - ptab->scroll_dx; /* rel. pos of col */ ! 303: for (i = ptab->hdr.fixedcols; i < ptab->hdr.ncols; i++) { ! 304: cp = &ptab->pcellpos[i]; ! 305: cp->start = curx + moveable + 1; ! 306: cp->clipstart = max(moveable+1, cp->start); ! 307: cp->clipend = cp->start + cp->size - 2; ! 308: curx += cp->size; ! 309: } ! 310: } ! 311: ! 312: /*************************************************************************** ! 313: * Function: gtab_linetorow ! 314: * ! 315: * Purpose: ! 316: * ! 317: * Convert screen line nr to table row nr ! 318: */ ! 319: long ! 320: gtab_linetorow(HWND hwnd, lpTable ptab, int line) ! 321: { ! 322: if (line < ptab->hdr.fixedrows) { ! 323: return(line); ! 324: } ! 325: ! 326: return (line + ptab->toprow); ! 327: } ! 328: ! 329: /*************************************************************************** ! 330: * Function: gtab_rowtoline ! 331: * ! 332: * Purpose: ! 333: * ! 334: * Convert table row nr to screen line nr or -1 if not on screen ! 335: */ ! 336: int ! 337: gtab_rowtoline(HWND hwnd, lpTable ptab, long row) ! 338: { ! 339: if (row < ptab->hdr.fixedrows) { ! 340: return( (int) row); ! 341: } ! 342: ! 343: row -= ptab->toprow; ! 344: if ((row >= ptab->hdr.fixedrows) && (row < ptab->nlines)) { ! 345: return ( (int) row); ! 346: } ! 347: return(-1); ! 348: } ! 349: ! 350: /*************************************************************************** ! 351: * Function: gtab_select ! 352: * ! 353: * Purpose: ! 354: * ! 355: * Replace old selection with new. Notify owner if bNotify. Change ! 356: * display to reflect new display. ! 357: */ ! 358: void ! 359: gtab_select( ! 360: HWND hwnd, ! 361: lpTable ptab, ! 362: long row, ! 363: long col, ! 364: long nrows, ! 365: long ncells, ! 366: BOOL bNotify) ! 367: { ! 368: int line; ! 369: ! 370: /* if in ROW mode, force col and ncells to reflect the entire row. */ ! 371: if (ptab->hdr.selectmode & TM_ROW) { ! 372: col = 0; ! 373: ncells = ptab->hdr.ncols; ! 374: } ! 375: ! 376: /* clear existing sel if valid and visible */ ! 377: if ((ptab->select.nrows > 0) && (ptab->selvisible == TRUE)) { ! 378: ! 379: /* only clear sel if it is different from the new one */ ! 380: if ((ptab->select.startrow != row) || ! 381: (ptab->select.startcell != col) || ! 382: (ptab->select.nrows != nrows) || ! 383: (ptab->select.ncells != ncells)) { ! 384: line = gtab_rowtoline(hwnd, ptab, ! 385: ptab->select.startrow); ! 386: if (line >= 0) { ! 387: gtab_invertsel(hwnd, ptab, NULL); ! 388: } ! 389: ptab->selvisible = FALSE; ! 390: } ! 391: } ! 392: ! 393: /* set select fields and send TQ_SELECT */ ! 394: if (row < ptab->hdr.nrows) { ! 395: ptab->select.startrow = row; ! 396: ptab->select.startcell = col; ! 397: ptab->select.nrows = nrows; ! 398: ptab->select.ncells = ncells; ! 399: } else { ! 400: ptab->select.nrows = 0; ! 401: ptab->select.startrow = 0; ! 402: ptab->select.startcell = 0; ! 403: ptab->select.ncells = 0; ! 404: } ! 405: ! 406: if (bNotify) { ! 407: gtab_sendtq(hwnd, TQ_SELECT, (long) (LPSTR) &ptab->select); ! 408: } ! 409: ! 410: /* paint in selection */ ! 411: if (nrows > 0) { ! 412: if (!ptab->selvisible) { ! 413: gtab_invertsel(hwnd, ptab, NULL); ! 414: ptab->selvisible = TRUE; ! 415: } ! 416: } else { ! 417: if (ptab->selvisible) { ! 418: gtab_invertsel(hwnd, ptab, NULL); ! 419: ptab->selvisible = FALSE; ! 420: } ! 421: ptab->selvisible = FALSE; ! 422: } ! 423: } ! 424: ! 425: /*************************************************************************** ! 426: * Function: gtab_ytoline ! 427: * ! 428: * Purpose: ! 429: * ! 430: * Convert window y co-ord to a line nr ! 431: */ ! 432: int ! 433: gtab_ytoline(HWND hwnd, lpTable ptab, int y) ! 434: { ! 435: return(y / ptab->rowheight); ! 436: } ! 437: ! 438: /*************************************************************************** ! 439: * Function: gtab_xtocol ! 440: * ! 441: * Purpose: ! 442: * ! 443: * Convert window x co-ord to a cell nr ! 444: */ ! 445: int ! 446: gtab_xtocol(HWND hwnd, lpTable ptab, int x) ! 447: { ! 448: int i; ! 449: lpCellPos ppos; ! 450: ! 451: for (i = 0; i < ptab->hdr.ncols; i++) { ! 452: ppos = &ptab->pcellpos[i]; ! 453: if (ppos->clipstart < ppos->clipend) { ! 454: if ( (x >= ppos->clipstart) && (x < ppos->clipend)) { ! 455: return(i); ! 456: } ! 457: } ! 458: } ! 459: return(-1); ! 460: } ! 461: ! 462: ! 463: /*************************************************************************** ! 464: * Function: gtab_isborder ! 465: * ! 466: * Purpose: ! 467: * ! 468: * Check if x co-ord is 'near' (+- 2 pixels) the right border of given cell ! 469: */ ! 470: BOOL ! 471: gtab_isborder(HWND hwnd, lpTable ptab, int x, int col) ! 472: { ! 473: ! 474: if (abs(ptab->pcellpos[col].clipend - x) < 2) { ! 475: return(TRUE); ! 476: } else { ! 477: return(FALSE); ! 478: } ! 479: } ! 480: ! 481: ! 482: /*************************************************************************** ! 483: * Function: gtab_enter ! 484: * ! 485: * Purpose: ! 486: * ! 487: * Set selection and send 'TQ_ENTER' event to owner ! 488: */ ! 489: void ! 490: gtab_enter(HWND hwnd, lpTable ptab, long row, long col, long nrows, ! 491: long ncells) ! 492: { ! 493: int line; ! 494: ! 495: /* clear existing sel if valid and visible */ ! 496: if ((ptab->select.nrows > 0) && (ptab->selvisible == TRUE)) { ! 497: ! 498: /* only clear sel if it is different from the new one */ ! 499: if ((ptab->select.startrow != row) || ! 500: (ptab->select.startcell != col) || ! 501: (ptab->select.nrows != nrows) || ! 502: (ptab->select.ncells != ncells)) { ! 503: line = gtab_rowtoline(hwnd, ptab, ! 504: ptab->select.startrow); ! 505: if (line >= 0) { ! 506: gtab_invertsel(hwnd, ptab, NULL); ! 507: } ! 508: ptab->selvisible = FALSE; ! 509: } ! 510: } ! 511: ! 512: /* set select fields and send TQ_SELECT */ ! 513: if (row < ptab->hdr.nrows) { ! 514: ptab->select.startrow = row; ! 515: ptab->select.startcell = col; ! 516: ptab->select.nrows = nrows; ! 517: ptab->select.ncells = ncells; ! 518: } else { ! 519: ptab->select.nrows = 0; ! 520: ptab->select.startrow = 0; ! 521: ptab->select.startcell = 0; ! 522: ptab->select.ncells = 0; ! 523: } ! 524: ! 525: /* paint in selection */ ! 526: if (nrows > 0) { ! 527: if (!ptab->selvisible) { ! 528: gtab_invertsel(hwnd, ptab, NULL); ! 529: ptab->selvisible = TRUE; ! 530: } ! 531: /* do this at end because it could cause a layout-change */ ! 532: gtab_sendtq(hwnd, TQ_ENTER, (long) (LPSTR) &ptab->select); ! 533: } else { ! 534: if (ptab->selvisible) { ! 535: gtab_invertsel(hwnd, ptab, NULL); ! 536: } ! 537: ptab->selvisible = FALSE; ! 538: } ! 539: } ! 540: ! 541: ! 542: /*************************************************************************** ! 543: * Function: gtab_trackcol ! 544: * ! 545: * Purpose: ! 546: * ! 547: * Start re-sizing a column ! 548: */ ! 549: void ! 550: gtab_trackcol(HWND hwnd, lpTable ptab, int col, int x) ! 551: { ! 552: ! 553: /* ensure we see the mouse-up */ ! 554: SetCapture(hwnd); ! 555: ptab->trackmode = TRACK_COLUMN; ! 556: ptab->tracknr = col; ! 557: ptab->trackline1 = x; ! 558: ! 559: /* if line at other side of cell is visible, draw that too */ ! 560: if (ptab->pcellpos[col].start >= ptab->pcellpos[col].clipstart) { ! 561: ptab->trackline2 = ptab->pcellpos[col].start; ! 562: } else { ! 563: ptab->trackline2 = -1; ! 564: } ! 565: gtab_drawvertline(hwnd, ptab); ! 566: } ! 567: ! 568: ! 569: ! 570: /*************************************************************************** ! 571: * Function: gtab_press ! 572: * ! 573: * Purpose: ! 574: * ! 575: * Called on mouse-down events. decide what to start tracking. ! 576: */ ! 577: void ! 578: gtab_press(HWND hwnd, lpTable ptab, int x, int y) ! 579: { ! 580: int cell; ! 581: long row; ! 582: ! 583: if (ptab->trackmode != TRACK_NONE) { ! 584: return; ! 585: } ! 586: ! 587: /* has he grabbed a cell-edge to resize ? */ ! 588: cell = gtab_xtocol(hwnd, ptab, x); ! 589: if (cell == -1) { ! 590: return; ! 591: } ! 592: if (gtab_isborder(hwnd, ptab, x, cell)) { ! 593: gtab_trackcol(hwnd, ptab, cell, x); ! 594: return; ! 595: } ! 596: if ( (cell > 0) && gtab_isborder(hwnd, ptab, x, cell-1)) { ! 597: gtab_trackcol(hwnd, ptab, cell, x); ! 598: return; ! 599: } ! 600: ! 601: /* find which line he selected */ ! 602: row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y)); ! 603: ! 604: /* is he selecting a disabled fixed area ? */ ! 605: if ( (row < ptab->hdr.fixedrows) || (cell < ptab->hdr.fixedcols)) { ! 606: if (ptab->hdr.fixedselectable == FALSE) { ! 607: return; ! 608: } ! 609: } ! 610: ! 611: /* ok, start cell selection */ ! 612: ptab->trackmode = TRACK_CELL; ! 613: SetCapture(hwnd); ! 614: ! 615: /* record and paint new selection */ ! 616: if (ptab->hdr.selectmode & TM_ROW) { ! 617: gtab_select(hwnd, ptab, row, 0, 1, ptab->hdr.ncols, FALSE); ! 618: } else { ! 619: gtab_select(hwnd, ptab, row, cell, 1, 1, FALSE); ! 620: } ! 621: return; ! 622: } ! 623: ! 624: /*************************************************************************** ! 625: * Function: gtab_release ! 626: * ! 627: * Purpose: ! 628: * ! 629: * Called on mouse-up. complete any tracking that was happening ! 630: */ ! 631: void ! 632: gtab_release(HWND hwnd, lpTable ptab, int x, int y) ! 633: { ! 634: lpCellPos ppos; ! 635: lpProps pprop; ! 636: long row; ! 637: int cx; ! 638: ! 639: switch(ptab->trackmode) { ! 640: ! 641: case TRACK_NONE: ! 642: return; ! 643: ! 644: case TRACK_COLUMN: ! 645: /* erase marker lines */ ! 646: gtab_drawvertline(hwnd, ptab); ! 647: ReleaseCapture(); ! 648: ptab->trackmode = TRACK_NONE; ! 649: ! 650: /* adjust cell width */ ! 651: ppos = &ptab->pcellpos[ptab->tracknr]; ! 652: cx = ptab->trackline1 - ppos->start; ! 653: pprop = &ptab->pcolhdr[ptab->tracknr].props; ! 654: pprop->valid |= P_WIDTH; ! 655: pprop->width = cx; ! 656: gtab_calcwidths(hwnd, ptab); ! 657: gtab_setsize(hwnd, ptab); ! 658: InvalidateRect(hwnd, NULL, TRUE); ! 659: return; ! 660: ! 661: case TRACK_CELL: ! 662: row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y)); ! 663: ReleaseCapture(); ! 664: ptab->trackmode = TRACK_NONE; ! 665: ! 666: /* keep the same selection. if the mouse is still ! 667: * in the box, select it, otherwise de-select it ! 668: */ ! 669: if ((row == ptab->select.startrow) && ! 670: ( (ptab->hdr.selectmode & TM_ROW) || ! 671: (ptab->select.startcell == gtab_xtocol(hwnd, ptab, x))) ) { ! 672: ! 673: gtab_select(hwnd, ptab, ptab->select.startrow, ! 674: ptab->select.startcell, ! 675: ptab->select.nrows, ptab->select.ncells, TRUE); ! 676: } else { ! 677: gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); ! 678: } ! 679: return; ! 680: } ! 681: } ! 682: ! 683: ! 684: /*************************************************************************** ! 685: * Function: gtab_move ! 686: * ! 687: * Purpose: ! 688: * ! 689: * Called on mouse-move. if tracking - adjust position, if not, ! 690: * set correct cursor ! 691: */ ! 692: void ! 693: gtab_move(HWND hwnd, lpTable ptab, int x, int y) ! 694: { ! 695: BOOL fOK; ! 696: long row; ! 697: int col; ! 698: lpCellPos ppos; ! 699: ! 700: switch(ptab->trackmode) { ! 701: ! 702: case TRACK_NONE: ! 703: col = gtab_xtocol(hwnd, ptab, x); ! 704: if (col == -1) { ! 705: SetCursor(hNormCurs); ! 706: return; ! 707: } ! 708: if (gtab_isborder(hwnd, ptab, x, col)) { ! 709: SetCursor(hVertCurs); ! 710: return; ! 711: } ! 712: if ( (col > 0) && gtab_isborder(hwnd, ptab, x, col-1)) { ! 713: SetCursor(hVertCurs); ! 714: return; ! 715: } ! 716: SetCursor(hNormCurs); ! 717: return; ! 718: ! 719: case TRACK_CELL: ! 720: row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y)); ! 721: ! 722: /* keep the same selection. if the mouse is still ! 723: * in the box, select it, otherwise de-select it ! 724: */ ! 725: if ((row == ptab->select.startrow) && ! 726: ( (ptab->hdr.selectmode & TM_ROW) || ! 727: (ptab->select.startcell == gtab_xtocol(hwnd, ptab, x))) ) { ! 728: ! 729: if (!ptab->selvisible) { ! 730: gtab_invertsel(hwnd, ptab, NULL); ! 731: ptab->selvisible = TRUE; ! 732: } ! 733: } else { ! 734: if (ptab->selvisible) { ! 735: gtab_invertsel(hwnd, ptab, NULL); ! 736: ptab->selvisible = FALSE; ! 737: } ! 738: } ! 739: return; ! 740: ! 741: case TRACK_COLUMN: ! 742: /* check that new x is still visible/valid */ ! 743: ppos = &ptab->pcellpos[ptab->tracknr]; ! 744: fOK = FALSE; ! 745: ! 746: if (ptab->tracknr < ptab->hdr.fixedcols) { ! 747: if ((x > ppos->start) && (x < ptab->winwidth)) { ! 748: fOK = TRUE; ! 749: } ! 750: } else { ! 751: if ((x > ppos->clipstart) && (x < ptab->winwidth)) { ! 752: fOK = TRUE; ! 753: } ! 754: } ! 755: if (fOK == TRUE) { ! 756: gtab_drawvertline(hwnd, ptab); ! 757: ptab->trackline1 = x; ! 758: gtab_drawvertline(hwnd, ptab); ! 759: } ! 760: return; ! 761: } ! 762: } ! 763: ! 764: /*************************************************************************** ! 765: * Function: gtab_dblclick ! 766: * ! 767: * Purpose: ! 768: * ! 769: * dbl-click - send an TQ_ENTER event to the owner (if valid) ! 770: */ ! 771: void ! 772: gtab_dblclick(HWND hwnd, lpTable ptab, int x, int y) ! 773: { ! 774: int cell, line; ! 775: long row; ! 776: ! 777: line = gtab_ytoline(hwnd, ptab, y); ! 778: cell = gtab_xtocol(hwnd, ptab, x); ! 779: if ( (line < ptab->hdr.fixedrows) || (cell < ptab->hdr.fixedcols) ) { ! 780: if (!ptab->hdr.fixedselectable) { ! 781: return; ! 782: } ! 783: } ! 784: row = gtab_linetorow(hwnd, ptab, line); ! 785: ! 786: if (ptab->hdr.selectmode & TM_ROW) { ! 787: gtab_enter(hwnd, ptab, row, 0, 1, ptab->hdr.ncols); ! 788: } else { ! 789: gtab_enter(hwnd, ptab, row, cell, 1, 1); ! 790: } ! 791: } ! 792: ! 793: /*************************************************************************** ! 794: * Function: gtab_showsel ! 795: * ! 796: * Purpose: ! 797: * ! 798: * Move selection area to visible part of window. Argument bToBottom ! 799: * indicates whether to move the line onto the bottom or the top of the ! 800: * window if not visible - this affects the smoothness of scrolling ! 801: * line-by-line. ! 802: */ ! 803: void ! 804: gtab_showsel(HWND hwnd, lpTable ptab, BOOL bToBottom) ! 805: { ! 806: int line; ! 807: long change; ! 808: ! 809: line = gtab_rowtoline(hwnd, ptab, ptab->select.startrow); ! 810: ! 811: /* move up if last line or not at all visible */ ! 812: if ( (line < 0) || line == (ptab->nlines - 1)) { ! 813: change = ptab->select.startrow - ptab->toprow; ! 814: if (bToBottom) { ! 815: /* change to bottom of window. subtract 2 not 1 ! 816: * since nlines includes one line that is only ! 817: * partly visible ! 818: */ ! 819: change -= (ptab->nlines - 2); ! 820: } ! 821: change -= ptab->hdr.fixedrows; ! 822: gtab_dovscroll(hwnd, ptab, change); ! 823: } ! 824: /* add support for TM_CELL here! */ ! 825: } ! 826: ! 827: /*************************************************************************** ! 828: * Function: gtab_showsel_middle ! 829: * ! 830: * Purpose: ! 831: * ! 832: * Scroll the window so that if possible, the selected row is in the ! 833: * middle 60% of the screen so that context around it is visible. ! 834: */ ! 835: void ! 836: gtab_showsel_middle(HWND hwnd, lpTable ptab) ! 837: { ! 838: int line; ! 839: long change; ! 840: int mid_top, mid_end; ! 841: ! 842: line = gtab_rowtoline(hwnd, ptab, ptab->select.startrow); ! 843: ! 844: ! 845: /* is this within the middle 60 % ? */ ! 846: mid_top = ptab->nlines * 20 / 100; ! 847: mid_end = ptab->nlines * 80 / 100; ! 848: if ((line < mid_top) || (line > mid_end)) { ! 849: ! 850: /* no - scroll so that selected line is at ! 851: * the 20% mark ! 852: */ ! 853: change = (ptab->select.startrow - mid_top) - ptab->toprow; ! 854: change -= ptab->hdr.fixedrows; ! 855: gtab_dovscroll(hwnd, ptab, change); ! 856: } ! 857: /* again - need code here for TM_CELL mode to ensure that ! 858: * active cell is horizontally scrolled correctly ! 859: */ ! 860: } ! 861: ! 862: ! 863: ! 864: /*************************************************************************** ! 865: * Function: gtab_changesel ! 866: * ! 867: * Purpose: ! 868: * ! 869: * Move the selection a specified nr of rows or cells ! 870: * if no selection, select first visible unit ! 871: */ ! 872: VOID ! 873: gtab_changesel(HWND hwnd, lpTable ptab, long rowincr, int cellincr, BOOL bToBottom) ! 874: { ! 875: long row, col, nrows, ncols; ! 876: ! 877: /* is there a selection ? */ ! 878: if (ptab->select.nrows < 1) { ! 879: ! 880: /* no selection - force a selection ! 881: * at the first visible unit ! 882: */ ! 883: if (ptab->hdr.fixedselectable) { ! 884: row = 0; ! 885: col = 0; ! 886: } else { ! 887: row = gtab_linetorow(hwnd, ptab, ptab->hdr.fixedrows); ! 888: /* should really check for first visible cell */ ! 889: col = ptab->hdr.fixedcols; ! 890: } ! 891: nrows = 1; ! 892: ncols = 1; ! 893: if (ptab->hdr.selectmode & TM_ROW) { ! 894: col = 0; ! 895: ncols = ptab->hdr.ncols; ! 896: } ! 897: } else { ! 898: row = ptab->select.startrow + rowincr; ! 899: col = ptab->select.startcell + cellincr; ! 900: while (col >= ptab->hdr.ncols) { ! 901: col -= ptab->hdr.ncols; ! 902: row++; ! 903: } ! 904: while (col < 0) { ! 905: col += ptab->hdr.ncols; ! 906: row--; ! 907: } ! 908: if (row < 0) { ! 909: row = 0; ! 910: } ! 911: if (row >= ptab->hdr.nrows) { ! 912: row = ptab->hdr.nrows-1; ! 913: } ! 914: /* check we haven't moved into non-selectable region */ ! 915: if ((row < ptab->hdr.fixedrows) && ! 916: (!ptab->hdr.fixedselectable)) { ! 917: row = ptab->hdr.fixedrows; ! 918: } ! 919: nrows = ptab->select.nrows; ! 920: ncols = ptab->select.ncells; ! 921: } ! 922: gtab_select(hwnd, ptab, row, col, nrows, ncols, TRUE); ! 923: /* ensure selection visible */ ! 924: gtab_showsel(hwnd, ptab, bToBottom); ! 925: } ! 926: ! 927: /*************************************************************************** ! 928: * Function: gtab_selhome ! 929: * ! 930: * Purpose: ! 931: * ! 932: * Set the topmost selectable unit in window as the selection ! 933: */ ! 934: void ! 935: gtab_selhome(HWND hwnd, lpTable ptab) ! 936: { ! 937: long row; ! 938: ! 939: if (ptab->hdr.fixedselectable) { ! 940: row = gtab_linetorow(hwnd, ptab, 0); ! 941: if (ptab->hdr.selectmode & TM_ROW) { ! 942: gtab_select(hwnd, ptab, row, 0, 1, ! 943: ptab->hdr.ncols, TRUE); ! 944: } else { ! 945: gtab_select(hwnd, ptab, row, 0, 1, 1, TRUE); ! 946: } ! 947: } else { ! 948: row = gtab_linetorow(hwnd, ptab, ptab->hdr.fixedrows); ! 949: if (ptab->hdr.selectmode & TM_ROW) { ! 950: gtab_select(hwnd, ptab, row, 0, 1, ! 951: ptab->hdr.ncols, TRUE); ! 952: } else { ! 953: gtab_select(hwnd, ptab, row, ! 954: ptab->hdr.fixedcols, 1, 1, TRUE); ! 955: } ! 956: } ! 957: } ! 958: ! 959: ! 960: /*************************************************************************** ! 961: * Function: gtab_key ! 962: * ! 963: * Purpose: ! 964: * ! 965: * Handle key-down events - scroll windows and/or move selection ! 966: */ ! 967: int ! 968: gtab_key(HWND hwnd, lpTable ptab, int vkey) ! 969: { ! 970: long row; ! 971: BOOL bControl = FALSE; ! 972: ! 973: if (GetKeyState(VK_CONTROL) & 0x8000) { ! 974: bControl = TRUE; ! 975: } ! 976: ! 977: switch(vkey) { ! 978: ! 979: case VK_UP: ! 980: if (bControl) { ! 981: /* control-uparrow scrolls window without selection. ! 982: * the selection is de-selected (to avoid surprises ! 983: * moving back to it). ! 984: */ ! 985: gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); ! 986: gtab_dovscroll(hwnd, ptab, -1); ! 987: } else { ! 988: /* uparrow moves selection up one line */ ! 989: gtab_changesel(hwnd, ptab, -1, 0, FALSE); ! 990: } ! 991: return(0); ! 992: ! 993: case VK_DOWN: ! 994: if (bControl) { ! 995: /* control downarrow scrolls window without ! 996: * a selection. ! 997: */ ! 998: gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); ! 999: gtab_dovscroll(hwnd, ptab, 1); ! 1000: } else { ! 1001: /* the normal gtab_changesel behaviour is ! 1002: * that if the selected line is not visible now, ! 1003: * we scroll it to the top of the window. This is fine ! 1004: * in most cases but causes unacceptable jumps when ! 1005: * repeatedly scrolling down with the down key. ! 1006: * ! 1007: * Thus we now have an argument to changesel to say ! 1008: * that in this case, if you need to move the line onto ! 1009: * the window, move it to the bottom and not the top ! 1010: */ ! 1011: gtab_changesel(hwnd, ptab, 1, 0, TRUE); ! 1012: } ! 1013: return(0); ! 1014: ! 1015: case VK_LEFT: ! 1016: /* if cell-selection mode, move left one cell. ! 1017: * otherwise the whole row is selected - scroll ! 1018: * the line left a little ! 1019: */ ! 1020: ! 1021: if (ptab->hdr.selectmode & TM_ROW) { ! 1022: if (bControl) { ! 1023: /* ctrl-left moves to start of line */ ! 1024: gtab_dohscroll(hwnd, ptab, -(ptab->scroll_dx)); ! 1025: } else { ! 1026: gtab_dohscroll(hwnd, ptab, -(ptab->avewidth)); ! 1027: } ! 1028: } else { ! 1029: gtab_changesel(hwnd, ptab, 0, -1, FALSE); ! 1030: } ! 1031: return(0); ! 1032: ! 1033: case VK_RIGHT: ! 1034: /* if cell-selection mode, move right one cell. ! 1035: * otherwise the whole row is selected - scroll ! 1036: * the line right a little ! 1037: */ ! 1038: if (ptab->hdr.selectmode & TM_ROW) { ! 1039: if (bControl) { ! 1040: /* control-right moves to right end of line */ ! 1041: gtab_dohscroll(hwnd, ptab, ptab->rowwidth - ! 1042: ptab->winwidth); ! 1043: } else { ! 1044: gtab_dohscroll(hwnd, ptab, ptab->avewidth); ! 1045: } ! 1046: } else { ! 1047: gtab_changesel(hwnd, ptab, 0, 1, TRUE); ! 1048: } ! 1049: return(0); ! 1050: ! 1051: case VK_HOME: ! 1052: if (bControl) { ! 1053: /* control-home == top of file */ ! 1054: gtab_dovscroll(hwnd, ptab, -(ptab->toprow)); ! 1055: } ! 1056: /* top of window */ ! 1057: gtab_selhome(hwnd, ptab); ! 1058: gtab_showsel(hwnd, ptab, FALSE); ! 1059: ! 1060: return(0); ! 1061: ! 1062: case VK_END: ! 1063: if (bControl) { ! 1064: /* control-end -> end of file */ ! 1065: row = ptab->hdr.nrows-1; ! 1066: } else { ! 1067: row = gtab_linetorow(hwnd, ptab, ptab->nlines - 1); ! 1068: if (row >= ptab->hdr.nrows) { ! 1069: row = ptab->hdr.nrows-1; ! 1070: } ! 1071: } ! 1072: if (ptab->hdr.selectmode & TM_ROW) { ! 1073: gtab_select(hwnd, ptab, row, 0, 1, ! 1074: ptab->hdr.ncols, TRUE); ! 1075: } else { ! 1076: gtab_select(hwnd, ptab, row, ! 1077: ptab->hdr.ncols-1, 1, 1, TRUE); ! 1078: } ! 1079: /* we have selected the bottom line. We don't want to ! 1080: * move it up into the window, since the intended ! 1081: * effect is to select the lowest line. This doesn't ! 1082: * apply to the ctrl-end behaviour (move to bottom of ! 1083: * buffer. ! 1084: */ ! 1085: if (bControl) { ! 1086: /* move the selection to make it visible - but move it ! 1087: * to the bottom and not to the top of the window ! 1088: */ ! 1089: gtab_showsel(hwnd, ptab, TRUE); ! 1090: } ! 1091: return(0); ! 1092: ! 1093: case VK_RETURN: ! 1094: if (ptab->select.nrows > 0) { ! 1095: gtab_showsel(hwnd, ptab, FALSE); ! 1096: gtab_enter(hwnd, ptab, ptab->select.startrow, ! 1097: ptab->select.startcell, ! 1098: ptab->select.nrows, ptab->select.ncells); ! 1099: } ! 1100: return(0); ! 1101: ! 1102: case VK_SPACE: ! 1103: /* toggle the selection */ ! 1104: if (ptab->select.nrows < 1) { ! 1105: /* no selection - make one */ ! 1106: gtab_changesel(hwnd, ptab, 0, 0, TRUE); ! 1107: } else { ! 1108: /* there is a selection - deselect it */ ! 1109: gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); ! 1110: } ! 1111: return(0); ! 1112: ! 1113: case VK_PRIOR: /* page up */ ! 1114: ! 1115: gtab_dovscroll(hwnd, ptab, -(ptab->nlines - 3)); ! 1116: gtab_selhome(hwnd, ptab); ! 1117: return(0); ! 1118: ! 1119: case VK_NEXT: /* page down */ ! 1120: ! 1121: /* scroll down one page */ ! 1122: gtab_dovscroll(hwnd, ptab, (ptab->nlines - 3)); ! 1123: ! 1124: /* select new bottom line */ ! 1125: row = gtab_linetorow(hwnd, ptab, ptab->nlines - 1); ! 1126: if (row >= ptab->hdr.nrows) { ! 1127: row = ptab->hdr.nrows-1; ! 1128: } ! 1129: /* select bottom line, but don't call showsel ! 1130: * since we don't want to adjust it's position - we ! 1131: * want it to remain at the bottom of the window ! 1132: */ ! 1133: if (ptab->hdr.selectmode & TM_ROW) { ! 1134: gtab_select(hwnd, ptab, row, 0, 1, ! 1135: ptab->hdr.ncols, TRUE); ! 1136: } else { ! 1137: gtab_select(hwnd, ptab, row, ! 1138: ptab->hdr.ncols-1, 1, 1, TRUE); ! 1139: } ! 1140: ! 1141: return(0); ! 1142: ! 1143: default: ! 1144: return(1); ! 1145: } ! 1146: } ! 1147:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.