Пример #1
2
/* If scroll_only is FALSE, move up one line.  If scroll_only is TRUE,
 * scroll up one line without scrolling the cursor. */
void do_up(bool scroll_only)
{
    size_t was_column = xplustabs();

    /* If we're at the top of the file, or if scroll_only is TRUE and
     * the top of the file is onscreen, get out. */
    if (openfile->current == openfile->fileage ||
		(scroll_only && openfile->edittop == openfile->fileage))
	return;

    assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);

    /* Move the current line of the edit window up. */
    openfile->current = openfile->current->prev;
    openfile->current_x = actual_x(openfile->current->data,
					openfile->placewewant);

    /* When the cursor was on the first line of the edit window (or when just
     * scrolling without moving the cursor), scroll the edit window up -- one
     * line if we're in smooth scrolling mode, and half a page otherwise. */
    if (openfile->current->next == openfile->edittop || scroll_only)
	edit_scroll(UPWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
				1 : editwinrows / 2 + 1);

    /* If the lines weren't already redrawn, see if they need to be. */
    if (openfile->current_y > 0) {
	/* Redraw the prior line if it was horizontally scrolled. */
	if (need_horizontal_scroll(was_column, 0))
	    update_line(openfile->current->next, 0);
	/* Redraw the current line if it needs to be horizontally scrolled. */
	if (need_horizontal_scroll(0, xplustabs()))
	    update_line(openfile->current, openfile->current_x);
    }
}
Пример #2
1
/* Move down one page. */
void do_page_down(void)
{
    int i;

    /* If there's less than a page of text left on the screen, put the
     * cursor at the beginning of the last line of the file, and then
     * update the edit window. */
    if (openfile->current->lineno + editwinrows - 2 >=
	openfile->filebot->lineno) {
	do_last_line();
	return;
    }

    /* If we're not in smooth scrolling mode, put the cursor at the
     * beginning of the top line of the edit window, as Pico does. */
#ifndef NANO_TINY
    if (!ISSET(SMOOTH_SCROLL)) {
#endif
	openfile->current = openfile->edittop;
	openfile->placewewant = 0;
#ifndef NANO_TINY
    }
#endif

    for (i = editwinrows - 2; i > 0 && openfile->current !=
	openfile->filebot; i--)
	openfile->current = openfile->current->next;

    openfile->current_x = actual_x(openfile->current->data,
	openfile->placewewant);

    /* Scroll the edit window down a page. */
    edit_scroll(DOWN_DIR, editwinrows - 2);
}
Пример #3
1
Файл: move.c Проект: rofl0r/nano
/* If scroll_only is FALSE, move down one line.  If scroll_only is TRUE,
 * scroll down one line without scrolling the cursor. */
void do_down(
#ifndef NANO_TINY
	bool scroll_only
#else
	void
#endif
	)
{
    bool onlastline = FALSE;

    /* If we're at the bottom of the file, get out. */
    if (openfile->current == openfile->filebot)
	return;


    assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);

    /* Move the current line of the edit window down. */
    openfile->current = openfile->current->next;
    openfile->current_x = actual_x(openfile->current->data,
	openfile->placewewant);

    if (ISSET(SOFTWRAP)) {
	if (openfile->current->lineno - openfile->edittop->lineno >= maxrows)
	    onlastline = TRUE;
    }

    /* If scroll_only is FALSE and if we're on the first line of the
     * edit window, scroll the edit window down one line if we're in
     * smooth scrolling mode, or down half a page if we're not.  If
     * scroll_only is TRUE, scroll the edit window down one line
     * unconditionally. */
    if (onlastline || openfile->current_y == editwinrows - 1
#ifndef NANO_TINY
	|| scroll_only
#endif
	) {
	edit_scroll(DOWN_DIR,
#ifndef NANO_TINY
		(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
		editwinrows / 2 + 1);

	edit_refresh_needed = TRUE;
    }
    /* If we're above the last line of the edit window, update the line
     * we were on before and the line we're on now.  The former needs to
     * be redrawn if we're not on the first page, and the latter needs
     * to be drawn unconditionally. */
    if (ISSET(SOFTWRAP) || openfile->current_y < editwinrows - 1) {
	if (need_vertical_update(0))
	    update_line(openfile->current->prev, 0);
	update_line(openfile->current, openfile->current_x);
    }
}
Пример #4
1
Файл: move.c Проект: rofl0r/nano
/* If scroll_only is FALSE, move up one line.  If scroll_only is TRUE,
 * scroll up one line without scrolling the cursor. */
void do_up(
#ifndef NANO_TINY
	bool scroll_only
#else
	void
#endif
	)
{
    /* If we're at the top of the file, or if scroll_only is TRUE and
     * the top of the file is onscreen, get out. */
    if (openfile->current == openfile->fileage
#ifndef NANO_TINY
	|| (scroll_only && openfile->edittop == openfile->fileage)
#endif
	)
	return;

    assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);

    /* Move the current line of the edit window up. */
    openfile->current = openfile->current->prev;
    openfile->current_x = actual_x(openfile->current->data,
	openfile->placewewant);

    /* If scroll_only is FALSE and if we're on the first line of the
     * edit window, scroll the edit window up one line if we're in
     * smooth scrolling mode, or up half a page if we're not.  If
     * scroll_only is TRUE, scroll the edit window up one line
     * unconditionally. */
    if (openfile->current_y == 0 || (ISSET(SOFTWRAP) && openfile->edittop->lineno == openfile->current->next->lineno)
#ifndef NANO_TINY
	|| scroll_only
#endif
	)
	edit_scroll(UP_DIR,
#ifndef NANO_TINY
		(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
#endif
		editwinrows / 2 + 1);

    /* If we're below the first line of the edit window, update the
     * line we were on before and the line we're on now.  The former
     * needs to be redrawn if we're not on the first page, and the
     * latter needs to be drawn unconditionally. */
    if (openfile->current_y > 0) {
	if (need_vertical_update(0))
	    update_line(openfile->current->next, 0);
	update_line(openfile->current, openfile->current_x);
    }
}
Пример #5
0
/* Move down one page. */
void do_page_down(void)
{
    int i, mustmove;

    /* If the cursor is less than a page away from the bottom of the file,
     * put it at the end of the last line. */
    if (openfile->current->lineno + maxrows - 2 >= openfile->filebot->lineno) {
	do_last_line();
	return;
    }

    /* If we're not in smooth scrolling mode, put the cursor at the
     * beginning of the top line of the edit window, as Pico does. */
    if (!ISSET(SMOOTH_SCROLL)) {
	openfile->current = openfile->edittop;
	openfile->placewewant = openfile->current_y = 0;
    }

    mustmove = (maxrows < 3) ? 1 : maxrows - 2;

    for (i = mustmove; i > 0 && openfile->current != openfile->filebot; i--) {
	openfile->current = openfile->current->next;
#ifdef DEBUG
	fprintf(stderr, "paging down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
#endif

    }

    openfile->current_x = actual_x(openfile->current->data,
					openfile->placewewant);

    /* Scroll the edit window down a page. */
    adjust_viewport(STATIONARY);
    refresh_needed = TRUE;
}
Пример #6
0
/* Handle a mouse click on the statusbar prompt or the shortcut list. */
int do_statusbar_mouse(void)
{
    int mouse_x, mouse_y;
    int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);

    /* We can click on the statusbar window text to move the cursor. */
    if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x,
	FALSE)) {
	size_t start_col;

	assert(prompt != NULL);

	start_col = strlenpt(prompt) + 2;

	/* Move to where the click occurred. */
	if (mouse_x >= start_col && mouse_y == 0) {
	    size_t pww_save = statusbar_pww;

	    statusbar_x = actual_x(answer,
			get_statusbar_page_start(start_col, start_col +
			statusbar_xplustabs()) + mouse_x - start_col);
	    statusbar_pww = statusbar_xplustabs();

	    if (need_statusbar_update(pww_save))
		update_statusbar_line(answer, statusbar_x);
	}
    }

    return retval;
}
Пример #7
0
/* Repaint the statusbar when getting a character in
 * get_prompt_string().  The statusbar text line will be displayed
 * starting with curranswer[index]. */
void update_statusbar_line(const char *curranswer, size_t index)
{
    size_t start_col, page_start;
    char *expanded;

    assert(prompt != NULL && index <= strlen(curranswer));

    start_col = strlenpt(prompt) + 2;
    index = strnlenpt(curranswer, index);
    page_start = get_statusbar_page_start(start_col, start_col + index);

    if (interface_color_pair[TITLE_BAR].bright)
	wattron(bottomwin, A_BOLD);
    wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);

    blank_statusbar();

    mvwaddnstr(bottomwin, 0, 0, prompt, actual_x(prompt, COLS - 2));
    waddch(bottomwin, ':');
    waddch(bottomwin, (page_start == 0) ? ' ' : '$');

    expanded = display_string(curranswer, page_start, COLS - start_col -
	1, FALSE);
    waddstr(bottomwin, expanded);
    free(expanded);

    wattroff(bottomwin, A_BOLD);
    wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
    statusbar_pww = statusbar_xplustabs();
    reset_statusbar_cursor();
    wnoutrefresh(bottomwin);
}
Пример #8
0
/* 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 at most len characters, even if len is very small and
 * keystroke and desc are long.  Note that waddnstr(,,(size_t)-1) adds
 * the whole string!  We do not bother padding the entry with blanks. */
void onekey(const std::string& keystroke, const std::string& desc, size_t len)
{
	size_t keystroke_len = keystroke.length() + 1;

	set_color(bottomwin, interface_colors[KEY_COMBO]);
	waddnstr(bottomwin, keystroke.c_str(), actual_x(keystroke.c_str(), len));
	clear_color(bottomwin, interface_colors[KEY_COMBO]);

	if (len > keystroke_len) {
		len -= keystroke_len;
	} else {
		len = 0;
	}

	if (len > 0) {
		waddch(bottomwin, ' ');
		waddnstr(bottomwin, desc.c_str(), actual_x(desc.c_str(), len));
	}
}
Пример #9
0
Файл: move.c Проект: ris21/yoda
/* Move up one page. */
void do_page_up(void)
{
    int i, skipped = 0;

    /* If there's less than a page of text left on the screen, put the
     * cursor at the beginning of the first line of the file, and then
     * update the edit window. */
    if (openfile->current->lineno == 1 || (
#ifndef NANO_TINY
	!ISSET(SOFTWRAP) &&
#endif
	openfile->current->lineno <= editwinrows - 2)) {
	do_first_line();
	return;
    }

    /* If we're not in smooth scrolling mode, put the cursor at the
     * beginning of the top line of the edit window, as Pico does. */
#ifndef NANO_TINY
    if (!ISSET(SMOOTH_SCROLL)) {
#endif
	openfile->current = openfile->edittop;
	openfile->placewewant = openfile->current_y = 0;
#ifndef NANO_TINY
    }
#endif

    for (i = editwinrows - 2; i - skipped > 0 && openfile->current !=
	openfile->fileage; i--) {
	openfile->current = openfile->current->prev;
#ifndef NANO_TINY
	if (ISSET(SOFTWRAP) && openfile->current) {
	    skipped += strlenpt(openfile->current->data) / COLS;
#ifdef DEBUG
	    fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %lu\n",
			i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data));
#endif
	}
#endif
    }

    openfile->current_x = actual_x(openfile->current->data,
	openfile->placewewant);

#ifdef DEBUG
    fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n",
	(unsigned long)openfile->current->lineno, skipped);
#endif

    /* Scroll the edit window up a page. */
    edit_update(NONE);
}
Пример #10
0
/* Indicate on the statusbar that the string at str was not found by the
 * last search. */
void not_found_msg(const char *str)
{
    char *disp;
    int numchars;

    assert(str != NULL);

    disp = display_string(str, 0, (COLS / 2) + 1, FALSE);
    numchars = actual_x(disp, mbstrnlen(disp, COLS / 2));

    statusbar(_("\"%.*s%s\" not found"), numchars, disp,
	(disp[numchars] == '\0') ? "" : "...");

    free(disp);
}
Пример #11
0
/* Move up one page. */
void do_page_up(void)
{
    int i, mustmove, skipped = 0;

    /* If the cursor is less than a page away from the top of the file,
     * put it at the beginning of the first line. */
    if (openfile->current->lineno == 1 || (!ISSET(SOFTWRAP) &&
		openfile->current->lineno <= editwinrows - 2)) {
	do_first_line();
	return;
    }

    /* If we're not in smooth scrolling mode, put the cursor at the
     * beginning of the top line of the edit window, as Pico does. */
    if (!ISSET(SMOOTH_SCROLL)) {
	openfile->current = openfile->edittop;
	openfile->placewewant = openfile->current_y = 0;
    }

    mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;

    for (i = mustmove; i - skipped > 0 && openfile->current != openfile->fileage; i--) {
	openfile->current = openfile->current->prev;
#ifndef NANO_TINY
	if (ISSET(SOFTWRAP) && openfile->current) {
	    skipped += strlenpt(openfile->current->data) / editwincols;
#ifdef DEBUG
	    fprintf(stderr, "paging up: i = %d, skipped = %d based on line %ld len %lu\n",
			i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data));
#endif
	}
#endif
    }

    openfile->current_x = actual_x(openfile->current->data,
					openfile->placewewant);

    /* Scroll the edit window up a page. */
    adjust_viewport(STATIONARY);
    refresh_needed = TRUE;
}
Пример #12
0
Файл: move.c Проект: rofl0r/nano
/* Move down one page. */
void do_page_down(void)
{
    int i;

    /* If there's less than a page of text left on the screen, put the
     * cursor at the beginning of the last line of the file, and then
     * update the edit window. */
    if (openfile->current->lineno + maxrows - 2 >=
	openfile->filebot->lineno) {
	do_last_line();
	return;
    }

    /* If we're not in smooth scrolling mode, put the cursor at the
     * beginning of the top line of the edit window, as Pico does. */
#ifndef NANO_TINY
    if (!ISSET(SMOOTH_SCROLL)) {
#endif
	openfile->current = openfile->edittop;
	openfile->placewewant = openfile->current_y = 0;
#ifndef NANO_TINY
    }
#endif

    for (i = maxrows - 2; i > 0 && openfile->current !=
	openfile->filebot; i--) {
	openfile->current = openfile->current->next;
#ifdef DEBUG
    fprintf(stderr, "do_page_down: moving to line %lu\n", (unsigned long) openfile->current->lineno);
#endif

    }

    openfile->current_x = actual_x(openfile->current->data,
	openfile->placewewant);

    /* Scroll the edit window down a page. */
    edit_update(NONE);
}
Пример #13
0
/* Highlight the current word being replaced or spell checked.  We
 * expect word to have tabs and control characters expanded. */
void do_replace_highlight(bool highlight, const char *word)
{
	size_t y = xplustabs(), word_len = strlenpt(word);

	y = get_page_start(y) + COLS - y;
	/* Now y is the number of columns that we can display on this
	 * line. */

	assert(y > 0);

	if (word_len > y) {
		y--;
	}

	reset_cursor();
	wnoutrefresh(edit);

	if (highlight) {
		wattron(edit, highlight_attribute);
	}

	/* This is so we can show zero-length matches. */
	if (word_len == 0) {
		waddch(edit, ' ');
	} else {
		waddnstr(edit, word, actual_x(word, y));
	}

	if (word_len > y) {
		waddch(edit, '$');
	}

	if (highlight) {
		wattroff(edit, highlight_attribute);
	}
}
Пример #14
0
void titlebar(const char *path)
{
	int space = COLS;
	/* The space we have available for display. */
	size_t verlen = strlenpt(PACKAGE_STRING) + 1;
	/* The length of the version message in columns, plus one for
	 * padding. */
	const char *prefix;
	/* "DIR:", "File:", or "New Buffer".  Goes before filename. */
	size_t prefixlen;
	/* The length of the prefix in columns, plus one for padding. */
	const char *state;
	/* "Modified", "View", or "".  Shows the state of this
	 * buffer. */
	ssize_t statelen = 0;
	/* The length of the state in columns, or the length of
	 * "Modified" if the state is blank and we're not in the file
	 * browser. */
	char *exppath = NULL;
	/* The filename, expanded for display. */
	bool newfie = false;
	/* Do we say "New Buffer"? */
	bool dots = false;
	/* Do we put an ellipsis before the path? */

	set_color(topwin, interface_colors[TITLE_BAR]);

	blank_titlebar();

	/* space has to be at least 4: two spaces before the version message,
	 * at least one character of the version message, and one space
	 * after the version message. */
	if (space < 4) {
		space = 0;
	} else {
		/* Limit verlen to 1/3 the length of the screen in columns,
		 * minus three columns for spaces. */
		if (verlen > (COLS / 3) - 3) {
			verlen = (COLS / 3) - 3;
		}
	}

	if (space >= 4) {
		/* Add a space after the version message, and account for both
		 * it and the two spaces before it. */
		mvwaddnstr(topwin, 0, 2, PACKAGE_STRING, actual_x(PACKAGE_STRING, verlen));
		verlen += 3;

		/* Account for the full length of the version message. */
		space -= verlen;
	}

	/* Don't display the state if we're in the file browser. */
	if (path != NULL) {
		state = "";
	} else {
		state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ? _("View") : "";
	}

	statelen = strlenpt((*state == '\0' && path == NULL) ? _("Modified") : state);

	/* If possible, add a space before state. */
	if (space > 0 && statelen < space) {
		statelen++;
	} else {
		goto the_end;
	}

	/* path should be a directory if we're in the file browser. */
	if (path != NULL) {
		prefix = _("DIR:");
	} else {
		if (openfile->filename[0] == '\0') {
			prefix = _("New Buffer");
			newfie = true;
		} else {
			prefix = _("File:");
		}
	}

	prefixlen = strnlenpt(prefix, space - statelen) + 1;

	/* If newfie is false, add a space after prefix. */
	if (!newfie && prefixlen + statelen < space) {
		prefixlen++;
	}

	/* If we're not in the file browser, set path to the current
	 * filename. */
	if (path == NULL) {
		path = openfile->filename.c_str();
	}

	/* Account for the full lengths of the prefix and the state. */
	if (space >= prefixlen + statelen) {
		space -= prefixlen + statelen;
	} else {
		space = 0;
	}
	/* space is now the room we have for the filename. */

	if (!newfie) {
		size_t lenpt = strlenpt(path), start_col;

		/* Don't set dots to true if we have fewer than eight columns
		 * (i.e. one column for padding, plus seven columns for a
		 * filename). */
		dots = (space >= 8 && lenpt >= space);

		if (dots) {
			start_col = lenpt - space + 3;
			space -= 3;
		} else {
			start_col = 0;
		}

		exppath = display_string(path, start_col, space, false);
	}

	/* If dots is true, we will display something like "File:
	 * ...ename". */
	if (dots) {
		mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix, prefixlen));
		if (space <= -3 || newfie) {
			goto the_end;
		}
		waddch(topwin, ' ');
		waddnstr(topwin, "...", space + 3);
		if (space <= 0) {
			goto the_end;
		}
		waddstr(topwin, exppath);
	} else {
		size_t exppathlen = newfie ? 0 : strlenpt(exppath);
		/* The length of the expanded filename. */

		/* There is room for the whole filename, so we center it. */
		mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3), prefix, actual_x(prefix, prefixlen));
		if (!newfie) {
			waddch(topwin, ' ');
			waddstr(topwin, exppath);
		}
	}

the_end:
	free(exppath);

	if (state[0] != '\0') {
		if (statelen >= COLS - 1) {
			mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
		} else {
			assert(COLS - statelen - 1 >= 0);

			mvwaddnstr(topwin, 0, COLS - statelen - 1, state, actual_x(state, statelen));
		}
	}

	clear_color(topwin, interface_colors[TITLE_BAR]);

	wnoutrefresh(topwin);
	reset_cursor();
	wnoutrefresh(edit);
}
Пример #15
0
/* Ask a question on the statusbar.  The prompt will be stored in the
 * static prompt, which should be NULL initially, and the answer will be
 * stored in the answer global.  Returns -1 on aborted enter, -2 on a
 * blank string, and 0 otherwise, the valid shortcut key caught.
 * curranswer is any editable text that we want to put up by default,
 * and refresh_func is the function we want to call to refresh the edit
 * window.
 *
 * The allow_tabs parameter indicates whether we should allow tabs to be
 * interpreted.  The allow_files parameter indicates whether we should
 * allow all files (as opposed to just directories) to be tab
 * completed. */
int do_prompt(bool allow_tabs,
#ifndef DISABLE_TABCOMP
	bool allow_files,
#endif
	int menu, const char *curranswer,
#ifndef DISABLE_HISTORIES
	linestruct **history_list,
#endif
	void (*refresh_func)(void), const char *msg, ...)
{
    va_list ap;
    int retval;
    functionptrtype func;
#ifndef DISABLE_TABCOMP
    bool list = FALSE;
#endif

    /* prompt has been freed and set to NULL unless the user resized
     * while at the statusbar prompt. */
    free(prompt);

    prompt = charalloc(((COLS - 4) * mb_cur_max()) + 1);

    bottombars(menu);

    va_start(ap, msg);
    vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
    va_end(ap);
    null_at(&prompt, actual_x(prompt, COLS - 4));

    func = get_prompt_string(&retval, allow_tabs,
#ifndef DISABLE_TABCOMP
	allow_files,
	&list,
#endif
	curranswer,
#ifndef DISABLE_HISTORIES
	history_list,
#endif
	refresh_func);

    free(prompt);
    prompt = NULL;

    /* We're done with the prompt, so save the statusbar cursor
     * position. */
    old_statusbar_x = statusbar_x;
    old_pww = statusbar_pww;

    /* If we left the prompt via Cancel or Enter, set the return value
     * properly. */
    if (func == do_cancel)
	retval = -1;
    else if (func == do_enter_void)
	retval = (*answer == '\0') ? -2 : 0;

    blank_statusbar();
    wnoutrefresh(bottomwin);

#ifdef DEBUG
    fprintf(stderr, "answer = \"%s\"\n", answer);
#endif

#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 that they're
     * cleared off. */
    if (list)
	refresh_func();
#endif

    return retval;
}
Пример #16
0
int do_dictionary_prompt(bool all, const char *msg, char *str)
{
    s_list l;
    s_node *p;
    int ok = -2, width = 16;
    const char *yesstr;		/* String of Yes characters accepted. */
    const char *nostr;		/* Same for No. */
    const char *allstr;		/* And All, surprise! */
    int u;
    char **thisarray = (char **)malloc(sizeof(char)*5);
	for(u = 0; u < 5; u++)
		thisarray[u] = (char *)malloc(sizeof(char)*16);
    thisarray = thisfunc(str);
    int oldmenu = currmenu;
    char but[16];
    int i, j = 0;
    int count = 0;
    int t = 0;
    int bs = 0;
    char buf[16];
    strcpy(buf, str);
    int tp;
    int we = 0, wc = 0;
    
    tp = typepos();
    
    assert(msg != NULL);
    
    s_init(&l);
    u = 0;
    while(u < 5) {
	s_append(&l, thisarray[u]);
	u++;
    }
    /*Now partial matched list is prepared*/
           p = l.head;
           

    if(str == NULL){
 
        count = 0;

        
        while(p){
            count++;
            p = p->next;
        }
    }
    
    //count=5;

    p = l.head;


    do {
	int kbinput;
	functionptrtype func;
        i = 0;
#ifndef DISABLE_MOUSE
	int mouse_x, mouse_y;
#endif

	if (!ISSET(NO_HELP)) {
	    char shortstr[3];
		/* Temporary string for (translated) " Y", " N" and " A". */

	    if (COLS < 32)
		width = COLS / 2;

	    /* Clear the shortcut list from the bottom of the screen. */
	    blank_bottombars();

	    /* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */


	    if (all) {
		shortstr[1] = allstr[0];
		wmove(bottomwin, 1, width);
		onekey(shortstr, _("All"), width);
	    }

            for(i = 0; i < count && i < 5; i++){
                sprintf(but, "%d", i + 1);
                if(i == 0) wmove(bottomwin, 1, 0);
                else wmove(bottomwin, 1, i * width);
                if(p){
                    onekey(but, p->word, width);
                    p = p->next;
                }
                j++;
            }

	    wmove(bottomwin, 1, i * width);
	    onekey("^C", _("Cancel"), width);
	}

	if (interface_color_pair[TITLE_BAR].bright)
	    wattron(bottomwin, A_BOLD);
	wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);

	blank_statusbar();
	mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));

	wattroff(bottomwin, A_BOLD);
	wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);

	/* Refresh edit window and statusbar before getting input. */
	wnoutrefresh(edit);
	wnoutrefresh(bottomwin);

	currmenu = MYESNO;
	kbinput = get_kbinput(bottomwin);

#ifndef NANO_TINY
	if (kbinput == KEY_WINCH)
	    continue;
#endif
        /*49 is 1, 50 is 2 and so on*/

	func = func_from_key(&kbinput);

	if (func == do_cancel){
	    ok = 0;
            return ok;
        }
  
        if(kbinput == 's'){
            if(i == 5) {
                continue;
            }
        }
        if(kbinput <= '0' || kbinput > '0' + count) return -1;
        
        if(kbinput > '0' && kbinput <= '0' + count){
            p = l.head;
            i = kbinput - '0' - 1;
            if(j > 5) t = j - 5 + i;
            else t = i;

            while(t--) if(p){
                        p = p->next;
                        }
            
            if(tp == 1 || tp == 2){
                bs = strlen(str);
                while(bs--) do_backspace();
            }
            

            if(tp == 6 || tp == 7){
                if(str != NULL){


                    we = openfile->current_x;

                    while(openfile->current->data[we] != ' ' && openfile->current->data[we] != '\00'){
                     we++;
                        wc++;
                        do_right();
                    }

                    we--;
                    while(openfile->current->data[we] != ' ' && openfile->current->data[we] != '\00'){

                        do_backspace();
                        we--;
                    }
                }
            }
            
            
            do_output(p->word, strlen(p->word), FALSE);
            return tp;
        }


	else if (func == total_refresh) {
	    total_redraw();
	    continue;
	} else {
		/* Look for the kbinput in the Yes, No and (optionally)
		 * All strings. */
		if (strchr(yesstr, kbinput) != NULL)
		    ok = 1;
		else if (strchr(nostr, kbinput) != NULL)
		    ok = 0;
		else if (all && strchr(allstr, kbinput) != NULL)
		    ok = 2;
	}
        i = 0;
        p = l.head;
        
    } while (ok == -2);

    currmenu = oldmenu;
    return ok;
}
Пример #17
0
/* edit_draw() takes care of the job of actually painting a line into
 * the edit window.  fileptr is the line to be painted, at row line of
 * the window.  converted is the actual string to be written to the
 * window, with tabs and control characters replaced by strings of
 * regular characters.  start is the column number of the first
 * character of this page.  That is, the first character of converted
 * corresponds to character number actual_x(fileptr->data, start) of the
 * line. */
void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start)
{
	size_t startpos = actual_x(fileptr->data, start);
	/* The position in fileptr->data of the leftmost character
	 * that displays at least partially on the window. */
	size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
	/* The position in fileptr->data of the first character that is
	 * completely off the window to the right.
	 *
	 * Note that endpos might be beyond the null terminator of the
	 * string. */

	assert(openfile != openfiles.end() && fileptr != NULL && converted != NULL);
	assert(strlenpt(converted) <= COLS);

	/* Just paint the string in any case (we'll add color or reverse on
	 * just the text that needs it). */
	mvwaddstr(edit, line, 0, converted);
	/* Tell ncurses to really redraw the line without trying to optimize
	 * for what it thinks is already there, because it gets it wrong in
	 * the case of a wide character in column zero. */
#ifndef USE_SLANG
	wredrawln(edit, line, 1);
#endif

	/* If color syntaxes are available and turned on, we need to display
	 * them. */
	if (!openfile->colorstrings.empty() && !ISSET(NO_COLOR_SYNTAX)) {
		/* Set up multi-line color data for this line if it's not yet calculated  */
		if (fileptr->multidata.empty() && openfile->syntax && openfile->syntax->nmultis > 0) {
			fileptr->multidata.resize(openfile->syntax->nmultis, -1); // assume that '-1' applies until we know otherwise
		}
		for (auto tmpcolor : openfile->colorstrings) {
			int x_start;
			/* Starting column for mvwaddnstr.  Zero-based. */
			int paintlen = 0;
			/* Number of chars to paint on this line.  There are
			 * COLS characters on a whole line. */
			size_t index;
			/* Index in converted where we paint. */
			regmatch_t startmatch;
			/* Match position for start_regex. */
			regmatch_t endmatch;
			/* Match position for end_regex. */

			if (tmpcolor->bright) {
				wattron(edit, A_BOLD);
			}
			if (tmpcolor->underline) {
				wattron(edit, A_UNDERLINE);
			}
			wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
			/* Two notes about regexec().  A return value of zero means
			 * that there is a match.  Also, rm_eo is the first
			 * non-matching character after the match. */

			/* First case,tmpcolor is a single-line expression. */
			if (tmpcolor->end == NULL) {
				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 e.g. C
				 * strings correctly. */
				while (k < endpos) {
					/* Note the fifth parameter to regexec().  It says
					 * not to match the beginning-of-line character
					 * unless k is zero.  If regexec() returns
					 * REG_NOMATCH, there are no more matches in the
					 * line. */
					if (regexec(tmpcolor->start, &fileptr->data[k], 1, &startmatch, (k == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH) {
						break;
					}


					/* Translate the match to the beginning of the
					 * line. */
					startmatch.rm_so += k;
					startmatch.rm_eo += k;

					/* Skip over a zero-length regex match. */
					if (startmatch.rm_so == startmatch.rm_eo) {
						startmatch.rm_eo++;
					} else if (startmatch.rm_so < endpos && startmatch.rm_eo > startpos) {
						x_start = (startmatch.rm_so <= startpos) ? 0 : strnlenpt(fileptr->data, startmatch.rm_so) - start;

						index = actual_x(converted, x_start);

						paintlen = actual_x(converted + index, strnlenpt(fileptr->data, startmatch.rm_eo) - start - x_start);

						assert(0 <= x_start && 0 <= paintlen);

						mvwaddnstr(edit, line, x_start, converted + index, paintlen);
					}
					k = startmatch.rm_eo;
				}
			} else if (!fileptr->multidata.empty() && fileptr->multidata[tmpcolor->id] != CNONE) {
				/* This is a multi-line regex.  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. */
				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;
				short md = fileptr->multidata[tmpcolor->id];

				if (md == -1) {
					fileptr->multidata[tmpcolor->id] = CNONE;    /* until we find out otherwise */
				} else if (md == CNONE) {
					unset_formatting(tmpcolor);
					continue;
				} else if (md == CWHOLELINE) {
					mvwaddnstr(edit, line, 0, converted, -1);
					unset_formatting(tmpcolor);
					continue;
				} else if (md == CBEGINBEFORE) {
					regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
					paintlen = actual_x(converted, strnlenpt(fileptr->data, endmatch.rm_eo) - start);
					mvwaddnstr(edit, line, 0, converted, paintlen);
					unset_formatting(tmpcolor);
					continue;
				}

				while (start_line != NULL && regexec(tmpcolor->start, start_line->data, 1, &startmatch, 0) == REG_NOMATCH) {
					/* If there is an end on this line, there is no need
					 * to look for starts on earlier lines. */
					if (regexec(tmpcolor->end, start_line->data, 0, NULL, 0) == 0) {
						goto step_two;
					}
					start_line = start_line->prev;
				}

				/* If the found start has been qualified as an end earlier, believe it and skip to the next step. */
				if (start_line != NULL && !start_line->multidata.empty() && start_line->multidata[tmpcolor->id] == CBEGINBEFORE) {
					goto step_two;
				}

				/* Skip over a zero-length regex match. */
				if (startmatch.rm_so == startmatch.rm_eo) {
					startmatch.rm_eo++;
				} else {
					/* 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 (true) {
						start_col += startmatch.rm_so;
						startmatch.rm_eo -= startmatch.rm_so;
						if (regexec(tmpcolor->end, start_line->data + start_col + startmatch.rm_eo, 0, NULL, (start_col + startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH) {
							/* No end found after this start. */
							break;
						}
						start_col++;
						if (regexec(tmpcolor->start, start_line->data + start_col, 1, &startmatch, REG_NOTBOL) == REG_NOMATCH) {
							/* No later start on this line. */
							goto step_two;
						}
					}
					/* 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;
					while (end_line != NULL && regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0) == REG_NOMATCH) {
						end_line = end_line->next;
					}

					/* No end found, or it is too early. */
					if (end_line == NULL || (end_line == fileptr && endmatch.rm_eo <= startpos)) {
						goto step_two;
					}

					/* Now paint the start of fileptr.  If the start of
					 * fileptr is on a different line from the end,
					 * paintlen is -1, meaning that everything on the
					 * line gets painted.  Otherwise, paintlen is the
					 * expanded location of the end of the match minus
					 * the expanded location of the beginning of the
					 * page. */
					if (end_line != fileptr) {
						paintlen = -1;
						fileptr->multidata[tmpcolor->id] = CWHOLELINE;
					} else {
						paintlen = actual_x(converted, strnlenpt(fileptr->data, endmatch.rm_eo) - start);
						fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
					}
					mvwaddnstr(edit, line, 0, converted, paintlen);
					/* If the whole line has been painted, don't bother looking for any more starts. */
					if (paintlen < 0) {
						continue;
					}
step_two:
					/* Second step, we look for starts on this line. */
					start_col = 0;

					while (start_col < endpos) {
						if (regexec(tmpcolor->start, fileptr->data + start_col, 1, &startmatch, (start_col == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH || start_col + startmatch.rm_so >= endpos) {
							/* 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 <= startpos) ? 0 : strnlenpt(fileptr->data, startmatch.rm_so) - start;

						index = actual_x(converted, x_start);

						if (regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo, 1, &endmatch, (startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) == 0) {
							/* 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 > startpos && endmatch.rm_eo > startmatch.rm_so) {
								paintlen = actual_x(converted + index, strnlenpt(fileptr->data, endmatch.rm_eo) - start - x_start);

								assert(0 <= x_start && x_start < COLS);

								mvwaddnstr(edit, line, x_start, converted + index, paintlen);
								if (paintlen > 0) {
									fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
								}

							}
						} else {
							/* There is no end on this line.  But we
							 * haven't yet looked for one on later
							 * lines. */
							end_line = fileptr->next;

							while (end_line != NULL && regexec(tmpcolor->end, end_line->data, 0, NULL, 0) == REG_NOMATCH) {
								end_line = end_line->next;
							}

							if (end_line != NULL) {
								assert(0 <= x_start && x_start < COLS);

								mvwaddnstr(edit, line, x_start, converted + index, -1);
								/* We painted to the end of the line, so
								 * don't bother checking any more
								 * starts. */
								fileptr->multidata[tmpcolor->id] = CENDAFTER;
								break;
							}
						}
						start_col = startmatch.rm_so + 1;
					}
				}
			}
			unset_formatting(tmpcolor);
		}
	}

	/* If the mark is on, we need to display it. */
	if (openfile->mark_set && (fileptr->lineno <=
	                           openfile->mark_begin->lineno || fileptr->lineno <=
	                           openfile->current->lineno) && (fileptr->lineno >=
	                                   openfile->mark_begin->lineno || fileptr->lineno >=
	                                   openfile->current->lineno)) {
		/* fileptr is at least partially selected. */
		const filestruct *top;
		/* Either current or mark_begin, whichever is first. */
		size_t top_x;
		/* current_x or mark_begin_x, corresponding to top. */
		const filestruct *bot;
		size_t bot_x;
		int x_start;
		/* Starting column for mvwaddnstr().  Zero-based. */
		int paintlen;
		/* Number of characters to paint on this line.  There are
		 * COLS characters on a whole line. */
		size_t index;
		/* Index in converted where we paint. */

		mark_order(&top, &top_x, &bot, &bot_x, NULL);

		if (top->lineno < fileptr->lineno || top_x < startpos) {
			top_x = startpos;
		}
		if (bot->lineno > fileptr->lineno || bot_x > endpos) {
			bot_x = endpos;
		}

		/* The selected bit of fileptr is on this page. */
		if (top_x < endpos && bot_x > startpos) {
			assert(startpos <= top_x);

			/* x_start is the expanded location of the beginning of the
			 * mark minus the beginning of the page. */
			x_start = strnlenpt(fileptr->data, top_x) - start;

			/* If the end of the mark is off the page, paintlen is -1,
			 * meaning that everything on the line gets painted.
			 * Otherwise, paintlen is the expanded location of the end
			 * of the mark minus the expanded location of the beginning
			 * of the mark. */
			if (bot_x >= endpos) {
				paintlen = -1;
			} else
				paintlen = strnlenpt(fileptr->data, bot_x) - (x_start + start);

			/* If x_start is before the beginning of the page, shift
			 * paintlen x_start characters to compensate, and put
			 * x_start at the beginning of the page. */
			if (x_start < 0) {
				paintlen += x_start;
				x_start = 0;
			}

			assert(x_start >= 0 && x_start <= strlen(converted));

			index = actual_x(converted, x_start);

			if (paintlen > 0) {
				paintlen = actual_x(converted + index, paintlen);
			}

			set_color(edit, interface_colors[FUNCTION_TAG]);
			mvwaddnstr(edit, line, x_start, converted + index, paintlen);
			clear_color(edit, interface_colors[FUNCTION_TAG]);
		}
	}
}
Пример #18
0
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
 * on the statusbar.  Return 1 for Yes, 0 for No, 2 for All (if all is
 * TRUE when passed in), and -1 for Cancel. */
int do_yesno_prompt(bool all, const char *msg)
{
    int ok = -2, width = 16;
    const char *yesstr;		/* String of Yes characters accepted. */
    const char *nostr;		/* Same for No. */
    const char *allstr;		/* And All, surprise! */
    int oldmenu = currmenu;

    assert(msg != NULL);

    /* yesstr, nostr, and allstr are strings of any length.  Each string
     * consists of all single-byte characters accepted as valid
     * characters for that value.  The first value will be the one
     * displayed in the shortcuts. */
    /* TRANSLATORS: For the next three strings, if possible, specify
     * the single-byte shortcuts for both your language and English.
     * For example, in French: "OoYy" for "Oui". */
    yesstr = _("Yy");
    nostr = _("Nn");
    allstr = _("Aa");

    do {
	int kbinput;
	functionptrtype func;
#ifndef DISABLE_MOUSE
	int mouse_x, mouse_y;
#endif

	if (!ISSET(NO_HELP)) {
	    char shortstr[3];
		/* Temporary string for (translated) " Y", " N" and " A". */

	    if (COLS < 32)
		width = COLS / 2;

	    /* Clear the shortcut list from the bottom of the screen. */
	    blank_bottombars();

	    /* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
	    sprintf(shortstr, " %c", yesstr[0]);
	    wmove(bottomwin, 1, 0);
	    onekey(shortstr, _("Yes"), width);

	    if (all) {
		shortstr[1] = allstr[0];
		wmove(bottomwin, 1, width);
		onekey(shortstr, _("All"), width);
	    }

	    shortstr[1] = nostr[0];
	    wmove(bottomwin, 2, 0);
	    onekey(shortstr, _("No"), width);

	    wmove(bottomwin, 2, width);
	    onekey("^C", _("Cancel"), width);
	}

	if (interface_color_pair[TITLE_BAR].bright)
	    wattron(bottomwin, A_BOLD);
	wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);

	blank_statusbar();
	mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));

	wattroff(bottomwin, A_BOLD);
	wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);

	/* Refresh edit window and statusbar before getting input. */
	wnoutrefresh(edit);
	wnoutrefresh(bottomwin);

	currmenu = MYESNO;
	kbinput = get_kbinput(bottomwin);

#ifndef NANO_TINY
	if (kbinput == KEY_WINCH)
	    continue;
#endif

	func = func_from_key(&kbinput);

	if (func == do_cancel)
	    ok = -1;
#ifndef DISABLE_MOUSE
	else if (kbinput == KEY_MOUSE) {
		/* We can click on the Yes/No/All shortcut list to
		 * select an answer. */
		if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 &&
			wmouse_trafo(bottomwin, &mouse_y, &mouse_x,
			FALSE) && mouse_x < (width * 2) &&
			mouse_y > 0) {
		    int x = mouse_x / width;
			/* Calculate the x-coordinate relative to the
			 * two columns of the Yes/No/All shortcuts in
			 * bottomwin. */
		    int y = mouse_y - 1;
			/* Calculate the y-coordinate relative to the
			 * beginning of the Yes/No/All shortcuts in
			 * bottomwin, i.e. with the sizes of topwin,
			 * edit, and the first line of bottomwin
			 * subtracted out. */

		    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;
		}
	}
#endif /* !DISABLE_MOUSE */
	else if (func == total_refresh) {
	    total_redraw();
	    continue;
	} else {
		/* Look for the kbinput in the Yes, No and (optionally)
		 * All strings. */
		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);

    currmenu = oldmenu;
    return ok;
}
Пример #19
0
/* If scroll_only is FALSE, move down one line.  If scroll_only is TRUE,
 * scroll down one line without scrolling the cursor. */
void do_down(bool scroll_only)
{
#ifndef NANO_TINY
    int amount = 0, enough;
    filestruct *topline;
#endif
    size_t was_column = xplustabs();

    /* If we're at the bottom of the file, get out. */
    if (openfile->current == openfile->filebot)
	return;

    assert(ISSET(SOFTWRAP) || openfile->current_y ==
		openfile->current->lineno - openfile->edittop->lineno);
    assert(openfile->current->next != NULL);

#ifndef NANO_TINY
    if (ISSET(SOFTWRAP)) {
	/* Compute the number of lines to scroll. */
	amount = strlenpt(openfile->current->data) / editwincols -
			xplustabs() / editwincols +
			strlenpt(openfile->current->next->data) / editwincols +
			openfile->current_y - editwinrows + 2;
	topline = openfile->edittop;
	/* Reduce the amount when there are overlong lines at the top. */
	for (enough = 1; enough < amount; enough++) {
	    amount -= strlenpt(topline->data) / editwincols;
	    if (amount > 0)
		topline = topline->next;
	    if (amount < enough) {
		amount = enough;
		break;
	    }
	}
    }
#endif

    /* Move to the next line in the file. */
    openfile->current = openfile->current->next;
    openfile->current_x = actual_x(openfile->current->data,
					openfile->placewewant);

    /* If scroll_only is FALSE and if we're on the last line of the
     * edit window, scroll the edit window down one line if we're in
     * smooth scrolling mode, or down half a page if we're not.  If
     * scroll_only is TRUE, scroll the edit window down one line
     * unconditionally. */
#ifndef NANO_TINY
    if (openfile->current_y == editwinrows - 1 || amount > 0 || scroll_only) {
	if (amount < 1 || scroll_only)
	    amount = 1;

	edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
				amount : editwinrows / 2 + 1);

	if (ISSET(SOFTWRAP)) {
	    refresh_needed = TRUE;
	    return;
	}
    }
#else
    if (openfile->current_y == editwinrows - 1)
	edit_scroll(DOWNWARD, editwinrows / 2 + 1);
#endif

    /* If the lines weren't already redrawn, see if they need to be. */
    if (openfile->current_y < editwinrows - 1) {
	/* Redraw the prior line if it was horizontally scrolled. */
	if (need_horizontal_scroll(was_column, 0))
	    update_line(openfile->current->prev, 0);
	/* Redraw the current line if it needs to be horizontally scrolled. */
	if (need_horizontal_scroll(0, xplustabs()))
	    update_line(openfile->current, openfile->current_x);
    }
}
Пример #20
0
/* Go to the specified line and column, or ask for them if interactive
 * is TRUE.  Save the x-coordinate and y-coordinate if save_pos is TRUE.
 * Update the screen afterwards if allow_update is TRUE.  Note that both
 * the line and column numbers should be one-based. */
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
	bool interactive, bool save_pos, bool allow_update)
{
    if (interactive) {
	char *ans = mallocstrcpy(NULL, answer);
	functionptrtype func;

	/* Ask for the line and column. */
	int i = do_prompt(FALSE,
#ifndef DISABLE_TABCOMP
		TRUE,
#endif
		MGOTOLINE, use_answer ? ans : "",
#ifndef DISABLE_HISTORIES
		NULL,
#endif
		/* TRANSLATORS: This is a prompt. */
		edit_refresh, _("Enter line number, column number"));

	free(ans);

	/* Cancel, or Enter with blank string. */
	if (i < 0) {
	    statusbar(_("Cancelled"));
	    display_main_list();
	    return;
	}

	func = func_from_key(&i);

	if (func == gototext_void) {
	    /* Keep answer up on the statusbar. */
	    search_init(TRUE, TRUE);

	    do_search();
	    return;
	}

	/* Do a bounds check.  Display a warning on an out-of-bounds
	 * line or column number only if we hit Enter at the statusbar
	 * prompt. */
	if (!parse_line_column(answer, &line, &column) || line < 1 ||
		column < 1) {
	    if (i == 0)
		statusbar(_("Invalid line or column number"));
	    display_main_list();
	    return;
	}
    } else {
	if (line < 1)
	    line = openfile->current->lineno;

	if (column < 1)
	    column = openfile->placewewant + 1;
    }

    for (openfile->current = openfile->fileage;
	openfile->current != openfile->filebot && line > 1; line--)
	openfile->current = openfile->current->next;

    openfile->current_x = actual_x(openfile->current->data, column - 1);
    openfile->placewewant = column - 1;

    /* Put the top line of the edit window in range of the current line.
     * If save_pos is TRUE, don't change the cursor position when doing
     * it. */
    edit_update(save_pos ? NONE : CENTER);

    /* If allow_update is TRUE, update the screen. */
    if (allow_update) {
	edit_refresh();
	display_main_list();
    }
}
Пример #21
0
char *display_string(const char *buf, size_t start_col, size_t len, bool dollars)
{
	size_t start_index;
	/* Index in buf of the first character shown. */
	size_t column;
	/* Screen column that start_index corresponds to. */
	size_t alloc_len;
	/* The length of memory allocated for converted. */
	char *converted;
	/* The string we return. */
	size_t index;
	/* Current position in converted. */
	char *buf_mb;
	int buf_mb_len;

	/* If dollars is true, make room for the "$" at the end of the
	 * line. */
	if (dollars && len > 0 && strlenpt(buf) > start_col + len) {
		len--;
	}

	if (len == 0) {
		return mallocstrcpy(NULL, "");
	}

	buf_mb = charalloc(mb_cur_max());

	start_index = actual_x(buf, start_col);
	column = strnlenpt(buf, start_index);

	assert(column <= start_col);

	/* Make sure there's enough room for the initial character, whether
	 * it's a multibyte control character, a non-control multibyte
	 * character, a tab character, or a null terminator.  Rationale:
	 *
	 * multibyte control character followed by a null terminator:
	 *     1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
	 * multibyte non-control character followed by a null terminator:
	 *     mb_cur_max() bytes + 1 byte ('\0')
	 * tab character followed by a null terminator:
	 *     mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
	 *
	 * Since tabsize has a minimum value of 1, it can substitute for 1
	 * byte above. */
	alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
	converted = charalloc(alloc_len);

	index = 0;

	if (buf[start_index] != '\0' && buf[start_index] != '\t' && (column < start_col || (dollars && column > 0))) {
		/* We don't display all of buf[start_index] since it starts to
		 * the left of the screen. */
		buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);

		if (is_cntrl_mbchar(buf_mb)) {
			if (column < start_col) {
				char *ctrl_buf_mb = charalloc(mb_cur_max());
				int ctrl_buf_mb_len, i;

				ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb, &ctrl_buf_mb_len);

				for (i = 0; i < ctrl_buf_mb_len; i++) {
					converted[index++] = ctrl_buf_mb[i];
				}

				start_col += mbwidth(ctrl_buf_mb);

				free(ctrl_buf_mb);

				start_index += buf_mb_len;
			}
		} else if (using_utf8() && mbwidth(buf_mb) == 2) {
			if (column >= start_col) {
				converted[index++] = ' ';
				start_col++;
			}

			converted[index++] = ' ';
			start_col++;

			start_index += buf_mb_len;
		}
	}

	while (buf[start_index] != '\0') {
		buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);

		/* Make sure there's enough room for the next character, whether
		 * it's a multibyte control character, a non-control multibyte
		 * character, a tab character, or a null terminator. */
		if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
			alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
			converted = charealloc(converted, alloc_len);
		}

		/* If buf contains a tab character, interpret it. */
		if (*buf_mb == '\t') {
			if (ISSET(WHITESPACE_DISPLAY)) {
				int i;

				for (i = 0; i < whitespace_len[0]; i++) {
					converted[index++] = whitespace[i];
				}
			} else {
				converted[index++] = ' ';
			}
			start_col++;
			while (start_col % tabsize != 0) {
				converted[index++] = ' ';
				start_col++;
			}
		} else if (is_cntrl_mbchar(buf_mb)) {
			/* If buf contains a control character, interpret it. */
			char *ctrl_buf_mb = charalloc(mb_cur_max());
			int ctrl_buf_mb_len, i;

			converted[index++] = '^';
			start_col++;

			ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb, &ctrl_buf_mb_len);

			for (i = 0; i < ctrl_buf_mb_len; i++) {
				converted[index++] = ctrl_buf_mb[i];
			}

			start_col += mbwidth(ctrl_buf_mb);

			free(ctrl_buf_mb);
			/* If buf contains a space character, interpret it. */
		} else if (*buf_mb == ' ') {
			if (ISSET(WHITESPACE_DISPLAY)) {
				int i;

				for (i = whitespace_len[0]; i < whitespace_len[0] + whitespace_len[1]; i++) {
					converted[index++] = whitespace[i];
				}
			} else {
				converted[index++] = ' ';
			}
			start_col++;
		} else {
			/* If buf contains a non-control character, interpret it.  If buf
			 * contains an invalid multibyte sequence, display it as such. */
			char *nctrl_buf_mb = charalloc(mb_cur_max());
			int nctrl_buf_mb_len, i;

			/* Make sure an invalid sequence-starter byte is properly
			 * terminated, so that it doesn't pick up lingering bytes
			 * of any previous content. */
			null_at(&buf_mb, buf_mb_len);

			nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb, &nctrl_buf_mb_len);

			for (i = 0; i < nctrl_buf_mb_len; i++) {
				converted[index++] = nctrl_buf_mb[i];
			}

			start_col += mbwidth(nctrl_buf_mb);

			free(nctrl_buf_mb);
		}

		start_index += buf_mb_len;
	}

	free(buf_mb);

	assert(alloc_len >= index + 1);

	/* Null-terminate converted. */
	converted[index] = '\0';

	/* Make sure converted takes up no more than len columns. */
	index = actual_x(converted, len);
	null_at(&converted, index);

	return converted;
}
Пример #22
0
Файл: move.c Проект: sria91/nano
/* If scroll_only is FALSE, move down one line.  If scroll_only is TRUE,
 * scroll down one line without scrolling the cursor. */
void do_down(
#ifndef NANO_TINY
    bool scroll_only
#else
    void
#endif
)
{
#ifndef NANO_TINY
    int amount = 0, enough;
    filestruct *topline;
#endif

    /* If we're at the bottom of the file, get out. */
    if (openfile->current == openfile->filebot || !openfile->current->next)
        return;

    assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);

    /* Move the current line of the edit window down. */
    openfile->current = openfile->current->next;
    openfile->current_x = actual_x(openfile->current->data,
                                   openfile->placewewant);

#ifndef NANO_TINY
    if (ISSET(SOFTWRAP)) {
        /* Compute the amount to scroll. */
        amount = (strlenpt(openfile->current->data) / COLS + openfile->current_y + 2
                  + strlenpt(openfile->current->prev->data) / COLS - editwinrows);
        topline = openfile->edittop;
        /* Reduce the amount when there are overlong lines at the top. */
        for (enough = 1; enough < amount; enough++) {
            if (amount <= strlenpt(topline->data) / COLS) {
                amount = enough;
                break;
            }
            amount -= strlenpt(topline->data) / COLS;
            topline = topline->next;
        }
    }
#endif

    /* If scroll_only is FALSE and if we're on the last line of the
     * edit window, scroll the edit window down one line if we're in
     * smooth scrolling mode, or down half a page if we're not.  If
     * scroll_only is TRUE, scroll the edit window down one line
     * unconditionally. */
    if (openfile->current_y == editwinrows - 1
#ifndef NANO_TINY
            || amount > 0 || scroll_only
#endif
       ) {
#ifndef NANO_TINY
        if (amount < 1 || scroll_only)
            amount = 1;
#endif
        edit_scroll(DOWNWARD,
#ifndef NANO_TINY
                    (ISSET(SMOOTH_SCROLL) || scroll_only) ? amount :
#endif
                    editwinrows / 2 + 1);
        edit_refresh_needed = TRUE;
    }
    /* If we're above the last line of the edit window, update the line
     * we were on before and the line we're on now.  The former needs to
     * be redrawn if we're not on the first page, and the latter needs
     * to be drawn unconditionally. */
    if (openfile->current_y < editwinrows - 1
#ifndef NANO_TINY
            || ISSET(SOFTWRAP)
#endif
       ) {
        if (need_screen_update(0))
            update_line(openfile->current->prev, 0);
        update_line(openfile->current, openfile->current_x);
    }
}