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 
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <unistd.h>
00047 // #include <kdebug.h>
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 //FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
00058 //FIXME: see if we can get this from terminfo.
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 /* Normalized                    Screen Operations                           */
00092 /*                                                                           */
00093 /* ------------------------------------------------------------------------- */
00094 
00095 // Cursor Setting --------------------------------------------------------------
00096 
00113 void TEScreen::cursorUp(int n)
00114 //=CUU
00115 {
00116   if (n == 0) n = 1; // Default
00117   int stop = cuY < tmargin ? 0 : tmargin;
00118   cuX = QMIN(columns-1,cuX); // nowrap!
00119   cuY = QMAX(stop,cuY-n);
00120 }
00121 
00128 void TEScreen::cursorDown(int n)
00129 //=CUD
00130 {
00131   if (n == 0) n = 1; // Default
00132   int stop = cuY > bmargin ? lines-1 : bmargin;
00133   cuX = QMIN(columns-1,cuX); // nowrap!
00134   cuY = QMIN(stop,cuY+n);
00135 }
00136 
00143 void TEScreen::cursorLeft(int n)
00144 //=CUB
00145 {
00146   if (n == 0) n = 1; // Default
00147   cuX = QMIN(columns-1,cuX); // nowrap!
00148   cuX = QMAX(0,cuX-n);
00149 }
00150 
00157 void TEScreen::cursorRight(int n)
00158 //=CUF
00159 {
00160   if (n == 0) n = 1; // Default
00161   cuX = QMIN(columns-1,cuX+n);
00162 }
00163 
00168 void TEScreen::setMargins(int top, int bot)
00169 //=STBM
00170 {
00171   if (top == 0) top = 1;      // Default
00172   if (bot == 0) bot = lines;  // Default
00173   top = top - 1;              // Adjust to internal lineno
00174   bot = bot - 1;              // Adjust to internal lineno
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;                   // Default error action: ignore
00179   }
00180   tmargin = top;
00181   bmargin = bot;
00182   cuX = 0;
00183   cuY = getMode(MODE_Origin) ? top : 0;
00184 }
00185 
00193 void TEScreen::index()
00194 //=IND
00195 {
00196   if (cuY == bmargin)
00197   {
00198     if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
00199     scrollUp(tmargin,1);
00200   }
00201   else if (cuY < lines-1)
00202     cuY += 1;
00203 }
00204 
00212 void TEScreen::reverseIndex()
00213 //=RI
00214 {
00215   if (cuY == tmargin)
00216      scrollDown(tmargin,1);
00217   else if (cuY > 0)
00218     cuY -= 1;
00219 }
00220 
00228 void TEScreen::NextLine()
00229 //=NEL
00230 {
00231   Return(); index();
00232 }
00233 
00234 // Line Editing ----------------------------------------------------------------
00235 
00244 void TEScreen::eraseChars(int n)
00245 {
00246   if (n == 0) n = 1; // Default
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; // Default
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; // Default
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; // Default
00286   scrollUp(cuY,n);
00287 }
00288 
00294 void TEScreen::insertLines(int n)
00295 {
00296   if (n == 0) n = 1; // Default
00297   scrollDown(cuY,n);
00298 }
00299 
00300 // Mode Operations -----------------------------------------------------------
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; //FIXME: home
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; //FIXME: home
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 //NOTE: this is a helper function
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 /*                             Screen Operations                             */
00371 /*                                                                           */
00372 /* ------------------------------------------------------------------------- */
00373 
00384 void TEScreen::resizeImage(int new_lines, int new_columns)
00385 {
00386 
00387   if (cuY > new_lines-1)
00388   { // attempt to preserve focus and lines
00389     bmargin = lines-1; //FIXME: margin lost
00390     for (int i = 0; i < cuY-(new_lines-1); i++)
00391     {
00392       addHistLine(); scrollUp(0,1);
00393     }
00394   }
00395 
00396   // make new image
00397   ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
00398 
00399   clearSelection();
00400 
00401   // clear new image
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   // copy to new image
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   // 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 { 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]); // for selection
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]); // for selection
00538        }
00539 
00540     }
00541   }
00542   // evtl. inverse display
00543   if (getMode(MODE_Screen))
00544   { int i,n = lines*columns;
00545     for (i = 0; i < n; i++)
00546       reverseRendition(&merged[i]); // for reverse display
00547   }
00548   if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
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  );  // wrap at end of margin
00560   resetMode(MODE_Origin); saveMode(MODE_Origin);  // position refere to [1,1]
00561   resetMode(MODE_Insert); saveMode(MODE_Insert);  // overstroke
00562     setMode(MODE_Cursor);                         // cursor visible
00563   resetMode(MODE_Screen);                         // screen not inverse
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   // note that TAB is a format effector (does not write ' ');
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   // Arrg! The 1st tabstop has to be one longer than the other.
00618   // i.e. the kids start counting from 0 instead of 1.
00619   // Other programs might behave correctly. Be aware.
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   //Clear entire selection if it overlaps region [from, to]
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   // Note that VT100 does wrapping BEFORE putting the character.
00655   // This has impact on the assumption of valid cursor positions.
00656   // We indicate the fact that a newline has to be triggered by
00657   // putting the cursor one right to the last column of the screen.
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); // check if selection is still valid.
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 // Region commands -------------------------------------------------------------
00679 
00680 
00686 void TEScreen::scrollUp(int from, int n)
00687 {
00688   if (n <= 0 || from + n > bmargin) return;
00689   //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
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 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
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; // Default
00720   x -= 1; // Adjust
00721   cuX = QMAX(0,QMIN(columns-1, x));
00722 }
00723 
00726 void TEScreen::setCursorY(int y)
00727 {
00728   if (y == 0) y = 1; // Default
00729   y -= 1; // Adjust
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 // Erasing ---------------------------------------------------------------------
00767 
00784 void TEScreen::clearImage(int loca, int loce, char c)
00785 { int i;
00786   int scr_TL=loc(0,hist.getLines());
00787   //FIXME: check positions
00788 
00789   //Clear entire selection if it overlaps region to be moved...
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; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
00798     image[i].b = ef_bg; //DEFAULT_BACK_COLOR; //       many have different
00799     image[i].r = ef_re; //DEFAULT_RENDITION;  //       ideas here.
00800   }
00801 }
00802 
00810 void TEScreen::moveImage(int dst, int loca, int loce)
00811 {
00812 //FIXME: check positions
00813   if (loce < loca) {
00814     // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
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 // Rendition ------------------------------------------------------------------
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 /*                            Marking & Selection                            */
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     /* FIXME, HACK to correct for x too far to the right... */
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; // Selection got clear while selecting.
00990 
00991   int *m;                       // buffer to fill.
00992   int s, d;                     // source index, dest. index.
00993   int hist_BR = loc(0, hist.getLines());
00994   int hY = sel_TL / columns;
00995   int hX = sel_TL % columns;
00996   int eol;                      // end of line
00997 
00998   s = sel_TL;                   // tracks copy in source.
00999 
01000                                 // allocate buffer for maximum
01001                                 // possible size...
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         {                       // get lines from hist.history
01010                                 // buffer.
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                                 // The line break handling
01028                                 // It's different from the screen
01029                                 // image case!
01030               if (eol % columns == 0)
01031                 {
01032                                 // That's either a completely filled
01033                                 // line or an empty line
01034                   if (eol == 0)
01035                     {
01036                       m[d++] = '\n';
01037                     }
01038                   else
01039                     {
01040                                 // We have a full line.
01041                                 // FIXME: How can we handle newlines
01042                                 // at this position?!
01043                     }
01044                 }
01045               else if ((eol + 1) % columns == 0)
01046                 {
01047                                 // FIXME: We don't know if this was a
01048                                 // space at the last position or a
01049                                 // short line!!
01050                   m[d++] = ' ';
01051                 }
01052               else
01053                 {
01054                                 // We have a short line here. Put a
01055                                 // newline or a space into the
01056                                 // buffer.
01057                   m[d++] = preserve_line_breaks ? '\n' : ' ';
01058                 }
01059             }
01060 
01061           hY++;
01062           hX = 0;
01063           s = hY * columns;
01064         }
01065     else
01066       {                         // or from screen image.
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                                 // eol processing see below ...
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 /* above ... end of line processing for selection -- psilva
01135 cases:
01136 
01137 1)    (eol+1)%columns == 0 --> the whole line is filled.
01138    If the last char is a space, insert (preserve) space. otherwise
01139    leave the text alone, so that words that are broken by linewrap
01140    are preserved.
01141 
01142 FIXME:
01143         * this suppresses \n for command output that is
01144           sized to the exact column width of the screen.
01145 
01146 2)    eol%columns == 0     --> blank line.
01147    insert a \n unconditionally.
01148    Do it either you would because you are in preserve_line_break mode,
01149    or because it's an ASCII paragraph delimiter, so even when
01150    not preserving line_breaks, you want to preserve paragraph breaks.
01151 
01152 3)    else               --> partially filled line
01153    insert a \n in preserve line break mode, else a space
01154    The space prevents concatenation of the last word of one
01155    line with the first of the next.
01156 
01157 */
01158 
01159 void TEScreen::addHistLine()
01160 {
01161   assert(hasScroll() || histCursor == 0);
01162 
01163   // add to hist buffer
01164   // we have to take care about scrolling, too...
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     // adjust history cursor
01177     histCursor += (hist.getLines()-1 == histCursor);
01178   }
01179 
01180   if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
01181 }
01182 
01183 void TEScreen::setHistCursor(int cursor)
01184 {
01185   histCursor = cursor; //FIXME:rangecheck
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 }

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