1
// vi:ts=4:shiftwidth=4:expandtab
2
/***************************************************************************
3
console.cpp - description
5
begin : Sun Mar 18 2001
6
copyright : (C) 2001 by ejoy
7
email : ejoy@users.sourceforge.net
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
25
int Console::mColorTable[16] =
26
{ 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 };
28
Console::Console(int x1, int y1, int x2, int y2)
29
:Window(x1, y1, x2, y2, WS_DEF), // set window console pointer
36
mConMaxCols = mMaxCols;
37
mConMaxRows = mMaxRows;
40
int size = mMaxCols * mMaxRows;
41
mpSavTextBuf = new char[size];
42
mpSavAttrBuf = new char[size];
43
mpSavFlagBuf = new char[size];
49
size = mMaxCols * HISTORY_LINES;
50
mpHistText = new char[size];
51
mpHistAttr = new char[size];
52
mpHistFlag = new char[size];
53
memset(mpHistText, ' ', size);
54
memset(mpHistAttr, mAttr, size);
55
memset(mpHistFlag, txtASCII | txtUpdated, size);
58
mMouseMask = 0x77; // 0x80 when mono
60
mSelStart = -1; // cleared by clear_selection
68
delete[] mpSavTextBuf;
69
delete[] mpSavAttrBuf;
70
delete[] mpSavFlagBuf;
74
/** handle ansi esc command */
75
void Console::DoEscape(char c) {
77
if (mEscIntro == '\0') {
87
case 'H': // Set Tab <ESC>H
88
mTabStop[Row() >> 5] |= (1 << (Row() & 31));
90
case 'M': // Reverse Index,Scroll Up
91
case 'T': // FreeBSD, cons25
92
if (Row() == mScrollStart)
95
ConGoto(Col(), Row() - 1);
100
// Redraw(); // why need? called by write
108
case '7': // Save Cursor & Attrs <ESC>7
111
case '8': // Restore Cursor & Attrs <ESC>8
118
else if (mEscIntro == '[') {
122
num = mpEscParam - mEscParam + 1;
124
case 'A': // Restore Cursor & Attrs <ESC>8
127
ConGoto(Col(), Row() - mEscParam[0]);
129
case 'B': // Cursor Down <ESC>[{COUNT}B
133
ConGoto(Col(), Row() + mEscParam[0]);
135
case 'C': // Cursor Forward <ESC>[{COUNT}C
139
ConGoto(Col() + mEscParam[0], Row());
141
case 'D': // Cursor Backward <ESC>[{COUNT}D
144
ConGoto(Col() - mEscParam[0], Row());
149
ConGoto(0, Row() + mEscParam[0]);
154
ConGoto(0, Row() - mEscParam[0]);
156
case 'G': // Cursor Horizontal Absolute
160
ConGoto(mEscParam[0], Row());
162
case 'H': // ESC [m;nH moves cursor to (m,n)
168
AbsGoto(mEscParam[1], mEscParam[0]);
170
case 'J': // ESC [sJ clears in display
171
switch (mEscParam[0]) {
172
case 0: // clear from cursor to end of screen
173
Clear(Col(), Row(), mConEndCol, Row(), mAttr);
174
if (Row() < mConEndRow)
175
Clear(0, Row() + 1, mConEndCol, mConEndRow, mAttr);
177
case 1: // clear from start to cursor
178
Clear(0, Row(), Col(), Row(), mAttr);
180
Clear(0, 0, mConEndCol, Row() - 1, mAttr);
182
case 2: // clear whole screen
183
Clear(0, 0, mConEndCol, mConEndRow, mAttr);
185
default: // do nothing
190
case 'K': // ESC [sK clears lines from cursor
191
switch (mEscParam[0]) {
192
case 0: // clear from cursor to end of line
193
Clear(Col(), Row(), mConEndCol, Row(), mAttr);
195
case 1: // clear from beinning of line to cursor
196
Clear(0, Row(), Col(), Row(), mAttr);
198
case 2: // clear whole line
199
Clear(0, Row(), mConEndCol, Row(), mAttr);
201
default: // do nothing
206
case 'L': // ESC [nL inserts n lines at cursor
207
InsertLine(mEscParam[0]);
209
case 'M': // ESC [nM deletes n lines at cursor
210
DeleteLine(mEscParam[0]);
212
case 'P': // ESC [nP deletes n chars at cursor
213
DeleteChar(mEscParam[0]);
217
int n = mEscParam[0];
221
Col() + n > mConEndCol ? mConEndCol : Col() + n,
227
case '@': // ESC [n@ insert n chars at cursor
228
InsertBlank(mEscParam[0]);
236
SetCursorType(mEscParam[0] | (mEscParam[1]<<8) | (mEscParam[2]<<16));
238
SetCursorType(CUR_DEFAULT);
244
AbsGoto(Col(), mEscParam[0]);
246
case 'g': // Clear Tab <ESC>[{3}g
248
mTabStop[Col() >> 5] &= ~(1 << (Col() & 31));
249
else if (mEscParam[0] == 3)
250
fill_n(mTabStop, 5, 0);
258
case 'm': // ESC [nm set attribute
259
for (int i = 0; i < num; i++) {
260
int value = mEscParam[i];
283
/* ANSI X3.64-1979 (SCO-ish?)
284
* Select primary font, don't display
285
* control chars if defined, don't set
291
/* ANSI X3.64-1979 (SCO-ish?)
292
* Select first alternate font, lets
293
* chars < 32 be displayed as ROM chars.
298
/* ANSI X3.64-1979 (SCO-ish?)
299
* Select second alternate font, toggle
300
* high bit before displaying as ROM char.
317
/* ANSI X3.64-1979 (SCO-ish?)
318
* Enables underscore, white foreground
319
* with white underscore (Linux - use
320
* default foreground).
322
mColor = BuildColor(FgColor(mDefColor),BgColor(mColor));
326
/* ANSI X3.64-1979 (SCO-ish?)
327
* Disable underline option.
328
* Reset colour to default? It did this
331
mColor = BuildColor(FgColor(mDefColor),BgColor(mColor));
335
mColor = BuildColor(FgColor(mColor),BgColor(mDefColor));
339
if (value >= 30 && value <= 37)
340
mColor = BuildColor(mColorTable[(value - 30)],
342
else if (value >= 40 && value <= 47)
343
mColor = BuildColor(FgColor(mColor),
344
mColorTable[(value - 40)]);
353
case 'n': // not implemented
356
case 'p': // Define Key
357
assert(!"Define Key not implemented yet!");
362
case 'r': // set scrolling range
366
mEscParam[1] = mConMaxRows;
367
/* Minimum allowed region is 2 lines */
368
if (mEscParam[0] < mEscParam[1] &&
369
mEscParam[1] <= mConMaxRows) {
370
mScrollStart = mEscParam[0] - 1;
371
mScrollEnd = mEscParam[1];
375
case 's': // Save Cursor <ESC>[s
378
case 'u': // Unsave Cursor <ESC>[u
382
else if (mEscIntro == ']') {
388
void Console::ParseEscape(char c) {
391
mEscIntro = '\0'; //ESC seen
392
mEscQuestion = false;
393
mpEscParam = mEscParam;
394
for (int i = 0; i < MAX_ESC_PARAMS; i++)
397
case '#': // DEC obsolete hacks
398
//anyone want to implement them?
400
case '[': //control sequence introducer
408
case '%': // unfinished
411
case '(': //Char Set G0
412
case ')': //Char Set G1
414
//charset change not implemented
420
case SQUARE: //ESC [ seen
423
else if (c >= '0' && c <= '9') {
424
if (mpEscParam < mEscParam + MAX_ESC_PARAMS)
425
*mpEscParam = *mpEscParam * 10 + (c - '0');
428
if (++mpEscParam < mEscParam + MAX_ESC_PARAMS)
444
void Console::SendChar(char c) {
447
//restore saved Buffer
448
memcpy(mpText, mpSavTextBuf, mConMaxCols * mConMaxRows);
449
memcpy(mpAttr, mpSavAttrBuf, mConMaxCols * mConMaxRows);
451
// Redraw(); // why need? called by write
458
assert(mInsertMode == false);
459
if (mCharSet == PRIMARY) {
460
// txtDblCode could be code1, code2, even ASCII
461
// It will be identified in UpdateScreen()
462
if (gpDecoder->IsCode1(c) || gpDecoder->IsCode2(c)) {
463
PutChar(mAttr,txtDblCode | txtPrimary | txtUpdated,c);
465
PutChar(mAttr,txtASCII | txtPrimary | txtUpdated,c);
468
else { // always table line char
469
PutChar(mAttr,txtASCII | txtUpdated,c);
473
if (Col() == mConEndCol)
474
mNeedWrap = mAutoWrap;
476
Goto(Col() + 1, Row());
479
//#include <sys/time.h>
480
//#include <sys/types.h>
481
//#include <unistd.h> //for debug
482
/** Write num chars in pBuf to console */
483
void Console::Write(const char *pBuf, int num) {
484
SelClear(); // hide mouse
485
bool isCursorOn = CursorOnOff();
486
// turn off cursor for rapid display
487
if (isCursorOn) CursorHide();
490
for (; num; pBuf++, num--) {
493
if (mEscState != NORMAL)
502
// struct timeval tv;
505
// tv.tv_usec = 10000; // 0.1 sec
506
// select(FD_SETSIZE, &set, NULL, NULL, &tv);
511
if (isCursorOn) CursorShow();
514
/** do ANSI control function */
515
void Console::DoControl(char c) {
525
Goto(Col()-1, Row());
531
while (Col() < mConEndCol) {
532
Goto(Col() + 1, Row());
533
if (mTabStop[Col() >> 5] & (1 << (Col() & 31)))
547
//translate = set_translate(G1_charset,currcons);
552
//translate = set_translate(G0_charset,currcons);
555
case 24://graph arrows
557
assert(mEscState == NORMAL);
570
break;//assert(!"unknown control char reached!");
572
//send out unknown control char
576
//Copy lines from r1 to r2
577
void Console::CopyLines(int r1, int r2, int count) {
578
assert(r1 >= 0 && r1 < mMaxRows && r2 >= 0 && r2 < mMaxRows);
579
if (count == 0 || r1 == r2)
586
if (r2 + count < mConMaxRows)
587
n = count * mConMaxCols;
589
n = (mConMaxRows - r2) * mConMaxCols;
591
memmove(&mpText[di], &mpText[si], n);
592
memmove(&mpAttr[di], &mpAttr[si], n);
593
memmove(&mpFlag[di], &mpFlag[si], n);
594
for (int i = 0; i < n; i++)
595
mpFlag[di + i] |= txtUpdated;
598
//insert n blank line at cursor
599
void Console::InsertLine(int n) {
600
assert(Row() + 1 <= mScrollEnd && Row() >= mScrollStart);
603
if (n > mScrollEnd - Row())
604
n = mScrollEnd - Row();
606
CopyLines(Row(), Row() + n, mScrollEnd - Row() - n);
607
Clear(0, Row(), mConEndCol, Row() + n - 1, mAttr);
611
//delete n lines at cursor
613
void Console::DeleteLine(int n) {
614
assert(Row() + 1 <= mScrollEnd && Row() >= mScrollStart);
618
if (n > mScrollEnd - Row())
619
n = mScrollEnd - Row();
621
CopyLines(Row() + n, Row(), mScrollEnd - Row() - n);
622
Clear(0, mScrollEnd - n, mConEndCol, mScrollEnd - 1, mAttr);
626
//insert n blank char at current position
627
void Console::InsertBlank(int n) {
630
if (Col() + n > mConEndCol)
631
n = mConEndCol - Col();
633
int count = mConEndCol - (Col() - 1) - n;
634
for (int s = mConEndCol - n, d = mConEndCol; count--;)
635
CopyChar(s--, Row(), d--, Row());
636
Clear(Col(), Row(), Col() + n - 1, Row(), mAttr);
640
//delete n chars at current position
641
//append blank char at the end of line
642
void Console::DeleteChar(int n) {
645
if (Col() + n > mConEndCol)
646
n = mConEndCol - Col();
648
int count = mConEndCol - (Col() - 1) - n;
649
for (int d = Col(), s = d + n; count--;) {
650
assert(s <= mEndCol);
651
CopyChar(s++, Row(), d++, Row());
654
Clear(mConEndCol - n + 1, Row(), mConEndCol, Row(), mAttr);
658
//copy a char from (r1,c1) to (r2,c2)
659
void Console::CopyChar(int c1, int r1, int c2, int r2) {
660
assert(r1 >= 0 && r1 <= mEndRow && r2 >= 0 && r2 <= mEndRow);
665
mpText[di] = mpText[si];
666
mpAttr[di] = mpAttr[si];
667
mpFlag[di] = mpFlag[si] | txtUpdated;
670
//scroll screen up or down one line
671
//in view: [mScrollStart,mScrollEnd)
672
void Console::ScrollScr(DIR dir) {
673
assert(mScrollEnd > mScrollStart);
675
int count = (mScrollEnd - mScrollStart - 1) * mConMaxCols;
679
si = (mScrollStart + 1) * mConMaxCols;
680
di = si - mConMaxCols;
681
blank = mScrollEnd - 1;
685
si = mScrollStart * mConMaxCols;
686
di = si + mConMaxCols;
687
blank = mScrollStart;
690
memmove(&mpText[di], &mpText[si], count);
691
memmove(&mpAttr[di], &mpAttr[si], count);
692
memmove(&mpFlag[di], &mpFlag[si], count);
693
for (int i = 0; i < count; i++)
694
mpFlag[di + i] |= txtUpdated;
695
Clear(0, blank, mConEndCol, blank, mAttr);
698
void Console::DefaultAttr() {
706
void Console::Reset() {
709
mTabStop[0] = 0x01010100;
710
mTabStop[1] = mTabStop[2] = mTabStop[3] = mTabStop[4] = 0x01010101;
711
mEscQuestion = false;
718
mScrollEnd = mConMaxRows;
720
int size = mConMaxCols * mConMaxRows;
721
memset(mpText, ' ', size);
722
memset(mpAttr, mAttr, size);
723
memset(mpFlag, txtASCII | txtUpdated, size);
727
void Console::SaveCursor() {
732
mOldUnderline = mUnderline;
733
mOldIntensity = mIntensity;
734
mOldReverse = mReverse;
735
mOldCharSet = mCharSet;
738
void Console::UnSaveCursor() {
739
ConGoto(mOldCol, mOldRow);
742
mUnderline = mOldUnderline;
744
mReverse = mOldReverse;
745
mCharSet = mOldCharSet;
750
void Console::SetMode(bool f) {
752
switch (mEscParam[0]) {
753
/* DEC private modes set/reset */
754
case 1: /* Cursor keys send ^[Ox/^[[x */
755
assert(!"set_dec_cursor_keys(tty, on_off)");
757
case 3: /* 80/132 mode switch unimplemented */
760
/* soft scroll/Jump scroll toggle, unimplemented yet */
762
case 5: /* Inverted screen on/off */
768
case 7: /* Autowrap on/off */
770
case 8: /* Autorepeat on/off not implemented yet */
772
case 25: /* Cursor on/off */
781
switch (mEscParam[0]) {
782
/* ANSI modes set/reset */
783
case 4: /* Insert Mode on/off */
787
case 20: /* Lf, Enter == CrLf/Lf */
788
// set_lf_mode(tty, on_off);
789
assert(!"Lf, Enter == CrLf/Lf");
794
void Console::ConGoto(int c, int r) {
798
else if (c > mConEndCol)
806
min_y = mScrollStart;
823
//for absolute user moves, when decom is set
824
void Console::AbsGoto(int c, int r) {
825
ConGoto(c, mDecom ? (mScrollStart + r) : r);
829
/* don't scroll if above bottom of scrolling region, or
830
* if below scrolling region
832
if (Row() + 1 == mScrollEnd)
834
else if (Row() < mConEndRow)
835
Goto(Col(), Row() + 1);
844
//push top line into history buffers
845
void Console::PushHistoryLine() {
847
memcpy(mpHistText + mHistCurRow * s, mpText, s);
848
memcpy(mpHistAttr + mHistCurRow * s, mpAttr, s);
849
memcpy(mpHistFlag + mHistCurRow * s, mpFlag, s);
850
mHistCurRow = (mHistCurRow + 1) % HISTORY_LINES;
853
//scroll into history buffer and switch to history mode if necessary
854
void Console::ScrollDelta(ScrollFlag f) {
856
static int sBackOffset = 0;
858
//history mode will be closed in PutChar()
862
memcpy(mpSavTextBuf, mpText, mConMaxCols * mConMaxRows);
863
memcpy(mpSavAttrBuf, mpAttr, mConMaxCols * mConMaxRows);
864
memcpy(mpSavFlagBuf, mpFlag, mConMaxCols * mConMaxRows);
868
sBackOffset += mConMaxRows / 2;
871
sBackOffset -= mConMaxRows / 2;
880
if (sBackOffset >= HISTORY_LINES)
881
sBackOffset = HISTORY_LINES - 1;
884
ShowHistory(sBackOffset);
887
void Console::ShowHistory(int offset) {
888
int row, indexCol, histrow;
890
for (row = 0; row < mConMaxRows && offset; row++, offset--) {
891
histrow = mHistCurRow - offset;
893
histrow += HISTORY_LINES;
895
indexCol = Index(0, histrow);
896
//copy one row from history buffer
897
memcpy(mpText + Index(0, row),mpHistText + indexCol,mConMaxCols);
898
memcpy(mpAttr + Index(0, row),mpHistAttr + indexCol,mConMaxCols);
899
memcpy(mpFlag + Index(0, row),mpHistFlag + indexCol,mConMaxCols);
900
ResetFlagRow(mpText + row * mConMaxCols,mpFlag + row * mConMaxCols,mConMaxCols);
902
//remain rows copied from screen buffer
903
for (int r = 0; row < mConMaxRows; row++, r++) {
904
memcpy(mpText + Index(0, row), mpSavTextBuf + Index(0, r),mConMaxCols);
905
memcpy(mpAttr + Index(0, row), mpSavAttrBuf + Index(0, r),mConMaxCols);
906
memcpy(mpFlag + Index(0, row), mpSavFlagBuf + Index(0, r),mConMaxCols);
907
ResetFlagRow(mpText + row * mConMaxCols,mpFlag + row * mConMaxCols,mConMaxCols);
908
// DrawRow(row, &mpText[indexCol], &mpAttr[indexCol],
909
// &mpFlag[indexCol], true);
912
// turn off cursor for rapid display
913
bool isCursorOn = CursorOnOff();
914
if (isCursorOn) CursorHide();
916
if (isCursorOn) CursorShow();
919
//modified from Yu Guanghui's auto-converter(judge.c)
920
Encode Console::DetectBufferEncode() {
925
/* first we look up "ļæ½ļæ½" and "ļæ½ļæ½" ,both gb and big5
928
for (phz = mpText; phz < (mpText + mConMaxRows * mConMaxCols);
931
if ((*phz == 0xB5 && *(phz + 1) == 0xC4)
932
|| ((*phz == 0xCE) && *(phz + 1) == 0xD2)) {
936
} else if ((*phz == 0xAA && *(phz + 1) == 0xBA)
937
|| ((*phz == 0xA7) && *(phz + 1) == 0xDA)) {
949
else if (c_gb == c_big5) {
950
//c_gb == 0,c_big5==0
951
/*There is not "ļæ½ļæ½" and "ļæ½ļæ½" in the text
952
*So we test the text with a 400 words table.
954
//unable to detect so return ascii
955
return ::ASCII; //j_code3(buff,count);
962
void Console::VtSizeDelta(int ColDelta, int RowDelta) {
964
int NewRows, NewEndRow;
965
NewRows = mMaxRows - RowDelta;
966
NewEndRow = NewRows - 1;
968
if (Row() > NewEndRow) {
969
//CopyLines(Row(), NewEndRow, 1);
970
Goto(Col(), NewEndRow);
973
//debug<<"Clear "<<NewRows<<"-"<<mConEndRow<<endl;
974
Clear(0, NewRows, mConEndCol, mConEndRow, 0);
978
mConMaxRows = NewRows;
979
mConEndRow = NewEndRow;
980
mScrollEnd = mConMaxRows;
983
void Console::GetVtSize(int &cols, int &rows) {
988
void Console::UpdateAttr(){
991
mAttr = (mAttr & 0xf0) | mUlColor;
992
else if (mIntensity == 0)
993
mAttr = (mAttr & 0xf0) | mHalfColor;
995
mAttr = ((mAttr) & 0x88) | ((((mAttr) >> 4) | ((mAttr) << 4)) & 0x77);
1002
/* use complementary color to show the mouse pointer */
1003
void Console::SelPointer(const int offset) {
1004
if (mMouseIdx >= 0 && mMouseIdx < mMaxCols * mMaxRows) {
1005
mpAttr[mMouseIdx] ^= mMouseMask;
1006
mpFlag[mMouseIdx] |= txtUpdated;
1009
RedrawChar(mMouseIdx % mMaxCols, mMouseIdx / mMaxCols);
1018
if (mMouseIdx > mMaxCols * mMaxRows - 1) {
1019
mMouseIdx = mMaxCols * mMaxRows - 1;
1022
mpAttr[mMouseIdx] ^= mMouseMask;
1023
mpFlag[mMouseIdx] |= txtUpdated;
1026
RedrawChar(mMouseIdx % mMaxCols, mMouseIdx / mMaxCols);
1029
/* set reverse video on characters s-e of console with selection. */
1030
void Console::SelHighlight(const int begin, const int end) {
1031
int count = end - begin + 1;
1032
char* pAttr = &mpAttr[begin];
1033
char* pFlag = &mpFlag[begin];
1038
//color = ((color) & 0x11) | (((color) & 0xe0) >> 4) | (((color) & 0x0e) << 4);
1039
color = ((color) & 0x88) | (((color) & 0x70) >> 4) | (((color) & 0x07) << 4);
1042
(*pFlag) |= txtUpdated;
1047
// turn off cursor for rapid display
1048
bool isCursorOn = CursorOnOff();
1049
if (isCursorOn) CursorHide();
1051
if (isCursorOn) CursorShow();
1053
int count = end - beign + 2;
1057
p = screenpos(currcons, beign, viewed);
1061
if (!can_do_color) {
1062
while (cnt--) *q++ ^= 0x0800;
1063
} else if (hi_font_mask == 0x100) {
1066
a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
1072
a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
1077
do_update_region(currcons, (unsigned long) p, count);
1081
/* remove the current selection highlight, if any,
1082
from the console holding the selection. */
1083
void Console::SelClear() {
1084
SelPointer(-1); /* hide the pointer */
1085
if (mSelStart != -1) {
1086
SelHighlight(mSelStart, mSelEnd);
1091
// User settable table: what characters are to be considered alphabetic?
1093
__u32 Console::mInWordLut[8] = {
1094
0x00000000, // control chars
1095
0x03FF0000, // digits
1096
0x87FFFFFE, // uppercase and '_'
1097
0x07FFFFFE, // lowercase
1100
0xFF7FFFFF, // latin-1 accented letters, not multiplication sign
1101
0xFF7FFFFF // latin-1 accented letters, not division sign
1104
int Console::InWord(const unsigned char c) {
1105
return ( mInWordLut[c>>5] >> (c & 0x1F) ) & 1;
1108
// does screen address p correspond to character at LH/RH edge of screen?
1109
int Console::AtColEdge(const int p)
1111
return (!(p % mMaxCols) || !((p + 1) % mMaxCols));
1114
// Don't take this from <ctype.h>: 011-015 on the screen aren't spaces
1115
#define IS_SPACE(c) ((c) == ' ')
1116
#define IS_ASCII(c) ((c) & txtASCII)
1118
// based on kernel, linux/drivers/char/selection.c
1119
void Console::SelCopy(int c1, int r1, int c2, int r2, int mode) {
1120
int xs, ys, xe, ye, ps, pe;
1121
xs = CorrectCol(c1);
1122
ys = CorrectRow(r1);
1123
xe = CorrectCol(c2);
1124
ye = CorrectRow(r2);
1125
ps = ys * mMaxCols + xs;
1126
pe = ye * mMaxCols + xe;
1127
//debug<<"Mouse " <<xs<<","<<ys<<" "<<xe<<","<<ye<<" "
1128
// <<ps<<","<<pe<<" "<<endl;
1130
if (mode == 4) { // useful for screendump without selection highlights
1135
if (ps > pe) // make exchange if sel_start > sel_end
1142
int new_sel_start, new_sel_end;
1149
case 0: // character-by-character selection
1153
case 1: // word-by-word selection
1154
spc = IS_SPACE(mpText[ps]);
1155
ascii = IS_ASCII(mpFlag[ps]);
1156
for (new_sel_start = ps; ; ps--)
1159
if (spc && !IS_SPACE(mpText[ps]))
1161
if (!spc && !InWord(mpText[ps]))
1164
if (IS_ASCII(mpFlag[ps]))
1168
if (!(ps % mMaxCols))
1171
spc = IS_SPACE(mpText[pe]);
1172
ascii = IS_ASCII(mpFlag[pe]);
1173
for (new_sel_end = pe; ; pe++)
1176
if (spc && !IS_SPACE(mpText[pe]))
1178
if (!spc && !InWord(mpText[pe]))
1181
if (IS_ASCII(mpFlag[pe]))
1185
if (!((pe+1) % mMaxCols))
1189
case 2: // line-by-line selection
1190
new_sel_start = ps - ps % mMaxCols;
1191
new_sel_end = pe + mMaxCols - pe % mMaxCols - 1;
1200
// remove the pointer
1203
// select to end of line if on trailing space
1204
if (new_sel_end > new_sel_start &&
1205
!AtColEdge(new_sel_end) &&
1206
IS_SPACE(mpText[new_sel_end])) {
1207
for (pe = new_sel_end + 1; ; pe++)
1208
if (!IS_SPACE(mpText[pe]) ||
1211
if (IS_SPACE(mpText[pe]))
1214
if (mSelStart == -1) // no current selection
1215
SelHighlight(new_sel_start, new_sel_end);
1216
else if (new_sel_start == mSelStart)
1218
if (new_sel_end == mSelEnd) // no action required
1220
else if (new_sel_end > mSelEnd) // extend to right
1221
SelHighlight(mSelEnd + 1, new_sel_end);
1222
else // contract from right
1223
SelHighlight(new_sel_end + 1, mSelEnd);
1225
else if (new_sel_end == mSelEnd)
1227
if (new_sel_start < mSelStart) // extend to left
1228
SelHighlight(new_sel_start, mSelStart - 1);
1229
else // contract from left
1230
SelHighlight(mSelStart, new_sel_start - 1);
1232
else // some other case; start selection from scratch
1235
SelHighlight(new_sel_start, new_sel_end);
1237
mSelStart = new_sel_start;
1238
mSelEnd = new_sel_end;
1240
// Allocate a new buffer before freeing the old one ...
1241
bp = new char[mSelEnd-mSelStart+1];
1242
if (!bp) { // selection: kmalloc() failed
1251
for (i = mSelStart; i <= mSelEnd; i++) {
1253
if (!IS_SPACE(*bp++))
1255
if (! ((i + 1) % mMaxCols)) {
1256
// strip trailing blanks from line and add newline,
1257
// unless non-space at end of line.
1265
mSelBufLen = bp - mpSelBuf;
1268
void Console::SelPaste(int fd) {
1270
int pasted = 0, count;
1271
while (mpSelBuf && (mSelBufLen > pasted)) {
1272
count = mSelBufLen - pasted;
1273
pasted = write(fd, mpSelBuf, count);