Add r_cons_is_utf8 () and use it to setup scr.utf8 on non-quiet mode

This commit is contained in:
pancake 2014-08-25 03:17:22 +02:00
parent 492cecdcb9
commit 2eefd8908e
4 changed files with 217 additions and 5 deletions

View file

@ -477,10 +477,8 @@ int main(int argc, char **argv, char **envp) {
r_config_set (r.config, "io.va", "false");
}
}
{ // if $LANG contains UTF-8, let's use UTF-8 in r2
const char *env_lang = r_sys_getenv ("LANG");
if (env_lang && strstr (env_lang, "UTF-8"))
r_config_set_i (r.config, "scr.utf8", R_TRUE);
if (!quiet && r_cons_is_utf8 ()) {
r_config_set_i (r.config, "scr.utf8", R_TRUE);
}
if (run_rc) {
char *homerc = r_str_home (".radare2rc");

View file

@ -1,7 +1,7 @@
include ../config.mk
NAME=r_cons
OBJS=cons.o pipe.o output.o grep.o canvas.o less.o
OBJS=cons.o pipe.o output.o grep.o canvas.o less.o utf8.o
OBJS+=line.o hud.o rgb.o input.o pal.o editor.o 2048.o
DEPS=r_util

213
libr/cons/utf8.c Normal file
View file

@ -0,0 +1,213 @@
/* radare - LGPL - Copyright 2014 - pancake */
// Copypasta from http://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
#include <r_cons.h>
#if __UNIX__
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#define RD_EOF -1
#define RD_EIO -2
static inline int rd(const int fd) {
unsigned char buffer[4];
ssize_t n;
while (1) {
n = read(fd, buffer, 1);
if (n > (ssize_t)0) {
return buffer[0];
}
if (n == (ssize_t)0)
return RD_EOF;
if (n != (ssize_t)-1)
return RD_EIO;
if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
return RD_EIO;
}
}
static inline int wr(const int fd, const char *const data, const size_t bytes) {
const char *head = data;
const char *const tail = data + bytes;
ssize_t n;
while (head < tail) {
n = write(fd, head, (size_t)(tail - head));
if (n > (ssize_t)0) {
head += n;
continue;
}
if (n != (ssize_t)-1)
return EIO;
if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
return errno;
}
return 0;
}
/* Return a new file descriptor to the current TTY.
*/
int current_tty(void) {
const char *dev;
int fd;
dev = ttyname(STDIN_FILENO);
if (!dev)
dev = ttyname(STDOUT_FILENO);
if (!dev)
dev = ttyname(STDERR_FILENO);
if (!dev) {
errno = ENOTTY;
return -1;
}
do {
fd = open(dev, O_RDWR | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd == -1)
return -1;
return fd;
}
/* As the tty for current cursor position.
* This function returns 0 if success, errno code otherwise.
* Actual errno will be unchanged.
*/
static int cursor_position(const int tty, int *const rowptr, int *const colptr) {
struct termios saved, temporary;
int ret, res, rows, cols, saved_errno;
/* Bad tty? */
if (tty == -1)
return ENOTTY;
saved_errno = errno;
/* Save current terminal settings. */
do {
res = tcgetattr(tty, &saved);
} while (res == -1 && errno == EINTR);
if (res == -1) {
ret = errno;
errno = saved_errno;
return ret;
}
/* Get current terminal settings for basis, too. */
do {
res = tcgetattr(tty, &temporary);
} while (res == -1 && errno == EINTR);
if (res == -1) {
ret = errno;
errno = saved_errno;
return ret;
}
/* Disable ICANON, ECHO, and CREAD. */
temporary.c_lflag &= ~ICANON;
temporary.c_lflag &= ~ECHO;
temporary.c_cflag &= ~CREAD;
/* This loop is only executed once. When broken out,
* the terminal settings will be restored, and the function
* will return ret to caller. It's better than goto.
*/
do {
/* Set modified settings. */
do {
res = tcsetattr(tty, TCSANOW, &temporary);
} while (res == -1 && errno == EINTR);
if (res == -1) {
ret = errno;
break;
}
/* Request cursor coordinates from the terminal. */
ret = wr(tty, "\033[6n", 4);
if (ret)
break;
/* Assume coordinate reponse parsing fails. */
ret = EIO;
/* Expect an ESC. */
res = rd(tty);
if (res != 27)
break;
/* Expect [ after the ESC. */
res = rd(tty);
if (res != '[')
break;
/* Parse rows. */
rows = 0;
res = rd(tty);
while (res >= '0' && res <= '9') {
rows = 10 * rows + res - '0';
res = rd(tty);
}
if (res != ';')
break;
/* Parse cols. */
cols = 0;
res = rd(tty);
while (res >= '0' && res <= '9') {
cols = 10 * cols + res - '0';
res = rd(tty);
}
if (res != 'R')
break;
/* Success! */
if (rowptr)
*rowptr = rows;
if (colptr)
*colptr = cols;
ret = 0;
} while (0);
/* Restore saved terminal settings. */
do {
res = tcsetattr (tty, TCSANOW, &saved);
} while (res == -1 && errno == EINTR);
if (res == -1 && !ret)
ret = errno;
/* Done. */
return ret;
}
R_API int r_cons_is_utf8() {
int row = 0, col = 0;
int row2 = 0, col2 = 0;
int fd = current_tty();
if (fd == -1)
return 0;
if (cursor_position(fd, &row, &col))
return 0;
write (1, "\xc3\x89\xc3\xa9", 4);
if (cursor_position (fd, &row2, &col2))
return 0;
write (1, "\r \r", 6);
return ((col2-col)==2);
}
#else
R_API int r_cons_is_utf8() {
return 0;
}
#endif

View file

@ -312,6 +312,7 @@ R_API void r_cons_2048();
R_API void r_cons_memset(char ch, int len);
R_API void r_cons_visual_flush();
R_API void r_cons_visual_write (char *buffer);
R_API int r_cons_is_utf8();
/* input */
//R_API int r_cons_fgets(char *buf, int len, int argc, const char **argv);