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