Beispiel #1
0
int load_prefs(buffer *const b, const char *const name)
{
    if (!b || !name)
    {
        return ERROR;
    }

    assert_buffer(b);

    b->exec_only_options = 1;

    int error = OK;
    char_stream *const cs = load_stream(NULL, name, false, false);
    if (cs)
    {
        error = play_macro(b, cs);
        free_char_stream(cs);
    }
    else
    {
        error = ERROR;
    }

    b->exec_only_options = 0;

    return error;
}
Beispiel #2
0
Datei: input.c Projekt: dmt4/ne
static void init_history(void) {
	if (!history_buff){
		history_buff = alloc_buffer(NULL);
		if (history_buff) {
			const char * const history_filename = tilde_expand("~/.ne/.history");
			clear_buffer(history_buff);
			history_buff->opt.do_undo = 0;
			history_buff->opt.auto_prefs = 0;
			load_file_in_buffer(history_buff, history_filename);
			/* The history buffer is agnostic. The actual encoding of each line is detected dynamically. */
			history_buff->encoding = ENC_8_BIT;
			change_filename(history_buff, str_dup(history_filename));
			assert_buffer(history_buff);

			/* This should be never necessary with new histories, as all lines will
				be terminated by a life feed, but it is kept for backward
				compatibility. */

			move_to_bof(history_buff);
			if (history_buff->cur_line_desc->line && history_buff->cur_line_desc->line_len) {
				insert_stream(history_buff,
								  history_buff->cur_line_desc,
								  history_buff->cur_line,
								  history_buff->cur_line_desc->line_len,
								  "", 1);
			}
		}
	}
	if (history_buff) {
		move_to_bof(history_buff);
		move_to_sol(history_buff);
	}
}
Beispiel #3
0
static int do_auto_prefs(buffer *b, const char *ext, int (prefs_func)(buffer *, const char *))
{
    if (!b)
    {
        return ERROR;
    }

    assert_buffer(b);

    if (!ext && (!b->filename || !(ext = extension(b->filename))))
    {
        return HAS_NO_EXTENSION;
    }

    /*  Try global autoprefs -- We always load these before ~/.ne autoprefs.
        That way the user can override whatever he wants, but anything he
        doesn't override still gets passed through. */

    int error = OK;
    char *auto_name;
    char  *prefs_dir;
    if (*prefs_func == load_prefs && (prefs_dir = exists_gprefs_dir()))
    {
        if ((auto_name = malloc(strlen(ext) + strlen(prefs_dir) + strlen(PREF_FILE_SUFFIX) + 2)))
        {
            strcat(strcat(strcpy(auto_name, prefs_dir), ext), PREF_FILE_SUFFIX);
            error = prefs_func(b, auto_name);
            free(auto_name);
            /*  We don't "return error;" here because we still haven't loaded
                the user's autoprefs. */
        }
    }

    /* Try ~/.ne autoprefs */
    if ((prefs_dir = exists_prefs_dir()))
    {
        if ((auto_name = malloc(strlen(ext) + strlen(prefs_dir) + strlen(PREF_FILE_SUFFIX) + 2)))
        {
            strcat(strcat(strcpy(auto_name, prefs_dir), ext), PREF_FILE_SUFFIX);
            error = prefs_func(b, auto_name);
            free(auto_name);
        }
        else
        {
            return OUT_OF_MEMORY;
        }
    }
    else
    {
        error = CANT_FIND_PREFS_DIR;
    }

    if (do_syntax && !b->syn)
    {
        load_syntax_by_name(b, ext);
    }

    return error;
}
Beispiel #4
0
Datei: prefs.c Projekt: vigna/ne
int save_prefs(buffer * const b, const char * const name) {
	if (!b || !name) return ERROR;

	assert_buffer(b);

	char_stream *cs = alloc_char_stream(PREF_FILE_SIZE_GUESS);
	if (cs) {
		/* We create a macro by recording an action for each kind of flag. */

		if (!saving_defaults && b->syn) record_action(cs, SYNTAX_A, -1, (const char *)b->syn->name, verbose_macros);

		record_action(cs, TABSIZE_A,          b->opt.tab_size,       NULL, verbose_macros);
		/* Skip cur_clip */
		record_action(cs, RIGHTMARGIN_A,      b->opt.right_margin,   NULL, verbose_macros);
		record_action(cs, FREEFORM_A,         b->opt.free_form,      NULL, verbose_macros);
		record_action(cs, HEXCODE_A,          b->opt.hex_code,       NULL, verbose_macros);
		record_action(cs, WORDWRAP_A,         b->opt.word_wrap,      NULL, verbose_macros);
		record_action(cs, AUTOINDENT_A,       b->opt.auto_indent,    NULL, verbose_macros);
		record_action(cs, PRESERVECR_A,       b->opt.preserve_cr,    NULL, verbose_macros);
		record_action(cs, INSERT_A,           b->opt.insert,         NULL, verbose_macros);
		record_action(cs, DOUNDO_A,           b->opt.do_undo,        NULL, verbose_macros);
		record_action(cs, AUTOPREFS_A,        b->opt.auto_prefs,     NULL, verbose_macros);
		record_action(cs, NOFILEREQ_A,        b->opt.no_file_req,    NULL, verbose_macros);
		/* Skip read_only */
		/* Skip search_back */
		record_action(cs, CASESEARCH_A,       b->opt.case_search,    NULL, verbose_macros);
		record_action(cs, TABS_A,             b->opt.tabs,           NULL, verbose_macros);
		record_action(cs, DELTABS_A,          b->opt.del_tabs,       NULL, verbose_macros);
		record_action(cs, SHIFTTABS_A,        b->opt.shift_tabs,     NULL, verbose_macros);
		record_action(cs, AUTOMATCHBRACKET_A, b->opt.automatch,      NULL, verbose_macros);
		record_action(cs, BINARY_A,           b->opt.binary,         NULL, verbose_macros);
		record_action(cs, UTF8AUTO_A,         b->opt.utf8auto,       NULL, verbose_macros);
		record_action(cs, VISUALBELL_A,       b->opt.visual_bell,    NULL, verbose_macros);

		if (saving_defaults) {
			/* We only save the global flags that differ from their defaults. */
			/* Make sure these are in sync with the defaults near the top of ne.c. */
#ifndef ALTPAGING
			if (req_order)       record_action(cs, REQUESTORDER_A,  req_order,      NULL, verbose_macros);
#else
			if (!req_order)      record_action(cs, REQUESTORDER_A,  req_order,      NULL, verbose_macros);
#endif
			if (fast_gui)        record_action(cs, FASTGUI_A,       fast_gui,       NULL, verbose_macros);
			if (!status_bar)     record_action(cs, STATUSBAR_A,     status_bar,     NULL, verbose_macros);
			if (!verbose_macros) record_action(cs, VERBOSEMACROS_A, verbose_macros, NULL, verbose_macros);
			saving_defaults = false;
		}

		const int error = save_stream(cs, name, b->is_CRLF, false);
		free_char_stream(cs);
		return error;
	}

	return OUT_OF_MEMORY;
}
Beispiel #5
0
Datei: prefs.c Projekt: vigna/ne
int load_syntax_by_name(buffer * const b, const char * const name) {
	assert_buffer(b);
	assert(name != NULL);

	struct high_syntax *syn = load_syntax((unsigned char *)name);
	if (!syn) syn = load_syntax((unsigned char *)ext2syntax(name));
	if (syn) {
		b->syn = syn;
		reset_syntax_states(b);
		return OK;
	}
	return NO_SYNTAX_FOR_EXT;
}
Beispiel #6
0
Datei: input.c Projekt: dmt4/ne
void close_history(void) {
	if (history_buff) {
		if (history_buff->is_modified) {
			while(history_buff->num_lines > 500) {
				move_to_sof(history_buff);
				delete_one_line(history_buff, history_buff->cur_line_desc, history_buff->cur_line);
				assert_buffer(history_buff);
			}
			save_buffer_to_file(history_buff,NULL);
		}
		free_buffer(history_buff);
		history_buff = NULL;
	}
}
Beispiel #7
0
Datei: buffer.c Projekt: dmt4/ne
void free_buffer(buffer * const b) {
	if (b == NULL) return;

	assert_buffer(b);

	free_buffer_contents(b);

	free_char_stream(b->cur_macro);

	free(b->find_string);
	free(b->replace_string);
	free(b->command_line);
	if (b->attr_buf) free(b->attr_buf);
	free(b);
}
Beispiel #8
0
Datei: input.c Projekt: dmt4/ne
static void add_to_history(const char * const str) {
	if (!history_buff || !str || !*str) return;

	move_to_bof(history_buff);

	/* This insert_stream() takes care of adding a line, including a line-feed
		at the end. */

	insert_stream(history_buff,
					  history_buff->cur_line_desc,
					  history_buff->cur_line,
					  history_buff->cur_line_desc->line_len,
					  str,
					  strlen(str) + 1);
	assert_buffer(history_buff);
}
Beispiel #9
0
Datei: buffer.c Projekt: dmt4/ne
int delete_one_line(buffer * const b, line_desc * const ld, const int64_t line) {
	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (ld->line_len && (b->last_deleted = reset_stream(b->last_deleted))) add_to_stream(b->last_deleted, ld->line, ld->line_len);

	/* We delete a line by delete_stream()ing its length plus one. However, if
		we are on the last line of text, there is no terminating line feed. */

	const int error = delete_stream(b, ld, line, 0, ld->line_len + (ld->ld_node.next->next ? 1 : 0));
	release_signals();

	return error;
}
Beispiel #10
0
Datei: buffer.c Projekt: dmt4/ne
void clear_buffer(buffer * const b) {
	if (!b) return;

	block_signals();

	free_buffer_contents(b);

	line_desc * const ld = alloc_line_desc(b);
	add_head(&b->line_desc_list, &ld->ld_node);
	if (do_syntax) {
		ld->highlight_state.state = 0;
		ld->highlight_state.stack = NULL;
		ld->highlight_state.saved_s[0] = 0;
	}

	b->num_lines = 1;
	reset_position_to_sof(b);

	assert_buffer(b);

	release_signals();
}
Beispiel #11
0
Datei: buffer.c Projekt: dmt4/ne
int insert_stream(buffer * const b, line_desc * ld, int64_t line, int64_t pos, const char * const stream, const int64_t stream_len) {
	if (!b || !ld || !stream || stream_len < 1 || pos > ld->line_len) return ERROR;

	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (b->opt.do_undo && !(b->undoing || b->redoing)) {
		const int error = add_undo_step(b, line, pos, -stream_len);
		if (error) {
			release_signals();
			return error;
		}
	}

	const char *s = stream;
	while(s - stream < stream_len) {
		int64_t const len = strnlen_ne(s, stream_len - (s - stream));
		if (len) {

			/* First case; there is no character allocated on this line. We
			have to freshly allocate the line. */

			if (!ld->line) {
				if (ld->line = alloc_chars(b, len)) {
					memcpy(ld->line, s, len);
					ld->line_len = len;
				}
				else {
					release_signals();
					return OUT_OF_MEMORY;
				}
			}


			/* Second case. There are not enough characters around ld->line. Note
			that the value of the check_first_before parameter depends on
			the position at which the insertion will be done, and it is chosen
			in such a way to minimize the number of characters to move. */

			else {
				const int64_t result = alloc_chars_around(b, ld, len, pos < ld->line_len / 2);
				if (result < 0) {
					char * const p = alloc_chars(b, ld->line_len + len);
					if (p) {
						memcpy(p, ld->line, pos);
						memcpy(&p[pos], s, len);
						memcpy(&p[pos + len], ld->line + pos, ld->line_len - pos);
						free_chars(b, ld->line, ld->line_len);
						ld->line = p;
						ld->line_len += len;
					}
					else {
						release_signals();
						return OUT_OF_MEMORY;
					}
				}
				else { /* Third case. There are enough free characters around ld->line. */
					if (len - result) memmove(ld->line - (len - result), ld->line, pos);
					if (result) memmove(ld->line + pos + result, ld->line + pos, ld->line_len - pos);
					memcpy(ld->line - (len - result) + pos, s, len);
	
					ld->line -= (len - result);
					ld->line_len += len;
				}
			}
			b->is_modified = 1;

			/* We just inserted len chars at (line,pos); adjust bookmarks and mark accordingly. */
			if (b->marking && b->block_start_line == line && b->block_start_pos > pos) b->block_start_pos += len;

			for (int i = 0, mask = b->bookmark_mask; mask; i++, mask >>= 1) 
				if ((mask & 1) && b->bookmark[i].line == line && b->bookmark[i].pos > pos) b->bookmark[i].pos += len;
		}

		/* If the string we have inserted has a NULL at the end, we create a new
			line under the current one and set ld to point to it. */

		if (len + (s - stream) < stream_len) {
			line_desc *new_ld;

			if (new_ld = alloc_line_desc(b)) {

				add(&new_ld->ld_node, &ld->ld_node);
				b->num_lines++;

				if (pos + len < ld->line_len) {
					new_ld->line_len = ld->line_len - pos - len;
					new_ld->line = &ld->line[pos + len];
					ld->line_len = pos + len;
					if (pos + len == 0) ld->line = NULL;
				}

				b->is_modified = 1;
				ld = new_ld;

				/* We just inserted a line break at (line,pos);
				   adjust the buffer bookmarks and mark accordingly. */
				if (b->marking) {
					if (b->block_start_line == line && b->block_start_pos > pos) {
						b->block_start_pos -= pos;
						b->block_start_line++;
					}
					else if (b->block_start_line > line) b->block_start_line++;
				}
				for (int i = 0, mask=b->bookmark_mask; mask; i++, mask >>= 1) {
					if (mask & 1) {
						if (b->bookmark[i].line == line && b->bookmark[i].pos > pos) {
							b->bookmark[i].pos -= pos;
							b->bookmark[i].line++;
						}
						else if (b->bookmark[i].line > line) b->bookmark[i].line++;
					}
				}
				pos = 0;
				line++;
			}
			else {
Beispiel #12
0
Datei: buffer.c Projekt: dmt4/ne
char *alloc_chars(buffer * const b, const int64_t len) {
	if (!len || !b) return NULL;

	assert_buffer(b);

	block_signals();

	char_pool *cp;
	for(cp = (char_pool *)b->char_pool_list.head; cp->cp_node.next; cp = (char_pool *)cp->cp_node.next) {
		assert_char_pool(cp);

		/* We try to allocate before the first used character,
		or after the last used character. If we succeed with a
		pool which is not the head of the list, we move it to
		the head in order to optimize the next try. */

		if (cp->first_used >= len) {

			cp->first_used -= len;
			b->free_chars -= len;

			if (cp != (char_pool *)b->char_pool_list.head) {
				rem(&cp->cp_node);
				add_head(&b->char_pool_list, &cp->cp_node);
			}

			release_signals();
			return cp->pool + cp->first_used;
		}
		else if (cp->size - cp->last_used > len) {

			cp->last_used += len;
			b->free_chars -= len;

			if (cp != (char_pool *)b->char_pool_list.head) {
				rem(&cp->cp_node);
				add_head(&b->char_pool_list, &cp->cp_node);
			}

			release_signals();
			return cp->pool + cp->last_used - len + 1;
		}
	}

	/* If no free space has been found, we allocate a new pool which is guaranteed
	to contain at least len characters. The pool is added to the head of the list. */

	if (cp = alloc_char_pool(len)) {
		add_head(&b->char_pool_list, &cp->cp_node);
		cp->last_used = len - 1;

		b->allocated_chars += cp->size;
		b->free_chars += cp->size - len;

		release_signals();
		return cp->pool;
	}

	release_signals();
	return NULL;
}
Beispiel #13
0
Datei: edit.c Projekt: vigna/ne
static int to_something(buffer *b, int (to_first)(int), int (to_rest)(int)) {
	assert_buffer(b);

	/* If we are after the end of the line, just return ERROR. */

	if (b->cur_line == b->num_lines -1 && b->cur_pos >= b->cur_line_desc->line_len) return ERROR;

	int64_t pos = b->cur_pos;
	int c;
	/* First of all, we search for the word start, if we're not over it. */
	if (pos >= b->cur_line_desc->line_len || !ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding))
		if (search_word(b, 1) != OK)
			return ERROR;

	bool changed = false;
	int64_t new_len = 0;
	pos = b->cur_pos;
	const int64_t cur_char = b->cur_char;
	const int cur_x = b->cur_x;
	/* Then, we compute the word position extremes, length of the result (which
		may change because of casing). */
	while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
		const int new_c = new_len ? to_rest(c) : to_first(c);
		changed |= (c != new_c);

		if (b->encoding == ENC_UTF8) new_len += utf8seqlen(new_c);
		else new_len++;

		pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
	}

	const int64_t len = pos - b->cur_pos;
	if (!len) {
		char_right(b);
		return OK;
	}

	if (changed) {
		/* We actually perform changes only if some character was case folded. */
		char * word = malloc(new_len * sizeof *word);
		if (!word) return OUT_OF_MEMORY;

		pos = b->cur_pos;
		new_len = 0;
		/* Second pass: we actually build the transformed word. */
		while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
			if (b->encoding == ENC_UTF8) new_len += utf8str(new_len ? to_rest(c) : to_first(c), word + new_len);
			else {
				word[new_len] = new_len ? to_rest(c) : to_first(c);
				new_len++;
			}

			pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
		}

		start_undo_chain(b);

		delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, len);
		if (new_len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, word, new_len);

		free(word);

		end_undo_chain(b);

		if (cur_char < b->attr_len) b->attr_len = cur_char;
		update_line(b, b->cur_line_desc, b->cur_y, cur_x, false);
		need_attr_update = true;
	}

	return search_word(b, 1);
}