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

screen.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------- */
00002 /*                                                                            */
00003 /* [screen.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 "screen.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 Screen::Screen(int lines, int columns)
00067 {
00068   this->lines   = lines;
00069   this->columns = columns;
00070 
00071   image      = QArray<Character>( lines*columns );
00072   tabstops   = NULL; initTabStops();
00073 
00074   histCursor = 0;
00075 
00076   clearSelection();
00077   reset();
00078 }
00079 
00083 Screen::~Screen()
00084 {
00085   delete image;
00086   if (tabstops) free(tabstops);
00087 }
00088 
00089 /* ------------------------------------------------------------------------- */
00090 /*                                                                           */
00091 /* Normalized                    Screen Operations                           */
00092 /*                                                                           */
00093 /* ------------------------------------------------------------------------- */
00094 
00095 // Cursor Setting --------------------------------------------------------------
00096 
00113 void Screen::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 Screen::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 Screen::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 Screen::cursorRight(int n)
00158 //=CUF
00159 {
00160   if (n == 0) n = 1; // Default
00161   cuX = QMIN(columns-1,cuX+n);
00162 }
00163 
00168 void Screen::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 Screen::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 Screen::reverseIndex()
00213 //=RI
00214 {
00215   if (cuY == tmargin)
00216      scrollDown(tmargin,1);
00217   else if (cuY > 0)
00218     cuY -= 1;
00219 }
00220 
00228 void Screen::NextLine()
00229 //=NEL
00230 {
00231   Return(); index();
00232 }
00233 
00234 // Line Editing ----------------------------------------------------------------
00235 
00244 void Screen::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 Screen::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 Screen::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 Screen::deleteLines(int n)
00284 {
00285   if (n == 0) n = 1; // Default
00286   scrollUp(cuY,n);
00287 }
00288 
00294 void Screen::insertLines(int n)
00295 {
00296   if (n == 0) n = 1; // Default
00297   scrollDown(cuY,n);
00298 }
00299 
00300 // Mode Operations -----------------------------------------------------------
00301 
00304 void Screen::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 Screen::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 Screen::saveMode(int m)
00327 {
00328   saveParm.mode[m] = currParm.mode[m];
00329 }
00330 
00333 void Screen::restoreMode(int m)
00334 {
00335   currParm.mode[m] = saveParm.mode[m];
00336 }
00337 
00338 //NOTE: this is a helper function
00340 BOOL Screen::getMode(int m)
00341 {
00342   return currParm.mode[m];
00343 }
00344 
00347 void Screen::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 Screen::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 Screen::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   QArray<Character> newimg = QArray<Character>( new_lines * new_columns );
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   delete 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 Screen::reverseRendition(Character *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 Screen::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 QArray<Character> Screen::getCookedImage()
00508 { int x,y;
00509   Character* merged = (Character*) malloc( lines * columns * sizeof( Character ) );
00510   Character 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   QArray<Character> res( sizeof( merged ) / sizeof( Character ) );
00551   res.assign( merged, sizeof( merged ) / sizeof( Character ) );
00552   return res;
00553 }
00554 
00555 
00559 void Screen::reset()
00560 {
00561     setMode(MODE_Wrap  ); saveMode(MODE_Wrap  );  // wrap at end of margin
00562   resetMode(MODE_Origin); saveMode(MODE_Origin);  // position refere to [1,1]
00563   resetMode(MODE_Insert); saveMode(MODE_Insert);  // overstroke
00564     setMode(MODE_Cursor);                         // cursor visible
00565   resetMode(MODE_Screen);                         // screen not inverse
00566   resetMode(MODE_NewLine);
00567 
00568   tmargin=0;
00569   bmargin=lines-1;
00570 
00571   setDefaultRendition();
00572   saveCursor();
00573 
00574   clear();
00575 }
00576 
00580 void Screen::clear()
00581 {
00582   clearEntireScreen();
00583   home();
00584 }
00585 
00589 void Screen::BackSpace()
00590 {
00591   cuX = QMAX(0,cuX-1);
00592   if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
00593 }
00594 
00598 void Screen::Tabulate()
00599 {
00600   // note that TAB is a format effector (does not write ' ');
00601   cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
00602 }
00603 
00604 void Screen::clearTabStops()
00605 {
00606   for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
00607 }
00608 
00609 void Screen::changeTabStop(bool set)
00610 {
00611   if (cuX >= columns) return;
00612   tabstops[cuX] = set;
00613 }
00614 
00615 void Screen::initTabStops()
00616 {
00617   if (tabstops) free(tabstops);
00618   tabstops = (bool*)malloc(columns*sizeof(bool));
00619   // Arrg! The 1st tabstop has to be one longer than the other.
00620   // i.e. the kids start counting from 0 instead of 1.
00621   // Other programs might behave correctly. Be aware.
00622   for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
00623 }
00624 
00631 void Screen::NewLine()
00632 {
00633   if (getMode(MODE_NewLine)) Return();
00634   index();
00635 }
00636 
00643 void Screen::checkSelection(int from, int to)
00644 {
00645   if (sel_begin == -1) return;
00646   int scr_TL = loc(0, hist.getLines());
00647   //Clear entire selection if it overlaps region [from, to]
00648   if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
00649   {
00650     clearSelection();
00651   }
00652 }
00653 
00654 void Screen::ShowCharacter(unsigned short c)
00655 {
00656   // Note that VT100 does wrapping BEFORE putting the character.
00657   // This has impact on the assumption of valid cursor positions.
00658   // We indicate the fact that a newline has to be triggered by
00659   // putting the cursor one right to the last column of the screen.
00660 
00661   if (cuX >= columns)
00662   {
00663     if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
00664   }
00665 
00666   if (getMode(MODE_Insert)) insertChars(1);
00667 
00668   int i = loc(cuX,cuY);
00669 
00670   checkSelection(i, i); // check if selection is still valid.
00671 
00672   image[i].c = c;
00673   image[i].f = ef_fg;
00674   image[i].b = ef_bg;
00675   image[i].r = ef_re;
00676 
00677   cuX += 1;
00678 }
00679 
00680 // Region commands -------------------------------------------------------------
00681 
00682 
00688 void Screen::scrollUp(int from, int n)
00689 {
00690   if (n <= 0 || from + n > bmargin) return;
00691   //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
00692   moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
00693   clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
00694 }
00695 
00701 void Screen::scrollDown(int from, int n)
00702 {
00703 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
00704   if (n <= 0) return;
00705   if (from > bmargin) return;
00706   if (from + n > bmargin) n = bmargin - from;
00707   moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
00708   clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
00709 }
00710 
00712 void Screen::setCursorYX(int y, int x)
00713 {
00714   setCursorY(y); setCursorX(x);
00715 }
00716 
00719 void Screen::setCursorX(int x)
00720 {
00721   if (x == 0) x = 1; // Default
00722   x -= 1; // Adjust
00723   cuX = QMAX(0,QMIN(columns-1, x));
00724 }
00725 
00728 void Screen::setCursorY(int y)
00729 {
00730   if (y == 0) y = 1; // Default
00731   y -= 1; // Adjust
00732   cuY = QMAX(0,QMIN(lines  -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
00733 }
00734 
00738 void Screen::home()
00739 {
00740   cuX = 0;
00741   cuY = 0;
00742 }
00743 
00747 void Screen::Return()
00748 {
00749   cuX = 0;
00750 }
00751 
00755 int Screen::getCursorX()
00756 {
00757   return cuX;
00758 }
00759 
00763 int Screen::getCursorY()
00764 {
00765   return cuY;
00766 }
00767 
00768 // Erasing ---------------------------------------------------------------------
00769 
00786 void Screen::clearImage(int loca, int loce, char c)
00787 { int i;
00788   int scr_TL=loc(0,hist.getLines());
00789   //FIXME: check positions
00790 
00791   //Clear entire selection if it overlaps region to be moved...
00792   if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
00793   {
00794     clearSelection();
00795   }
00796   for (i = loca; i <= loce; i++)
00797   {
00798     image[i].c = c;
00799     image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
00800     image[i].b = ef_bg; //DEFAULT_BACK_COLOR; //       many have different
00801     image[i].r = ef_re; //DEFAULT_RENDITION;  //       ideas here.
00802   }
00803 }
00804 
00812 void Screen::moveImage(int dst, int loca, int loce)
00813 {
00814 //FIXME: check positions
00815   if (loce < loca) {
00816     // kdDebug() << "WARNING!!! call to Screen:moveImage with loce < loca!" << endl;
00817     return;
00818   }
00819   memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(Character));
00820 }
00821 
00825 void Screen::clearToEndOfScreen()
00826 {
00827   clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
00828 }
00829 
00833 void Screen::clearToBeginOfScreen()
00834 {
00835   clearImage(loc(0,0),loc(cuX,cuY),' ');
00836 }
00837 
00841 void Screen::clearEntireScreen()
00842 {
00843   clearImage(loc(0,0),loc(columns-1,lines-1),' ');
00844 }
00845 
00850 void Screen::helpAlign()
00851 {
00852   clearImage(loc(0,0),loc(columns-1,lines-1),'E');
00853 }
00854 
00858 void Screen::clearToEndOfLine()
00859 {
00860   clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
00861 }
00862 
00866 void Screen::clearToBeginOfLine()
00867 {
00868   clearImage(loc(0,cuY),loc(cuX,cuY),' ');
00869 }
00870 
00874 void Screen::clearEntireLine()
00875 {
00876   clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
00877 }
00878 
00879 // Rendition ------------------------------------------------------------------
00880 
00885 void Screen::setRendition(int re)
00886 {
00887   cu_re |= re;
00888   effectiveRendition();
00889 }
00890 
00895 void Screen::resetRendition(int re)
00896 {
00897   cu_re &= ~re;
00898   effectiveRendition();
00899 }
00900 
00904 void Screen::setDefaultRendition()
00905 {
00906   setForeColorToDefault();
00907   setBackColorToDefault();
00908   cu_re   = DEFAULT_RENDITION;
00909   effectiveRendition();
00910 }
00911 
00915 void Screen::setForeColor(int fgcolor)
00916 {
00917   cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
00918   effectiveRendition();
00919 }
00920 
00924 void Screen::setBackColor(int bgcolor)
00925 {
00926   cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
00927   effectiveRendition();
00928 }
00929 
00933 void Screen::setBackColorToDefault()
00934 {
00935   cu_bg = DEFAULT_BACK_COLOR;
00936   effectiveRendition();
00937 }
00938 
00942 void Screen::setForeColorToDefault()
00943 {
00944   cu_fg = DEFAULT_FORE_COLOR;
00945   effectiveRendition();
00946 }
00947 
00948 /* ------------------------------------------------------------------------- */
00949 /*                                                                           */
00950 /*                            Marking & Selection                            */
00951 /*                                                                           */
00952 /* ------------------------------------------------------------------------- */
00953 
00954 void Screen::clearSelection()
00955 {
00956   sel_BR = -1;
00957   sel_TL = -1;
00958   sel_begin = -1;
00959 }
00960 
00961 void Screen::setSelBeginXY(const int x, const int y)
00962 {
00963   sel_begin = loc(x,y+histCursor) ;
00964   sel_BR = sel_begin;
00965   sel_TL = sel_begin;
00966 }
00967 
00968 void Screen::setSelExtentXY(const int x, const int y)
00969 {
00970   if (sel_begin == -1) return;
00971   int l =  loc(x,y + histCursor);
00972 
00973   if (l < sel_begin)
00974   {
00975     sel_TL = l;
00976     sel_BR = sel_begin;
00977   }
00978   else
00979   {
00980     /* FIXME, HACK to correct for x too far to the right... */
00981     if (( x == columns )|| (x == 0)) l--;
00982 
00983     sel_TL = sel_begin;
00984     sel_BR = l;
00985   }
00986 }
00987 
00988 QString Screen::getSelText(const BOOL preserve_line_breaks)
00989 {
00990   if (sel_begin == -1) 
00991      return QString::null; // Selection got clear while selecting.
00992 
00993   int *m;                       // buffer to fill.
00994   int s, d;                     // source index, dest. index.
00995   int hist_BR = loc(0, hist.getLines());
00996   int hY = sel_TL / columns;
00997   int hX = sel_TL % columns;
00998   int eol;                      // end of line
00999 
01000   s = sel_TL;                   // tracks copy in source.
01001 
01002                                 // allocate buffer for maximum
01003                                 // possible size...
01004   d = (sel_BR - sel_TL) / columns + 1;
01005   m = new int[d * (columns + 1) + 2];
01006   d = 0;
01007 
01008   while (s <= sel_BR)
01009     {
01010       if (s < hist_BR)
01011         {                       // get lines from hist.history
01012                                 // buffer.
01013           eol = hist.getLineLen(hY);
01014 
01015           if ((hY == (sel_BR / columns)) &&
01016               (eol >= (sel_BR % columns)))
01017             {
01018               eol = sel_BR % columns + 1;
01019             }
01020           
01021           while (hX < eol)
01022             {
01023               m[d++] = hist.getCell(hY, hX++).c;
01024               s++;
01025             }
01026 
01027           if (s <= sel_BR)
01028             {
01029                                 // The line break handling
01030                                 // It's different from the screen
01031                                 // image case!
01032               if (eol % columns == 0)
01033                 {
01034                                 // That's either a completely filled
01035                                 // line or an empty line
01036                   if (eol == 0)
01037                     {
01038                       m[d++] = '\n';
01039                     }
01040                   else
01041                     {
01042                                 // We have a full line.
01043                                 // FIXME: How can we handle newlines
01044                                 // at this position?!
01045                     }
01046                 }
01047               else if ((eol + 1) % columns == 0)
01048                 {
01049                                 // FIXME: We don't know if this was a
01050                                 // space at the last position or a
01051                                 // short line!!
01052                   m[d++] = ' ';
01053                 }
01054               else
01055                 {
01056                                 // We have a short line here. Put a
01057                                 // newline or a space into the
01058                                 // buffer.
01059                   m[d++] = preserve_line_breaks ? '\n' : ' ';
01060                 }
01061             }
01062 
01063           hY++;
01064           hX = 0;
01065           s = hY * columns;
01066         }
01067     else
01068       {                         // or from screen image.
01069         eol = (s / columns + 1) * columns - 1;
01070 
01071         if (eol < sel_BR)
01072           {
01073             while ((eol > s) &&
01074                    isspace(image[eol - hist_BR].c))
01075               {
01076                 eol--;
01077               }
01078           }
01079         else
01080           {
01081             eol = sel_BR;
01082           }
01083 
01084         while (s <= eol)
01085           {
01086             m[d++] = image[s++ - hist_BR].c;
01087           }
01088 
01089         if (eol < sel_BR)
01090           {
01091                                 // eol processing see below ...
01092             if ((eol + 1) % columns == 0)
01093               {
01094                 if (image[eol - hist_BR].c == ' ')
01095                   {
01096                     m[d++] = ' ';
01097                   }
01098               }
01099             else
01100               {
01101                 m[d++] = ((preserve_line_breaks ||
01102                            ((eol % columns) == 0)) ?
01103                           '\n' : ' ');
01104               }
01105           }
01106 
01107         s = (eol / columns + 1) * columns;
01108       }
01109     }
01110 
01111   QChar* qc = new QChar[d];
01112 
01113   for (int i = 0; i < d; i++)
01114     {
01115       qc[i] = m[i];
01116     }
01117   
01118   QString res(qc, d);
01119 
01120   delete m;
01121   delete qc;
01122 
01123   return res;
01124 }
01125 /* above ... end of line processing for selection -- psilva
01126 cases:
01127 
01128 1)    (eol+1)%columns == 0 --> the whole line is filled.
01129    If the last char is a space, insert (preserve) space. otherwise
01130    leave the text alone, so that words that are broken by linewrap
01131    are preserved.
01132 
01133 FIXME:
01134         * this suppresses \n for command output that is
01135           sized to the exact column width of the screen.
01136 
01137 2)    eol%columns == 0     --> blank line.
01138    insert a \n unconditionally.
01139    Do it either you would because you are in preserve_line_break mode,
01140    or because it's an ASCII paragraph delimiter, so even when
01141    not preserving line_breaks, you want to preserve paragraph breaks.
01142 
01143 3)    else               --> partially filled line
01144    insert a \n in preserve line break mode, else a space
01145    The space prevents concatenation of the last word of one
01146    line with the first of the next.
01147 
01148 */
01149 
01150 void Screen::addHistLine()
01151 {
01152   assert(hasScroll() || histCursor == 0);
01153 
01154   // add to hist buffer
01155   // we have to take care about scrolling, too...
01156 
01157   if (hasScroll())
01158   { Character dft;
01159 
01160     int end = columns-1;
01161     while (end >= 0 && image[end] == dft)
01162       end -= 1;
01163 
01164     hist.addCells(image.data(), end+1);
01165     hist.addLine();
01166 
01167     // adjust history cursor
01168     histCursor += (hist.getLines()-1 == histCursor);
01169   }
01170 
01171   if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
01172 }
01173 
01174 void Screen::setHistCursor(int cursor)
01175 {
01176   histCursor = cursor; //FIXME:rangecheck
01177 }
01178 
01179 int Screen::getHistCursor()
01180 {
01181   return histCursor;
01182 }
01183 
01184 int Screen::getHistLines()
01185 {
01186   return hist.getLines();
01187 }
01188 
01189 void Screen::setScroll(bool on)
01190 {
01191   histCursor = 0;
01192   clearSelection();
01193   hist.setScroll(on);
01194 }
01195 
01196 bool Screen::hasScroll()
01197 {
01198   return hist.hasScroll();
01199 }

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