1
1

Implemented username tab completion, cleaned up existing tabcomp code, added --disable-tabcomp option

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@313 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
Этот коммит содержится в:
Chris Allegretta 2000-11-24 14:00:16 +00:00
родитель 1866609311
Коммит be77c6119f
9 изменённых файлов: 412 добавлений и 255 удалений

Просмотреть файл

@ -1,4 +1,12 @@
CVS code - CVS code -
- General
- Added configure argument --disable tabcomp. Affects
configure.in, configure, bottom of files.c and write_file, and
winio.c:nanogettsr().
- Username tab completion code, and cleaned up existing tabcomp
code. New functions real_dir_from_tide(), append_slash_if_dir(),
username_tab_completion is more than a stub now =-).
nano 0.9.21 - 11/23/2000 nano 0.9.21 - 11/23/2000
- AUTHORS - AUTHORS
- Added Rocco Corsi. - Added Rocco Corsi.

Просмотреть файл

@ -24,3 +24,5 @@
/* Define to use the slang wrappers for curses instead of native curses */ /* Define to use the slang wrappers for curses instead of native curses */
#undef USE_SLANG #undef USE_SLANG
/* Define to disable the tab completion code Chris worked so hard on! */
#undef DISABLE_TABCOMP

Просмотреть файл

@ -76,6 +76,9 @@
/* Define to use the slang wrappers for curses instead of native curses */ /* Define to use the slang wrappers for curses instead of native curses */
#undef USE_SLANG #undef USE_SLANG
/* Define to disable the tab completion code Chris worked so hard on! */
#undef DISABLE_TABCOMP
/* Define if you have the __argz_count function. */ /* Define if you have the __argz_count function. */
#undef HAVE___ARGZ_COUNT #undef HAVE___ARGZ_COUNT

370
configure поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -21,6 +21,12 @@ AC_ARG_ENABLE(tiny,
AC_DEFINE(NANO_SMALL) tiny_support=yes AC_DEFINE(NANO_SMALL) tiny_support=yes
fi]) fi])
AC_ARG_ENABLE(tabcomp,
[ --disable-tabcomp Disables tab completion code for a smaller binary],
[if test x$enableval != xyes; then
AC_DEFINE(DISABLE_TABCOMP)
fi])
AC_MSG_CHECKING(whether to use slang) AC_MSG_CHECKING(whether to use slang)
CURSES_LIB_NAME="" CURSES_LIB_NAME=""
AC_ARG_WITH(slang, AC_ARG_WITH(slang,

211
files.c
Просмотреть файл

@ -295,6 +295,7 @@ int write_file(char *name, int tmp)
filestruct *fileptr; filestruct *fileptr;
int fd, mask = 0; int fd, mask = 0;
struct stat st; struct stat st;
char *realname = NULL;
if (!strcmp(name, "")) { if (!strcmp(name, "")) {
statusbar(_("Cancelled")); statusbar(_("Cancelled"));
@ -302,17 +303,21 @@ int write_file(char *name, int tmp)
} }
titlebar(); titlebar();
fileptr = fileage; fileptr = fileage;
#ifndef DISABLE_TABCOMP
realname = real_dir_from_tilde(name);
#else
realname = mallocstrcpy(realname, name);
#endif
/* Check to see if the file is a regular file and FOLLOW_SYMLINKS is /* Check to see if the file is a regular file and FOLLOW_SYMLINKS is
set. If so then don't do the delete and recreate code which would set. If so then don't do the delete and recreate code which would
cause unexpected behavior */ cause unexpected behavior */
lstat(name, &st); lstat(realname, &st);
/* Open the file and truncate it. Trust the symlink. */ /* Open the file and truncate it. Trust the symlink. */
if ((ISSET(FOLLOW_SYMLINKS) || !S_ISLNK(st.st_mode)) && !tmp) { if ((ISSET(FOLLOW_SYMLINKS) || !S_ISLNK(st.st_mode)) && !tmp) {
if ((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, if ((fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
S_IWOTH)) == -1) { S_IWOTH)) == -1) {
if (ISSET(TEMP_OPT)) { if (ISSET(TEMP_OPT)) {
@ -321,18 +326,19 @@ int write_file(char *name, int tmp)
} }
statusbar(_("Could not open file for writing: %s"), statusbar(_("Could not open file for writing: %s"),
strerror(errno)); strerror(errno));
free(realname);
return -1; return -1;
} }
} }
/* Don't follow symlink. Create new file. */ /* Don't follow symlink. Create new file. */
else { else {
if (strlen(name) > (PATH_MAX - 7)) { if (strlen(realname) > (PATH_MAX - 7)) {
statusbar(_("Could not open file: Path length exceeded.")); statusbar(_("Could not open file: Path length exceeded."));
return -1; return -1;
} }
memset(buf, 0x00, PATH_MAX + 1); memset(buf, 0x00, PATH_MAX + 1);
strcat(buf, name); strcat(buf, realname);
strcat(buf, ".XXXXXX"); strcat(buf, ".XXXXXX");
if ((fd = mkstemp(buf)) == -1) { if ((fd = mkstemp(buf)) == -1) {
if (ISSET(TEMP_OPT)) { if (ISSET(TEMP_OPT)) {
@ -385,13 +391,13 @@ int write_file(char *name, int tmp)
if (close(fd) == -1) { if (close(fd) == -1) {
statusbar(_("Could not close %s: %s"), name, strerror(errno)); statusbar(_("Could not close %s: %s"), realname, strerror(errno));
unlink(buf); unlink(buf);
return -1; return -1;
} }
if (!ISSET(FOLLOW_SYMLINKS) || tmp) { if (!ISSET(FOLLOW_SYMLINKS) || tmp) {
if (stat(name, &st) == -1) { if (stat(realname, &st) == -1) {
/* Use default umask as file permisions if file is a new file. */ /* Use default umask as file permisions if file is a new file. */
mask = umask(0); mask = umask(0);
umask(mask); umask(mask);
@ -404,37 +410,37 @@ int write_file(char *name, int tmp)
} else { } else {
/* Use permissions from file we are overwriting. */ /* Use permissions from file we are overwriting. */
mask = st.st_mode; mask = st.st_mode;
if (unlink(name) == -1) { if (unlink(realname) == -1) {
if (errno != ENOENT) { if (errno != ENOENT) {
statusbar(_("Could not open %s for writing: %s"), statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno)); realname, strerror(errno));
unlink(buf); unlink(buf);
return -1; return -1;
} }
} }
} }
if (link(buf, name) != -1) if (link(buf, realname) != -1)
unlink(buf); unlink(buf);
else if (errno != EPERM) { else if (errno != EPERM) {
statusbar(_("Could not open %s for writing: %s"), statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno)); name, strerror(errno));
unlink(buf); unlink(buf);
return -1; return -1;
} else if (rename(buf, name) == -1) { /* Try a rename?? */ } else if (rename(buf, realname) == -1) { /* Try a rename?? */
statusbar(_("Could not open %s for writing: %s"), statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno)); realname, strerror(errno));
unlink(buf); unlink(buf);
return -1; return -1;
} }
if (chmod(name, mask) == -1) { if (chmod(realname, mask) == -1) {
statusbar(_("Could not set permissions %o on %s: %s"), statusbar(_("Could not set permissions %o on %s: %s"),
mask, name, strerror(errno)); mask, realname, strerror(errno));
} }
} }
if (!tmp) { if (!tmp) {
strncpy(filename, name, 132); strncpy(filename, realname, 132);
statusbar(_("Wrote %d lines"), lineswritten); statusbar(_("Wrote %d lines"), lineswritten);
} }
UNSET(MODIFIED); UNSET(MODIFIED);
@ -497,6 +503,58 @@ int do_writeout_void(void)
return do_writeout(0); return do_writeout(0);
} }
#ifndef DISABLE_TABCOMP
static char **homedirs;
/* Return a malloc()ed string containing the actual directory, used
* to convert ~user and ~/ notation...
*/
char *real_dir_from_tilde (char *buf)
{
char *dirtmp = NULL, *tmp;
if (buf[0] == '~') {
if (buf[1] == '/') {
if (getenv("HOME") != NULL) {
dirtmp = nmalloc(strlen(buf) + 2 + strlen(getenv("HOME")));
sprintf(dirtmp, "%s/%s", getenv("HOME"), &buf[2]);
}
}
else if (buf[1] != 0) {
dirtmp = nmalloc(strlen(buf) + 2 + strlen(homedirs[0]));
for (tmp = &buf[2]; *tmp != '/' && *tmp != 0; tmp++);
sprintf(dirtmp, "%s%s", homedirs[0], tmp);
}
}
else
dirtmp = mallocstrcpy(dirtmp, buf);
return dirtmp;
}
/* Tack a slash onto the string we're completing if it's a directory */
void append_slash_if_dir(char *buf, int *lastWasTab, int *place)
{
char *dirptr;
struct stat fileinfo;
dirptr = real_dir_from_tilde(buf);
if (stat(dirptr, &fileinfo) == -1)
;
else if (S_ISDIR(fileinfo.st_mode)) {
strncat(buf, "/", 1);
*place += 1;
/* now we start over again with # of tabs so far */
*lastWasTab = 0;
}
if (dirptr != buf)
free(dirptr);
}
/* /*
* These functions (username_tab_completion, cwd_tab_completion, and * These functions (username_tab_completion, cwd_tab_completion, and
@ -517,24 +575,90 @@ int do_writeout_void(void)
* This code may safely be consumed by a BSD or GPL license. * This code may safely be consumed by a BSD or GPL license.
*/ */
#if 0
char **username_tab_completion(char *buf, int *num_matches) char **username_tab_completion(char *buf, int *num_matches)
{ {
char **matches = (char **) NULL; char **matches = (char **) NULL, *line = NULL, *lineptr;
*num_matches = 0; char *matchline = NULL, *matchdir = NULL;
int fd, i = 0, status = 1;
char byte[1];
if((fd = open("/etc/passwd", O_RDONLY)) == -1) {
return NULL;
}
if (homedirs != NULL) {
for (i = 0; i < *num_matches; i++)
free(homedirs[i]);
free(homedirs);
homedirs = (char **) NULL;
*num_matches = 0;
}
matches = nmalloc(BUFSIZ);
homedirs = nmalloc(BUFSIZ);
strcat(buf, "*");
do {
i = 0;
line = nmalloc(1);
while ((status = read(fd, byte, 1)) != 0 && byte[0] != '\n') {
line[i] = byte[0];
i++;
line = nrealloc(line, i+1);
}
if (i == 0)
break;
line[i] = 0;
lineptr = strtok(line, ":");
if (check_wildcard_match(line, &buf[1]) == TRUE) {
if (*num_matches == BUFSIZ)
break;
/* Cool, found a match. Add it to the list
* This makes a lot more sense to me (Chris) this way...
*/
matchline = nmalloc(strlen(line) + 2);
sprintf(matchline, "~%s", line);
for (i = 0; i <= 4 && lineptr != NULL; i++)
lineptr = strtok(NULL, ":");
if (lineptr == NULL)
break;
matchdir = mallocstrcpy(matchdir, lineptr);
homedirs[*num_matches] = matchdir;
matches[*num_matches] = matchline;
++*num_matches;
/* If there's no more room, bail out */
if (*num_matches == BUFSIZ)
break;
}
free(line);
} while (status != 0);
close(fd);
return matches;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "\nin username_tab_completion\n"); fprintf(stderr, "\nin username_tab_completion\n");
#endif #endif
return (matches); return (matches);
} }
#endif
/* This was originally called exe_n_cwd_tab_completion, but we're not /* This was originally called exe_n_cwd_tab_completion, but we're not
worried about executables, only filenames :> */ worried about executables, only filenames :> */
char **cwd_tab_completion(char *buf, int *num_matches) char **cwd_tab_completion(char *buf, int *num_matches)
{ {
char *dirName, *tmp = NULL, *tmp2 = NULL; char *dirName, *dirtmp = NULL, *tmp = NULL, *tmp2 = NULL;
char **matches = (char **) NULL; char **matches = (char **) NULL;
DIR *dir; DIR *dir;
struct dirent *next; struct dirent *next;
@ -569,6 +693,17 @@ char **cwd_tab_completion(char *buf, int *num_matches)
fprintf(stderr, "\ntmp = %s\n", tmp); fprintf(stderr, "\ntmp = %s\n", tmp);
#endif #endif
dirtmp = real_dir_from_tilde(dirName);
free(dirName);
dirName = dirtmp;
#ifdef DEBUG
fprintf(stderr, "\nDir = %s\n", dirName);
fprintf(stderr, "\nbuf = %s\n", buf);
fprintf(stderr, "\ntmp = %s\n", tmp);
#endif
dir = opendir(dirName); dir = opendir(dirName);
if (!dir) { if (!dir) {
/* Don't print an error, just shut up and return */ /* Don't print an error, just shut up and return */
@ -618,7 +753,6 @@ char *input_tab(char *buf, int place, int *lastWasTab, int *newplace)
int pos = place, i = 0, col = 0, editline = 0; int pos = place, i = 0, col = 0, editline = 0;
int longestname = 0; int longestname = 0;
char *foo; char *foo;
struct stat fileinfo;
if (*lastWasTab == FALSE) { if (*lastWasTab == FALSE) {
char *tmp, *copyto, *matchBuf; char *tmp, *copyto, *matchBuf;
@ -648,9 +782,9 @@ char *input_tab(char *buf, int place, int *lastWasTab, int *newplace)
/* If the word starts with `~' and there is no slash in the word, /* If the word starts with `~' and there is no slash in the word,
* then try completing this word as a username. */ * then try completing this word as a username. */
/* FIXME -- this check is broken! /* FIXME -- this check is broken! */
if (*tmp == '~' && !strchr(tmp, '/')) if (*tmp == '~' && !strchr(tmp, '/'))
matches = username_tab_completion(tmp, &num_matches); */ matches = username_tab_completion(tmp, &num_matches);
/* Try to match everything in the current working directory that /* Try to match everything in the current working directory that
* matches. */ * matches. */
@ -680,21 +814,8 @@ char *input_tab(char *buf, int place, int *lastWasTab, int *newplace)
} else } else
tmp = buf; tmp = buf;
if (!strcmp(tmp, matches[0])) { if (!strcmp(tmp, matches[0]))
append_slash_if_dir(buf, lastWasTab, newplace);
/* Is it a directory? */
if (stat(buf, &fileinfo) == -1)
break;
else if (S_ISDIR(fileinfo.st_mode)) {
/* Tack on a slash */
strncat(buf, "/", 1);
*newplace += 1;
/* now we start over with 0 tabs so far */
*lastWasTab = 0;
}
break;
}
copyto = tmp; copyto = tmp;
for (pos = 0; *tmp == matches[0][pos] && for (pos = 0; *tmp == matches[0][pos] &&
@ -705,14 +826,9 @@ char *input_tab(char *buf, int place, int *lastWasTab, int *newplace)
strncpy(copyto, matches[0], strlen(matches[0]) + 1); strncpy(copyto, matches[0], strlen(matches[0]) + 1);
*newplace += strlen(matches[0]) - pos; *newplace += strlen(matches[0]) - pos;
if (stat(buf, &fileinfo) == -1) /* Is it a directory? */
break; append_slash_if_dir(buf, lastWasTab, newplace);
else if (S_ISDIR(fileinfo.st_mode)) {
strncat(buf, "/", 1);
*newplace += 1;
/* now we start over again with # of tabs so far */
*lastWasTab = 0;
}
break; break;
default: default:
/* Check to see if all matches share a beginning, and if so /* Check to see if all matches share a beginning, and if so
@ -815,3 +931,4 @@ char *input_tab(char *buf, int place, int *lastWasTab, int *newplace)
curs_set(1); curs_set(1);
return buf; return buf;
} }
#endif

Просмотреть файл

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2000-11-22 20:20-0500\n" "POT-Creation-Date: 2000-11-24 08:45-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -55,59 +55,59 @@ msgstr ""
msgid "File to insert [from ./] " msgid "File to insert [from ./] "
msgstr "" msgstr ""
#: files.c:276 files.c:300 files.c:488 nano.c:1355 #: files.c:276 files.c:301 files.c:494 nano.c:1355
msgid "Cancelled" msgid "Cancelled"
msgstr "" msgstr ""
#: files.c:322 files.c:342 files.c:356 files.c:373 files.c:379 #: files.c:327 files.c:348 files.c:362 files.c:379 files.c:385
#, c-format #, c-format
msgid "Could not open file for writing: %s" msgid "Could not open file for writing: %s"
msgstr "" msgstr ""
#: files.c:330 #: files.c:336
msgid "Could not open file: Path length exceeded." msgid "Could not open file: Path length exceeded."
msgstr "" msgstr ""
#: files.c:361 #: files.c:367
#, c-format #, c-format
msgid "Wrote >%s\n" msgid "Wrote >%s\n"
msgstr "" msgstr ""
#: files.c:388 #: files.c:394
#, c-format #, c-format
msgid "Could not close %s: %s" msgid "Could not close %s: %s"
msgstr "" msgstr ""
#. Try a rename?? #. Try a rename??
#: files.c:409 files.c:420 files.c:425 #: files.c:415 files.c:426 files.c:431
#, c-format #, c-format
msgid "Could not open %s for writing: %s" msgid "Could not open %s for writing: %s"
msgstr "" msgstr ""
#: files.c:431 #: files.c:437
#, c-format #, c-format
msgid "Could not set permissions %o on %s: %s" msgid "Could not set permissions %o on %s: %s"
msgstr "" msgstr ""
#: files.c:438 #: files.c:444
#, c-format #, c-format
msgid "Wrote %d lines" msgid "Wrote %d lines"
msgstr "" msgstr ""
#: files.c:467 #: files.c:473
msgid "File Name to write" msgid "File Name to write"
msgstr "" msgstr ""
#: files.c:472 #: files.c:478
#, c-format #, c-format
msgid "filename is %s" msgid "filename is %s"
msgstr "" msgstr ""
#: files.c:477 #: files.c:483
msgid "File exists, OVERWRITE ?" msgid "File exists, OVERWRITE ?"
msgstr "" msgstr ""
#: files.c:801 #: files.c:917
msgid "(more)" msgid "(more)"
msgstr "" msgstr ""
@ -384,7 +384,7 @@ msgid "Case Sens"
msgstr "" msgstr ""
#: global.c:344 global.c:364 global.c:375 global.c:385 global.c:401 #: global.c:344 global.c:364 global.c:375 global.c:385 global.c:401
#: global.c:405 global.c:411 winio.c:1020 #: global.c:405 global.c:411 winio.c:1025
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
@ -817,67 +817,67 @@ msgstr ""
msgid "actual_x_from_start for xplus=%d returned %d\n" msgid "actual_x_from_start for xplus=%d returned %d\n"
msgstr "" msgstr ""
#: winio.c:433 #: winio.c:438
#, c-format #, c-format
msgid "input '%c' (%d)\n" msgid "input '%c' (%d)\n"
msgstr "" msgstr ""
#: winio.c:471 #: winio.c:476
msgid "New Buffer" msgid "New Buffer"
msgstr "" msgstr ""
#: winio.c:474 #: winio.c:479
msgid " File: ..." msgid " File: ..."
msgstr "" msgstr ""
#: winio.c:482 #: winio.c:487
msgid "Modified" msgid "Modified"
msgstr "" msgstr ""
#: winio.c:934 #: winio.c:939
#, c-format #, c-format
msgid "Moved to (%d, %d) in edit buffer\n" msgid "Moved to (%d, %d) in edit buffer\n"
msgstr "" msgstr ""
#: winio.c:945 #: winio.c:950
#, c-format #, c-format
msgid "current->data = \"%s\"\n" msgid "current->data = \"%s\"\n"
msgstr "" msgstr ""
#: winio.c:990 #: winio.c:995
#, c-format #, c-format
msgid "I got \"%s\"\n" msgid "I got \"%s\"\n"
msgstr "" msgstr ""
#: winio.c:1015 #: winio.c:1020
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
#: winio.c:1017 #: winio.c:1022
msgid "All" msgid "All"
msgstr "" msgstr ""
#: winio.c:1019 #: winio.c:1024
msgid "No" msgid "No"
msgstr "" msgstr ""
#: winio.c:1156 #: winio.c:1161
#, c-format #, c-format
msgid "do_cursorpos: linepct = %f, bytepct = %f\n" msgid "do_cursorpos: linepct = %f, bytepct = %f\n"
msgstr "" msgstr ""
#: winio.c:1160 #: winio.c:1165
msgid "line %d of %d (%.0f%%), character %d of %d (%.0f%%)" msgid "line %d of %d (%.0f%%), character %d of %d (%.0f%%)"
msgstr "" msgstr ""
#: winio.c:1288 #: winio.c:1293
msgid "Dumping file buffer to stderr...\n" msgid "Dumping file buffer to stderr...\n"
msgstr "" msgstr ""
#: winio.c:1290 #: winio.c:1295
msgid "Dumping cutbuffer to stderr...\n" msgid "Dumping cutbuffer to stderr...\n"
msgstr "" msgstr ""
#: winio.c:1292 #: winio.c:1297
msgid "Dumping a buffer to stderr...\n" msgid "Dumping a buffer to stderr...\n"
msgstr "" msgstr ""

Просмотреть файл

@ -88,7 +88,9 @@ int do_down(void);
int do_left(void); int do_left(void);
int do_right(void); int do_right(void);
int check_wildcard_match(const char *text, const char *pattern); int check_wildcard_match(const char *text, const char *pattern);
char *input_tab(char *buf, int place, int *lastWasTab, int *newplace); char *input_tab(char *buf, int place, int *lastWasTab, int *newplace);
char *real_dir_from_tilde(char *buf);
void shortcut_init(void); void shortcut_init(void);
void lowercase(char *src); void lowercase(char *src);

Просмотреть файл

@ -247,8 +247,11 @@ int nanogetstr(int allowtabs, char *buf, char *def, shortcut s[], int slen,
int start_x) int start_x)
{ {
int kbinput = 0, j = 0, x = 0, xend; int kbinput = 0, j = 0, x = 0, xend;
int x_left = 0, inputlen, tabbed = 0, shift = 0; int x_left = 0, inputlen, tabbed = 0;
char *inputbuf; char *inputbuf;
#ifndef DISABLE_TABCOMP
int shift = 0;
#endif
inputbuf = nmalloc(strlen(def) + 1); inputbuf = nmalloc(strlen(def) + 1);
inputbuf[0] = 0; inputbuf[0] = 0;
@ -340,6 +343,7 @@ int nanogetstr(int allowtabs, char *buf, char *def, shortcut s[], int slen,
x--; x--;
nanoget_repaint(buf, inputbuf, x); nanoget_repaint(buf, inputbuf, x);
break; break;
#ifndef DISABLE_TABCOMP
case NANO_CONTROL_I: case NANO_CONTROL_I:
if (allowtabs) { if (allowtabs) {
shift = 0; shift = 0;
@ -349,6 +353,7 @@ int nanogetstr(int allowtabs, char *buf, char *def, shortcut s[], int slen,
nanoget_repaint(buf, inputbuf, x); nanoget_repaint(buf, inputbuf, x);
} }
break; break;
#endif
case KEY_LEFT: case KEY_LEFT:
if (x > strlen(buf)) if (x > strlen(buf))
x--; x--;