mirror of https://github.com/davatorium/rofi.git
Indent o mania.
This commit is contained in:
parent
4d37cf35dc
commit
c87312be36
|
@ -30,41 +30,41 @@ Settings config = {
|
||||||
// Set the default window opacity.
|
// Set the default window opacity.
|
||||||
// This option only works when running a composite manager.
|
// This option only works when running a composite manager.
|
||||||
// -o
|
// -o
|
||||||
.window_opacity = 100,
|
.window_opacity = 100,
|
||||||
// Border width around the window.
|
// Border width around the window.
|
||||||
.menu_bw = 1,
|
.menu_bw = 1,
|
||||||
// The width of the switcher. (0-100 in % > 100 in pixels)
|
// The width of the switcher. (0-100 in % > 100 in pixels)
|
||||||
.menu_width = 50,
|
.menu_width = 50,
|
||||||
// Maximum number of options to show.
|
// Maximum number of options to show.
|
||||||
.menu_lines = 15,
|
.menu_lines = 15,
|
||||||
// Font
|
// Font
|
||||||
.menu_font = "mono-12",
|
.menu_font = "mono-12",
|
||||||
// Foreground color
|
// Foreground color
|
||||||
.menu_fg = "#222222",
|
.menu_fg = "#222222",
|
||||||
// Background color
|
// Background color
|
||||||
.menu_bg = "#f2f1f0",
|
.menu_bg = "#f2f1f0",
|
||||||
// Foreground color (selected)
|
// Foreground color (selected)
|
||||||
.menu_hlfg = "#ffffff",
|
.menu_hlfg = "#ffffff",
|
||||||
// Background color (selected)
|
// Background color (selected)
|
||||||
.menu_hlbg = "#005577",
|
.menu_hlbg = "#005577",
|
||||||
// Border color.
|
// Border color.
|
||||||
.menu_bc = "black",
|
.menu_bc = "black",
|
||||||
// Directly select when only 1 choice is left
|
// Directly select when only 1 choice is left
|
||||||
.zeltak_mode = 0,
|
.zeltak_mode = 0,
|
||||||
// Terminal to use. (for ssh and open in terminal)
|
// Terminal to use. (for ssh and open in terminal)
|
||||||
.terminal_emulator = "x-terminal-emulator",
|
.terminal_emulator = "x-terminal-emulator",
|
||||||
#ifdef I3
|
#ifdef I3
|
||||||
// Auto-detected. no longer used.
|
// Auto-detected. no longer used.
|
||||||
.i3_mode = 0,
|
.i3_mode = 0,
|
||||||
#endif
|
#endif
|
||||||
// Key binding
|
// Key binding
|
||||||
.window_key = "F12",
|
.window_key = "F12",
|
||||||
.run_key = "mod1+F2",
|
.run_key = "mod1+F2",
|
||||||
.ssh_key = "mod1+F3",
|
.ssh_key = "mod1+F3",
|
||||||
// Location of the window. WL_CENTER, WL_NORTH_WEST, WL_NORTH,WL_NORTH_EAST, etc.
|
// Location of the window. WL_CENTER, WL_NORTH_WEST, WL_NORTH,WL_NORTH_EAST, etc.
|
||||||
.location = WL_CENTER,
|
.location = WL_CENTER,
|
||||||
// Mode of window, list (Vertical) or dmenu like (Horizontal)
|
// Mode of window, list (Vertical) or dmenu like (Horizontal)
|
||||||
.wmode = VERTICAL,
|
.wmode = VERTICAL,
|
||||||
// Padding of the window.
|
// Padding of the window.
|
||||||
.padding = 5
|
.padding = 5
|
||||||
};
|
};
|
||||||
|
|
106
include/rofi.h
106
include/rofi.h
|
@ -3,18 +3,19 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
|
||||||
#define NEAR(a,o,b) ((b) > (a)-(o) && (b) < (a)+(o))
|
#define NEAR( a, o, b ) ( ( b ) > ( a ) - ( o ) && ( b ) < ( a ) + ( o ) )
|
||||||
#define OVERLAP(a,b,c,d) (((a)==(c) && (b)==(d)) || MIN((a)+(b), (c)+(d)) - MAX((a), (c)) > 0)
|
#define OVERLAP( a, b, c, d ) ( ( ( a ) == ( c ) && ( b ) == ( d ) ) || MIN ( ( a ) + ( b ), ( c ) + ( d ) ) - MAX ( ( a ), ( c ) ) > 0 )
|
||||||
#define INTERSECT(x,y,w,h,x1,y1,w1,h1) (OVERLAP((x),(w),(x1),(w1)) && OVERLAP((y),(h),(y1),(h1)))
|
#define INTERSECT( x, y, w, h, x1, y1, w1, h1 ) ( OVERLAP ( ( x ), ( w ), ( x1 ), ( w1 ) ) && OVERLAP ( ( y ), ( h ), ( y1 ), ( h1 ) ) )
|
||||||
|
|
||||||
extern const char *cache_dir;
|
extern const char *cache_dir;
|
||||||
#ifdef HAVE_I3_IPC_H
|
#ifdef HAVE_I3_IPC_H
|
||||||
extern char *i3_socket_path;
|
extern char *i3_socket_path;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
WINDOW_SWITCHER,
|
WINDOW_SWITCHER,
|
||||||
RUN_DIALOG,
|
RUN_DIALOG,
|
||||||
SSH_DIALOG,
|
SSH_DIALOG,
|
||||||
|
@ -24,46 +25,48 @@ typedef enum {
|
||||||
NEXT_DIALOG
|
NEXT_DIALOG
|
||||||
} SwitcherMode;
|
} SwitcherMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
MENU_OK = 0,
|
{
|
||||||
|
MENU_OK = 0,
|
||||||
MENU_CANCEL = -1,
|
MENU_CANCEL = -1,
|
||||||
MENU_NEXT = -2,
|
MENU_NEXT = -2,
|
||||||
MENU_CUSTOM_INPUT = -3,
|
MENU_CUSTOM_INPUT = -3,
|
||||||
MENU_ENTRY_DELETE = -4
|
MENU_ENTRY_DELETE = -4
|
||||||
|
|
||||||
} MenuReturn;
|
} MenuReturn;
|
||||||
|
|
||||||
|
|
||||||
typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, void *data );
|
typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, void *data );
|
||||||
MenuReturn menu( char **lines, char **input, char *prompt,
|
MenuReturn menu ( char **lines, char **input, char *prompt,
|
||||||
Time *time, int *shift,
|
Time *time, int *shift,
|
||||||
menu_match_cb mmc, void *mmc_data,
|
menu_match_cb mmc, void *mmc_data,
|
||||||
int *selected_line );
|
int *selected_line );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocator wrappers
|
* Allocator wrappers
|
||||||
*/
|
*/
|
||||||
void* allocate( unsigned long bytes ) __attribute__((malloc));
|
void* allocate ( unsigned long bytes ) __attribute__( ( malloc ) );
|
||||||
void* allocate_clear( unsigned long bytes );
|
void* allocate_clear ( unsigned long bytes );
|
||||||
void* reallocate( void *ptr, unsigned long bytes );
|
void* reallocate ( void *ptr, unsigned long bytes );
|
||||||
|
|
||||||
|
|
||||||
void catch_exit( __attribute__( ( unused ) ) int sig );
|
void catch_exit ( __attribute__( ( unused ) ) int sig );
|
||||||
|
|
||||||
typedef enum _WindowLocation {
|
typedef enum _WindowLocation
|
||||||
WL_CENTER = 0,
|
{
|
||||||
WL_NORTH_WEST = 1,
|
WL_CENTER = 0,
|
||||||
WL_NORTH = 2,
|
WL_NORTH_WEST = 1,
|
||||||
WL_NORTH_EAST = 3,
|
WL_NORTH = 2,
|
||||||
WL_EAST = 4,
|
WL_NORTH_EAST = 3,
|
||||||
WL_EAST_SOUTH = 5,
|
WL_EAST = 4,
|
||||||
WL_SOUTH = 6,
|
WL_EAST_SOUTH = 5,
|
||||||
WL_SOUTH_WEST = 7,
|
WL_SOUTH = 6,
|
||||||
WL_WEST = 8
|
WL_SOUTH_WEST = 7,
|
||||||
|
WL_WEST = 8
|
||||||
} WindowLocation;
|
} WindowLocation;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
VERTICAL = 0,
|
VERTICAL = 0,
|
||||||
HORIZONTAL = 1
|
HORIZONTAL = 1
|
||||||
} WindowMode;
|
} WindowMode;
|
||||||
|
@ -71,38 +74,39 @@ typedef enum {
|
||||||
* Settings
|
* Settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _Settings {
|
typedef struct _Settings
|
||||||
|
{
|
||||||
// Window settings
|
// Window settings
|
||||||
unsigned int window_opacity;
|
unsigned int window_opacity;
|
||||||
// Menu settings
|
// Menu settings
|
||||||
unsigned int menu_bw;
|
unsigned int menu_bw;
|
||||||
unsigned int menu_width;
|
unsigned int menu_width;
|
||||||
unsigned int menu_lines;
|
unsigned int menu_lines;
|
||||||
char * menu_font;
|
char * menu_font;
|
||||||
char * menu_fg;
|
char * menu_fg;
|
||||||
char * menu_bg;
|
char * menu_bg;
|
||||||
char * menu_hlfg;
|
char * menu_hlfg;
|
||||||
char * menu_hlbg;
|
char * menu_hlbg;
|
||||||
char * menu_bc;
|
char * menu_bc;
|
||||||
// Behavior
|
// Behavior
|
||||||
unsigned int zeltak_mode;
|
unsigned int zeltak_mode;
|
||||||
char * terminal_emulator;
|
char * terminal_emulator;
|
||||||
#ifdef HAVE_I3_IPC_H
|
#ifdef HAVE_I3_IPC_H
|
||||||
unsigned int i3_mode;
|
unsigned int i3_mode;
|
||||||
#endif
|
#endif
|
||||||
// Key bindings
|
// Key bindings
|
||||||
char * window_key;
|
char * window_key;
|
||||||
char * run_key;
|
char * run_key;
|
||||||
char * ssh_key;
|
char * ssh_key;
|
||||||
WindowLocation location;
|
WindowLocation location;
|
||||||
WindowMode wmode;
|
WindowMode wmode;
|
||||||
unsigned int padding;
|
unsigned int padding;
|
||||||
} Settings;
|
} Settings;
|
||||||
|
|
||||||
extern Settings config;
|
extern Settings config;
|
||||||
|
|
||||||
|
|
||||||
int token_match ( char **tokens, const char *input,
|
int token_match ( char **tokens, const char *input,
|
||||||
__attribute__( ( unused ) )int index,
|
__attribute__( ( unused ) ) int index,
|
||||||
__attribute__( ( unused ) )void *data );
|
__attribute__( ( unused ) ) void *data );
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,47 +1,49 @@
|
||||||
#ifndef __TEXTBOX_H__
|
#ifndef __TEXTBOX_H__
|
||||||
#define __TEXTBOX_H__
|
#define __TEXTBOX_H__
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
Window window, parent;
|
Window window, parent;
|
||||||
short x, y, w, h;
|
short x, y, w, h;
|
||||||
short cursor;
|
short cursor;
|
||||||
XftFont *font;
|
XftFont *font;
|
||||||
XftColor color_fg, color_bg;
|
XftColor color_fg, color_bg;
|
||||||
char *text, *prompt;
|
char *text, *prompt;
|
||||||
XIM xim;
|
XIM xim;
|
||||||
XIC xic;
|
XIC xic;
|
||||||
XGlyphInfo extents;
|
XGlyphInfo extents;
|
||||||
} textbox;
|
} textbox;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
TB_AUTOHEIGHT = 1<<0,
|
{
|
||||||
TB_AUTOWIDTH = 1<<1,
|
TB_AUTOHEIGHT = 1 << 0,
|
||||||
TB_LEFT = 1<<16,
|
TB_AUTOWIDTH = 1 << 1,
|
||||||
TB_RIGHT = 1<<17,
|
TB_LEFT = 1 << 16,
|
||||||
TB_CENTER = 1<<18,
|
TB_RIGHT = 1 << 17,
|
||||||
TB_EDITABLE = 1<<19,
|
TB_CENTER = 1 << 18,
|
||||||
|
TB_EDITABLE = 1 << 19,
|
||||||
} TextboxFlags;
|
} TextboxFlags;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
textbox* textbox_create( Window parent,
|
textbox* textbox_create ( Window parent,
|
||||||
TextboxFlags flags,
|
TextboxFlags flags,
|
||||||
short x, short y, short w, short h,
|
short x, short y, short w, short h,
|
||||||
char *font, char *fg, char *bg,
|
char *font, char *fg, char *bg,
|
||||||
char *text, char *prompt );
|
char *text, char *prompt );
|
||||||
|
|
||||||
void textbox_free( textbox *tb );
|
void textbox_free ( textbox *tb );
|
||||||
|
|
||||||
void textbox_font( textbox *tb, char *font, char *fg, char *bg );
|
void textbox_font ( textbox *tb, char *font, char *fg, char *bg );
|
||||||
|
|
||||||
void textbox_text( textbox *tb, char *text );
|
void textbox_text ( textbox *tb, char *text );
|
||||||
void textbox_show( textbox *tb );
|
void textbox_show ( textbox *tb );
|
||||||
void textbox_draw( textbox *tb );
|
void textbox_draw ( textbox *tb );
|
||||||
|
|
||||||
int textbox_keypress( textbox *tb, XEvent *ev );
|
int textbox_keypress ( textbox *tb, XEvent *ev );
|
||||||
|
|
||||||
void textbox_cursor_end( textbox *tb );
|
void textbox_cursor_end ( textbox *tb );
|
||||||
#endif //__TEXTBOX_H__
|
#endif //__TEXTBOX_H__
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __XRMOPTIONS_H__
|
#ifndef __XRMOPTIONS_H__
|
||||||
#define __XRMOPTIONS_H__
|
#define __XRMOPTIONS_H__
|
||||||
void parse_xresource_options( Display *display );
|
void parse_xresource_options ( Display *display );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,16 +42,19 @@ static char **get_dmenu ( )
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
char **retv = NULL;
|
char **retv = NULL;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
while ( fgets( buffer, 1024, stdin ) != NULL ) {
|
while ( fgets ( buffer, 1024, stdin ) != NULL )
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
{
|
||||||
retv[index] = strdup( buffer );
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index+1] = NULL;
|
retv[index] = strdup ( buffer );
|
||||||
|
retv[index + 1] = NULL;
|
||||||
|
|
||||||
// Filter out line-end.
|
// Filter out line-end.
|
||||||
if ( retv[index][strlen( buffer )-1] == '\n' )
|
if ( retv[index][strlen ( buffer ) - 1] == '\n' )
|
||||||
retv[index][strlen( buffer )-1] = '\0';
|
{
|
||||||
|
retv[index][strlen ( buffer ) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
@ -61,27 +64,36 @@ static char **get_dmenu ( )
|
||||||
|
|
||||||
SwitcherMode dmenu_switcher_dialog ( char **input )
|
SwitcherMode dmenu_switcher_dialog ( char **input )
|
||||||
{
|
{
|
||||||
int selected_line = 0;
|
int selected_line = 0;
|
||||||
SwitcherMode retv = MODE_EXIT;
|
SwitcherMode retv = MODE_EXIT;
|
||||||
// act as a launcher
|
// act as a launcher
|
||||||
char **list = get_dmenu( );
|
char **list = get_dmenu ( );
|
||||||
|
|
||||||
int mretv = menu( list, input, dmenu_prompt,NULL, NULL,
|
int mretv = menu ( list, input, dmenu_prompt, NULL, NULL,
|
||||||
token_match, NULL, &selected_line );
|
token_match, NULL, &selected_line );
|
||||||
|
|
||||||
if ( mretv == MENU_NEXT ) {
|
if ( mretv == MENU_NEXT )
|
||||||
|
{
|
||||||
retv = DMENU_DIALOG;
|
retv = DMENU_DIALOG;
|
||||||
} else if ( mretv == MENU_OK && list[selected_line] != NULL ) {
|
}
|
||||||
fputs( list[selected_line],stdout );
|
else if ( mretv == MENU_OK && list[selected_line] != NULL )
|
||||||
} else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) {
|
{
|
||||||
fputs( *input, stdout );
|
fputs ( list[selected_line], stdout );
|
||||||
|
}
|
||||||
|
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' )
|
||||||
|
{
|
||||||
|
fputs ( *input, stdout );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( unsigned int i=0; list != NULL && list[i] != NULL; i++ ) {
|
for ( unsigned int i = 0; list != NULL && list[i] != NULL; i++ )
|
||||||
free( list[i] );
|
{
|
||||||
|
free ( list[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( list != NULL ) free( list );
|
if ( list != NULL )
|
||||||
|
{
|
||||||
|
free ( list );
|
||||||
|
}
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
1832
source/rofi.c
1832
source/rofi.c
File diff suppressed because it is too large
Load Diff
|
@ -45,151 +45,176 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RUN_CACHE_FILE "rofi-2.runcache"
|
#define RUN_CACHE_FILE "rofi-2.runcache"
|
||||||
|
|
||||||
static inline int execsh( const char *cmd ,int run_in_term )
|
static inline int execsh ( const char *cmd, int run_in_term )
|
||||||
{
|
{
|
||||||
// use sh for args parsing
|
// use sh for args parsing
|
||||||
if ( run_in_term )
|
if ( run_in_term )
|
||||||
return execlp( config.terminal_emulator, config.terminal_emulator, "-e", "sh", "-c", cmd, NULL );
|
{
|
||||||
|
return execlp ( config.terminal_emulator, config.terminal_emulator, "-e", "sh", "-c", cmd, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
return execlp( "/bin/sh", "sh", "-c", cmd, NULL );
|
return execlp ( "/bin/sh", "sh", "-c", cmd, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _element{
|
typedef struct _element
|
||||||
long int index;
|
|
||||||
char name[1024];
|
|
||||||
}element;
|
|
||||||
static int element_sort_func(const void *ea,const void *eb)
|
|
||||||
{
|
{
|
||||||
element *a = *(element **)ea;
|
long int index;
|
||||||
element *b = *(element **)eb;
|
char name[1024];
|
||||||
|
}element;
|
||||||
|
static int element_sort_func ( const void *ea, const void *eb )
|
||||||
|
{
|
||||||
|
element *a = *(element * *) ea;
|
||||||
|
element *b = *(element * *) eb;
|
||||||
return b->index - a->index;
|
return b->index - a->index;
|
||||||
}
|
}
|
||||||
// execute sub-process
|
// execute sub-process
|
||||||
static pid_t exec_cmd( const char *cmd, int run_in_term )
|
static pid_t exec_cmd ( const char *cmd, int run_in_term )
|
||||||
{
|
{
|
||||||
if ( !cmd || !cmd[0] ) return -1;
|
if ( !cmd || !cmd[0] )
|
||||||
|
{
|
||||||
signal( SIGCHLD, catch_exit );
|
return -1;
|
||||||
pid_t pid = fork();
|
|
||||||
|
|
||||||
if ( !pid ) {
|
|
||||||
setsid();
|
|
||||||
execsh( cmd, run_in_term );
|
|
||||||
exit( EXIT_FAILURE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int curr = -1;
|
signal ( SIGCHLD, catch_exit );
|
||||||
unsigned int index = 0;
|
pid_t pid = fork ();
|
||||||
element **retv = NULL;
|
|
||||||
|
if ( !pid )
|
||||||
|
{
|
||||||
|
setsid ();
|
||||||
|
execsh ( cmd, run_in_term );
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
int curr = -1;
|
||||||
|
unsigned int index = 0;
|
||||||
|
element **retv = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This happens in non-critical time (After launching app)
|
* This happens in non-critical time (After launching app)
|
||||||
* It is allowed to be a bit slower.
|
* It is allowed to be a bit slower.
|
||||||
*/
|
*/
|
||||||
size_t path_length = strlen( cache_dir ) + strlen( RUN_CACHE_FILE )+3;
|
size_t path_length = strlen ( cache_dir ) + strlen ( RUN_CACHE_FILE ) + 3;
|
||||||
char *path = allocate( path_length );
|
char *path = allocate ( path_length );
|
||||||
snprintf( path, path_length, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
snprintf ( path, path_length, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
if(strlen(buffer) == 0) continue;
|
{
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( element* ) );
|
if ( strlen ( buffer ) == 0 )
|
||||||
retv[index] = allocate(sizeof(element));
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
continue;
|
||||||
|
}
|
||||||
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( element* ) );
|
||||||
|
retv[index] = allocate ( sizeof ( element ) );
|
||||||
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
char * start = NULL;
|
char * start = NULL;
|
||||||
retv[index]->index = strtol(buffer, &start, 10);
|
retv[index]->index = strtol ( buffer, &start, 10 );
|
||||||
snprintf(retv[index]->name, 1024, "%s", start+1);
|
snprintf ( retv[index]->name, 1024, "%s", start + 1 );
|
||||||
retv[index+1] = NULL;
|
retv[index + 1] = NULL;
|
||||||
|
|
||||||
if ( strcasecmp( retv[index]->name, cmd ) == 0 ) {
|
if ( strcasecmp ( retv[index]->name, cmd ) == 0 )
|
||||||
|
{
|
||||||
curr = index;
|
curr = index;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
if(curr < 0) {
|
if ( curr < 0 )
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( element* ) );
|
{
|
||||||
retv[index] = allocate(sizeof(element));
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( element* ) );
|
||||||
retv[index]->index = 1;
|
retv[index] = allocate ( sizeof ( element ) );
|
||||||
snprintf(retv[index]->name, 1024, "%s", cmd);
|
retv[index]->index = 1;
|
||||||
index++;
|
snprintf ( retv[index]->name, 1024, "%s", cmd );
|
||||||
}else {
|
index++;
|
||||||
retv[curr]->index++;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retv[curr]->index++;
|
||||||
}
|
}
|
||||||
// Sort the list.
|
// Sort the list.
|
||||||
qsort(retv, index, sizeof(element*), element_sort_func);
|
qsort ( retv, index, sizeof ( element* ), element_sort_func );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write out the last 25 results again.
|
* Write out the last 25 results again.
|
||||||
*/
|
*/
|
||||||
fd = fopen ( path, "w" );
|
fd = fopen ( path, "w" );
|
||||||
|
|
||||||
if ( fd ) {
|
if ( fd )
|
||||||
|
{
|
||||||
for ( int i = 0; i < ( int )index && i < 20; i++ ) {
|
for ( int i = 0; i < ( int ) index && i < 20; i++ )
|
||||||
if(retv[i]->name && retv[i]->name[0] != '\0') {
|
{
|
||||||
fprintf(fd, "%ld %s\n",
|
if ( retv[i]->name && retv[i]->name[0] != '\0' )
|
||||||
retv[i]->index,
|
{
|
||||||
retv[i]->name
|
fprintf ( fd, "%ld %s\n",
|
||||||
);
|
retv[i]->index,
|
||||||
|
retv[i]->name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; retv != NULL && retv[i] != NULL; i++ ) {
|
for ( int i = 0; retv != NULL && retv[i] != NULL; i++ )
|
||||||
free( retv[i] );
|
{
|
||||||
|
free ( retv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( retv );
|
free ( retv );
|
||||||
|
|
||||||
free( path );
|
free ( path );
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
// execute sub-process
|
// execute sub-process
|
||||||
static void delete_entry( const char *cmd )
|
static void delete_entry ( const char *cmd )
|
||||||
{
|
{
|
||||||
int curr = -1;
|
int curr = -1;
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
element **retv = NULL;
|
element **retv = NULL;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This happens in non-critical time (After launching app)
|
* This happens in non-critical time (After launching app)
|
||||||
* It is allowed to be a bit slower.
|
* It is allowed to be a bit slower.
|
||||||
*/
|
*/
|
||||||
char *path = allocate( strlen( cache_dir ) + strlen( RUN_CACHE_FILE )+3 );
|
char *path = allocate ( strlen ( cache_dir ) + strlen ( RUN_CACHE_FILE ) + 3 );
|
||||||
sprintf( path, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
sprintf ( path, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
if(strlen(buffer) == 0) continue;
|
{
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( element* ) );
|
if ( strlen ( buffer ) == 0 )
|
||||||
retv[index] = allocate(sizeof(element));
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
continue;
|
||||||
|
}
|
||||||
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( element* ) );
|
||||||
|
retv[index] = allocate ( sizeof ( element ) );
|
||||||
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
char * start = NULL;
|
char * start = NULL;
|
||||||
retv[index]->index = strtol(buffer, &start, 10);
|
retv[index]->index = strtol ( buffer, &start, 10 );
|
||||||
snprintf(retv[index]->name, 1024, "%s", start+1);
|
snprintf ( retv[index]->name, 1024, "%s", start + 1 );
|
||||||
retv[index+1] = NULL;
|
retv[index + 1] = NULL;
|
||||||
|
|
||||||
if ( strcasecmp( retv[index]->name, cmd ) == 0 ) {
|
if ( strcasecmp ( retv[index]->name, cmd ) == 0 )
|
||||||
|
{
|
||||||
curr = index;
|
curr = index;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,88 +222,107 @@ static void delete_entry( const char *cmd )
|
||||||
*/
|
*/
|
||||||
fd = fopen ( path, "w" );
|
fd = fopen ( path, "w" );
|
||||||
|
|
||||||
if ( fd ) {
|
if ( fd )
|
||||||
for ( int i = 0; i < ( int )index && i < 20; i++ ) {
|
{
|
||||||
if ( i != curr ) {
|
for ( int i = 0; i < ( int ) index && i < 20; i++ )
|
||||||
if(retv[i]->name && retv[i]->name[0] != '\0') {
|
{
|
||||||
fprintf(fd, "%ld %s\n",
|
if ( i != curr )
|
||||||
retv[i]->index,
|
{
|
||||||
retv[i]->name
|
if ( retv[i]->name && retv[i]->name[0] != '\0' )
|
||||||
);
|
{
|
||||||
|
fprintf ( fd, "%ld %s\n",
|
||||||
|
retv[i]->index,
|
||||||
|
retv[i]->name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; retv != NULL && retv[i] != NULL; i++ ) {
|
for ( int i = 0; retv != NULL && retv[i] != NULL; i++ )
|
||||||
free( retv[i] );
|
{
|
||||||
|
free ( retv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( retv );
|
free ( retv );
|
||||||
|
|
||||||
free( path );
|
|
||||||
|
|
||||||
|
free ( path );
|
||||||
}
|
}
|
||||||
static int sort_func ( const void *a, const void *b )
|
static int sort_func ( const void *a, const void *b )
|
||||||
{
|
{
|
||||||
const char *astr = *( const char * const * )a;
|
const char *astr = *( const char * const * ) a;
|
||||||
const char *bstr = *( const char * const * )b;
|
const char *bstr = *( const char * const * ) b;
|
||||||
return strcasecmp( astr,bstr );
|
return strcasecmp ( astr, bstr );
|
||||||
}
|
}
|
||||||
static char ** get_apps ( )
|
static char ** get_apps ( )
|
||||||
{
|
{
|
||||||
unsigned int num_favorites = 0;
|
unsigned int num_favorites = 0;
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
char *path;
|
char *path;
|
||||||
char **retv = NULL;
|
char **retv = NULL;
|
||||||
#ifdef TIMING
|
#ifdef TIMING
|
||||||
struct timespec start, stop;
|
struct timespec start, stop;
|
||||||
clock_gettime( CLOCK_REALTIME, &start );
|
clock_gettime ( CLOCK_REALTIME, &start );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( getenv( "PATH" ) == NULL ) return NULL;
|
if ( getenv ( "PATH" ) == NULL )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
path = allocate( strlen( cache_dir ) + strlen( RUN_CACHE_FILE )+3 );
|
path = allocate ( strlen ( cache_dir ) + strlen ( RUN_CACHE_FILE ) + 3 );
|
||||||
sprintf( path, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
sprintf ( path, "%s/%s", cache_dir, RUN_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
if(strlen(buffer) == 0) continue;
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
if ( strlen ( buffer ) == 0 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
char *start = NULL;
|
char *start = NULL;
|
||||||
// Don't use result.
|
// Don't use result.
|
||||||
strtol(buffer, &start, 10);
|
strtol ( buffer, &start, 10 );
|
||||||
if(start == NULL) continue;
|
if ( start == NULL )
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
{
|
||||||
retv[index] = strdup( start+1 );
|
continue;
|
||||||
retv[index+1] = NULL;
|
}
|
||||||
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
|
retv[index] = strdup ( start + 1 );
|
||||||
|
retv[index + 1] = NULL;
|
||||||
index++;
|
index++;
|
||||||
num_favorites++;
|
num_favorites++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( path );
|
free ( path );
|
||||||
|
|
||||||
|
|
||||||
path = strdup( getenv( "PATH" ) );
|
path = strdup ( getenv ( "PATH" ) );
|
||||||
|
|
||||||
for ( const char *dirname = strtok( path, ":" ); dirname != NULL; dirname = strtok( NULL, ":" ) ) {
|
for ( const char *dirname = strtok ( path, ":" ); dirname != NULL; dirname = strtok ( NULL, ":" ) )
|
||||||
DIR *dir = opendir( dirname );
|
{
|
||||||
|
DIR *dir = opendir ( dirname );
|
||||||
|
|
||||||
if ( dir != NULL ) {
|
if ( dir != NULL )
|
||||||
|
{
|
||||||
struct dirent *dent;
|
struct dirent *dent;
|
||||||
|
|
||||||
while ( ( dent=readdir( dir ) )!=NULL ) {
|
while ( ( dent = readdir ( dir ) ) != NULL )
|
||||||
|
{
|
||||||
if ( dent->d_type != DT_REG &&
|
if ( dent->d_type != DT_REG &&
|
||||||
dent->d_type != DT_LNK &&
|
dent->d_type != DT_LNK &&
|
||||||
dent->d_type != DT_UNKNOWN ) {
|
dent->d_type != DT_UNKNOWN )
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,72 +330,93 @@ static char ** get_apps ( )
|
||||||
|
|
||||||
// This is a nice little penalty, but doable? time will tell.
|
// This is a nice little penalty, but doable? time will tell.
|
||||||
// given num_favorites is max 25.
|
// given num_favorites is max 25.
|
||||||
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) {
|
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ )
|
||||||
if ( strcasecmp( dent->d_name, retv[j] ) == 0 ) found = 1;
|
{
|
||||||
|
if ( strcasecmp ( dent->d_name, retv[j] ) == 0 )
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( found == 1 ) continue;
|
if ( found == 1 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index] = strdup( dent->d_name );
|
retv[index] = strdup ( dent->d_name );
|
||||||
retv[index+1] = NULL;
|
retv[index + 1] = NULL;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir( dir );
|
closedir ( dir );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check this is still fast enough. (takes 1ms on laptop.)
|
// TODO: check this is still fast enough. (takes 1ms on laptop.)
|
||||||
if(index > num_favorites) {
|
if ( index > num_favorites )
|
||||||
qsort( &retv[num_favorites],index-num_favorites, sizeof( char* ), sort_func );
|
{
|
||||||
|
qsort ( &retv[num_favorites], index - num_favorites, sizeof ( char* ), sort_func );
|
||||||
}
|
}
|
||||||
free( path );
|
free ( path );
|
||||||
#ifdef TIMING
|
#ifdef TIMING
|
||||||
clock_gettime( CLOCK_REALTIME, &stop );
|
clock_gettime ( CLOCK_REALTIME, &stop );
|
||||||
|
|
||||||
if ( stop.tv_sec != start.tv_sec ) {
|
if ( stop.tv_sec != start.tv_sec )
|
||||||
stop.tv_nsec += ( stop.tv_sec-start.tv_sec )*1e9;
|
{
|
||||||
|
stop.tv_nsec += ( stop.tv_sec - start.tv_sec ) * 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
long diff = stop.tv_nsec-start.tv_nsec;
|
long diff = stop.tv_nsec - start.tv_nsec;
|
||||||
printf( "Time elapsed: %ld us\n", diff/1000 );
|
printf ( "Time elapsed: %ld us\n", diff / 1000 );
|
||||||
#endif
|
#endif
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherMode run_switcher_dialog ( char **input )
|
SwitcherMode run_switcher_dialog ( char **input )
|
||||||
{
|
{
|
||||||
int shift=0;
|
int shift = 0;
|
||||||
int selected_line = 0;
|
int selected_line = 0;
|
||||||
SwitcherMode retv = MODE_EXIT;
|
SwitcherMode retv = MODE_EXIT;
|
||||||
// act as a launcher
|
// act as a launcher
|
||||||
char **cmd_list = get_apps( );
|
char **cmd_list = get_apps ( );
|
||||||
|
|
||||||
if ( cmd_list == NULL ) {
|
if ( cmd_list == NULL )
|
||||||
cmd_list = allocate( 2*sizeof( char * ) );
|
{
|
||||||
cmd_list[0] = strdup( "No applications found" );
|
cmd_list = allocate ( 2 * sizeof ( char * ) );
|
||||||
|
cmd_list[0] = strdup ( "No applications found" );
|
||||||
cmd_list[1] = NULL;
|
cmd_list[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mretv = menu( cmd_list, input, "$", NULL, &shift,token_match, NULL, &selected_line );
|
int mretv = menu ( cmd_list, input, "$", NULL, &shift, token_match, NULL, &selected_line );
|
||||||
|
|
||||||
if ( mretv == MENU_NEXT ) {
|
if ( mretv == MENU_NEXT )
|
||||||
|
{
|
||||||
retv = NEXT_DIALOG;
|
retv = NEXT_DIALOG;
|
||||||
} else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) {
|
}
|
||||||
exec_cmd( cmd_list[selected_line], shift );
|
else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL )
|
||||||
} else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) {
|
{
|
||||||
exec_cmd( *input, shift );
|
exec_cmd ( cmd_list[selected_line], shift );
|
||||||
} else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) {
|
}
|
||||||
|
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' )
|
||||||
|
{
|
||||||
|
exec_cmd ( *input, shift );
|
||||||
|
}
|
||||||
|
else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] )
|
||||||
|
{
|
||||||
delete_entry ( cmd_list[selected_line] );
|
delete_entry ( cmd_list[selected_line] );
|
||||||
retv = RUN_DIALOG;
|
retv = RUN_DIALOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; cmd_list != NULL && cmd_list[i] != NULL; i++ ) {
|
for ( int i = 0; cmd_list != NULL && cmd_list[i] != NULL; i++ )
|
||||||
free( cmd_list[i] );
|
{
|
||||||
|
free ( cmd_list[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cmd_list != NULL ) free( cmd_list );
|
if ( cmd_list != NULL )
|
||||||
|
{
|
||||||
|
free ( cmd_list );
|
||||||
|
}
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,54 +45,61 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SSH_CACHE_FILE "rofi.sshcache"
|
#define SSH_CACHE_FILE "rofi.sshcache"
|
||||||
|
|
||||||
static inline int execshssh( const char *host )
|
static inline int execshssh ( const char *host )
|
||||||
{
|
{
|
||||||
return execlp( config.terminal_emulator, config.terminal_emulator, "-e", "ssh", host, NULL );
|
return execlp ( config.terminal_emulator, config.terminal_emulator, "-e", "ssh", host, NULL );
|
||||||
}
|
}
|
||||||
// execute sub-process
|
// execute sub-process
|
||||||
static pid_t exec_ssh( const char *cmd )
|
static pid_t exec_ssh ( const char *cmd )
|
||||||
{
|
{
|
||||||
if ( !cmd || !cmd[0] ) return -1;
|
if ( !cmd || !cmd[0] )
|
||||||
|
{
|
||||||
signal( SIGCHLD, catch_exit );
|
return -1;
|
||||||
pid_t pid = fork();
|
|
||||||
|
|
||||||
if ( !pid ) {
|
|
||||||
setsid();
|
|
||||||
execshssh( cmd );
|
|
||||||
exit( EXIT_FAILURE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int curr = -1;
|
signal ( SIGCHLD, catch_exit );
|
||||||
unsigned int index = 0;
|
pid_t pid = fork ();
|
||||||
char **retv = NULL;
|
|
||||||
|
if ( !pid )
|
||||||
|
{
|
||||||
|
setsid ();
|
||||||
|
execshssh ( cmd );
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
int curr = -1;
|
||||||
|
unsigned int index = 0;
|
||||||
|
char **retv = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This happens in non-critical time (After launching app)
|
* This happens in non-critical time (After launching app)
|
||||||
* It is allowed to be a bit slower.
|
* It is allowed to be a bit slower.
|
||||||
*/
|
*/
|
||||||
char *path = allocate( strlen( cache_dir ) + strlen( SSH_CACHE_FILE )+3 );
|
char *path = allocate ( strlen ( cache_dir ) + strlen ( SSH_CACHE_FILE ) + 3 );
|
||||||
sprintf( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
sprintf ( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index] = strdup( buffer );
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
retv[index+1] = NULL;
|
retv[index] = strdup ( buffer );
|
||||||
|
retv[index + 1] = NULL;
|
||||||
|
|
||||||
if ( strcasecmp( retv[index], cmd ) == 0 ) {
|
if ( strcasecmp ( retv[index], cmd ) == 0 )
|
||||||
|
{
|
||||||
curr = index;
|
curr = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,63 +107,73 @@ static pid_t exec_ssh( const char *cmd )
|
||||||
*/
|
*/
|
||||||
fd = fopen ( path, "w" );
|
fd = fopen ( path, "w" );
|
||||||
|
|
||||||
if ( fd ) {
|
if ( fd )
|
||||||
|
{
|
||||||
// Last one goes on top!
|
// Last one goes on top!
|
||||||
fputs( cmd, fd );
|
fputs ( cmd, fd );
|
||||||
fputc( '\n', fd );
|
fputc ( '\n', fd );
|
||||||
|
|
||||||
for ( int i = 0; i < ( int )index && i < 20; i++ ) {
|
for ( int i = 0; i < ( int ) index && i < 20; i++ )
|
||||||
if ( i != curr ) {
|
{
|
||||||
fputs( retv[i], fd );
|
if ( i != curr )
|
||||||
fputc( '\n', fd );
|
{
|
||||||
|
fputs ( retv[i], fd );
|
||||||
|
fputc ( '\n', fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; retv != NULL && retv[i] != NULL; i++ ) {
|
for ( int i = 0; retv != NULL && retv[i] != NULL; i++ )
|
||||||
free( retv[i] );
|
{
|
||||||
|
free ( retv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( retv );
|
free ( retv );
|
||||||
|
|
||||||
free( path );
|
free ( path );
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
static void delete_ssh( const char *cmd )
|
static void delete_ssh ( const char *cmd )
|
||||||
{
|
{
|
||||||
if ( !cmd || !cmd[0] ) return ;
|
if ( !cmd || !cmd[0] )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int curr = -1;
|
int curr = -1;
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
char **retv = NULL;
|
char **retv = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This happens in non-critical time (After launching app)
|
* This happens in non-critical time (After launching app)
|
||||||
* It is allowed to be a bit slower.
|
* It is allowed to be a bit slower.
|
||||||
*/
|
*/
|
||||||
char *path = allocate( strlen( cache_dir ) + strlen( SSH_CACHE_FILE )+3 );
|
char *path = allocate ( strlen ( cache_dir ) + strlen ( SSH_CACHE_FILE ) + 3 );
|
||||||
sprintf( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
sprintf ( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index] = strdup( buffer );
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
retv[index+1] = NULL;
|
retv[index] = strdup ( buffer );
|
||||||
|
retv[index + 1] = NULL;
|
||||||
|
|
||||||
if ( strcasecmp( retv[index], cmd ) == 0 ) {
|
if ( strcasecmp ( retv[index], cmd ) == 0 )
|
||||||
|
{
|
||||||
curr = index;
|
curr = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,118 +181,146 @@ static void delete_ssh( const char *cmd )
|
||||||
*/
|
*/
|
||||||
fd = fopen ( path, "w" );
|
fd = fopen ( path, "w" );
|
||||||
|
|
||||||
if ( fd ) {
|
if ( fd )
|
||||||
|
{
|
||||||
for ( int i = 0; i < ( int )index && i < 20; i++ ) {
|
for ( int i = 0; i < ( int ) index && i < 20; i++ )
|
||||||
if ( i != curr ) {
|
{
|
||||||
fputs( retv[i], fd );
|
if ( i != curr )
|
||||||
fputc( '\n', fd );
|
{
|
||||||
|
fputs ( retv[i], fd );
|
||||||
|
fputc ( '\n', fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; retv != NULL && retv[i] != NULL; i++ ) {
|
for ( int i = 0; retv != NULL && retv[i] != NULL; i++ )
|
||||||
free( retv[i] );
|
{
|
||||||
|
free ( retv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( retv );
|
free ( retv );
|
||||||
|
|
||||||
free( path );
|
|
||||||
|
|
||||||
|
free ( path );
|
||||||
}
|
}
|
||||||
static int sort_func ( const void *a, const void *b )
|
static int sort_func ( const void *a, const void *b )
|
||||||
{
|
{
|
||||||
const char *astr = *( const char * const * )a;
|
const char *astr = *( const char * const * ) a;
|
||||||
const char *bstr = *( const char * const * )b;
|
const char *bstr = *( const char * const * ) b;
|
||||||
return strcasecmp( astr,bstr );
|
return strcasecmp ( astr, bstr );
|
||||||
}
|
}
|
||||||
static char ** get_ssh ( )
|
static char ** get_ssh ( )
|
||||||
{
|
{
|
||||||
unsigned int num_favorites = 0;
|
unsigned int num_favorites = 0;
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
char *path;
|
char *path;
|
||||||
char **retv = NULL;
|
char **retv = NULL;
|
||||||
#ifdef TIMING
|
#ifdef TIMING
|
||||||
struct timespec start, stop;
|
struct timespec start, stop;
|
||||||
clock_gettime( CLOCK_REALTIME, &start );
|
clock_gettime ( CLOCK_REALTIME, &start );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( getenv( "HOME" ) == NULL ) return NULL;
|
if ( getenv ( "HOME" ) == NULL )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
path = allocate( strlen( cache_dir ) + strlen( "/"SSH_CACHE_FILE )+2 );
|
path = allocate ( strlen ( cache_dir ) + strlen ( "/"SSH_CACHE_FILE ) + 2 );
|
||||||
sprintf( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
sprintf ( path, "%s/%s", cache_dir, SSH_CACHE_FILE );
|
||||||
FILE *fd = fopen ( path, "r" );
|
FILE *fd = fopen ( path, "r" );
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
{
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
{
|
||||||
retv[index] = strdup( buffer );
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index+1] = NULL;
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
|
retv[index] = strdup ( buffer );
|
||||||
|
retv[index + 1] = NULL;
|
||||||
index++;
|
index++;
|
||||||
num_favorites++;
|
num_favorites++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( path );
|
free ( path );
|
||||||
const char *hd = getenv( "HOME" );
|
const char *hd = getenv ( "HOME" );
|
||||||
path = allocate( strlen( hd ) + strlen( ".ssh/config" )+3 );
|
path = allocate ( strlen ( hd ) + strlen ( ".ssh/config" ) + 3 );
|
||||||
sprintf( path, "%s/%s", hd, ".ssh/config" );
|
sprintf ( path, "%s/%s", hd, ".ssh/config" );
|
||||||
fd = fopen ( path, "r" );
|
fd = fopen ( path, "r" );
|
||||||
|
|
||||||
if ( fd != NULL ) {
|
if ( fd != NULL )
|
||||||
while ( fgets( buffer,1024,fd ) != NULL ) {
|
{
|
||||||
if ( strncasecmp( buffer, "Host", 4 ) == 0 ) {
|
while ( fgets ( buffer, 1024, fd ) != NULL )
|
||||||
int start = 0, stop=0;
|
{
|
||||||
buffer[strlen( buffer )-1] = '\0';
|
if ( strncasecmp ( buffer, "Host", 4 ) == 0 )
|
||||||
|
{
|
||||||
|
int start = 0, stop = 0;
|
||||||
|
buffer[strlen ( buffer ) - 1] = '\0';
|
||||||
|
|
||||||
for ( start=4; isspace( buffer[start] ); start++ );
|
for ( start = 4; isspace ( buffer[start] ); start++ )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
for ( stop=start; isalnum( buffer[stop] ) ||
|
for ( stop = start; isalnum ( buffer[stop] ) ||
|
||||||
buffer[stop] == '_' ||
|
buffer[stop] == '_' ||
|
||||||
buffer[stop] == '.' ; stop++ );
|
buffer[stop] == '.'; stop++ )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
if ( start == stop ) continue;
|
if ( start == stop )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// This is a nice little penalty, but doable? time will tell.
|
// This is a nice little penalty, but doable? time will tell.
|
||||||
// given num_favorites is max 25.
|
// given num_favorites is max 25.
|
||||||
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) {
|
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ )
|
||||||
if ( strncasecmp( &buffer[start], retv[j],stop-start ) == 0 ) found = 1;
|
{
|
||||||
|
if ( strncasecmp ( &buffer[start], retv[j], stop - start ) == 0 )
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( found == 1 ) continue;
|
if ( found == 1 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
retv = reallocate( retv, ( index+2 )*sizeof( char* ) );
|
retv = reallocate ( retv, ( index + 2 ) * sizeof ( char* ) );
|
||||||
retv[index] = strndup( &buffer[start], stop-start );
|
retv[index] = strndup ( &buffer[start], stop - start );
|
||||||
retv[index+1] = NULL;
|
retv[index + 1] = NULL;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose( fd );
|
fclose ( fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check this is still fast enough. (takes 1ms on laptop.)
|
// TODO: check this is still fast enough. (takes 1ms on laptop.)
|
||||||
if(index > num_favorites) {
|
if ( index > num_favorites )
|
||||||
qsort( &retv[num_favorites],index-num_favorites, sizeof( char* ), sort_func );
|
{
|
||||||
|
qsort ( &retv[num_favorites], index - num_favorites, sizeof ( char* ), sort_func );
|
||||||
}
|
}
|
||||||
free( path );
|
free ( path );
|
||||||
#ifdef TIMING
|
#ifdef TIMING
|
||||||
clock_gettime( CLOCK_REALTIME, &stop );
|
clock_gettime ( CLOCK_REALTIME, &stop );
|
||||||
|
|
||||||
if ( stop.tv_sec != start.tv_sec ) {
|
if ( stop.tv_sec != start.tv_sec )
|
||||||
stop.tv_nsec += ( stop.tv_sec-start.tv_sec )*1e9;
|
{
|
||||||
|
stop.tv_nsec += ( stop.tv_sec - start.tv_sec ) * 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
long diff = stop.tv_nsec-start.tv_nsec;
|
long diff = stop.tv_nsec - start.tv_nsec;
|
||||||
printf( "Time elapsed: %ld us\n", diff/1000 );
|
printf ( "Time elapsed: %ld us\n", diff / 1000 );
|
||||||
#endif
|
#endif
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
@ -284,35 +329,47 @@ SwitcherMode ssh_switcher_dialog ( char **input )
|
||||||
{
|
{
|
||||||
SwitcherMode retv = MODE_EXIT;
|
SwitcherMode retv = MODE_EXIT;
|
||||||
// act as a launcher
|
// act as a launcher
|
||||||
char **cmd_list = get_ssh( );
|
char **cmd_list = get_ssh ( );
|
||||||
|
|
||||||
if ( cmd_list == NULL ) {
|
if ( cmd_list == NULL )
|
||||||
cmd_list = allocate( 2*sizeof( char * ) );
|
{
|
||||||
cmd_list[0] = strdup( "No ssh hosts found" );
|
cmd_list = allocate ( 2 * sizeof ( char * ) );
|
||||||
|
cmd_list[0] = strdup ( "No ssh hosts found" );
|
||||||
cmd_list[1] = NULL;
|
cmd_list[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int shift=0;
|
int shift = 0;
|
||||||
int selected_line = 0;
|
int selected_line = 0;
|
||||||
int mretv = menu( cmd_list, input, "ssh", NULL, &shift,token_match, NULL , &selected_line );
|
int mretv = menu ( cmd_list, input, "ssh", NULL, &shift, token_match, NULL, &selected_line );
|
||||||
|
|
||||||
if ( mretv == MENU_NEXT ) {
|
if ( mretv == MENU_NEXT )
|
||||||
|
{
|
||||||
retv = NEXT_DIALOG;
|
retv = NEXT_DIALOG;
|
||||||
} else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) {
|
}
|
||||||
exec_ssh( cmd_list[selected_line] );
|
else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL )
|
||||||
} else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) {
|
{
|
||||||
exec_ssh( *input );
|
exec_ssh ( cmd_list[selected_line] );
|
||||||
} else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) {
|
}
|
||||||
|
else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' )
|
||||||
|
{
|
||||||
|
exec_ssh ( *input );
|
||||||
|
}
|
||||||
|
else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] )
|
||||||
|
{
|
||||||
delete_ssh ( cmd_list[selected_line] );
|
delete_ssh ( cmd_list[selected_line] );
|
||||||
// Stay
|
// Stay
|
||||||
retv = SSH_DIALOG;
|
retv = SSH_DIALOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i=0; cmd_list[i] != NULL; i++ ) {
|
for ( int i = 0; cmd_list[i] != NULL; i++ )
|
||||||
free( cmd_list[i] );
|
{
|
||||||
|
free ( cmd_list[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cmd_list != NULL ) free( cmd_list );
|
if ( cmd_list != NULL )
|
||||||
|
{
|
||||||
|
free ( cmd_list );
|
||||||
|
}
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
393
source/textbox.c
393
source/textbox.c
|
@ -1,29 +1,29 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
MIT/X11 License
|
MIT/X11 License
|
||||||
Copyright (c) 2012 Sean Pringle <sean.pringle@gmail.com>
|
Copyright (c) 2012 Sean Pringle <sean.pringle@gmail.com>
|
||||||
Modified (c) 2013-2014 Qball Cow <qball@gmpclient.org>
|
Modified (c) 2013-2014 Qball Cow <qball@gmpclient.org>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
The above copyright notice and this permission notice shall be
|
||||||
included in all copies or substantial portions of the Software.
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
|
@ -39,297 +39,342 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include "rofi.h"
|
#include "rofi.h"
|
||||||
#include "textbox.h"
|
#include "textbox.h"
|
||||||
#define SIDE_MARGIN 3
|
#define SIDE_MARGIN 3
|
||||||
|
|
||||||
extern Display *display;
|
extern Display *display;
|
||||||
|
|
||||||
void textbox_moveresize( textbox *tb, int x, int y, int w, int h );
|
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
|
||||||
|
|
||||||
// Xft text box, optionally editable
|
// Xft text box, optionally editable
|
||||||
textbox* textbox_create( Window parent,
|
textbox* textbox_create ( Window parent,
|
||||||
TextboxFlags flags,
|
TextboxFlags flags,
|
||||||
short x, short y, short w, short h,
|
short x, short y, short w, short h,
|
||||||
char *font, char *fg, char *bg,
|
char *font, char *fg, char *bg,
|
||||||
char *text, char *prompt )
|
char *text, char *prompt )
|
||||||
{
|
{
|
||||||
textbox *tb = calloc( 1, sizeof( textbox ) );
|
textbox *tb = calloc ( 1, sizeof ( textbox ) );
|
||||||
|
|
||||||
tb->flags = flags;
|
tb->flags = flags;
|
||||||
tb->parent = parent;
|
tb->parent = parent;
|
||||||
|
|
||||||
tb->x = x;
|
tb->x = x;
|
||||||
tb->y = y;
|
tb->y = y;
|
||||||
tb->w = MAX( 1, w );
|
tb->w = MAX ( 1, w );
|
||||||
tb->h = MAX( 1, h );
|
tb->h = MAX ( 1, h );
|
||||||
|
|
||||||
XColor color;
|
XColor color;
|
||||||
Colormap map = DefaultColormap( display, DefaultScreen( display ) );
|
Colormap map = DefaultColormap ( display, DefaultScreen ( display ) );
|
||||||
unsigned int cp = XAllocNamedColor( display, map, bg, &color, &color ) ? color.pixel: None;
|
unsigned int cp = XAllocNamedColor ( display, map, bg, &color, &color ) ? color.pixel : None;
|
||||||
|
|
||||||
tb->window = XCreateSimpleWindow( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
|
tb->window = XCreateSimpleWindow ( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
|
||||||
|
|
||||||
// need to preload the font to calc line height
|
// need to preload the font to calc line height
|
||||||
textbox_font( tb, font, fg, bg );
|
textbox_font ( tb, font, fg, bg );
|
||||||
|
|
||||||
tb->prompt = strdup( prompt ? prompt: "" );
|
tb->prompt = strdup ( prompt ? prompt : "" );
|
||||||
textbox_text( tb, text ? text: "" );
|
textbox_text ( tb, text ? text : "" );
|
||||||
textbox_cursor_end( tb );
|
textbox_cursor_end ( tb );
|
||||||
|
|
||||||
// auto height/width modes get handled here
|
// auto height/width modes get handled here
|
||||||
textbox_moveresize( tb, tb->x, tb->y, tb->w, tb->h );
|
textbox_moveresize ( tb, tb->x, tb->y, tb->w, tb->h );
|
||||||
|
|
||||||
// edit mode controls
|
// edit mode controls
|
||||||
if ( tb->flags & TB_EDITABLE ) {
|
if ( tb->flags & TB_EDITABLE )
|
||||||
tb->xim = XOpenIM( display, NULL, NULL, NULL );
|
{
|
||||||
tb->xic = XCreateIC( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
|
tb->xim = XOpenIM ( display, NULL, NULL, NULL );
|
||||||
|
tb->xic = XCreateIC ( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set an Xft font by name
|
// set an Xft font by name
|
||||||
void textbox_font( textbox *tb, char *font, char *fg, char *bg )
|
void textbox_font ( textbox *tb, char *font, char *fg, char *bg )
|
||||||
{
|
{
|
||||||
if ( tb->font ) {
|
if ( tb->font )
|
||||||
|
{
|
||||||
XftColorFree ( display,
|
XftColorFree ( display,
|
||||||
DefaultVisual( display, DefaultScreen( display ) ),
|
DefaultVisual ( display, DefaultScreen ( display ) ),
|
||||||
DefaultColormap( display, DefaultScreen( display ) ),
|
DefaultColormap ( display, DefaultScreen ( display ) ),
|
||||||
&tb->color_fg );
|
&tb->color_fg );
|
||||||
XftColorFree ( display,
|
XftColorFree ( display,
|
||||||
DefaultVisual( display, DefaultScreen( display ) ),
|
DefaultVisual ( display, DefaultScreen ( display ) ),
|
||||||
DefaultColormap( display, DefaultScreen( display ) ),
|
DefaultColormap ( display, DefaultScreen ( display ) ),
|
||||||
&tb->color_bg );
|
&tb->color_bg );
|
||||||
|
|
||||||
XftFontClose( display, tb->font );
|
XftFontClose ( display, tb->font );
|
||||||
}
|
}
|
||||||
|
|
||||||
tb->font = XftFontOpenName( display, DefaultScreen( display ), font );
|
tb->font = XftFontOpenName ( display, DefaultScreen ( display ), font );
|
||||||
|
|
||||||
XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), fg, &tb->color_fg );
|
XftColorAllocName ( display, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ), fg, &tb->color_fg );
|
||||||
XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), bg, &tb->color_bg );
|
XftColorAllocName ( display, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ), bg, &tb->color_bg );
|
||||||
}
|
}
|
||||||
|
|
||||||
// outer code may need line height, width, etc
|
// outer code may need line height, width, etc
|
||||||
void textbox_extents( textbox *tb )
|
void textbox_extents ( textbox *tb )
|
||||||
{
|
{
|
||||||
int length = strlen( tb->text ) + strlen( tb->prompt ) +1;
|
int length = strlen ( tb->text ) + strlen ( tb->prompt ) + 1;
|
||||||
char line[length + 1 ];
|
char line[length + 1 ];
|
||||||
sprintf( line, "%s %s", tb->prompt, tb->text );
|
sprintf ( line, "%s %s", tb->prompt, tb->text );
|
||||||
XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, length, &tb->extents );
|
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, length, &tb->extents );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the default text to display
|
// set the default text to display
|
||||||
void textbox_text( textbox *tb, char *text )
|
void textbox_text ( textbox *tb, char *text )
|
||||||
{
|
{
|
||||||
if ( tb->text ) free( tb->text );
|
if ( tb->text )
|
||||||
|
{
|
||||||
|
free ( tb->text );
|
||||||
|
}
|
||||||
|
|
||||||
tb->text = strdup( text );
|
tb->text = strdup ( text );
|
||||||
tb->cursor = MAX( 0,MIN( ( int )strlen( text ), tb->cursor ) );
|
tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
|
||||||
textbox_extents( tb );
|
textbox_extents ( tb );
|
||||||
}
|
}
|
||||||
|
|
||||||
// within the parent. handled auto width/height modes
|
// within the parent. handled auto width/height modes
|
||||||
void textbox_moveresize( textbox *tb, int x, int y, int w, int h )
|
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||||
{
|
{
|
||||||
if ( tb->flags & TB_AUTOHEIGHT )
|
if ( tb->flags & TB_AUTOHEIGHT )
|
||||||
|
{
|
||||||
h = tb->font->ascent + tb->font->descent;
|
h = tb->font->ascent + tb->font->descent;
|
||||||
|
}
|
||||||
|
|
||||||
if ( tb->flags & TB_AUTOWIDTH )
|
if ( tb->flags & TB_AUTOWIDTH )
|
||||||
|
{
|
||||||
w = tb->extents.width;
|
w = tb->extents.width;
|
||||||
|
}
|
||||||
|
|
||||||
if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h ) {
|
if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h )
|
||||||
|
{
|
||||||
tb->x = x;
|
tb->x = x;
|
||||||
tb->y = y;
|
tb->y = y;
|
||||||
tb->w = MAX( 1, w );
|
tb->w = MAX ( 1, w );
|
||||||
tb->h = MAX( 1, h );
|
tb->h = MAX ( 1, h );
|
||||||
XMoveResizeWindow( display, tb->window, tb->x, tb->y, tb->w, tb->h );
|
XMoveResizeWindow ( display, tb->window, tb->x, tb->y, tb->w, tb->h );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void textbox_show( textbox *tb )
|
void textbox_show ( textbox *tb )
|
||||||
{
|
{
|
||||||
XMapWindow( display, tb->window );
|
XMapWindow ( display, tb->window );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// will also unmap the window if still displayed
|
// will also unmap the window if still displayed
|
||||||
void textbox_free( textbox *tb )
|
void textbox_free ( textbox *tb )
|
||||||
{
|
{
|
||||||
if ( tb->flags & TB_EDITABLE ) {
|
if ( tb->flags & TB_EDITABLE )
|
||||||
XDestroyIC( tb->xic );
|
{
|
||||||
XCloseIM( tb->xim );
|
XDestroyIC ( tb->xic );
|
||||||
|
XCloseIM ( tb->xim );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tb->text ) free( tb->text );
|
if ( tb->text )
|
||||||
|
{
|
||||||
|
free ( tb->text );
|
||||||
|
}
|
||||||
|
|
||||||
if ( tb->prompt ) free( tb->prompt );
|
if ( tb->prompt )
|
||||||
|
{
|
||||||
|
free ( tb->prompt );
|
||||||
|
}
|
||||||
|
|
||||||
if ( tb->font ) {
|
if ( tb->font )
|
||||||
|
{
|
||||||
XftColorFree ( display,
|
XftColorFree ( display,
|
||||||
DefaultVisual( display, DefaultScreen( display ) ),
|
DefaultVisual ( display, DefaultScreen ( display ) ),
|
||||||
DefaultColormap( display, DefaultScreen( display ) ),
|
DefaultColormap ( display, DefaultScreen ( display ) ),
|
||||||
&tb->color_fg );
|
&tb->color_fg );
|
||||||
XftColorFree ( display,
|
XftColorFree ( display,
|
||||||
DefaultVisual( display, DefaultScreen( display ) ),
|
DefaultVisual ( display, DefaultScreen ( display ) ),
|
||||||
DefaultColormap( display, DefaultScreen( display ) ),
|
DefaultColormap ( display, DefaultScreen ( display ) ),
|
||||||
&tb->color_bg );
|
&tb->color_bg );
|
||||||
|
|
||||||
XftFontClose( display, tb->font );
|
XftFontClose ( display, tb->font );
|
||||||
}
|
}
|
||||||
|
|
||||||
XDestroyWindow( display, tb->window );
|
XDestroyWindow ( display, tb->window );
|
||||||
free( tb );
|
free ( tb );
|
||||||
}
|
}
|
||||||
|
|
||||||
void textbox_draw( textbox *tb )
|
void textbox_draw ( textbox *tb )
|
||||||
{
|
{
|
||||||
XGlyphInfo extents;
|
XGlyphInfo extents;
|
||||||
|
|
||||||
GC context = XCreateGC( display, tb->window, 0, 0 );
|
GC context = XCreateGC ( display, tb->window, 0, 0 );
|
||||||
Pixmap canvas = XCreatePixmap( display, tb->window, tb->w, tb->h, DefaultDepth( display, DefaultScreen( display ) ) );
|
Pixmap canvas = XCreatePixmap ( display, tb->window, tb->w, tb->h, DefaultDepth ( display, DefaultScreen ( display ) ) );
|
||||||
XftDraw *draw = XftDrawCreate( display, canvas, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ) );
|
XftDraw *draw = XftDrawCreate ( display, canvas, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ) );
|
||||||
|
|
||||||
// clear canvas
|
// clear canvas
|
||||||
XftDrawRect( draw, &tb->color_bg, 0, 0, tb->w, tb->h );
|
XftDrawRect ( draw, &tb->color_bg, 0, 0, tb->w, tb->h );
|
||||||
|
|
||||||
char *line = tb->text,
|
char *line = tb->text,
|
||||||
*text = tb->text ? tb->text: "",
|
*text = tb->text ? tb->text : "",
|
||||||
*prompt = tb->prompt ? tb->prompt: "";
|
*prompt = tb->prompt ? tb->prompt : "";
|
||||||
|
|
||||||
int text_len = strlen( text );
|
int text_len = strlen ( text );
|
||||||
int length = text_len;
|
int length = text_len;
|
||||||
int line_height = tb->font->ascent + tb->font->descent;
|
int line_height = tb->font->ascent + tb->font->descent;
|
||||||
int line_width = 0;
|
int line_width = 0;
|
||||||
|
|
||||||
int cursor_x = 0;
|
int cursor_x = 0;
|
||||||
int cursor_width = MAX( 2, line_height/10 );
|
int cursor_width = MAX ( 2, line_height / 10 );
|
||||||
|
|
||||||
if ( tb->flags & TB_EDITABLE ) {
|
if ( tb->flags & TB_EDITABLE )
|
||||||
|
{
|
||||||
int cursor_offset = 0;
|
int cursor_offset = 0;
|
||||||
int prompt_len = strlen( prompt ) +1;
|
int prompt_len = strlen ( prompt ) + 1;
|
||||||
length = text_len + prompt_len;
|
length = text_len + prompt_len;
|
||||||
cursor_offset = MIN( tb->cursor + prompt_len, length );
|
cursor_offset = MIN ( tb->cursor + prompt_len, length );
|
||||||
|
|
||||||
line = alloca( length + 10 );
|
line = alloca ( length + 10 );
|
||||||
sprintf( line, "%s %s", prompt, text );
|
sprintf ( line, "%s %s", prompt, text );
|
||||||
|
|
||||||
// replace spaces so XftTextExtents8 includes their width
|
// replace spaces so XftTextExtents8 includes their width
|
||||||
for ( int i = 0; i < length; i++ ) if ( isspace( line[i] ) ) line[i] = '_';
|
for ( int i = 0; i < length; i++ )
|
||||||
|
{
|
||||||
|
if ( isspace ( line[i] ) )
|
||||||
|
{
|
||||||
|
line[i] = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// calc cursor position
|
// calc cursor position
|
||||||
XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, cursor_offset, &extents );
|
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, cursor_offset, &extents );
|
||||||
cursor_x = extents.width;
|
cursor_x = extents.width;
|
||||||
|
|
||||||
// restore correct text string with spaces
|
// restore correct text string with spaces
|
||||||
sprintf( line, "%s %s", prompt, text );
|
sprintf ( line, "%s %s", prompt, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
// calc full input text width
|
// calc full input text width
|
||||||
// Calculate the right size, so no characters are cut off.
|
// Calculate the right size, so no characters are cut off.
|
||||||
// TODO: Check performance of this.
|
// TODO: Check performance of this.
|
||||||
while ( 1 ) {
|
while ( 1 )
|
||||||
XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, length, &extents );
|
{
|
||||||
|
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, length, &extents );
|
||||||
line_width = extents.width;
|
line_width = extents.width;
|
||||||
|
|
||||||
if ( line_width < ( tb->w-2*SIDE_MARGIN ) ) break;
|
if ( line_width < ( tb->w - 2 * SIDE_MARGIN ) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for(length-=1; length > 0 && (line[length]&0xc0) == 0x80; length -=1);
|
for ( length -= 1; length > 0 && ( line[length] & 0xc0 ) == 0x80; length -= 1 )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = SIDE_MARGIN, y = tb->font->ascent;
|
int x = SIDE_MARGIN, y = tb->font->ascent;
|
||||||
|
|
||||||
if ( tb->flags & TB_RIGHT ) x = tb->w - line_width;
|
if ( tb->flags & TB_RIGHT )
|
||||||
|
{
|
||||||
|
x = tb->w - line_width;
|
||||||
|
}
|
||||||
|
|
||||||
if ( tb->flags & TB_CENTER ) x = ( tb->w - line_width ) / 2;
|
if ( tb->flags & TB_CENTER )
|
||||||
|
{
|
||||||
|
x = ( tb->w - line_width ) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
// draw the text, including any prompt in edit mode
|
// draw the text, including any prompt in edit mode
|
||||||
XftDrawStringUtf8( draw, &tb->color_fg, tb->font, x, y, ( unsigned char* )line, length );
|
XftDrawStringUtf8 ( draw, &tb->color_fg, tb->font, x, y, ( unsigned char * ) line, length );
|
||||||
|
|
||||||
// draw the cursor
|
// draw the cursor
|
||||||
if ( tb->flags & TB_EDITABLE )
|
if ( tb->flags & TB_EDITABLE )
|
||||||
XftDrawRect( draw, &tb->color_fg, cursor_x+SIDE_MARGIN, 2, cursor_width, line_height-4 );
|
{
|
||||||
|
XftDrawRect ( draw, &tb->color_fg, cursor_x + SIDE_MARGIN, 2, cursor_width, line_height - 4 );
|
||||||
|
}
|
||||||
|
|
||||||
XftDrawRect( draw, &tb->color_bg, tb->w-SIDE_MARGIN, 0, SIDE_MARGIN, tb->h );
|
XftDrawRect ( draw, &tb->color_bg, tb->w - SIDE_MARGIN, 0, SIDE_MARGIN, tb->h );
|
||||||
// flip canvas to window
|
// flip canvas to window
|
||||||
XCopyArea( display, canvas, tb->window, context, 0, 0, tb->w, tb->h, 0, 0 );
|
XCopyArea ( display, canvas, tb->window, context, 0, 0, tb->w, tb->h, 0, 0 );
|
||||||
|
|
||||||
XFreeGC( display, context );
|
XFreeGC ( display, context );
|
||||||
XftDrawDestroy( draw );
|
XftDrawDestroy ( draw );
|
||||||
XFreePixmap( display, canvas );
|
XFreePixmap ( display, canvas );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t nextrune(textbox *tb, int inc) {
|
static size_t nextrune ( textbox *tb, int inc )
|
||||||
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
/* return location of next utf8 rune in the given direction (+1 or -1) */
|
/* return location of next utf8 rune in the given direction (+1 or -1) */
|
||||||
for(n = tb->cursor + inc; n + inc >= 0 && (tb->text[n] & 0xc0) == 0x80; n += inc);
|
for ( n = tb->cursor + inc; n + inc >= 0 && ( tb->text[n] & 0xc0 ) == 0x80; n += inc )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
// cursor handling for edit mode
|
// cursor handling for edit mode
|
||||||
void textbox_cursor( textbox *tb, int pos )
|
void textbox_cursor ( textbox *tb, int pos )
|
||||||
{
|
{
|
||||||
tb->cursor = MAX( 0, MIN( ( int )strlen( tb->text ), pos ) );
|
tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( tb->text ), pos ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// move right
|
// move right
|
||||||
void textbox_cursor_inc( textbox *tb )
|
void textbox_cursor_inc ( textbox *tb )
|
||||||
{
|
{
|
||||||
textbox_cursor( tb, nextrune(tb, 1) );
|
textbox_cursor ( tb, nextrune ( tb, 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// move left
|
// move left
|
||||||
void textbox_cursor_dec( textbox *tb )
|
void textbox_cursor_dec ( textbox *tb )
|
||||||
{
|
{
|
||||||
textbox_cursor( tb, nextrune(tb,-1) );
|
textbox_cursor ( tb, nextrune ( tb, -1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// end of line
|
// end of line
|
||||||
void textbox_cursor_end( textbox *tb )
|
void textbox_cursor_end ( textbox *tb )
|
||||||
{
|
{
|
||||||
tb->cursor = ( int )strlen( tb->text );
|
tb->cursor = ( int ) strlen ( tb->text );
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert text
|
// insert text
|
||||||
void textbox_insert( textbox *tb, int pos, char *str )
|
void textbox_insert ( textbox *tb, int pos, char *str )
|
||||||
{
|
{
|
||||||
int len = ( int )strlen( tb->text ), slen = ( int )strlen( str );
|
int len = ( int ) strlen ( tb->text ), slen = ( int ) strlen ( str );
|
||||||
pos = MAX( 0, MIN( len, pos ) );
|
pos = MAX ( 0, MIN ( len, pos ) );
|
||||||
// expand buffer
|
// expand buffer
|
||||||
tb->text = realloc( tb->text, len + slen + 1 );
|
tb->text = realloc ( tb->text, len + slen + 1 );
|
||||||
// move everything after cursor upward
|
// move everything after cursor upward
|
||||||
char *at = tb->text + pos;
|
char *at = tb->text + pos;
|
||||||
memmove( at + slen, at, len - pos + 1 );
|
memmove ( at + slen, at, len - pos + 1 );
|
||||||
// insert new str
|
// insert new str
|
||||||
memmove( at, str, slen );
|
memmove ( at, str, slen );
|
||||||
textbox_extents( tb );
|
textbox_extents ( tb );
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove text
|
// remove text
|
||||||
void textbox_delete( textbox *tb, int pos, int dlen )
|
void textbox_delete ( textbox *tb, int pos, int dlen )
|
||||||
{
|
{
|
||||||
int len = strlen( tb->text );
|
int len = strlen ( tb->text );
|
||||||
pos = MAX( 0, MIN( len, pos ) );
|
pos = MAX ( 0, MIN ( len, pos ) );
|
||||||
// move everything after pos+dlen down
|
// move everything after pos+dlen down
|
||||||
char *at = tb->text + pos;
|
char *at = tb->text + pos;
|
||||||
memmove( at, at + dlen, len - pos );
|
memmove ( at, at + dlen, len - pos );
|
||||||
textbox_extents( tb );
|
textbox_extents ( tb );
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete on character
|
// delete on character
|
||||||
void textbox_cursor_del( textbox *tb )
|
void textbox_cursor_del ( textbox *tb )
|
||||||
{
|
{
|
||||||
int del_r = nextrune(tb, 1);
|
int del_r = nextrune ( tb, 1 );
|
||||||
textbox_delete( tb, tb->cursor, del_r-tb->cursor );
|
textbox_delete ( tb, tb->cursor, del_r - tb->cursor );
|
||||||
}
|
}
|
||||||
|
|
||||||
// back up and delete one character
|
// back up and delete one character
|
||||||
void textbox_cursor_bkspc( textbox *tb )
|
void textbox_cursor_bkspc ( textbox *tb )
|
||||||
{
|
{
|
||||||
if ( tb->cursor > 0 ) {
|
if ( tb->cursor > 0 )
|
||||||
textbox_cursor_dec( tb );
|
{
|
||||||
textbox_cursor_del( tb );
|
textbox_cursor_dec ( tb );
|
||||||
|
textbox_cursor_del ( tb );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,42 +382,56 @@ void textbox_cursor_bkspc( textbox *tb )
|
||||||
// 0 = unhandled
|
// 0 = unhandled
|
||||||
// 1 = handled
|
// 1 = handled
|
||||||
// -1 = handled and return pressed (finished)
|
// -1 = handled and return pressed (finished)
|
||||||
int textbox_keypress( textbox *tb, XEvent *ev )
|
int textbox_keypress ( textbox *tb, XEvent *ev )
|
||||||
{
|
{
|
||||||
KeySym key;
|
KeySym key;
|
||||||
Status stat;
|
Status stat;
|
||||||
char pad[32];
|
char pad[32];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if ( !( tb->flags & TB_EDITABLE ) ) return 0;
|
if ( !( tb->flags & TB_EDITABLE ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
len = Xutf8LookupString( tb->xic, &ev->xkey, pad, sizeof( pad ), &key, &stat );
|
len = Xutf8LookupString ( tb->xic, &ev->xkey, pad, sizeof ( pad ), &key, &stat );
|
||||||
pad[len] = 0;
|
pad[len] = 0;
|
||||||
|
|
||||||
if ( key == XK_Left ) {
|
if ( key == XK_Left )
|
||||||
textbox_cursor_dec( tb );
|
{
|
||||||
|
textbox_cursor_dec ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
} else if ( key == XK_Right ) {
|
}
|
||||||
textbox_cursor_inc( tb );
|
else if ( key == XK_Right )
|
||||||
|
{
|
||||||
|
textbox_cursor_inc ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
} /*else if ( key == XK_Home ) {
|
} /*else if ( key == XK_Home ) {
|
||||||
|
|
||||||
textbox_cursor_home( tb );
|
textbox_cursor_home( tb );
|
||||||
|
return 1;
|
||||||
|
} else if ( key == XK_End ) {
|
||||||
|
textbox_cursor_end( tb );
|
||||||
|
return 1;
|
||||||
|
} */
|
||||||
|
else if ( key == XK_Delete )
|
||||||
|
{
|
||||||
|
textbox_cursor_del ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
} else if ( key == XK_End ) {
|
}
|
||||||
textbox_cursor_end( tb );
|
else if ( key == XK_BackSpace )
|
||||||
|
{
|
||||||
|
textbox_cursor_bkspc ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
} */else if ( key == XK_Delete ) {
|
}
|
||||||
textbox_cursor_del( tb );
|
else if ( key == XK_Return )
|
||||||
return 1;
|
{
|
||||||
} else if ( key == XK_BackSpace ) {
|
|
||||||
textbox_cursor_bkspc( tb );
|
|
||||||
return 1;
|
|
||||||
} else if ( key == XK_Return ) {
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if ( !iscntrl( *pad ) ) {
|
}
|
||||||
textbox_insert( tb, tb->cursor, pad );
|
else if ( !iscntrl ( *pad ) )
|
||||||
textbox_cursor_inc( tb );
|
{
|
||||||
|
textbox_insert ( tb, tb->cursor, pad );
|
||||||
|
textbox_cursor_inc ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,64 +34,72 @@
|
||||||
|
|
||||||
// Big thanks to Sean Pringle for this code.
|
// Big thanks to Sean Pringle for this code.
|
||||||
// This maps xresource options to config structure.
|
// This maps xresource options to config structure.
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
xrm_String = 0,
|
xrm_String = 0,
|
||||||
xrm_Number = 1
|
xrm_Number = 1
|
||||||
} XrmOptionType;
|
} XrmOptionType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
int type;
|
{
|
||||||
char * name ;
|
int type;
|
||||||
union {
|
char * name;
|
||||||
|
union
|
||||||
|
{
|
||||||
unsigned int * num;
|
unsigned int * num;
|
||||||
char ** str;
|
char ** str;
|
||||||
};
|
};
|
||||||
} XrmOption;
|
} XrmOption;
|
||||||
XrmOption xrmOptions[] = {
|
XrmOption xrmOptions[] = {
|
||||||
{ xrm_Number, "opacity", { .num = &config.window_opacity } },
|
{ xrm_Number, "opacity", { .num = &config.window_opacity } },
|
||||||
{ xrm_Number, "width", { .num = &config.menu_width } },
|
{ xrm_Number, "width", { .num = &config.menu_width } },
|
||||||
{ xrm_Number, "lines", { .num = &config.menu_lines } },
|
{ xrm_Number, "lines", { .num = &config.menu_lines } },
|
||||||
{ xrm_String, "font", { .str = &config.menu_font } },
|
{ xrm_String, "font", { .str = &config.menu_font } },
|
||||||
{ xrm_String, "foreground", { .str = &config.menu_fg } },
|
{ xrm_String, "foreground", { .str = &config.menu_fg } },
|
||||||
{ xrm_String, "background", { .str = &config.menu_bg } },
|
{ xrm_String, "background", { .str = &config.menu_bg } },
|
||||||
{ xrm_String, "highlightfg", { .str = &config.menu_hlfg } },
|
{ xrm_String, "highlightfg", { .str = &config.menu_hlfg } },
|
||||||
{ xrm_String, "highlightbg", { .str = &config.menu_hlbg } },
|
{ xrm_String, "highlightbg", { .str = &config.menu_hlbg } },
|
||||||
{ xrm_String, "bordercolor", { .str = &config.menu_bc } },
|
{ xrm_String, "bordercolor", { .str = &config.menu_bc } },
|
||||||
{ xrm_Number, "padding", { .num = &config.padding } },
|
{ xrm_Number, "padding", { .num = &config.padding } },
|
||||||
{ xrm_Number, "borderwidth", { .num = &config.menu_bw} },
|
{ xrm_Number, "borderwidth", { .num = &config.menu_bw } },
|
||||||
{ xrm_String, "terminal", { .str = &config.terminal_emulator } },
|
{ xrm_String, "terminal", { .str = &config.terminal_emulator } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void parse_xresource_options( Display *display )
|
void parse_xresource_options ( Display *display )
|
||||||
{
|
{
|
||||||
// Map Xresource entries to simpleswitcher config options.
|
// Map Xresource entries to simpleswitcher config options.
|
||||||
XrmInitialize();
|
XrmInitialize ();
|
||||||
char * xRMS = XResourceManagerString ( display );
|
char * xRMS = XResourceManagerString ( display );
|
||||||
|
|
||||||
if ( xRMS != NULL ) {
|
if ( xRMS != NULL )
|
||||||
|
{
|
||||||
XrmDatabase xDB = XrmGetStringDatabase ( xRMS );
|
XrmDatabase xDB = XrmGetStringDatabase ( xRMS );
|
||||||
|
|
||||||
char * xrmType;
|
char * xrmType;
|
||||||
XrmValue xrmValue;
|
XrmValue xrmValue;
|
||||||
// TODO: update when we have new name.
|
// TODO: update when we have new name.
|
||||||
const char * namePrefix = "rofi";
|
const char * namePrefix = "rofi";
|
||||||
const char * classPrefix = "Simpleswitcher";
|
const char * classPrefix = "Simpleswitcher";
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); ++i ) {
|
for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); ++i )
|
||||||
char *name = ( char* ) allocate( ( strlen ( namePrefix ) + 1 + strlen ( xrmOptions[i].name ) ) *
|
{
|
||||||
sizeof ( char ) + 1 );
|
char *name = ( char * ) allocate ( ( strlen ( namePrefix ) + 1 + strlen ( xrmOptions[i].name ) ) *
|
||||||
char *class = ( char* ) allocate( ( strlen ( classPrefix ) + 1 + strlen ( xrmOptions[i].name ) ) *
|
sizeof ( char ) + 1 );
|
||||||
sizeof ( char ) + 1 );
|
char *class = ( char * ) allocate ( ( strlen ( classPrefix ) + 1 + strlen ( xrmOptions[i].name ) ) *
|
||||||
|
sizeof ( char ) + 1 );
|
||||||
sprintf ( name, "%s.%s", namePrefix, xrmOptions[i].name );
|
sprintf ( name, "%s.%s", namePrefix, xrmOptions[i].name );
|
||||||
sprintf ( class, "%s.%s", classPrefix, xrmOptions[i].name );
|
sprintf ( class, "%s.%s", classPrefix, xrmOptions[i].name );
|
||||||
|
|
||||||
if ( XrmGetResource ( xDB, name, class, &xrmType, &xrmValue ) ) {
|
if ( XrmGetResource ( xDB, name, class, &xrmType, &xrmValue ) )
|
||||||
|
{
|
||||||
if ( xrmOptions[i].type == xrm_String ) {
|
if ( xrmOptions[i].type == xrm_String )
|
||||||
|
{
|
||||||
*xrmOptions[i].str = ( char * ) allocate ( xrmValue.size * sizeof ( char ) );
|
*xrmOptions[i].str = ( char * ) allocate ( xrmValue.size * sizeof ( char ) );
|
||||||
strncpy ( *xrmOptions[i].str, xrmValue.addr, xrmValue.size );
|
strncpy ( *xrmOptions[i].str, xrmValue.addr, xrmValue.size );
|
||||||
} else if ( xrmOptions[i].type == xrm_Number ) {
|
}
|
||||||
|
else if ( xrmOptions[i].type == xrm_Number )
|
||||||
|
{
|
||||||
*xrmOptions[i].num = strtol ( xrmValue.addr, NULL, 10 );
|
*xrmOptions[i].num = strtol ( xrmValue.addr, NULL, 10 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,5 +108,4 @@ void parse_xresource_options( Display *display )
|
||||||
free ( class );
|
free ( class );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue