1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
elinks/src/osdep/osdep.c

912 lines
18 KiB
C
Raw Normal View History

/* Features which vary with the OS */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#ifdef HAVE_IO_H
#include <io.h> /* For win32 && set_bin(). */
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_SIGNAL_H
#include <sys/signal.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> /* Need to be after sys/types.h */
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* OS/2 needs this after sys/types.h */
#endif
/* We need to have it here. Stupid BSD. */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
/* This is for some exotic TOS mangling when handling passive FTP sockets. */
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#else
#ifdef HAVE_NETINET_IN_SYSTEM_H
#include <netinet/in_system.h>
#endif
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_LOCALE_H
/* For the sake of SunOS, keep this away from files including
* intl/gettext/libintl.h because <locale.h> includes system <libintl.h> which
* either includes system gettext header or contains gettext function
* declarations. */
#include <locale.h>
#endif
#ifdef HAVE_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
#include "elinks.h"
#include "main/select.h"
#include "osdep/osdep.h"
#include "osdep/signals.h"
#include "terminal/terminal.h"
#include "util/conv.h"
#include "util/memory.h"
#include "util/string.h"
/* Set a file descriptor to non-blocking mode. It returns a non-zero value
* on error. */
int
set_nonblocking_fd(int fd)
{
#if defined(O_NONBLOCK) || defined(O_NDELAY)
int flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) return -1;
#if defined(O_NONBLOCK)
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
return fcntl(fd, F_SETFL, flags | O_NDELAY);
#endif
#elif defined(FIONBIO)
int flag = 1;
return ioctl(fd, FIONBIO, &flag);
#else
return 0;
#endif
}
/* Set a file descriptor to blocking mode. It returns a non-zero value on
* error. */
int
set_blocking_fd(int fd)
{
#if defined(O_NONBLOCK) || defined(O_NDELAY)
int flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) return -1;
#if defined(O_NONBLOCK)
return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
#else
return fcntl(fd, F_SETFL, flags & ~O_NDELAY);
#endif
#elif defined(FIONBIO)
int flag = 0;
return ioctl(fd, FIONBIO, &flag);
#else
return 0;
#endif
}
void
set_ip_tos_throughput(int socket)
{
#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
int on = IPTOS_THROUGHPUT;
setsockopt(socket, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(on));
#endif
}
int
get_e(unsigned char *env)
{
char *v = getenv(env);
return (v ? atoi(v) : 0);
}
unsigned char *
get_cwd(void)
{
int bufsize = 128;
unsigned char *buf;
while (1) {
buf = mem_alloc(bufsize);
if (!buf) return NULL;
if (getcwd(buf, bufsize)) return buf;
mem_free(buf);
if (errno == EINTR) continue;
if (errno != ERANGE) return NULL;
bufsize += 128;
}
return NULL;
}
void
set_cwd(unsigned char *path)
{
if (path) while (chdir(path) && errno == EINTR);
}
unsigned char *
get_shell(void)
{
unsigned char *shell = GETSHELL;
if (!shell || !*shell)
shell = DEFAULT_SHELL;
return shell;
}
/* Terminal size */
2006-01-11 14:10:27 -05:00
#if !defined(CONFIG_OS_OS2) && !defined(CONFIG_OS_WIN32)
static void
sigwinch(void *s)
{
((void (*)(void)) s)();
}
void
handle_terminal_resize(int fd, void (*fn)(void))
{
install_signal_handler(SIGWINCH, sigwinch, fn, 0);
}
void
unhandle_terminal_resize(int fd)
{
install_signal_handler(SIGWINCH, NULL, NULL, 0);
}
void
get_terminal_size(int fd, int *x, int *y)
{
struct winsize ws;
if (ioctl(1, TIOCGWINSZ, &ws) != -1) {
*x = ws.ws_col;
*y = ws.ws_row;
} else {
*x = 0;
*y = 0;
}
if (!*x) {
*x = get_e("COLUMNS");
if (!*x) *x = DEFAULT_TERMINAL_WIDTH;
}
if (!*y) {
*y = get_e("LINES");
if (!*y) *y = DEFAULT_TERMINAL_HEIGHT;
}
}
#endif
/* Pipe */
2006-01-11 14:12:59 -05:00
#if defined(CONFIG_OS_UNIX) || defined(CONFIG_OS_BEOS) || defined(CONFIG_OS_RISCOS)
void
set_bin(int fd)
{
}
int
c_pipe(int *fd)
{
return pipe(fd);
}
2006-01-11 14:10:27 -05:00
#elif defined(CONFIG_OS_OS2) || defined(CONFIG_OS_WIN32)
void
set_bin(int fd)
{
setmode(fd, O_BINARY);
}
int
c_pipe(int *fd)
{
int r = pipe(fd);
if (!r) {
set_bin(fd[0]);
set_bin(fd[1]);
}
return r;
}
#endif
/* Exec */
int
is_twterm(void) /* Check if it make sense to call a twterm. */
{
static int tw = -1;
if (tw == -1) tw = !!getenv("TWDISPLAY");
return tw;
}
int
is_gnuscreen(void)
{
static int screen = -1;
if (screen == -1) screen = !!getenv("STY");
return screen;
}
2006-01-11 14:10:27 -05:00
#if defined(CONFIG_OS_UNIX) || defined(CONFIG_OS_WIN32)
int
is_xterm(void)
{
static int xt = -1;
if (xt == -1) {
/* Paraphrased from debian bug 228977:
*
* It is not enough to simply check the DISPLAY env variable,
* as it is pretty legal to have a DISPLAY set. While these
* days this practice is pretty uncommon, it still makes sense
* sometimes, especially for people who prefer the text mode
* for some reason. Only relying on DISPLAY will results in bad
* codes being written to the terminal.
*
* Any real xterm derivative sets WINDOWID as well.
* Unfortunately, konsole is an exception, and it needs to be
* checked for separately.
*
* FIXME: The code below still fails to detect some terminals
* that do support a title (like the popular PuTTY ssh client).
* In general, proper xterm detection is a nightmarish task...
*
* -- Adam Borowski <kilobyte@mimuw.edu.pl> */
unsigned char *display = getenv("DISPLAY");
unsigned char *windowid = getenv("WINDOWID");
if (!windowid || !*windowid)
windowid = getenv("KONSOLE_DCOP_SESSION");
xt = (display && *display && windowid && *windowid);
}
return xt;
}
#endif
unsigned int resize_count = 0;
2006-01-11 14:10:26 -05:00
#ifndef CONFIG_OS_OS2
2006-01-11 14:12:59 -05:00
#if !(defined(CONFIG_OS_BEOS) && defined(HAVE_SETPGID)) && !defined(CONFIG_OS_WIN32)
int
exe(unsigned char *path)
{
return system(path);
}
#endif
2006-01-06 06:02:51 -05:00
static unsigned char *clipboard;
unsigned char *
2006-01-06 06:02:51 -05:00
get_clipboard_text(void)
{
/* The following support for GNU Screen's clipboard is
* disabled for two reasons:
*
* 1. It does not actually return the string from that
* clipboard, but rather causes the clipboard contents to
* appear in stdin. get_clipboard_text is normally called
* because the user pressed a Paste key in an input field,
* so the characters end up being inserted in that field;
* but if there are newlines in the clipboard, then the
* field may lose focus, in which case the remaining
* characters may trigger arbitrary actions in ELinks.
*
* 2. It pastes from both GNU Screen's clipboard and the ELinks
* internal clipboard. Because set_clipboard_text also sets
* them both, the same text would typically get pasted twice.
*
* Users can instead use the GNU Screen key bindings to run the
* paste command. This method still suffers from problem 1 but
* any user of GNU Screen should know that already. */
#if 0
/* GNU Screen's clipboard */
if (is_gnuscreen()) {
struct string str;
if (!init_string(&str)) return NULL;
add_to_string(&str, "screen -X paste .");
if (str.length) exe(str.source);
if (str.source) done_string(&str);
}
#endif
return stracpy(empty_string_or_(clipboard));
}
void
set_clipboard_text(unsigned char *data)
{
/* GNU Screen's clipboard */
if (is_gnuscreen()) {
struct string str;
if (!init_string(&str)) return;
add_to_string(&str, "screen -X register . ");
add_shell_quoted_to_string(&str, data, strlen(data));
if (str.length) exe(str.source);
if (str.source) done_string(&str);
}
/* Shouldn't complain about leaks. */
if (clipboard) free(clipboard);
clipboard = strdup(data);
}
/* Set xterm-like term window's title. */
void
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
set_window_title(unsigned char *title, int codepage)
{
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
struct string filtered;
#ifndef HAVE_SYS_CYGWIN_H
/* Check if we're in a xterm-like terminal. */
if (!is_xterm() && !is_gnuscreen()) return;
#endif
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
if (!init_string(&filtered)) return;
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
/* Copy title to filtered if different from NULL */
if (title) {
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
unsigned char *scan = title;
unsigned char *end = title + strlen(title);
/* Remove control characters, so that they cannot
* interfere with the command we send to the terminal.
* However, do not attempt to limit the title length
* to terminal width, because the title is usually
* drawn in a different font anyway. */
/* Note that this is the right place where to do it, since
* potential alternative set_window_title() routines might
* want to take different precautions. */
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
for (;;) {
unsigned char *charbegin = scan;
unicode_val_T unicode
= cp_to_unicode(codepage, &scan, end);
int charlen = scan - charbegin;
if (unicode == UCS_NO_CHAR)
break;
/* This need not recognize all Unicode control
* characters. Only those that can make the
* terminal misparse the command. */
if (unicode < 0x20
|| (unicode >= 0x7F && unicode < 0xA0))
continue;
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
/* xterm entirely rejects 1024-byte or longer
* titles. */
if (filtered.length + charlen >= 1024 - 3) {
add_to_string(&filtered, "...");
break;
}
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
add_bytes_to_string(&filtered, charbegin, charlen);
}
}
/* Send terminal escape sequence + title string */
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
printf("\033]0;%s\a", filtered.source);
#if 0
/* Miciah don't like this so it is disabled because it changes the
* default window name. --jonas */
/* Set the GNU screen window name */
if (is_gnuscreen())
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
printf("\033k%s\033\134", filtered.source);
#endif
fflush(stdout);
Bug 885: Proper charset support in xterm window title When ELinks runs in an X11 terminal emulator (e.g. xterm), or in GNU Screen, it tries to update the title of the window to match the title of the current document. To do this, ELinks sends an "OSC 1 ; Pt BEL" sequence to the terminal. Unfortunately, xterm expects the Pt string to be in the ISO-8859-1 charset, making it impossible to display e.g. Cyrillic characters. In xterm patch #210 (2006-03-12) however, there is a menu item and a resource that can make xterm take the Pt string in UTF-8 instead, allowing characters from all around the world. The downside is that ELinks apparently cannot ask xterm whether the setting is on or off; so add a terminal._template_.latin1_title option to ELinks and let the user edit that instead. Complete list of changes: - Add the terminal._template_.latin1_title option. But do not add that to the terminal options window because it's already rather crowded there. - In set_window_title(), take a new codepage argument. Use it to decode the title into Unicode characters, and remove only actual control characters. For example, CP437 has graphical characters in the 0x80...0x9F range, so don't remove those, even though ISO-8859-1 has control characters in the same range. Likewise, don't misinterpret single bytes of UTF-8 characters as control characters. - In set_window_title(), do not truncate the title to the width of the window. The font is likely to be different and proportional anyway. But do truncate before 1024 bytes, an xterm limit. - In struct itrm, add a title_codepage member to remember which charset the master said it was going to use in the terminal window title. Initialize title_codepage in handle_trm(), update it in dispatch_special() if the master sends the new request TERM_FN_TITLE_CODEPAGE, and use it in most set_window_title() calls; but not in the one that sets $TERM as the title, because that string was not received from the master and should consist of ASCII characters only. - In set_terminal_title(), convert the caller-provided title to ISO-8859-1 or UTF-8 if appropriate, and report the codepage to the slave with the new TERM_FN_TITLE_CODEPAGE request. The conversion can run out of memory, so return a success/error flag, rather than void. In display_window_title(), check this result and don't update caches on error. - Add a NEWS entry for all of this.
2008-12-28 20:09:53 -05:00
done_string(&filtered);
}
#ifdef HAVE_X11
static int x_error = 0;
static int
catch_x_error(void)
{
x_error = 1;
return 0;
}
#endif
unsigned char *
get_window_title(void)
{
#ifdef HAVE_X11
/* Following code is stolen from our beloved vim. */
unsigned char *winid;
Display *display;
Window window, root, parent, *children;
XTextProperty text_prop;
Status status;
unsigned int num_children;
unsigned char *ret = NULL;
if (!is_xterm())
return NULL;
winid = getenv("WINDOWID");
if (!winid)
return NULL;
window = (Window) atol(winid);
if (!window)
return NULL;
display = XOpenDisplay(NULL);
if (!display)
return NULL;
/* If WINDOWID is bad, we don't want X to abort us. */
x_error = 0;
XSetErrorHandler((int (*)(Display *, XErrorEvent *)) catch_x_error);
status = XGetWMName(display, window, &text_prop);
/* status = XGetWMIconName(x11_display, x11_window, &text_prop); */
while (!x_error && (!status || !text_prop.value)) {
if (!XQueryTree(display, window, &root, &parent, &children, &num_children))
break;
if (children)
XFree((void *) children);
if (parent == root || parent == 0)
break;
window = parent;
status = XGetWMName(display, window, &text_prop);
}
if (!x_error && status && text_prop.value) {
ret = stracpy(text_prop.value);
XFree(text_prop.value);
}
XCloseDisplay(display);
return ret;
#else
/* At least reset the window title to a blank one. */
return stracpy("");
#endif
}
int
resize_window(int width, int height, int old_width, int old_height)
{
#ifdef HAVE_X11
/* Following code is stolen from our beloved vim. */
unsigned char *winid;
Display *display;
Window window;
Status status;
XWindowAttributes attributes;
if (!is_xterm())
return -1;
winid = getenv("WINDOWID");
if (!winid)
return -1;
window = (Window) atol(winid);
if (!window)
return -1;
display = XOpenDisplay(NULL);
if (!display)
return -1;
/* If WINDOWID is bad, we don't want X to abort us. */
x_error = 0;
XSetErrorHandler((int (*)(Display *, XErrorEvent *)) catch_x_error);
status = XGetWindowAttributes(display, window, &attributes);
while (!x_error && !status) {
Window root, parent, *children;
unsigned int num_children;
if (!XQueryTree(display, window, &root, &parent, &children, &num_children))
break;
if (children)
XFree((void *) children);
if (parent == root || parent == 0)
break;
window = parent;
status = XGetWindowAttributes(display, window, &attributes);
}
if (!x_error && status) {
XSizeHints *size_hints;
long mask;
int px_width = 0;
int px_height = 0;
/* With xterm 210, a window with 80x24 characters at
* a 6x13 font appears to have 484x316 pixels; both
* the width and height include four extra pixels.
* Computing a new size by scaling these values often
* results in windows that cannot display as many
* characters as was intended. We can do better if we
* can find out the actual size of character cells.
* If the terminal emulator has set a window size
* increment, assume that is the cell size. */
size_hints = XAllocSizeHints();
if (size_hints != NULL
&& XGetWMNormalHints(display, window, size_hints, &mask)
&& (mask & PResizeInc) != 0) {
px_width = attributes.width
+ (width - old_width) * size_hints->width_inc;
px_height = attributes.height
+ (height - old_height) * size_hints->height_inc;
}
if (px_width <= 0 || px_height <= 0) {
double ratio_width = (double) attributes.width / old_width;
double ratio_height = (double) attributes.height / old_height;
px_width = (int) ((double) width * ratio_width);
px_height = (int) ((double) height * ratio_height);
}
if (size_hints)
XFree(size_hints);
status = XResizeWindow(display, window, px_width, px_height);
while (!x_error && !status) {
Window root, parent, *children;
unsigned int num_children;
if (!XQueryTree(display, window, &root, &parent, &children, &num_children))
break;
if (children)
XFree((void *) children);
if (parent == root || parent == 0)
break;
window = parent;
status = XResizeWindow(display, window, px_width, px_height);
}
}
XCloseDisplay(display);
return 0;
#else
return -1;
#endif
}
#endif
/* Threads */
2006-01-11 14:12:59 -05:00
#if defined(HAVE_BEGINTHREAD) || defined(CONFIG_OS_BEOS)
struct tdata {
void (*fn)(void *, int);
int h;
unsigned char data[1];
};
void
bgt(struct tdata *t)
{
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
t->fn(t->data, t->h);
write(t->h, "x", 1);
close(t->h);
free(t);
}
#else
int
start_thread(void (*fn)(void *, int), void *ptr, int l)
{
int p[2];
pid_t pid;
if (c_pipe(p) < 0) return -1;
if (set_nonblocking_fd(p[0]) < 0) return -1;
if (set_nonblocking_fd(p[1]) < 0) return -1;
pid = fork();
if (!pid) {
struct terminal *term;
/* Close input in this thread; otherwise, if it will live
* longer than its parent, it'll block the terminal until it'll
* quit as well; this way it will hopefully just die unseen and
* in background, causing no trouble. */
/* Particularly, when async dns resolving was in progress and
* someone quitted ELinks, it could make a delay before the
* terminal would be really freed and returned to shell. */
foreach (term, terminals)
if (term->fdin > 0)
close(term->fdin);
close(p[0]);
fn(ptr, p[1]);
write(p[1], "x", 1);
close(p[1]);
/* We use _exit() here instead of exit(), see
* http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC6 for
* reasons. Fixed by Sven Neumann <sven@convergence.de>. */
_exit(0);
}
if (pid == -1) {
close(p[0]);
close(p[1]);
return -1;
}
close(p[1]);
return p[0];
}
#endif
#ifndef OS2_MOUSE
void
want_draw(void)
{
}
void
done_draw(void)
{
}
#endif
2006-01-11 14:10:27 -05:00
#if !defined(CONFIG_OS_WIN32)
int
get_output_handle(void)
{
return 1;
}
int
get_ctl_handle(void)
{
static int fd = -1;
if (isatty(0)) return 0;
if (fd < 0) fd = open("/dev/tty", O_RDONLY);
return fd;
}
#endif
2006-01-11 14:12:59 -05:00
#if !defined(CONFIG_OS_BEOS) && !(defined(HAVE_BEGINTHREAD) && defined(HAVE_READ_KBD)) \
2006-01-11 14:10:27 -05:00
&& !defined(CONFIG_OS_WIN32)
int
get_input_handle(void)
{
return get_ctl_handle();
}
#endif
2006-01-11 14:10:27 -05:00
#ifndef CONFIG_OS_WIN32
void
init_osdep(void)
{
#ifdef HAVE_LOCALE_H
setlocale(LC_ALL, "");
#endif
}
#endif
2006-01-11 14:10:27 -05:00
#if defined(CONFIG_OS_UNIX) || defined(CONFIG_OS_OS2) || defined(CONFIG_OS_RISCOS)
void
terminate_osdep(void)
{
}
#endif
2006-01-11 14:12:59 -05:00
#ifndef CONFIG_OS_BEOS
void
block_stdin(void)
{
}
void
unblock_stdin(void)
{
}
#endif
void
elinks_cfmakeraw(struct termios *t)
{
/* This elinks_cfmakeraw() intentionally leaves the following
* settings unchanged, even though the standard cfmakeraw()
* would change some of them:
*
* - c_cflag & CSIZE: number of bits per character.
* Bug 54 asked ELinks not to change this.
* - c_cflag & (PARENB | PARODD): parity bit in characters.
* Bug 54 asked ELinks not to change this.
* - c_iflag & (IXON | IXOFF | IXANY): XON/XOFF flow control.
*
* The reasoning is, if the user has set up unusual values for
* those settings before starting ELinks, then the terminal
* probably expects those values and ELinks should not mess
* with them. */
t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
t->c_oflag &= ~OPOST;
t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
t->c_cc[VMIN] = 1;
t->c_cc[VTIME] = 0;
}
#if !defined(CONFIG_MOUSE) || (!defined(CONFIG_GPM) && !defined(CONFIG_SYSMOUSE) && !defined(OS2_MOUSE))
void *
handle_mouse(int cons, void (*fn)(void *, unsigned char *, int),
void *data)
{
return NULL;
}
void
unhandle_mouse(void *data)
{
}
void
suspend_mouse(void *data)
{
}
void
resume_mouse(void *data)
{
}
#endif
2006-01-11 14:10:27 -05:00
#ifndef CONFIG_OS_WIN32
/* Create a bitmask consisting from system-independent envirnoment modifiers.
* This is then complemented by system-specific modifiers in an appropriate
* get_system_env() routine. */
static int
get_common_env(void)
{
int env = 0;
if (is_xterm()) env |= ENV_XWIN;
if (is_twterm()) env |= ENV_TWIN;
if (is_gnuscreen()) env |= ENV_SCREEN;
/* ENV_CONSOLE is always set now and indicates that we are working w/ a
* displaying-capable character-adressed terminal. Sounds purely
* theoretically now, but it already makes some things easier and it
* could give us interesting opportunities later (after graphical
* frontends will be introduced, when working in some mysterious daemon
* mode or who knows what ;). --pasky */
env |= ENV_CONSOLE;
return env;
}
#endif
2006-01-11 14:10:27 -05:00
#if defined(CONFIG_OS_UNIX) || defined(CONFIG_OS_RISCOS)
int
get_system_env(void)
{
return get_common_env();
}
#endif
int
can_resize_window(int environment)
{
return !!(environment & (ENV_OS2VIO | ENV_XWIN));
}
2006-01-11 14:10:26 -05:00
#ifndef CONFIG_OS_OS2
int
can_open_os_shell(int environment)
{
return 1;
}
void
set_highpri(void)
{
}
#endif
unsigned char *
get_system_str(int xwin)
{
return xwin ? SYSTEM_STR "-xwin" : SYSTEM_STR;
}