Support for underline and ibeam terminal cursor styles
* Add support for underline and i-beam cursor shapes. No corresponding UI configuration in preferences view ATM because preferences are waiting for refactoring and we need some eggs for this Easters. ;-) * Add handling of VT520/xterm specific DECSCUSR control sequences allowing applications to modify the style and blinking state of the cursor. May be utilized, for example, by console version of vim; * Implement cursor blinking/hiding on DECSET/DECRST commands.
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
#include <NodeInfo.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "PrefHandler.h"
|
||||
#include "TermConst.h"
|
||||
|
||||
|
||||
@@ -81,6 +80,7 @@ static const pref_defaults kTermDefaults[] = {
|
||||
{ PREF_WINDOW_TITLE, "%T %i: %t" },
|
||||
{ PREF_BLINK_CURSOR, PREF_TRUE },
|
||||
{ PREF_WARN_ON_EXIT, PREF_TRUE },
|
||||
{ PREF_CURSOR_STYLE, PREF_BLOCK_CURSOR },
|
||||
|
||||
{ NULL, NULL},
|
||||
};
|
||||
@@ -262,6 +262,20 @@ PrefHandler::getBool(const char *key)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PrefHandler::getCursor(const char *key)
|
||||
{
|
||||
const char *value = fContainer.FindString(key);
|
||||
if (value != NULL && strcmp(value, PREF_BLOCK_CURSOR) != 0) {
|
||||
if (strcmp(value, PREF_UNDERLINE_CURSOR) == 0)
|
||||
return UNDERLINE_CURSOR;
|
||||
if (strcmp(value, PREF_IBEAM_CURSOR) == 0)
|
||||
return IBEAM_CURSOR;
|
||||
}
|
||||
return BLOCK_CURSOR;
|
||||
}
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "Terminal getRGB"
|
||||
|
||||
|
||||
@@ -26,6 +26,11 @@ struct pref_defaults {
|
||||
#define PREF_TRUE "true"
|
||||
#define PREF_FALSE "false"
|
||||
|
||||
#define PREF_BLOCK_CURSOR "block"
|
||||
#define PREF_IBEAM_CURSOR "ibeam"
|
||||
#define PREF_UNDERLINE_CURSOR "underline"
|
||||
|
||||
|
||||
class BMessage;
|
||||
class BEntry;
|
||||
|
||||
@@ -49,6 +54,7 @@ class PrefHandler {
|
||||
const char* getString(const char *key);
|
||||
bool getBool(const char *key);
|
||||
rgb_color getRGB(const char *key);
|
||||
int getCursor(const char *key);
|
||||
|
||||
void setInt32(const char *key, int32 data);
|
||||
void setFloat(const char *key, float data);
|
||||
|
||||
@@ -105,6 +105,7 @@ static const uint32 MSG_SAVE_WINDOW_POSITION = 'swps';
|
||||
static const uint32 MSG_MOVE_TAB_LEFT = 'mvtl';
|
||||
static const uint32 MSG_MOVE_TAB_RIGHT = 'mvtr';
|
||||
static const uint32 MSG_ACTIVATE_TERM = 'msat';
|
||||
static const uint32 MSG_SET_CURSOR_STYLE = 'mscs';
|
||||
|
||||
|
||||
// Preference Read/Write Keys
|
||||
@@ -153,6 +154,7 @@ static const char* const PREF_TEXT_ENCODING = "Text encoding";
|
||||
|
||||
static const char* const PREF_BLINK_CURSOR = "Blinking cursor";
|
||||
static const char* const PREF_WARN_ON_EXIT = "Warn on exit";
|
||||
static const char* const PREF_CURSOR_STYLE = "Cursor style";
|
||||
|
||||
static const char* const PREF_TAB_TITLE = "Tab title";
|
||||
static const char* const PREF_WINDOW_TITLE = "Window title";
|
||||
@@ -169,6 +171,15 @@ enum {
|
||||
SELECTION_BACKGROUND_COLOR
|
||||
};
|
||||
|
||||
|
||||
// Cursor shape
|
||||
enum {
|
||||
BLOCK_CURSOR,
|
||||
UNDERLINE_CURSOR,
|
||||
IBEAM_CURSOR
|
||||
};
|
||||
|
||||
|
||||
// Preference Folder and setting path
|
||||
|
||||
static const int32 DEFAULT = -1;
|
||||
|
||||
@@ -694,6 +694,12 @@ TermParse::EscParse()
|
||||
param[nparam++] = DEFAULT;
|
||||
break;
|
||||
|
||||
case CASE_CSI_SP: // ESC [N q
|
||||
// part of change cursor style DECSCUSR
|
||||
if (nparam < NPARAM)
|
||||
param[nparam++] = ' ';
|
||||
break;
|
||||
|
||||
case CASE_DEC_STATE:
|
||||
/* enter dec mode */
|
||||
parsestate = gDecTable;
|
||||
@@ -988,6 +994,34 @@ TermParse::EscParse()
|
||||
parsestate = groundtable;
|
||||
break;
|
||||
|
||||
case CASE_DECSCUSR_ETC:
|
||||
// DECSCUSR - set cursor style VT520
|
||||
if (nparam == 2 && param[1] == ' ') {
|
||||
bool blinking = (param[0] & 0x01) != 0;
|
||||
int style = -1;
|
||||
switch (param[0]) {
|
||||
case 0:
|
||||
blinking = true;
|
||||
case 1:
|
||||
case 2:
|
||||
style = BLOCK_CURSOR;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
style = UNDERLINE_CURSOR;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
style = IBEAM_CURSOR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (style != -1)
|
||||
fBuffer->SetCursorStyle(style, blinking);
|
||||
}
|
||||
parsestate = groundtable;
|
||||
break;
|
||||
|
||||
case CASE_DECREQTPARM:
|
||||
// DEXREQTPARM - request terminal parameters
|
||||
_DecReqTermParms(param[0]);
|
||||
@@ -1344,11 +1378,11 @@ TermParse::_DecPrivateModeSet(int value)
|
||||
break;
|
||||
case 12:
|
||||
// Start Blinking Cursor.
|
||||
// Not supported yet.
|
||||
fBuffer->SetCursorBlinking(true);
|
||||
break;
|
||||
case 25:
|
||||
// Show Cursor.
|
||||
// Not supported yet.
|
||||
fBuffer->SetCursorHidden(false);
|
||||
break;
|
||||
case 47:
|
||||
// Use Alternate Screen Buffer.
|
||||
@@ -1419,11 +1453,11 @@ TermParse::_DecPrivateModeReset(int value)
|
||||
break;
|
||||
case 12:
|
||||
// Stop Blinking Cursor.
|
||||
// Not supported yet.
|
||||
fBuffer->SetCursorBlinking(false);
|
||||
break;
|
||||
case 25:
|
||||
// Hide Cursor
|
||||
// Not supported yet.
|
||||
fBuffer->SetCursorHidden(true);
|
||||
break;
|
||||
case 47:
|
||||
// Use Normal Screen Buffer.
|
||||
|
||||
@@ -300,7 +300,9 @@ TermView::_InitObject(const ShellParameters& shellParameters)
|
||||
fResizeViewDisableCount = 0;
|
||||
fLastActivityTime = 0;
|
||||
fCursorState = 0;
|
||||
fCursorHeight = 0;
|
||||
fCursorStyle = BLOCK_CURSOR;
|
||||
fCursorBlinking = true;
|
||||
fCursorHidden = false;
|
||||
fCursor = TermPos(0, 0);
|
||||
fTextBuffer = NULL;
|
||||
fVisibleTextBuffer = NULL;
|
||||
@@ -748,7 +750,9 @@ TermView::SetTermFont(const BFont *font)
|
||||
fFontAscent = font_ascent;
|
||||
fFontHeight = font_ascent + font_descent + font_leading + 1;
|
||||
|
||||
fCursorHeight = fFontHeight;
|
||||
fCursorStyle = PrefHandler::Default() == NULL ? BLOCK_CURSOR
|
||||
: PrefHandler::Default()->getCursor(PREF_CURSOR_STYLE);
|
||||
fCursorBlinking = PrefHandler::Default()->getBool(PREF_BLINK_CURSOR);
|
||||
|
||||
_ScrollTo(0, false);
|
||||
if (fScrollBar != NULL)
|
||||
@@ -881,18 +885,30 @@ TermView::_DetachShell()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::_SwitchCursorBlinking(bool blinkingOn)
|
||||
{
|
||||
if (blinkingOn) {
|
||||
if (fCursorBlinkRunner == NULL) {
|
||||
BMessage blinkMessage(kBlinkCursor);
|
||||
fCursorBlinkRunner = new (std::nothrow) BMessageRunner(
|
||||
BMessenger(this), &blinkMessage, kCursorBlinkInterval);
|
||||
}
|
||||
} else {
|
||||
// make sure the cursor becomes visible
|
||||
fCursorState = 0;
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
delete fCursorBlinkRunner;
|
||||
fCursorBlinkRunner = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::_Activate()
|
||||
{
|
||||
bool blinkCursor = PrefHandler::Default()->getBool(PREF_BLINK_CURSOR);
|
||||
|
||||
fActive = true;
|
||||
|
||||
if (fCursorBlinkRunner == NULL && blinkCursor) {
|
||||
BMessage blinkMessage(kBlinkCursor);
|
||||
fCursorBlinkRunner = new (std::nothrow) BMessageRunner(
|
||||
BMessenger(this), &blinkMessage, kCursorBlinkInterval);
|
||||
}
|
||||
_SwitchCursorBlinking(fCursorBlinking);
|
||||
}
|
||||
|
||||
|
||||
@@ -902,8 +918,8 @@ TermView::_Deactivate()
|
||||
// make sure the cursor becomes visible
|
||||
fCursorState = 0;
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
delete fCursorBlinkRunner;
|
||||
fCursorBlinkRunner = NULL;
|
||||
|
||||
_SwitchCursorBlinking(false);
|
||||
|
||||
fActive = false;
|
||||
}
|
||||
@@ -987,7 +1003,7 @@ TermView::_DrawCursor()
|
||||
{
|
||||
BRect rect(fFontWidth * fCursor.x, _LineOffset(fCursor.y), 0, 0);
|
||||
rect.right = rect.left + fFontWidth - 1;
|
||||
rect.bottom = rect.top + fCursorHeight - 1;
|
||||
rect.bottom = rect.top + fFontHeight - 1;
|
||||
int32 firstVisible = _LineAt(0);
|
||||
|
||||
UTF8Char character;
|
||||
@@ -995,9 +1011,24 @@ TermView::_DrawCursor()
|
||||
|
||||
bool cursorVisible = _IsCursorVisible();
|
||||
|
||||
if (cursorVisible) {
|
||||
switch (fCursorStyle) {
|
||||
case UNDERLINE_CURSOR:
|
||||
rect.top = rect.bottom - 2;
|
||||
break;
|
||||
case IBEAM_CURSOR:
|
||||
rect.right = rect.left + 1;
|
||||
break;
|
||||
case BLOCK_CURSOR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool selected = _CheckSelectedRegion(TermPos(fCursor.x, fCursor.y));
|
||||
if (fVisibleTextBuffer->GetChar(fCursor.y - firstVisible, fCursor.x,
|
||||
character, attr) == A_CHAR) {
|
||||
character, attr) == A_CHAR
|
||||
&& (fCursorStyle == BLOCK_CURSOR || !cursorVisible)) {
|
||||
int32 width;
|
||||
if (IS_WIDTH(attr))
|
||||
width = 2;
|
||||
@@ -1042,7 +1073,7 @@ TermView::_DrawCursor()
|
||||
bool
|
||||
TermView::_IsCursorVisible() const
|
||||
{
|
||||
return fCursorState < kCursorVisibleIntervals;
|
||||
return !fCursorHidden && fCursorState < kCursorVisibleIntervals;
|
||||
}
|
||||
|
||||
|
||||
@@ -1863,6 +1894,23 @@ TermView::MessageReceived(BMessage *msg)
|
||||
|
||||
break;
|
||||
}
|
||||
case MSG_SET_CURSOR_STYLE:
|
||||
{
|
||||
int32 style = BLOCK_CURSOR;
|
||||
if (msg->FindInt32("style", &style) == B_OK)
|
||||
fCursorStyle = style;
|
||||
|
||||
bool blinking = fCursorBlinking;
|
||||
if (msg->FindBool("blinking", &blinking) == B_OK) {
|
||||
fCursorBlinking = blinking;
|
||||
_SwitchCursorBlinking(fCursorBlinking);
|
||||
}
|
||||
|
||||
bool hidden = fCursorHidden;
|
||||
if (msg->FindBool("hidden", &hidden) == B_OK)
|
||||
fCursorHidden = hidden;
|
||||
break;
|
||||
}
|
||||
case MSG_REPORT_MOUSE_EVENT:
|
||||
{
|
||||
bool report;
|
||||
|
||||
@@ -160,6 +160,7 @@ private:
|
||||
|
||||
void _Activate();
|
||||
void _Deactivate();
|
||||
void _SwitchCursorBlinking(bool blinkingOn);
|
||||
|
||||
void _DrawLinePart(int32 x1, int32 y1, uint32 attr,
|
||||
char* buffer, int32 width, bool mouse,
|
||||
@@ -241,7 +242,9 @@ private:
|
||||
// Cursor Blinking, draw flag.
|
||||
bigtime_t fLastActivityTime;
|
||||
int32 fCursorState;
|
||||
int fCursorHeight;
|
||||
int fCursorStyle;
|
||||
bool fCursorBlinking;
|
||||
bool fCursorHidden;
|
||||
|
||||
// Cursor position.
|
||||
TermPos fCursor;
|
||||
|
||||
@@ -177,6 +177,40 @@ TerminalBuffer::ResetColors(uint8* indexes, int32 count, bool dynamic)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TerminalBuffer::SetCursorStyle(int32 style, bool blinking)
|
||||
{
|
||||
if (fListenerValid) {
|
||||
BMessage message(MSG_SET_CURSOR_STYLE);
|
||||
message.AddInt32("style", style);
|
||||
message.AddBool("blinking", blinking);
|
||||
fListener.SendMessage(&message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TerminalBuffer::SetCursorBlinking(bool blinking)
|
||||
{
|
||||
if (fListenerValid) {
|
||||
BMessage message(MSG_SET_CURSOR_STYLE);
|
||||
message.AddBool("blinking", blinking);
|
||||
fListener.SendMessage(&message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TerminalBuffer::SetCursorHidden(bool hidden)
|
||||
{
|
||||
if (fListenerValid) {
|
||||
BMessage message(MSG_SET_CURSOR_STYLE);
|
||||
message.AddBool("hidden", hidden);
|
||||
fListener.SendMessage(&message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TerminalBuffer::NotifyQuit(int32 reason)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,10 @@ public:
|
||||
int32 count = 1, bool dynamic = false);
|
||||
void ResetColors(uint8* indexes,
|
||||
int32 count = 1, bool dynamic = false);
|
||||
void SetCursorStyle(int32 style, bool blinking);
|
||||
void SetCursorBlinking(bool blinking);
|
||||
void SetCursorHidden(bool hidden);
|
||||
|
||||
void NotifyQuit(int32 reason);
|
||||
|
||||
virtual status_t ResizeTo(int32 width, int32 height);
|
||||
|
||||
@@ -1377,7 +1377,7 @@ CASE_IGNORE,
|
||||
CASE_IGNORE,
|
||||
CASE_IGNORE,
|
||||
/* SP ! " # */
|
||||
CASE_ESC_IGNORE,
|
||||
CASE_CSI_SP,
|
||||
CASE_ESC_IGNORE,
|
||||
CASE_ESC_IGNORE,
|
||||
CASE_ESC_IGNORE,
|
||||
@@ -1478,7 +1478,7 @@ CASE_CPR,
|
||||
CASE_GROUND_STATE,
|
||||
/* p q r s */
|
||||
CASE_GROUND_STATE,
|
||||
CASE_GROUND_STATE,
|
||||
CASE_DECSCUSR_ETC,
|
||||
CASE_DECSTBM,
|
||||
CASE_GROUND_STATE,
|
||||
/* t u v w */
|
||||
|
||||
@@ -125,3 +125,5 @@
|
||||
#define CASE_ECH 91 /* erase characters */
|
||||
|
||||
#define CASE_PRINT_GRA 92
|
||||
#define CASE_DECSCUSR_ETC 93
|
||||
#define CASE_CSI_SP 94
|
||||
|
||||
Reference in New Issue
Block a user