mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
Issue: #381: Try to handle X11 input and UTF-8 better.
In window_get_text_prop do conversion when input is of type STRING. (latin1) to utf8. Dmenu: don't skip invalid lines, but try to display as much as possible. Window mode: Double check all input from X.
This commit is contained in:
parent
c3b236db28
commit
e54e012500
8 changed files with 73 additions and 13 deletions
|
@ -166,5 +166,10 @@ void cmd_set_arguments ( int argc, char **argv );
|
|||
char *rofi_expand_path ( const char *input );
|
||||
unsigned int levenshtein ( const char *needle, const char *haystack );
|
||||
|
||||
/**
|
||||
* Convert string to valid utf-8, replacing invalid parts with replacement character.
|
||||
*/
|
||||
char * rofi_force_utf8 ( gchar *data );
|
||||
char * rofi_latin_to_utf8_strdup ( const char *input, gssize length );
|
||||
/*@}*/
|
||||
#endif // ROFI_HELPER_H
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* The 'object' that makes a mode in rofi.
|
||||
* @{
|
||||
*/
|
||||
typedef struct rofi_mode Mode;
|
||||
typedef struct rofi_mode Mode;
|
||||
|
||||
/**
|
||||
* Enum used to sum the possible states of ROFI.
|
||||
|
|
|
@ -36,6 +36,8 @@ void window_set_atom_prop ( xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms,
|
|||
#define EWMH_ATOMS( X ) \
|
||||
X ( _NET_WM_WINDOW_OPACITY ), \
|
||||
X ( I3_SOCKET_PATH ), \
|
||||
X ( UTF8_STRING ), \
|
||||
X ( STRING ), \
|
||||
X ( WM_WINDOW_ROLE )
|
||||
|
||||
enum { EWMH_ATOMS ( ATOM_ENUM ), NUM_NETATOMS };
|
||||
|
|
|
@ -92,10 +92,8 @@ static char **get_dmenu ( DmenuModePrivateData *pd, FILE *fd, unsigned int *leng
|
|||
data[l - 1] = '\0';
|
||||
l--;
|
||||
}
|
||||
if ( !g_utf8_validate ( data, l, NULL ) ) {
|
||||
fprintf ( stderr, "String: '%s' is not valid utf-8\n", data );
|
||||
continue;
|
||||
}
|
||||
data = rofi_force_utf8 ( data );
|
||||
printf ( "data: %s\n", data );
|
||||
|
||||
retv[( *length )] = data;
|
||||
data = NULL;
|
||||
|
|
|
@ -53,8 +53,6 @@
|
|||
|
||||
#define WINLIST 32
|
||||
|
||||
#define CLIENTTITLE 100
|
||||
#define CLIENTCLASS 50
|
||||
#define CLIENTSTATE 10
|
||||
#define CLIENTWINDOWTYPE 10
|
||||
#define CLIENTROLE 50
|
||||
|
@ -285,7 +283,8 @@ static client* window_client ( xcb_window_t win )
|
|||
cky = xcb_icccm_get_wm_class ( xcb->connection, c->window );
|
||||
xcb_icccm_get_wm_class_reply_t wcr;
|
||||
if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) {
|
||||
c->class = g_strdup ( wcr.class_name );
|
||||
c->class = rofi_latin_to_utf8_strdup ( wcr.class_name, -1 );
|
||||
c->name = rofi_latin_to_utf8_strdup ( wcr.instance_name, -1 );
|
||||
xcb_icccm_get_wm_class_reply_wipe ( &wcr );
|
||||
}
|
||||
|
||||
|
@ -295,6 +294,14 @@ static client* window_client ( xcb_window_t win )
|
|||
c->hint_flags = r.flags;
|
||||
}
|
||||
|
||||
/** Do UTF-8 Check, should not be needed, does not hurt here to be paranoid. */
|
||||
{
|
||||
c->title = rofi_force_utf8 ( c->title );
|
||||
c->class = rofi_force_utf8 ( c->class );
|
||||
c->name = rofi_force_utf8 ( c->name );
|
||||
c->role = rofi_force_utf8 ( c->role );
|
||||
}
|
||||
|
||||
winlist_append ( cache_client, c->window, c );
|
||||
g_free ( attr );
|
||||
return c;
|
||||
|
|
|
@ -659,3 +659,42 @@ unsigned int levenshtein ( const char *needle, const char *haystack )
|
|||
}
|
||||
return column[needlelen];
|
||||
}
|
||||
|
||||
char * rofi_latin_to_utf8_strdup ( const char *input, gssize length )
|
||||
{
|
||||
gsize slength = 0;
|
||||
return g_convert_with_fallback ( input, length, "UTF-8", "latin1", "\uFFFD", NULL, &slength, NULL );
|
||||
}
|
||||
|
||||
char * rofi_force_utf8 ( gchar *start )
|
||||
{
|
||||
if ( start == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
const char *data = start;
|
||||
const char *end;
|
||||
gsize length = strlen ( data );
|
||||
GString *string;
|
||||
|
||||
if ( g_utf8_validate ( data, length, &end ) ) {
|
||||
return start;
|
||||
}
|
||||
string = g_string_sized_new ( length + 16 );
|
||||
|
||||
do {
|
||||
/* Valid part of the string */
|
||||
g_string_append_len ( string, data, end - data );
|
||||
/* Replacement character */
|
||||
g_string_append ( string, "\uFFFD" );
|
||||
length -= ( end - data ) + 1;
|
||||
data = end + 1;
|
||||
} while ( !g_utf8_validate ( data, length, &end ) );
|
||||
|
||||
if ( length ) {
|
||||
g_string_append_len ( string, data, length );
|
||||
}
|
||||
|
||||
// Free input string.
|
||||
g_free ( start );
|
||||
return g_string_free ( string, FALSE );
|
||||
}
|
||||
|
|
|
@ -626,8 +626,8 @@ int main ( int argc, char *argv[] )
|
|||
// 2 the binary that executed is called dmenu (e.g. symlink to rofi)
|
||||
else{
|
||||
// Get the base name of the executable called.
|
||||
char *base_name = g_path_get_basename ( argv[0] );
|
||||
const char * const dmenu_str = "dmenu";
|
||||
char *base_name = g_path_get_basename ( argv[0] );
|
||||
const char * const dmenu_str = "dmenu";
|
||||
dmenu_mode = ( strcmp ( base_name, dmenu_str ) == 0 );
|
||||
// Free the basename for dmenu detection.
|
||||
g_free ( base_name );
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "xcb-internal.h"
|
||||
#include "xcb.h"
|
||||
#include "settings.h"
|
||||
#include "helper.h"
|
||||
|
||||
#include <rofi.h>
|
||||
#define OVERLAP( a, b, c, \
|
||||
|
@ -90,9 +91,17 @@ char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom )
|
|||
xcb_get_property_reply_t *r = xcb_get_property_reply ( xcb->connection, c, NULL );
|
||||
if ( r ) {
|
||||
if ( xcb_get_property_value_length ( r ) > 0 ) {
|
||||
char *str = g_malloc ( xcb_get_property_value_length ( r ) + 1 );
|
||||
memcpy ( str, xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
||||
str[xcb_get_property_value_length ( r )] = '\0';
|
||||
char *str = NULL;
|
||||
if ( r->type == netatoms[UTF8_STRING] ) {
|
||||
str = g_strndup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
||||
}
|
||||
else if ( r->type == netatoms[STRING] ) {
|
||||
str = rofi_latin_to_utf8_strdup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
||||
}
|
||||
else {
|
||||
str = g_strdup ( "Invalid encoding." );
|
||||
}
|
||||
|
||||
free ( r );
|
||||
return str;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue