2000-08-06 21:13:45 +00:00
|
|
|
|
/* $Id$ */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
/**************************************************************************
|
|
|
|
|
* winio.c *
|
|
|
|
|
* *
|
2003-01-15 19:33:27 +00:00
|
|
|
|
* Copyright (C) 1999-2003 Chris Allegretta *
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
2001-10-24 11:33:54 +00:00
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option) *
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* any later version. *
|
|
|
|
|
* *
|
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
|
* *
|
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
|
* along with this program; if not, write to the Free Software *
|
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
|
|
|
|
* *
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
2002-09-13 18:14:04 +00:00
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <string.h>
|
2000-07-07 05:13:09 +00:00
|
|
|
|
#include <stdlib.h>
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#include <unistd.h>
|
2002-06-13 00:40:19 +00:00
|
|
|
|
#include <ctype.h>
|
2002-05-12 19:52:15 +00:00
|
|
|
|
#include <assert.h>
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#include "proto.h"
|
|
|
|
|
#include "nano.h"
|
|
|
|
|
|
|
|
|
|
static int statblank = 0; /* Number of keystrokes left after
|
2001-05-05 17:45:54 +00:00
|
|
|
|
we call statusbar(), before we
|
2000-06-06 05:53:49 +00:00
|
|
|
|
actually blank the statusbar */
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
int do_first_line(void)
|
|
|
|
|
{
|
|
|
|
|
current = fileage;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
current_x = 0;
|
2000-07-29 04:33:38 +00:00
|
|
|
|
edit_update(current, CENTER);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int do_last_line(void)
|
|
|
|
|
{
|
|
|
|
|
current = filebot;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
current_x = 0;
|
2000-07-29 04:33:38 +00:00
|
|
|
|
edit_update(current, CENTER);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Return the placewewant associated with current_x. That is, xplustabs
|
|
|
|
|
* is the zero-based column position of the cursor. Value is no smaller
|
|
|
|
|
* than current_x. */
|
|
|
|
|
size_t xplustabs(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return strnlenpt(current->data, current_x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Return what current_x should be, given xplustabs() for the line. */
|
|
|
|
|
size_t actual_x(const filestruct *fileptr, size_t xplus)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t i = 0;
|
|
|
|
|
/* the position in fileptr->data, returned */
|
|
|
|
|
size_t length = 0;
|
|
|
|
|
/* the screen display width to data[i] */
|
|
|
|
|
char *c;
|
|
|
|
|
/* fileptr->data + i */
|
|
|
|
|
|
|
|
|
|
assert(fileptr != NULL && fileptr->data != NULL);
|
|
|
|
|
|
|
|
|
|
for (c = fileptr->data; length < xplus && *c != '\0'; i++, c++) {
|
|
|
|
|
if (*c == '\t')
|
|
|
|
|
length += tabsize - length % tabsize;
|
2002-07-20 13:57:41 +00:00
|
|
|
|
else if (is_cntrl_char((int)*c))
|
2002-07-19 01:08:59 +00:00
|
|
|
|
length += 2;
|
|
|
|
|
else
|
|
|
|
|
length++;
|
|
|
|
|
}
|
|
|
|
|
assert(length == strnlenpt(fileptr->data, i));
|
|
|
|
|
assert(i <= strlen(fileptr->data));
|
2002-06-13 00:40:19 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (length > xplus)
|
|
|
|
|
i--;
|
2002-06-13 00:40:19 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#ifdef DEBUG
|
2002-07-19 01:08:59 +00:00
|
|
|
|
fprintf(stderr, _("actual_x for xplus=%d returns %d\n"), xplus, i);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#endif
|
2002-05-11 03:04:44 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return i;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* A strlen with tabs factored in, similar to xplustabs(). */
|
|
|
|
|
size_t strnlenpt(const char *buf, size_t size)
|
2000-06-06 23:04:06 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t length = 0;
|
|
|
|
|
|
|
|
|
|
if (buf != NULL)
|
|
|
|
|
for (; *buf != '\0' && size != 0; size--, buf++) {
|
|
|
|
|
if (*buf == '\t')
|
|
|
|
|
length += tabsize - (length % tabsize);
|
2002-07-20 13:57:41 +00:00
|
|
|
|
else if (is_cntrl_char((int)*buf))
|
2002-07-19 01:08:59 +00:00
|
|
|
|
length += 2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
else
|
2002-07-19 01:08:59 +00:00
|
|
|
|
length++;
|
|
|
|
|
}
|
|
|
|
|
return length;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t strlenpt(const char *buf)
|
2002-03-05 19:55:55 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return strnlenpt(buf, -1);
|
2002-03-05 19:55:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void blank_bottombars(void)
|
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (!no_help()) {
|
|
|
|
|
mvwaddstr(bottomwin, 1, 0, hblank);
|
|
|
|
|
mvwaddstr(bottomwin, 2, 0, hblank);
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
void blank_bottomwin(void)
|
|
|
|
|
{
|
|
|
|
|
if (ISSET(NO_HELP))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mvwaddstr(bottomwin, 1, 0, hblank);
|
|
|
|
|
mvwaddstr(bottomwin, 2, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void blank_edit(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i <= editwinrows - 1; i++)
|
|
|
|
|
mvwaddstr(edit, i, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void blank_statusbar(void)
|
|
|
|
|
{
|
|
|
|
|
mvwaddstr(bottomwin, 0, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blank_statusbar_refresh(void)
|
|
|
|
|
{
|
|
|
|
|
blank_statusbar();
|
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void check_statblank(void)
|
|
|
|
|
{
|
|
|
|
|
if (statblank > 1)
|
|
|
|
|
statblank--;
|
|
|
|
|
else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
|
|
|
|
|
statblank--;
|
|
|
|
|
blank_statusbar_refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
/* Repaint the statusbar when getting a character in nanogetstr(). buf
|
2002-07-19 01:08:59 +00:00
|
|
|
|
* should be no longer than COLS - 4.
|
|
|
|
|
*
|
2003-01-13 01:35:15 +00:00
|
|
|
|
* Note that we must turn on A_REVERSE here, since do_help() turns it
|
2002-07-19 01:08:59 +00:00
|
|
|
|
* off! */
|
2002-08-21 16:10:37 +00:00
|
|
|
|
void nanoget_repaint(const char *buf, const char *inputbuf, int x)
|
2000-10-24 22:25:36 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
int len = strlen(buf) + 2;
|
2000-11-02 15:30:24 +00:00
|
|
|
|
int wid = COLS - len;
|
2000-11-02 04:40:39 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
assert(wid >= 2);
|
|
|
|
|
assert(0 <= x && x <= strlen(inputbuf));
|
|
|
|
|
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
2000-11-02 15:30:24 +00:00
|
|
|
|
blank_statusbar();
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddstr(bottomwin, 0, 0, buf);
|
|
|
|
|
waddch(bottomwin, ':');
|
|
|
|
|
waddch(bottomwin, x < wid ? ' ' : '$');
|
|
|
|
|
waddnstr(bottomwin, &inputbuf[wid * (x / wid)], wid);
|
|
|
|
|
wmove(bottomwin, 0, (x % wid) + len);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2000-10-24 22:25:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Get the input from the kb; this should only be called from
|
|
|
|
|
* statusq(). */
|
2002-08-21 16:10:37 +00:00
|
|
|
|
int nanogetstr(int allowtabs, const char *buf, const char *def,
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
historyheadtype *history_list,
|
|
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
|
const shortcut *s
|
2001-01-11 05:30:31 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2002-09-06 20:35:28 +00:00
|
|
|
|
, int *list
|
2000-11-24 14:00:16 +00:00
|
|
|
|
#endif
|
2003-01-26 21:01:16 +00:00
|
|
|
|
, int resetpos)
|
2002-07-19 01:08:59 +00:00
|
|
|
|
{
|
|
|
|
|
int kbinput;
|
2003-01-16 22:16:38 +00:00
|
|
|
|
static int x = -1;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* the cursor position in 'answer' */
|
|
|
|
|
int xend;
|
|
|
|
|
/* length of 'answer', the status bar text */
|
|
|
|
|
int tabbed = 0;
|
|
|
|
|
/* used by input_tab() */
|
|
|
|
|
const shortcut *t;
|
|
|
|
|
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* for history */
|
|
|
|
|
char *history = NULL;
|
2003-01-09 05:29:58 +00:00
|
|
|
|
char *currentbuf = NULL;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
char *complete = NULL;
|
2003-01-09 05:29:58 +00:00
|
|
|
|
int last_kbinput = 0, ret2cb = 0;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
|
xend = strlen(def);
|
2003-01-16 22:16:38 +00:00
|
|
|
|
|
|
|
|
|
/* Only put x at the end of the string if it's uninitialized or if
|
|
|
|
|
it would be past the end of the string as it is. Otherwise,
|
|
|
|
|
leave it alone. This is so the cursor position stays at the same
|
|
|
|
|
place if a prompt-changing toggle is pressed. */
|
2003-01-26 21:01:16 +00:00
|
|
|
|
if (x == -1 || x > xend || resetpos)
|
2003-01-16 22:16:38 +00:00
|
|
|
|
x = xend;
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
answer = (char *)nrealloc(answer, xend + 1);
|
|
|
|
|
if (xend > 0)
|
|
|
|
|
strcpy(answer, def);
|
|
|
|
|
else
|
|
|
|
|
answer[0] = '\0';
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
#if !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION))
|
2001-04-12 03:01:53 +00:00
|
|
|
|
currshortcut = s;
|
2001-05-21 12:56:25 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
/* Get the input! */
|
2000-11-02 04:40:39 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
nanoget_repaint(buf, answer, x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Make sure any editor screen updates are displayed before getting
|
|
|
|
|
input */
|
2000-11-14 17:47:58 +00:00
|
|
|
|
wrefresh(edit);
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
while ((kbinput = wgetch(bottomwin)) != 13) {
|
2002-02-15 19:17:02 +00:00
|
|
|
|
for (t = s; t != NULL; t = t->next) {
|
2001-04-12 03:01:53 +00:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput, kbinput);
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-02-15 19:17:02 +00:00
|
|
|
|
if (kbinput == t->val && kbinput < 32) {
|
2000-11-16 06:01:10 +00:00
|
|
|
|
|
2001-10-22 03:15:31 +00:00
|
|
|
|
#ifndef DISABLE_HELP
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Have to do this here, it would be too late to do it
|
|
|
|
|
in statusq() */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
|
2001-10-22 03:15:31 +00:00
|
|
|
|
do_help();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-01-17 21:07:38 +00:00
|
|
|
|
|
|
|
|
|
/* We canceled putting in an answer; reset x */
|
|
|
|
|
if (kbinput == NANO_CANCEL_KEY)
|
|
|
|
|
x = -1;
|
|
|
|
|
|
2002-02-15 19:17:02 +00:00
|
|
|
|
return t->val;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
assert(0 <= x && x <= xend && xend == strlen(answer));
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2000-11-05 17:54:41 +00:00
|
|
|
|
if (kbinput != '\t')
|
|
|
|
|
tabbed = 0;
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput) {
|
2001-04-12 03:01:53 +00:00
|
|
|
|
|
2002-01-19 01:59:37 +00:00
|
|
|
|
/* Stuff we want to equate with <enter>, ASCII 13 */
|
2000-10-26 01:44:42 +00:00
|
|
|
|
case 343:
|
2000-10-18 19:35:59 +00:00
|
|
|
|
ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
|
|
|
|
|
break;
|
2002-01-19 01:59:37 +00:00
|
|
|
|
/* Stuff we want to ignore */
|
2000-11-16 19:55:30 +00:00
|
|
|
|
#ifdef PDCURSES
|
|
|
|
|
case 541:
|
|
|
|
|
case 542:
|
2002-01-19 01:59:37 +00:00
|
|
|
|
case 543: /* Right ctrl again */
|
2000-11-16 19:55:30 +00:00
|
|
|
|
case 544:
|
2002-01-19 01:59:37 +00:00
|
|
|
|
case 545: /* Right alt again */
|
2001-04-12 03:01:53 +00:00
|
|
|
|
break;
|
|
|
|
|
#endif
|
2002-12-22 16:30:00 +00:00
|
|
|
|
#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
|
2001-04-12 03:01:53 +00:00
|
|
|
|
case KEY_MOUSE:
|
|
|
|
|
do_mouse();
|
|
|
|
|
break;
|
2000-11-16 19:55:30 +00:00
|
|
|
|
#endif
|
2001-06-14 02:54:22 +00:00
|
|
|
|
case NANO_HOME_KEY:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case KEY_HOME:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
case NANO_END_KEY:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case KEY_END:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
|
|
|
|
case KEY_RIGHT:
|
2001-03-21 15:07:20 +00:00
|
|
|
|
case NANO_FORWARD_KEY:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (x < xend)
|
|
|
|
|
x++;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_CONTROL_D:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x < xend) {
|
|
|
|
|
memmove(answer + x, answer + x + 1, xend - x);
|
|
|
|
|
xend--;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NANO_CONTROL_K:
|
|
|
|
|
case NANO_CONTROL_U:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
null_at(&answer, 0);
|
|
|
|
|
xend = 0;
|
|
|
|
|
x = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
|
|
|
|
case KEY_BACKSPACE:
|
|
|
|
|
case 127:
|
|
|
|
|
case NANO_CONTROL_H:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x > 0) {
|
|
|
|
|
memmove(answer + x - 1, answer + x, xend - x + 1);
|
2000-11-05 17:54:41 +00:00
|
|
|
|
x--;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
xend--;
|
|
|
|
|
}
|
2000-11-05 17:54:41 +00:00
|
|
|
|
break;
|
|
|
|
|
case NANO_CONTROL_I:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* tab history completion */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if (history_list != NULL) {
|
|
|
|
|
if (!complete || last_kbinput != NANO_CONTROL_I) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
history_list->current = (historytype *)history_list;
|
|
|
|
|
history_list->len = strlen(answer);
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if (history_list->len > 0) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
complete = get_history_completion(history_list, answer);
|
|
|
|
|
xend = strlen(complete);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, complete);
|
|
|
|
|
}
|
2000-11-06 02:57:22 +00:00
|
|
|
|
}
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2003-01-17 05:04:17 +00:00
|
|
|
|
else
|
|
|
|
|
#endif
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2003-01-17 05:04:17 +00:00
|
|
|
|
if (allowtabs) {
|
|
|
|
|
int shift = 0;
|
|
|
|
|
|
|
|
|
|
answer = input_tab(answer, x, &tabbed, &shift, list);
|
|
|
|
|
xend = strlen(answer);
|
|
|
|
|
x += shift;
|
|
|
|
|
if (x > xend)
|
|
|
|
|
x = xend;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case KEY_LEFT:
|
2001-03-21 15:07:20 +00:00
|
|
|
|
case NANO_BACK_KEY:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x > 0)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
x--;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_UP:
|
2003-01-13 01:35:15 +00:00
|
|
|
|
case NANO_UP_KEY:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-16 22:16:38 +00:00
|
|
|
|
if (history_list != NULL) {
|
2003-01-09 05:29:58 +00:00
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
/* If there's no previous temp holder, or if we already
|
|
|
|
|
arrowed back down to it and (possibly edited it),
|
|
|
|
|
update the holder */
|
2003-01-09 05:29:58 +00:00
|
|
|
|
if (currentbuf == NULL || (ret2cb == 1 && strcmp(currentbuf, answer))) {
|
|
|
|
|
currentbuf = mallocstrcpy(currentbuf, answer);
|
|
|
|
|
ret2cb = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-05 20:41:21 +00:00
|
|
|
|
/* get older search from the history list */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if ((history = get_history_older(history_list)) != NULL) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, history);
|
|
|
|
|
xend = strlen(history);
|
|
|
|
|
} else {
|
|
|
|
|
answer = mallocstrcpy(answer, "");
|
|
|
|
|
xend = 0;
|
|
|
|
|
}
|
|
|
|
|
x = xend;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-01-09 23:43:12 +00:00
|
|
|
|
break;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case KEY_DOWN:
|
2003-01-13 01:35:15 +00:00
|
|
|
|
case NANO_DOWN_KEY:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-16 22:16:38 +00:00
|
|
|
|
if (history_list != NULL) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
/* get newer search from the history list */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if ((history = get_history_newer(history_list)) != NULL) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, history);
|
|
|
|
|
xend = strlen(history);
|
2003-01-09 05:29:58 +00:00
|
|
|
|
|
2003-01-16 22:16:38 +00:00
|
|
|
|
/* else if we ran out of history, regurgitate the temporary
|
|
|
|
|
buffer and blow away currentbuf */
|
2003-01-09 05:29:58 +00:00
|
|
|
|
} else if (currentbuf != NULL) {
|
|
|
|
|
answer = mallocstrcpy(answer, currentbuf);
|
2003-01-16 22:16:38 +00:00
|
|
|
|
free(currentbuf);
|
|
|
|
|
currentbuf = NULL;
|
|
|
|
|
xend = strlen(answer);
|
2003-01-09 05:29:58 +00:00
|
|
|
|
ret2cb = 1;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
} else {
|
|
|
|
|
answer = mallocstrcpy(answer, "");
|
|
|
|
|
xend = 0;
|
|
|
|
|
}
|
|
|
|
|
x = xend;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case KEY_DC:
|
|
|
|
|
goto do_deletekey;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case 27:
|
|
|
|
|
switch (kbinput = wgetch(edit)) {
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case 'O':
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput = wgetch(edit)) {
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case 'F':
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case 'H':
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case '[':
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput = wgetch(edit)) {
|
|
|
|
|
case 'C':
|
|
|
|
|
if (x < xend)
|
|
|
|
|
x++;
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x > 0)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
x--;
|
|
|
|
|
break;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
case '1':
|
|
|
|
|
case '7':
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = 0;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
goto skip_tilde;
|
|
|
|
|
case '3':
|
|
|
|
|
do_deletekey:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x < xend) {
|
|
|
|
|
memmove(answer + x, answer + x + 1, xend - x);
|
|
|
|
|
xend--;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2001-09-23 01:18:03 +00:00
|
|
|
|
goto skip_tilde;
|
|
|
|
|
case '4':
|
|
|
|
|
case '8':
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2001-09-23 01:18:03 +00:00
|
|
|
|
skip_tilde:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
nodelay(edit, TRUE);
|
|
|
|
|
kbinput = wgetch(edit);
|
2001-09-23 01:18:03 +00:00
|
|
|
|
if (kbinput == '~' || kbinput == ERR)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
kbinput = -1;
|
|
|
|
|
nodelay(edit, FALSE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
break;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
default:
|
|
|
|
|
|
2002-02-15 19:17:02 +00:00
|
|
|
|
for (t = s; t != NULL; t = t->next) {
|
2001-06-14 02:54:22 +00:00
|
|
|
|
#ifdef DEBUG
|
2002-01-19 01:59:37 +00:00
|
|
|
|
fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput,
|
|
|
|
|
kbinput);
|
2001-06-14 02:54:22 +00:00
|
|
|
|
#endif
|
2003-01-17 21:07:38 +00:00
|
|
|
|
if (kbinput == t->val || kbinput == t->val - 32)
|
|
|
|
|
/* We hit an Alt key. Do like above. We don't
|
|
|
|
|
just ungetch() the letter and let it get
|
|
|
|
|
caught above cause that screws the
|
|
|
|
|
keypad... */
|
2002-02-15 19:17:02 +00:00
|
|
|
|
return t->val;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (kbinput < 32)
|
|
|
|
|
break;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
answer = nrealloc(answer, xend + 2);
|
|
|
|
|
memmove(answer + x + 1, answer + x, xend - x + 1);
|
|
|
|
|
xend++;
|
|
|
|
|
answer[x] = kbinput;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
x++;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
|
|
|
|
|
#endif
|
2003-01-05 20:41:21 +00:00
|
|
|
|
} /* switch (kbinput) */
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-05 20:41:21 +00:00
|
|
|
|
last_kbinput = kbinput;
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
|
nanoget_repaint(buf, answer, x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
} /* while (kbinput ...) */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-17 21:07:38 +00:00
|
|
|
|
/* We finished putting in an answer; reset x */
|
|
|
|
|
x = -1;
|
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
/* Just check for a blank answer here */
|
2003-01-05 21:47:06 +00:00
|
|
|
|
if (answer[0] == '\0')
|
2000-06-06 05:53:49 +00:00
|
|
|
|
return -2;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* If modified is not already set, set it and update titlebar. */
|
|
|
|
|
void set_modified(void)
|
|
|
|
|
{
|
|
|
|
|
if (!ISSET(MODIFIED)) {
|
|
|
|
|
SET(MODIFIED);
|
|
|
|
|
titlebar(NULL);
|
|
|
|
|
wrefresh(topwin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
void titlebar(const char *path)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
int namelen, space;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
const char *what = path;
|
2001-01-03 07:11:47 +00:00
|
|
|
|
|
|
|
|
|
if (path == NULL)
|
|
|
|
|
what = filename;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
wattron(topwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddstr(topwin, 0, 0, hblank);
|
2002-06-21 03:20:06 +00:00
|
|
|
|
mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
space = COLS - sizeof(VERMSG) - 22;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2001-01-03 07:11:47 +00:00
|
|
|
|
namelen = strlen(what);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-06-21 03:20:06 +00:00
|
|
|
|
if (space > 0) {
|
|
|
|
|
if (what[0] == '\0')
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"),
|
|
|
|
|
COLS / 2 + COLS % 2 - 6);
|
|
|
|
|
else if (namelen > space) {
|
|
|
|
|
if (path == NULL)
|
|
|
|
|
waddstr(topwin, _(" File: ..."));
|
|
|
|
|
else
|
|
|
|
|
waddstr(topwin, _(" DIR: ..."));
|
|
|
|
|
waddstr(topwin, &what[namelen - space]);
|
|
|
|
|
} else {
|
|
|
|
|
if (path == NULL)
|
|
|
|
|
mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
|
|
|
|
|
_("File: "));
|
|
|
|
|
else
|
|
|
|
|
mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
|
|
|
|
|
_(" DIR: "));
|
|
|
|
|
waddstr(topwin, what);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2002-06-21 03:20:06 +00:00
|
|
|
|
} /* If we don't have space, we shouldn't bother */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (ISSET(MODIFIED))
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11);
|
2002-05-11 03:04:44 +00:00
|
|
|
|
else if (ISSET(VIEW_MODE))
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattroff(topwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(topwin);
|
|
|
|
|
reset_cursor();
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
void bottombars(const shortcut *s)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-02-16 20:03:44 +00:00
|
|
|
|
int i, j, numcols;
|
2003-01-23 00:46:12 +00:00
|
|
|
|
char keystr[9];
|
2002-02-15 19:17:02 +00:00
|
|
|
|
int slen;
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (ISSET(NO_HELP))
|
|
|
|
|
return;
|
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
if (s == main_list) {
|
|
|
|
|
slen = MAIN_VISIBLE;
|
|
|
|
|
assert(MAIN_VISIBLE <= length_of_list(s));
|
|
|
|
|
} else
|
|
|
|
|
slen = length_of_list(s);
|
|
|
|
|
|
|
|
|
|
/* There will be this many columns of shortcuts */
|
|
|
|
|
numcols = (slen + (slen % 2)) / 2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
blank_bottomwin();
|
2001-06-14 02:54:22 +00:00
|
|
|
|
|
2002-02-16 20:03:44 +00:00
|
|
|
|
for (i = 0; i < numcols; i++) {
|
|
|
|
|
for (j = 0; j <= 1; j++) {
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
wmove(bottomwin, 1 + j, i * (COLS / numcols));
|
2001-06-14 02:54:22 +00:00
|
|
|
|
|
2003-01-05 20:41:21 +00:00
|
|
|
|
/* Yucky sentinel values we can't handle a better way */
|
2002-05-12 19:52:15 +00:00
|
|
|
|
if (s->val == NANO_CONTROL_SPACE)
|
|
|
|
|
strcpy(keystr, "^ ");
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-05 20:41:21 +00:00
|
|
|
|
else if (s->val == KEY_UP)
|
2003-01-23 00:46:12 +00:00
|
|
|
|
strncpy(keystr, _("Up"), 8);
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#endif /* NANO_SMALL */
|
|
|
|
|
else if (s->val > 0) {
|
2002-05-12 19:52:15 +00:00
|
|
|
|
if (s->val < 64)
|
|
|
|
|
sprintf(keystr, "^%c", s->val + 64);
|
|
|
|
|
else
|
|
|
|
|
sprintf(keystr, "M-%c", s->val - 32);
|
|
|
|
|
} else if (s->altval > 0)
|
|
|
|
|
sprintf(keystr, "M-%c", s->altval);
|
2001-06-14 02:54:22 +00:00
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
onekey(keystr, s->desc, COLS / numcols);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
s = s->next;
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
goto break_completely_out;
|
2002-12-22 16:30:00 +00:00
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
break_completely_out:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Write a shortcut key to the help area at the bottom of the window.
|
|
|
|
|
* keystroke is e.g. "^G" and desc is e.g. "Get Help".
|
|
|
|
|
* We are careful to write exactly len characters, even if len is
|
|
|
|
|
* very small and keystroke and desc are long. */
|
|
|
|
|
void onekey(const char *keystroke, const char *desc, int len)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2003-01-05 20:41:21 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
|
|
|
|
waddnstr(bottomwin, keystroke, len);
|
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
|
|
|
|
len -= strlen(keystroke);
|
|
|
|
|
if (len > 0) {
|
|
|
|
|
waddch(bottomwin, ' ');
|
|
|
|
|
len--;
|
|
|
|
|
waddnstr(bottomwin, desc, len);
|
|
|
|
|
len -= strlen(desc);
|
|
|
|
|
for (; len > 0; len--)
|
|
|
|
|
waddch(bottomwin, ' ');
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* And so start the display update routines. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
int check_linenumbers(const filestruct *fileptr)
|
2000-06-21 03:00:43 +00:00
|
|
|
|
{
|
2002-09-27 14:21:59 +00:00
|
|
|
|
int check_line = 0;
|
|
|
|
|
const filestruct *filetmp;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
|
|
|
|
|
check_line++;
|
|
|
|
|
return check_line;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#endif
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* nano scrolls horizontally within a line in chunks. This function
|
|
|
|
|
* returns the column number of the first character displayed in the
|
|
|
|
|
* window when the cursor is at the given column. */
|
2002-08-21 16:10:37 +00:00
|
|
|
|
int get_page_start(int column)
|
2002-07-19 01:08:59 +00:00
|
|
|
|
{
|
|
|
|
|
assert(COLS > 9);
|
|
|
|
|
return column < COLS - 1 ? 0 : column - 7 - (column - 8) % (COLS - 9);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-21 16:10:37 +00:00
|
|
|
|
/* Resets current_y, based on the position of current, and puts the
|
|
|
|
|
* cursor at (current_y, current_x). */
|
|
|
|
|
void reset_cursor(void)
|
|
|
|
|
{
|
|
|
|
|
const filestruct *ptr = edittop;
|
|
|
|
|
size_t x;
|
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
/* Yuck. This condition can be true after open_file() when opening
|
|
|
|
|
* the first file. */
|
2002-08-21 16:10:37 +00:00
|
|
|
|
if (edittop == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
current_y = 0;
|
|
|
|
|
|
|
|
|
|
while (ptr != current && ptr != editbot && ptr->next != NULL) {
|
|
|
|
|
ptr = ptr->next;
|
|
|
|
|
current_y++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
x = xplustabs();
|
|
|
|
|
wmove(edit, current_y, x - get_page_start(x));
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* edit_add() takes care of the job of actually painting a line into
|
|
|
|
|
* the edit window. Called only from update_line(). Expects a
|
|
|
|
|
* converted-to-not-have-tabs line. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
void edit_add(const filestruct *fileptr, int yval, int start
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
, int virt_mark_beginx, int virt_cur_x
|
|
|
|
|
#endif
|
|
|
|
|
)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, "Painting line %d, current is %d\n", fileptr->lineno,
|
|
|
|
|
current->lineno);
|
2001-12-02 04:55:44 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Just paint the string in any case (we'll add color or reverse on
|
2002-01-19 01:59:37 +00:00
|
|
|
|
just the text that needs it */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
mvwaddnstr(edit, yval, 0, &fileptr->data[start], COLS);
|
2001-12-02 04:55:44 +00:00
|
|
|
|
|
2001-12-08 19:52:28 +00:00
|
|
|
|
#ifdef ENABLE_COLOR
|
2002-10-13 18:43:45 +00:00
|
|
|
|
if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
const colortype *tmpcolor = colorstrings;
|
|
|
|
|
|
|
|
|
|
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
|
|
|
|
int x_start;
|
|
|
|
|
/* Starting column for mvwaddnstr. Zero-based. */
|
|
|
|
|
int paintlen;
|
|
|
|
|
/* number of chars to paint on this line. There are COLS
|
|
|
|
|
* characters on a whole line. */
|
|
|
|
|
regex_t start_regexp; /* Compiled search regexp */
|
|
|
|
|
regmatch_t startmatch; /* match position for start_regexp*/
|
|
|
|
|
regmatch_t endmatch; /* match position for end_regexp*/
|
|
|
|
|
|
|
|
|
|
regcomp(&start_regexp, tmpcolor->start, REG_EXTENDED);
|
|
|
|
|
|
|
|
|
|
if (tmpcolor->bright)
|
|
|
|
|
wattron(edit, A_BOLD);
|
|
|
|
|
wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
|
|
|
|
|
/* Two notes about regexec. Return value 0 means there is a
|
|
|
|
|
* match. Also, rm_eo is the first non-matching character
|
|
|
|
|
* after the match. */
|
|
|
|
|
|
|
|
|
|
/* First case, tmpcolor is a single-line expression. */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
if (tmpcolor->end == NULL) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
size_t k = 0;
|
|
|
|
|
|
|
|
|
|
/* We increment k by rm_eo, to move past the end of the
|
|
|
|
|
last match. Even though two matches may overlap, we
|
|
|
|
|
want to ignore them, so that we can highlight C-strings
|
|
|
|
|
correctly. */
|
|
|
|
|
while (k < start + COLS) {
|
|
|
|
|
/* Note the fifth parameter to regexec. It says not to
|
|
|
|
|
* match the beginning-of-line character unless
|
2002-12-22 16:30:00 +00:00
|
|
|
|
* k == 0. If regexec returns nonzero, there are no
|
|
|
|
|
* more matches in the line. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (regexec(&start_regexp, &fileptr->data[k], 1,
|
|
|
|
|
&startmatch, k == 0 ? 0 : REG_NOTBOL))
|
2002-01-19 16:52:34 +00:00
|
|
|
|
break;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* Translate the match to the beginning of the line. */
|
|
|
|
|
startmatch.rm_so += k;
|
|
|
|
|
startmatch.rm_eo += k;
|
2002-10-17 02:19:31 +00:00
|
|
|
|
if (startmatch.rm_so == startmatch.rm_eo) {
|
|
|
|
|
startmatch.rm_eo++;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
statusbar(_("Refusing 0 length regex match"));
|
2002-10-17 02:19:31 +00:00
|
|
|
|
} else if (startmatch.rm_so < start + COLS &&
|
2002-09-27 14:21:59 +00:00
|
|
|
|
startmatch.rm_eo > start) {
|
|
|
|
|
x_start = startmatch.rm_so - start;
|
|
|
|
|
if (x_start < 0)
|
|
|
|
|
x_start = 0;
|
|
|
|
|
paintlen = startmatch.rm_eo - start - x_start;
|
|
|
|
|
if (paintlen > COLS - x_start)
|
|
|
|
|
paintlen = COLS - x_start;
|
|
|
|
|
|
|
|
|
|
assert(0 <= x_start && 0 < paintlen &&
|
|
|
|
|
x_start + paintlen <= COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
|
|
|
|
fileptr->data + start + x_start, paintlen);
|
|
|
|
|
}
|
|
|
|
|
k = startmatch.rm_eo;
|
2002-01-19 01:59:37 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* This is a multi-line regexp. There are two steps.
|
|
|
|
|
* First, we have to see if the beginning of the line is
|
|
|
|
|
* colored by a start on an earlier line, and an end on
|
|
|
|
|
* this line or later.
|
|
|
|
|
*
|
|
|
|
|
* We find the first line before fileptr matching the
|
|
|
|
|
* start. If every match on that line is followed by an
|
|
|
|
|
* end, then go to step two. Otherwise, find the next line
|
|
|
|
|
* after start_line matching the end. If that line is not
|
|
|
|
|
* before fileptr, then paint the beginning of this line. */
|
|
|
|
|
|
|
|
|
|
regex_t end_regexp; /* Compiled search regexp */
|
|
|
|
|
const filestruct *start_line = fileptr->prev;
|
|
|
|
|
/* the first line before fileptr matching start*/
|
|
|
|
|
regoff_t start_col;
|
|
|
|
|
/* where it starts in that line */
|
|
|
|
|
const filestruct *end_line;
|
|
|
|
|
int searched_later_lines = 0;
|
|
|
|
|
/* Used in step 2. Have we looked for an end on
|
|
|
|
|
* lines after fileptr? */
|
|
|
|
|
|
|
|
|
|
regcomp(&end_regexp, tmpcolor->end, REG_EXTENDED);
|
|
|
|
|
|
|
|
|
|
while (start_line != NULL &&
|
|
|
|
|
regexec(&start_regexp, start_line->data, 1,
|
|
|
|
|
&startmatch, 0)) {
|
|
|
|
|
/* If there is an end on this line, there is no need
|
|
|
|
|
* to look for starts on earlier lines. */
|
|
|
|
|
if (!regexec(&end_regexp, start_line->data, 1,
|
|
|
|
|
&endmatch, 0))
|
|
|
|
|
goto step_two;
|
|
|
|
|
start_line = start_line->prev;
|
|
|
|
|
}
|
|
|
|
|
/* No start found, so skip to the next step. */
|
|
|
|
|
if (start_line == NULL)
|
|
|
|
|
goto step_two;
|
|
|
|
|
/* Now start_line is the first line before fileptr
|
|
|
|
|
* containing a start match. Is there a start on this
|
|
|
|
|
* line not followed by an end on this line? */
|
|
|
|
|
|
|
|
|
|
start_col = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
start_col += startmatch.rm_so;
|
|
|
|
|
startmatch.rm_eo -= startmatch.rm_so;
|
|
|
|
|
if (regexec(&end_regexp,
|
|
|
|
|
start_line->data + start_col + startmatch.rm_eo,
|
|
|
|
|
1, &endmatch,
|
|
|
|
|
start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL))
|
|
|
|
|
/* No end found after this start */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
break;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col++;
|
|
|
|
|
if (regexec(&start_regexp,
|
|
|
|
|
start_line->data + start_col, 1, &startmatch,
|
|
|
|
|
REG_NOTBOL))
|
|
|
|
|
/* No later start on this line. */
|
|
|
|
|
goto step_two;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* Indeed, there is a start not followed on this line by an
|
|
|
|
|
* end. */
|
|
|
|
|
|
|
|
|
|
/* We have already checked that there is no end before
|
|
|
|
|
* fileptr and after the start. Is there an end after
|
|
|
|
|
* the start at all? We don't paint unterminated starts. */
|
|
|
|
|
end_line = fileptr;
|
2002-12-22 16:30:00 +00:00
|
|
|
|
while (end_line != NULL && regexec(&end_regexp, end_line->data,
|
|
|
|
|
1, &endmatch, 0))
|
2002-09-27 14:21:59 +00:00
|
|
|
|
end_line = end_line->next;
|
|
|
|
|
|
|
|
|
|
/* No end found, or it is too early. */
|
2002-12-22 16:30:00 +00:00
|
|
|
|
if (end_line == NULL || end_line->lineno < fileptr->lineno ||
|
2002-09-27 14:21:59 +00:00
|
|
|
|
(end_line == fileptr && endmatch.rm_eo <= start))
|
|
|
|
|
goto step_two;
|
|
|
|
|
|
|
|
|
|
/* Now paint the start of fileptr. */
|
|
|
|
|
paintlen = end_line != fileptr
|
|
|
|
|
? COLS : endmatch.rm_eo - start;
|
|
|
|
|
if (paintlen > COLS)
|
|
|
|
|
paintlen = COLS;
|
|
|
|
|
|
|
|
|
|
assert(0 < paintlen && paintlen <= COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, 0, fileptr->data + start, paintlen);
|
|
|
|
|
|
|
|
|
|
/* We have already painted the whole line. */
|
|
|
|
|
if (paintlen == COLS)
|
|
|
|
|
goto skip_step_two;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
step_two: /* Second step, we look for starts on this line. */
|
|
|
|
|
start_col = 0;
|
|
|
|
|
while (start_col < start + COLS) {
|
|
|
|
|
if (regexec(&start_regexp, fileptr->data + start_col, 1,
|
|
|
|
|
&startmatch, start_col == 0 ? 0 : REG_NOTBOL)
|
|
|
|
|
|| start_col + startmatch.rm_so >= start + COLS)
|
|
|
|
|
/* No more starts on this line. */
|
|
|
|
|
break;
|
|
|
|
|
/* Translate the match to be relative to the
|
|
|
|
|
* beginning of the line. */
|
|
|
|
|
startmatch.rm_so += start_col;
|
|
|
|
|
startmatch.rm_eo += start_col;
|
|
|
|
|
|
|
|
|
|
x_start = startmatch.rm_so - start;
|
|
|
|
|
if (x_start < 0) {
|
|
|
|
|
x_start = 0;
|
|
|
|
|
startmatch.rm_so = start;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (!regexec(&end_regexp, fileptr->data + startmatch.rm_eo,
|
|
|
|
|
1, &endmatch,
|
|
|
|
|
startmatch.rm_eo == 0 ? 0 : REG_NOTBOL)) {
|
|
|
|
|
/* Translate the end match to be relative to the
|
|
|
|
|
beginning of the line. */
|
|
|
|
|
endmatch.rm_so += startmatch.rm_eo;
|
|
|
|
|
endmatch.rm_eo += startmatch.rm_eo;
|
|
|
|
|
/* There is an end on this line. But does it
|
|
|
|
|
appear on this page, and is the match more than
|
|
|
|
|
zero characters long? */
|
|
|
|
|
if (endmatch.rm_eo > start &&
|
|
|
|
|
endmatch.rm_eo > startmatch.rm_so) {
|
|
|
|
|
paintlen = endmatch.rm_eo - start - x_start;
|
|
|
|
|
if (x_start + paintlen > COLS)
|
|
|
|
|
paintlen = COLS - x_start;
|
|
|
|
|
|
|
|
|
|
assert(0 <= x_start && 0 < paintlen &&
|
|
|
|
|
x_start + paintlen <= COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
|
|
|
|
fileptr->data + start + x_start, paintlen);
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
} else if (!searched_later_lines) {
|
|
|
|
|
searched_later_lines = 1;
|
|
|
|
|
/* There is no end on this line. But we haven't
|
|
|
|
|
* yet looked for one on later lines. */
|
|
|
|
|
end_line = fileptr->next;
|
2002-12-22 16:30:00 +00:00
|
|
|
|
while (end_line != NULL && regexec(&end_regexp,
|
|
|
|
|
end_line->data, 1, &endmatch, 0))
|
2002-09-27 14:21:59 +00:00
|
|
|
|
end_line = end_line->next;
|
|
|
|
|
if (end_line != NULL) {
|
|
|
|
|
assert(0 <= x_start && x_start < COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
|
|
|
|
fileptr->data + start + x_start,
|
|
|
|
|
COLS - x_start);
|
|
|
|
|
/* We painted to the end of the line, so
|
|
|
|
|
* don't bother checking any more starts. */
|
|
|
|
|
break;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col = startmatch.rm_so + 1;
|
|
|
|
|
} /* while start_col < start + COLS */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
skip_step_two:
|
|
|
|
|
regfree(&end_regexp);
|
|
|
|
|
} /* if (tmp_color->end != NULL) */
|
2002-05-12 20:43:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
regfree(&start_regexp);
|
|
|
|
|
wattroff(edit, A_BOLD);
|
|
|
|
|
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
|
|
|
|
|
} /* for tmpcolor in colorstrings */
|
|
|
|
|
}
|
2002-01-19 01:59:37 +00:00
|
|
|
|
#endif /* ENABLE_COLOR */
|
2001-12-02 04:55:44 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(MARK_ISSET)
|
|
|
|
|
&& (fileptr->lineno <= mark_beginbuf->lineno
|
|
|
|
|
|| fileptr->lineno <= current->lineno)
|
|
|
|
|
&& (fileptr->lineno >= mark_beginbuf->lineno
|
|
|
|
|
|| fileptr->lineno >= current->lineno)) {
|
|
|
|
|
/* fileptr is at least partially selected. */
|
|
|
|
|
|
|
|
|
|
int x_start;
|
|
|
|
|
/* Starting column for mvwaddnstr. Zero-based. */
|
|
|
|
|
int paintlen;
|
|
|
|
|
/* number of chars to paint on this line. There are COLS
|
|
|
|
|
* characters on a whole line. */
|
|
|
|
|
|
|
|
|
|
if (mark_beginbuf == fileptr && current == fileptr) {
|
|
|
|
|
x_start = virt_mark_beginx < virt_cur_x ? virt_mark_beginx
|
|
|
|
|
: virt_cur_x;
|
|
|
|
|
paintlen = abs(virt_mark_beginx - virt_cur_x);
|
|
|
|
|
} else {
|
|
|
|
|
if (mark_beginbuf->lineno < fileptr->lineno ||
|
|
|
|
|
current->lineno < fileptr->lineno)
|
|
|
|
|
x_start = 0;
|
|
|
|
|
else
|
|
|
|
|
x_start = mark_beginbuf == fileptr ? virt_mark_beginx
|
|
|
|
|
: virt_cur_x;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (mark_beginbuf->lineno > fileptr->lineno ||
|
|
|
|
|
current->lineno > fileptr->lineno)
|
|
|
|
|
paintlen = start + COLS;
|
|
|
|
|
else
|
|
|
|
|
paintlen = mark_beginbuf == fileptr ? virt_mark_beginx
|
|
|
|
|
: virt_cur_x;
|
|
|
|
|
}
|
|
|
|
|
x_start -= start;
|
|
|
|
|
if (x_start < 0) {
|
|
|
|
|
paintlen += x_start;
|
|
|
|
|
x_start = 0;
|
|
|
|
|
}
|
|
|
|
|
if (x_start + paintlen > COLS)
|
|
|
|
|
paintlen = COLS - x_start;
|
|
|
|
|
if (paintlen > 0) {
|
2000-10-26 01:44:42 +00:00
|
|
|
|
wattron(edit, A_REVERSE);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
assert(x_start >= 0 && paintlen > 0 && x_start + paintlen <= COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
|
|
|
|
fileptr->data + start + x_start, paintlen);
|
2000-10-26 01:44:42 +00:00
|
|
|
|
wattroff(edit, A_REVERSE);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2001-11-29 02:42:27 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* Just update one line in the edit buffer. Basically a wrapper for
|
|
|
|
|
* edit_add(). If fileptr != current, then index is considered 0.
|
|
|
|
|
* The line will be displayed starting with fileptr->data[index].
|
|
|
|
|
* Likely args are current_x or 0. */
|
2002-09-06 20:35:28 +00:00
|
|
|
|
void update_line(filestruct *fileptr, int index)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-09-27 14:21:59 +00:00
|
|
|
|
int line;
|
|
|
|
|
/* line in the edit window for CURSES calls */
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
int virt_cur_x;
|
|
|
|
|
int virt_mark_beginx;
|
|
|
|
|
#endif
|
|
|
|
|
char *original;
|
|
|
|
|
/* The original string fileptr->data. */
|
|
|
|
|
char *converted;
|
|
|
|
|
/* fileptr->data converted to have tabs and control characters
|
|
|
|
|
* expanded. */
|
|
|
|
|
size_t pos;
|
|
|
|
|
size_t page_start;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
if (fileptr == NULL)
|
2000-06-21 03:00:43 +00:00
|
|
|
|
return;
|
2000-06-18 00:11:03 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
line = fileptr->lineno - edittop->lineno;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* We assume the line numbers are valid. Is that really true? */
|
|
|
|
|
assert(line < 0 || line == check_linenumbers(fileptr));
|
2000-06-16 04:25:30 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (line < 0 || line >= editwinrows)
|
|
|
|
|
return;
|
2000-06-16 04:25:30 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* First, blank out the line (at a minimum) */
|
|
|
|
|
mvwaddstr(edit, line, 0, hblank);
|
|
|
|
|
|
|
|
|
|
original = fileptr->data;
|
|
|
|
|
converted = charalloc(strlenpt(original) + 1);
|
2003-01-05 20:41:21 +00:00
|
|
|
|
|
|
|
|
|
/* Next, convert all the tabs to spaces, so everything else is easy.
|
2002-09-27 14:21:59 +00:00
|
|
|
|
* Note the internal speller sends us index == -1. */
|
|
|
|
|
index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
virt_cur_x = fileptr == current ? strnlenpt(original, current_x) : current_x;
|
|
|
|
|
virt_mark_beginx = fileptr == mark_beginbuf ? strnlenpt(original, mark_beginx) : mark_beginx;
|
|
|
|
|
#endif
|
2000-06-16 04:25:30 +00:00
|
|
|
|
|
|
|
|
|
pos = 0;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
for (; *original != '\0'; original++) {
|
|
|
|
|
if (*original == '\t')
|
2000-06-16 04:25:30 +00:00
|
|
|
|
do {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
converted[pos++] = ' ';
|
2000-08-03 22:51:21 +00:00
|
|
|
|
} while (pos % tabsize);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
else if (is_cntrl_char(*original)) {
|
|
|
|
|
converted[pos++] = '^';
|
|
|
|
|
if (*original == 127)
|
|
|
|
|
converted[pos++] = '?';
|
|
|
|
|
else if (*original == '\n')
|
|
|
|
|
/* Treat newlines (ASCII 10's) embedded in a line as encoded
|
|
|
|
|
* nulls (ASCII 0's); the line in question should be run
|
|
|
|
|
* through unsunder() before reaching here */
|
|
|
|
|
converted[pos++] = '@';
|
|
|
|
|
else
|
|
|
|
|
converted[pos++] = *original + 64;
|
|
|
|
|
} else
|
|
|
|
|
converted[pos++] = *original;
|
2000-06-16 04:25:30 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
converted[pos] = '\0';
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-05-11 03:04:44 +00:00
|
|
|
|
/* Now, paint the line */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
original = fileptr->data;
|
|
|
|
|
fileptr->data = converted;
|
|
|
|
|
page_start = get_page_start(index);
|
|
|
|
|
edit_add(fileptr, line, page_start
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
, virt_mark_beginx, virt_cur_x
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
free(converted);
|
|
|
|
|
fileptr->data = original;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (page_start > 0)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
mvwaddch(edit, line, 0, '$');
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (pos > page_start + COLS)
|
|
|
|
|
mvwaddch(edit, line, COLS - 1, '$');
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* This function updates current, based on where current_y is;
|
|
|
|
|
* reset_cursor() does the opposite. */
|
|
|
|
|
void update_cursor(void)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
|
|
|
|
|
current_x);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
current = edittop;
|
|
|
|
|
while (i < current_y && current->next != NULL) {
|
|
|
|
|
current = current->next;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2003-01-23 04:27:23 +00:00
|
|
|
|
fprintf(stderr, "current->data = \"%s\"\n", current->data);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void center_cursor(void)
|
|
|
|
|
{
|
|
|
|
|
current_y = editwinrows / 2;
|
|
|
|
|
wmove(edit, current_y, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Refresh the screen without changing the position of lines. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void edit_refresh(void)
|
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Neither of these conditions should occur, but they do. edittop is
|
|
|
|
|
* NULL when you open an existing file on the command line, and
|
|
|
|
|
* ENABLE_COLOR is defined. Yuck. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (current == NULL)
|
|
|
|
|
return;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (edittop == NULL)
|
|
|
|
|
edittop = current;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-26 19:47:10 +00:00
|
|
|
|
if (current->lineno < edittop->lineno ||
|
|
|
|
|
current->lineno >= edittop->lineno + editwinrows)
|
2002-12-22 16:30:00 +00:00
|
|
|
|
/* Note that edit_update() changes edittop so that
|
|
|
|
|
* current->lineno = edittop->lineno + editwinrows / 2. Thus
|
|
|
|
|
* when it then calls edit_refresh(), there is no danger of
|
|
|
|
|
* getting an infinite loop. */
|
2000-07-31 01:26:42 +00:00
|
|
|
|
edit_update(current, CENTER);
|
2002-12-22 16:30:00 +00:00
|
|
|
|
else {
|
|
|
|
|
int nlines = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
/* Don't make the cursor jump around the screen whilst updating */
|
|
|
|
|
leaveok(edit, TRUE);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
editbot = edittop;
|
|
|
|
|
while (nlines < editwinrows) {
|
|
|
|
|
update_line(editbot, current_x);
|
|
|
|
|
nlines++;
|
|
|
|
|
if (editbot->next == NULL)
|
|
|
|
|
break;
|
|
|
|
|
editbot = editbot->next;
|
|
|
|
|
}
|
|
|
|
|
while (nlines < editwinrows) {
|
|
|
|
|
mvwaddstr(edit, nlines, 0, hblank);
|
|
|
|
|
nlines++;
|
|
|
|
|
}
|
|
|
|
|
/* What the hell are we expecting to update the screen if this
|
2003-01-13 01:35:15 +00:00
|
|
|
|
isn't here? Luck? */
|
2002-12-22 16:30:00 +00:00
|
|
|
|
wrefresh(edit);
|
|
|
|
|
leaveok(edit, FALSE);
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
/* Same as above, but touch the window first, so everything is
|
|
|
|
|
* redrawn. */
|
2000-08-19 03:53:39 +00:00
|
|
|
|
void edit_refresh_clearok(void)
|
|
|
|
|
{
|
|
|
|
|
clearok(edit, TRUE);
|
|
|
|
|
edit_refresh();
|
|
|
|
|
clearok(edit, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
/*
|
2001-05-05 17:45:54 +00:00
|
|
|
|
* Nice generic routine to update the edit buffer, given a pointer to the
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* file struct =)
|
|
|
|
|
*/
|
2002-07-19 01:08:59 +00:00
|
|
|
|
void edit_update(filestruct *fileptr, topmidbotnone location)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
if (fileptr == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (location != TOP) {
|
|
|
|
|
int goal = location == NONE ? current_y - 1 : editwinrows / 2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
for (; goal >= 0 && fileptr->prev != NULL; goal--)
|
|
|
|
|
fileptr = fileptr->prev;
|
|
|
|
|
}
|
|
|
|
|
edittop = fileptr;
|
2000-07-05 03:16:04 +00:00
|
|
|
|
fix_editbot();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
edit_refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ask a question on the statusbar. Answer will be stored in answer
|
|
|
|
|
* global. Returns -1 on aborted enter, -2 on a blank string, and 0
|
2001-05-05 17:45:54 +00:00
|
|
|
|
* otherwise, the valid shortcut key caught. Def is any editable text we
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* want to put up by default.
|
2000-11-06 02:57:22 +00:00
|
|
|
|
*
|
|
|
|
|
* New arg tabs tells whether or not to allow tab completion.
|
2000-06-06 05:53:49 +00:00
|
|
|
|
*/
|
2002-07-19 01:08:59 +00:00
|
|
|
|
int statusq(int tabs, const shortcut *s, const char *def,
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
historyheadtype *which_history,
|
|
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
|
const char *msg, ...)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
char *foo = charalloc(COLS - 3);
|
2002-02-15 20:08:05 +00:00
|
|
|
|
int ret;
|
2001-11-29 03:43:08 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2002-01-05 18:59:54 +00:00
|
|
|
|
int list = 0;
|
2001-11-29 03:43:08 +00:00
|
|
|
|
#endif
|
2003-01-26 21:01:16 +00:00
|
|
|
|
static int resetpos = 0; /* Do we need to scrap the cursor position
|
|
|
|
|
on the statusbar? */
|
2001-11-29 03:43:08 +00:00
|
|
|
|
|
2002-02-15 19:17:02 +00:00
|
|
|
|
bottombars(s);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
vsnprintf(foo, COLS - 4, msg, ap);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
va_end(ap);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
foo[COLS - 4] = '\0';
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2003-01-05 20:41:21 +00:00
|
|
|
|
ret = nanogetstr(tabs, foo, def,
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
which_history,
|
|
|
|
|
#endif
|
|
|
|
|
s
|
2001-11-29 03:43:08 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2003-01-05 20:41:21 +00:00
|
|
|
|
, &list
|
2001-11-29 03:43:08 +00:00
|
|
|
|
#endif
|
2003-01-26 21:01:16 +00:00
|
|
|
|
, resetpos);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
free(foo);
|
2003-01-26 21:01:16 +00:00
|
|
|
|
resetpos = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
|
case NANO_FIRSTLINE_KEY:
|
|
|
|
|
do_first_line();
|
2003-01-26 21:01:16 +00:00
|
|
|
|
resetpos = 1;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
|
|
|
|
case NANO_LASTLINE_KEY:
|
|
|
|
|
do_last_line();
|
2003-01-26 21:01:16 +00:00
|
|
|
|
resetpos = 1;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
|
|
|
|
case NANO_CANCEL_KEY:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
ret = -1;
|
2003-01-26 21:01:16 +00:00
|
|
|
|
resetpos = 1;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
break;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
default:
|
2000-11-16 19:55:30 +00:00
|
|
|
|
blank_statusbar();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, _("I got \"%s\"\n"), answer);
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
|
|
|
|
/* if we've done tab completion, there might be a list of
|
|
|
|
|
filename matches on the edit window at this point; make sure
|
|
|
|
|
they're cleared off */
|
|
|
|
|
if (list)
|
|
|
|
|
edit_refresh();
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2002-09-06 20:35:28 +00:00
|
|
|
|
* Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
|
2002-12-22 16:30:00 +00:00
|
|
|
|
* for N, 2 for All (if all is nonzero when passed in) and -1 for abort
|
|
|
|
|
* (^C).
|
2000-06-06 05:53:49 +00:00
|
|
|
|
*/
|
2002-07-19 01:08:59 +00:00
|
|
|
|
int do_yesno(int all, int leavecursor, const char *msg, ...)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
2003-01-28 01:23:40 +00:00
|
|
|
|
char *foo;
|
|
|
|
|
int ok = -2;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
const char *yesstr; /* String of yes characters accepted */
|
|
|
|
|
const char *nostr; /* Same for no */
|
|
|
|
|
const char *allstr; /* And all, surprise! */
|
2001-04-12 13:24:40 +00:00
|
|
|
|
|
2001-02-16 01:49:31 +00:00
|
|
|
|
/* Yes, no and all are strings of any length. Each string consists of
|
2002-01-19 01:59:37 +00:00
|
|
|
|
all characters accepted as a valid character for that value.
|
|
|
|
|
The first value will be the one displayed in the shortcuts. */
|
2001-02-16 01:49:31 +00:00
|
|
|
|
yesstr = _("Yy");
|
|
|
|
|
nostr = _("Nn");
|
|
|
|
|
allstr = _("Aa");
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2000-06-23 01:00:13 +00:00
|
|
|
|
/* Remove gettext call for keybindings until we clear the thing up */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (!ISSET(NO_HELP)) {
|
2002-05-12 19:52:15 +00:00
|
|
|
|
char shortstr[3]; /* Temp string for Y, N, A */
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
/* Write the bottom of the screen */
|
|
|
|
|
blank_bottombars();
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
sprintf(shortstr, " %c", yesstr[0]);
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 1, 0);
|
2002-02-15 19:17:02 +00:00
|
|
|
|
onekey(shortstr, _("Yes"), 16);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
|
|
|
|
if (all) {
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 1, 16);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
shortstr[1] = allstr[0];
|
2002-02-15 19:17:02 +00:00
|
|
|
|
onekey(shortstr, _("All"), 16);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 2, 0);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
shortstr[1] = nostr[0];
|
2002-02-15 19:17:02 +00:00
|
|
|
|
onekey(shortstr, _("No"), 16);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 2, 16);
|
2002-02-15 19:17:02 +00:00
|
|
|
|
onekey("^C", _("Cancel"), 16);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2003-01-28 01:23:40 +00:00
|
|
|
|
|
|
|
|
|
foo = charalloc(COLS);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
va_start(ap, msg);
|
2003-01-28 01:23:40 +00:00
|
|
|
|
vsnprintf(foo, COLS, msg, ap);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
va_end(ap);
|
2003-01-28 01:23:40 +00:00
|
|
|
|
foo[COLS - 1] = '\0';
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
|
|
|
|
blank_statusbar();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
mvwaddstr(bottomwin, 0, 0, foo);
|
2003-01-28 01:23:40 +00:00
|
|
|
|
free(foo);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
do {
|
|
|
|
|
int kbinput = wgetch(edit);
|
|
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
|
MEVENT mevent;
|
2001-04-12 13:24:40 +00:00
|
|
|
|
#endif
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
if (kbinput == NANO_CONTROL_C)
|
|
|
|
|
ok = -1;
|
|
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
|
/* Look ma! We get to duplicate lots of code from do_mouse!! */
|
|
|
|
|
else if (kbinput == KEY_MOUSE && getmouse(&mevent) != ERR &&
|
|
|
|
|
wenclose(bottomwin, mevent.y, mevent.x) &&
|
|
|
|
|
!ISSET(NO_HELP) && mevent.x < 32 &&
|
|
|
|
|
mevent.y >= editwinrows + 3) {
|
|
|
|
|
int x = mevent.x /= 16;
|
|
|
|
|
/* Did we click in the first column of shortcuts, or the
|
|
|
|
|
second? */
|
|
|
|
|
int y = mevent.y - editwinrows - 3;
|
|
|
|
|
/* Did we click in the first row of shortcuts? */
|
|
|
|
|
|
|
|
|
|
assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
|
|
|
|
|
/* x = 0 means they clicked Yes or No.
|
|
|
|
|
y = 0 means Yes or All. */
|
|
|
|
|
ok = -2 * x * y + x - y + 1;
|
|
|
|
|
|
|
|
|
|
if (ok == 2 && !all)
|
|
|
|
|
ok = -2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2003-01-28 01:23:40 +00:00
|
|
|
|
#endif
|
|
|
|
|
/* Look for the kbinput in the yes, no and (optionally) all str */
|
|
|
|
|
else if (strchr(yesstr, kbinput) != NULL)
|
|
|
|
|
ok = 1;
|
|
|
|
|
else if (strchr(nostr, kbinput) != NULL)
|
|
|
|
|
ok = 0;
|
|
|
|
|
else if (all && strchr(allstr, kbinput) != NULL)
|
|
|
|
|
ok = 2;
|
|
|
|
|
} while (ok == -2);
|
|
|
|
|
|
|
|
|
|
/* Then blank the statusbar. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
blank_statusbar_refresh();
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
return ok;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
int total_refresh(void)
|
|
|
|
|
{
|
|
|
|
|
clearok(edit, TRUE);
|
|
|
|
|
clearok(topwin, TRUE);
|
|
|
|
|
clearok(bottomwin, TRUE);
|
|
|
|
|
wnoutrefresh(edit);
|
|
|
|
|
wnoutrefresh(topwin);
|
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
doupdate();
|
|
|
|
|
clearok(edit, FALSE);
|
|
|
|
|
clearok(topwin, FALSE);
|
|
|
|
|
clearok(bottomwin, FALSE);
|
|
|
|
|
edit_refresh();
|
|
|
|
|
titlebar(NULL);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void display_main_list(void)
|
|
|
|
|
{
|
|
|
|
|
bottombars(main_list);
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
void statusbar(const char *msg, ...)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
char *foo;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
int start_x = 0;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t foo_len;
|
|
|
|
|
|
|
|
|
|
assert(COLS >= 4);
|
|
|
|
|
foo = charalloc(COLS - 3);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
vsnprintf(foo, COLS - 3, msg, ap);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
va_end(ap);
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
foo[COLS - 4] = '\0';
|
|
|
|
|
foo_len = strlen(foo);
|
|
|
|
|
start_x = (COLS - foo_len - 4) / 2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
/* Blank out line */
|
|
|
|
|
blank_statusbar();
|
|
|
|
|
|
|
|
|
|
wmove(bottomwin, 0, start_x);
|
|
|
|
|
|
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
|
|
|
|
|
|
|
|
|
waddstr(bottomwin, "[ ");
|
|
|
|
|
waddstr(bottomwin, foo);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
free(foo);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
waddstr(bottomwin, " ]");
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
SET(DISABLE_CURPOS);
|
|
|
|
|
statblank = 26;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
/*
|
|
|
|
|
* If constant is false, the user typed ^C so we unconditionally display
|
|
|
|
|
* the cursor position. Otherwise, we display it only if the character
|
|
|
|
|
* position changed, and DISABLE_CURPOS is not set.
|
|
|
|
|
*
|
|
|
|
|
* If constant and DISABLE_CURPOS is set, we unset it and update old_i and
|
|
|
|
|
* old_totsize. That way, we leave the current statusbar alone, but next
|
|
|
|
|
* time we will display. */
|
2001-11-29 03:43:08 +00:00
|
|
|
|
int do_cursorpos(int constant)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2003-01-28 01:16:47 +00:00
|
|
|
|
const filestruct *fileptr;
|
|
|
|
|
unsigned long i = 0;
|
|
|
|
|
static unsigned long old_i = 0;
|
|
|
|
|
static long old_totsize = -1;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
assert(current != NULL && fileage != NULL && totlines != 0);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
|
|
|
|
|
if (old_totsize == -1)
|
|
|
|
|
old_totsize = totsize;
|
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
|
|
|
|
|
assert(fileptr != NULL);
|
2002-02-12 01:57:24 +00:00
|
|
|
|
i += strlen(fileptr->data) + 1;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
}
|
2002-02-12 01:57:24 +00:00
|
|
|
|
i += current_x;
|
2002-01-25 21:59:02 +00:00
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
if (constant && ISSET(DISABLE_CURPOS)) {
|
|
|
|
|
UNSET(DISABLE_CURPOS);
|
|
|
|
|
old_i = i;
|
|
|
|
|
old_totsize = totsize;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
/* if constant is false, display the position on the statusbar
|
2001-11-29 03:43:08 +00:00
|
|
|
|
unconditionally; otherwise, only display the position when the
|
|
|
|
|
character values have changed */
|
2003-01-28 01:16:47 +00:00
|
|
|
|
if (!constant || old_i != i || old_totsize != totsize) {
|
|
|
|
|
unsigned long xpt = xplustabs() + 1;
|
|
|
|
|
unsigned long cur_len = strlenpt(current->data) + 1;
|
|
|
|
|
int linepct = 100 * current->lineno / totlines;
|
|
|
|
|
int colpct = 100 * xpt / cur_len;
|
|
|
|
|
int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
|
|
|
|
|
|
|
|
|
|
statusbar(
|
|
|
|
|
_("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
|
|
|
|
|
current->lineno, totlines, linepct,
|
|
|
|
|
xpt, cur_len, colpct,
|
|
|
|
|
i, totsize, bytepct);
|
|
|
|
|
UNSET(DISABLE_CURPOS);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
old_i = i;
|
|
|
|
|
old_totsize = totsize;
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
reset_cursor();
|
2003-01-28 01:16:47 +00:00
|
|
|
|
return 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-11-29 03:43:08 +00:00
|
|
|
|
int do_cursorpos_void(void)
|
|
|
|
|
{
|
|
|
|
|
return do_cursorpos(0);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-21 03:20:06 +00:00
|
|
|
|
/* Our shortcut-list-compliant help function, which is
|
|
|
|
|
* better than nothing, and dynamic! */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
int do_help(void)
|
|
|
|
|
{
|
2001-01-12 07:51:05 +00:00
|
|
|
|
#ifndef DISABLE_HELP
|
2001-04-12 03:01:53 +00:00
|
|
|
|
int i, j, row = 0, page = 1, kbinput = 0, no_more = 0, kp, kp2;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
int no_help_flag = 0;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
const shortcut *oldshortcut;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
blank_edit();
|
|
|
|
|
curs_set(0);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
blank_statusbar();
|
|
|
|
|
|
2002-06-21 03:20:06 +00:00
|
|
|
|
/* set help_text as the string to display */
|
2001-10-22 03:15:31 +00:00
|
|
|
|
help_init();
|
2002-06-21 03:20:06 +00:00
|
|
|
|
assert(help_text != NULL);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
|
|
|
|
|
oldshortcut = currshortcut;
|
|
|
|
|
|
2001-04-12 03:01:53 +00:00
|
|
|
|
currshortcut = help_list;
|
2001-05-21 12:56:25 +00:00
|
|
|
|
|
2001-01-06 18:12:43 +00:00
|
|
|
|
kp = keypad_on(edit, 1);
|
2001-04-12 03:01:53 +00:00
|
|
|
|
kp2 = keypad_on(bottomwin, 1);
|
2001-01-06 18:12:43 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (ISSET(NO_HELP)) {
|
|
|
|
|
|
2001-05-05 17:45:54 +00:00
|
|
|
|
/* Well, if we're going to do this, we should at least
|
2001-01-07 23:02:02 +00:00
|
|
|
|
do it the right way */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
no_help_flag = 1;
|
2000-06-21 03:00:43 +00:00
|
|
|
|
UNSET(NO_HELP);
|
2001-01-07 23:02:02 +00:00
|
|
|
|
window_init();
|
2002-02-15 19:17:02 +00:00
|
|
|
|
bottombars(help_list);
|
2001-01-07 23:02:02 +00:00
|
|
|
|
|
2000-06-21 03:00:43 +00:00
|
|
|
|
} else
|
2002-02-15 19:17:02 +00:00
|
|
|
|
bottombars(help_list);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
do {
|
2002-06-21 03:20:06 +00:00
|
|
|
|
const char *ptr = help_text;
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput) {
|
2002-12-22 16:30:00 +00:00
|
|
|
|
#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
|
2002-01-19 01:59:37 +00:00
|
|
|
|
case KEY_MOUSE:
|
|
|
|
|
do_mouse();
|
|
|
|
|
break;
|
2001-04-12 03:01:53 +00:00
|
|
|
|
#endif
|
2002-06-13 00:40:19 +00:00
|
|
|
|
case 27:
|
|
|
|
|
kbinput = wgetch(edit);
|
|
|
|
|
switch(kbinput) {
|
|
|
|
|
case '[':
|
|
|
|
|
kbinput = wgetch(edit);
|
|
|
|
|
switch(kbinput) {
|
|
|
|
|
case '5': /* Alt-[-5 = Page Up */
|
|
|
|
|
wgetch(edit);
|
|
|
|
|
goto do_pageupkey;
|
|
|
|
|
break;
|
|
|
|
|
case 'V': /* Alt-[-V = Page Up in Hurd Console */
|
|
|
|
|
case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
|
|
|
|
|
goto do_pageupkey;
|
|
|
|
|
break;
|
|
|
|
|
case '6': /* Alt-[-6 = Page Down */
|
|
|
|
|
wgetch(edit);
|
|
|
|
|
goto do_pagedownkey;
|
|
|
|
|
break;
|
|
|
|
|
case 'U': /* Alt-[-U = Page Down in Hurd Console */
|
|
|
|
|
case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
|
|
|
|
|
goto do_pagedownkey;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
case NANO_NEXTPAGE_KEY:
|
|
|
|
|
case NANO_NEXTPAGE_FKEY:
|
|
|
|
|
case KEY_NPAGE:
|
2002-06-13 00:40:19 +00:00
|
|
|
|
do_pagedownkey:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (!no_more) {
|
|
|
|
|
blank_edit();
|
|
|
|
|
page++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NANO_PREVPAGE_KEY:
|
|
|
|
|
case NANO_PREVPAGE_FKEY:
|
|
|
|
|
case KEY_PPAGE:
|
2002-06-13 00:40:19 +00:00
|
|
|
|
do_pageupkey:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (page > 1) {
|
|
|
|
|
no_more = 0;
|
|
|
|
|
blank_edit();
|
|
|
|
|
page--;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-05 17:45:54 +00:00
|
|
|
|
/* Calculate where in the text we should be, based on the page */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
for (i = 1; i < page; i++) {
|
|
|
|
|
row = 0;
|
|
|
|
|
j = 0;
|
2000-09-07 03:37:38 +00:00
|
|
|
|
|
|
|
|
|
while (row < editwinrows - 2 && *ptr != '\0') {
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (*ptr == '\n' || j == COLS - 5) {
|
|
|
|
|
j = 0;
|
|
|
|
|
row++;
|
|
|
|
|
}
|
|
|
|
|
ptr++;
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
j = 0;
|
|
|
|
|
while (i < editwinrows && *ptr != '\0') {
|
2002-06-21 03:20:06 +00:00
|
|
|
|
const char *end = ptr;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
while (*end != '\n' && *end != '\0' && j != COLS - 5) {
|
|
|
|
|
end++;
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
if (j == COLS - 5) {
|
|
|
|
|
|
2001-05-05 17:45:54 +00:00
|
|
|
|
/* Don't print half a word if we've run out of space */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
while (*end != ' ' && *end != '\0') {
|
|
|
|
|
end--;
|
|
|
|
|
j--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mvwaddnstr(edit, i, 0, ptr, j);
|
|
|
|
|
j = 0;
|
|
|
|
|
i++;
|
|
|
|
|
if (*end == '\n')
|
|
|
|
|
end++;
|
|
|
|
|
ptr = end;
|
|
|
|
|
}
|
|
|
|
|
if (*ptr == '\0') {
|
|
|
|
|
no_more = 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-01-19 01:59:37 +00:00
|
|
|
|
} while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY &&
|
|
|
|
|
kbinput != NANO_EXIT_FKEY);
|
2000-12-18 05:03:16 +00:00
|
|
|
|
|
2001-10-22 03:15:31 +00:00
|
|
|
|
currshortcut = oldshortcut;
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (no_help_flag) {
|
2001-01-07 23:02:02 +00:00
|
|
|
|
blank_bottombars();
|
2000-06-21 03:00:43 +00:00
|
|
|
|
wrefresh(bottomwin);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
SET(NO_HELP);
|
2001-01-07 23:02:02 +00:00
|
|
|
|
window_init();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
} else
|
2002-02-15 19:17:02 +00:00
|
|
|
|
bottombars(currshortcut);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
curs_set(1);
|
|
|
|
|
edit_refresh();
|
2001-01-06 18:12:43 +00:00
|
|
|
|
kp = keypad_on(edit, kp);
|
2001-04-12 03:01:53 +00:00
|
|
|
|
kp2 = keypad_on(bottomwin, kp2);
|
2001-01-06 18:12:43 +00:00
|
|
|
|
|
2002-06-21 03:20:06 +00:00
|
|
|
|
/* The help_init() at the beginning allocated help_text, which has
|
|
|
|
|
now been written to screen. */
|
|
|
|
|
free(help_text);
|
|
|
|
|
help_text = NULL;
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
#elif defined(DISABLE_HELP)
|
|
|
|
|
nano_disabled_msg();
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
int keypad_on(WINDOW *win, int newval)
|
2000-10-26 01:44:42 +00:00
|
|
|
|
{
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* This is taken right from aumix. Don't sue me. */
|
|
|
|
|
#ifdef HAVE_USEKEYPAD
|
|
|
|
|
int old = win->_use_keypad;
|
|
|
|
|
keypad(win, newval);
|
|
|
|
|
return old;
|
|
|
|
|
#else
|
|
|
|
|
keypad(win, newval);
|
|
|
|
|
return 1;
|
|
|
|
|
#endif /* HAVE_USEKEYPAD */
|
2000-07-04 02:35:19 +00:00
|
|
|
|
}
|
2000-11-24 20:45:14 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Highlight the current word being replaced or spell checked. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
void do_replace_highlight(int highlight_flag, const char *word)
|
2000-12-05 11:36:41 +00:00
|
|
|
|
{
|
|
|
|
|
char *highlight_word = NULL;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
int x, y, word_len;
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
2002-01-19 01:59:37 +00:00
|
|
|
|
highlight_word =
|
|
|
|
|
mallocstrcpy(highlight_word, ¤t->data[current_x]);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_REGEX_H
|
|
|
|
|
if (ISSET(USE_REGEXP))
|
|
|
|
|
/* if we're using regexps, the highlight is the length of the
|
|
|
|
|
search result, not the length of the regexp string */
|
|
|
|
|
word_len = regmatches[0].rm_eo - regmatches[0].rm_so;
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
word_len = strlen(word);
|
|
|
|
|
|
|
|
|
|
highlight_word[word_len] = '\0';
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
2001-05-05 17:45:54 +00:00
|
|
|
|
/* adjust output when word extends beyond screen */
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
|
|
|
|
x = xplustabs();
|
2002-07-19 01:08:59 +00:00
|
|
|
|
y = get_page_start(x) + COLS;
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if ((COLS - (y - x) + word_len) > COLS) {
|
2000-12-05 11:36:41 +00:00
|
|
|
|
highlight_word[y - x - 1] = '$';
|
|
|
|
|
highlight_word[y - x] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OK display the output */
|
|
|
|
|
|
|
|
|
|
reset_cursor();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
|
2000-12-05 11:36:41 +00:00
|
|
|
|
if (highlight_flag)
|
|
|
|
|
wattron(edit, A_REVERSE);
|
|
|
|
|
|
|
|
|
|
waddstr(edit, highlight_word);
|
|
|
|
|
|
|
|
|
|
if (highlight_flag)
|
|
|
|
|
wattroff(edit, A_REVERSE);
|
|
|
|
|
|
|
|
|
|
free(highlight_word);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Fix editbot, based on the assumption that edittop is correct. */
|
|
|
|
|
void fix_editbot(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
editbot = edittop;
|
|
|
|
|
for (i = 0; i < editwinrows && editbot->next != NULL; i++)
|
|
|
|
|
editbot = editbot->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
/* Dump the current file structure to stderr */
|
|
|
|
|
void dump_buffer(const filestruct *inptr) {
|
|
|
|
|
if (inptr == fileage)
|
|
|
|
|
fprintf(stderr, _("Dumping file buffer to stderr...\n"));
|
|
|
|
|
else if (inptr == cutbuffer)
|
|
|
|
|
fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
|
|
|
|
|
else
|
|
|
|
|
fprintf(stderr, _("Dumping a buffer to stderr...\n"));
|
|
|
|
|
|
|
|
|
|
while (inptr != NULL) {
|
|
|
|
|
fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
|
|
|
|
|
inptr = inptr->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
void dump_buffer_reverse(void) {
|
|
|
|
|
const filestruct *fileptr = filebot;
|
|
|
|
|
|
|
|
|
|
while (fileptr != NULL) {
|
|
|
|
|
fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
|
|
|
|
|
fileptr = fileptr->prev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#ifdef NANO_EXTRA
|
2002-11-04 16:05:42 +00:00
|
|
|
|
#define CREDIT_LEN 53
|
2002-07-21 15:44:13 +00:00
|
|
|
|
#define XLCREDIT_LEN 8
|
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
|
void do_credits(void)
|
|
|
|
|
{
|
2000-11-25 18:21:37 +00:00
|
|
|
|
int i, j = 0, k, place = 0, start_x;
|
2002-07-21 15:44:13 +00:00
|
|
|
|
|
2002-09-13 18:14:04 +00:00
|
|
|
|
const char *what;
|
|
|
|
|
const char *xlcredits[XLCREDIT_LEN];
|
2002-07-21 15:44:13 +00:00
|
|
|
|
|
2002-09-13 18:14:04 +00:00
|
|
|
|
const char *credits[CREDIT_LEN] = {
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"0", /* "The nano text editor" */
|
|
|
|
|
"1", /* "version" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
VERSION,
|
|
|
|
|
"",
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"2", /* "Brought to you by:" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Chris Allegretta",
|
|
|
|
|
"Jordi Mallach",
|
|
|
|
|
"Adam Rogoyski",
|
|
|
|
|
"Rob Siemborski",
|
|
|
|
|
"Rocco Corsi",
|
2002-02-15 19:17:02 +00:00
|
|
|
|
"David Lawrence Ramsey",
|
2002-11-04 16:05:42 +00:00
|
|
|
|
"David Benbennick",
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Ken Tyler",
|
|
|
|
|
"Sven Guckes",
|
|
|
|
|
"Florian K<>nig",
|
|
|
|
|
"Pauli Virtanen",
|
|
|
|
|
"Daniele Medri",
|
|
|
|
|
"Clement Laforet",
|
|
|
|
|
"Tedi Heriyanto",
|
|
|
|
|
"Bill Soudan",
|
|
|
|
|
"Christian Weisgerber",
|
|
|
|
|
"Erik Andersen",
|
|
|
|
|
"Big Gaute",
|
|
|
|
|
"Joshua Jensen",
|
|
|
|
|
"Ryan Krebs",
|
|
|
|
|
"Albert Chin",
|
|
|
|
|
"",
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"3", /* "Special thanks to:" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Plattsburgh State University",
|
|
|
|
|
"Benet Laboratories",
|
|
|
|
|
"Amy Allegretta",
|
|
|
|
|
"Linda Young",
|
|
|
|
|
"Jeremy Robichaud",
|
|
|
|
|
"Richard Kolb II",
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"4", /* "The Free Software Foundation" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Linus Torvalds",
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"5", /* "For ncurses:" */
|
2002-03-16 01:03:41 +00:00
|
|
|
|
"Thomas Dickey",
|
|
|
|
|
"Pavel Curtis",
|
|
|
|
|
"Zeyd Ben-Halim",
|
|
|
|
|
"Eric S. Raymond",
|
2002-07-21 15:44:13 +00:00
|
|
|
|
"6", /* "and anyone else we forgot..." */
|
|
|
|
|
"7", /* "Thank you for using nano!\n" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"", "", "", "",
|
|
|
|
|
"(c) 1999-2002 Chris Allegretta",
|
|
|
|
|
"", "", "", "",
|
2002-11-04 16:05:42 +00:00
|
|
|
|
"http://www.nano-editor.org/"
|
2000-11-24 20:45:14 +00:00
|
|
|
|
};
|
|
|
|
|
|
2002-07-21 15:44:13 +00:00
|
|
|
|
xlcredits[0] = _("The nano text editor");
|
|
|
|
|
xlcredits[1] = _("version ");
|
|
|
|
|
xlcredits[2] = _("Brought to you by:");
|
|
|
|
|
xlcredits[3] = _("Special thanks to:");
|
|
|
|
|
xlcredits[4] = _("The Free Software Foundation");
|
|
|
|
|
xlcredits[5] = _("For ncurses:");
|
|
|
|
|
xlcredits[6] = _("and anyone else we forgot...");
|
|
|
|
|
xlcredits[7] = _("Thank you for using nano!\n");
|
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
|
curs_set(0);
|
|
|
|
|
nodelay(edit, TRUE);
|
|
|
|
|
blank_bottombars();
|
|
|
|
|
mvwaddstr(topwin, 0, 0, hblank);
|
2000-11-25 18:21:37 +00:00
|
|
|
|
blank_edit();
|
|
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
wrefresh(topwin);
|
|
|
|
|
|
|
|
|
|
while (wgetch(edit) == ERR) {
|
2000-11-25 18:21:37 +00:00
|
|
|
|
for (k = 0; k <= 1; k++) {
|
|
|
|
|
blank_edit();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
|
|
|
|
|
i--) {
|
2000-11-25 18:21:37 +00:00
|
|
|
|
mvwaddstr(edit, i * 2 - k, 0, hblank);
|
|
|
|
|
|
2002-07-21 15:44:13 +00:00
|
|
|
|
if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
|
2000-11-25 18:21:37 +00:00
|
|
|
|
what = credits[place - (editwinrows / 2 - 1 - i)];
|
2002-07-21 15:44:13 +00:00
|
|
|
|
|
|
|
|
|
/* God I've missed hacking. If what is exactly
|
|
|
|
|
1 char long, it's a sentinel for a translated
|
|
|
|
|
string, so use that instead. This means no
|
|
|
|
|
thanking people with 1 character long names ;-) */
|
|
|
|
|
if (strlen(what) == 1)
|
|
|
|
|
what = xlcredits[atoi(what)];
|
|
|
|
|
} else
|
2000-11-25 18:21:37 +00:00
|
|
|
|
what = "";
|
|
|
|
|
|
2001-01-20 21:40:07 +00:00
|
|
|
|
start_x = COLS / 2 - strlen(what) / 2 - 1;
|
2000-11-25 18:21:37 +00:00
|
|
|
|
mvwaddstr(edit, i * 2 - k, start_x, what);
|
|
|
|
|
}
|
|
|
|
|
usleep(700000);
|
|
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
}
|
|
|
|
|
if (j < editwinrows / 2 - 1)
|
|
|
|
|
j++;
|
|
|
|
|
|
|
|
|
|
place++;
|
|
|
|
|
|
|
|
|
|
if (place >= CREDIT_LEN + editwinrows / 2)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodelay(edit, FALSE);
|
|
|
|
|
curs_set(1);
|
|
|
|
|
display_main_list();
|
|
|
|
|
total_refresh();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
}
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#endif
|