#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
#include "config.h"
#include "proto.h"
{
return do_writeout(0);
}
+
+
+/*
+ * These functions (username_tab_completion, cwd_tab_completion, and
+ * input_tab were taken from busybox 0.46 (cmdedit.c). Here is the notice
+ * from that file:
+ *
+ * Termios command line History and Editting, originally
+ * intended for NetBSD sh (ash)
+ * Copyright (c) 1999
+ * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu>
+ * Etc: Dave Cinege <dcinege@psychosis.com>
+ * Majorly adjusted/re-written for busybox:
+ * Erik Andersen <andersee@debian.org>
+ *
+ * You may use this code as you wish, so long as the original author(s)
+ * are attributed in any redistributions of the source code.
+ * This code is 'as is' with no warranty.
+ * This code may safely be consumed by a BSD or GPL license.
+ */
+
+char **username_tab_completion(char *buf, int *num_matches)
+{
+ char **matches = (char **) NULL;
+ *num_matches = 0;
+#ifdef DEBUG
+ fprintf(stderr, "\nin username_tab_completion\n");
+#endif
+ return (matches);
+}
+
+/* This was originally called exe_n_cwd_tab_completion, but we're not
+ worried about executables, only filenames :> */
+
+char **cwd_tab_completion(char *buf, int *num_matches)
+{
+ char *dirName, *tmp = NULL;
+ char **matches = (char **) NULL;
+ DIR *dir;
+ struct dirent *next;
+
+ matches = malloc(sizeof(char *) * 50);
+
+ /* Stick a wildcard onto the buf, for later use */
+ strcat(buf, "*");
+
+ /* Now wall the current directory */
+/* if (!strcmp(filename, ""))
+ dirName = get_current_dir_name(); */
+
+ if (strcmp(buf, "") && strstr(buf, "/")) {
+ dirName = malloc(strlen(buf) + 1);
+ tmp = buf + strlen(buf);
+ while (*tmp != '/' && tmp != buf)
+ tmp--;
+ strncpy(dirName, buf, tmp - buf);
+ dirName[tmp - buf] = 0;
+ tmp++;
+
+ } else {
+ if ((dirName = getcwd(NULL, 0)) == NULL)
+ return matches;
+ else
+ tmp = buf;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "\nDir = %s\n", dirName);
+ fprintf(stderr, "\nbuf = %s\n", buf);
+ fprintf(stderr, "\ntmp = %s\n", tmp);
+#endif
+
+ dir = opendir(dirName);
+ if (!dir) {
+ /* Don't print an error, just shut up and return */
+ *num_matches = 0;
+ beep();
+ return (matches);
+ }
+ while ((next = readdir(dir)) != NULL) {
+
+ /* Some quick sanity checks */
+ if ((strcmp(next->d_name, "..") == 0)
+ || (strcmp(next->d_name, ".") == 0)) {
+ continue;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "\nComparing \'%s\'\n", next->d_name);
+#endif
+ /* See if this matches */
+ if (check_wildcard_match(next->d_name, tmp) == TRUE) {
+ /* Cool, found a match. Add it to the list */
+ matches[*num_matches] = malloc(strlen(next->d_name) + 1);
+ strcpy(matches[*num_matches], next->d_name);
+ ++*num_matches;
+ //matches = realloc( matches, sizeof(char*)*(*num_matches));
+ }
+ }
+
+ return (matches);
+}
+
+/* This function now return an int which refers to how much the
+ * statusbar (place) should be advanced, i.e. the new cursor pos.
+ */
+int input_tab(char *buf, int place, int lastWasTab)
+{
+ /* Do TAB completion */
+ static int num_matches = 0;
+ static char **matches = (char **) NULL;
+ int pos = place, newplace = 0;
+
+ if (lastWasTab == FALSE) {
+ char *tmp, *matchBuf;
+
+ /* For now, we will not bother with trying to distinguish
+ * whether the cursor is in/at a command extression -- we
+ * will always try all possible matches. If you don't like
+ * that then feel free to fix it.
+ */
+
+ /* Make a local copy of the string -- up to the position of the
+ cursor */
+ matchBuf = (char *) calloc(strlen(buf), sizeof(char));
+ strncpy(matchBuf, buf, place);
+ tmp = matchBuf;
+
+ /* skip any leading white space */
+ while (*tmp && isspace(*tmp))
+ ++tmp;
+
+ /* Free up any memory already allocated */
+ if (matches != NULL) {
+ free(matches);
+ matches = (char **) NULL;
+ }
+
+ /* If the word starts with `~' and there is no slash in the word,
+ * then try completing this word as a username. */
+
+ /* FIXME -- this check is broken!
+ if (*tmp == '~' && !strchr(tmp, '/'))
+ matches = username_tab_completion(tmp, &num_matches); */
+
+ /* Try to match everything in the current working directory that
+ * matches. */
+ if (!matches)
+ matches = cwd_tab_completion(tmp, &num_matches);
+
+ /* Don't leak memory */
+ free(matchBuf);
+
+ /* Did we find exactly one match? */
+ if (matches && num_matches == 1) {
+ buf = nrealloc(buf, strlen(buf) + strlen(matches[0]) - pos + 1);
+ /* write out the matched command */
+ strncpy(buf + pos, matches[0] + pos,
+ strlen(matches[0]) - pos);
+ newplace += strlen(matches[0]) - pos;
+ }
+ } else {
+ /* Ok -- the last char was a TAB. Since they
+ * just hit TAB again, print a list of all the
+ * available choices... */
+ if (matches && num_matches > 0) {
+ int i, col;
+
+ /* Blank the edit window, and print the matches out there */
+ blank_edit();
+ wmove(edit, 0, 0);
+
+ /* Print the list of matches */
+ for (i = 0, col = 0; i < num_matches; i++) {
+ char foo[17];
+ sprintf(foo, "%-14s ", matches[i]);
+ col += waddnstr(edit, foo, strlen(foo));
+ if (col > 60 && matches[i + 1] != NULL) {
+ waddstr(edit, "\n");
+ col = 0;
+ }
+ }
+ wrefresh(edit);
+ num_matches = 0;
+ }
+
+ }
+
+ edit_refresh();
+ return newplace;
+}
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-11-05 11:52-0500\n"
+"POT-Creation-Date: 2000-11-05 12:08-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "Blew away cutbuffer =)\n"
msgstr ""
-#: files.c:120
+#: files.c:122
msgid "read_line: not on first line and prev is NULL"
msgstr ""
-#: files.c:182 files.c:199
+#: files.c:184 files.c:201
#, c-format
msgid "Read %d lines"
msgstr ""
-#: files.c:217 search.c:164
+#: files.c:219 search.c:164
#, c-format
msgid "\"%s\" not found"
msgstr ""
#. We have a new file
-#: files.c:221
+#: files.c:223
msgid "New File"
msgstr ""
-#: files.c:230
+#: files.c:232
#, c-format
msgid "File \"%s\" is a directory"
msgstr ""
-#: files.c:236
+#: files.c:238
msgid "Reading File"
msgstr ""
-#: files.c:249
+#: files.c:251
msgid "File to insert [from ./] "
msgstr ""
-#: files.c:274 files.c:298 files.c:486 nano.c:1347
+#: files.c:276 files.c:300 files.c:488 nano.c:1347
msgid "Cancelled"
msgstr ""
-#: files.c:320 files.c:340 files.c:354 files.c:371 files.c:377
+#: files.c:322 files.c:342 files.c:356 files.c:373 files.c:379
#, c-format
msgid "Could not open file for writing: %s"
msgstr ""
-#: files.c:328
+#: files.c:330
msgid "Could not open file: Path length exceeded."
msgstr ""
-#: files.c:359
+#: files.c:361
#, c-format
msgid "Wrote >%s\n"
msgstr ""
-#: files.c:386
+#: files.c:388
#, c-format
msgid "Could not close %s: %s"
msgstr ""
#. Try a rename??
-#: files.c:407 files.c:418 files.c:423
+#: files.c:409 files.c:420 files.c:425
#, c-format
msgid "Could not open %s for writing: %s"
msgstr ""
-#: files.c:429
+#: files.c:431
#, c-format
msgid "Could not set permissions %o on %s: %s"
msgstr ""
-#: files.c:436
+#: files.c:438
#, c-format
msgid "Wrote %d lines"
msgstr ""
-#: files.c:465
+#: files.c:467
msgid "File Name to write"
msgstr ""
-#: files.c:470
+#: files.c:472
#, c-format
msgid "filename is %s"
msgstr ""
-#: files.c:475
+#: files.c:477
msgid "File exists, OVERWRITE ?"
msgstr ""
msgstr ""
#: global.c:344 global.c:364 global.c:375 global.c:385 global.c:401
-#: global.c:405 global.c:411 winio.c:993
+#: global.c:405 global.c:411 winio.c:1009
msgid "Cancel"
msgstr ""
msgid "actual_x_from_start for xplus=%d returned %d\n"
msgstr ""
-#: winio.c:408
+#: winio.c:424
#, c-format
msgid "input '%c' (%d)\n"
msgstr ""
-#: winio.c:446
+#: winio.c:462
msgid "New Buffer"
msgstr ""
-#: winio.c:449
+#: winio.c:465
msgid " File: ..."
msgstr ""
-#: winio.c:457
+#: winio.c:473
msgid "Modified"
msgstr ""
-#: winio.c:909
+#: winio.c:925
#, c-format
msgid "Moved to (%d, %d) in edit buffer\n"
msgstr ""
-#: winio.c:920
+#: winio.c:936
#, c-format
msgid "current->data = \"%s\"\n"
msgstr ""
-#: winio.c:963
+#: winio.c:979
#, c-format
msgid "I got \"%s\"\n"
msgstr ""
-#: winio.c:988
+#: winio.c:1004
msgid "Yes"
msgstr ""
-#: winio.c:990
+#: winio.c:1006
msgid "All"
msgstr ""
-#: winio.c:992
+#: winio.c:1008
msgid "No"
msgstr ""
-#: winio.c:1129
+#: winio.c:1145
#, c-format
msgid "do_cursorpos: linepct = %f, bytepct = %f\n"
msgstr ""
-#: winio.c:1133
+#: winio.c:1149
msgid "line %d of %d (%.0f%%), character %d of %d (%.0f%%)"
msgstr ""
-#: winio.c:1261
+#: winio.c:1277
msgid "Dumping file buffer to stderr...\n"
msgstr ""
-#: winio.c:1263
+#: winio.c:1279
msgid "Dumping cutbuffer to stderr...\n"
msgstr ""
-#: winio.c:1265
+#: winio.c:1281
msgid "Dumping a buffer to stderr...\n"
msgstr ""
filebot = filebot->next;
totlines++;
}
+
+/*
+ * Routine to see if a text string is matched by a wildcard pattern.
+ * Returns TRUE if the text is matched, or FALSE if it is not matched
+ * or if the pattern is invalid.
+ * * matches zero or more characters
+ * ? matches a single character
+ * [abc] matches 'a', 'b' or 'c'
+ * \c quotes character c
+ * Adapted from code written by Ingo Wilken, and
+ * then taken from sash, Copyright (c) 1999 by David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ * Permission to distribute this code under the GPL has been granted.
+ */
+int check_wildcard_match(const char *text, const char *pattern)
+{
+ const char *retryPat;
+ const char *retryText;
+ int ch;
+ int found;
+ int len;
+
+ retryPat = NULL;
+ retryText = NULL;
+
+ while (*text || *pattern) {
+ ch = *pattern++;
+
+ switch (ch) {
+ case '*':
+ retryPat = pattern;
+ retryText = text;
+ break;
+
+ case '[':
+ found = FALSE;
+
+ while ((ch = *pattern++) != ']') {
+ if (ch == '\\')
+ ch = *pattern++;
+
+ if (ch == '\0')
+ return FALSE;
+
+ if (*text == ch)
+ found = TRUE;
+ }
+ len = strlen(text);
+ if (found == FALSE && len != 0) {
+ return FALSE;
+ }
+ if (found == TRUE) {
+ if (strlen(pattern) == 0 && len == 1) {
+ return TRUE;
+ }
+ if (len != 0) {
+ text++;
+ continue;
+ }
+ }
+
+ /* fall into next case */
+
+ case '?':
+ if (*text++ == '\0')
+ return FALSE;
+
+ break;
+
+ case '\\':
+ ch = *pattern++;
+
+ if (ch == '\0')
+ return FALSE;
+
+ /* fall into next case */
+
+ default:
+ if (*text == ch) {
+ if (*text)
+ text++;
+ break;
+ }
+
+ if (*text) {
+ pattern = retryPat;
+ text = ++retryText;
+ break;
+ }
+
+ return FALSE;
+ }
+
+ if (pattern == NULL)
+ return FALSE;
+ }
+
+ return TRUE;
+}
int nanogetstr(char *buf, char *def, shortcut s[], int slen, int start_x)
{
int kbinput = 0, j = 0, x = 0, xend;
- int x_left = 0, inputlen;
+ int x_left = 0, inputlen, tabbed = 0;
char *inputbuf;
inputbuf = nmalloc(strlen(def) + 1);
}
xend = strlen(buf) + strlen(inputbuf);
+ if (kbinput != '\t')
+ tabbed = 0;
+
switch (kbinput) {
/* Stuff we want to equate with <enter>, ASCII 13 */
case 343:
inputbuf[strlen(inputbuf) - 1] = 0;
}
}
- x--;
+ if (x > strlen(buf))
+ x--;
nanoget_repaint(buf, inputbuf, x);
- x++;
+ break;
+ case NANO_CONTROL_I:
+ tabbed++;
+#ifdef DEBUG
+ fprintf(stderr, "Before call, x = %d\n", x);
+#endif
+ x += input_tab(inputbuf, (x - x_left), tabbed - 1);
+#ifdef DEBUG
+ fprintf(stderr, "After call, x = %d\n", x);
+#endif
+ nanoget_repaint(buf, inputbuf, x);
+ tabbed = 1;
+ break;
case KEY_LEFT:
if (x > strlen(buf))
x--;