Index: Makefile =================================================================== RCS file: /home/pcvs/ports/x11/thinglaunch/Makefile,v retrieving revision 1.10 diff -u -u -r1.10 Makefile --- Makefile 2 Sep 2009 11:50:05 -0000 1.10 +++ Makefile 6 Sep 2009 19:02:52 -0000 @@ -16,13 +16,14 @@ USE_XORG= x11 xproto MAKE_JOBS_SAFE= yes -CPPFLAGS= -I${LOCALBASE}/include -lX11 +CPPFLAGS= -I${LOCALBASE}/include -lX11 -ggdb LDFLAGS= -L${LOCALBASE}/lib PLIST_FILES= bin/thinglaunch do-build: - ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} ${WRKSRC}/${PORTNAME}.c \ + ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} \ + ${WRKSRC}/${PORTNAME}.c ${WRKSRC}/completion.c \ -o ${WRKSRC}/${PORTNAME} do-install: Index: files/patch-completion =================================================================== RCS file: files/patch-completion diff -N files/patch-completion --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ files/patch-completion 6 Sep 2009 18:59:22 -0000 @@ -0,0 +1,182 @@ +--- completion.h.orig 2009-09-05 16:15:04.000000000 +0200 ++++ completion.h 2009-09-06 20:31:31.000000000 +0200 +@@ -0,0 +1,15 @@ ++#ifndef COMPLETION_H ++#define COMPLETION_H ++ ++#include ++ ++#define MAX_CMD_LEN 256 ++ ++typedef struct comp_ *comp_t; ++ ++int comp_init(comp_t *); ++int comp_cleanup(comp_t); ++int comp_update(comp_t, char *); ++char *comp_next(comp_t); ++ ++#endif /* !COMPLETION_H */ +--- completion.c.orig 2009-09-05 16:15:04.000000000 +0200 ++++ completion.c 2009-09-06 20:40:30.000000000 +0200 +@@ -0,0 +1,161 @@ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "completion.h" ++ ++struct comp_ { ++ char **path_elem; ++ char **exec_elem; ++ size_t nof_path_elem; ++ size_t nof_exec_elem; ++ size_t curr_elem; ++ uid_t uid; ++ gid_t gid; ++}; ++ ++int ++comp_init(comp_t *compp) ++{ ++ comp_t comp; ++ char *path; ++ char *path_elem_start; ++ char *path_elem_end; ++ size_t path_len; ++ size_t i; ++ ++ /* ++ * initialize structure ++ */ ++ if (!(comp = malloc(sizeof *comp))) { ++ return (1); ++ } ++ ++ /* ++ * initialize path elements ++ */ ++ path_elem_start = path = getenv("PATH"); ++ path_elem_end = NULL; ++ path_len = strlen(path); ++ for (i=0; inof_path_elem++; ++ path_elem_end = path+i; ++ if (!(comp->path_elem = realloc(comp->path_elem, comp->nof_path_elem * sizeof (char *)))) { ++ return (1); ++ } ++ if (!(comp->path_elem[comp->nof_path_elem-1] = malloc((path_elem_end - path_elem_start + 1) * sizeof (char)))) { ++ return (1); ++ } ++ memcpy(comp->path_elem[comp->nof_path_elem-1], path_elem_start, path_elem_end - path_elem_start); ++ comp->path_elem[comp->nof_path_elem-1][path_elem_end - path_elem_start] = '\0'; ++ path_elem_start = path+i+1; ++ } ++ } ++ ++ /* ++ * initialize other members ++ */ ++ comp->exec_elem = NULL; ++ comp->nof_exec_elem = comp->curr_elem = 0; ++ comp->uid = getuid(); ++ comp->gid = getgid(); ++ ++ *compp = comp; ++ return (0); ++} ++ ++int ++comp_cleanup(comp_t comp) ++{ ++ size_t i; ++ ++ for (i=0; inof_path_elem; i++) { ++ free(comp->path_elem[i]); ++ } ++ free(comp->path_elem); ++ ++ for (i=0; inof_exec_elem; i++) { ++ free(comp->exec_elem[i]); ++ } ++ free(comp->exec_elem); ++ ++ free(comp); ++ return (0); ++} ++ ++int ++comp_update(comp_t comp, char *hint) ++{ ++ struct dirent *dp; ++ struct stat sb; ++ char buffer[MAX_CMD_LEN+1]; ++ DIR *dirp; ++ size_t hint_len; ++ size_t i; ++ ++ for (i=0; inof_exec_elem; i++) { ++ free(comp->exec_elem[i]); ++ } ++ free(comp->exec_elem); ++ comp->exec_elem = NULL; ++ comp->nof_exec_elem = comp->curr_elem = 0; ++ ++ if ((hint_len = strlen(hint)) == 0) { ++ return (EINVAL); ++ } ++ ++ /* ++ * Each path element ++ */ ++ for (i=0; inof_path_elem; i++) { ++ if (!(dirp = opendir(comp->path_elem[i]))) { ++ continue; ++ } ++ while ((dp = readdir(dirp))) { ++ if (!strncmp(dp->d_name, hint, hint_len)) { ++ snprintf(buffer, MAX_CMD_LEN, "%s/%s", comp->path_elem[i], dp->d_name); ++ if (stat(buffer, &sb)) { ++ continue; ++ } ++ if (sb.st_mode & S_IFREG) { ++ if (sb.st_uid == comp->uid && sb.st_mode & S_IXUSR || ++ sb.st_gid == comp->gid && sb.st_mode & S_IXGRP || ++ sb.st_mode & S_IXOTH) { ++ ++ comp->nof_exec_elem++; ++ if (!(comp->exec_elem = realloc(comp->exec_elem, comp->nof_exec_elem * sizeof (char *)))) { ++ closedir(dirp); ++ return (ENOMEM); ++ } ++ if (!(comp->exec_elem[comp->nof_exec_elem-1] = strdup(buffer))) { ++ closedir(dirp); ++ return (ENOMEM); ++ } ++ } ++ } ++ } ++ } ++ } ++ return (0); ++} ++ ++char * ++comp_next(comp_t comp) ++{ ++ if (!comp->exec_elem) { ++ return (NULL); ++ } ++ ++ if (comp->curr_elem == comp->nof_exec_elem) { ++ comp->curr_elem = 0; ++ } ++ ++ return (comp->exec_elem[comp->curr_elem++]); ++} Index: files/patch-thinglaunch.c =================================================================== RCS file: /home/pcvs/ports/x11/thinglaunch/files/patch-thinglaunch.c,v retrieving revision 1.2 diff -u -u -r1.2 patch-thinglaunch.c --- files/patch-thinglaunch.c 2 Sep 2009 11:50:05 -0000 1.2 +++ files/patch-thinglaunch.c 6 Sep 2009 18:51:40 -0000 @@ -1,6 +1,6 @@ --- thinglaunch.c.orig 2004-09-20 16:27:56.000000000 +0200 -+++ thinglaunch.c 2009-09-01 22:11:10.000000000 +0200 -@@ -19,10 +19,14 @@ ++++ thinglaunch.c 2009-09-06 20:50:30.000000000 +0200 +@@ -19,10 +19,16 @@ */ #include #include @@ -12,13 +12,24 @@ +#ifdef __FreeBSD__ +#include +#endif ++ ++#include "completion.h" static void createWindow(); static void setupGC(); -@@ -50,10 +54,13 @@ +@@ -44,16 +50,24 @@ + int screen_num; + unsigned long black, white; + +-#define MAXCMD 255 ++comp_t comp; ++ + #define WINWIDTH 640 + #define WINHEIGHT 25 /* the actual commandline */ - char command[MAXCMD+1]; +-char command[MAXCMD+1]; ++char command[MAX_CMD_LEN+1]; +size_t cursor_pos; int main(int argc, char ** argv) { @@ -26,10 +37,14 @@ command[0] = 0x0; + cursor_pos = 0; + ++ if (comp_init(&comp)) { ++ exit(1); ++ } ++ createWindow(); setupGC(); -@@ -209,15 +216,15 @@ +@@ -209,15 +223,15 @@ int font_height; int textwidth; @@ -49,12 +64,14 @@ XFlush(display); -@@ -229,22 +236,36 @@ +@@ -228,37 +242,71 @@ + #define KEYBUFLEN 20 char buffer[KEYBUFLEN+1]; ++ char *cmd; KeySym key_symbol; - int len; -+ int len, tmp_pos; ++ int len, tmp_pos, need_rescan = 0; len = XLookupString(keyevent, buffer, 1, &key_symbol, NULL); buffer[len] = 0x0; @@ -63,6 +80,7 @@ switch(key_symbol) { - case 0xff1b: /* this is escape */ + case XK_Escape: ++ comp_cleanup(comp); exit(0); break; - case 0xff08: /* backspace */ @@ -74,11 +92,13 @@ + if (cursor_pos) + for (tmp_pos = --cursor_pos; tmp_pos <= len; tmp_pos++) + command[tmp_pos] = command[tmp_pos+1]; ++ need_rescan = 1; + break; + case XK_Left: + if (cursor_pos) + cursor_pos--; -+ break; + break; +- case 0xff0d: /* enter */ + case XK_Right: + if (cursor_pos < len) + cursor_pos++; @@ -88,24 +108,43 @@ + break; + case XK_End: + cursor_pos = len; - break; -- case 0xff0d: /* enter */ ++ break; + case XK_Return: execcmd(); break; ++ case XK_Tab: ++ cmd = comp_next(comp); ++ if (!cmd) { ++ break; ++ } ++ cmd = strrchr(cmd, '/'); ++ sprintf(command, "%s", cmd+1); ++ cursor_pos = strlen(cmd+1); ++ break; default: -@@ -253,10 +274,11 @@ + break; + } /* normal printable chars */ if (key_symbol >= 0x20 && key_symbol <= 0x7e) { - len = strlen(command); - if (len < MAXCMD) { +- if (len < MAXCMD) { - command[len] = buffer[0]; - command[len+1] = 0x0; -+ if (cursor_pos != len) -+ for (tmp_pos = len; tmp_pos > cursor_pos; tmp_pos--) ++ if (len < MAX_CMD_LEN) { ++ if (cursor_pos != len) { ++ for (tmp_pos = len; tmp_pos > cursor_pos; tmp_pos--) { + command[tmp_pos] = command[tmp_pos-1]; ++ } ++ } + command[cursor_pos++] = buffer[0]; ++ need_rescan = 1; } } ++ ++ if (need_rescan) { ++ comp_update(comp, command); ++ } redraw(); + + }