Skip to content

Instantly share code, notes, and snippets.

@saitoha
Last active December 18, 2015 08:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save saitoha/5750854 to your computer and use it in GitHub Desktop.
Save saitoha/5750854 to your computer and use it in GitHub Desktop.
Add DECLRMM(DECVSSM) and DECSLRM feature to iTerm2 (on progress)
diff --git a/VT100Screen.h b/VT100Screen.h
index d47185e..585d326 100644
--- a/VT100Screen.h
+++ b/VT100Screen.h
@@ -87,6 +87,8 @@ void TranslateCharacterSet(screen_char_t *s, int len);
int ALT_SAVE_CURSOR_Y;
int SCROLL_TOP;
int SCROLL_BOTTOM;
+ int SCROLL_LEFT;
+ int SCROLL_RIGHT;
NSMutableSet* tabStops;
VT100Terminal *TERMINAL;
@@ -98,7 +100,7 @@ void TranslateCharacterSet(screen_char_t *s, int len);
BOOL SHOWBELL;
BOOL FLASHBELL;
BOOL GROWL;
-
+ BOOL vsplitMode;
BOOL blinkingCursor;
PTYTextView *display;
@@ -183,6 +185,8 @@ void TranslateCharacterSet(screen_char_t *s, int len);
- (PTYTask *)shellTask;
- (PTYSession *) session;
- (void)setSession:(PTYSession *)session;
+- (BOOL)vsplitMode;
+- (void)setVsplitMode: (BOOL)mode;
- (PTYTextView *) display;
- (void) setDisplay: (PTYTextView *) aDisplay;
@@ -250,6 +254,7 @@ void TranslateCharacterSet(screen_char_t *s, int len);
- (void)cursorDown:(int)n;
- (void)cursorToX: (int) x;
- (void)cursorToX:(int)x Y:(int)y;
+- (void)carriageReturn;
- (void)saveCursorPosition;
- (void)restoreCursorPosition;
- (void)setTopBottom:(VT100TCC)token;
diff --git a/VT100Screen.m b/VT100Screen.m
index f634774..0deb115 100644
--- a/VT100Screen.m
+++ b/VT100Screen.m
@@ -332,7 +332,9 @@ static __inline__ screen_char_t *incrementLinePointer(screen_char_t *buf_start,
cursorX = cursorY = 0;
SAVE_CURSOR_X = SAVE_CURSOR_Y = 0;
ALT_SAVE_CURSOR_X = ALT_SAVE_CURSOR_Y = 0;
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
TERMINAL = nil;
@@ -433,7 +435,9 @@ static __inline__ screen_char_t *incrementLinePointer(screen_char_t *buf_start,
cursorX = cursorY = 0;
SAVE_CURSOR_X = SAVE_CURSOR_Y = 0;
ALT_SAVE_CURSOR_X = ALT_SAVE_CURSOR_Y = 0;
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
blinkShow=YES;
findContext.substring = nil;
@@ -692,6 +696,11 @@ static __inline__ screen_char_t *incrementLinePointer(screen_char_t *buf_start,
}
}
+- (void)carriageReturn
+{
+ [self setCursorX:vsplitMode ? SCROLL_LEFT:0 Y:cursorY];
+}
+
- (void)setWidth:(int)width height:(int)height
{
#if DEBUG_METHOD_TRACE
@@ -705,7 +714,9 @@ static __inline__ screen_char_t *incrementLinePointer(screen_char_t *buf_start,
[self setCursorX:0 Y:0];
SAVE_CURSOR_X = SAVE_CURSOR_Y = 0;
ALT_SAVE_CURSOR_X = ALT_SAVE_CURSOR_Y = 0;
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
}
}
@@ -1699,8 +1710,10 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
[linebuffer dump];
#endif
- // reset terminal scroll top and bottom
+ // reset terminal scroll region
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
[self clampCursorPositionToValid];
@@ -1762,8 +1775,10 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
// Save screen contents before resetting.
[self scrollScreenIntoScrollbackBuffer:1];
- // reset terminal scroll top and bottom
+ // reset terminal scroll region
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
[self clearScreen];
@@ -2024,7 +2039,7 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
[SESSION clearTriggerLine];
break;
case VT100CC_CR:
- [self setCursorX:0 Y:cursorY];
+ [self carriageReturn];
[SESSION clearTriggerLine];
break;
case VT100CC_SO: break;
@@ -2078,7 +2093,9 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
aLine[WIDTH].code = EOL_HARD;
}
// reset scroll region
+ SCROLL_LEFT = 0;
SCROLL_TOP = 0;
+ SCROLL_RIGHT = WIDTH - 1;
SCROLL_BOTTOM = HEIGHT - 1;
// set cursor to (1, 1)
[self setCursorX:0 Y:0];
@@ -2215,6 +2232,22 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
}
break;
+ case VT100CSI_DECSLRM:
+ SCROLL_LEFT = token.u.csi.p[0] - 1;
+ SCROLL_RIGHT = token.u.csi.p[1] - 1;
+ if (SCROLL_RIGHT == 0) {
+ SCROLL_RIGHT = WIDTH - 1;
+ }
+ // check wrong parameter
+ if (SCROLL_RIGHT - SCROLL_LEFT < 1) {
+ SCROLL_LEFT = 0;
+ SCROLL_RIGHT = WIDTH - 1;
+ }
+ if (SCROLL_RIGHT > WIDTH - 1) {
+ SCROLL_RIGHT = WIDTH - 1;
+ }
+ break;
+
/* My interpretation of this:
* http://www.cl.cam.ac.uk/~mgk25/unicode.html#term
* is that UTF-8 terminals should ignore SCS because
@@ -2300,11 +2333,10 @@ static BOOL XYIsBeforeXY(int px1, int py1, int px2, int py2) {
[SESSION clearTriggerLine];
break;
case ANSICSI_VPA:
- [self cursorToX:cursorX + 1 Y:token.u.csi.p[0]];
- [SESSION clearTriggerLine];
+ [self cursorToY:token.u.csi.p[0]];
break;
case ANSICSI_VPR:
- [self cursorToX:cursorX + 1 Y:token.u.csi.p[0] + cursorY + 1];
+ [self cursorRight:token.u.csi.p[0]];
[SESSION clearTriggerLine];
break;
case ANSICSI_ECH:
@@ -2787,6 +2819,7 @@ void DumpBuf(screen_char_t* p, int n) {
int charsToInsert;
int len;
int newx;
+ int leftMargin, rightMargin;
screen_char_t *buffer;
screen_char_t *aLine;
@@ -2949,17 +2982,25 @@ void DumpBuf(screen_char_t* p, int n) {
} else {
widthOffset = 0;
}
- if (cursorX >= WIDTH - widthOffset) {
+
+ if (vsplitMode && cursorX <= SCROLL_RIGHT + 1) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+ if (cursorX >= rightMargin - widthOffset) {
if ([TERMINAL wraparoundMode]) {
// Set the continuation marker
screen_char_t* prevLine = [self getLineAtScreenIndex:cursorY];
- BOOL splitDwc = (cursorX == WIDTH - 1);
- prevLine[WIDTH].code = (splitDwc ? EOL_DWC : EOL_SOFT);
+ BOOL splitDwc = (cursorX == rightMargin - 1);
+ prevLine[rightMargin].code = (splitDwc ? EOL_DWC : EOL_SOFT);
if (splitDwc) {
- prevLine[WIDTH].code = EOL_DWC;
- prevLine[WIDTH-1].code = DWC_SKIP;
+ prevLine[rightMargin].code = EOL_DWC;
+ prevLine[rightMargin - 1].code = DWC_SKIP;
}
- [self setCursorX:0 Y:cursorY];
+ [self setCursorX:leftMargin Y:cursorY];
// Advance to the next line
[self setNewLine];
#ifdef VERBOSE_STRING
@@ -2972,7 +3013,7 @@ void DumpBuf(screen_char_t* p, int n) {
// and insert the last character there.
// Clear the continuation marker
- [self getLineAtScreenIndex:cursorY][WIDTH].code = EOL_HARD;
+ [self getLineAtScreenIndex:cursorY][rightMargin].code = EOL_HARD;
// Cause the loop to end after this character.
int ncx = WIDTH - 1;
@@ -3000,7 +3041,7 @@ void DumpBuf(screen_char_t* p, int n) {
#endif
}
}
- const int spaceRemainingInLine = WIDTH - cursorX;
+ const int spaceRemainingInLine = rightMargin - cursorX;
const int charsLeftToAppend = len - idx;
#ifdef VERBOSE_STRING
@@ -3011,7 +3052,12 @@ void DumpBuf(screen_char_t* p, int n) {
NSLog(@"There is %d space left in the line and we are appending %d chars",
spaceRemainingInLine, charsLeftToAppend);
#endif
- int effective_width = WIDTH;
+ int effective_width;
+ if (vsplitMode) {
+ effective_width = WIDTH;
+ } else {
+ effective_width = SCROLL_RIGHT + 1;
+ }
if (spaceRemainingInLine <= charsLeftToAppend) {
#ifdef VERBOSE_STRING
NSLog(@"Not enough space in the line for everything we want to append.");
@@ -3027,13 +3073,13 @@ void DumpBuf(screen_char_t* p, int n) {
NSLog(@"Dropping a char from the end to avoid splitting a DWC.");
#endif
wrapDwc = YES;
- newx = WIDTH - 1;
+ newx = rightMargin - 1;
--effective_width;
} else {
#ifdef VERBOSE_STRING
NSLog(@"Inserting up to the end of the line only.");
#endif
- newx = WIDTH;
+ newx = rightMargin;
}
} else {
// This is the last iteration through this loop and we will not
@@ -3060,14 +3106,14 @@ void DumpBuf(screen_char_t* p, int n) {
aLine = [self getLineAtScreenIndex:cursorY];
if ([TERMINAL insertMode]) {
- if (cursorX + charsToInsert < WIDTH) {
+ if (cursorX + charsToInsert < rightMargin) {
#ifdef VERBOSE_STRING
NSLog(@"Shifting old contents to the right");
#endif
// Shift the old line contents to the right by 'charsToInsert' positions.
screen_char_t* src = aLine + cursorX;
screen_char_t* dst = aLine + cursorX + charsToInsert;
- int elements = WIDTH - cursorX - charsToInsert;
+ int elements = rightMargin - cursorX - charsToInsert;
if (cursorX > 0 && src[0].code == DWC_RIGHT) {
// The insert occurred in the middle of a DWC.
src[-1].code = ' ';
@@ -3080,14 +3126,14 @@ void DumpBuf(screen_char_t* p, int n) {
src[elements - 1].code = ' ';
src[elements - 1].complexChar = NO;
} else if (src[elements].code == DWC_SKIP &&
- aLine[WIDTH].code == EOL_DWC) {
+ aLine[rightMargin].code == EOL_DWC) {
// Stomping on a DWC_SKIP. Join the lines normally.
- aLine[WIDTH].code = EOL_SOFT;
+ aLine[rightMargin].code = EOL_SOFT;
}
memmove(dst, src, elements * sizeof(screen_char_t));
memset(dirty + screenIdx + cursorX,
1,
- WIDTH - cursorX);
+ rightMargin - cursorX);
}
}
@@ -3126,7 +3172,7 @@ void DumpBuf(screen_char_t* p, int n) {
// Overwrote some stuff that was already on the screen leaving behind the
// second half of a DWC
- if (cursorX < WIDTH-1 && aLine[cursorX].code == DWC_RIGHT) {
+ if (cursorX < rightMargin - 1 && aLine[cursorX].code == DWC_RIGHT) {
aLine[cursorX].code = ' ';
aLine[cursorX].complexChar = NO;
}
@@ -3140,11 +3186,11 @@ void DumpBuf(screen_char_t* p, int n) {
if (cursorX >= effective_width && [TERMINAL isAnsi]) {
if ([TERMINAL wraparoundMode]) {
//set the wrapping flag
- aLine[WIDTH].code = ((effective_width == WIDTH) ? EOL_SOFT : EOL_DWC);
- [self setCursorX:0 Y:cursorY];
+ aLine[rightMargin].code = ((effective_width == WIDTH) ? EOL_SOFT : EOL_DWC);
+ [self setCursorX:leftMargin Y:cursorY];
[self setNewLine];
} else {
- [self setCursorX:WIDTH - 1
+ [self setCursorX:rightMargin - 1
Y:cursorY];
if (idx < len - 1) {
// Iterate once more to draw the last character at the end
@@ -3217,7 +3263,7 @@ void DumpBuf(screen_char_t* p, int n) {
}
}
DebugLog(@"setNewline advance cursor");
- } else if (SCROLL_TOP == 0 && SCROLL_BOTTOM == HEIGHT - 1) {
+ } else if (SCROLL_TOP == 0 && SCROLL_BOTTOM == HEIGHT - 1 && (!vsplitMode || (SCROLL_LEFT == 0 && SCROLL_RIGHT == WIDTH - 1))) {
// Scroll the whole screen.
// Mark the cursor's previous location dirty. This fixes a rare race condition where
@@ -3237,9 +3283,10 @@ void DumpBuf(screen_char_t* p, int n) {
// set last screen line default
aLine = [self getLineAtScreenIndex: (HEIGHT - 1)];
+
memcpy(aLine,
- [self _getDefaultLineWithWidth:WIDTH],
- REAL_WIDTH*sizeof(screen_char_t));
+ [self _getDefaultLineWithWidth:WIDTH],
+ REAL_WIDTH * sizeof(screen_char_t));
// Mark everything dirty if we're not using the scrollback buffer
if (showingAltScreen) {
@@ -3263,54 +3310,73 @@ void DumpBuf(screen_char_t* p, int n) {
{
screen_char_t *aLine;
int i;
-
+ int leftMargin, rightMargin;
+
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[VT100Screen deleteCharacter]: %d", __FILE__, __LINE__, n);
#endif
+
+ if (vsplitMode) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
- if (cursorX >= 0 && cursorX < WIDTH &&
+ if (cursorX >= leftMargin && cursorX < rightMargin &&
cursorY >= 0 && cursorY < HEIGHT) {
int idx;
idx = cursorY * WIDTH;
- if (n + cursorX > WIDTH) {
- n = WIDTH - cursorX;
+ if (n + cursorX > rightMargin) {
+ n = rightMargin - cursorX;
}
// get the appropriate screen line
aLine = [self getLineAtScreenIndex:cursorY];
- if (n < WIDTH) {
+ if (n < rightMargin) {
memmove(aLine + cursorX,
aLine + cursorX + n,
- (WIDTH - cursorX - n) * sizeof(screen_char_t));
+ (rightMargin - cursorX - n) * sizeof(screen_char_t));
}
for (i = 0; i < n; i++) {
- aLine[WIDTH-n+i].code = 0;
- aLine[WIDTH-n+i].complexChar = NO;
- CopyForegroundColor(&aLine[WIDTH-n+i], [TERMINAL foregroundColorCodeReal]);
- CopyBackgroundColor(&aLine[WIDTH-n+i], [TERMINAL backgroundColorCodeReal]);
+ aLine[rightMargin - n + i].code = 0;
+ aLine[rightMargin - n + i].complexChar = NO;
+ CopyForegroundColor(&aLine[rightMargin - n + i], [TERMINAL foregroundColorCodeReal]);
+ CopyBackgroundColor(&aLine[rightMargin - n + i], [TERMINAL backgroundColorCodeReal]);
}
DebugLog(@"deleteCharacters");
- [self setRangeDirty:NSMakeRange(idx + cursorX, WIDTH - cursorX)];
+ [self setRangeDirty:NSMakeRange(idx + cursorX, rightMargin - cursorX)];
}
}
- (void)backSpace
{
+ int leftMargin, rightMargin;
+
+ if (vsplitMode) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+
if (cursorX > 0) {
if (cursorX >= WIDTH) {
[self setCursorX:cursorX - 2 Y:cursorY];
} else {
[self setCursorX:cursorX - 1 Y:cursorY];
}
- } else if (cursorX == 0 && cursorY > 0) {
+ } else if (cursorX == leftMargin && cursorY > 0) {
screen_char_t* aLine = [self getLineAtScreenIndex:cursorY - 1];
- if (aLine[WIDTH].code == EOL_SOFT) {
- [self setCursorX:WIDTH - 1 Y:cursorY - 1];
- } else if (aLine[WIDTH].code == EOL_DWC) {
- [self setCursorX:WIDTH - 2 Y:cursorY - 1];
+ if (aLine[rightMargin].code == EOL_SOFT) {
+ [self setCursorX:rightMargin - 1 Y:cursorY - 1];
+ } else if (aLine[rightMargin].code == EOL_DWC) {
+ [self setCursorX:rightMargin - 2 Y:cursorY - 1];
}
}
}
@@ -3624,14 +3690,23 @@ void DumpBuf(screen_char_t* p, int n) {
- (void)cursorLeft:(int)n
{
int x = cursorX - (n > 0 ? n : 1);
+ int leftMargin, rightMargin;
+
+ if (vsplitMode) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[VT100Screen cursorLeft:%d]",
__FILE__, __LINE__, n);
#endif
- if (x < 0)
- x = 0;
- if (x >= 0 && x < WIDTH) {
+ if (x < leftMargin)
+ x = leftMargin;
+ if (x >= leftMargin && x < rightMargin) {
[self setCursorX:x Y:cursorY];
}
@@ -3644,14 +3719,23 @@ void DumpBuf(screen_char_t* p, int n) {
- (void)cursorRight:(int)n
{
int x = cursorX + (n > 0 ? n : 1);
+ int leftMargin, rightMargin;
+
+ if (vsplitMode) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[VT100Screen cursorRight:%d]",
__FILE__, __LINE__, n);
#endif
- if (x >= WIDTH)
- x = WIDTH - 1;
- if (x >= 0 && x < WIDTH) {
+ if (x >= rightMargin)
+ x = rightMargin - 1;
+ if (x >= leftMargin && x < rightMargin) {
[self setCursorX:x Y:cursorY];
}
@@ -3690,7 +3774,7 @@ void DumpBuf(screen_char_t* p, int n) {
- (void)cursorToX:(int)x
{
int x_pos;
-
+ int leftMargin, rightMargin;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[VT100Screen cursorToX:%d]",
@@ -3698,6 +3782,17 @@ void DumpBuf(screen_char_t* p, int n) {
#endif
x_pos = (x-1);
+ if (vsplitMode) {
+ if ([TERMINAL originMode]) {
+ x_pos += SCROLL_LEFT;
+ }
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+
if (x_pos < 0) {
x_pos = 0;
} else if (x_pos >= WIDTH) {
@@ -3713,6 +3808,34 @@ void DumpBuf(screen_char_t* p, int n) {
}
+- (void)cursorToY:(int)y
+{
+ int y_pos;
+
+#if DEBUG_METHOD_TRACE
+ NSLog(@"%s(%d):-[VT100Screen cursorToY:%d]",
+ __FILE__, __LINE__, y);
+#endif
+
+ y_pos = y - 1;
+
+ if ([TERMINAL originMode]) {
+ y_pos += SCROLL_TOP;
+ }
+
+ if (y_pos < 0) {
+ y_pos = 0;
+ } else if (y_pos >= HEIGHT) {
+ y_pos = HEIGHT - 1;
+ }
+
+ [self setCursorX:cursorX Y:y_pos];
+
+ [self setCharAtCursorDirty:1];
+ DebugLog(@"cursorToY");
+
+}
+
- (void)cursorToX:(int)x Y:(int)y
{
#if DEBUG_METHOD_TRACE
@@ -3720,17 +3843,30 @@ void DumpBuf(screen_char_t* p, int n) {
__FILE__, __LINE__, x, y);
#endif
int x_pos, y_pos;
-
+ int leftMargin, rightMargin;
x_pos = x - 1;
y_pos = y - 1;
- if ([TERMINAL originMode]) y_pos += SCROLL_TOP;
-
- if (x_pos < 0) {
- x_pos = 0;
- } else if (x_pos >= WIDTH) {
- x_pos = WIDTH - 1;
+ if ([TERMINAL originMode]) {
+ y_pos += SCROLL_TOP;
+ if (vsplitMode) {
+ x_pos += SCROLL_LEFT;
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+
+ if (x_pos < leftMargin) {
+ x_pos = leftMargin;
+ } else if (x_pos >= rightMargin) {
+ x_pos = rightMargin - 1;
}
if (y_pos < 0) {
y_pos = 0;
@@ -3821,7 +3957,8 @@ void DumpBuf(screen_char_t* p, int n) {
assert(SCROLL_BOTTOM < HEIGHT);
if ([TERMINAL originMode]) {
- [self setCursorX:0 Y:SCROLL_TOP];
+ [self setCursorX:vsplitMode ? SCROLL_LEFT: 0
+ Y:SCROLL_TOP];
} else {
[self setCursorX:0 Y:0];
}
@@ -3841,7 +3978,7 @@ void DumpBuf(screen_char_t* p, int n) {
assert(SCROLL_BOTTOM >= 0 && SCROLL_BOTTOM < HEIGHT);
assert(SCROLL_TOP <= SCROLL_BOTTOM );
- if (SCROLL_TOP == 0 && SCROLL_BOTTOM == HEIGHT -1) {
+ if (SCROLL_TOP == 0 && SCROLL_BOTTOM == HEIGHT - 1 && (!vsplitMode || (SCROLL_LEFT == 0 && SCROLL_RIGHT == WIDTH - 1))) {
[self setNewLine];
} else if (SCROLL_TOP < SCROLL_BOTTOM) {
// Not scrolling the whole screen.
@@ -3855,32 +3992,54 @@ void DumpBuf(screen_char_t* p, int n) {
// check if the screen area is wrapped
sourceLine = [self getLineAtScreenIndex:SCROLL_TOP];
targetLine = [self getLineAtScreenIndex:SCROLL_BOTTOM];
- if (sourceLine < targetLine) {
- // screen area is not wrapped; direct memmove
- memmove(sourceLine,
- sourceLine + REAL_WIDTH,
- (SCROLL_BOTTOM - SCROLL_TOP) * REAL_WIDTH * sizeof(screen_char_t));
- } else {
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT < WIDTH - 1) && vsplitMode) {
// screen area is wrapped; copy line by line
for(i = SCROLL_TOP; i < SCROLL_BOTTOM; i++) {
- sourceLine = [self getLineAtScreenIndex:i+1];
+ sourceLine = [self getLineAtScreenIndex:i + 1];
targetLine = [self getLineAtScreenIndex: i];
- memmove(targetLine,
- sourceLine,
- REAL_WIDTH * sizeof(screen_char_t));
+ memmove(targetLine + SCROLL_LEFT,
+ sourceLine + SCROLL_LEFT,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ }
+ // new line at SCROLL_BOTTOM with default settings
+ targetLine = [self getLineAtScreenIndex:SCROLL_BOTTOM];
+ memcpy(targetLine + SCROLL_LEFT,
+ [self _getDefaultLineWithWidth:SCROLL_RIGHT + 1 - SCROLL_LEFT],
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+
+ // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
+ [self setDirtyFromX:SCROLL_LEFT
+ Y:SCROLL_TOP
+ toX:SCROLL_RIGHT + 1
+ Y:SCROLL_BOTTOM];
+ } else {
+ if (sourceLine < targetLine) {
+ // screen area is not wrapped; direct memmove
+ memmove(sourceLine,
+ sourceLine + REAL_WIDTH,
+ (SCROLL_BOTTOM - SCROLL_TOP) * REAL_WIDTH * sizeof(screen_char_t));
+ } else {
+ // screen area is wrapped; copy line by line
+ for(i = SCROLL_TOP; i < SCROLL_BOTTOM; i++) {
+ sourceLine = [self getLineAtScreenIndex:i + 1];
+ targetLine = [self getLineAtScreenIndex:i];
+ memmove(targetLine,
+ sourceLine,
+ REAL_WIDTH * sizeof(screen_char_t));
+ }
}
+ // new line at SCROLL_BOTTOM with default settings
+ targetLine = [self getLineAtScreenIndex:SCROLL_BOTTOM];
+ memcpy(targetLine,
+ [self _getDefaultLineWithWidth:WIDTH],
+ REAL_WIDTH * sizeof(screen_char_t));
+
+ // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
+ [self setDirtyFromX:0
+ Y:SCROLL_TOP
+ toX:WIDTH
+ Y:SCROLL_BOTTOM];
}
- // new line at SCROLL_BOTTOM with default settings
- targetLine = [self getLineAtScreenIndex:SCROLL_BOTTOM];
- memcpy(targetLine,
- [self _getDefaultLineWithWidth:WIDTH],
- REAL_WIDTH * sizeof(screen_char_t));
-
- // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
- [self setDirtyFromX:0
- Y:SCROLL_TOP
- toX:WIDTH
- Y:SCROLL_BOTTOM];
DebugLog(@"scrollUp");
}
}
@@ -3896,41 +4055,62 @@ void DumpBuf(screen_char_t* p, int n) {
NSParameterAssert(SCROLL_TOP >= 0 && SCROLL_TOP < HEIGHT);
NSParameterAssert(SCROLL_BOTTOM >= 0 && SCROLL_BOTTOM < HEIGHT);
- NSParameterAssert(SCROLL_TOP <= SCROLL_BOTTOM );
+ NSParameterAssert(SCROLL_TOP <= SCROLL_BOTTOM);
- if (SCROLL_TOP<SCROLL_BOTTOM)
- {
+ if (SCROLL_TOP < SCROLL_BOTTOM) {
// move all lines between SCROLL_TOP and SCROLL_BOTTOM one line down
// check if screen is wrapped
sourceLine = [self getLineAtScreenIndex:SCROLL_TOP];
targetLine = [self getLineAtScreenIndex:SCROLL_BOTTOM];
- if (sourceLine < targetLine)
- {
- // screen area is not wrapped; direct memmove
- memmove(sourceLine+REAL_WIDTH, sourceLine, (SCROLL_BOTTOM-SCROLL_TOP)*REAL_WIDTH*sizeof(screen_char_t));
- }
- else
- {
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT + 1 < WIDTH) && vsplitMode) {
// screen area is wrapped; move line by line
- for(i = SCROLL_BOTTOM - 1; i >= SCROLL_TOP; i--)
- {
+ for(i = SCROLL_BOTTOM - 1; i >= SCROLL_TOP; i--) {
sourceLine = [self getLineAtScreenIndex:i];
- targetLine = [self getLineAtScreenIndex:i+1];
- memmove(targetLine, sourceLine, REAL_WIDTH*sizeof(screen_char_t));
+ targetLine = [self getLineAtScreenIndex:i + 1];
+ memmove(targetLine + SCROLL_LEFT,
+ sourceLine + SCROLL_LEFT,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ }
+
+ // new line at SCROLL_TOP with default settings
+ targetLine = [self getLineAtScreenIndex:SCROLL_TOP];
+ memcpy(targetLine + SCROLL_LEFT,
+ [self _getDefaultLineWithWidth:SCROLL_RIGHT + 1 - SCROLL_LEFT],
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+
+ // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
+ [self setDirtyFromX:SCROLL_LEFT
+ Y:SCROLL_TOP
+ toX:SCROLL_RIGHT + 1
+ Y:SCROLL_BOTTOM];
+ } else {
+ if (sourceLine < targetLine) {
+ // screen area is not wrapped; direct memmove
+ memmove(sourceLine + REAL_WIDTH,
+ sourceLine,
+ (SCROLL_BOTTOM - SCROLL_TOP) * REAL_WIDTH * sizeof(screen_char_t));
+ } else {
+ // screen area is wrapped; move line by line
+ for(i = SCROLL_BOTTOM - 1; i >= SCROLL_TOP; i--) {
+ sourceLine = [self getLineAtScreenIndex:i];
+ targetLine = [self getLineAtScreenIndex:i + 1];
+ memmove(targetLine, sourceLine, REAL_WIDTH * sizeof(screen_char_t));
+ }
}
+
+ // new line at SCROLL_TOP with default settings
+ targetLine = [self getLineAtScreenIndex:SCROLL_TOP];
+ memcpy(targetLine,
+ [self _getDefaultLineWithWidth:WIDTH],
+ REAL_WIDTH * sizeof(screen_char_t));
+
+ // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
+ [self setDirtyFromX:0
+ Y:SCROLL_TOP
+ toX:WIDTH
+ Y:SCROLL_BOTTOM];
}
}
- // new line at SCROLL_TOP with default settings
- targetLine = [self getLineAtScreenIndex:SCROLL_TOP];
- memcpy(targetLine,
- [self _getDefaultLineWithWidth:WIDTH],
- REAL_WIDTH*sizeof(screen_char_t));
-
- // everything between SCROLL_TOP and SCROLL_BOTTOM is dirty
- [self setDirtyFromX:0
- Y:SCROLL_TOP
- toX:WIDTH
- Y:SCROLL_BOTTOM];
DebugLog(@"scrollDown");
}
@@ -3938,13 +4118,22 @@ void DumpBuf(screen_char_t* p, int n) {
{
screen_char_t *aLine;
int i;
+ int leftMargin, rightMargin;
- if (cursorX >= WIDTH) {
+ if (vsplitMode) {
+ leftMargin = SCROLL_LEFT;
+ rightMargin = SCROLL_RIGHT + 1;
+ } else {
+ leftMargin = 0;
+ rightMargin = WIDTH;
+ }
+
+ if (cursorX >= rightMargin || cursorX < leftMargin) {
return;
}
- if (n + cursorX > WIDTH) {
- n = WIDTH - cursorX;
+ if (n + cursorX > rightMargin) {
+ n = rightMargin - cursorX;
}
// get the appropriate line
@@ -3952,7 +4141,7 @@ void DumpBuf(screen_char_t* p, int n) {
memmove(aLine + cursorX + n,
aLine + cursorX,
- (WIDTH - cursorX - n) * sizeof(screen_char_t));
+ (rightMargin - cursorX - n) * sizeof(screen_char_t));
for (i = 0; i < n; i++) {
aLine[cursorX + i].code = 0;
@@ -3962,9 +4151,9 @@ void DumpBuf(screen_char_t* p, int n) {
}
// everything from cursorX to end of line is dirty
- [self setDirtyFromX:MIN(WIDTH - 1, cursorX)
+ [self setDirtyFromX:MIN(rightMargin - 1, cursorX)
Y:cursorY
- toX:WIDTH
+ toX:rightMargin
Y:cursorY];
DebugLog(@"insertBlank");
}
@@ -3987,9 +4176,16 @@ void DumpBuf(screen_char_t* p, int n) {
for (i = num_lines_moved ; i >= 0; i--) {
sourceLine = [self getLineAtScreenIndex:cursorY + i];
targetLine = [self getLineAtScreenIndex:cursorY + i + n];
- memcpy(targetLine, sourceLine, REAL_WIDTH * sizeof(screen_char_t));
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT + 1 < WIDTH) && vsplitMode) {
+ memcpy(targetLine + SCROLL_LEFT,
+ sourceLine + SCROLL_LEFT,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ } else {
+ memcpy(targetLine,
+ sourceLine,
+ REAL_WIDTH * sizeof(screen_char_t));
+ }
}
-
}
if (n + cursorY > SCROLL_BOTTOM) {
n = SCROLL_BOTTOM - cursorY + 1;
@@ -3999,7 +4195,15 @@ void DumpBuf(screen_char_t* p, int n) {
aDefaultLine = [self _getDefaultLineWithWidth:WIDTH];
for (i = 0; i < n; i++) {
sourceLine = [self getLineAtScreenIndex:cursorY + i];
- memcpy(sourceLine, aDefaultLine, REAL_WIDTH*sizeof(screen_char_t));
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT + 1 < WIDTH) && vsplitMode) {
+ memcpy(sourceLine + SCROLL_LEFT,
+ aDefaultLine,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ } else {
+ memcpy(sourceLine,
+ aDefaultLine,
+ REAL_WIDTH * sizeof(screen_char_t));
+ }
}
// everything between cursorY and SCROLL_BOTTOM is dirty
@@ -4025,7 +4229,15 @@ void DumpBuf(screen_char_t* p, int n) {
for (i = 0; i <= num_lines_moved; i++) {
sourceLine = [self getLineAtScreenIndex:cursorY + i + n];
targetLine = [self getLineAtScreenIndex:cursorY + i];
- memcpy(targetLine, sourceLine, REAL_WIDTH*sizeof(screen_char_t));
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT + 1 < WIDTH) && vsplitMode) {
+ memcpy(targetLine + SCROLL_LEFT,
+ sourceLine + SCROLL_LEFT,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ } else {
+ memcpy(targetLine,
+ sourceLine,
+ REAL_WIDTH * sizeof(screen_char_t));
+ }
}
}
@@ -4036,7 +4248,15 @@ void DumpBuf(screen_char_t* p, int n) {
aDefaultLine = [self _getDefaultLineWithWidth:WIDTH];
for (i = 0; i < n; i++) {
sourceLine = [self getLineAtScreenIndex:SCROLL_BOTTOM-n+1+i];
- memcpy(sourceLine, aDefaultLine, REAL_WIDTH*sizeof(screen_char_t));
+ if ((SCROLL_LEFT > 0 || SCROLL_RIGHT + 1 < WIDTH) && vsplitMode) {
+ memcpy(sourceLine + SCROLL_LEFT,
+ aDefaultLine,
+ (SCROLL_RIGHT + 1 - SCROLL_LEFT) * sizeof(screen_char_t));
+ } else {
+ memcpy(sourceLine,
+ aDefaultLine,
+ REAL_WIDTH * sizeof(screen_char_t));
+ }
}
// everything between cursorY and SCROLL_BOTTOM is dirty
@@ -4143,7 +4363,7 @@ void DumpBuf(screen_char_t* p, int n) {
int x, y;
if ([TERMINAL originMode]) {
- x = cursorX + 1;
+ x = cursorX - SCROLL_LEFT + 1;
y = cursorY - SCROLL_TOP + 1;
}
else {
@@ -4209,6 +4429,20 @@ void DumpBuf(screen_char_t* p, int n) {
}
}
+- (void)setVsplitMode: (BOOL)mode;
+{
+ vsplitMode = mode;
+ if (!mode) {
+ SCROLL_LEFT = 0;
+ SCROLL_RIGHT = WIDTH - 1;
+ }
+}
+
+- (BOOL)vsplitMode;
+{
+ return vsplitMode;
+}
+
- (void)blink
{
if ([self isAnyCharDirty]) {
diff --git a/VT100Terminal.h b/VT100Terminal.h
index 65682b3..1b335a4 100644
--- a/VT100Terminal.h
+++ b/VT100Terminal.h
@@ -106,6 +106,7 @@
#define VT100CSI_DECDSR 2050 // Device Status Report (DEC specific)
#define VT100CSI_SET_MODIFIERS 2051 // CSI > Ps; Pm m (Whether to set modifiers for different kinds of key presses; no official name)
#define VT100CSI_RESET_MODIFIERS 2052 // CSI > Ps n (Set all modifiers values to -1, disabled)
+#define VT100CSI_DECSLRM 2053 // Set left-right margin
// some xterm extension
#define XTERMCC_WIN_TITLE 86 // Set window title
diff --git a/VT100Terminal.m b/VT100Terminal.m
index 9ac2e0e..1cfc1c4 100644
--- a/VT100Terminal.m
+++ b/VT100Terminal.m
@@ -263,7 +263,7 @@ static int advanceAndEatControlChars(unsigned char **ppdata,
[SCREEN setNewLine];
break;
case VT100CC_CR:
- [SCREEN cursorToX:1 Y:[SCREEN cursorY]];
+ [SCREEN carriageReturn];
break;
case VT100CC_SO:
// TODO: ISO-2022 mode terminal should implement SO
@@ -458,7 +458,7 @@ static int getCSIParam(unsigned char *datap,
case VT100CC_LF:
case VT100CC_VT:
case VT100CC_FF: [SCREEN setNewLine]; break;
- case VT100CC_CR: [SCREEN cursorToX:1 Y:[SCREEN cursorY]]; break;
+ case VT100CC_CR: [SCREEN carriageReturn]; break;
case VT100CC_SO: break;
case VT100CC_SI: break;
case VT100CC_DC1: break;
@@ -1357,8 +1357,14 @@ static VT100TCC decode_csi_canonically(unsigned char *datap,
SET_PARAM_DEFAULT(param,0,0);
break;
case 's':
- result.type = ANSICSI_SCP;
- SET_PARAM_DEFAULT(param,0,0);
+ if (SCREEN.vsplitMode) {
+ result.type = VT100CSI_DECSLRM;
+ SET_PARAM_DEFAULT(param, 0, 1);
+ SET_PARAM_DEFAULT(param, 1, 1);
+ } else {
+ result.type = ANSICSI_SCP;
+ SET_PARAM_DEFAULT(param, 0, 0);
+ }
break;
case 'u':
result.type = ANSICSI_RCP;
@@ -2497,6 +2503,7 @@ static VT100TCC decode_string(unsigned char *datap,
MOUSE_MODE = MOUSE_REPORTING_NONE;
MOUSE_FORMAT = MOUSE_FORMAT_XTERM;
[SCREEN mouseModeDidChange:MOUSE_MODE];
+ SCREEN.vsplitMode = NO;
REPORT_FOCUS = NO;
TRACE = NO;
@@ -3309,6 +3316,9 @@ static VT100TCC decode_string(unsigned char *datap,
case 9: INTERLACE_MODE = mode; break;
case 25: [SCREEN showCursor: mode]; break;
case 40: allowColumnMode = mode; break;
+ case 69:
+ SCREEN.vsplitMode = mode;
+ break;
case 1049:
// From the xterm release log:
diff --git a/tests/slrm-test1.txt b/tests/slrm-test1.txt
new file mode 100644
index 0000000..bbf0d2f
--- /dev/null
+++ b/tests/slrm-test1.txt
@@ -0,0 +1,8 @@
+7[?69h8IRM:01234567890#####abcdefghTESTTEST01234567890TEST7[?69l8
+IRM-OK: 01234TEST567890 ##### 01234TEST56 abcTESTde
+7[?69h8ICH:01234567890#####abcdefgh[4@TEST[4@TEST01234567890[4@TEST7[?69l8
+ICH-OK: 01234TEST90 ##### 01234TEST56 abcTESTh
+7[?69h8DCH:01234567890#####abcdefgh012345678907[?69l8
+DCH-OK: 01234567890 ##### 0123490 abcdefgh
+ECH:#######################################################################7[?69h87[?69l8
+ECH-OK: ##### ########################################### ## ###
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment