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:
Siarzhuk Zharski
2013-03-14 07:44:47 +00:00
parent b0b7933ee7
commit 6d30b376e9
10 changed files with 179 additions and 23 deletions
+15 -1
View File
@@ -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"
+6
View File
@@ -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);
+11
View File
@@ -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;
+38 -4
View File
@@ -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.
+63 -15
View File
@@ -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;
+4 -1
View File
@@ -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;
+34
View File
@@ -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)
{
+4
View File
@@ -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);
+2 -2
View File
@@ -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 */
+2
View File
@@ -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