00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <unistd.h>
00047
00048
00049 #include <assert.h>
00050 #include <string.h>
00051 #include <ctype.h>
00052
00053 #include "TEScreen.h"
00054
00055 #define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
00056
00057
00058
00059 #define BS_CLEARS FALSE
00060
00061 #define loc(X,Y) ((Y)*columns+(X))
00062
00066 TEScreen::TEScreen(int lines, int columns)
00067 {
00068 this->lines = lines;
00069 this->columns = columns;
00070
00071 image = (ca*) malloc(lines*columns*sizeof(ca));
00072 tabstops = NULL; initTabStops();
00073
00074 histCursor = 0;
00075
00076 clearSelection();
00077 reset();
00078 }
00079
00083 TEScreen::~TEScreen()
00084 {
00085 free(image);
00086 if (tabstops) free(tabstops);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00113 void TEScreen::cursorUp(int n)
00114
00115 {
00116 if (n == 0) n = 1;
00117 int stop = cuY < tmargin ? 0 : tmargin;
00118 cuX = QMIN(columns-1,cuX);
00119 cuY = QMAX(stop,cuY-n);
00120 }
00121
00128 void TEScreen::cursorDown(int n)
00129
00130 {
00131 if (n == 0) n = 1;
00132 int stop = cuY > bmargin ? lines-1 : bmargin;
00133 cuX = QMIN(columns-1,cuX);
00134 cuY = QMIN(stop,cuY+n);
00135 }
00136
00143 void TEScreen::cursorLeft(int n)
00144
00145 {
00146 if (n == 0) n = 1;
00147 cuX = QMIN(columns-1,cuX);
00148 cuX = QMAX(0,cuX-n);
00149 }
00150
00157 void TEScreen::cursorRight(int n)
00158
00159 {
00160 if (n == 0) n = 1;
00161 cuX = QMIN(columns-1,cuX+n);
00162 }
00163
00168 void TEScreen::setMargins(int top, int bot)
00169
00170 {
00171 if (top == 0) top = 1;
00172 if (bot == 0) bot = lines;
00173 top = top - 1;
00174 bot = bot - 1;
00175 if ( !( 0 <= top && top < bot && bot < lines ) )
00176 { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
00177 __FILE__,__LINE__,top,bot);
00178 return;
00179 }
00180 tmargin = top;
00181 bmargin = bot;
00182 cuX = 0;
00183 cuY = getMode(MODE_Origin) ? top : 0;
00184 }
00185
00193 void TEScreen::index()
00194
00195 {
00196 if (cuY == bmargin)
00197 {
00198 if (tmargin == 0 && bmargin == lines-1) addHistLine();
00199 scrollUp(tmargin,1);
00200 }
00201 else if (cuY < lines-1)
00202 cuY += 1;
00203 }
00204
00212 void TEScreen::reverseIndex()
00213
00214 {
00215 if (cuY == tmargin)
00216 scrollDown(tmargin,1);
00217 else if (cuY > 0)
00218 cuY -= 1;
00219 }
00220
00228 void TEScreen::NextLine()
00229
00230 {
00231 Return(); index();
00232 }
00233
00234
00235
00244 void TEScreen::eraseChars(int n)
00245 {
00246 if (n == 0) n = 1;
00247 int p = QMAX(0,QMIN(cuX+n-1,columns-1));
00248 clearImage(loc(cuX,cuY),loc(p,cuY),' ');
00249 }
00250
00256 void TEScreen::deleteChars(int n)
00257 {
00258 if (n == 0) n = 1;
00259 int p = QMAX(0,QMIN(cuX+n,columns-1));
00260 moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
00261 clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
00262 }
00263
00269 void TEScreen::insertChars(int n)
00270 {
00271 if (n == 0) n = 1;
00272 int p = QMAX(0,QMIN(columns-1-n,columns-1));
00273 int q = QMAX(0,QMIN(cuX+n,columns-1));
00274 moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
00275 clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
00276 }
00277
00283 void TEScreen::deleteLines(int n)
00284 {
00285 if (n == 0) n = 1;
00286 scrollUp(cuY,n);
00287 }
00288
00294 void TEScreen::insertLines(int n)
00295 {
00296 if (n == 0) n = 1;
00297 scrollDown(cuY,n);
00298 }
00299
00300
00301
00304 void TEScreen::setMode(int m)
00305 {
00306 currParm.mode[m] = TRUE;
00307 switch(m)
00308 {
00309 case MODE_Origin : cuX = 0; cuY = tmargin; break;
00310 }
00311 }
00312
00315 void TEScreen::resetMode(int m)
00316 {
00317 currParm.mode[m] = FALSE;
00318 switch(m)
00319 {
00320 case MODE_Origin : cuX = 0; cuY = 0; break;
00321 }
00322 }
00323
00326 void TEScreen::saveMode(int m)
00327 {
00328 saveParm.mode[m] = currParm.mode[m];
00329 }
00330
00333 void TEScreen::restoreMode(int m)
00334 {
00335 currParm.mode[m] = saveParm.mode[m];
00336 }
00337
00338
00340 BOOL TEScreen::getMode(int m)
00341 {
00342 return currParm.mode[m];
00343 }
00344
00347 void TEScreen::saveCursor()
00348 {
00349 sa_cuX = cuX;
00350 sa_cuY = cuY;
00351 sa_cu_re = cu_re;
00352 sa_cu_fg = cu_fg;
00353 sa_cu_bg = cu_bg;
00354 }
00355
00358 void TEScreen::restoreCursor()
00359 {
00360 cuX = QMIN(sa_cuX,columns-1);
00361 cuY = QMIN(sa_cuY,lines-1);
00362 cu_re = sa_cu_re;
00363 cu_fg = sa_cu_fg;
00364 cu_bg = sa_cu_bg;
00365 effectiveRendition();
00366 }
00367
00368
00369
00370
00371
00372
00373
00384 void TEScreen::resizeImage(int new_lines, int new_columns)
00385 {
00386
00387 if (cuY > new_lines-1)
00388 {
00389 bmargin = lines-1;
00390 for (int i = 0; i < cuY-(new_lines-1); i++)
00391 {
00392 addHistLine(); scrollUp(0,1);
00393 }
00394 }
00395
00396
00397 ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
00398
00399 clearSelection();
00400
00401
00402 for (int y = 0; y < new_lines; y++)
00403 for (int x = 0; x < new_columns; x++)
00404 {
00405 newimg[y*new_columns+x].c = ' ';
00406 newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
00407 newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
00408 newimg[y*new_columns+x].r = DEFAULT_RENDITION;
00409 }
00410 int cpy_lines = QMIN(new_lines, lines);
00411 int cpy_columns = QMIN(new_columns,columns);
00412
00413 for (int y = 0; y < cpy_lines; y++)
00414 for (int x = 0; x < cpy_columns; x++)
00415 {
00416 newimg[y*new_columns+x].c = image[loc(x,y)].c;
00417 newimg[y*new_columns+x].f = image[loc(x,y)].f;
00418 newimg[y*new_columns+x].b = image[loc(x,y)].b;
00419 newimg[y*new_columns+x].r = image[loc(x,y)].r;
00420 }
00421 free(image);
00422 image = newimg;
00423 lines = new_lines;
00424 columns = new_columns;
00425 cuX = QMIN(cuX,columns-1);
00426 cuY = QMIN(cuY,lines-1);
00427
00428
00429 tmargin=0;
00430 bmargin=lines-1;
00431 initTabStops();
00432 clearSelection();
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 void TEScreen::reverseRendition(ca* p)
00470 { UINT8 f = p->f; UINT8 b = p->b;
00471 p->f = b; p->b = f;
00472 }
00473
00474 void TEScreen::effectiveRendition()
00475
00476 {
00477 ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
00478 if (cu_re & RE_REVERSE)
00479 {
00480 ef_fg = cu_bg;
00481 ef_bg = cu_fg;
00482 }
00483 else
00484 {
00485 ef_fg = cu_fg;
00486 ef_bg = cu_bg;
00487 }
00488 if (cu_re & RE_BOLD)
00489 {
00490 if (ef_fg < BASE_COLORS)
00491 ef_fg += BASE_COLORS;
00492 else
00493 ef_fg -= BASE_COLORS;
00494 }
00495 }
00496
00507 ca* TEScreen::getCookedImage()
00508 { int x,y;
00509 ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
00510 ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
00511
00512 for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
00513 {
00514 int len = QMIN(columns,hist.getLineLen(y+histCursor));
00515 int yp = y*columns;
00516 int yq = (y+histCursor)*columns;
00517
00518 hist.getCells(y+histCursor,0,len,merged+yp);
00519 for (x = len; x < columns; x++) merged[yp+x] = dft;
00520 for (x = 0; x < columns; x++)
00521 { int p=x + yp; int q=x + yq;
00522 if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
00523 reverseRendition(&merged[p]);
00524 }
00525 }
00526 if (lines >= hist.getLines()-histCursor)
00527 {
00528 for (y = (hist.getLines()-histCursor); y < lines ; y++)
00529 {
00530 int yp = y*columns;
00531 int yq = (y+histCursor)*columns;
00532 int yr = (y-hist.getLines()+histCursor)*columns;
00533 for (x = 0; x < columns; x++)
00534 { int p = x + yp; int q = x + yq; int r = x + yr;
00535 merged[p] = image[r];
00536 if ( q >= sel_TL && q <= sel_BR )
00537 reverseRendition(&merged[p]);
00538 }
00539
00540 }
00541 }
00542
00543 if (getMode(MODE_Screen))
00544 { int i,n = lines*columns;
00545 for (i = 0; i < n; i++)
00546 reverseRendition(&merged[i]);
00547 }
00548 if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines))
00549 reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
00550 return merged;
00551 }
00552
00553
00557 void TEScreen::reset()
00558 {
00559 setMode(MODE_Wrap ); saveMode(MODE_Wrap );
00560 resetMode(MODE_Origin); saveMode(MODE_Origin);
00561 resetMode(MODE_Insert); saveMode(MODE_Insert);
00562 setMode(MODE_Cursor);
00563 resetMode(MODE_Screen);
00564 resetMode(MODE_NewLine);
00565
00566 tmargin=0;
00567 bmargin=lines-1;
00568
00569 setDefaultRendition();
00570 saveCursor();
00571
00572 clear();
00573 }
00574
00578 void TEScreen::clear()
00579 {
00580 clearEntireScreen();
00581 home();
00582 }
00583
00587 void TEScreen::BackSpace()
00588 {
00589 cuX = QMAX(0,cuX-1);
00590 if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
00591 }
00592
00596 void TEScreen::Tabulate()
00597 {
00598
00599 cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
00600 }
00601
00602 void TEScreen::clearTabStops()
00603 {
00604 for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
00605 }
00606
00607 void TEScreen::changeTabStop(bool set)
00608 {
00609 if (cuX >= columns) return;
00610 tabstops[cuX] = set;
00611 }
00612
00613 void TEScreen::initTabStops()
00614 {
00615 if (tabstops) free(tabstops);
00616 tabstops = (bool*)malloc(columns*sizeof(bool));
00617
00618
00619
00620 for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
00621 }
00622
00629 void TEScreen::NewLine()
00630 {
00631 if (getMode(MODE_NewLine)) Return();
00632 index();
00633 }
00634
00641 void TEScreen::checkSelection(int from, int to)
00642 {
00643 if (sel_begin == -1) return;
00644 int scr_TL = loc(0, hist.getLines());
00645
00646 if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
00647 {
00648 clearSelection();
00649 }
00650 }
00651
00652 void TEScreen::ShowCharacter(unsigned short c)
00653 {
00654
00655
00656
00657
00658
00659 if (cuX >= columns)
00660 {
00661 if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
00662 }
00663
00664 if (getMode(MODE_Insert)) insertChars(1);
00665
00666 int i = loc(cuX,cuY);
00667
00668 checkSelection(i, i);
00669
00670 image[i].c = c;
00671 image[i].f = ef_fg;
00672 image[i].b = ef_bg;
00673 image[i].r = ef_re;
00674
00675 cuX += 1;
00676 }
00677
00678
00679
00680
00686 void TEScreen::scrollUp(int from, int n)
00687 {
00688 if (n <= 0 || from + n > bmargin) return;
00689
00690 moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
00691 clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
00692 }
00693
00699 void TEScreen::scrollDown(int from, int n)
00700 {
00701
00702 if (n <= 0) return;
00703 if (from > bmargin) return;
00704 if (from + n > bmargin) n = bmargin - from;
00705 moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
00706 clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
00707 }
00708
00710 void TEScreen::setCursorYX(int y, int x)
00711 {
00712 setCursorY(y); setCursorX(x);
00713 }
00714
00717 void TEScreen::setCursorX(int x)
00718 {
00719 if (x == 0) x = 1;
00720 x -= 1;
00721 cuX = QMAX(0,QMIN(columns-1, x));
00722 }
00723
00726 void TEScreen::setCursorY(int y)
00727 {
00728 if (y == 0) y = 1;
00729 y -= 1;
00730 cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
00731 }
00732
00736 void TEScreen::home()
00737 {
00738 cuX = 0;
00739 cuY = 0;
00740 }
00741
00745 void TEScreen::Return()
00746 {
00747 cuX = 0;
00748 }
00749
00753 int TEScreen::getCursorX()
00754 {
00755 return cuX;
00756 }
00757
00761 int TEScreen::getCursorY()
00762 {
00763 return cuY;
00764 }
00765
00766
00767
00784 void TEScreen::clearImage(int loca, int loce, char c)
00785 { int i;
00786 int scr_TL=loc(0,hist.getLines());
00787
00788
00789
00790 if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
00791 {
00792 clearSelection();
00793 }
00794 for (i = loca; i <= loce; i++)
00795 {
00796 image[i].c = c;
00797 image[i].f = ef_fg;
00798 image[i].b = ef_bg;
00799 image[i].r = ef_re;
00800 }
00801 }
00802
00810 void TEScreen::moveImage(int dst, int loca, int loce)
00811 {
00812
00813 if (loce < loca) {
00814
00815 return;
00816 }
00817 memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
00818 }
00819
00823 void TEScreen::clearToEndOfScreen()
00824 {
00825 clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
00826 }
00827
00831 void TEScreen::clearToBeginOfScreen()
00832 {
00833 clearImage(loc(0,0),loc(cuX,cuY),' ');
00834 }
00835
00839 void TEScreen::clearEntireScreen()
00840 {
00841 clearImage(loc(0,0),loc(columns-1,lines-1),' ');
00842 }
00843
00848 void TEScreen::helpAlign()
00849 {
00850 clearImage(loc(0,0),loc(columns-1,lines-1),'E');
00851 }
00852
00856 void TEScreen::clearToEndOfLine()
00857 {
00858 clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
00859 }
00860
00864 void TEScreen::clearToBeginOfLine()
00865 {
00866 clearImage(loc(0,cuY),loc(cuX,cuY),' ');
00867 }
00868
00872 void TEScreen::clearEntireLine()
00873 {
00874 clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
00875 }
00876
00877
00878
00883 void TEScreen::setRendition(int re)
00884 {
00885 cu_re |= re;
00886 effectiveRendition();
00887 }
00888
00893 void TEScreen::resetRendition(int re)
00894 {
00895 cu_re &= ~re;
00896 effectiveRendition();
00897 }
00898
00902 void TEScreen::setDefaultRendition()
00903 {
00904 setForeColorToDefault();
00905 setBackColorToDefault();
00906 cu_re = DEFAULT_RENDITION;
00907 effectiveRendition();
00908 }
00909
00913 void TEScreen::setForeColor(int fgcolor)
00914 {
00915 cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
00916 effectiveRendition();
00917 }
00918
00922 void TEScreen::setBackColor(int bgcolor)
00923 {
00924 cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
00925 effectiveRendition();
00926 }
00927
00931 void TEScreen::setBackColorToDefault()
00932 {
00933 cu_bg = DEFAULT_BACK_COLOR;
00934 effectiveRendition();
00935 }
00936
00940 void TEScreen::setForeColorToDefault()
00941 {
00942 cu_fg = DEFAULT_FORE_COLOR;
00943 effectiveRendition();
00944 }
00945
00946
00947
00948
00949
00950
00951
00952 void TEScreen::clearSelection()
00953 {
00954 sel_BR = -1;
00955 sel_TL = -1;
00956 sel_begin = -1;
00957 }
00958
00959 void TEScreen::setSelBeginXY(const int x, const int y)
00960 {
00961 sel_begin = loc(x,y+histCursor) ;
00962 sel_BR = sel_begin;
00963 sel_TL = sel_begin;
00964 }
00965
00966 void TEScreen::setSelExtentXY(const int x, const int y)
00967 {
00968 if (sel_begin == -1) return;
00969 int l = loc(x,y + histCursor);
00970
00971 if (l < sel_begin)
00972 {
00973 sel_TL = l;
00974 sel_BR = sel_begin;
00975 }
00976 else
00977 {
00978
00979 if (( x == columns )|| (x == 0)) l--;
00980
00981 sel_TL = sel_begin;
00982 sel_BR = l;
00983 }
00984 }
00985
00986 QString TEScreen::getSelText(const BOOL preserve_line_breaks)
00987 {
00988 if (sel_begin == -1)
00989 return QString::null;
00990
00991 int *m;
00992 int s, d;
00993 int hist_BR = loc(0, hist.getLines());
00994 int hY = sel_TL / columns;
00995 int hX = sel_TL % columns;
00996 int eol;
00997
00998 s = sel_TL;
00999
01000
01001
01002 d = (sel_BR - sel_TL) / columns + 1;
01003 m = new int[d * (columns + 1) + 2];
01004 d = 0;
01005
01006 while (s <= sel_BR)
01007 {
01008 if (s < hist_BR)
01009 {
01010
01011 eol = hist.getLineLen(hY);
01012
01013 if ((hY == (sel_BR / columns)) &&
01014 (eol >= (sel_BR % columns)))
01015 {
01016 eol = sel_BR % columns + 1;
01017 }
01018
01019 while (hX < eol)
01020 {
01021 m[d++] = hist.getCell(hY, hX++).c;
01022 s++;
01023 }
01024
01025 if (s <= sel_BR)
01026 {
01027
01028
01029
01030 if (eol % columns == 0)
01031 {
01032
01033
01034 if (eol == 0)
01035 {
01036 m[d++] = '\n';
01037 }
01038 else
01039 {
01040
01041
01042
01043 }
01044 }
01045 else if ((eol + 1) % columns == 0)
01046 {
01047
01048
01049
01050 m[d++] = ' ';
01051 }
01052 else
01053 {
01054
01055
01056
01057 m[d++] = preserve_line_breaks ? '\n' : ' ';
01058 }
01059 }
01060
01061 hY++;
01062 hX = 0;
01063 s = hY * columns;
01064 }
01065 else
01066 {
01067 eol = (s / columns + 1) * columns - 1;
01068
01069 if (eol < sel_BR)
01070 {
01071 while ((eol > s) &&
01072 isspace(image[eol - hist_BR].c))
01073 {
01074 eol--;
01075 }
01076 }
01077 else
01078 {
01079 eol = sel_BR;
01080 }
01081
01082 while (s <= eol)
01083 {
01084 m[d++] = image[s++ - hist_BR].c;
01085 }
01086
01087 if (eol < sel_BR)
01088 {
01089
01090 if ((eol + 1) % columns == 0)
01091 {
01092 if (image[eol - hist_BR].c == ' ')
01093 {
01094 m[d++] = ' ';
01095 }
01096 }
01097 else
01098 {
01099 m[d++] = ((preserve_line_breaks ||
01100 ((eol % columns) == 0)) ?
01101 '\n' : ' ');
01102 }
01103 }
01104
01105 s = (eol / columns + 1) * columns;
01106 }
01107 }
01108
01109 QChar* qc = new QChar[d];
01110
01111 for (int i = 0; i < d; i++)
01112 {
01113 qc[i] = m[i];
01114 }
01115
01116 QString res(qc, d);
01117
01118 delete m;
01119 delete qc;
01120
01121 return res;
01122 }
01123 QString TEScreen::getHistory() {
01124 sel_begin = 0;
01125 sel_BR = sel_begin;
01126 sel_TL = sel_begin;
01127 setSelExtentXY(columns-1,lines-1);
01128 QString tmp=getSelText(true);
01129 while (tmp.at(tmp.length()-2).unicode()==10 && tmp.at(tmp.length()-1).unicode()==10)
01130 tmp.truncate(tmp.length()-1);
01131
01132 return tmp;
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159 void TEScreen::addHistLine()
01160 {
01161 assert(hasScroll() || histCursor == 0);
01162
01163
01164
01165
01166 if (hasScroll())
01167 { ca dft;
01168
01169 int end = columns-1;
01170 while (end >= 0 && image[end] == dft)
01171 end -= 1;
01172
01173 hist.addCells(image,end+1);
01174 hist.addLine();
01175
01176
01177 histCursor += (hist.getLines()-1 == histCursor);
01178 }
01179
01180 if (!hasScroll()) histCursor = 0;
01181 }
01182
01183 void TEScreen::setHistCursor(int cursor)
01184 {
01185 histCursor = cursor;
01186 }
01187
01188 int TEScreen::getHistCursor()
01189 {
01190 return histCursor;
01191 }
01192
01193 int TEScreen::getHistLines()
01194 {
01195 return hist.getLines();
01196 }
01197
01198 void TEScreen::setScroll(bool on)
01199 {
01200 histCursor = 0;
01201 clearSelection();
01202 hist.setScroll(on);
01203 }
01204
01205 bool TEScreen::hasScroll()
01206 {
01207 return hist.hasScroll();
01208 }