summaryrefslogtreecommitdiff
path: root/core/apps/embeddedkonsole/TEScreen.cpp
Unidiff
Diffstat (limited to 'core/apps/embeddedkonsole/TEScreen.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/apps/embeddedkonsole/TEScreen.cpp1197
1 files changed, 1197 insertions, 0 deletions
diff --git a/core/apps/embeddedkonsole/TEScreen.cpp b/core/apps/embeddedkonsole/TEScreen.cpp
new file mode 100644
index 0000000..a3d115d
--- a/dev/null
+++ b/core/apps/embeddedkonsole/TEScreen.cpp
@@ -0,0 +1,1197 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEScreen.C] Screen Data Type */
4/* */
5/* -------------------------------------------------------------------------- */
6/* */
7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
8/* */
9/* This file is part of Konsole - an X terminal for KDE */
10/* */
11/* -------------------------------------------------------------------------- */
12 /* */
13/* Ported Konsole to Qt/Embedded */
14 /* */
15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
16 /* */
17/* -------------------------------------------------------------------------- */
18
19/*! \file
20*/
21
22/*! \class TEScreen
23
24 \brief The image manipulated by the emulation.
25
26 This class implements the operations of the terminal emulation framework.
27 It is a complete passive device, driven by the emulation decoder
28 (TEmuVT102). By this it forms in fact an ADT, that defines operations
29 on a rectangular image.
30
31 It does neither know how to display its image nor about escape sequences.
32 It is further independent of the underlying toolkit. By this, one can even
33 use this module for an ordinary text surface.
34
35 Since the operations are called by a specific emulation decoder, one may
36 collect their different operations here.
37
38 The state manipulated by the operations is mainly kept in `image', though
39 it is a little more complex bejond this. See the header file of the class.
40
41 \sa TEWidget \sa VT102Emulation
42*/
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <unistd.h>
47// #include <kdebug.h>
48
49#include <assert.h>
50#include <string.h>
51#include <ctype.h>
52
53#include "TEScreen.h"
54
55#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
56
57//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
58//FIXME: see if we can get this from terminfo.
59#define BS_CLEARS FALSE
60
61#define loc(X,Y) ((Y)*columns+(X))
62
63/*! creates a `TEScreen' of `lines' lines and `columns' columns.
64*/
65
66TEScreen::TEScreen(int lines, int columns)
67{
68 this->lines = lines;
69 this->columns = columns;
70
71 image = (ca*) malloc(lines*columns*sizeof(ca));
72 tabstops = NULL; initTabStops();
73
74 histCursor = 0;
75
76 clearSelection();
77 reset();
78}
79
80/*! Destructor
81*/
82
83TEScreen::~TEScreen()
84{
85 free(image);
86 if (tabstops) free(tabstops);
87}
88
89/* ------------------------------------------------------------------------- */
90/* */
91/* Normalized Screen Operations */
92/* */
93/* ------------------------------------------------------------------------- */
94
95// Cursor Setting --------------------------------------------------------------
96
97/*! \section Cursor
98
99 The `cursor' is a location within the screen that is implicitely used in
100 many operations. The operations within this section allow to manipulate
101 the cursor explicitly and to obtain it's value.
102
103 The position of the cursor is guarantied to be between (including) 0 and
104 `columns-1' and `lines-1'.
105*/
106
107/*!
108 Move the cursor up.
109
110 The cursor will not be moved beyond the top margin.
111*/
112
113void TEScreen::cursorUp(int n)
114//=CUU
115{
116 if (n == 0) n = 1; // Default
117 int stop = cuY < tmargin ? 0 : tmargin;
118 cuX = QMIN(columns-1,cuX); // nowrap!
119 cuY = QMAX(stop,cuY-n);
120}
121
122/*!
123 Move the cursor down.
124
125 The cursor will not be moved beyond the bottom margin.
126*/
127
128void TEScreen::cursorDown(int n)
129//=CUD
130{
131 if (n == 0) n = 1; // Default
132 int stop = cuY > bmargin ? lines-1 : bmargin;
133 cuX = QMIN(columns-1,cuX); // nowrap!
134 cuY = QMIN(stop,cuY+n);
135}
136
137/*!
138 Move the cursor left.
139
140 The cursor will not move beyond the first column.
141*/
142
143void TEScreen::cursorLeft(int n)
144//=CUB
145{
146 if (n == 0) n = 1; // Default
147 cuX = QMIN(columns-1,cuX); // nowrap!
148 cuX = QMAX(0,cuX-n);
149}
150
151/*!
152 Move the cursor left.
153
154 The cursor will not move beyond the rightmost column.
155*/
156
157void TEScreen::cursorRight(int n)
158//=CUF
159{
160 if (n == 0) n = 1; // Default
161 cuX = QMIN(columns-1,cuX+n);
162}
163
164/*!
165 Set top and bottom margin.
166*/
167
168void TEScreen::setMargins(int top, int bot)
169//=STBM
170{
171 if (top == 0) top = 1; // Default
172 if (bot == 0) bot = lines; // Default
173 top = top - 1; // Adjust to internal lineno
174 bot = bot - 1; // Adjust to internal lineno
175 if ( !( 0 <= top && top < bot && bot < lines ) )
176 { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
177 __FILE__,__LINE__,top,bot);
178 return; // Default error action: ignore
179 }
180 tmargin = top;
181 bmargin = bot;
182 cuX = 0;
183 cuY = getMode(MODE_Origin) ? top : 0;
184}
185
186/*!
187 Move the cursor down one line.
188
189 If cursor is on bottom margin, the region between the
190 actual top and bottom margin is scrolled up instead.
191*/
192
193void TEScreen::index()
194//=IND
195{
196 if (cuY == bmargin)
197 {
198 if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
199 scrollUp(tmargin,1);
200 }
201 else if (cuY < lines-1)
202 cuY += 1;
203}
204
205/*!
206 Move the cursor up one line.
207
208 If cursor is on the top margin, the region between the
209 actual top and bottom margin is scrolled down instead.
210*/
211
212void TEScreen::reverseIndex()
213//=RI
214{
215 if (cuY == tmargin)
216 scrollDown(tmargin,1);
217 else if (cuY > 0)
218 cuY -= 1;
219}
220
221/*!
222 Move the cursor to the begin of the next line.
223
224 If cursor is on bottom margin, the region between the
225 actual top and bottom margin is scrolled up.
226*/
227
228void TEScreen::NextLine()
229//=NEL
230{
231 Return(); index();
232}
233
234// Line Editing ----------------------------------------------------------------
235
236/*! \section inserting / deleting characters
237*/
238
239/*! erase `n' characters starting from (including) the cursor position.
240
241 The line is filled in from the right with spaces.
242*/
243
244void TEScreen::eraseChars(int n)
245{
246 if (n == 0) n = 1; // Default
247 int p = QMAX(0,QMIN(cuX+n-1,columns-1));
248 clearImage(loc(cuX,cuY),loc(p,cuY),' ');
249}
250
251/*! delete `n' characters starting from (including) the cursor position.
252
253 The line is filled in from the right with spaces.
254*/
255
256void TEScreen::deleteChars(int n)
257{
258 if (n == 0) n = 1; // Default
259 int p = QMAX(0,QMIN(cuX+n,columns-1));
260 moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
261 clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
262}
263
264/*! insert `n' spaces at the cursor position.
265
266 The cursor is not moved by the operation.
267*/
268
269void TEScreen::insertChars(int n)
270{
271 if (n == 0) n = 1; // Default
272 int p = QMAX(0,QMIN(columns-1-n,columns-1));
273 int q = QMAX(0,QMIN(cuX+n,columns-1));
274 moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
275 clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
276}
277
278/*! delete `n' lines starting from (including) the cursor position.
279
280 The cursor is not moved by the operation.
281*/
282
283void TEScreen::deleteLines(int n)
284{
285 if (n == 0) n = 1; // Default
286 scrollUp(cuY,n);
287}
288
289/*! insert `n' lines at the cursor position.
290
291 The cursor is not moved by the operation.
292*/
293
294void TEScreen::insertLines(int n)
295{
296 if (n == 0) n = 1; // Default
297 scrollDown(cuY,n);
298}
299
300// Mode Operations -----------------------------------------------------------
301
302/*! Set a specific mode. */
303
304void TEScreen::setMode(int m)
305{
306 currParm.mode[m] = TRUE;
307 switch(m)
308 {
309 case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
310 }
311}
312
313/*! Reset a specific mode. */
314
315void TEScreen::resetMode(int m)
316{
317 currParm.mode[m] = FALSE;
318 switch(m)
319 {
320 case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
321 }
322}
323
324/*! Save a specific mode. */
325
326void TEScreen::saveMode(int m)
327{
328 saveParm.mode[m] = currParm.mode[m];
329}
330
331/*! Restore a specific mode. */
332
333void TEScreen::restoreMode(int m)
334{
335 currParm.mode[m] = saveParm.mode[m];
336}
337
338//NOTE: this is a helper function
339/*! Return the setting a specific mode. */
340BOOL TEScreen::getMode(int m)
341{
342 return currParm.mode[m];
343}
344
345/*! Save the cursor position and the rendition attribute settings. */
346
347void TEScreen::saveCursor()
348{
349 sa_cuX = cuX;
350 sa_cuY = cuY;
351 sa_cu_re = cu_re;
352 sa_cu_fg = cu_fg;
353 sa_cu_bg = cu_bg;
354}
355
356/*! Restore the cursor position and the rendition attribute settings. */
357
358void TEScreen::restoreCursor()
359{
360 cuX = QMIN(sa_cuX,columns-1);
361 cuY = QMIN(sa_cuY,lines-1);
362 cu_re = sa_cu_re;
363 cu_fg = sa_cu_fg;
364 cu_bg = sa_cu_bg;
365 effectiveRendition();
366}
367
368/* ------------------------------------------------------------------------- */
369/* */
370/* Screen Operations */
371/* */
372/* ------------------------------------------------------------------------- */
373
374/*! Assing a new size to the screen.
375
376 The topmost left position is maintained, while lower lines
377 or right hand side columns might be removed or filled with
378 spaces to fit the new size.
379
380 The region setting is reset to the whole screen and the
381 tab positions reinitialized.
382*/
383
384void TEScreen::resizeImage(int new_lines, int new_columns)
385{
386
387 if (cuY > new_lines-1)
388 { // attempt to preserve focus and lines
389 bmargin = lines-1; //FIXME: margin lost
390 for (int i = 0; i < cuY-(new_lines-1); i++)
391 {
392 addHistLine(); scrollUp(0,1);
393 }
394 }
395
396 // make new image
397 ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
398
399 clearSelection();
400
401 // clear new image
402 for (int y = 0; y < new_lines; y++)
403 for (int x = 0; x < new_columns; x++)
404 {
405 newimg[y*new_columns+x].c = ' ';
406 newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
407 newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
408 newimg[y*new_columns+x].r = DEFAULT_RENDITION;
409 }
410 int cpy_lines = QMIN(new_lines, lines);
411 int cpy_columns = QMIN(new_columns,columns);
412 // copy to new image
413 for (int y = 0; y < cpy_lines; y++)
414 for (int x = 0; x < cpy_columns; x++)
415 {
416 newimg[y*new_columns+x].c = image[loc(x,y)].c;
417 newimg[y*new_columns+x].f = image[loc(x,y)].f;
418 newimg[y*new_columns+x].b = image[loc(x,y)].b;
419 newimg[y*new_columns+x].r = image[loc(x,y)].r;
420 }
421 free(image);
422 image = newimg;
423 lines = new_lines;
424 columns = new_columns;
425 cuX = QMIN(cuX,columns-1);
426 cuY = QMIN(cuY,lines-1);
427
428 // FIXME: try to keep values, evtl.
429 tmargin=0;
430 bmargin=lines-1;
431 initTabStops();
432 clearSelection();
433}
434
435/*
436 Clarifying rendition here and in TEWidget.
437
438 currently, TEWidget's color table is
439 0 1 2 .. 9 10 .. 17
440 dft_fg, dft_bg, dim 0..7, intensive 0..7
441
442 cu_fg, cu_bg contain values 0..8;
443 - 0 = default color
444 - 1..8 = ansi specified color
445
446 re_fg, re_bg contain values 0..17
447 due to the TEWidget's color table
448
449 rendition attributes are
450
451 attr widget screen
452 -------------- ------ ------
453 RE_UNDERLINE XX XX affects foreground only
454 RE_BLINK XX XX affects foreground only
455 RE_BOLD XX XX affects foreground only
456 RE_REVERSE -- XX
457 RE_TRANSPARENT XX -- affects background only
458 RE_INTENSIVE XX -- affects foreground only
459
460 Note that RE_BOLD is used in both widget
461 and screen rendition. Since xterm/vt102
462 is to poor to distinguish between bold
463 (which is a font attribute) and intensive
464 (which is a color attribute), we translate
465 this and RE_BOLD in falls eventually appart
466 into RE_BOLD and RE_INTENSIVE.
467*/
468
469void TEScreen::reverseRendition(ca* p)
470{ UINT8 f = p->f; UINT8 b = p->b;
471 p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
472}
473
474void TEScreen::effectiveRendition()
475// calculate rendition
476{
477 ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
478 if (cu_re & RE_REVERSE)
479 {
480 ef_fg = cu_bg;
481 ef_bg = cu_fg;
482 }
483 else
484 {
485 ef_fg = cu_fg;
486 ef_bg = cu_bg;
487 }
488 if (cu_re & RE_BOLD)
489 {
490 if (ef_fg < BASE_COLORS)
491 ef_fg += BASE_COLORS;
492 else
493 ef_fg -= BASE_COLORS;
494 }
495}
496
497/*!
498 returns the image.
499
500 Get the size of the image by \sa getLines and \sa getColumns.
501
502 NOTE that the image returned by this function must later be
503 freed.
504
505*/
506
507ca* TEScreen::getCookedImage()
508{ int x,y;
509 ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
510 ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
511
512 for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
513 {
514 int len = QMIN(columns,hist.getLineLen(y+histCursor));
515 int yp = y*columns;
516 int yq = (y+histCursor)*columns;
517
518 hist.getCells(y+histCursor,0,len,merged+yp);
519 for (x = len; x < columns; x++) merged[yp+x] = dft;
520 for (x = 0; x < columns; x++)
521 { int p=x + yp; int q=x + yq;
522 if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
523 reverseRendition(&merged[p]); // for selection
524 }
525 }
526 if (lines >= hist.getLines()-histCursor)
527 {
528 for (y = (hist.getLines()-histCursor); y < lines ; y++)
529 {
530 int yp = y*columns;
531 int yq = (y+histCursor)*columns;
532 int yr = (y-hist.getLines()+histCursor)*columns;
533 for (x = 0; x < columns; x++)
534 { int p = x + yp; int q = x + yq; int r = x + yr;
535 merged[p] = image[r];
536 if ( q >= sel_TL && q <= sel_BR )
537 reverseRendition(&merged[p]); // for selection
538 }
539
540 }
541 }
542 // evtl. inverse display
543 if (getMode(MODE_Screen))
544 { int i,n = lines*columns;
545 for (i = 0; i < n; i++)
546 reverseRendition(&merged[i]); // for reverse display
547 }
548 if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
549 reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
550 return merged;
551}
552
553
554/*!
555*/
556
557void TEScreen::reset()
558{
559 setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
560 resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
561 resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
562 setMode(MODE_Cursor); // cursor visible
563 resetMode(MODE_Screen); // screen not inverse
564 resetMode(MODE_NewLine);
565
566 tmargin=0;
567 bmargin=lines-1;
568
569 setDefaultRendition();
570 saveCursor();
571
572 clear();
573}
574
575/*! Clear the entire screen and home the cursor.
576*/
577
578void TEScreen::clear()
579{
580 clearEntireScreen();
581 home();
582}
583
584/*! Moves the cursor left one column.
585*/
586
587void TEScreen::BackSpace()
588{
589 cuX = QMAX(0,cuX-1);
590 if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
591}
592
593/*!
594*/
595
596void TEScreen::Tabulate()
597{
598 // note that TAB is a format effector (does not write ' ');
599 cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
600}
601
602void TEScreen::clearTabStops()
603{
604 for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
605}
606
607void TEScreen::changeTabStop(bool set)
608{
609 if (cuX >= columns) return;
610 tabstops[cuX] = set;
611}
612
613void TEScreen::initTabStops()
614{
615 if (tabstops) free(tabstops);
616 tabstops = (bool*)malloc(columns*sizeof(bool));
617 // Arrg! The 1st tabstop has to be one longer than the other.
618 // i.e. the kids start counting from 0 instead of 1.
619 // Other programs might behave correctly. Be aware.
620 for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
621}
622
623/*!
624 This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
625 depending on the NewLine Mode (LNM). This mode also
626 affects the key sequence returned for newline ([CR]LF).
627*/
628
629void TEScreen::NewLine()
630{
631 if (getMode(MODE_NewLine)) Return();
632 index();
633}
634
635/*! put `c' literally onto the screen at the current cursor position.
636
637 VT100 uses the convention to produce an automatic newline (am)
638 with the *first* character that would fall onto the next line (xenl).
639*/
640
641void TEScreen::checkSelection(int from, int to)
642{
643 if (sel_begin == -1) return;
644 int scr_TL = loc(0, hist.getLines());
645 //Clear entire selection if it overlaps region [from, to]
646 if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
647 {
648 clearSelection();
649 }
650}
651
652void TEScreen::ShowCharacter(unsigned short c)
653{
654 // Note that VT100 does wrapping BEFORE putting the character.
655 // This has impact on the assumption of valid cursor positions.
656 // We indicate the fact that a newline has to be triggered by
657 // putting the cursor one right to the last column of the screen.
658
659 if (cuX >= columns)
660 {
661 if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
662 }
663
664 if (getMode(MODE_Insert)) insertChars(1);
665
666 int i = loc(cuX,cuY);
667
668 checkSelection(i, i); // check if selection is still valid.
669
670 image[i].c = c;
671 image[i].f = ef_fg;
672 image[i].b = ef_bg;
673 image[i].r = ef_re;
674
675 cuX += 1;
676}
677
678// Region commands -------------------------------------------------------------
679
680
681/*! scroll up `n' lines within current region.
682 The `n' new lines are cleared.
683 \sa setRegion \sa scrollDown
684*/
685
686void TEScreen::scrollUp(int from, int n)
687{
688 if (n <= 0 || from + n > bmargin) return;
689 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
690 moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
691 clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
692}
693
694/*! scroll down `n' lines within current region.
695 The `n' new lines are cleared.
696 \sa setRegion \sa scrollUp
697*/
698
699void TEScreen::scrollDown(int from, int n)
700{
701//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
702 if (n <= 0) return;
703 if (from > bmargin) return;
704 if (from + n > bmargin) n = bmargin - from;
705 moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
706 clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
707}
708
709/*! position the cursor to a specific line and column. */
710void TEScreen::setCursorYX(int y, int x)
711{
712 setCursorY(y); setCursorX(x);
713}
714
715/*! Set the cursor to x-th line. */
716
717void TEScreen::setCursorX(int x)
718{
719 if (x == 0) x = 1; // Default
720 x -= 1; // Adjust
721 cuX = QMAX(0,QMIN(columns-1, x));
722}
723
724/*! Set the cursor to y-th line. */
725
726void TEScreen::setCursorY(int y)
727{
728 if (y == 0) y = 1; // Default
729 y -= 1; // Adjust
730 cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
731}
732
733/*! set cursor to the `left upper' corner of the screen (1,1).
734*/
735
736void TEScreen::home()
737{
738 cuX = 0;
739 cuY = 0;
740}
741
742/*! set cursor to the begin of the current line.
743*/
744
745void TEScreen::Return()
746{
747 cuX = 0;
748}
749
750/*! returns the current cursor columns.
751*/
752
753int TEScreen::getCursorX()
754{
755 return cuX;
756}
757
758/*! returns the current cursor line.
759*/
760
761int TEScreen::getCursorY()
762{
763 return cuY;
764}
765
766// Erasing ---------------------------------------------------------------------
767
768/*! \section Erasing
769
770 This group of operations erase parts of the screen contents by filling
771 it with spaces colored due to the current rendition settings.
772
773 Althought the cursor position is involved in most of these operations,
774 it is never modified by them.
775*/
776
777/*! fill screen between (including) `loca' and `loce' with spaces.
778
779 This is an internal helper functions. The parameter types are internal
780 addresses of within the screen image and make use of the way how the
781 screen matrix is mapped to the image vector.
782*/
783
784void TEScreen::clearImage(int loca, int loce, char c)
785{ int i;
786 int scr_TL=loc(0,hist.getLines());
787 //FIXME: check positions
788
789 //Clear entire selection if it overlaps region to be moved...
790 if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
791 {
792 clearSelection();
793 }
794 for (i = loca; i <= loce; i++)
795 {
796 image[i].c = c;
797 image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
798 image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
799 image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
800 }
801}
802
803/*! move image between (including) `loca' and `loce' to 'dst'.
804
805 This is an internal helper functions. The parameter types are internal
806 addresses of within the screen image and make use of the way how the
807 screen matrix is mapped to the image vector.
808*/
809
810void TEScreen::moveImage(int dst, int loca, int loce)
811{
812//FIXME: check positions
813 if (loce < loca) {
814 // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
815 return;
816 }
817 memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
818}
819
820/*! clear from (including) current cursor position to end of screen.
821*/
822
823void TEScreen::clearToEndOfScreen()
824{
825 clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
826}
827
828/*! clear from begin of screen to (including) current cursor position.
829*/
830
831void TEScreen::clearToBeginOfScreen()
832{
833 clearImage(loc(0,0),loc(cuX,cuY),' ');
834}
835
836/*! clear the entire screen.
837*/
838
839void TEScreen::clearEntireScreen()
840{
841 clearImage(loc(0,0),loc(columns-1,lines-1),' ');
842}
843
844/*! fill screen with 'E'
845 This is to aid screen alignment
846*/
847
848void TEScreen::helpAlign()
849{
850 clearImage(loc(0,0),loc(columns-1,lines-1),'E');
851}
852
853/*! clear from (including) current cursor position to end of current cursor line.
854*/
855
856void TEScreen::clearToEndOfLine()
857{
858 clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
859}
860
861/*! clear from begin of current cursor line to (including) current cursor position.
862*/
863
864void TEScreen::clearToBeginOfLine()
865{
866 clearImage(loc(0,cuY),loc(cuX,cuY),' ');
867}
868
869/*! clears entire current cursor line
870*/
871
872void TEScreen::clearEntireLine()
873{
874 clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
875}
876
877// Rendition ------------------------------------------------------------------
878
879/*!
880 set rendition mode
881*/
882
883void TEScreen::setRendition(int re)
884{
885 cu_re |= re;
886 effectiveRendition();
887}
888
889/*!
890 reset rendition mode
891*/
892
893void TEScreen::resetRendition(int re)
894{
895 cu_re &= ~re;
896 effectiveRendition();
897}
898
899/*!
900*/
901
902void TEScreen::setDefaultRendition()
903{
904 setForeColorToDefault();
905 setBackColorToDefault();
906 cu_re = DEFAULT_RENDITION;
907 effectiveRendition();
908}
909
910/*!
911*/
912
913void TEScreen::setForeColor(int fgcolor)
914{
915 cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
916 effectiveRendition();
917}
918
919/*!
920*/
921
922void TEScreen::setBackColor(int bgcolor)
923{
924 cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
925 effectiveRendition();
926}
927
928/*!
929*/
930
931void TEScreen::setBackColorToDefault()
932{
933 cu_bg = DEFAULT_BACK_COLOR;
934 effectiveRendition();
935}
936
937/*!
938*/
939
940void TEScreen::setForeColorToDefault()
941{
942 cu_fg = DEFAULT_FORE_COLOR;
943 effectiveRendition();
944}
945
946/* ------------------------------------------------------------------------- */
947/* */
948/* Marking & Selection */
949/* */
950/* ------------------------------------------------------------------------- */
951
952void TEScreen::clearSelection()
953{
954 sel_BR = -1;
955 sel_TL = -1;
956 sel_begin = -1;
957}
958
959void TEScreen::setSelBeginXY(const int x, const int y)
960{
961 sel_begin = loc(x,y+histCursor) ;
962 sel_BR = sel_begin;
963 sel_TL = sel_begin;
964}
965
966void TEScreen::setSelExtentXY(const int x, const int y)
967{
968 if (sel_begin == -1) return;
969 int l = loc(x,y + histCursor);
970
971 if (l < sel_begin)
972 {
973 sel_TL = l;
974 sel_BR = sel_begin;
975 }
976 else
977 {
978 /* FIXME, HACK to correct for x too far to the right... */
979 if (( x == columns )|| (x == 0)) l--;
980
981 sel_TL = sel_begin;
982 sel_BR = l;
983 }
984}
985
986QString TEScreen::getSelText(const BOOL preserve_line_breaks)
987{
988 if (sel_begin == -1)
989 return QString::null; // Selection got clear while selecting.
990
991 int *m; // buffer to fill.
992 int s, d; // source index, dest. index.
993 int hist_BR = loc(0, hist.getLines());
994 int hY = sel_TL / columns;
995 int hX = sel_TL % columns;
996 int eol; // end of line
997
998 s = sel_TL; // tracks copy in source.
999
1000 // allocate buffer for maximum
1001 // possible size...
1002 d = (sel_BR - sel_TL) / columns + 1;
1003 m = new int[d * (columns + 1) + 2];
1004 d = 0;
1005
1006 while (s <= sel_BR)
1007 {
1008 if (s < hist_BR)
1009 { // get lines from hist.history
1010 // buffer.
1011 eol = hist.getLineLen(hY);
1012
1013 if ((hY == (sel_BR / columns)) &&
1014 (eol >= (sel_BR % columns)))
1015 {
1016 eol = sel_BR % columns + 1;
1017 }
1018
1019 while (hX < eol)
1020 {
1021 m[d++] = hist.getCell(hY, hX++).c;
1022 s++;
1023 }
1024
1025 if (s <= sel_BR)
1026 {
1027 // The line break handling
1028 // It's different from the screen
1029 // image case!
1030 if (eol % columns == 0)
1031 {
1032 // That's either a completely filled
1033 // line or an empty line
1034 if (eol == 0)
1035 {
1036 m[d++] = '\n';
1037 }
1038 else
1039 {
1040 // We have a full line.
1041 // FIXME: How can we handle newlines
1042 // at this position?!
1043 }
1044 }
1045 else if ((eol + 1) % columns == 0)
1046 {
1047 // FIXME: We don't know if this was a
1048 // space at the last position or a
1049 // short line!!
1050 m[d++] = ' ';
1051 }
1052 else
1053 {
1054 // We have a short line here. Put a
1055 // newline or a space into the
1056 // buffer.
1057 m[d++] = preserve_line_breaks ? '\n' : ' ';
1058 }
1059 }
1060
1061 hY++;
1062 hX = 0;
1063 s = hY * columns;
1064 }
1065 else
1066 { // or from screen image.
1067 eol = (s / columns + 1) * columns - 1;
1068
1069 if (eol < sel_BR)
1070 {
1071 while ((eol > s) &&
1072 isspace(image[eol - hist_BR].c))
1073 {
1074 eol--;
1075 }
1076 }
1077 else
1078 {
1079 eol = sel_BR;
1080 }
1081
1082 while (s <= eol)
1083 {
1084 m[d++] = image[s++ - hist_BR].c;
1085 }
1086
1087 if (eol < sel_BR)
1088 {
1089 // eol processing see below ...
1090 if ((eol + 1) % columns == 0)
1091 {
1092 if (image[eol - hist_BR].c == ' ')
1093 {
1094 m[d++] = ' ';
1095 }
1096 }
1097 else
1098 {
1099 m[d++] = ((preserve_line_breaks ||
1100 ((eol % columns) == 0)) ?
1101 '\n' : ' ');
1102 }
1103 }
1104
1105 s = (eol / columns + 1) * columns;
1106 }
1107 }
1108
1109 QChar* qc = new QChar[d];
1110
1111 for (int i = 0; i < d; i++)
1112 {
1113 qc[i] = m[i];
1114 }
1115
1116 QString res(qc, d);
1117
1118 delete m;
1119 delete qc;
1120
1121 return res;
1122}
1123/* above ... end of line processing for selection -- psilva
1124cases:
1125
11261) (eol+1)%columns == 0 --> the whole line is filled.
1127 If the last char is a space, insert (preserve) space. otherwise
1128 leave the text alone, so that words that are broken by linewrap
1129 are preserved.
1130
1131FIXME:
1132 * this suppresses \n for command output that is
1133 sized to the exact column width of the screen.
1134
11352) eol%columns == 0 --> blank line.
1136 insert a \n unconditionally.
1137 Do it either you would because you are in preserve_line_break mode,
1138 or because it's an ASCII paragraph delimiter, so even when
1139 not preserving line_breaks, you want to preserve paragraph breaks.
1140
1141 3) else --> partially filled line
1142 insert a \n in preserve line break mode, else a space
1143 The space prevents concatenation of the last word of one
1144 line with the first of the next.
1145
1146*/
1147
1148void TEScreen::addHistLine()
1149{
1150 assert(hasScroll() || histCursor == 0);
1151
1152 // add to hist buffer
1153 // we have to take care about scrolling, too...
1154
1155 if (hasScroll())
1156 { ca dft;
1157
1158 int end = columns-1;
1159 while (end >= 0 && image[end] == dft)
1160 end -= 1;
1161
1162 hist.addCells(image,end+1);
1163 hist.addLine();
1164
1165 // adjust history cursor
1166 histCursor += (hist.getLines()-1 == histCursor);
1167 }
1168
1169 if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
1170}
1171
1172void TEScreen::setHistCursor(int cursor)
1173{
1174 histCursor = cursor; //FIXME:rangecheck
1175}
1176
1177int TEScreen::getHistCursor()
1178{
1179 return histCursor;
1180}
1181
1182int TEScreen::getHistLines()
1183{
1184 return hist.getLines();
1185}
1186
1187void TEScreen::setScroll(bool on)
1188{
1189 histCursor = 0;
1190 clearSelection();
1191 hist.setScroll(on);
1192}
1193
1194bool TEScreen::hasScroll()
1195{
1196 return hist.hasScroll();
1197}