Forked from saitoha/iterm2-left-right-margin.diff
Last active
September 14, 2015 02:20
-
-
Save zchee/eb98d50e390823dd79ce to your computer and use it in GitHub Desktop.
Add DECLRMM(DECVSSM) and DECSLRM feature to iTerm2 (on progress)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 @@ | |
+[1;1H[2J7[?69h[20;70s8[1GIRM:[10G01234567890[30G#####[72Gabcdefgh[4h[75GTEST[15GTEST[60G01234567890[65GTEST[4l7[s[?69l8 | |
+IRM-OK: 01234TEST567890 ##### 01234TEST56 abcTESTde | |
+7[?69h[20;70s8[1GICH:[10G01234567890[30G#####[72Gabcdefgh[75G[4@TEST[15G[4@TEST[60G01234567890[65G[4@TEST7[s[?69l8 | |
+ICH-OK: 01234TEST90 ##### 01234TEST56 abcTESTh | |
+7[?69h[20;70s8[1GDCH:[10G01234567890[30G#####[72Gabcdefgh[75G[4P[15G[4P[60G01234567890[65G[4P7[s[?69l8 | |
+DCH-OK: 01234567890 ##### 0123490 abcdefgh | |
+[1GECH:[10G#######################################################################7[?69h[20;70s8[15G[10X[68G[5X[75G[3X7[s[?69l8 | |
+ECH-OK: ##### ########################################### ## ### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment