Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

TEScreen.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------- */
00002 /*                                                                            */
00003 /* [TEScreen.C]               Screen Data Type                                */
00004 /*                                                                            */
00005 /* -------------------------------------------------------------------------- */
00006 /*                                                                            */
00007 /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>            */
00008 /*                                                                            */
00009 /* This file is part of Konsole - an X terminal for KDE                       */
00010 /*                                                                            */
00011 /* -------------------------------------------------------------------------- */
00012 /*                        */
00013 /* Ported Konsole to Qt/Embedded                                              */
00014 /*                        */
00015 /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com>                  */
00016 /*                        */
00017 /* -------------------------------------------------------------------------- */
00018 // enhancements added by L.J. Potter <ljp@llornkcor.com>
00019 
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047 #include <unistd.h>
00048 // #include <kdebug.h>
00049 
00050 #include <assert.h>
00051 #include <string.h>
00052 #include <ctype.h>
00053 
00054 #include <qpe/config.h>
00055 #include "TEScreen.h"
00056 
00057 #define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
00058 
00059 //FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
00060 //FIXME: see if we can get this from terminfo.
00061 #define BS_CLEARS FALSE
00062 
00063 #define loc(X,Y) ((Y) * columns + (X))
00064 
00068 TEScreen::TEScreen(int lines, int columns)
00069 {
00070   this->lines   = lines;
00071   this->columns = columns;
00072 //  odebug << "Columns " << columns << "" << oendl; 
00073   
00074   image      = (ca*) malloc(lines*columns*sizeof(ca));
00075   tabstops   = NULL; initTabStops();
00076 
00077   histCursor = 0;
00078   horzCursor = 0;
00079 
00080   clearSelection();
00081   reset();
00082 }
00083 
00087 TEScreen::~TEScreen()
00088 {
00089   free(image);
00090   if (tabstops) free(tabstops);
00091 }
00092 
00093 /* ------------------------------------------------------------------------- */
00094 /*                                                                           */
00095 /* Normalized                    Screen Operations                           */
00096 /*                                                                           */
00097 /* ------------------------------------------------------------------------- */
00098 
00099 // Cursor Setting --------------------------------------------------------------
00100 
00117 void TEScreen::cursorUp(int n)
00118 //=CUU
00119 {
00120   if (n == 0) n = 1; // Default
00121   int stop = cuY < tmargin ? 0 : tmargin;
00122   cuX = QMIN(columns-1,cuX); // nowrap!
00123   cuY = QMAX(stop,cuY-n);
00124 }
00125 
00132 void TEScreen::cursorDown(int n)
00133 //=CUD
00134 {
00135   if (n == 0) n = 1; // Default
00136   int stop = cuY > bmargin ? lines-1 : bmargin;
00137   cuX = QMIN(columns-1,cuX); // nowrap!
00138   cuY = QMIN(stop,cuY+n);
00139 }
00140 
00147 void TEScreen::cursorLeft(int n)
00148 //=CUB
00149 {
00150   if (n == 0) n = 1; // Default
00151   cuX = QMIN(columns-1,cuX); // nowrap!
00152   cuX = QMAX(0,cuX-n);
00153 }
00154 
00161 void TEScreen::cursorRight(int n)
00162 //=CUF
00163 {
00164   if (n == 0) n = 1; // Default
00165   cuX = QMIN(columns-1,cuX+n);
00166 }
00167 
00172 void TEScreen::setMargins(int top, int bot)
00173 //=STBM
00174 {
00175   if (top == 0) top = 1;      // Default
00176   if (bot == 0) bot = lines;  // Default
00177   top = top - 1;              // Adjust to internal lineno
00178   bot = bot - 1;              // Adjust to internal lineno
00179   if ( !( 0 <= top && top < bot && bot < lines ) )
00180   { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
00181                    __FILE__,__LINE__,top,bot);
00182     return;                   // Default error action: ignore
00183   }
00184   tmargin = top;
00185   bmargin = bot;
00186   cuX = 0;
00187   cuY = getMode(MODE_Origin) ? top : 0;
00188 }
00189 
00197 void TEScreen::index()
00198 //=IND
00199 {
00200   if (cuY == bmargin)
00201   {
00202     if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
00203     scrollUp(tmargin,1);
00204   }
00205   else if (cuY < lines-1)
00206     cuY += 1;
00207 }
00208 
00216 void TEScreen::reverseIndex()
00217 //=RI
00218 {
00219   if (cuY == tmargin)
00220      scrollDown(tmargin,1);
00221   else if (cuY > 0)
00222     cuY -= 1;
00223 }
00224 
00232 void TEScreen::NextLine()
00233 //=NEL
00234 {
00235   Return(); index();
00236 }
00237 
00238 // Line Editing ----------------------------------------------------------------
00239 
00248 void TEScreen::eraseChars(int n)
00249 {
00250   if (n == 0) n = 1; // Default
00251   int p = QMAX(0,QMIN(cuX+n-1,columns-1));
00252   clearImage(loc(cuX,cuY),loc(p,cuY),' ');
00253 }
00254 
00260 void TEScreen::deleteChars(int n)
00261 {
00262   if (n == 0) n = 1; // Default
00263   int p = QMAX(0,QMIN(cuX+n,columns-1));
00264   moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
00265   clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
00266 }
00267 
00273 void TEScreen::insertChars(int n)
00274 {
00275   if (n == 0) n = 1; // Default
00276   int p = QMAX(0,QMIN(columns-1-n,columns-1));
00277   int q = QMAX(0,QMIN(cuX+n,columns-1));
00278   moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
00279   clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
00280 }
00281 
00287 void TEScreen::deleteLines(int n)
00288 {
00289   if (n == 0) n = 1; // Default
00290   scrollUp(cuY,n);
00291 }
00292 
00298 void TEScreen::insertLines(int n)
00299 {
00300   if (n == 0) n = 1; // Default
00301   scrollDown(cuY,n);
00302 }
00303 
00304 // Mode Operations -----------------------------------------------------------
00305 
00308 void TEScreen::setMode(int m)
00309 {
00310   currParm.mode[m] = TRUE;
00311   switch(m)
00312   {
00313     case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
00314   }
00315 }
00316 
00319 void TEScreen::resetMode(int m)
00320 {
00321   currParm.mode[m] = FALSE;
00322   switch(m)
00323   {
00324     case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
00325   }
00326 }
00327 
00330 void TEScreen::saveMode(int m)
00331 {
00332   saveParm.mode[m] = currParm.mode[m];
00333 }
00334 
00337 void TEScreen::restoreMode(int m)
00338 {
00339   currParm.mode[m] = saveParm.mode[m];
00340 }
00341 
00342 //NOTE: this is a helper function
00344 BOOL TEScreen::getMode(int m)
00345 {
00346   return currParm.mode[m];
00347 }
00348 
00351 void TEScreen::saveCursor()
00352 {
00353   sa_cuX     = cuX;
00354   sa_cuY     = cuY;
00355   sa_cu_re   = cu_re;
00356   sa_cu_fg   = cu_fg;
00357   sa_cu_bg   = cu_bg;
00358 }
00359 
00362 void TEScreen::restoreCursor()
00363 {
00364   cuX     = QMIN(sa_cuX,columns-1);
00365   cuY     = QMIN(sa_cuY,lines-1);
00366   cu_re   = sa_cu_re;
00367   cu_fg   = sa_cu_fg;
00368   cu_bg   = sa_cu_bg;
00369   effectiveRendition();
00370 }
00371 
00372 /* ------------------------------------------------------------------------- */
00373 /*                                                                           */
00374 /*                             Screen Operations                             */
00375 /*                                                                           */
00376 /* ------------------------------------------------------------------------- */
00377 
00388 void TEScreen::resizeImage(int new_lines, int new_columns)
00389 {
00390     if (cuY > new_lines-1)  {
00391 // attempt to preserve focus and lines
00392         bmargin = lines-1; //FIXME: margin lost
00393         for (int i = 0; i < cuY-(new_lines-1); i++) {
00394             addHistLine(); scrollUp(horzCursor,1);
00395         }
00396     }
00397 
00398       // make new image
00399     ca* newimg = (ca*)malloc( new_lines * new_columns * sizeof( ca));
00400 
00401     clearSelection();
00402 
00403       // clear new image
00404     for (int y = 0; y < new_lines; y++)
00405         for (int x = 0; x < new_columns; x++) {
00406             newimg[y*new_columns+x].c = ' ';
00407             newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
00408             newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
00409             newimg[y*new_columns+x].r = DEFAULT_RENDITION;
00410         }
00411     int cpy_lines   = QMIN(new_lines,  lines);
00412     int cpy_columns = QMIN(new_columns,columns);
00413       // copy to new image
00414     for (int y = 0; y < cpy_lines; y++)
00415         for (int x = 0; x < cpy_columns; x++) {
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       // FIXME: try to keep values, evtl.
00429     tmargin=0;
00430     bmargin=lines-1;
00431     initTabStops();
00432     clearSelection();
00433 }
00434 
00435 /*
00436    Clarifying rendition here and in TEWidget.
00437 
00438    currently, TEWidget's color table is
00439      0       1       2 .. 9    10 .. 17
00440      dft_fg, dft_bg, dim 0..7, intensive 0..7
00441 
00442    cu_fg, cu_bg contain values 0..8;
00443    - 0    = default color
00444    - 1..8 = ansi specified color
00445 
00446    re_fg, re_bg contain values 0..17
00447    due to the TEWidget's color table
00448 
00449    rendition attributes are
00450 
00451       attr           widget screen
00452       -------------- ------ ------
00453       RE_UNDERLINE     XX     XX    affects foreground only
00454       RE_BLINK         XX     XX    affects foreground only
00455       RE_BOLD          XX     XX    affects foreground only
00456       RE_REVERSE       --     XX
00457       RE_TRANSPARENT   XX     --    affects background only
00458       RE_INTENSIVE     XX     --    affects foreground only
00459 
00460    Note that RE_BOLD is used in both widget
00461    and screen rendition. Since xterm/vt102
00462    is to poor to distinguish between bold
00463    (which is a font attribute) and intensive
00464    (which is a color attribute), we translate
00465    this and RE_BOLD in falls eventually appart
00466    into RE_BOLD and RE_INTENSIVE.
00467 */
00468 
00469 void TEScreen::reverseRendition(ca* p)
00470 { UINT8 f = p->f; UINT8 b = p->b;
00471   p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
00472 }
00473 
00474 void TEScreen::effectiveRendition()
00475 // calculate rendition
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 {
00509  int x,y;
00510   ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
00511   ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
00512 
00513   if (histCursor > hist.getLines()) {
00514     histCursor = hist.getLines();
00515   }
00516 
00517   for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
00518   {
00519     int len = QMIN(columns,hist.getLineLen(y+histCursor));
00520     int yp  = y*columns;
00521     int yq  = (y+histCursor)*columns;
00522 
00523     hist.getCells(y+histCursor,0,len,merged+yp);
00524     for (x = len; x < columns; x++) merged[yp+x] = dft;
00525     for (x = 0; x < columns; x++)
00526     {   int p=x + yp; int q=x + yq;
00527         if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
00528           reverseRendition(&merged[p]); // for selection
00529     }
00530   }
00531   if (lines >= hist.getLines()-histCursor)
00532   {
00533     for (y = (hist.getLines()-histCursor); y < lines ; y++)
00534     {
00535        int yp  = y*columns;
00536        int yq  = (y+histCursor)*columns;
00537        int yr =  (y-hist.getLines()+histCursor)*columns;
00538        for (x = 0; x < columns; x++)
00539        { int p = x + yp; int q = x + yq; int r = x + yr;
00540          merged[p] = image[r];
00541          if ( q >= sel_TL && q <= sel_BR )
00542            reverseRendition(&merged[p]); // for selection
00543        }
00544 
00545     }
00546   }
00547   // evtl. inverse display
00548   if (getMode(MODE_Screen))
00549   { int i,n = lines*columns;
00550     for (i = 0; i < n; i++)
00551       reverseRendition(&merged[i]); // for reverse display
00552   }
00553   if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
00554     reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
00555   return merged;
00556  
00557 }
00558 
00559 
00563 void TEScreen::reset()
00564 {
00565   Config cfg( "Konsole" );
00566   cfg.setGroup("ScrollBar");
00567   if( !cfg.readBoolEntry("HorzScroll",0) )
00568     setMode(MODE_Wrap  ); saveMode(MODE_Wrap  );  // wrap at end of margin
00569 
00570     
00571   resetMode(MODE_Origin); saveMode(MODE_Origin);  // position refere to [1,1]
00572   resetMode(MODE_Insert); saveMode(MODE_Insert);  // overstroke
00573     setMode(MODE_Cursor);                         // cursor visible
00574   resetMode(MODE_Screen);                         // screen not inverse
00575   resetMode(MODE_NewLine);
00576 
00577   tmargin=0;
00578   bmargin=lines-1;
00579 
00580   setDefaultRendition();
00581   saveCursor();
00582 
00583   clear();
00584 }
00585 
00589 void TEScreen::clear()
00590 {
00591   clearEntireScreen();
00592   home();
00593 }
00594 
00598 void TEScreen::BackSpace()
00599 {
00600   cuX = QMAX(0,cuX-1);
00601   if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
00602 }
00603 
00607 void TEScreen::Tabulate()
00608 {
00609   // note that TAB is a format effector (does not write ' ');
00610   cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
00611 }
00612 
00613 void TEScreen::clearTabStops()
00614 {
00615   for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
00616 }
00617 
00618 void TEScreen::changeTabStop(bool set)
00619 {
00620   if (cuX >= columns) return;
00621   tabstops[cuX] = set;
00622 }
00623 
00624 void TEScreen::initTabStops()
00625 {
00626   if (tabstops) free(tabstops);
00627   tabstops = (bool*)malloc(columns*sizeof(bool));
00628   // Arrg! The 1st tabstop has to be one longer than the other.
00629   // i.e. the kids start counting from 0 instead of 1.
00630   // Other programs might behave correctly. Be aware.
00631   for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
00632 }
00633 
00640 void TEScreen::NewLine()
00641 {
00642   if (getMode(MODE_NewLine)) Return();
00643   index();
00644 }
00645 
00652 void TEScreen::checkSelection(int from, int to)
00653 {
00654   if (sel_begin == -1) return;
00655   int scr_TL = loc(0, hist.getLines());
00656   //Clear entire selection if it overlaps region [from, to]
00657   if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
00658   {
00659     clearSelection();
00660   }
00661 }
00662 
00663 void TEScreen::ShowCharacter(unsigned short c)
00664 {
00665   // Note that VT100 does wrapping BEFORE putting the character.
00666   // This has impact on the assumption of valid cursor positions.
00667   // We indicate the fact that a newline has to be triggered by
00668   // putting the cursor one right to the last column of the screen.
00669 
00670   if (cuX >= columns)
00671   {
00672     if (getMode(MODE_Wrap)) NextLine(); else cuX = columns - 1;
00673        // comment out for no wrap
00674   }
00675 
00676   if (getMode(MODE_Insert)) insertChars(1);
00677 
00678   int i = loc( cuX, cuY);
00679 
00680   checkSelection(i, i); // check if selection is still valid.
00681 
00682   image[i].c = c;
00683   image[i].f = ef_fg;
00684   image[i].b = ef_bg;
00685   image[i].r = ef_re;
00686 
00687   cuX += 1;
00688 }
00689 
00690 // Region commands -------------------------------------------------------------
00691 
00692 
00698 void TEScreen::scrollUp(int from, int n)
00699 {
00700  if (n <= 0 || from + n > bmargin) return;
00701   //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
00702 
00703     moveImage( loc( 0, from), loc( 0, from + n), loc( columns - 1, bmargin));
00704     clearImage( loc( 0, bmargin - n + 1), loc( columns - 1, bmargin), ' ');
00705 }
00706 
00712 void TEScreen::scrollDown(int from, int n)
00713 {
00714     
00715 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
00716  if (n <= 0) return;
00717   if (from > bmargin) return;
00718   if (from + n > bmargin) n = bmargin - from;
00719 
00720   moveImage( loc(0,from+n), loc(0,from), loc(columns-1,bmargin-n));
00721   clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
00722 }
00723 
00724 
00725 
00727 void TEScreen::setCursorYX(int y, int x)
00728 {
00729   setCursorY(y); setCursorX(x);
00730 }
00731 
00734 void TEScreen::setCursorX(int x)
00735 {
00736   if (x == 0) x = 1; // Default
00737   x -= 1; // Adjust
00738   cuX = QMAX(0,QMIN(columns-1, x));
00739 }
00740 
00743 void TEScreen::setCursorY(int y)
00744 {
00745   if (y == 0) y = 1; // Default
00746   y -= 1; // Adjust
00747   cuY = QMAX(0,QMIN(lines  -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
00748 }
00749 
00753 void TEScreen::home()
00754 {
00755   cuX = 0;
00756   cuY = 0;
00757 }
00758 
00762 void TEScreen::Return()
00763 {
00764   cuX = 0;
00765 }
00766 
00770 int TEScreen::getCursorX()
00771 {
00772   return cuX;
00773 }
00774 
00778 int TEScreen::getCursorY()
00779 {
00780   return cuY;
00781 }
00782 
00783 // Erasing ---------------------------------------------------------------------
00784 
00801 void TEScreen::clearImage(int loca, int loce, char c)
00802 { int i;
00803   int scr_TL=loc(0,hist.getLines());
00804   //FIXME: check positions
00805 
00806   //Clear entire selection if it overlaps region to be moved...
00807   if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
00808   {
00809     clearSelection();
00810   }
00811   for (i = loca; i <= loce; i++)
00812   {
00813     image[i].c = c;
00814     image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
00815     image[i].b = ef_bg; //DEFAULT_BACK_COLOR; //       many have different
00816     image[i].r = ef_re; //DEFAULT_RENDITION;  //       ideas here.
00817   }
00818 }
00819 
00827 void TEScreen::moveImage(int dst, int loca, int loce)
00828 {
00829 //FIXME: check positions
00830   if (loce < loca) {
00831     // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
00832     return;
00833   }
00834   memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
00835 }
00836 
00840 void TEScreen::clearToEndOfScreen()
00841 {
00842   clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
00843 }
00844 
00848 void TEScreen::clearToBeginOfScreen()
00849 {
00850   clearImage(loc(0,0),loc(cuX,cuY),' ');
00851 }
00852 
00856 void TEScreen::clearEntireScreen()
00857 {
00858   clearImage(loc(0,0),loc(columns-1,lines-1),' ');
00859 }
00860 
00865 void TEScreen::helpAlign()
00866 {
00867   clearImage(loc(0,0),loc(columns-1,lines-1),'E');
00868 }
00869 
00873 void TEScreen::clearToEndOfLine()
00874 {
00875   clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
00876 }
00877 
00881 void TEScreen::clearToBeginOfLine()
00882 {
00883   clearImage(loc(0,cuY),loc(cuX,cuY),' ');
00884 }
00885 
00889 void TEScreen::clearEntireLine()
00890 {
00891   clearImage( loc( 0, cuY),loc( columns - 1, cuY),' ');
00892 }
00893 
00894 // Rendition ------------------------------------------------------------------
00895 
00900 void TEScreen::setRendition(int re)
00901 {
00902   cu_re |= re;
00903   effectiveRendition();
00904 }
00905 
00910 void TEScreen::resetRendition(int re)
00911 {
00912   cu_re &= ~re;
00913   effectiveRendition();
00914 }
00915 
00919 void TEScreen::setDefaultRendition()
00920 {
00921   setForeColorToDefault();
00922   setBackColorToDefault();
00923   cu_re   = DEFAULT_RENDITION;
00924   effectiveRendition();
00925 }
00926 
00930 void TEScreen::setForeColor(int fgcolor)
00931 {
00932   cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
00933   effectiveRendition();
00934 }
00935 
00939 void TEScreen::setBackColor(int bgcolor)
00940 {
00941   cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
00942   effectiveRendition();
00943 }
00944 
00948 void TEScreen::setBackColorToDefault()
00949 {
00950   cu_bg = DEFAULT_BACK_COLOR;
00951   effectiveRendition();
00952 }
00953 
00957 void TEScreen::setForeColorToDefault()
00958 {
00959   cu_fg = DEFAULT_FORE_COLOR;
00960   effectiveRendition();
00961 }
00962 
00963 /* ------------------------------------------------------------------------- */
00964 /*                                                                           */
00965 /*                            Marking & Selection                            */
00966 /*                                                                           */
00967 /* ------------------------------------------------------------------------- */
00968 
00969 void TEScreen::clearSelection()
00970 {
00971   sel_BR = -1;
00972   sel_TL = -1;
00973   sel_begin = -1;
00974 }
00975 
00976 void TEScreen::setSelBeginXY(const int x, const int y)
00977 {
00978   if (histCursor > hist.getLines()) {
00979     histCursor = hist.getLines();
00980   }
00981   sel_begin = loc(x,y+histCursor) ;
00982   sel_BR = sel_begin;
00983   sel_TL = sel_begin;
00984 }
00985 
00986 void TEScreen::setSelExtentXY(const int x, const int y)
00987 {
00988   if (sel_begin == -1) return;
00989   if (histCursor > hist.getLines()) {
00990     histCursor = hist.getLines();
00991   }
00992   int l =  loc(x,y + histCursor);
00993 
00994   if (l < sel_begin)
00995   {
00996     sel_TL = l;
00997     sel_BR = sel_begin;
00998   }
00999   else
01000   {
01001     /* FIXME, HACK to correct for x too far to the right... */
01002     if (( x == columns )|| (x == 0)) l--;
01003 
01004     sel_TL = sel_begin;
01005     sel_BR = l;
01006   }
01007 }
01008 
01009 QString TEScreen::getSelText(const BOOL preserve_line_breaks)
01010 {
01011   if (sel_begin == -1) 
01012      return QString::null; // Selection got clear while selecting.
01013 
01014   int *m;     // buffer to fill.
01015   int s, d;     // source index, dest. index.
01016   int hist_BR = loc(0, hist.getLines());
01017   int hY = sel_TL / columns;
01018   int hX = sel_TL % columns;
01019   int eol;      // end of line
01020 
01021   s = sel_TL;     // tracks copy in source.
01022 
01023         // allocate buffer for maximum
01024         // possible size...
01025   d = (sel_BR - sel_TL) / columns + 1;
01026   m = new int[d * (columns + 1) + 2];
01027   d = 0;
01028 
01029   while (s <= sel_BR)
01030     {
01031       if (s < hist_BR)
01032   {     // get lines from hist.history
01033         // buffer.
01034     eol = hist.getLineLen(hY);
01035 
01036     if ((hY == (sel_BR / columns)) &&
01037         (eol >= (sel_BR % columns)))
01038       {
01039         eol = sel_BR % columns + 1;
01040       }
01041     
01042     while (hX < eol)
01043       {
01044         m[d++] = hist.getCell(hY, hX++).c;
01045         s++;
01046       }
01047 
01048     if (s <= sel_BR)
01049       {
01050         // The line break handling
01051         // It's different from the screen
01052         // image case!
01053         if (eol % columns == 0)
01054     {
01055         // That's either a completely filled
01056         // line or an empty line
01057       if (eol == 0)
01058         {
01059           m[d++] = '\n';
01060         }
01061       else
01062         {
01063         // We have a full line.
01064         // FIXME: How can we handle newlines
01065         // at this position?!
01066         }
01067     }
01068         else if ((eol + 1) % columns == 0)
01069     {
01070         // FIXME: We don't know if this was a
01071         // space at the last position or a
01072         // short line!!
01073       m[d++] = ' ';
01074     }
01075         else
01076     {
01077         // We have a short line here. Put a
01078         // newline or a space into the
01079         // buffer.
01080       m[d++] = preserve_line_breaks ? '\n' : ' ';
01081     }
01082       }
01083 
01084     hY++;
01085     hX = 0;
01086     s = hY * columns;
01087   }
01088     else
01089       {       // or from screen image.
01090   eol = (s / columns + 1) * columns - 1;
01091 
01092   if (eol < sel_BR)
01093     {
01094       while ((eol > s) &&
01095        isspace(image[eol - hist_BR].c))
01096         {
01097     eol--;
01098         }
01099     }
01100   else
01101     {
01102       eol = sel_BR;
01103     }
01104 
01105   while (s <= eol)
01106     {
01107       m[d++] = image[s++ - hist_BR].c;
01108     }
01109 
01110   if (eol < sel_BR)
01111     {
01112         // eol processing see below ...
01113       if ((eol + 1) % columns == 0)
01114         {
01115     if (image[eol - hist_BR].c == ' ')
01116       {
01117         m[d++] = ' ';
01118       }
01119         }
01120       else
01121         {
01122     m[d++] = ((preserve_line_breaks ||
01123          ((eol % columns) == 0)) ?
01124         '\n' : ' ');
01125         }
01126     }
01127 
01128   s = (eol / columns + 1) * columns;
01129       }
01130     }
01131 
01132   QChar* qc = new QChar[d];
01133 
01134   for (int i = 0; i < d; i++)
01135     {
01136       qc[i] = m[i];
01137     }
01138   
01139   QString res(qc, d);
01140 
01141   delete m;
01142   delete qc;
01143 
01144   return res;
01145 }
01146 /* above ... end of line processing for selection -- psilva
01147 cases:
01148 
01149 1)    (eol+1)%columns == 0 --> the whole line is filled.
01150    If the last char is a space, insert (preserve) space. otherwise
01151    leave the text alone, so that words that are broken by linewrap
01152    are preserved.
01153 
01154 FIXME:
01155   * this suppresses \n for command output that is
01156     sized to the exact column width of the screen.
01157 
01158 2)    eol%columns == 0     --> blank line.
01159    insert a \n unconditionally.
01160    Do it either you would because you are in preserve_line_break mode,
01161    or because it's an ASCII paragraph delimiter, so even when
01162    not preserving line_breaks, you want to preserve paragraph breaks.
01163 
01164 3)    else     --> partially filled line
01165    insert a \n in preserve line break mode, else a space
01166    The space prevents concatenation of the last word of one
01167    line with the first of the next.
01168 
01169 */
01170 
01171 void TEScreen::addHistLine()
01172 {
01173   assert(hasScroll() || histCursor == 0);
01174 
01175   // add to hist buffer
01176   // we have to take care about scrolling, too...
01177 
01178   if (hasScroll()){
01179       ca dft;
01180 
01181     int end = columns - 1;
01182     while (end >= 0 && image[end] == dft)
01183       end -= 1;
01184 
01185     hist.addCells( image, end + 1);
01186     hist.addLine();
01187 
01188     // adjust history cursor
01189     histCursor += ( hist.getLines() - 1 == histCursor);
01190   }
01191 
01192   if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
01193 }
01194 
01195 void TEScreen::setHistCursor(int cursor)
01196 {
01197   histCursor = cursor; //FIXME:rangecheck
01198   if (histCursor > hist.getLines()) {
01199     histCursor = hist.getLines();
01200   }
01201   if (histCursor < 0) {
01202     histCursor = 0;
01203   }
01204 }
01205 
01206 void TEScreen::setHorzCursor(int cursor)
01207 {
01208   horzCursor = cursor; 
01209 }
01210 
01211 int TEScreen::getHistCursor()
01212 {
01213   return histCursor;
01214 }
01215 
01216 int TEScreen::getHorzCursor()
01217 {
01218   return horzCursor;
01219 }
01220 
01221 int TEScreen::getHistLines()
01222 {
01223   return hist.getLines();
01224 }
01225 
01226 void TEScreen::setScroll(bool on)
01227 {
01228   histCursor = 0;
01229   clearSelection();
01230   hist.setScroll(on);
01231 }
01232 
01233 bool TEScreen::hasScroll()
01234 {
01235   return hist.hasScroll();
01236 }

Generated on Sat Nov 5 16:15:27 2005 for OPIE by  doxygen 1.4.2