2004-05-29 10:17:37 +00:00
|
|
|
/*
|
|
|
|
|
* Buffer handling for QEmacs
|
2007-12-03 16:10:38 +00:00
|
|
|
*
|
2014-01-23 12:56:22 +00:00
|
|
|
* Copyright (c) 2000-2002 Fabrice Bellard.
|
2026-05-25 11:32:49 +02:00
|
|
|
* Copyright (c) 2002-2026 Charlie Gordon.
|
2004-05-29 10:17:37 +00:00
|
|
|
*
|
2023-03-05 02:04:02 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2004-05-29 10:17:37 +00:00
|
|
|
*
|
2023-03-05 02:04:02 +01:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
|
* all copies or substantial portions of the Software.
|
2004-05-29 10:17:37 +00:00
|
|
|
*
|
2023-03-05 02:04:02 +01:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
* THE SOFTWARE.
|
2004-05-29 10:17:37 +00:00
|
|
|
*/
|
2007-12-03 16:10:38 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
#include "qe.h"
|
2008-04-05 23:04:56 +00:00
|
|
|
#ifdef CONFIG_MMAP
|
2004-05-29 10:17:37 +00:00
|
|
|
#include <sys/mman.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-01-03 09:51:29 +00:00
|
|
|
static void eb_addlog(EditBuffer *b, enum LogOperation op,
|
2004-05-29 10:17:37 +00:00
|
|
|
int offset, int size);
|
|
|
|
|
|
|
|
|
|
/************************************************************/
|
|
|
|
|
/* basic access to the edit buffer */
|
|
|
|
|
|
|
|
|
|
/* find a page at a given offset */
|
2015-08-24 12:59:25 +00:00
|
|
|
static inline Page *find_page(EditBuffer *b, int offset, int *page_offset_ptr)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2015-08-24 12:59:25 +00:00
|
|
|
Page *p = b->page_table;
|
|
|
|
|
int page_offset = offset;
|
|
|
|
|
|
|
|
|
|
if (b->cur_page && offset >= b->cur_offset) {
|
|
|
|
|
p = b->cur_page;
|
|
|
|
|
page_offset -= b->cur_offset;
|
|
|
|
|
if (page_offset < p->size) {
|
|
|
|
|
*page_offset_ptr = page_offset;
|
|
|
|
|
return p;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-08-24 12:59:25 +00:00
|
|
|
while (page_offset >= p->size) {
|
|
|
|
|
page_offset -= p->size;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
*page_offset_ptr = page_offset;
|
|
|
|
|
b->cur_offset = offset - page_offset;
|
|
|
|
|
b->cur_page = p;
|
|
|
|
|
return p;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* prepare a page to be written */
|
|
|
|
|
static void update_page(Page *p)
|
|
|
|
|
{
|
2005-05-11 14:35:54 +00:00
|
|
|
u8 *buf;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* if the page is read only, copy it */
|
|
|
|
|
if (p->flags & PG_READ_ONLY) {
|
2024-07-28 19:22:07 +02:00
|
|
|
buf = qe_malloc_dup_bytes(p->data, p->size);
|
2004-05-29 10:17:37 +00:00
|
|
|
/* XXX: should return an error */
|
|
|
|
|
if (!buf)
|
|
|
|
|
return;
|
|
|
|
|
p->data = buf;
|
|
|
|
|
p->flags &= ~PG_READ_ONLY;
|
|
|
|
|
}
|
|
|
|
|
p->flags &= ~(PG_VALID_POS | PG_VALID_CHAR | PG_VALID_COLORS);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-16 19:22:01 +00:00
|
|
|
/* Read one raw byte from the buffer:
|
|
|
|
|
* We should have: 0 <= offset < b->total_size
|
|
|
|
|
* Returns the byte or -1 upon failure.
|
|
|
|
|
*/
|
|
|
|
|
int eb_read_one_byte(EditBuffer *b, int offset)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2015-08-16 19:22:01 +00:00
|
|
|
const Page *p;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2015-08-16 19:22:01 +00:00
|
|
|
/* We clip the request for safety */
|
|
|
|
|
if (offset < 0 || offset >= b->total_size)
|
|
|
|
|
return -1;
|
2007-12-18 17:59:48 +00:00
|
|
|
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(b, offset, &offset);
|
2015-08-16 19:22:01 +00:00
|
|
|
return p->data[offset];
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2015-08-16 19:22:01 +00:00
|
|
|
/* Read raw data from the buffer:
|
|
|
|
|
* We should have: 0 <= offset < b->total_size, size >= 0
|
|
|
|
|
*/
|
|
|
|
|
int eb_read(EditBuffer *b, int offset, void *buf, int size)
|
|
|
|
|
{
|
|
|
|
|
int len, remain;
|
|
|
|
|
const Page *p;
|
|
|
|
|
|
2016-12-13 17:20:51 +00:00
|
|
|
/* We carefully clip the request, avoiding integer overflow */
|
2015-08-16 19:22:01 +00:00
|
|
|
if (offset < 0 || size <= 0 || offset >= b->total_size)
|
2004-05-29 10:17:37 +00:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-16 19:22:01 +00:00
|
|
|
len = b->total_size - offset;
|
|
|
|
|
if (size > len)
|
|
|
|
|
size = len;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(b, offset, &offset);
|
2015-08-16 19:22:01 +00:00
|
|
|
for (remain = size;;) {
|
2004-05-29 10:17:37 +00:00
|
|
|
len = p->size - offset;
|
2015-08-16 19:22:01 +00:00
|
|
|
if (len > remain)
|
|
|
|
|
len = remain;
|
|
|
|
|
memcpy(buf, p->data + offset, len);
|
|
|
|
|
if ((remain -= len) <= 0)
|
|
|
|
|
break;
|
|
|
|
|
buf = (u8*)buf + len;
|
|
|
|
|
p++;
|
|
|
|
|
offset = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2015-08-16 19:22:01 +00:00
|
|
|
return size;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-16 19:22:01 +00:00
|
|
|
/* Write raw data into the buffer.
|
|
|
|
|
* We should have 0 <= offset <= b->total_size, size >= 0.
|
|
|
|
|
* Note: eb_write can be used to append data at the end of the buffer
|
|
|
|
|
*/
|
|
|
|
|
int eb_write(EditBuffer *b, int offset, const void *buf, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2015-08-16 19:22:01 +00:00
|
|
|
int len, remain, write_size, page_offset;
|
|
|
|
|
Page *p;
|
2007-12-20 20:39:18 +00:00
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
if (b->flags & BF_READONLY)
|
2015-08-16 19:22:01 +00:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-22 20:49:01 +00:00
|
|
|
/* We carefully clip the request, avoiding integer overflow */
|
2015-08-16 19:22:01 +00:00
|
|
|
if (offset < 0 || size <= 0 || offset > b->total_size)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
write_size = size;
|
|
|
|
|
len = b->total_size - offset;
|
|
|
|
|
if (write_size > len)
|
|
|
|
|
write_size = len;
|
|
|
|
|
|
|
|
|
|
if (write_size > 0) {
|
|
|
|
|
eb_addlog(b, LOGOP_WRITE, offset, write_size);
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(b, offset, &page_offset);
|
2015-08-16 19:22:01 +00:00
|
|
|
for (remain = write_size;;) {
|
|
|
|
|
len = p->size - page_offset;
|
|
|
|
|
if (len > remain)
|
|
|
|
|
len = remain;
|
|
|
|
|
update_page(p);
|
|
|
|
|
memcpy(p->data + page_offset, buf, len);
|
|
|
|
|
buf = (const u8*)buf + len;
|
|
|
|
|
if ((remain -= len) <= 0)
|
|
|
|
|
break;
|
|
|
|
|
p++;
|
|
|
|
|
page_offset = 0;
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2026-05-24 14:38:47 +02:00
|
|
|
if (size > write_size) {
|
|
|
|
|
b->file_ignore++;
|
2015-08-16 19:22:01 +00:00
|
|
|
eb_insert(b, offset + write_size, buf, size - write_size);
|
2026-05-24 14:38:47 +02:00
|
|
|
b->file_ignore--;
|
|
|
|
|
}
|
2015-08-16 19:22:01 +00:00
|
|
|
return size;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* internal function for insertion : 'buf' of size 'size' at the
|
|
|
|
|
beginning of the page at page_index */
|
2005-05-05 11:10:26 +00:00
|
|
|
static void eb_insert1(EditBuffer *b, int page_index, const u8 *buf, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
int len, n;
|
|
|
|
|
Page *p;
|
|
|
|
|
|
|
|
|
|
if (page_index < b->nb_pages) {
|
2007-12-15 07:24:03 +00:00
|
|
|
p = &b->page_table[page_index];
|
2004-05-29 10:17:37 +00:00
|
|
|
len = MAX_PAGE_SIZE - p->size;
|
|
|
|
|
if (len > size)
|
|
|
|
|
len = size;
|
|
|
|
|
if (len > 0) {
|
|
|
|
|
update_page(p);
|
2007-12-12 11:49:02 +00:00
|
|
|
/* CG: probably faster with qe_malloc + qe_free */
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&p->data, p->size + len);
|
2005-05-11 14:35:54 +00:00
|
|
|
memmove(p->data + len, p->data, p->size);
|
2004-05-29 10:17:37 +00:00
|
|
|
memcpy(p->data, buf + size - len, len);
|
|
|
|
|
size -= len;
|
|
|
|
|
p->size += len;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* now add new pages if necessary */
|
|
|
|
|
n = (size + MAX_PAGE_SIZE - 1) / MAX_PAGE_SIZE;
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
b->nb_pages += n;
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_array(&b->page_table, b->nb_pages);
|
2007-12-15 07:24:03 +00:00
|
|
|
p = &b->page_table[page_index];
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(p + n, p, b->nb_pages - n - page_index);
|
2004-05-29 10:17:37 +00:00
|
|
|
while (size > 0) {
|
|
|
|
|
len = size;
|
|
|
|
|
if (len > MAX_PAGE_SIZE)
|
|
|
|
|
len = MAX_PAGE_SIZE;
|
|
|
|
|
p->size = len;
|
2024-07-28 19:22:07 +02:00
|
|
|
p->data = qe_malloc_dup_bytes(buf, len);
|
2004-05-29 10:17:37 +00:00
|
|
|
p->flags = 0;
|
|
|
|
|
buf += len;
|
|
|
|
|
size -= len;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We must have : 0 <= offset <= b->total_size */
|
2005-05-05 11:10:26 +00:00
|
|
|
static void eb_insert_lowlevel(EditBuffer *b, int offset,
|
2005-05-11 14:35:54 +00:00
|
|
|
const u8 *buf, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
int len, len_out, page_index;
|
|
|
|
|
Page *p;
|
|
|
|
|
|
|
|
|
|
b->total_size += size;
|
|
|
|
|
|
|
|
|
|
/* find the correct page */
|
|
|
|
|
p = b->page_table;
|
|
|
|
|
if (offset > 0) {
|
|
|
|
|
offset--;
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(b, offset, &offset);
|
2004-05-29 10:17:37 +00:00
|
|
|
offset++;
|
2015-08-22 20:49:01 +00:00
|
|
|
retry:
|
2004-05-29 10:17:37 +00:00
|
|
|
/* compute what we can insert in current page */
|
|
|
|
|
len = MAX_PAGE_SIZE - offset;
|
|
|
|
|
if (len > size)
|
|
|
|
|
len = size;
|
|
|
|
|
/* number of bytes to put in next pages */
|
|
|
|
|
len_out = p->size + len - MAX_PAGE_SIZE;
|
|
|
|
|
page_index = p - b->page_table;
|
2015-08-22 20:49:01 +00:00
|
|
|
if (len_out > 0) {
|
|
|
|
|
#if 1
|
2015-08-24 12:59:25 +00:00
|
|
|
/* First try and shift some of these bytes to the previous pages */
|
2015-08-22 20:49:01 +00:00
|
|
|
if (page_index > 0 && p[-1].size < MAX_PAGE_SIZE) {
|
|
|
|
|
int chunk;
|
|
|
|
|
update_page(p - 1);
|
|
|
|
|
update_page(p);
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
chunk = min_offset(MAX_PAGE_SIZE - p[-1].size, offset);
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&p[-1].data, p[-1].size + chunk);
|
2015-08-22 20:49:01 +00:00
|
|
|
memcpy(p[-1].data + p[-1].size, p->data, chunk);
|
|
|
|
|
p[-1].size += chunk;
|
|
|
|
|
p->size -= chunk;
|
|
|
|
|
if (p->size == 0) {
|
|
|
|
|
/* if page was completely fused with previous one */
|
|
|
|
|
b->nb_pages -= 1;
|
|
|
|
|
qe_free(&p->data);
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(p, p + 1, b->nb_pages - page_index);
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_array(&b->page_table, b->nb_pages);
|
2015-08-22 20:49:01 +00:00
|
|
|
p = b->page_table + page_index - 1;
|
|
|
|
|
offset = p->size;
|
|
|
|
|
goto retry;
|
|
|
|
|
}
|
|
|
|
|
memmove(p->data, p->data + chunk, p->size);
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&p->data, p->size);
|
2015-08-22 20:49:01 +00:00
|
|
|
offset -= chunk;
|
|
|
|
|
if (offset == 0 && p[-1].size < MAX_PAGE_SIZE) {
|
|
|
|
|
/* restart from previous page */
|
|
|
|
|
p--;
|
|
|
|
|
offset = p->size;
|
|
|
|
|
}
|
|
|
|
|
goto retry;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2008-01-03 09:51:29 +00:00
|
|
|
eb_insert1(b, page_index + 1,
|
2004-05-29 10:17:37 +00:00
|
|
|
p->data + p->size - len_out, len_out);
|
2015-08-22 20:49:01 +00:00
|
|
|
} else {
|
2004-05-29 10:17:37 +00:00
|
|
|
len_out = 0;
|
2015-08-22 20:49:01 +00:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
/* now we can insert in current page */
|
|
|
|
|
if (len > 0) {
|
2015-08-22 20:49:01 +00:00
|
|
|
/* reload p because page_table may have been reallocated */
|
2004-05-29 10:17:37 +00:00
|
|
|
p = b->page_table + page_index;
|
|
|
|
|
update_page(p);
|
|
|
|
|
p->size += len - len_out;
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&p->data, p->size);
|
2008-01-03 09:51:29 +00:00
|
|
|
memmove(p->data + offset + len,
|
2004-05-29 10:17:37 +00:00
|
|
|
p->data + offset, p->size - (offset + len));
|
|
|
|
|
memcpy(p->data + offset, buf, len);
|
|
|
|
|
buf += len;
|
|
|
|
|
size -= len;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
page_index = -1;
|
|
|
|
|
}
|
|
|
|
|
/* insert the remaining data in the next pages */
|
|
|
|
|
if (size > 0)
|
|
|
|
|
eb_insert1(b, page_index + 1, buf, size);
|
|
|
|
|
|
|
|
|
|
/* the page cache is no longer valid */
|
|
|
|
|
b->cur_page = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
/* Insert 'size' bytes of 'src' buffer from position 'src_offset' into
|
|
|
|
|
* buffer 'dest' at offset 'dest_offset'. 'src' MUST BE DIFFERENT from
|
|
|
|
|
* 'dest'. Raw insertion performed, encoding is ignored.
|
|
|
|
|
*/
|
|
|
|
|
int eb_insert_buffer(EditBuffer *dest, int dest_offset,
|
|
|
|
|
EditBuffer *src, int src_offset,
|
|
|
|
|
int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2015-08-27 18:59:56 +00:00
|
|
|
Page *p;
|
|
|
|
|
int len, size0;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
if (dest->flags & BF_READONLY)
|
2014-01-06 09:40:20 +00:00
|
|
|
return 0;
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
/* Assert parameter consistency */
|
|
|
|
|
if (dest_offset < 0 || src_offset < 0 || src_offset >= src->total_size)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (src_offset + size > src->total_size)
|
|
|
|
|
size = src->total_size - src_offset;
|
|
|
|
|
|
|
|
|
|
if (dest_offset > dest->total_size)
|
|
|
|
|
dest_offset = dest->total_size;
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
if (size <= 0)
|
|
|
|
|
return 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
size0 = size;
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_addlog(dest, LOGOP_INSERT, dest_offset, size);
|
2015-08-22 20:49:01 +00:00
|
|
|
#if 1
|
|
|
|
|
/* Much simpler algorithm with fewer pathological cases */
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(src, src_offset, &src_offset);
|
2015-08-22 20:49:01 +00:00
|
|
|
while (size > 0) {
|
|
|
|
|
len = p->size - src_offset;
|
|
|
|
|
if (len > size)
|
|
|
|
|
len = size;
|
|
|
|
|
if ((p->flags & PG_READ_ONLY) && src_offset == 0 && len == MAX_PAGE_SIZE) {
|
|
|
|
|
/* XXX: should share complete read-only pages. This is
|
|
|
|
|
* actually a little tricky: the mapping may be removed
|
|
|
|
|
* upon buffer close. We need a ref count scheme to keep
|
|
|
|
|
* track of these pages.
|
|
|
|
|
* A brute force approach may prove best: upon unmapping a
|
|
|
|
|
* file, scan all buffers for shared pages and delay
|
|
|
|
|
* unmapping until these get freed. We may keep a global
|
|
|
|
|
* and a buffer based count of shared pages and a list of
|
|
|
|
|
* mappings to accelerate this phase.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
eb_insert_lowlevel(dest, dest_offset, p->data + src_offset, len);
|
|
|
|
|
dest_offset += len;
|
|
|
|
|
src_offset = 0;
|
|
|
|
|
p++;
|
|
|
|
|
size -= len;
|
|
|
|
|
}
|
|
|
|
|
return size0;
|
|
|
|
|
#else
|
2015-08-27 18:59:56 +00:00
|
|
|
Page *p_start, *q;
|
|
|
|
|
int n, page_index;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* insert the data from the first page if it is not completely
|
|
|
|
|
selected */
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(src, src_offset, &src_offset);
|
2015-08-22 20:49:01 +00:00
|
|
|
if (src_offset > 0 /* || size <= p->size */ ) {
|
2004-05-29 10:17:37 +00:00
|
|
|
len = p->size - src_offset;
|
|
|
|
|
if (len > size)
|
|
|
|
|
len = size;
|
|
|
|
|
eb_insert_lowlevel(dest, dest_offset, p->data + src_offset, len);
|
|
|
|
|
dest_offset += len;
|
|
|
|
|
size -= len;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (size == 0)
|
2014-01-06 09:40:20 +00:00
|
|
|
return size0;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
/* cut the page at dest offset if needed */
|
|
|
|
|
if (dest_offset < dest->total_size) {
|
2015-08-24 12:59:25 +00:00
|
|
|
q = find_page(dest, dest_offset, &dest_offset);
|
2004-05-29 10:17:37 +00:00
|
|
|
page_index = q - dest->page_table;
|
|
|
|
|
if (dest_offset > 0) {
|
|
|
|
|
page_index++;
|
2008-01-03 09:51:29 +00:00
|
|
|
eb_insert1(dest, page_index, q->data + dest_offset,
|
2004-05-29 10:17:37 +00:00
|
|
|
q->size - dest_offset);
|
|
|
|
|
/* must reload q because page_table may have been
|
|
|
|
|
realloced */
|
|
|
|
|
q = dest->page_table + page_index - 1;
|
|
|
|
|
update_page(q);
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&q->data, dest_offset);
|
2004-05-29 10:17:37 +00:00
|
|
|
q->size = dest_offset;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
page_index = dest->nb_pages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* update total_size */
|
|
|
|
|
dest->total_size += size;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* compute the number of complete pages to insert */
|
|
|
|
|
p_start = p;
|
|
|
|
|
while (size > 0 && p->size <= size) {
|
|
|
|
|
size -= p->size;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
n = p - p_start; /* number of pages to insert */
|
|
|
|
|
p = p_start;
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
/* add the pages */
|
|
|
|
|
dest->nb_pages += n;
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_array(&dest->page_table, dest->nb_pages);
|
2004-05-29 10:17:37 +00:00
|
|
|
q = dest->page_table + page_index;
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(q + n, q, dest->nb_pages - n - page_index);
|
2004-05-29 10:17:37 +00:00
|
|
|
p = p_start;
|
|
|
|
|
while (n > 0) {
|
|
|
|
|
len = p->size;
|
|
|
|
|
q->size = len;
|
|
|
|
|
if (p->flags & PG_READ_ONLY) {
|
|
|
|
|
/* simply copy the reference */
|
|
|
|
|
q->flags = PG_READ_ONLY;
|
|
|
|
|
q->data = p->data;
|
|
|
|
|
} else {
|
|
|
|
|
/* allocate a new page */
|
|
|
|
|
q->flags = 0;
|
2024-07-28 19:22:07 +02:00
|
|
|
q->data = qe_malloc_dup_bytes(p->data, len);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
n--;
|
|
|
|
|
p++;
|
|
|
|
|
q++;
|
|
|
|
|
}
|
|
|
|
|
page_index = q - dest->page_table;
|
|
|
|
|
}
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* insert the remaning bytes */
|
|
|
|
|
if (size > 0) {
|
|
|
|
|
eb_insert1(dest, page_index, p->data, size);
|
|
|
|
|
}
|
|
|
|
|
/* the page cache is no longer valid */
|
|
|
|
|
dest->cur_page = NULL;
|
2014-01-06 09:40:20 +00:00
|
|
|
return size0;
|
2015-08-22 20:49:01 +00:00
|
|
|
#endif
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insert 'size' bytes from 'buf' into 'b' at offset 'offset'. We must
|
|
|
|
|
have : 0 <= offset <= b->total_size */
|
2014-01-31 12:14:13 +00:00
|
|
|
/* Return number of bytes inserted */
|
|
|
|
|
int eb_insert(EditBuffer *b, int offset, const void *buf, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2007-12-20 11:49:54 +00:00
|
|
|
if (b->flags & BF_READONLY)
|
2014-01-31 12:14:13 +00:00
|
|
|
return 0;
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2007-12-18 17:59:48 +00:00
|
|
|
/* sanity checks */
|
|
|
|
|
if (offset > b->total_size)
|
2007-12-20 20:39:18 +00:00
|
|
|
offset = b->total_size;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2007-12-18 17:59:48 +00:00
|
|
|
if (offset < 0 || size <= 0)
|
2014-01-31 12:14:13 +00:00
|
|
|
return 0;
|
2007-12-18 17:59:48 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_addlog(b, LOGOP_INSERT, offset, size);
|
|
|
|
|
|
|
|
|
|
eb_insert_lowlevel(b, offset, buf, size);
|
2014-01-31 12:14:13 +00:00
|
|
|
return size;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-21 20:49:30 +00:00
|
|
|
/* We must have : 0 <= offset <= b->total_size,
|
|
|
|
|
* return actual number of bytes removed.
|
|
|
|
|
*/
|
|
|
|
|
int eb_delete(EditBuffer *b, int offset, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2014-03-21 20:49:30 +00:00
|
|
|
int n, len, size0;
|
2004-05-29 10:17:37 +00:00
|
|
|
Page *del_start, *p;
|
|
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
if (b->flags & BF_READONLY)
|
2014-03-21 20:49:30 +00:00
|
|
|
return 0;
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2014-03-21 20:49:30 +00:00
|
|
|
if (offset < 0 || offset >= b->total_size || size <= 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (size > b->total_size - offset)
|
2007-12-20 20:39:18 +00:00
|
|
|
size = b->total_size - offset;
|
2007-12-18 17:59:48 +00:00
|
|
|
|
2014-03-21 20:49:30 +00:00
|
|
|
size0 = size;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
/* dispatch callbacks before buffer update */
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_addlog(b, LOGOP_DELETE, offset, size);
|
|
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
b->total_size -= size;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* find the correct page */
|
2015-08-24 12:59:25 +00:00
|
|
|
p = find_page(b, offset, &offset);
|
2004-05-29 10:17:37 +00:00
|
|
|
n = 0;
|
|
|
|
|
del_start = NULL;
|
|
|
|
|
while (size > 0) {
|
|
|
|
|
len = p->size - offset;
|
|
|
|
|
if (len > size)
|
|
|
|
|
len = size;
|
|
|
|
|
if (len == p->size) {
|
|
|
|
|
if (!del_start)
|
|
|
|
|
del_start = p;
|
|
|
|
|
/* we cannot free if read only */
|
|
|
|
|
if (!(p->flags & PG_READ_ONLY))
|
2007-12-12 11:49:02 +00:00
|
|
|
qe_free(&p->data);
|
2004-05-29 10:17:37 +00:00
|
|
|
p++;
|
|
|
|
|
offset = 0;
|
|
|
|
|
n++;
|
|
|
|
|
} else {
|
|
|
|
|
update_page(p);
|
2008-01-03 09:51:29 +00:00
|
|
|
memmove(p->data + offset, p->data + offset + len,
|
2004-05-29 10:17:37 +00:00
|
|
|
p->size - offset - len);
|
|
|
|
|
p->size -= len;
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_bytes(&p->data, p->size);
|
2004-05-29 10:17:37 +00:00
|
|
|
offset += len;
|
2015-08-22 20:49:01 +00:00
|
|
|
/* XXX: should merge with adjacent pages if size becomes small? */
|
2004-05-29 10:17:37 +00:00
|
|
|
if (offset >= p->size) {
|
|
|
|
|
p++;
|
|
|
|
|
offset = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
size -= len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* now delete the requested pages */
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
b->nb_pages -= n;
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(del_start, del_start + n,
|
|
|
|
|
b->page_table + b->nb_pages - del_start);
|
2024-07-28 19:22:07 +02:00
|
|
|
// XXX: test for failure
|
|
|
|
|
qe_realloc_array(&b->page_table, b->nb_pages);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* the page cache is no longer valid */
|
|
|
|
|
b->cur_page = NULL;
|
2014-03-21 20:49:30 +00:00
|
|
|
|
|
|
|
|
return size0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-22 20:49:01 +00:00
|
|
|
/*---------------- finding buffers ----------------*/
|
|
|
|
|
|
2026-05-17 00:37:59 +03:00
|
|
|
/* Verify that buffer still exists, return argument or NULL,
|
|
|
|
|
* update handle if buffer is invalid.
|
2015-08-22 20:49:01 +00:00
|
|
|
*/
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
EditBuffer *qe_check_buffer(QEmacsState *qs, EditBuffer **sp)
|
2015-08-22 20:49:01 +00:00
|
|
|
{
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
EditBuffer *b0 = *sp;
|
2015-08-22 20:49:01 +00:00
|
|
|
EditBuffer *b;
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (b0 == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2015-08-22 20:49:01 +00:00
|
|
|
for (b = qs->first_buffer; b != NULL; b = b->next) {
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (b == b0)
|
2015-08-22 20:49:01 +00:00
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
return *sp = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-26 00:53:23 +00:00
|
|
|
#ifdef CONFIG_TINY
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
EditBuffer *qe_find_buffer_name(QEmacsState *qs, const char *name)
|
2015-08-22 20:49:01 +00:00
|
|
|
{
|
|
|
|
|
EditBuffer *b;
|
|
|
|
|
|
|
|
|
|
b = qs->first_buffer;
|
|
|
|
|
while (b != NULL) {
|
|
|
|
|
if (strequal(b->name, name))
|
|
|
|
|
return b;
|
|
|
|
|
b = b->next;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-08-27 18:59:56 +00:00
|
|
|
#define eb_cache_remove(b)
|
2015-08-26 00:53:23 +00:00
|
|
|
#define eb_cache_insert(b) 0
|
|
|
|
|
#else
|
|
|
|
|
/* return index >= 0 if found, -1-insert_pos if not found */
|
|
|
|
|
static int eb_cache_locate(EditBuffer **cache, int len, const char *name)
|
|
|
|
|
{
|
|
|
|
|
int aa, bb, m, cmp;
|
|
|
|
|
|
|
|
|
|
for (aa = 0, bb = len; aa < bb;) {
|
|
|
|
|
m = (aa + bb) >> 1;
|
|
|
|
|
cmp = strcmp(name, cache[m]->name);
|
|
|
|
|
if (cmp < 0) {
|
|
|
|
|
bb = m;
|
|
|
|
|
} else
|
|
|
|
|
if (cmp > 0) {
|
|
|
|
|
aa = m + 1;
|
|
|
|
|
} else {
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -aa - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_cache_remove(EditBuffer *b)
|
|
|
|
|
{
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
QEmacsState *qs = b->qs;
|
2015-08-26 00:53:23 +00:00
|
|
|
EditBuffer **cache = qs->buffer_cache;
|
|
|
|
|
int len = qs->buffer_cache_len;
|
|
|
|
|
int pos = eb_cache_locate(cache, len, b->name);
|
|
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (cache[pos] != b)
|
|
|
|
|
return -2;
|
|
|
|
|
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(cache + pos, cache + pos + 1, len - pos - 1);
|
2015-08-26 00:53:23 +00:00
|
|
|
len -= 1;
|
|
|
|
|
qs->buffer_cache_len = len;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_cache_insert(EditBuffer *b)
|
|
|
|
|
{
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
QEmacsState *qs = b->qs;
|
2015-08-26 00:53:23 +00:00
|
|
|
EditBuffer **cache = qs->buffer_cache;
|
|
|
|
|
int len = qs->buffer_cache_len;
|
|
|
|
|
int pos = eb_cache_locate(cache, len, b->name);
|
|
|
|
|
|
|
|
|
|
if (pos >= 0)
|
|
|
|
|
return (cache[pos] == b) ? -3 : -2;
|
|
|
|
|
|
|
|
|
|
if (len >= qs->buffer_cache_size) {
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
int size = max_int(32, len + (len >> 1) + (len >> 3));
|
2024-07-28 19:22:07 +02:00
|
|
|
cache = qe_realloc_array(&qs->buffer_cache, size);
|
2015-08-26 00:53:23 +00:00
|
|
|
if (!cache)
|
|
|
|
|
return -1;
|
|
|
|
|
qs->buffer_cache_size = size;
|
|
|
|
|
}
|
|
|
|
|
pos = -pos - 1;
|
Add macros for block comparison, copy and move
After spending a few hours debugging a stupid memcpy size error, I
decided to use a typed version of memcpy, memcmp and memmove wherever
the array type size is greater than 1.
- add blockcmp(p1, p2, n), blockcpy(p1, p2, n), blockmove(p1, p2, n)
for operation on typed arrays
- add max_uint() and min_uint()
- bumped VERSION to 5.3.4w
2022-09-27 09:31:48 +02:00
|
|
|
blockmove(cache + pos + 1, cache + pos, len - pos);
|
2015-08-26 00:53:23 +00:00
|
|
|
cache[pos] = b;
|
|
|
|
|
len += 1;
|
|
|
|
|
qs->buffer_cache_len = len;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
EditBuffer *qe_find_buffer_name(QEmacsState *qs, const char *name)
|
2015-08-26 00:53:23 +00:00
|
|
|
{
|
|
|
|
|
EditBuffer **cache = qs->buffer_cache;
|
|
|
|
|
int len = qs->buffer_cache_len;
|
|
|
|
|
int pos = eb_cache_locate(cache, len, name);
|
|
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return cache[pos];
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2015-08-22 20:49:01 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* flush the log */
|
2015-08-25 16:19:42 +00:00
|
|
|
void eb_free_log_buffer(EditBuffer *b)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2024-12-08 19:43:26 +01:00
|
|
|
// FIXME: what if log buffer is shown in a window?
|
2014-01-23 12:56:22 +00:00
|
|
|
eb_free(&b->log_buffer);
|
|
|
|
|
b->log_new_index = 0;
|
|
|
|
|
b->log_current = 0;
|
|
|
|
|
b->nb_logs = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-26 00:53:23 +00:00
|
|
|
/* rename a buffer: modify name to ensure uniqueness */
|
|
|
|
|
/* eb_set_buffer_name() may fail only for a newly created buffer */
|
|
|
|
|
int eb_set_buffer_name(EditBuffer *b, const char *name1)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2008-01-03 09:51:29 +00:00
|
|
|
char name[MAX_BUFFERNAME_SIZE];
|
2004-05-29 10:17:37 +00:00
|
|
|
int n, pos;
|
2015-08-26 00:53:23 +00:00
|
|
|
const char *prefix = "<";
|
|
|
|
|
const char *suffix = ">";
|
|
|
|
|
EditBuffer *b1;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2008-01-03 09:51:29 +00:00
|
|
|
pstrcpy(name, sizeof(name) - 10, name1);
|
2004-05-29 10:17:37 +00:00
|
|
|
pos = strlen(name);
|
2015-08-26 00:53:23 +00:00
|
|
|
if (pos > 0 && name[pos - 1] == '*') {
|
|
|
|
|
pos--;
|
|
|
|
|
prefix = "-";
|
|
|
|
|
suffix = "*";
|
|
|
|
|
}
|
|
|
|
|
n = 0;
|
|
|
|
|
/* do not allow an empty name */
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
while ((b1 = qe_find_buffer_name(b->qs, name)) != NULL || *name == '\0') {
|
2015-08-26 00:53:23 +00:00
|
|
|
if (b == b1)
|
|
|
|
|
return 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
n++;
|
2015-08-26 00:53:23 +00:00
|
|
|
snprintf(name + pos, sizeof(name) - pos, "%s%d%s", prefix, n, suffix);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2015-08-26 00:53:23 +00:00
|
|
|
/* This is the only place where b->name is modified */
|
|
|
|
|
eb_cache_remove(b);
|
2022-08-10 18:50:19 +02:00
|
|
|
pstrcpy(unconst(char *)b->name, sizeof(b->name), name);
|
2015-08-26 00:53:23 +00:00
|
|
|
/* eb_cache_insert may fail only for a newly created buffer */
|
|
|
|
|
return eb_cache_insert(b);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
EditBuffer *qe_new_buffer(QEmacsState *qs, const char *name, int flags)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
EditBuffer *b;
|
2007-12-18 17:59:48 +00:00
|
|
|
EditBuffer **pb;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2026-05-02 08:51:35 +02:00
|
|
|
if (flags & (BC_REUSE | BC_CLEAR)) {
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
b = qe_find_buffer_name(qs, name);
|
|
|
|
|
if (b != NULL) {
|
|
|
|
|
if (flags & BC_CLEAR)
|
|
|
|
|
eb_clear(b);
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
flags &= ~(BC_REUSE | BC_CLEAR);
|
|
|
|
|
|
2007-12-12 11:49:02 +00:00
|
|
|
b = qe_mallocz(EditBuffer);
|
2024-12-08 19:43:26 +01:00
|
|
|
if (!b) {
|
|
|
|
|
qe_put_error(qs, "Out of memory for buffer '%s'", name);
|
2004-05-29 10:17:37 +00:00
|
|
|
return NULL;
|
2024-12-08 19:43:26 +01:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2024-08-27 19:32:10 +02:00
|
|
|
b->qs = qs;
|
2014-01-15 19:44:24 +00:00
|
|
|
b->flags = flags & ~BF_STYLES;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
/* set default data type */
|
|
|
|
|
b->data_type = &raw_data_type;
|
|
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
/* initial value of save_log: 0 or 1 */
|
2004-05-29 10:17:37 +00:00
|
|
|
b->save_log = ((flags & BF_SAVELOG) != 0);
|
|
|
|
|
|
2008-03-25 10:13:37 +00:00
|
|
|
/* initialize default mode stuff */
|
2014-01-21 00:01:20 +00:00
|
|
|
b->tab_width = qs->default_tab_width;
|
|
|
|
|
b->fill_column = qs->default_fill_column;
|
2014-02-05 00:56:48 +00:00
|
|
|
b->eol_type = qs->default_eol_type;
|
2026-05-23 22:25:52 +02:00
|
|
|
b->atime = b->mtime = b->ctime = get_clock_ms();
|
2008-03-25 10:13:37 +00:00
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
/* set the buffer name to a unique name */
|
|
|
|
|
// XXX: `b` is not in the buffer list nor in the buffer cache
|
|
|
|
|
// `eb_set_buffer_name` will insert it into the cache.
|
|
|
|
|
// This is somewhat sloppy.
|
|
|
|
|
if (eb_set_buffer_name(b, name)) {
|
2024-12-08 19:43:26 +01:00
|
|
|
qe_put_error(qs, "Cannot set buffer name '%s'", name);
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
qe_free(&b);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-18 17:59:48 +00:00
|
|
|
/* add buffer in global buffer list (at end for system buffers) */
|
|
|
|
|
pb = &qs->first_buffer;
|
|
|
|
|
if (*b->name == '*') {
|
2007-12-20 20:39:18 +00:00
|
|
|
while (*pb)
|
|
|
|
|
pb = &(*pb)->next;
|
2007-12-18 17:59:48 +00:00
|
|
|
}
|
|
|
|
|
b->next = *pb;
|
|
|
|
|
*pb = b;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2008-03-30 16:10:15 +00:00
|
|
|
if (flags & BF_UTF8) {
|
2014-02-05 00:56:48 +00:00
|
|
|
eb_set_charset(b, &charset_utf8, b->eol_type);
|
2014-02-10 20:29:26 +00:00
|
|
|
} else
|
|
|
|
|
if (flags & BF_RAW) {
|
|
|
|
|
eb_set_charset(b, &charset_raw, EOL_UNIX);
|
2008-03-30 16:10:15 +00:00
|
|
|
} else {
|
|
|
|
|
/* CG: default charset should be selectable */
|
2014-02-05 00:56:48 +00:00
|
|
|
eb_set_charset(b, &charset_8859_1, b->eol_type);
|
2008-03-30 16:10:15 +00:00
|
|
|
}
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* add mark move callback */
|
2014-01-14 03:29:36 +00:00
|
|
|
eb_add_callback(b, eb_offset_callback, &b->mark, 0);
|
|
|
|
|
eb_add_callback(b, eb_offset_callback, &b->offset, 1);
|
2005-05-08 15:33:24 +00:00
|
|
|
|
2014-01-15 19:44:24 +00:00
|
|
|
if (flags & BF_STYLES)
|
|
|
|
|
eb_create_style_buffer(b, flags);
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
void eb_clear(EditBuffer *b)
|
|
|
|
|
{
|
|
|
|
|
b->flags &= ~BF_READONLY;
|
2014-01-13 23:38:15 +00:00
|
|
|
|
|
|
|
|
/* XXX: should just reset logging instead of disabling it */
|
2007-12-20 11:49:54 +00:00
|
|
|
b->save_log = 0;
|
2014-01-14 03:29:36 +00:00
|
|
|
b->last_log = 0;
|
2007-12-20 11:49:54 +00:00
|
|
|
eb_delete(b, 0, b->total_size);
|
2015-08-25 16:19:42 +00:00
|
|
|
eb_free_log_buffer(b);
|
2007-12-20 11:49:54 +00:00
|
|
|
|
2017-05-07 06:08:57 +00:00
|
|
|
#ifdef CONFIG_MMAP
|
2014-05-18 11:01:55 +00:00
|
|
|
eb_munmap_buffer(b);
|
|
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
/* close and reset file handle */
|
2014-05-26 14:35:37 +00:00
|
|
|
if (b->map_handle > 0) {
|
|
|
|
|
close(b->map_handle);
|
2007-12-20 11:49:54 +00:00
|
|
|
}
|
2014-05-26 14:35:37 +00:00
|
|
|
b->map_handle = 0;
|
2017-05-07 06:08:57 +00:00
|
|
|
#endif
|
2015-08-25 16:19:42 +00:00
|
|
|
b->modified = 0;
|
2007-12-20 11:49:54 +00:00
|
|
|
|
|
|
|
|
/* TODO: clear buffer structure */
|
|
|
|
|
//memset(b, 0, offsetof(EditBuffer, remanent_area));
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
void eb_free(EditBuffer **bp)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2014-01-23 12:56:22 +00:00
|
|
|
if (*bp) {
|
|
|
|
|
EditBuffer *b = *bp;
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
QEmacsState *qs = b->qs;
|
2014-01-23 12:56:22 +00:00
|
|
|
EditBuffer **pb;
|
2015-08-27 22:51:56 +00:00
|
|
|
EditBuffer *b1;
|
2014-01-23 12:56:22 +00:00
|
|
|
|
2026-06-23 16:24:02 +02:00
|
|
|
// XXX should use qe_free_mode_data()
|
2015-08-27 15:31:59 +00:00
|
|
|
/* free b->mode_data_list by calling destructors */
|
|
|
|
|
while (b->mode_data_list) {
|
|
|
|
|
QEModeData *md = b->mode_data_list;
|
|
|
|
|
b->mode_data_list = md->next;
|
|
|
|
|
md->next = NULL;
|
|
|
|
|
if (md->mode && md->mode->mode_free)
|
|
|
|
|
md->mode->mode_free(b, md);
|
2026-06-23 16:24:02 +02:00
|
|
|
if (qs->key_ctx.grab_key_opaque == md)
|
|
|
|
|
qs->key_ctx.grab_key_opaque = NULL;
|
2015-08-27 15:31:59 +00:00
|
|
|
qe_free(&md);
|
|
|
|
|
}
|
2014-01-23 12:56:22 +00:00
|
|
|
|
|
|
|
|
/* free each callback */
|
|
|
|
|
while (b->first_callback) {
|
|
|
|
|
EditBufferCallbackList *cb = b->first_callback;
|
|
|
|
|
b->first_callback = cb->next;
|
|
|
|
|
qe_free(&cb);
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
eb_delete_properties(b, 0, INT_MAX, QE_PROP_ALL);
|
2015-08-26 00:53:23 +00:00
|
|
|
eb_cache_remove(b);
|
2024-12-08 19:43:26 +01:00
|
|
|
/* eb_clear frees b->log_buffer.
|
|
|
|
|
* it should also call eb_free_style_buffer(b)
|
2026-06-13 18:08:40 +02:00
|
|
|
* and eb_delete_properties(b, 0, INT_MAX, QE_PROP_ALL);
|
2024-12-08 19:43:26 +01:00
|
|
|
*/
|
2014-01-23 12:56:22 +00:00
|
|
|
eb_clear(b);
|
2007-12-18 17:59:48 +00:00
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
/* suppress from buffer list */
|
|
|
|
|
pb = &qs->first_buffer;
|
2015-08-27 22:51:56 +00:00
|
|
|
while ((b1 = *pb) != NULL) {
|
|
|
|
|
if (b1->log_buffer == b) {
|
|
|
|
|
b1->log_buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (b1->b_styles == b) {
|
|
|
|
|
b1->b_styles = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (b1 == b)
|
|
|
|
|
*pb = b1->next;
|
|
|
|
|
else
|
|
|
|
|
pb = &b1->next;
|
2014-01-23 12:56:22 +00:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
if (b == qs->trace_buffer)
|
|
|
|
|
qs->trace_buffer = NULL;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2024-12-08 19:43:26 +01:00
|
|
|
if (b->flags & BF_SYSTEM) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < NB_YANK_BUFFERS; i++) {
|
|
|
|
|
if (qs->yank_buffers[i] == b)
|
|
|
|
|
qs->yank_buffers[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
eb_free_style_buffer(b);
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2015-08-27 15:31:59 +00:00
|
|
|
qe_free(&b->saved_data);
|
2026-06-23 16:24:02 +02:00
|
|
|
if (qs->key_ctx.grab_key_opaque == b)
|
|
|
|
|
qs->key_ctx.grab_key_opaque = NULL;
|
2025-02-05 12:52:48 +01:00
|
|
|
// XXX: cannot use qe_free(bp) because *bp may have been set to NULL
|
|
|
|
|
// already, eg: eb_free_log_buffer() and eb_free_style_buffer()
|
|
|
|
|
qe_free(&b);
|
|
|
|
|
*bp = NULL;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 19:43:26 +01:00
|
|
|
EditBuffer *qe_find_buffer_filename(QEmacsState *qs, const char *filename)
|
2008-01-04 22:24:37 +00:00
|
|
|
{
|
|
|
|
|
EditBuffer *b;
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
for (b = qs->first_buffer; b != NULL; b = b->next) {
|
2004-05-29 10:17:37 +00:00
|
|
|
/* XXX: should also use stat to ensure this is same file */
|
2008-01-08 03:42:53 +00:00
|
|
|
if (strequal(b->filename, filename))
|
2004-05-29 10:17:37 +00:00
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-19 19:20:57 +00:00
|
|
|
/* Find a window attached to a given buffer, different from s */
|
|
|
|
|
EditState *eb_find_window(EditBuffer *b, EditState *s)
|
2006-12-11 23:10:33 +00:00
|
|
|
{
|
2015-08-19 19:20:57 +00:00
|
|
|
EditState *e;
|
2006-12-11 23:10:33 +00:00
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (!b)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
for (e = b->qs->first_window; e != NULL; e = e->next_window) {
|
2015-08-19 19:20:57 +00:00
|
|
|
if (e != s && e->b == b)
|
|
|
|
|
break;
|
2006-12-11 23:10:33 +00:00
|
|
|
}
|
2015-08-19 19:20:57 +00:00
|
|
|
return e;
|
2006-12-11 23:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
void qe_trace_bytes(QEmacsState *qs, const void *buf, int size, int state)
|
2006-12-11 23:10:33 +00:00
|
|
|
{
|
2007-12-21 12:30:55 +00:00
|
|
|
EditBuffer *b = qs->trace_buffer;
|
2006-12-11 23:10:33 +00:00
|
|
|
EditState *e;
|
2015-08-26 00:24:14 +00:00
|
|
|
const char *str = NULL;
|
|
|
|
|
const u8 *p0, *endp, *p;
|
2022-09-08 13:47:02 +02:00
|
|
|
int line, col, len, flush;
|
2022-08-27 20:11:38 +02:00
|
|
|
int prev_state = qs->trace_buffer_state;
|
2015-08-26 00:24:14 +00:00
|
|
|
|
2022-08-27 20:11:38 +02:00
|
|
|
/* prevent tracing if nagivating the *trace* buffer */
|
|
|
|
|
if (!b || !(qs->trace_flags & state)
|
|
|
|
|
|| (qs->active_window && qs->active_window->b == b))
|
2015-08-26 00:24:14 +00:00
|
|
|
return;
|
|
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
/* output at end of trace buffer */
|
|
|
|
|
b->offset = b->total_size;
|
2015-08-26 00:24:14 +00:00
|
|
|
if (size < 0)
|
|
|
|
|
size = strlen(buf);
|
|
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
eb_get_pos(b, &line, &col, b->offset);
|
2022-08-27 20:11:38 +02:00
|
|
|
flush = state & EB_TRACE_FLUSH;
|
|
|
|
|
state &= ~EB_TRACE_FLUSH;
|
|
|
|
|
if (prev_state == state) {
|
|
|
|
|
if (state == EB_TRACE_COMMAND)
|
|
|
|
|
flush = 1;
|
|
|
|
|
} else {
|
|
|
|
|
if (!(state <= EB_TRACE_COMMAND && prev_state <= state)
|
|
|
|
|
&& !(state == EB_TRACE_EMULATE && prev_state == EB_TRACE_PTY))
|
|
|
|
|
flush = 1;
|
|
|
|
|
}
|
|
|
|
|
if (flush && col) {
|
2022-09-08 13:47:02 +02:00
|
|
|
eb_putc(b, '\n');
|
2022-08-27 20:11:38 +02:00
|
|
|
col = 0;
|
|
|
|
|
}
|
|
|
|
|
if (col == 0 || prev_state != state) {
|
2024-09-28 14:07:46 +02:00
|
|
|
size_t i;
|
2015-08-26 00:24:14 +00:00
|
|
|
qs->trace_buffer_state = state;
|
2024-09-28 14:07:46 +02:00
|
|
|
for (i = 0; i < qe_trace_defs_count; i++) {
|
|
|
|
|
if (state == qe_trace_defs[i].flags) {
|
|
|
|
|
str = qe_trace_defs[i].name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-08-26 00:24:14 +00:00
|
|
|
}
|
|
|
|
|
if (str) {
|
2022-08-27 20:36:44 +02:00
|
|
|
int len1 = (int)strlen(str);
|
2022-08-27 20:11:38 +02:00
|
|
|
int width = (col == 0 ? 7 :
|
2024-09-13 01:05:12 +02:00
|
|
|
col <= 24 ? 31 - col :
|
|
|
|
|
col <= 52 ? 59 - col : len1 + 2);
|
2022-08-27 20:11:38 +02:00
|
|
|
col += eb_printf(b, "%*s: ", width, str);
|
2015-08-26 00:24:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p0 = buf;
|
|
|
|
|
endp = p0 + size;
|
|
|
|
|
|
2024-09-13 01:05:12 +02:00
|
|
|
#define MAX_TRACE_WIDTH 98
|
2015-08-26 00:24:14 +00:00
|
|
|
for (p = p0; p0 < endp; p++) {
|
|
|
|
|
while (p >= endp || *p < 32 || *p >= 127 || *p == '\\') {
|
|
|
|
|
if (p0 >= endp)
|
2006-12-31 19:34:00 +00:00
|
|
|
break;
|
2015-08-26 00:24:14 +00:00
|
|
|
if (col >= MAX_TRACE_WIDTH) {
|
2022-09-08 13:47:02 +02:00
|
|
|
eb_puts(b, "\n | ");
|
2015-08-26 00:24:14 +00:00
|
|
|
col = 9;
|
2006-12-31 19:34:00 +00:00
|
|
|
}
|
2015-08-26 00:24:14 +00:00
|
|
|
if (p0 < p) {
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
len = min_offset(p - p0, MAX_TRACE_WIDTH - col);
|
2022-09-08 13:47:02 +02:00
|
|
|
eb_printf(b, "%.*s", len, p0);
|
2015-08-26 00:24:14 +00:00
|
|
|
p0 += len;
|
|
|
|
|
col += len;
|
|
|
|
|
continue;
|
2006-12-31 19:34:00 +00:00
|
|
|
}
|
2015-08-26 00:24:14 +00:00
|
|
|
if (p < endp) {
|
2022-08-31 22:26:38 +02:00
|
|
|
char buf1[16];
|
2026-06-17 19:12:41 +02:00
|
|
|
len = strquote_byte(buf1, sizeof buf1, *p, SQB_USE_CONTROL);
|
2022-09-08 13:47:02 +02:00
|
|
|
eb_puts(b, buf1);
|
2015-08-26 00:24:14 +00:00
|
|
|
p0 = p + 1;
|
2022-08-28 20:28:40 +02:00
|
|
|
col += len;
|
2006-12-31 19:34:00 +00:00
|
|
|
}
|
2015-08-26 00:24:14 +00:00
|
|
|
break;
|
2006-12-11 23:10:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-08-27 20:11:38 +02:00
|
|
|
/* Make output visible in window */
|
2015-08-26 00:24:14 +00:00
|
|
|
/* XXX: proper tracking should do this automatically */
|
|
|
|
|
e = eb_find_window(b, NULL);
|
2022-08-27 20:11:38 +02:00
|
|
|
if (e)
|
2022-09-08 13:47:02 +02:00
|
|
|
e->offset = b->offset;
|
2006-12-11 23:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/************************************************************/
|
|
|
|
|
/* callbacks */
|
|
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
int eb_add_callback(EditBuffer *b, EditBufferCallback cb,
|
|
|
|
|
void *opaque, int arg)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
EditBufferCallbackList *l;
|
|
|
|
|
|
2014-01-23 12:56:22 +00:00
|
|
|
l = qe_mallocz(EditBufferCallbackList);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!l)
|
|
|
|
|
return -1;
|
|
|
|
|
l->callback = cb;
|
|
|
|
|
l->opaque = opaque;
|
2014-01-14 03:29:36 +00:00
|
|
|
l->arg = arg;
|
2004-05-29 10:17:37 +00:00
|
|
|
l->next = b->first_callback;
|
|
|
|
|
b->first_callback = l;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-20 20:39:18 +00:00
|
|
|
void eb_free_callback(EditBuffer *b, EditBufferCallback cb, void *opaque)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
EditBufferCallbackList **pl, *l;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2005-05-11 14:35:54 +00:00
|
|
|
for (pl = &b->first_callback; (*pl) != NULL; pl = &(*pl)->next) {
|
2004-05-29 10:17:37 +00:00
|
|
|
l = *pl;
|
|
|
|
|
if (l->callback == cb && l->opaque == opaque) {
|
|
|
|
|
*pl = l->next;
|
2007-12-12 11:49:02 +00:00
|
|
|
qe_free(&l);
|
2004-05-29 10:17:37 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* standard callback to move offsets */
|
2015-09-16 22:18:22 +00:00
|
|
|
void eb_offset_callback(qe__unused__ EditBuffer *b, void *opaque, int edge,
|
2007-12-18 17:59:48 +00:00
|
|
|
enum LogOperation op, int offset, int size)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
int *offset_ptr = opaque;
|
|
|
|
|
|
2005-05-11 14:35:54 +00:00
|
|
|
switch (op) {
|
2004-05-29 10:17:37 +00:00
|
|
|
case LOGOP_INSERT:
|
|
|
|
|
if (*offset_ptr > offset)
|
|
|
|
|
*offset_ptr += size;
|
2014-01-14 03:29:36 +00:00
|
|
|
/* special case for buffer's own point position and shell cursor:
|
2008-03-25 10:13:37 +00:00
|
|
|
* edge position is pushed right */
|
2014-01-14 03:29:36 +00:00
|
|
|
if (*offset_ptr == offset && edge)
|
2008-03-25 10:13:37 +00:00
|
|
|
*offset_ptr += size;
|
2004-05-29 10:17:37 +00:00
|
|
|
break;
|
|
|
|
|
case LOGOP_DELETE:
|
|
|
|
|
if (*offset_ptr > offset) {
|
|
|
|
|
*offset_ptr -= size;
|
|
|
|
|
if (*offset_ptr < offset)
|
|
|
|
|
*offset_ptr = offset;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-15 19:44:24 +00:00
|
|
|
int eb_create_style_buffer(EditBuffer *b, int flags)
|
|
|
|
|
{
|
|
|
|
|
if (b->b_styles) {
|
2024-09-07 12:31:31 +02:00
|
|
|
/* FIXME: should extend style width if needed */
|
2014-01-15 19:44:24 +00:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
2015-08-19 19:20:57 +00:00
|
|
|
char name[MAX_BUFFERNAME_SIZE];
|
2022-08-31 08:59:39 -04:00
|
|
|
snprintf(name, sizeof(name), "*S<%.*s>", MAX_BUFFERNAME_SIZE - 5, b->name);
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
b->b_styles = qe_new_buffer(b->qs, name, BF_SYSTEM | BF_IS_STYLE | BF_RAW);
|
|
|
|
|
if (!b->b_styles)
|
|
|
|
|
return -1;
|
2014-01-15 19:44:24 +00:00
|
|
|
b->flags |= flags & BF_STYLES;
|
2024-09-07 12:31:31 +02:00
|
|
|
b->style_shift = (((unsigned)flags & BF_STYLES) / BF_STYLE1) - 1;
|
2014-01-15 19:44:24 +00:00
|
|
|
b->style_bytes = 1 << b->style_shift;
|
|
|
|
|
eb_set_style(b, 0, LOGOP_INSERT, 0, b->total_size);
|
|
|
|
|
eb_add_callback(b, eb_style_callback, NULL, 0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void eb_free_style_buffer(EditBuffer *b)
|
|
|
|
|
{
|
2024-12-08 19:43:26 +01:00
|
|
|
// FIXME: what if style buffer is shown in a window?
|
2014-01-23 12:56:22 +00:00
|
|
|
eb_free(&b->b_styles);
|
2014-01-15 19:44:24 +00:00
|
|
|
b->style_shift = b->style_bytes = 0;
|
|
|
|
|
eb_free_callback(b, eb_style_callback, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX: should compress styles buffer with run length encoding */
|
2017-04-12 07:33:20 +00:00
|
|
|
void eb_set_style(EditBuffer *b, QETermStyle style, enum LogOperation op,
|
2014-01-15 19:44:24 +00:00
|
|
|
int offset, int size)
|
|
|
|
|
{
|
2017-04-12 07:33:20 +00:00
|
|
|
union {
|
2017-04-14 06:59:17 +00:00
|
|
|
uint64_t buf8[256 / 8];
|
|
|
|
|
uint32_t buf4[256 / 4];
|
|
|
|
|
uint16_t buf2[256 / 2];
|
2017-04-12 07:33:20 +00:00
|
|
|
unsigned char buf[256];
|
|
|
|
|
QETermStyle align;
|
|
|
|
|
} s;
|
2014-01-15 19:44:24 +00:00
|
|
|
int i, len;
|
|
|
|
|
|
|
|
|
|
if (!b->b_styles || !size)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
offset = (offset >> b->char_shift) << b->style_shift;
|
|
|
|
|
size = (size >> b->char_shift) << b->style_shift;
|
|
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
|
case LOGOP_WRITE:
|
|
|
|
|
case LOGOP_INSERT:
|
2015-08-26 00:53:23 +00:00
|
|
|
/* XXX: should use a single loop to initialize buf */
|
|
|
|
|
/* XXX: should initialize buf just once */
|
2014-01-15 19:44:24 +00:00
|
|
|
while (size > 0) {
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
len = min_offset(size, ssizeof(s.buf));
|
2017-04-12 07:33:20 +00:00
|
|
|
if (b->style_shift == 3) {
|
2017-04-14 06:59:17 +00:00
|
|
|
for (i = 0; i < len >> 3; i++) {
|
|
|
|
|
s.buf8[i] = style;
|
2017-04-12 07:33:20 +00:00
|
|
|
}
|
|
|
|
|
} else
|
2014-01-15 19:44:24 +00:00
|
|
|
if (b->style_shift == 2) {
|
2017-04-14 06:59:17 +00:00
|
|
|
for (i = 0; i < len >> 2; i++) {
|
|
|
|
|
s.buf4[i] = style;
|
2014-01-15 19:44:24 +00:00
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (b->style_shift == 1) {
|
2017-04-14 06:59:17 +00:00
|
|
|
for (i = 0; i < len >> 1; i++) {
|
|
|
|
|
s.buf2[i] = style;
|
2014-01-15 19:44:24 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2017-04-12 07:33:20 +00:00
|
|
|
memset(s.buf, style, len);
|
2014-01-15 19:44:24 +00:00
|
|
|
}
|
|
|
|
|
if (op == LOGOP_WRITE)
|
2017-04-12 07:33:20 +00:00
|
|
|
eb_write(b->b_styles, offset, s.buf, len);
|
2014-01-15 19:44:24 +00:00
|
|
|
else
|
2017-04-12 07:33:20 +00:00
|
|
|
eb_insert(b->b_styles, offset, s.buf, len);
|
2014-01-15 19:44:24 +00:00
|
|
|
size -= len;
|
|
|
|
|
offset += len;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case LOGOP_DELETE:
|
|
|
|
|
eb_delete(b->b_styles, offset, size);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void eb_style_callback(EditBuffer *b, void *opaque, int arg,
|
|
|
|
|
enum LogOperation op, int offset, int size)
|
|
|
|
|
{
|
|
|
|
|
eb_set_style(b, b->cur_style, op, offset, size);
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************/
|
|
|
|
|
/* undo buffer */
|
|
|
|
|
|
2008-01-03 09:51:29 +00:00
|
|
|
static void eb_addlog(EditBuffer *b, enum LogOperation op,
|
2004-05-29 10:17:37 +00:00
|
|
|
int offset, int size)
|
|
|
|
|
{
|
|
|
|
|
int was_modified, len, size_trailer;
|
|
|
|
|
LogBuffer lb;
|
|
|
|
|
EditBufferCallbackList *l;
|
|
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
/* callbacks and logging disabled for composite undo phase */
|
|
|
|
|
if (b->save_log & 2)
|
|
|
|
|
return;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* call each callback */
|
2005-05-11 14:35:54 +00:00
|
|
|
for (l = b->first_callback; l != NULL; l = l->next) {
|
2014-01-14 03:29:36 +00:00
|
|
|
l->callback(b, l->opaque, l->arg, op, offset, size);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
was_modified = b->modified;
|
|
|
|
|
b->modified = 1;
|
2026-05-23 22:25:52 +02:00
|
|
|
b->mtime = get_clock_ms();
|
2014-01-13 23:38:15 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!b->save_log)
|
|
|
|
|
return;
|
2014-01-13 23:38:15 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!b->log_buffer) {
|
2007-12-18 17:59:48 +00:00
|
|
|
char buf[MAX_BUFFERNAME_SIZE];
|
2007-12-27 10:04:09 +00:00
|
|
|
/* Name should be unique because b->name is, but b->name may
|
|
|
|
|
* later change if buffer is written to a different file. This
|
|
|
|
|
* should not be a problem since this log buffer is never
|
|
|
|
|
* referenced by name.
|
|
|
|
|
*/
|
2022-08-31 08:59:39 -04:00
|
|
|
snprintf(buf, sizeof(buf), "*L<%.*s>", MAX_BUFFERNAME_SIZE - 5, b->name);
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
b->log_buffer = qe_new_buffer(b->qs, buf, BF_SYSTEM | BF_IS_LOG | BF_RAW);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!b->log_buffer)
|
|
|
|
|
return;
|
2015-08-27 22:51:56 +00:00
|
|
|
b->log_new_index = 0;
|
|
|
|
|
b->log_current = 0;
|
|
|
|
|
b->last_log = 0;
|
|
|
|
|
b->last_log_char = 0;
|
|
|
|
|
b->nb_logs = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
/* XXX: better test to limit size */
|
|
|
|
|
if (b->nb_logs >= (NB_LOGS_MAX-1)) {
|
|
|
|
|
/* no free space, delete least recent entry */
|
2014-01-13 23:38:15 +00:00
|
|
|
/* XXX: should check undo record integrity */
|
|
|
|
|
eb_read(b->log_buffer, 0, &lb, sizeof(lb));
|
2004-05-29 10:17:37 +00:00
|
|
|
len = lb.size;
|
|
|
|
|
if (lb.op == LOGOP_INSERT)
|
|
|
|
|
len = 0;
|
|
|
|
|
len += sizeof(LogBuffer) + sizeof(int);
|
|
|
|
|
eb_delete(b->log_buffer, 0, len);
|
|
|
|
|
b->log_new_index -= len;
|
|
|
|
|
if (b->log_current > 1)
|
|
|
|
|
b->log_current -= len;
|
|
|
|
|
b->nb_logs--;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-14 03:29:36 +00:00
|
|
|
/* If inserting, try and coalesce log record with previous */
|
|
|
|
|
if (op == LOGOP_INSERT && b->last_log == LOGOP_INSERT
|
2014-05-27 22:59:48 +00:00
|
|
|
&& (size_t)b->log_new_index >= sizeof(lb) + sizeof(int)
|
2014-01-14 03:29:36 +00:00
|
|
|
&& eb_read(b->log_buffer, b->log_new_index - sizeof(int), &size_trailer,
|
|
|
|
|
sizeof(int)) == sizeof(int)
|
|
|
|
|
&& size_trailer == 0
|
|
|
|
|
&& eb_read(b->log_buffer, b->log_new_index - sizeof(lb) - sizeof(int), &lb,
|
|
|
|
|
sizeof(lb)) == sizeof(lb)
|
|
|
|
|
&& lb.op == LOGOP_INSERT
|
|
|
|
|
&& lb.offset + lb.size == offset) {
|
|
|
|
|
lb.size += size;
|
|
|
|
|
eb_write(b->log_buffer, b->log_new_index - sizeof(lb) - sizeof(int), &lb, sizeof(lb));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b->last_log = op;
|
|
|
|
|
|
2014-01-13 23:38:15 +00:00
|
|
|
/* XXX: should check undo record integrity */
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* header */
|
2007-12-27 10:04:09 +00:00
|
|
|
lb.pad1 = '\n'; /* make log buffer display readable */
|
|
|
|
|
lb.pad2 = ':';
|
2004-05-29 10:17:37 +00:00
|
|
|
lb.op = op;
|
|
|
|
|
lb.offset = offset;
|
|
|
|
|
lb.size = size;
|
|
|
|
|
lb.was_modified = was_modified;
|
2014-01-13 23:38:15 +00:00
|
|
|
eb_write(b->log_buffer, b->log_new_index, &lb, sizeof(lb));
|
|
|
|
|
b->log_new_index += sizeof(lb);
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
/* data */
|
2005-05-11 14:35:54 +00:00
|
|
|
switch (op) {
|
2004-05-29 10:17:37 +00:00
|
|
|
case LOGOP_DELETE:
|
|
|
|
|
case LOGOP_WRITE:
|
|
|
|
|
eb_insert_buffer(b->log_buffer, b->log_new_index, b, offset, size);
|
|
|
|
|
b->log_new_index += size;
|
|
|
|
|
size_trailer = size;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
size_trailer = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* trailer */
|
2006-12-31 19:34:00 +00:00
|
|
|
eb_write(b->log_buffer, b->log_new_index, &size_trailer, sizeof(int));
|
2004-05-29 10:17:37 +00:00
|
|
|
b->log_new_index += sizeof(int);
|
|
|
|
|
|
|
|
|
|
b->nb_logs++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void do_undo(EditState *s)
|
|
|
|
|
{
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
QEmacsState *qs = s->qs;
|
2004-05-29 10:17:37 +00:00
|
|
|
EditBuffer *b = s->b;
|
2014-01-13 23:38:15 +00:00
|
|
|
int log_index, size_trailer;
|
2004-05-29 10:17:37 +00:00
|
|
|
LogBuffer lb;
|
|
|
|
|
|
2014-01-31 14:50:13 +00:00
|
|
|
if (!b->log_buffer) {
|
2024-12-03 22:52:55 +01:00
|
|
|
put_error(s, "No undo information");
|
2004-05-29 10:17:37 +00:00
|
|
|
return;
|
2014-01-31 14:50:13 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-09 16:54:17 +02:00
|
|
|
/* deactivate region hilite and multi-cursor */
|
2014-01-31 14:50:13 +00:00
|
|
|
s->region_style = 0;
|
2024-08-09 16:54:17 +02:00
|
|
|
s->multi_cursor_active = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-01-14 03:29:36 +00:00
|
|
|
/* Should actually keep undo state current until new logs are added */
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (qs->last_cmd_func != (CmdFunc)do_undo
|
|
|
|
|
&& qs->last_cmd_func != (CmdFunc)do_redo) {
|
2004-05-29 10:17:37 +00:00
|
|
|
b->log_current = 0;
|
2014-01-14 03:29:36 +00:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
if (b->log_current == 0) {
|
|
|
|
|
log_index = b->log_new_index;
|
|
|
|
|
} else {
|
|
|
|
|
log_index = b->log_current - 1;
|
|
|
|
|
}
|
|
|
|
|
if (log_index == 0) {
|
2024-12-03 22:52:55 +01:00
|
|
|
put_error(s, "No further undo information");
|
2004-05-29 10:17:37 +00:00
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
put_status(s, "Undo!");
|
|
|
|
|
}
|
Add `repeat-mode` (#34)
- add `repeat` command on `C-x z`
- add `repeat-mode`, always enabled
- cycle all matching tags in current file on `goto-tag` and `find-tag`
- set up `repeat-mode` for these commands:
- `undo` on `C-x u` (`u` repeats `undo`, `r` performs `redo`)
- `undo` on `C-x r` (`r` repeats `redo`, `u` performs `undo`)
- `find-window-left`, `find-window-right`, `find-window-up`, `find-window-dow`
repeat navigation on `up`, `down`, `left`, `right`
- `next-error`, `previous-error`: `M-n` and `M-p` repeat in corresponding direction
- `next-buffer`, `previous-buffer: repeat buffers nagivation with `left` and `right`
- `enlarge-window` / `shrink-window`: repeat resizing on `^`, `v`, `{`, `}`
and cursor movement keys
- `goto-tag` on `C-x ,` goto next tag with `,` and `.`
- `call-last-kbd-macro` on `C-x e`: repeat macro on `e`
- add `eb_count_buffers` and `eb_get_buffer_from_index` for safe buffer navigation
- add transient bindings, known as repeat maps in GNU emacs
- pass `KeyDef **lp` (aka key maps) instead of mode for binding commands
- replace `do_next_buffer` and `do_prevous_buffer` with repeatable command
`do_buffer_navigation`
- fix `bufed_select` crash bug when selecting buffer from a regular window
2024-05-25 23:37:05 +02:00
|
|
|
if (!qs->first_transient_key
|
|
|
|
|
&& (qs->last_key == 'u' || qs->last_key == 'u')) {
|
2024-12-03 22:52:55 +01:00
|
|
|
put_status(s, "Repeat with 'u', 'r'");
|
Add `repeat-mode` (#34)
- add `repeat` command on `C-x z`
- add `repeat-mode`, always enabled
- cycle all matching tags in current file on `goto-tag` and `find-tag`
- set up `repeat-mode` for these commands:
- `undo` on `C-x u` (`u` repeats `undo`, `r` performs `redo`)
- `undo` on `C-x r` (`r` repeats `redo`, `u` performs `undo`)
- `find-window-left`, `find-window-right`, `find-window-up`, `find-window-dow`
repeat navigation on `up`, `down`, `left`, `right`
- `next-error`, `previous-error`: `M-n` and `M-p` repeat in corresponding direction
- `next-buffer`, `previous-buffer: repeat buffers nagivation with `left` and `right`
- `enlarge-window` / `shrink-window`: repeat resizing on `^`, `v`, `{`, `}`
and cursor movement keys
- `goto-tag` on `C-x ,` goto next tag with `,` and `.`
- `call-last-kbd-macro` on `C-x e`: repeat macro on `e`
- add `eb_count_buffers` and `eb_get_buffer_from_index` for safe buffer navigation
- add transient bindings, known as repeat maps in GNU emacs
- pass `KeyDef **lp` (aka key maps) instead of mode for binding commands
- replace `do_next_buffer` and `do_prevous_buffer` with repeatable command
`do_buffer_navigation`
- fix `bufed_select` crash bug when selecting buffer from a regular window
2024-05-25 23:37:05 +02:00
|
|
|
qe_register_transient_binding(qs, "undo", "u");
|
|
|
|
|
qe_register_transient_binding(qs, "redo", "r");
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* go backward */
|
|
|
|
|
log_index -= sizeof(int);
|
2007-12-15 16:33:20 +00:00
|
|
|
eb_read(b->log_buffer, log_index, &size_trailer, sizeof(int));
|
2004-05-29 10:17:37 +00:00
|
|
|
log_index -= size_trailer + sizeof(LogBuffer);
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* log_current is 1 + index to have zero as default value */
|
|
|
|
|
b->log_current = log_index + 1;
|
|
|
|
|
|
|
|
|
|
/* play the log entry */
|
2007-12-15 16:33:20 +00:00
|
|
|
eb_read(b->log_buffer, log_index, &lb, sizeof(LogBuffer));
|
2004-05-29 10:17:37 +00:00
|
|
|
log_index += sizeof(LogBuffer);
|
|
|
|
|
|
2014-01-14 03:29:36 +00:00
|
|
|
b->last_log = 0; /* prevent log compression */
|
|
|
|
|
|
2005-05-11 14:35:54 +00:00
|
|
|
switch (lb.op) {
|
2004-05-29 10:17:37 +00:00
|
|
|
case LOGOP_WRITE:
|
|
|
|
|
/* we must disable the log because we want to record a single
|
|
|
|
|
write (we should have the single operation: eb_write_buffer) */
|
2014-01-13 23:38:15 +00:00
|
|
|
b->save_log |= 2;
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_delete(b, lb.offset, lb.size);
|
|
|
|
|
eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
|
2014-01-13 23:38:15 +00:00
|
|
|
b->save_log &= ~2;
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_addlog(b, LOGOP_WRITE, lb.offset, lb.size);
|
|
|
|
|
s->offset = lb.offset + lb.size;
|
|
|
|
|
break;
|
|
|
|
|
case LOGOP_DELETE:
|
|
|
|
|
/* we must also disable the log there because the log buffer
|
|
|
|
|
would be modified BEFORE we insert it by the implicit
|
|
|
|
|
eb_addlog */
|
2014-01-13 23:38:15 +00:00
|
|
|
b->save_log |= 2;
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
|
2014-01-13 23:38:15 +00:00
|
|
|
b->save_log &= ~2;
|
2004-05-29 10:17:37 +00:00
|
|
|
eb_addlog(b, LOGOP_INSERT, lb.offset, lb.size);
|
|
|
|
|
s->offset = lb.offset + lb.size;
|
|
|
|
|
break;
|
|
|
|
|
case LOGOP_INSERT:
|
|
|
|
|
eb_delete(b, lb.offset, lb.size);
|
|
|
|
|
s->offset = lb.offset;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
b->modified = lb.was_modified;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-14 03:29:36 +00:00
|
|
|
void do_redo(EditState *s)
|
|
|
|
|
{
|
|
|
|
|
EditBuffer *b = s->b;
|
|
|
|
|
int log_index, size_trailer;
|
|
|
|
|
LogBuffer lb;
|
|
|
|
|
|
2014-01-31 14:50:13 +00:00
|
|
|
if (!b->log_buffer) {
|
2024-12-03 22:52:55 +01:00
|
|
|
put_error(s, "No undo information");
|
2014-01-14 03:29:36 +00:00
|
|
|
return;
|
2014-01-31 14:50:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* deactivate region hilite */
|
|
|
|
|
s->region_style = 0;
|
2014-01-14 03:29:36 +00:00
|
|
|
|
|
|
|
|
/* Should actually keep undo state current until new logs are added */
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (s->qs->last_cmd_func != (CmdFunc)do_undo
|
|
|
|
|
&& s->qs->last_cmd_func != (CmdFunc)do_redo) {
|
2014-01-14 03:29:36 +00:00
|
|
|
b->log_current = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!b->log_current || !b->log_new_index) {
|
2024-12-03 22:52:55 +01:00
|
|
|
put_error(s, "Nothing to redo");
|
2014-01-14 03:29:36 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
put_status(s, "Redo!");
|
|
|
|
|
|
|
|
|
|
/* go forward in undo stack */
|
|
|
|
|
log_index = b->log_current - 1;
|
|
|
|
|
eb_read(b->log_buffer, log_index, &lb, sizeof(LogBuffer));
|
|
|
|
|
log_index += sizeof(LogBuffer);
|
|
|
|
|
if (lb.op != LOGOP_INSERT)
|
|
|
|
|
log_index += lb.size;
|
|
|
|
|
log_index += sizeof(int);
|
|
|
|
|
/* log_current is 1 + index to have zero as default value */
|
|
|
|
|
b->log_current = log_index + 1;
|
|
|
|
|
|
|
|
|
|
/* go backward from the end and remove undo record */
|
|
|
|
|
log_index = b->log_new_index;
|
|
|
|
|
log_index -= sizeof(int);
|
|
|
|
|
eb_read(b->log_buffer, log_index, &size_trailer, sizeof(int));
|
|
|
|
|
log_index -= size_trailer + sizeof(LogBuffer);
|
|
|
|
|
|
|
|
|
|
/* play the log entry */
|
|
|
|
|
eb_read(b->log_buffer, log_index, &lb, sizeof(LogBuffer));
|
|
|
|
|
log_index += sizeof(LogBuffer);
|
|
|
|
|
|
|
|
|
|
switch (lb.op) {
|
|
|
|
|
case LOGOP_WRITE:
|
|
|
|
|
/* we must disable the log because we want to record a single
|
|
|
|
|
write (we should have the single operation: eb_write_buffer) */
|
|
|
|
|
b->save_log |= 2;
|
|
|
|
|
eb_delete(b, lb.offset, lb.size);
|
|
|
|
|
eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
|
|
|
|
|
b->save_log &= ~3;
|
|
|
|
|
eb_addlog(b, LOGOP_WRITE, lb.offset, lb.size);
|
|
|
|
|
b->save_log |= 1;
|
|
|
|
|
s->offset = lb.offset + lb.size;
|
|
|
|
|
break;
|
|
|
|
|
case LOGOP_DELETE:
|
|
|
|
|
/* we must also disable the log there because the log buffer
|
|
|
|
|
would be modified BEFORE we insert it by the implicit
|
|
|
|
|
eb_addlog */
|
|
|
|
|
b->save_log |= 2;
|
|
|
|
|
eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
|
|
|
|
|
b->save_log &= ~3;
|
|
|
|
|
eb_addlog(b, LOGOP_INSERT, lb.offset, lb.size);
|
|
|
|
|
b->save_log |= 1;
|
|
|
|
|
s->offset = lb.offset + lb.size;
|
|
|
|
|
break;
|
|
|
|
|
case LOGOP_INSERT:
|
|
|
|
|
b->save_log &= ~1;
|
|
|
|
|
eb_delete(b, lb.offset, lb.size);
|
|
|
|
|
b->save_log |= 1;
|
|
|
|
|
s->offset = lb.offset;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b->modified = lb.was_modified;
|
|
|
|
|
|
|
|
|
|
log_index -= sizeof(LogBuffer);
|
|
|
|
|
eb_delete(b->log_buffer, log_index, b->log_new_index - log_index);
|
|
|
|
|
b->log_new_index = log_index;
|
|
|
|
|
|
|
|
|
|
if (b->log_current >= log_index + 1) {
|
|
|
|
|
/* redone everything */
|
|
|
|
|
b->log_current = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/************************************************************/
|
|
|
|
|
/* line related functions */
|
|
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
void eb_set_charset(EditBuffer *b, QECharset *charset, EOLType eol_type)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2014-01-07 00:49:14 +00:00
|
|
|
int n;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
if (b->charset) {
|
|
|
|
|
charset_decode_close(&b->charset_state);
|
|
|
|
|
}
|
2014-02-05 00:56:48 +00:00
|
|
|
b->eol_type = eol_type;
|
2004-05-29 10:17:37 +00:00
|
|
|
b->charset = charset;
|
2008-03-30 16:10:15 +00:00
|
|
|
b->flags &= ~BF_UTF8;
|
|
|
|
|
if (charset == &charset_utf8)
|
|
|
|
|
b->flags |= BF_UTF8;
|
2014-02-04 22:47:31 +00:00
|
|
|
|
|
|
|
|
if (charset)
|
2014-02-05 00:56:48 +00:00
|
|
|
charset_decode_init(&b->charset_state, charset, eol_type);
|
2014-01-06 09:40:20 +00:00
|
|
|
|
2014-01-15 19:44:24 +00:00
|
|
|
b->char_bytes = 1;
|
|
|
|
|
b->char_shift = 0;
|
|
|
|
|
if (charset) {
|
|
|
|
|
b->char_bytes = charset->char_size;
|
|
|
|
|
if (charset->char_size == 4)
|
|
|
|
|
b->char_shift = 2;
|
|
|
|
|
else
|
|
|
|
|
b->char_shift = charset->char_size - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
/* Reset page cache flags */
|
2014-01-07 00:49:14 +00:00
|
|
|
for (n = 0; n < b->nb_pages; n++) {
|
2014-01-06 09:40:20 +00:00
|
|
|
Page *p = &b->page_table[n];
|
|
|
|
|
p->flags &= ~(PG_VALID_POS | PG_VALID_CHAR | PG_VALID_COLORS);
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX: change API to go faster */
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t eb_nextc(EditBuffer *b, int offset, int *next_ptr)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2008-05-02 17:05:38 +00:00
|
|
|
u8 buf[MAX_CHAR_BYTES];
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t ch;
|
|
|
|
|
int c;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2016-12-13 17:20:51 +00:00
|
|
|
/* XXX: should inline this */
|
2022-10-29 19:43:38 +02:00
|
|
|
c = eb_read_one_byte(b, offset);
|
|
|
|
|
if (c < 0) {
|
2015-08-16 19:22:01 +00:00
|
|
|
/* to simplify calling code, return '\n' at buffer boundaries */
|
2004-05-29 10:17:37 +00:00
|
|
|
ch = '\n';
|
2013-11-30 13:50:12 +00:00
|
|
|
if (offset < 0)
|
|
|
|
|
offset = 0;
|
|
|
|
|
if (offset >= b->total_size)
|
|
|
|
|
offset = b->total_size;
|
2004-05-29 10:17:37 +00:00
|
|
|
} else {
|
2008-05-02 16:04:09 +00:00
|
|
|
/* we use the charset conversion table directly to go faster */
|
2004-05-29 10:17:37 +00:00
|
|
|
offset++;
|
2022-10-29 19:43:38 +02:00
|
|
|
ch = b->charset_state.table[c];
|
2015-06-08 06:54:56 +00:00
|
|
|
if (ch == ESCAPE_CHAR) {
|
2022-10-29 19:43:38 +02:00
|
|
|
/* clear decode buffer to avoid undefined behavior at EOB */
|
|
|
|
|
memset(buf, 0, MAX_CHAR_BYTES);
|
2015-08-16 19:22:01 +00:00
|
|
|
eb_read(b, offset - 1, buf, MAX_CHAR_BYTES);
|
2008-05-02 17:05:38 +00:00
|
|
|
b->charset_state.p = buf;
|
2015-08-16 23:15:01 +00:00
|
|
|
/* XXX: incorrect behaviour on ill encoded utf8 sequences */
|
2008-05-02 17:05:38 +00:00
|
|
|
ch = b->charset_state.decode_func(&b->charset_state);
|
|
|
|
|
offset += (b->charset_state.p - buf) - 1;
|
2015-06-08 06:54:56 +00:00
|
|
|
}
|
|
|
|
|
if (ch == '\r') {
|
|
|
|
|
if (b->eol_type == EOL_DOS) {
|
|
|
|
|
b->charset_state.p = buf;
|
|
|
|
|
if (eb_read(b, offset, buf, MAX_CHAR_BYTES) >= 1
|
2014-02-05 00:56:48 +00:00
|
|
|
&& b->charset_state.decode_func(&b->charset_state) == '\n') {
|
|
|
|
|
offset += b->charset_state.char_size;
|
|
|
|
|
ch = '\n';
|
|
|
|
|
}
|
2015-06-08 06:54:56 +00:00
|
|
|
} else
|
|
|
|
|
if (b->eol_type == EOL_MAC) {
|
|
|
|
|
ch = '\n';
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (ch == '\n') {
|
|
|
|
|
if (b->eol_type == EOL_MAC) {
|
|
|
|
|
ch = '\r';
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-05-02 16:04:09 +00:00
|
|
|
*next_ptr = offset;
|
2004-05-29 10:17:37 +00:00
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-12 07:33:20 +00:00
|
|
|
QETermStyle eb_get_style(EditBuffer *b, int offset)
|
2016-12-13 17:20:51 +00:00
|
|
|
{
|
|
|
|
|
if (b->b_styles) {
|
2017-04-12 07:33:20 +00:00
|
|
|
if (b->style_shift == 3) {
|
|
|
|
|
uint64_t style = 0;
|
|
|
|
|
eb_read(b->b_styles, (offset >> b->char_shift) << 3, &style, 8);
|
|
|
|
|
return style;
|
|
|
|
|
} else
|
2016-12-13 17:20:51 +00:00
|
|
|
if (b->style_shift == 2) {
|
|
|
|
|
uint32_t style = 0;
|
|
|
|
|
eb_read(b->b_styles, (offset >> b->char_shift) << 2, &style, 4);
|
2016-12-23 19:51:48 +00:00
|
|
|
return style;
|
2016-12-13 17:20:51 +00:00
|
|
|
} else
|
|
|
|
|
if (b->style_shift == 1) {
|
|
|
|
|
uint16_t style = 0;
|
|
|
|
|
eb_read(b->b_styles, (offset >> b->char_shift) << 1, &style, 2);
|
2016-12-23 19:51:48 +00:00
|
|
|
return style;
|
2016-12-13 17:20:51 +00:00
|
|
|
} else {
|
|
|
|
|
uint8_t style = 0;
|
2017-04-12 07:33:20 +00:00
|
|
|
eb_read(b->b_styles, (offset >> b->char_shift) << 0, &style, 1);
|
2016-12-23 19:51:48 +00:00
|
|
|
return style;
|
2016-12-13 17:20:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-12-23 19:51:48 +00:00
|
|
|
return 0;
|
2016-12-13 17:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
2014-01-13 10:31:56 +00:00
|
|
|
/* compute offset after moving 'n' chars from 'offset'.
|
|
|
|
|
* 'n' can be negative
|
2015-08-27 23:03:39 +00:00
|
|
|
*/
|
2014-01-08 16:26:44 +00:00
|
|
|
int eb_skip_chars(EditBuffer *b, int offset, int n)
|
|
|
|
|
{
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Compute offset after moving `n` codepoints from `offset`.
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the position in bytes in the buffer
|
|
|
|
|
@argument `n` the number of codepoints to skip forward or backward
|
|
|
|
|
@return the new buffer position
|
|
|
|
|
@note 'n' can be negative
|
|
|
|
|
*/
|
2016-12-23 19:51:48 +00:00
|
|
|
for (; n < 0 && offset > 0; n++) {
|
|
|
|
|
offset = eb_prev(b, offset);
|
2014-01-13 10:31:56 +00:00
|
|
|
}
|
2016-12-23 19:51:48 +00:00
|
|
|
for (; n > 0 && offset < b->total_size; n--) {
|
|
|
|
|
offset = eb_next(b, offset);
|
2014-01-13 10:31:56 +00:00
|
|
|
}
|
2014-01-08 16:26:44 +00:00
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_delete_char32(EditBuffer *b, int offset) {
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Delete one character at offset `offset`, return number of bytes removed
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the position in bytes in the buffer
|
|
|
|
|
@return the number of bytes removed
|
|
|
|
|
*/
|
2022-08-28 20:28:40 +02:00
|
|
|
return eb_delete_range(b, offset, eb_next(b, offset));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eb_skip_accents(EditBuffer *b, int offset) {
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Skip over combining glyphs
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the position in bytes in the buffer
|
|
|
|
|
@return the new buffer position past any combining glyphs
|
|
|
|
|
*/
|
2014-03-21 20:49:30 +00:00
|
|
|
int offset1;
|
2022-08-28 20:28:40 +02:00
|
|
|
while (qe_isaccent(eb_nextc(b, offset, &offset1)))
|
|
|
|
|
offset = offset1;
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
2015-08-27 23:03:39 +00:00
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t eb_next_glyph(EditBuffer *b, int offset, int *next_ptr) {
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Read the main character for the next glyph,
|
|
|
|
|
update offset to next_ptr
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the position in bytes in the buffer
|
|
|
|
|
@argument `next_ptr` a pointer to a variable for the updated
|
|
|
|
|
buffer position after the codepoint and any combining glyphs
|
|
|
|
|
@return the main codepoint value
|
|
|
|
|
*/
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_nextc(b, offset, &offset);
|
2022-08-29 02:55:50 +02:00
|
|
|
if (c >= ' ') {
|
|
|
|
|
offset += eb_skip_accents(b, offset);
|
|
|
|
|
}
|
|
|
|
|
*next_ptr = offset;
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t eb_prev_glyph(EditBuffer *b, int offset, int *next_ptr) {
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Return the main character for the previous glyph,
|
|
|
|
|
update offset to next_ptr
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the position in bytes in the buffer
|
|
|
|
|
@argument `next_ptr` a pointer to a variable for the updated
|
|
|
|
|
buffer position of the codepoint before any combining glyphs
|
|
|
|
|
@return the main codepoint value
|
|
|
|
|
*/
|
2022-08-29 02:55:50 +02:00
|
|
|
for (;;) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_prevc(b, offset, &offset);
|
2022-08-29 02:55:50 +02:00
|
|
|
if (!qe_isaccent(c)) {
|
|
|
|
|
*next_ptr = offset;
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-28 20:28:40 +02:00
|
|
|
/* compute offset after moving 'n' glyphs from 'offset'.
|
|
|
|
|
* 'n' can be negative,
|
|
|
|
|
* combining accents are skipped as part of the previous character.
|
|
|
|
|
*/
|
|
|
|
|
int eb_skip_glyphs(EditBuffer *b, int offset, int n) {
|
2022-10-29 19:43:38 +02:00
|
|
|
int offset1;
|
|
|
|
|
|
2022-08-28 20:28:40 +02:00
|
|
|
if (n < 0) {
|
|
|
|
|
while (offset > 0) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_prevc(b, offset, &offset);
|
2022-08-28 20:28:40 +02:00
|
|
|
n += !qe_isaccent(c);
|
|
|
|
|
if (n >= 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-03-21 20:49:30 +00:00
|
|
|
} else {
|
2022-08-28 20:28:40 +02:00
|
|
|
while (offset < b->total_size) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_nextc(b, offset, &offset1);
|
2022-08-28 20:28:40 +02:00
|
|
|
if (!qe_isaccent(c) && n-- <= 0)
|
|
|
|
|
break;
|
|
|
|
|
offset = offset1;
|
|
|
|
|
}
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
2022-08-28 20:28:40 +02:00
|
|
|
return offset;
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-21 20:49:30 +00:00
|
|
|
/* return number of bytes deleted. n can be negative to delete
|
|
|
|
|
* characters before offset
|
|
|
|
|
*/
|
2014-01-08 16:26:44 +00:00
|
|
|
int eb_delete_chars(EditBuffer *b, int offset, int n)
|
|
|
|
|
{
|
2020-10-17 15:41:31 +00:00
|
|
|
return eb_delete_range(b, offset, eb_skip_chars(b, offset, n));
|
2014-01-08 16:26:44 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-28 20:28:40 +02:00
|
|
|
/* return number of bytes deleted. n can be negative to delete
|
|
|
|
|
* characters before offset
|
|
|
|
|
*/
|
|
|
|
|
int eb_delete_glyphs(EditBuffer *b, int offset, int n)
|
|
|
|
|
{
|
|
|
|
|
return eb_delete_range(b, offset, eb_skip_glyphs(b, offset, n));
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-02 16:04:09 +00:00
|
|
|
/* XXX: only stateless charsets are supported */
|
2022-08-28 20:28:40 +02:00
|
|
|
/* XXX: suppress that? */
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t eb_prevc(EditBuffer *b, int offset, int *prev_ptr)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t ch;
|
|
|
|
|
int char_size;
|
2016-12-23 19:51:48 +00:00
|
|
|
u8 buf[MAX_CHAR_BYTES + 1], *q;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
if (offset <= 0) {
|
|
|
|
|
offset = 0;
|
|
|
|
|
ch = '\n';
|
|
|
|
|
} else {
|
|
|
|
|
if (b->charset == &charset_utf8) {
|
2015-08-16 23:15:01 +00:00
|
|
|
char_size = 1;
|
|
|
|
|
offset -= 1;
|
|
|
|
|
ch = eb_read_one_byte(b, offset);
|
|
|
|
|
if (utf8_is_trailing_byte(ch)) {
|
|
|
|
|
int offset1 = offset;
|
|
|
|
|
q = buf + sizeof(buf);
|
2016-12-23 19:51:48 +00:00
|
|
|
*--q = '\0';
|
2015-08-16 23:15:01 +00:00
|
|
|
*--q = ch;
|
|
|
|
|
while (utf8_is_trailing_byte(ch) && offset > 0 && q > buf) {
|
|
|
|
|
offset -= 1;
|
|
|
|
|
*--q = ch = eb_read_one_byte(b, offset);
|
|
|
|
|
}
|
|
|
|
|
if (ch >= 0xc0) {
|
|
|
|
|
ch = utf8_decode((const char **)(void *)&q);
|
|
|
|
|
}
|
2016-12-23 19:51:48 +00:00
|
|
|
if (q != buf + sizeof(buf) - 1) {
|
2015-08-16 23:15:01 +00:00
|
|
|
/* decoding error: only take the last byte */
|
|
|
|
|
offset = offset1;
|
2016-12-23 19:51:48 +00:00
|
|
|
ch = buf[sizeof(buf) - 2];
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-08-16 23:15:01 +00:00
|
|
|
/* XXX: this only works for stateless charsets.
|
|
|
|
|
* it would fail for utf-16 and east-asian encodings.
|
|
|
|
|
* Should use the line/column system to be really generic
|
|
|
|
|
*/
|
|
|
|
|
char_size = b->charset_state.char_size;
|
|
|
|
|
offset -= char_size;
|
|
|
|
|
q = buf + sizeof(buf) - char_size;
|
|
|
|
|
eb_read(b, offset, q, char_size);
|
2008-05-02 17:05:38 +00:00
|
|
|
b->charset_state.p = q;
|
|
|
|
|
ch = b->charset_state.decode_func(&b->charset_state);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2015-06-08 06:54:56 +00:00
|
|
|
if (ch == '\r') {
|
|
|
|
|
if (b->eol_type == EOL_MAC) {
|
|
|
|
|
ch = '\n';
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (ch == '\n') {
|
|
|
|
|
if (b->eol_type == EOL_DOS) {
|
|
|
|
|
if (offset >= char_size) {
|
|
|
|
|
eb_read(b, offset - char_size, buf, char_size);
|
|
|
|
|
b->charset_state.p = buf;
|
|
|
|
|
if (b->charset_state.decode_func(&b->charset_state) == '\r')
|
|
|
|
|
offset -= char_size;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (b->eol_type == EOL_MAC) {
|
|
|
|
|
ch = '\r';
|
|
|
|
|
}
|
2014-02-05 00:56:48 +00:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2008-05-02 16:04:09 +00:00
|
|
|
*prev_ptr = offset;
|
2004-05-29 10:17:37 +00:00
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eb_goto_pos(EditBuffer *b, int line1, int col1)
|
|
|
|
|
{
|
|
|
|
|
Page *p, *p_end;
|
2014-02-04 22:47:31 +00:00
|
|
|
int line2, col2, line, col, offset, offset1;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
|
|
|
|
line = 0;
|
|
|
|
|
col = 0;
|
|
|
|
|
offset = 0;
|
2008-05-02 16:04:09 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
p = b->page_table;
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (!p)
|
|
|
|
|
return 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
p_end = b->page_table + b->nb_pages;
|
|
|
|
|
while (p < p_end) {
|
|
|
|
|
if (!(p->flags & PG_VALID_POS)) {
|
|
|
|
|
p->flags |= PG_VALID_POS;
|
2008-05-02 16:04:09 +00:00
|
|
|
b->charset_state.get_pos_func(&b->charset_state, p->data, p->size,
|
|
|
|
|
&p->nb_lines, &p->col);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
line2 = line + p->nb_lines;
|
|
|
|
|
if (p->nb_lines)
|
|
|
|
|
col2 = 0;
|
|
|
|
|
col2 = col + p->col;
|
|
|
|
|
if (line2 > line1 || (line2 == line1 && col2 >= col1)) {
|
|
|
|
|
/* compute offset */
|
2008-05-02 16:04:09 +00:00
|
|
|
if (line < line1) {
|
|
|
|
|
/* seek to the correct line */
|
2014-02-05 00:56:48 +00:00
|
|
|
offset += b->charset->goto_line_func(&b->charset_state,
|
2008-05-02 16:04:09 +00:00
|
|
|
p->data, p->size, line1 - line);
|
|
|
|
|
line = line1;
|
2004-05-29 10:17:37 +00:00
|
|
|
col = 0;
|
|
|
|
|
}
|
2014-02-04 22:47:31 +00:00
|
|
|
while (col < col1 && eb_nextc(b, offset, &offset1) != '\n') {
|
2004-05-29 10:17:37 +00:00
|
|
|
col++;
|
|
|
|
|
offset = offset1;
|
|
|
|
|
}
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
line = line2;
|
|
|
|
|
col = col2;
|
|
|
|
|
offset += p->size;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
return b->total_size;
|
|
|
|
|
}
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
int eb_get_pos(EditBuffer *b, int *line_ptr, int *col_ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
Page *p, *p_end;
|
|
|
|
|
int line, col, line1, col1;
|
|
|
|
|
|
2005-05-05 13:40:57 +00:00
|
|
|
QASSERT(offset >= 0);
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
line = 0;
|
|
|
|
|
col = 0;
|
|
|
|
|
p = b->page_table;
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (!p)
|
|
|
|
|
goto the_end;
|
2004-05-29 10:17:37 +00:00
|
|
|
p_end = p + b->nb_pages;
|
2005-05-11 14:35:54 +00:00
|
|
|
for (;;) {
|
2004-05-29 10:17:37 +00:00
|
|
|
if (p >= p_end)
|
|
|
|
|
goto the_end;
|
|
|
|
|
if (offset < p->size)
|
|
|
|
|
break;
|
|
|
|
|
if (!(p->flags & PG_VALID_POS)) {
|
|
|
|
|
p->flags |= PG_VALID_POS;
|
2008-05-02 16:04:09 +00:00
|
|
|
b->charset_state.get_pos_func(&b->charset_state, p->data, p->size,
|
|
|
|
|
&p->nb_lines, &p->col);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
line += p->nb_lines;
|
|
|
|
|
if (p->nb_lines)
|
|
|
|
|
col = 0;
|
|
|
|
|
col += p->col;
|
|
|
|
|
offset -= p->size;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
2008-05-02 16:04:09 +00:00
|
|
|
b->charset_state.get_pos_func(&b->charset_state, p->data, offset,
|
|
|
|
|
&line1, &col1);
|
2004-05-29 10:17:37 +00:00
|
|
|
line += line1;
|
|
|
|
|
if (line1)
|
|
|
|
|
col = 0;
|
|
|
|
|
col += col1;
|
2008-05-02 16:04:09 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
the_end:
|
|
|
|
|
*line_ptr = line;
|
|
|
|
|
*col_ptr = col;
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************/
|
|
|
|
|
/* char offset computation */
|
|
|
|
|
|
2008-05-02 16:04:09 +00:00
|
|
|
/* convert a char number into a byte offset according to buffer charset */
|
2004-05-29 10:17:37 +00:00
|
|
|
int eb_goto_char(EditBuffer *b, int pos)
|
|
|
|
|
{
|
|
|
|
|
int offset;
|
|
|
|
|
Page *p, *p_end;
|
|
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
if (!b->charset->variable_size && b->eol_type != EOL_DOS) {
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
offset = min_offset(pos * b->charset->char_size, b->total_size);
|
2004-05-29 10:17:37 +00:00
|
|
|
} else {
|
|
|
|
|
offset = 0;
|
|
|
|
|
p = b->page_table;
|
|
|
|
|
p_end = b->page_table + b->nb_pages;
|
|
|
|
|
while (p < p_end) {
|
|
|
|
|
if (!(p->flags & PG_VALID_CHAR)) {
|
|
|
|
|
p->flags |= PG_VALID_CHAR;
|
2014-02-05 00:56:48 +00:00
|
|
|
p->nb_chars = b->charset->get_chars_func(&b->charset_state, p->data, p->size);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
if (pos < p->nb_chars) {
|
2014-02-05 00:56:48 +00:00
|
|
|
offset += b->charset->goto_char_func(&b->charset_state, p->data, p->size, pos);
|
2004-05-29 10:17:37 +00:00
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
pos -= p->nb_chars;
|
|
|
|
|
offset += p->size;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-02 16:04:09 +00:00
|
|
|
/* convert a byte offset into a char number according to buffer charset */
|
2004-05-29 10:17:37 +00:00
|
|
|
int eb_get_char_offset(EditBuffer *b, int offset)
|
|
|
|
|
{
|
|
|
|
|
int pos;
|
|
|
|
|
Page *p, *p_end;
|
|
|
|
|
|
2014-01-04 15:54:48 +00:00
|
|
|
if (offset < 0)
|
|
|
|
|
offset = 0;
|
|
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
if (!b->charset->variable_size && b->eol_type != EOL_DOS) {
|
2014-01-04 15:54:48 +00:00
|
|
|
/* offset is round down to character boundary */
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
pos = min_offset(offset, b->total_size) / b->charset->char_size;
|
2004-05-29 10:17:37 +00:00
|
|
|
} else {
|
2014-02-05 00:56:48 +00:00
|
|
|
/* XXX: should handle rounding if EOL_DOS */
|
|
|
|
|
/* XXX: should fix buffer offset via charset specific method */
|
2016-12-23 19:51:48 +00:00
|
|
|
/* XXX: fails in case of encoding error */
|
2014-01-04 15:54:48 +00:00
|
|
|
if (b->charset == &charset_utf8) {
|
|
|
|
|
/* Round offset down to character boundary */
|
|
|
|
|
u8 buf[1];
|
|
|
|
|
while (offset > 0 && eb_read(b, offset, buf, 1) == 1 &&
|
2015-08-16 23:15:01 +00:00
|
|
|
utf8_is_trailing_byte(buf[0])) {
|
2014-01-04 15:54:48 +00:00
|
|
|
/* backtrack over trailing bytes */
|
|
|
|
|
offset--;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* CG: XXX: offset rounding to character boundary is undefined */
|
|
|
|
|
}
|
2008-05-02 16:04:09 +00:00
|
|
|
pos = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
p = b->page_table;
|
|
|
|
|
p_end = p + b->nb_pages;
|
2008-05-02 16:04:09 +00:00
|
|
|
while (p < p_end) {
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!(p->flags & PG_VALID_CHAR)) {
|
|
|
|
|
p->flags |= PG_VALID_CHAR;
|
2014-02-05 00:56:48 +00:00
|
|
|
p->nb_chars = b->charset->get_chars_func(&b->charset_state, p->data, p->size);
|
2008-05-02 16:04:09 +00:00
|
|
|
}
|
|
|
|
|
if (offset < p->size) {
|
2014-02-05 00:56:48 +00:00
|
|
|
pos += b->charset->get_chars_func(&b->charset_state, p->data, offset);
|
2008-05-02 16:04:09 +00:00
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
pos += p->nb_chars;
|
|
|
|
|
offset -= p->size;
|
|
|
|
|
p++;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-20 11:49:54 +00:00
|
|
|
/* delete a range of bytes from the buffer, bounds in any order, return
|
2014-03-21 20:49:30 +00:00
|
|
|
* number of bytes removed.
|
2007-12-20 11:49:54 +00:00
|
|
|
*/
|
|
|
|
|
int eb_delete_range(EditBuffer *b, int p1, int p2)
|
|
|
|
|
{
|
|
|
|
|
if (p1 > p2) {
|
2007-12-20 20:39:18 +00:00
|
|
|
int tmp = p1;
|
|
|
|
|
p1 = p2;
|
|
|
|
|
p2 = tmp;
|
2007-12-20 11:49:54 +00:00
|
|
|
}
|
2014-03-21 20:49:30 +00:00
|
|
|
return eb_delete(b, p1, p2 - p1);
|
2007-12-20 11:49:54 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-29 18:41:29 +02:00
|
|
|
/* replace 'size' bytes at offset 'offset' with 'size1' bytes from 'buf'
|
|
|
|
|
* return the number of bytes written
|
|
|
|
|
*/
|
|
|
|
|
int eb_replace(EditBuffer *b, int offset, int size,
|
|
|
|
|
const void *buf, int size1)
|
2007-12-20 11:49:54 +00:00
|
|
|
{
|
|
|
|
|
/* CG: behaviour is not exactly identical: mark, point and other
|
|
|
|
|
* callback based offsets will be updated differently. should
|
|
|
|
|
* write portion that fits and insert or delete remainder?
|
2022-08-28 20:28:40 +02:00
|
|
|
* or should simulate callbacks?
|
2007-12-20 11:49:54 +00:00
|
|
|
*/
|
|
|
|
|
if (size == size1) {
|
2022-08-29 18:41:29 +02:00
|
|
|
return eb_write(b, offset, buf, size1);
|
2007-12-20 11:49:54 +00:00
|
|
|
} else {
|
2007-12-20 20:39:18 +00:00
|
|
|
eb_delete(b, offset, size);
|
2022-08-29 18:41:29 +02:00
|
|
|
return eb_insert(b, offset, buf, size1);
|
2007-12-20 11:49:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/************************************************************/
|
|
|
|
|
/* buffer I/O */
|
|
|
|
|
|
|
|
|
|
#define IOBUF_SIZE 32768
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
|
|
typedef struct BufferIOState {
|
|
|
|
|
URLContext *handle;
|
|
|
|
|
void (*progress_cb)(void *opaque, int size);
|
|
|
|
|
void (*completion_cb)(void *opaque, int err);
|
|
|
|
|
void *opaque;
|
|
|
|
|
int offset;
|
|
|
|
|
int saved_flags;
|
|
|
|
|
int saved_log;
|
|
|
|
|
int nolog;
|
|
|
|
|
unsigned char buffer[IOBUF_SIZE];
|
|
|
|
|
} BufferIOState;
|
|
|
|
|
|
|
|
|
|
static void load_connected_cb(void *opaque, int err);
|
|
|
|
|
static void load_read_cb(void *opaque, int size);
|
|
|
|
|
static void eb_io_stop(EditBuffer *b, int err);
|
|
|
|
|
|
|
|
|
|
/* load a buffer asynchronously and launch the callback. The buffer
|
|
|
|
|
stays in 'loading' state while begin loaded. It is also marked
|
|
|
|
|
readonly. */
|
2008-01-03 09:51:29 +00:00
|
|
|
int load_buffer(EditBuffer *b, const char *filename,
|
2004-05-29 10:17:37 +00:00
|
|
|
int offset, int nolog,
|
2008-01-03 09:51:29 +00:00
|
|
|
void (*progress_cb)(void *opaque, int size),
|
2004-05-29 10:17:37 +00:00
|
|
|
void (*completion_cb)(void *opaque, int err), void *opaque)
|
|
|
|
|
{
|
|
|
|
|
URLContext *h;
|
|
|
|
|
BufferIOState *s;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* cannot load a buffer if already I/Os or readonly */
|
|
|
|
|
if (b->flags & (BF_LOADING | BF_SAVING | BF_READONLY))
|
|
|
|
|
return -1;
|
2014-01-23 12:56:22 +00:00
|
|
|
s = qe_mallocz(BufferIOState);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!s)
|
|
|
|
|
return -1;
|
|
|
|
|
b->io_state = s;
|
|
|
|
|
h = url_new();
|
|
|
|
|
if (!h) {
|
2007-12-12 11:49:02 +00:00
|
|
|
qe_free(&b->io_state);
|
2004-05-29 10:17:37 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
s->handle = h;
|
|
|
|
|
s->saved_flags = b->flags;
|
|
|
|
|
s->nolog = nolog;
|
|
|
|
|
if (s->nolog) {
|
|
|
|
|
s->saved_log = b->save_log;
|
|
|
|
|
b->save_log = 0;
|
|
|
|
|
}
|
|
|
|
|
b->flags |= BF_LOADING | BF_READONLY;
|
|
|
|
|
s->handle = h;
|
|
|
|
|
s->progress_cb = progress_cb;
|
|
|
|
|
s->completion_cb = completion_cb;
|
|
|
|
|
s->opaque = opaque;
|
|
|
|
|
s->offset = offset;
|
|
|
|
|
printf("connect_async: '%s'\n", filename);
|
|
|
|
|
url_connect_async(s->handle, filename, URL_RDONLY,
|
|
|
|
|
load_connected_cb, b);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void load_connected_cb(void *opaque, int err)
|
|
|
|
|
{
|
|
|
|
|
EditBuffer *b = opaque;
|
|
|
|
|
BufferIOState *s = b->io_state;
|
|
|
|
|
printf("connect_cb: err=%d\n", err);
|
|
|
|
|
if (err) {
|
|
|
|
|
eb_io_stop(b, err);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
url_read_async(s->handle, s->buffer, IOBUF_SIZE, load_read_cb, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void load_read_cb(void *opaque, int size)
|
|
|
|
|
{
|
|
|
|
|
EditBuffer *b = opaque;
|
|
|
|
|
BufferIOState *s = b->io_state;
|
|
|
|
|
|
|
|
|
|
printf("read_cb: size=%d\n", size);
|
|
|
|
|
if (size < 0) {
|
|
|
|
|
eb_io_stop(b, -EIO);
|
|
|
|
|
} else if (size == 0) {
|
|
|
|
|
/* end of file */
|
|
|
|
|
eb_io_stop(b, 0);
|
|
|
|
|
} else {
|
2022-08-28 20:28:40 +02:00
|
|
|
s->offset += eb_insert(b, s->offset, s->buffer, size);
|
2004-05-29 10:17:37 +00:00
|
|
|
/* launch next read request */
|
|
|
|
|
url_read_async(s->handle, s->buffer, IOBUF_SIZE, load_read_cb, b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void eb_io_stop(EditBuffer *b, int err)
|
|
|
|
|
{
|
|
|
|
|
BufferIOState *s = b->io_state;
|
|
|
|
|
|
|
|
|
|
b->flags = s->saved_flags;
|
|
|
|
|
if (s->nolog) {
|
|
|
|
|
b->modified = 0;
|
|
|
|
|
b->save_log = s->saved_log;
|
|
|
|
|
}
|
|
|
|
|
url_close(s->handle);
|
|
|
|
|
s->completion_cb(s->opaque, err);
|
2007-12-12 11:49:02 +00:00
|
|
|
qe_free(&b->io_state);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-01-03 18:31:24 +00:00
|
|
|
/* CG: returns number of bytes read, or -1 upon read error */
|
2015-08-25 16:19:42 +00:00
|
|
|
int eb_raw_buffer_load1(EditBuffer *b, FILE *f, int offset)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
unsigned char buf[IOBUF_SIZE];
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
int len, size, inserted;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2024-12-03 22:52:55 +01:00
|
|
|
//put_status(b->qs->active_window, "Loading %s", filename);
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
size = inserted = 0;
|
2005-05-11 14:35:54 +00:00
|
|
|
for (;;) {
|
2004-05-29 10:17:37 +00:00
|
|
|
len = fread(buf, 1, IOBUF_SIZE, f);
|
2008-04-22 08:17:02 +00:00
|
|
|
if (len <= 0) {
|
|
|
|
|
if (ferror(f))
|
|
|
|
|
return -1;
|
2004-05-29 10:17:37 +00:00
|
|
|
break;
|
2008-04-22 08:17:02 +00:00
|
|
|
}
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
inserted += eb_insert(b, offset, buf, len);
|
2004-05-29 10:17:37 +00:00
|
|
|
offset += len;
|
2008-01-03 18:31:24 +00:00
|
|
|
size += len;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
//put_status(b->qs->active_window, "");
|
2008-01-03 18:31:24 +00:00
|
|
|
return size;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2008-04-05 23:04:56 +00:00
|
|
|
#ifdef CONFIG_MMAP
|
2014-05-18 11:01:55 +00:00
|
|
|
void eb_munmap_buffer(EditBuffer *b)
|
|
|
|
|
{
|
|
|
|
|
if (b->map_address) {
|
|
|
|
|
munmap(b->map_address, b->map_length);
|
|
|
|
|
b->map_address = NULL;
|
|
|
|
|
b->map_length = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eb_mmap_buffer(EditBuffer *b, const char *filename)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
int fd, len, file_size, n, size;
|
|
|
|
|
u8 *file_ptr, *ptr;
|
|
|
|
|
Page *p;
|
|
|
|
|
|
2014-05-18 11:01:55 +00:00
|
|
|
eb_munmap_buffer(b);
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
fd = open(filename, O_RDONLY);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
file_size = lseek(fd, 0, SEEK_END);
|
2024-12-03 22:52:55 +01:00
|
|
|
//put_status(b->qs->active_window, "Mapping %s", filename);
|
2004-05-29 10:17:37 +00:00
|
|
|
file_ptr = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);
|
2005-05-05 13:40:57 +00:00
|
|
|
if ((void*)file_ptr == MAP_FAILED) {
|
2004-05-29 10:17:37 +00:00
|
|
|
close(fd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2014-05-18 11:01:55 +00:00
|
|
|
b->map_address = file_ptr;
|
|
|
|
|
b->map_length = file_size;
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
n = (file_size + MAX_PAGE_SIZE - 1) / MAX_PAGE_SIZE;
|
2007-12-12 11:49:02 +00:00
|
|
|
p = qe_malloc_array(Page, n);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (!p) {
|
|
|
|
|
close(fd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
b->page_table = p;
|
|
|
|
|
b->total_size = file_size;
|
|
|
|
|
b->nb_pages = n;
|
|
|
|
|
size = file_size;
|
|
|
|
|
ptr = file_ptr;
|
|
|
|
|
while (size > 0) {
|
|
|
|
|
len = size;
|
|
|
|
|
if (len > MAX_PAGE_SIZE)
|
|
|
|
|
len = MAX_PAGE_SIZE;
|
|
|
|
|
p->data = ptr;
|
|
|
|
|
p->size = len;
|
|
|
|
|
p->flags = PG_READ_ONLY;
|
|
|
|
|
ptr += len;
|
|
|
|
|
size -= len;
|
|
|
|
|
p++;
|
|
|
|
|
}
|
2014-05-18 11:01:55 +00:00
|
|
|
// XXX: not needed
|
2014-05-26 14:35:37 +00:00
|
|
|
b->map_handle = fd;
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
//put_status(b->qs->active_window, "");
|
2004-05-29 10:17:37 +00:00
|
|
|
return 0;
|
2008-01-08 16:37:54 +00:00
|
|
|
}
|
2008-04-05 23:04:56 +00:00
|
|
|
#endif
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2013-12-23 23:26:43 +00:00
|
|
|
static int raw_buffer_load(EditBuffer *b, FILE *f)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
2008-04-05 23:04:56 +00:00
|
|
|
/* TODO: Should produce error messages */
|
|
|
|
|
|
|
|
|
|
if (stat(b->filename, &st))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_MMAP
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (st.st_size >= b->qs->mmap_threshold) {
|
2014-05-18 11:01:55 +00:00
|
|
|
if (!eb_mmap_buffer(b, b->filename))
|
2008-04-05 23:04:56 +00:00
|
|
|
return 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2008-04-05 23:04:56 +00:00
|
|
|
#endif
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (st.st_size <= b->qs->max_load_size) {
|
2015-08-25 16:19:42 +00:00
|
|
|
return eb_raw_buffer_load1(b, f, 0);
|
2008-04-05 23:04:56 +00:00
|
|
|
}
|
|
|
|
|
return -1;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2007-12-20 16:27:21 +00:00
|
|
|
/* Write bytes between <start> and <end> to file filename,
|
|
|
|
|
* return bytes written or -1 if error
|
|
|
|
|
*/
|
2013-12-23 23:26:43 +00:00
|
|
|
static int raw_buffer_save(EditBuffer *b, int start, int end,
|
2007-12-20 16:27:21 +00:00
|
|
|
const char *filename)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2007-12-20 16:27:21 +00:00
|
|
|
int fd, len, size, written;
|
2004-05-29 10:17:37 +00:00
|
|
|
unsigned char buf[IOBUF_SIZE];
|
|
|
|
|
|
2008-01-03 09:51:29 +00:00
|
|
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (fd < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2024-12-03 22:52:55 +01:00
|
|
|
//put_status(b->qs->active_window, "Writing %s", filename);
|
2007-12-20 16:27:21 +00:00
|
|
|
if (end < start) {
|
|
|
|
|
int tmp = start;
|
|
|
|
|
start = end;
|
|
|
|
|
end = tmp;
|
|
|
|
|
}
|
|
|
|
|
if (start < 0)
|
|
|
|
|
start = 0;
|
|
|
|
|
if (end > b->total_size)
|
|
|
|
|
end = b->total_size;
|
|
|
|
|
written = 0;
|
|
|
|
|
size = end - start;
|
2004-05-29 10:17:37 +00:00
|
|
|
while (size > 0) {
|
|
|
|
|
len = size;
|
|
|
|
|
if (len > IOBUF_SIZE)
|
|
|
|
|
len = IOBUF_SIZE;
|
2007-12-20 16:27:21 +00:00
|
|
|
eb_read(b, start, buf, len);
|
2004-05-29 10:17:37 +00:00
|
|
|
len = write(fd, buf, len);
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
close(fd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2007-12-20 16:27:21 +00:00
|
|
|
written += len;
|
|
|
|
|
start += len;
|
2004-05-29 10:17:37 +00:00
|
|
|
size -= len;
|
|
|
|
|
}
|
|
|
|
|
close(fd);
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
//put_status(b->qs->active_window, "");
|
2007-12-20 16:27:21 +00:00
|
|
|
return written;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-09-16 22:18:22 +00:00
|
|
|
static void raw_buffer_close(qe__unused__ EditBuffer *b)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
/* nothing to do */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Associate a buffer with a file and rename it to match the
|
|
|
|
|
filename. Find a unique buffer name */
|
2007-12-27 10:04:09 +00:00
|
|
|
void eb_set_filename(EditBuffer *b, const char *filename)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2022-08-10 18:50:19 +02:00
|
|
|
pstrcpy(unconst(char *)b->filename, sizeof(b->filename), filename);
|
2008-04-08 06:54:44 +00:00
|
|
|
eb_set_buffer_name(b, get_basename(filename));
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
/* Encode unicode character according to buffer charset and eol_type */
|
2014-02-04 22:47:31 +00:00
|
|
|
/* Return number of bytes of conversion */
|
|
|
|
|
/* the function uses '?' to indicate that no match could be found in
|
|
|
|
|
buffer charset */
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_encode_char32(EditBuffer *b, char *buf, char32_t c) {
|
2014-02-04 22:47:31 +00:00
|
|
|
QECharset *charset = b->charset;
|
|
|
|
|
u8 *q = (u8 *)buf;
|
|
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
if (c == '\n') {
|
|
|
|
|
if (b->eol_type == EOL_MAC)
|
|
|
|
|
c = '\r';
|
|
|
|
|
else
|
|
|
|
|
if (b->eol_type == EOL_DOS) {
|
|
|
|
|
q = charset->encode_func(charset, q, '\r');
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-02-04 22:47:31 +00:00
|
|
|
q = charset->encode_func(charset, q, c);
|
|
|
|
|
if (!q) {
|
|
|
|
|
q = (u8 *)buf;
|
|
|
|
|
*q++ = '?';
|
|
|
|
|
}
|
|
|
|
|
*q = '\0';
|
|
|
|
|
return q - (u8 *)buf;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
/* Insert unicode character according to buffer encoding */
|
2014-01-31 12:14:13 +00:00
|
|
|
/* Return number of bytes inserted */
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_insert_char32(EditBuffer *b, int offset, char32_t c) {
|
2014-01-06 09:40:20 +00:00
|
|
|
char buf[MAX_CHAR_BYTES];
|
|
|
|
|
int len;
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
len = eb_encode_char32(b, buf, c);
|
2014-01-31 12:14:13 +00:00
|
|
|
return eb_insert(b, offset, buf, len);
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
|
2017-04-25 16:46:41 +00:00
|
|
|
/* Replace the character at `offset` with `c`,
|
|
|
|
|
* return number of bytes to move past `c`.
|
|
|
|
|
*/
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_replace_char32(EditBuffer *b, int offset, char32_t c) {
|
2017-04-25 16:46:41 +00:00
|
|
|
char buf[MAX_CHAR_BYTES];
|
|
|
|
|
int len;
|
|
|
|
|
int offset1;
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
len = eb_encode_char32(b, buf, c);
|
2017-04-25 16:46:41 +00:00
|
|
|
eb_nextc(b, offset, &offset1);
|
2022-08-29 18:41:29 +02:00
|
|
|
return eb_replace(b, offset, offset1 - offset, buf, len);
|
2017-04-25 16:46:41 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_insert_char32_n(EditBuffer *b, int offset, char32_t c, int n) {
|
2022-08-29 18:41:29 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
int size, pos;
|
|
|
|
|
|
|
|
|
|
size = pos = 0;
|
|
|
|
|
while (n --> 0) {
|
2022-10-29 19:43:38 +02:00
|
|
|
pos += eb_encode_char32(b, buf + pos, c);
|
2022-08-29 18:41:29 +02:00
|
|
|
if (pos > ssizeof(buf) - MAX_CHAR_BYTES || n == 0) {
|
|
|
|
|
size += eb_insert(b, offset + size, buf, pos);
|
|
|
|
|
pos = 0;
|
2014-03-15 22:52:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
/* Insert buffer with utf8 chars according to buffer encoding */
|
2014-01-31 12:14:13 +00:00
|
|
|
/* Return number of bytes inserted */
|
2022-11-22 23:21:28 +01:00
|
|
|
int eb_insert_utf8_buf(EditBuffer *b, int offset, const char *str, int len)
|
2014-01-06 09:40:20 +00:00
|
|
|
{
|
2014-02-05 00:56:48 +00:00
|
|
|
if (b->charset == &charset_utf8 && b->eol_type == EOL_UNIX) {
|
2022-11-22 23:21:28 +01:00
|
|
|
return eb_insert(b, offset, str, len);
|
2014-01-06 09:40:20 +00:00
|
|
|
} else {
|
2022-11-22 23:21:28 +01:00
|
|
|
char buf[1024];
|
|
|
|
|
int size, pos;
|
|
|
|
|
const char *p = str;
|
|
|
|
|
const char *strend = str + len;
|
|
|
|
|
|
|
|
|
|
size = pos = 0;
|
|
|
|
|
while (p < strend) {
|
|
|
|
|
char32_t c = utf8_decode(&p);
|
|
|
|
|
int clen = eb_encode_char32(b, buf + pos, c);
|
|
|
|
|
pos += clen;
|
|
|
|
|
if (pos > countof(buf) - MAX_CHAR_BYTES || p >= strend) {
|
|
|
|
|
size += eb_insert(b, offset + size, buf, pos);
|
|
|
|
|
pos = 0;
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
/* Insert chars from char32 array according to buffer encoding */
|
2015-08-15 13:08:41 +00:00
|
|
|
/* Return number of bytes inserted */
|
2022-11-22 23:21:28 +01:00
|
|
|
int eb_insert_char32_buf(EditBuffer *b, int offset, const char32_t *p, int len)
|
|
|
|
|
{
|
|
|
|
|
char buf[1024];
|
|
|
|
|
int i, size, pos;
|
|
|
|
|
|
|
|
|
|
i = size = pos = 0;
|
|
|
|
|
while (i < len) {
|
|
|
|
|
char32_t c = p[i++];
|
|
|
|
|
int clen = eb_encode_char32(b, buf + pos, c);
|
|
|
|
|
pos += clen;
|
|
|
|
|
if (pos > countof(buf) - MAX_CHAR_BYTES || i >= len) {
|
|
|
|
|
size += eb_insert(b, offset + size, buf, pos);
|
|
|
|
|
pos = 0;
|
2015-08-15 13:08:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-11 14:38:30 +00:00
|
|
|
int eb_insert_str(EditBuffer *b, int offset, const char *str)
|
|
|
|
|
{
|
|
|
|
|
return eb_insert_utf8_buf(b, offset, str, strlen(str));
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_match_char32(EditBuffer *b, int offset, char32_t c, int *offsetp)
|
2014-01-11 14:38:30 +00:00
|
|
|
{
|
2014-01-11 15:07:14 +00:00
|
|
|
if (eb_nextc(b, offset, &offset) != c)
|
|
|
|
|
return 0;
|
|
|
|
|
if (offsetp)
|
|
|
|
|
*offsetp = offset;
|
|
|
|
|
return 1;
|
2014-01-11 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
2022-11-01 01:19:32 +01:00
|
|
|
int eb_match_str_utf8(EditBuffer *b, int offset, const char *str, int *offsetp) {
|
2014-01-11 14:38:30 +00:00
|
|
|
const char *p = str;
|
|
|
|
|
|
|
|
|
|
while (*p) {
|
2022-11-01 01:19:32 +01:00
|
|
|
char32_t c = utf8_decode(&p);
|
2014-01-11 14:38:30 +00:00
|
|
|
if (eb_nextc(b, offset, &offset) != c)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2014-01-11 15:07:14 +00:00
|
|
|
if (offsetp)
|
|
|
|
|
*offsetp = offset;
|
2014-01-11 14:38:30 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
Add *equivalents* for `compare-windows` (#27)
*equivalents* are strings that should compare equal in a `compare-windows`
session. You can define such strings in a **.qerc** file in the directory of
one of the files being compared. This helps ignoring known changes such as
type of function renaming... Here is an example to help compare files between
the `bellard/quickjs` and the `quickjs-ng/quickjs` repositories:
```
define_equivalent("JS_DupValue(ctx, ", "js_dup(");
define_equivalent("JSValue", "JSValueConst");
define_equivalent("JS_NewInt32(ctx, ", "js_int32(");
define_equivalent("JS_NewInt32(ctx,\n", "js_int32(");
define_equivalent("JS_NewUint32(ctx, ", "js_uint32(");
define_equivalent("JS_NewUint32(ctx,\n", "js_uint32(");
define_equivalent("JS_NewBool(ctx, ", "js_bool(");
define_equivalent("JS_NewFloat64(ctx, ", "js_float64(");
define_equivalent("JS_EXTERN ", "");
define_equivalent("JS_EXTERN JS", "JS");
define_equivalent("JS_EXTERN JS_", "JS_");
ignore_equivalent = 1;
```
Other changes were necessary for proper utf8 skipping:
- add `utf8_prefix_len(str1, str2)` to compute the length of a common initial
prefix not falling inside UTF-8 encoded codepoints.
- add `utf8_decode_prev` to get the previous codepoint
- add `eb_match_str_utf8_reverse`
2024-05-19 21:16:37 +02:00
|
|
|
int eb_match_str_utf8_reverse(EditBuffer *b, int offset, const char *str, int pos, int *offsetp) {
|
|
|
|
|
const char *p = str + pos;
|
|
|
|
|
while (p > str) {
|
|
|
|
|
char32_t c = utf8_decode_prev(&p, str);
|
|
|
|
|
if (eb_prevc(b, offset, &offset) != c)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (offsetp)
|
|
|
|
|
*offsetp = offset;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 01:19:32 +01:00
|
|
|
int eb_match_istr_utf8(EditBuffer *b, int offset, const char *str, int *offsetp) {
|
2014-01-11 14:38:30 +00:00
|
|
|
const char *p = str;
|
|
|
|
|
|
|
|
|
|
while (*p) {
|
2022-11-01 01:19:32 +01:00
|
|
|
char32_t c = utf8_decode(&p);
|
|
|
|
|
// XXX: should ignore accents?
|
|
|
|
|
if (qe_wtoupper(eb_nextc(b, offset, &offset)) != qe_wtoupper(c))
|
2014-01-11 14:38:30 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2014-01-11 15:07:14 +00:00
|
|
|
if (offsetp)
|
|
|
|
|
*offsetp = offset;
|
2014-01-11 14:38:30 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_putc(EditBuffer *b, char32_t c) {
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
char buf[8];
|
2022-10-29 19:43:38 +02:00
|
|
|
int len = eb_encode_char32(b, buf, c);
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
return eb_insert(b, b->offset, buf, len);
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
int eb_puts(EditBuffer *b, const char *s) {
|
|
|
|
|
return eb_insert_utf8_buf(b, b->offset, s, strlen(s));
|
sessions: implement session saving/restoring
- add qe_save_variables(s, b)
- add use_session_file global variable
- add VarDef::modified flag to detect customized variables
- set modified flag upon variable modifications
- dired: set modified flag when changing in dired variables
- fix BUG in qe_register_variables, did not set set_value handler
on last VarDef element
- make qe_save_variables() public
- remove do_save_variables(), move save_session() to parser.c
- add eb_puts() and eb_putc() for consistency
- add WF_HIDDEN window flag to temporarily flag windows to be deleted
- add do_hide_window(), do_delete_all_windows() and do_delete_hidden_windows()
- add qe_save_window_layout() to save window layout to session file
- add do_create_window(s, filename, layout) to restore window layout
- add qe_save_macros() to save keyboard macros to session file
- detect keyboard macro redefinitions and avoid duplicates
- add qe_save_open_files() to save list of open files and directories
- pass `all` flag to do_delete_other_windows() to force complete deletion
- add qe_load_session() and do_save_session():
* qe_load_session() is invoked before parsing the command line if
use_session_file is set, via the config file or command line option (-s)
* do_save_session() is invoked just before closing qemacs. It can also
be invoked as a command and shows a popup window with the contents of
the session file produced instead of saving it.
- fix CRASH BUG in command definitions, missing argument specifier caused
spurious crashes when invoking commands from script files. This affected:
find-file(), find-file-other-window(), find-alternate-file(), kill-buffer()
load-file-from-path().
- insert newly created windows in list in top-down left-right order
- update WF_RSEPARATOR flag upon deletion of vertically split window
2015-09-10 00:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
int eb_vprintf(EditBuffer *b, const char *fmt, va_list ap) {
|
2006-12-11 23:10:33 +00:00
|
|
|
char buf0[1024];
|
|
|
|
|
char *buf;
|
2014-01-31 12:14:13 +00:00
|
|
|
int len, size, written;
|
2017-03-26 15:57:24 +00:00
|
|
|
va_list ap2;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2017-04-15 09:39:02 +00:00
|
|
|
#ifndef va_copy
|
|
|
|
|
#define va_copy(s,d) __va_copy(s,d)
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-03-26 15:57:24 +00:00
|
|
|
va_copy(ap2, ap);
|
2006-12-11 23:10:33 +00:00
|
|
|
size = sizeof(buf0);
|
|
|
|
|
buf = buf0;
|
2017-03-26 15:57:24 +00:00
|
|
|
len = vsnprintf(buf, size, fmt, ap2);
|
|
|
|
|
va_end(ap2);
|
2006-12-11 23:10:33 +00:00
|
|
|
if (len >= size) {
|
|
|
|
|
size = len + 1;
|
2014-01-23 12:56:22 +00:00
|
|
|
buf = qe_malloc_bytes(size);
|
2006-12-11 23:10:33 +00:00
|
|
|
vsnprintf(buf, size, fmt, ap);
|
|
|
|
|
}
|
2014-02-05 00:56:48 +00:00
|
|
|
/* CG: insert buf encoding according to b->charset and b->eol_type.
|
2014-01-11 14:38:30 +00:00
|
|
|
* buf may contain \0 characters via the %c modifer.
|
|
|
|
|
* XXX: %c does not encode non ASCII characters as utf8.
|
|
|
|
|
*/
|
2022-09-08 13:47:02 +02:00
|
|
|
written = eb_insert_utf8_buf(b, b->offset, buf, len);
|
2008-04-05 23:04:56 +00:00
|
|
|
if (buf != buf0)
|
2014-01-23 12:56:22 +00:00
|
|
|
qe_free(&buf);
|
2014-01-31 12:14:13 +00:00
|
|
|
return written;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 13:47:02 +02:00
|
|
|
int eb_printf(EditBuffer *b, const char *fmt, ...) {
|
2017-03-26 15:57:24 +00:00
|
|
|
va_list ap;
|
|
|
|
|
int written;
|
|
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
written = eb_vprintf(b, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
return written;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-17 19:12:41 +02:00
|
|
|
int eb_print_style(EditBuffer *b, QETermStyle style, const char *fmt, ...) {
|
|
|
|
|
va_list ap;
|
|
|
|
|
int written;
|
|
|
|
|
|
|
|
|
|
b->cur_style = style;
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
written = eb_vprintf(b, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
b->cur_style = QE_STYLE_DEFAULT;
|
|
|
|
|
return written;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eb_print_field(EditBuffer *b, const char *name, const char *fmt, ...) {
|
|
|
|
|
va_list ap;
|
|
|
|
|
int written;
|
|
|
|
|
|
|
|
|
|
written = eb_print_style(b, QE_STYLE_VARIABLE, "%*s", b->tab_width, name);
|
|
|
|
|
written += eb_puts(b, *name ? ": " : " ");
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
written += eb_vprintf(b, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
return written;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-08 16:26:44 +00:00
|
|
|
#if 0
|
2004-05-29 10:17:37 +00:00
|
|
|
/* pad current line with spaces so that it reaches column n */
|
2022-09-08 13:47:02 +02:00
|
|
|
void eb_line_pad(EditBuffer *b, int offset, int n) {
|
|
|
|
|
/* Compute visual column visual column */
|
|
|
|
|
int tw = b->tab_width > 0 ? b->tab_width : 8;
|
|
|
|
|
int col = text_screen_width(b, eb_goto_bol(b, offset), offset, tw);
|
|
|
|
|
if (n > col)
|
|
|
|
|
eb_insert_spaces(b, offset, n - col);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2014-01-08 16:26:44 +00:00
|
|
|
#endif
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-02-10 21:27:53 +00:00
|
|
|
/* Read the contents of a buffer region encoded in a utf8 string */
|
|
|
|
|
int eb_get_region_contents(EditBuffer *b, int start, int stop,
|
2022-11-11 15:45:49 +01:00
|
|
|
char *buf, int buf_size, int encode_zero)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2022-11-11 15:45:49 +01:00
|
|
|
int size, offset;
|
|
|
|
|
buf_t outbuf, *out;
|
2014-02-10 21:27:53 +00:00
|
|
|
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
stop = clamp_offset(stop, 0, b->total_size);
|
|
|
|
|
start = clamp_offset(start, 0, stop);
|
2014-02-10 21:27:53 +00:00
|
|
|
size = stop - start;
|
|
|
|
|
|
2014-01-16 13:45:04 +00:00
|
|
|
/* do not use eb_read if overflow to avoid partial characters */
|
2014-02-05 00:56:48 +00:00
|
|
|
if (b->charset == &charset_utf8 && b->eol_type == EOL_UNIX
|
2014-02-10 21:27:53 +00:00
|
|
|
&& size < buf_size) {
|
|
|
|
|
eb_read(b, start, buf, size);
|
|
|
|
|
buf[size] = '\0';
|
2022-11-11 15:45:49 +01:00
|
|
|
if (!encode_zero || (int)strlen(buf) == size)
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
out = buf_init(&outbuf, buf, buf_size);
|
|
|
|
|
for (offset = start; offset < stop;) {
|
|
|
|
|
char32_t c = eb_nextc(b, offset, &offset);
|
|
|
|
|
if (c == 0 && encode_zero) {
|
|
|
|
|
/* special case: use redundant utf8x encoding */
|
|
|
|
|
buf_write(out, "\xC0\x80", 2);
|
|
|
|
|
} else {
|
2014-02-07 15:56:15 +00:00
|
|
|
buf_putc_utf8(out, c);
|
2014-01-16 13:45:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-11 15:45:49 +01:00
|
|
|
return out->len;
|
2014-02-07 15:56:15 +00:00
|
|
|
}
|
|
|
|
|
|
2014-02-10 21:27:53 +00:00
|
|
|
/* Compute the size of the contents of a buffer region encoded in utf8 */
|
|
|
|
|
int eb_get_region_content_size(EditBuffer *b, int start, int stop)
|
2014-02-07 15:56:15 +00:00
|
|
|
{
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
stop = clamp_offset(stop, 0, b->total_size);
|
|
|
|
|
start = clamp_offset(start, 0, stop);
|
2014-02-10 21:27:53 +00:00
|
|
|
|
2016-12-13 17:20:51 +00:00
|
|
|
/* assuming start and stop fall on character boundaries */
|
2014-02-07 15:56:15 +00:00
|
|
|
if (b->charset == &charset_utf8 && b->eol_type == EOL_UNIX) {
|
2014-02-10 21:27:53 +00:00
|
|
|
return stop - start;
|
2014-02-07 15:56:15 +00:00
|
|
|
} else {
|
2022-10-29 19:43:38 +02:00
|
|
|
int offset, size;
|
2014-02-07 15:56:15 +00:00
|
|
|
char buf[MAX_CHAR_BYTES];
|
|
|
|
|
|
2014-02-10 21:27:53 +00:00
|
|
|
for (size = 0, offset = start; offset < stop;) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_nextc(b, offset, &offset);
|
2014-02-07 15:56:15 +00:00
|
|
|
size += utf8_encode(buf, c);
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 09:40:20 +00:00
|
|
|
/* Insert 'size' bytes of 'src' buffer from position 'src_offset' into
|
|
|
|
|
* buffer 'dest' at offset 'dest_offset'. 'src' MUST BE DIFFERENT from
|
|
|
|
|
* 'dest'. Charset converson between source and destination buffer is
|
|
|
|
|
* performed.
|
2014-01-31 12:14:13 +00:00
|
|
|
* Return the number of bytes inserted.
|
2014-01-06 09:40:20 +00:00
|
|
|
*/
|
|
|
|
|
int eb_insert_buffer_convert(EditBuffer *dest, int dest_offset,
|
|
|
|
|
EditBuffer *src, int src_offset,
|
|
|
|
|
int size)
|
|
|
|
|
{
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
int styles_flags = min_int((dest->flags & BF_STYLES), (src->flags & BF_STYLES));
|
2014-01-15 19:44:24 +00:00
|
|
|
|
2014-02-05 00:56:48 +00:00
|
|
|
if (dest->charset == src->charset
|
|
|
|
|
&& dest->eol_type == src->eol_type
|
|
|
|
|
&& !styles_flags) {
|
2014-01-06 09:40:20 +00:00
|
|
|
return eb_insert_buffer(dest, dest_offset, src, src_offset, size);
|
|
|
|
|
} else {
|
|
|
|
|
EditBuffer *b;
|
2014-01-15 19:44:24 +00:00
|
|
|
int offset, offset_max, offset1 = dest_offset;
|
2014-01-06 09:40:20 +00:00
|
|
|
|
|
|
|
|
b = dest;
|
2014-01-15 19:44:24 +00:00
|
|
|
if (!styles_flags
|
|
|
|
|
&& ((b->flags & BF_SAVELOG) || dest_offset != b->total_size)) {
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
b = qe_new_buffer(b->qs, "*tmp*", BF_SYSTEM);
|
|
|
|
|
if (!b)
|
|
|
|
|
return 0;
|
2014-02-05 00:56:48 +00:00
|
|
|
eb_set_charset(b, dest->charset, dest->eol_type);
|
2014-01-15 19:44:24 +00:00
|
|
|
offset1 = 0;
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* well, not very fast, but simple */
|
2014-01-13 23:38:15 +00:00
|
|
|
/* XXX: should optimize save_log system for insert sequences */
|
2022-08-18 14:59:10 +02:00
|
|
|
// XXX: should optimize styles transfer
|
Various improvements for consistency
* add -Wno-packed compiler option
* add CONFIG_REGEX flag, undefined for tiny build
* disable regex commands in tiny build
* add documentation for some search commands and APIs
* reorder search tags for readability
* add isearch_yank_char
* use emacs names for:
isearch-repeat-backward, isearch-repeat-forward,
isearch-ring-advance, isearch-ring-retreat,
isearch-yank-word-or-char
* add occur alias for list-matching-lines
* add char32_to_utf8()
* restored some macros in cutils.h:
likely(x), unlikely(x), __maybe_unused, BOOL, FALSE, TRUE
* remove max(), min(), maxp(), minp(), clampp()
* add typed arithmetic functions:
min_int(), max_int(), clamp_int(), min3_int(), max3_int()
min_offset(), max_offset(), clamp_offset()
* use typed functions everywhere
* bump version to 5.4.1d
2022-11-21 00:20:18 +01:00
|
|
|
offset_max = min_offset(src->total_size, src_offset + size);
|
2014-01-06 09:40:20 +00:00
|
|
|
size = 0;
|
|
|
|
|
for (offset = src_offset; offset < offset_max;) {
|
|
|
|
|
char buf[MAX_CHAR_BYTES];
|
2017-04-12 07:33:20 +00:00
|
|
|
QETermStyle style = eb_get_style(src, offset);
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_nextc(src, offset, &offset);
|
|
|
|
|
int len = eb_encode_char32(b, buf, c);
|
2016-12-23 19:51:48 +00:00
|
|
|
b->cur_style = style;
|
2014-01-31 12:14:13 +00:00
|
|
|
size += eb_insert(b, offset1 + size, buf, len);
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (b != dest) {
|
|
|
|
|
size = eb_insert_buffer(dest, dest_offset, b, 0, b->total_size);
|
2014-01-23 12:56:22 +00:00
|
|
|
eb_free(&b);
|
2014-01-06 09:40:20 +00:00
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_get_line(EditBuffer *b, char32_t *buf, int size,
|
2026-05-14 15:21:04 +02:00
|
|
|
int offset, int *offset_ptr /* nullable */)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Get contents of the line starting at offset `offset` as an array of
|
|
|
|
|
code points. `offset` is bumped to point to the first unread character.
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `buf` a valid pointer to the destination array
|
|
|
|
|
@argument `size` the length of the destination array
|
|
|
|
|
@argument `offset` the offset in bytes of the beginning of the line in
|
|
|
|
|
the buffer
|
2026-05-14 15:21:04 +02:00
|
|
|
@argument `offset_ptr` a nullable pointer to a variable to receive the
|
|
|
|
|
offset of the first unread character in the buffer
|
2024-07-27 23:15:54 +02:00
|
|
|
@returns the number of codepoints stored into the destination array
|
|
|
|
|
before the newline if any.
|
|
|
|
|
@note: the return value `len` verifies `len >= 0` and `len < buf_size`.
|
|
|
|
|
If a complete line was read, `buf[len] == '\n'` and `buf[len + 1] == '\0'`.
|
2026-05-14 15:21:04 +02:00
|
|
|
A newline is stored at `buf[len]` even if at end of buffer without a trailing
|
|
|
|
|
newline.
|
2024-07-27 23:15:54 +02:00
|
|
|
Truncation can be detected by checking `buf[len] != '\n'` or `len < buf_size - 1`.
|
|
|
|
|
*/
|
2022-10-29 19:43:38 +02:00
|
|
|
int len = 0;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2016-12-23 19:51:48 +00:00
|
|
|
if (size > 0) {
|
|
|
|
|
for (;;) {
|
2024-07-27 23:15:54 +02:00
|
|
|
int next;
|
|
|
|
|
char32_t c = eb_nextc(b, offset, &next);
|
2016-12-23 19:51:48 +00:00
|
|
|
if (len + 1 >= size) {
|
|
|
|
|
buf[len] = '\0';
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-04-03 08:33:57 +00:00
|
|
|
buf[len++] = c;
|
2024-07-27 23:15:54 +02:00
|
|
|
offset = next;
|
2016-12-23 19:51:48 +00:00
|
|
|
if (c == '\n') {
|
2024-07-27 23:15:54 +02:00
|
|
|
/* end of line: offset points to the beginning of the next line */
|
|
|
|
|
/* adjust return value for easy stripping and truncation test */
|
2016-12-23 19:51:48 +00:00
|
|
|
buf[len--] = '\0';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2016-12-23 19:51:48 +00:00
|
|
|
if (offset_ptr)
|
|
|
|
|
*offset_ptr = offset;
|
|
|
|
|
return len;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-14 15:21:04 +02:00
|
|
|
int eb_get_line_length(EditBuffer *b, int offset, int *offset_ptr /* nullable */)
|
2024-07-29 08:16:49 +02:00
|
|
|
{
|
|
|
|
|
/*@API buffer
|
|
|
|
|
Get the length in codepoints of the line starting at offset `offset`
|
|
|
|
|
as an number of code points. `offset` is bumped to point to the first
|
|
|
|
|
character after the newline.
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `offset` the offset in bytes of the beginning of the line in
|
|
|
|
|
the buffer
|
2026-05-14 15:21:04 +02:00
|
|
|
@argument `offset_ptr` a nullable pointer to a variable to receive the
|
|
|
|
|
offset of the first unread character in the buffer.
|
2024-07-29 08:16:49 +02:00
|
|
|
@returns the number of codepoints in the line including the newline if any.
|
|
|
|
|
*/
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
|
|
while (eb_nextc(b, offset, &offset) != '\n') {
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
if (offset_ptr)
|
|
|
|
|
*offset_ptr = offset;
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-27 23:15:54 +02:00
|
|
|
int eb_fgets(EditBuffer *b, char *buf, int size,
|
2016-12-23 19:51:48 +00:00
|
|
|
int offset, int *offset_ptr)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2024-07-27 23:15:54 +02:00
|
|
|
/*@API buffer
|
|
|
|
|
Get the contents of the line starting at offset `offset` encoded
|
|
|
|
|
in UTF-8. `offset` is bumped to point to the first unread character.
|
|
|
|
|
@argument `b` a valid pointer to an `EditBuffer`
|
|
|
|
|
@argument `buf` a valid pointer to the destination array
|
|
|
|
|
@argument `size` the length of the destination array
|
|
|
|
|
@argument `offset` the offset in bytes of the beginning of the line in
|
|
|
|
|
the buffer
|
2026-05-14 15:21:04 +02:00
|
|
|
@argument `offset_ptr` a nullable pointer to a variable to receive the
|
|
|
|
|
offset of the first unread character in the buffer
|
2024-07-27 23:15:54 +02:00
|
|
|
@returns the number of bytes stored into the destination array before
|
|
|
|
|
the newline if any. No partial encoding is stored into the array.
|
|
|
|
|
@note: the return value `len` verifies `len >= 0` and `len < buf_size`.
|
|
|
|
|
If a complete line was read, `buf[len] == '\n'` and `buf[len + 1] == '\0'`.
|
|
|
|
|
Truncation can be detected by checking `buf[len] != '\n'` or `len < buf_size - 1`.
|
|
|
|
|
*/
|
|
|
|
|
int len = 0;
|
2014-01-16 13:45:04 +00:00
|
|
|
buf_t outbuf, *out;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2024-07-27 23:15:54 +02:00
|
|
|
if (size > 0) {
|
|
|
|
|
out = buf_init(&outbuf, buf, size);
|
|
|
|
|
for (;;) {
|
|
|
|
|
int next;
|
|
|
|
|
char32_t c = eb_nextc(b, offset, &next);
|
|
|
|
|
if (!buf_putc_utf8(out, c)) {
|
|
|
|
|
/* truncation: offset points to the first unread character */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
offset = next;
|
|
|
|
|
if (c == '\n') {
|
|
|
|
|
/* end of line: offset points to the beginning of the next line */
|
|
|
|
|
/* adjust return value for easy stripping and truncation test */
|
|
|
|
|
out->len--;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-12-23 19:51:48 +00:00
|
|
|
}
|
2024-07-27 23:15:54 +02:00
|
|
|
len = out->len;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2024-07-27 23:15:54 +02:00
|
|
|
if (offset_ptr)
|
|
|
|
|
*offset_ptr = offset;
|
|
|
|
|
return len;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2007-12-15 07:24:03 +00:00
|
|
|
int eb_prev_line(EditBuffer *b, int offset)
|
|
|
|
|
{
|
|
|
|
|
int offset1, seen_nl;
|
|
|
|
|
|
|
|
|
|
for (seen_nl = 0;;) {
|
|
|
|
|
if (eb_prevc(b, offset, &offset1) == '\n') {
|
|
|
|
|
if (seen_nl++)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
offset = offset1;
|
|
|
|
|
}
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* return offset of the beginning of the line containing offset */
|
2004-05-29 10:17:37 +00:00
|
|
|
int eb_goto_bol(EditBuffer *b, int offset)
|
|
|
|
|
{
|
2007-12-15 07:24:03 +00:00
|
|
|
int offset1;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2005-05-11 14:35:54 +00:00
|
|
|
for (;;) {
|
2007-12-15 07:24:03 +00:00
|
|
|
if (eb_prevc(b, offset, &offset1) == '\n')
|
2004-05-29 10:17:37 +00:00
|
|
|
break;
|
|
|
|
|
offset = offset1;
|
|
|
|
|
}
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-15 07:24:03 +00:00
|
|
|
/* move to the beginning of the line containing offset */
|
|
|
|
|
/* return offset of the beginning of the line containing offset */
|
|
|
|
|
/* store count of characters skipped at *countp */
|
|
|
|
|
int eb_goto_bol2(EditBuffer *b, int offset, int *countp)
|
|
|
|
|
{
|
|
|
|
|
int count, offset1;
|
|
|
|
|
|
|
|
|
|
for (count = 0;; count++) {
|
|
|
|
|
if (eb_prevc(b, offset, &offset1) == '\n')
|
|
|
|
|
break;
|
|
|
|
|
offset = offset1;
|
|
|
|
|
}
|
|
|
|
|
*countp = count;
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-30 21:43:28 +08:00
|
|
|
/* return offset of the first non-whitespace character of the line containing offset.
|
|
|
|
|
* If there are no non-whitespace characters on the line, return the end of line.
|
|
|
|
|
*/
|
|
|
|
|
int eb_goto_bol_nspace(EditBuffer *b, int offset)
|
|
|
|
|
{
|
|
|
|
|
int offset1 = eb_goto_bol(b, offset);
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
offset = offset1;
|
|
|
|
|
char32_t c = eb_nextc(b, offset, &offset1);
|
|
|
|
|
if (!qe_isblank(c))
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-19 17:25:02 +00:00
|
|
|
/* test for blank line starting at <offset>.
|
|
|
|
|
* return 0 if not blank.
|
|
|
|
|
* return 1 if blank and store start of next line in <*offset1>.
|
|
|
|
|
*/
|
2022-08-13 16:16:21 +02:00
|
|
|
int eb_is_blank_line(EditBuffer *b, int offset, int *offset1) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c;
|
2015-08-27 23:03:39 +00:00
|
|
|
|
2014-01-19 17:25:02 +00:00
|
|
|
while ((c = eb_nextc(b, offset, &offset)) != '\n') {
|
|
|
|
|
if (!qe_isblank(c))
|
|
|
|
|
return 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
2014-01-19 17:25:02 +00:00
|
|
|
if (offset1)
|
|
|
|
|
*offset1 = offset;
|
|
|
|
|
return 1;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
2014-03-23 01:11:34 +00:00
|
|
|
/* check if <offset> is within indentation. */
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_is_in_indentation(EditBuffer *b, int offset) {
|
|
|
|
|
char32_t c;
|
2014-03-23 01:11:34 +00:00
|
|
|
|
|
|
|
|
while ((c = eb_prevc(b, offset, &offset)) != '\n') {
|
|
|
|
|
if (!qe_isblank(c))
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-15 07:24:03 +00:00
|
|
|
/* return offset of the end of the line containing offset */
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_goto_eol(EditBuffer *b, int offset1) {
|
2007-12-15 07:24:03 +00:00
|
|
|
for (;;) {
|
2022-10-29 19:43:38 +02:00
|
|
|
int offset = offset1;
|
|
|
|
|
char32_t c = eb_nextc(b, offset, &offset1);
|
2007-12-15 07:24:03 +00:00
|
|
|
if (c == '\n')
|
2022-10-29 19:43:38 +02:00
|
|
|
return offset;
|
2007-12-15 07:24:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 19:43:38 +02:00
|
|
|
int eb_next_line(EditBuffer *b, int offset) {
|
2005-05-11 14:35:54 +00:00
|
|
|
for (;;) {
|
2022-10-29 19:43:38 +02:00
|
|
|
char32_t c = eb_nextc(b, offset, &offset);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (c == '\n')
|
2022-10-29 19:43:38 +02:00
|
|
|
return offset;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-31 07:51:56 +00:00
|
|
|
/* buffer property handling */
|
|
|
|
|
|
|
|
|
|
static void eb_plist_callback(EditBuffer *b, void *opaque, int edge,
|
|
|
|
|
enum LogOperation op, int offset, int size)
|
|
|
|
|
{
|
|
|
|
|
QEProperty **pp;
|
|
|
|
|
QEProperty *p;
|
2020-10-21 15:01:52 +00:00
|
|
|
|
2017-03-31 07:51:56 +00:00
|
|
|
/* update properties */
|
|
|
|
|
if (op == LOGOP_INSERT) {
|
|
|
|
|
for (p = b->property_list; p; p = p->next) {
|
2026-06-13 18:08:40 +02:00
|
|
|
if (p->offset >= offset) {
|
|
|
|
|
if (p->offset == offset && (p->flags & QE_PROP_MARK))
|
|
|
|
|
continue;
|
2017-03-31 07:51:56 +00:00
|
|
|
p->offset += size;
|
2026-06-13 18:08:40 +02:00
|
|
|
}
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (op == LOGOP_DELETE) {
|
|
|
|
|
for (pp = &b->property_list; (p = *pp) != NULL;) {
|
|
|
|
|
if (p->offset >= offset) {
|
2026-06-14 00:13:10 +03:00
|
|
|
if (p->offset == offset && (p->flags & QE_PROP_MARK)) {
|
|
|
|
|
pp = &p->next;
|
2026-06-13 18:08:40 +02:00
|
|
|
continue;
|
2026-06-14 00:13:10 +03:00
|
|
|
}
|
2017-03-31 07:51:56 +00:00
|
|
|
if (p->offset < offset + size) {
|
|
|
|
|
/* property is anchored inside block: remove it */
|
2026-06-13 18:08:40 +02:00
|
|
|
if (!(p->flags & QE_PROP_KEEP)) {
|
|
|
|
|
*pp = p->next;
|
|
|
|
|
if (p->flags & QE_PROP_FREE) {
|
|
|
|
|
qe_free(&p->data);
|
|
|
|
|
}
|
|
|
|
|
qe_free(&p);
|
|
|
|
|
continue;
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
2026-06-13 18:08:40 +02:00
|
|
|
p->offset = offset;
|
2026-06-14 00:13:10 +03:00
|
|
|
pp = &p->next;
|
2017-03-31 07:51:56 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
p->offset -= size;
|
|
|
|
|
}
|
2026-06-13 18:08:40 +02:00
|
|
|
pp = &p->next;
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
QEProperty *eb_add_property(EditBuffer *b, int offset, int type, int flags, const void *data) {
|
2017-04-17 09:16:24 +00:00
|
|
|
QEProperty *p;
|
2017-03-31 07:51:56 +00:00
|
|
|
QEProperty **pp;
|
2026-06-13 18:08:40 +02:00
|
|
|
int extra = 0;
|
|
|
|
|
|
|
|
|
|
if (flags & QE_PROP_DUP) {
|
|
|
|
|
extra = strlen(data) + 1;
|
|
|
|
|
flags &= ~QE_PROP_FREE;
|
|
|
|
|
}
|
2017-03-31 07:51:56 +00:00
|
|
|
|
|
|
|
|
if (!b->property_list) {
|
|
|
|
|
eb_add_callback(b, eb_plist_callback, NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-18 19:18:58 +02:00
|
|
|
/* insert property in ascending order of offset */
|
2026-06-13 18:08:40 +02:00
|
|
|
for (pp = &b->property_list; (p = *pp) != NULL; pp = &p->next) {
|
2024-07-18 19:18:58 +02:00
|
|
|
if (p->offset > offset)
|
2017-03-31 07:51:56 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2017-04-17 09:16:24 +00:00
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
p = qe_mallocz_hack(QEProperty, extra);
|
2017-04-17 09:16:24 +00:00
|
|
|
p->offset = offset;
|
|
|
|
|
p->type = type;
|
2026-06-13 18:08:40 +02:00
|
|
|
p->flags = flags;
|
|
|
|
|
if (extra)
|
|
|
|
|
data = memcpy(p + 1, data, extra);
|
|
|
|
|
p->data = unconst(void*)data;
|
2017-03-31 07:51:56 +00:00
|
|
|
p->next = *pp;
|
2026-06-13 18:08:40 +02:00
|
|
|
return *pp = p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eb_del_property(EditBuffer *b, QEProperty *prop) {
|
|
|
|
|
QEProperty *p;
|
|
|
|
|
QEProperty **pp;
|
|
|
|
|
|
|
|
|
|
for (pp = &b->property_list; (p = *pp) != NULL; pp = &p->next) {
|
|
|
|
|
if (p == prop) {
|
|
|
|
|
*pp = p->next;
|
|
|
|
|
if (p->flags & QE_PROP_FREE) {
|
|
|
|
|
qe_free(&p->data);
|
|
|
|
|
}
|
|
|
|
|
qe_free(&p);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-18 19:18:58 +02:00
|
|
|
void eb_add_tag(EditBuffer *b, int offset, const char *s) {
|
|
|
|
|
QEProperty *p;
|
|
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
/* prevent tag duplicates with exact same offset */
|
|
|
|
|
for (p = b->property_list; p && p->offset <= offset; p = p->next) {
|
2024-07-18 19:18:58 +02:00
|
|
|
if (p->offset == offset && p->type == QE_PROP_TAG && strequal(p->data, s))
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-06-13 18:08:40 +02:00
|
|
|
eb_add_property(b, offset, QE_PROP_TAG, QE_PROP_DUP, s);
|
2024-07-18 19:18:58 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
QEProperty *eb_find_property(EditBuffer *b, int offset, int offset2, int type, QEProperty *stop) {
|
2017-03-31 07:51:56 +00:00
|
|
|
QEProperty *found = NULL;
|
|
|
|
|
QEProperty *p;
|
2026-06-13 18:08:40 +02:00
|
|
|
for (p = b->property_list; p && p != stop && p->offset < offset2; p = p->next) {
|
2017-04-17 09:16:24 +00:00
|
|
|
if (p->offset >= offset && p->type == type) {
|
|
|
|
|
/* return the last property between offset and offset2 */
|
2017-03-31 07:51:56 +00:00
|
|
|
found = p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-13 18:08:40 +02:00
|
|
|
void eb_delete_properties(EditBuffer *b, int offset, int offset2, int mask) {
|
2017-03-31 07:51:56 +00:00
|
|
|
QEProperty *p;
|
|
|
|
|
QEProperty **pp;
|
|
|
|
|
|
2017-04-17 09:16:24 +00:00
|
|
|
if (!b->property_list)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (pp = &b->property_list; (p = *pp) != NULL && p->offset < offset2;) {
|
2026-06-13 18:08:40 +02:00
|
|
|
if (p->offset >= offset && p->offset < offset2 && (p->type & mask)) {
|
|
|
|
|
*pp = p->next;
|
|
|
|
|
if (p->flags & QE_PROP_FREE) {
|
2017-04-17 09:16:24 +00:00
|
|
|
qe_free(&p->data);
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
2017-04-17 09:16:24 +00:00
|
|
|
qe_free(&p);
|
|
|
|
|
} else {
|
2026-06-13 18:08:40 +02:00
|
|
|
pp = &p->next;
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
2017-04-17 09:16:24 +00:00
|
|
|
}
|
|
|
|
|
if (!b->property_list) {
|
|
|
|
|
eb_free_callback(b, eb_plist_callback, NULL);
|
2017-03-31 07:51:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* buffer data type handling */
|
|
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
void qe_register_data_type(QEmacsState *qs, EditBufferDataType *bdt)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
|
|
|
|
EditBufferDataType **lp;
|
|
|
|
|
|
2014-01-04 17:32:42 +00:00
|
|
|
lp = &qs->first_buffer_data_type;
|
2004-05-29 10:17:37 +00:00
|
|
|
while (*lp != NULL)
|
|
|
|
|
lp = &(*lp)->next;
|
|
|
|
|
bdt->next = NULL;
|
|
|
|
|
*lp = bdt;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-20 16:27:21 +00:00
|
|
|
/* Write buffer contents between <start> and <end> to file <filename>,
|
|
|
|
|
* return bytes written or -1 if error
|
2004-05-29 10:17:37 +00:00
|
|
|
*/
|
2007-12-20 16:27:21 +00:00
|
|
|
int eb_write_buffer(EditBuffer *b, int start, int end, const char *filename)
|
|
|
|
|
{
|
|
|
|
|
if (!b->data_type->buffer_save)
|
|
|
|
|
return -1;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2007-12-20 16:27:21 +00:00
|
|
|
return b->data_type->buffer_save(b, start, end, filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save buffer contents to buffer associated file, handle backups,
|
|
|
|
|
* return bytes written or -1 if error
|
|
|
|
|
*/
|
|
|
|
|
int eb_save_buffer(EditBuffer *b)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
2014-01-04 17:26:30 +00:00
|
|
|
int ret, st_mode;
|
2004-05-29 10:17:37 +00:00
|
|
|
char buf1[MAX_FILENAME_SIZE];
|
|
|
|
|
const char *filename;
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
|
|
if (!b->data_type->buffer_save)
|
|
|
|
|
return -1;
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
filename = b->filename;
|
|
|
|
|
/* get old file permission */
|
2014-01-04 17:26:30 +00:00
|
|
|
st_mode = 0644;
|
2004-05-29 10:17:37 +00:00
|
|
|
if (stat(filename, &st) == 0)
|
2014-01-04 17:26:30 +00:00
|
|
|
st_mode = st.st_mode & 0777;
|
2004-05-29 10:17:37 +00:00
|
|
|
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
if (!b->qs->backup_inhibited
|
2014-03-15 23:15:53 +00:00
|
|
|
&& strlen(filename) < MAX_FILENAME_SIZE - 1) {
|
|
|
|
|
/* backup old file if present */
|
2008-04-22 08:17:02 +00:00
|
|
|
if (snprintf(buf1, sizeof(buf1), "%s~", filename) < ssizeof(buf1)) {
|
|
|
|
|
// should check error code
|
|
|
|
|
rename(filename, buf1);
|
|
|
|
|
}
|
2007-12-26 09:49:52 +00:00
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
|
2014-01-04 17:26:30 +00:00
|
|
|
/* CG: should pass st_mode to buffer_save */
|
2007-12-20 16:27:21 +00:00
|
|
|
ret = b->data_type->buffer_save(b, 0, b->total_size, filename);
|
2004-05-29 10:17:37 +00:00
|
|
|
if (ret < 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2008-04-05 23:04:56 +00:00
|
|
|
#ifndef CONFIG_WIN32
|
2014-01-04 17:26:30 +00:00
|
|
|
/* set correct file st_mode to old file permissions */
|
|
|
|
|
chmod(filename, st_mode);
|
2004-05-29 10:17:37 +00:00
|
|
|
#endif
|
2026-05-24 14:38:47 +02:00
|
|
|
if (stat(filename, &st) == 0) {
|
|
|
|
|
b->file_mtime = st.st_mtime;
|
|
|
|
|
b->file_size = st.st_size;
|
|
|
|
|
}
|
2004-05-29 10:17:37 +00:00
|
|
|
/* reset log */
|
2006-12-09 19:02:07 +00:00
|
|
|
/* CG: should not do this! */
|
2015-08-25 16:19:42 +00:00
|
|
|
//eb_free_log_buffer(b);
|
2004-05-29 10:17:37 +00:00
|
|
|
b->modified = 0;
|
2007-12-20 16:27:21 +00:00
|
|
|
return ret;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* invalidate buffer raw data */
|
|
|
|
|
void eb_invalidate_raw_data(EditBuffer *b)
|
|
|
|
|
{
|
|
|
|
|
b->save_log = 0;
|
|
|
|
|
eb_delete(b, 0, b->total_size);
|
2015-08-25 16:19:42 +00:00
|
|
|
eb_free_log_buffer(b);
|
|
|
|
|
b->modified = 0;
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EditBufferDataType raw_data_type = {
|
|
|
|
|
"raw",
|
2013-12-23 23:26:43 +00:00
|
|
|
raw_buffer_load,
|
|
|
|
|
raw_buffer_save,
|
|
|
|
|
raw_buffer_close,
|
2006-12-31 19:34:00 +00:00
|
|
|
NULL, /* next */
|
2004-05-29 10:17:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* init buffer handling */
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
void qe_data_init(QEmacsState *qs)
|
2004-05-29 10:17:37 +00:00
|
|
|
{
|
Remove references to global `qe_state` (#45)
* Remove references to global `qe_state`
Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`
Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`
Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`
Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`
Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`
Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00
|
|
|
qe_register_data_type(qs, &raw_data_type);
|
2004-05-29 10:17:37 +00:00
|
|
|
}
|