TUI using slang with pure ascii (7 bit) characters via termcap
I am using newt/snack (a TUI graphical Widgit library for Python based on slang) to have some interactive scripts. However for some target terminals the output of those screens are not very nice. I can change the look of them by changing the $TERM
variable to remove non printable characters, and to convert them to something more suitable. For example:
TERM=linux python myscript.py
So far the values I tested for $TERM
, yielded only moderate success.
Is there a known value for $TERM that consistently converts graphical characters:
┌────────────┤ Title ├────────────┐
│ │
│ Some text for the entry window │
│ │
│ foo _______________________ │
│ bar _______________________ │
│ baz _______________________ │
│ 开发者_如何学编程 │
│ ┌────┐ ┌────────┐ │
│ │ Ok │ │ Cancel │ │
│ └────┘ └────────┘ │
│ │
└─────────────────────────────────┘
into non graphical characters:
+------------| Title |------------+
| |
| Some text for the entry window |
| |
| foo _______________________ |
| bar _______________________ |
| baz _______________________ |
| |
| +----+ +--------+ |
| | Ok | | Cancel | |
| +----+ +--------+ |
| |
+---------------------------------+
short: no - it (newt and slang) simply doesn't do that.
long:
newt uses the function SLsmg_draw_box
which is shown here for reference:
void SLsmg_draw_box (int r, int c, unsigned int dr, unsigned int dc)
{
if (Smg_Mode == SMG_MODE_NONE) return;
if (!dr || !dc) return;
This_Row = r; This_Col = c;
dr--; dc--;
SLsmg_draw_hline (dc);
SLsmg_draw_vline (dr);
This_Row = r; This_Col = c;
SLsmg_draw_vline (dr);
SLsmg_draw_hline (dc);
SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
SLsmg_draw_object (r, c + (int) dc, SLSMG_URCORN_CHAR);
SLsmg_draw_object (r + (int) dr, c, SLSMG_LLCORN_CHAR);
SLsmg_draw_object (r + (int) dr, c + (int) dc, SLSMG_LRCORN_CHAR);
This_Row = r; This_Col = c;
}
In the slsmg.c
file, slang does have a table:
typedef struct
{
unsigned char vt100_char;
unsigned char ascii;
SLwchar_Type unicode; /* may have an ambiguous width */
SLwchar_Type unicode_narrow; /* has a narrow width */
}
ACS_Def_Type;
static SLCONST ACS_Def_Type UTF8_ACS_Map[] =
{
{'+', '>', 0x2192, '>'}, /* RIGHTWARDS ARROW [A] */
{',', '<', 0x2190, '<'}, /* LEFTWARDS ARROW [A] */
{'-', '^', 0x2191, 0x2303}, /* UPWARDS ARROW [A] */
{'.', 'v', 0x2193, 0x2304}, /* DOWNWARDS ARROW [A] */
but it will automatically choose the Unicode values if told by the application (newt) to use UTF-8 encoding. newt does that unconditionally, ignoring the terminal and locale information:
/**
* @brief Initialize the newt library
* @return int - 0 for success, else < 0
*/
int newtInit(void) {
char * MonoValue, * MonoEnv = "NEWT_MONO";
const char *lang;
int ret;
if ((lang = getenv("LC_ALL")) == NULL)
if ((lang = getenv("LC_CTYPE")) == NULL)
if ((lang = getenv("LANG")) == NULL)
lang = "";
/* slang doesn't support multibyte encodings except UTF-8,
avoid character corruption by redrawing the screen */
if (strstr (lang, ".euc") != NULL)
trashScreen = 1;
(void) strlen(ident);
SLutf8_enable(-1);
SLtt_get_terminfo();
SLtt_get_screen_size();
Back in slsmg.c
, the init_acs()
function will first try to use Unicode (and always succeed if your locale supports UTF-8). If it happens to be something else, the functions proceeds to use whatever information exists in the terminal description.
As a rule, if a terminal supports line-drawing characters, every terminal description is written to tell how to draw lines. If you modified a terminal description to remove those capabilities, you could get just ASCII (but that's based on just reading the function: slang has numerous hard-coded cases designed to fill in for terminal descriptions which don't behave as slang's author wants, and you might trip over one of those).
For what it's worth, the terminfo capabilities used by slang are: acsc
, enacs
, rmacs
, smacs
.
It might be based on your $LANG
being set to something like en_US.UTF-8
. Try changing it to en_US
(assuming your base locale is en_US
).
精彩评论