diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index f8e402e10..4f8b552e2 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -27,6 +27,7 @@ qwaq_app_dat_src= \ qwaq-app.r \ qwaq-button.r \ qwaq-draw.r \ + qwaq-editbuffer.r \ qwaq-garray.r \ qwaq-group.r \ qwaq-listener.r \ @@ -41,7 +42,11 @@ qwaq_curses_libs= \ $(top_builddir)/libs/video/targets/libvid_common.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/gib/libQFgib.la -qwaq_curses_SOURCES=main.c qwaq-curses.c qwaq-input.c +qwaq_curses_SOURCES= \ + main.c \ + qwaq-curses.c \ + qwaq-editbuffer-bi.c \ + qwaq-input.c qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) qwaq_curses_LDFLAGS= diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 484618571..1e7bfa28f 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -154,9 +154,10 @@ create_progs (void) PR_Init_Cvars (); PR_Init (pr); RUA_Init (pr, 0); - Key_Progs_Init (pr); - PR_Cmds_Init (pr); - BI_Init (pr); + Key_Progs_Init (pr); // FIXME not all threads + PR_Cmds_Init (pr); // FIXME not all threads + BI_Init (pr); // FIXME not all threads + QWAQ_EditBuffer_Init (pr); // FIXME not all threads return pr; } diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c new file mode 100644 index 000000000..d8ec63969 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -0,0 +1,908 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/progs.h" +#include "QF/quakeio.h" +#include "QF/txtbuffer.h" + +#include "qwaq.h" +#include "qwaq-editbuffer.h" + +#define always_inline inline __attribute__((__always_inline__)) + +typedef struct editbuffer_s { + void *freenext; // for PR_RESMAP + txtbuffer_t *txtbuffer; + int modified; + int tabSize; +} editbuffer_t; + +typedef struct qwaq_ebresources_s { + progs_t *pr; + PR_RESMAP (editbuffer_t) buffers; +} qwaq_ebresources_t; + +static editbuffer_t * +editbuffer_new (qwaq_ebresources_t *res) +{ + PR_RESNEW (editbuffer_t, res->buffers); +} + +static void +editbuffer_free (qwaq_ebresources_t *res, editbuffer_t *buffer) +{ + PR_RESFREE (editbuffer_t, res->buffers, buffer); +} + +static void +editbuffer_reset (qwaq_ebresources_t *res) +{ + PR_RESRESET (editbuffer_t, res->buffers); +} + +static inline editbuffer_t * +editbuffer_get (qwaq_ebresources_t *res, unsigned index) +{ + PR_RESGET (res->buffers, index); +} + +static inline int +editbuffer_index (qwaq_ebresources_t *res, editbuffer_t *buffer) +{ + PR_RESINDEX (res->buffers, buffer); +} + +static always_inline editbuffer_t * __attribute__((pure)) +get_editbuffer (qwaq_ebresources_t *res, const char *name, int handle) +{ + editbuffer_t *buffer = editbuffer_get (res, handle); + + if (!buffer || !buffer->txtbuffer) { + PR_RunError (res->pr, "invalid edit buffer passed to %s", name + 3); + } + return buffer; +} + +static always_inline int +isword (unsigned char c) +{ + return c >= 128 || c == '_' || isalnum(c); +} + +static always_inline unsigned +spanGap (txtbuffer_t *buffer, unsigned ptr) +{ + return ptr < buffer->gapOffset ? ptr : ptr + buffer->gapSize; +} + +static always_inline char +getChar (txtbuffer_t *buffer, unsigned ptr) +{ + return buffer->text[spanGap (buffer, ptr)]; +} + +static always_inline unsigned +nextChar (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr < buffer->textSize && getChar (buffer, ptr) != '\n') { + return ptr + 1; + } + return ptr; +} + +static always_inline unsigned +prevChar (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr > 0 && getChar (buffer, ptr - 1) != '\n') { + return ptr - 1; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextNonSpace (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isspace (c) || c == '\n') { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +prevNonSpace (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isspace (c) || c == '\n') { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextWord (txtbuffer_t *buffer, unsigned ptr) +{ + if (buffer->textSize && ptr < buffer->textSize - 1) { + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isword (c)) { + break; + } + ptr++; + } + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (c == '\n') { + return ptr; + } + if (isword (c)) { + break; + } + ptr++; + } + } + return ptr; +} + +static always_inline unsigned +prevWord (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr > 0) { + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isword (c)) { + break; + } + ptr--; + } + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (c == '\n') { + return ptr; + } + if (isword (c)) { + break; + } + ptr--; + } + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextLine (txtbuffer_t *buffer, unsigned ptr) +{ + unsigned oldptr = ptr; + while (ptr < buffer->textSize && getChar (buffer, ptr++) != '\n') { + } + if (ptr == buffer->textSize && ptr > 0 + && getChar (buffer, ptr - 1) != '\n') { + return oldptr; + } + return ptr; +} + +static always_inline unsigned +prevLine (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr) { + ptr--; + while (ptr > 0 && getChar (buffer, ptr - 1) != '\n') { + ptr--; + } + } + return ptr; +} + +static always_inline unsigned +charPos (txtbuffer_t *buffer, unsigned ptr, unsigned target, int tabSize) +{ + unsigned pos = 0; + + while (ptr < target) { + if (getChar (buffer, ptr) == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + return pos; +} + +static always_inline unsigned __attribute__((pure)) +charPtr (txtbuffer_t *buffer, unsigned ptr, unsigned target, int tabSize) +{ + unsigned pos = 0; + while (pos < target && ptr < buffer->textSize + && getChar (buffer, ptr) != '\n') { + if (getChar (buffer, ptr) == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + if (pos > target) { + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +getEOW (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isword (c)) { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +getBOW (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isword (c)) { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +getEOL (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (c == '\n') { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +getBOL (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (c == '\n') { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned +_countLines (txtbuffer_t *buffer, unsigned start, unsigned len) +{ + unsigned count = 0; + char *ptr = buffer->text + start; + + while (len-- > 0) { + count += *ptr++ == '\n'; + } + return count; +} + +static always_inline unsigned +countLines (txtbuffer_t *buffer, unsigned start, unsigned len) +{ + if (start < buffer->gapOffset) { + if (start + len <= buffer->gapOffset) { + return _countLines (buffer, start, len); + } else { + return _countLines (buffer, start, buffer->gapOffset - start) + + _countLines (buffer, buffer->gapOffset + buffer->gapSize, + len - (buffer->gapOffset - start)); + } + } else { + return _countLines (buffer, start + buffer->gapOffset, len); + } +} + +static const char * +_search (txtbuffer_t *buffer, const char *ptr, unsigned len, + const char *str, unsigned slen, int dir, + int (*cmp)(const char *, const char *, size_t)) +{ + while (len-- > 0) { + if (*ptr == *str) { + unsigned offset = ptr - buffer->text; + if (offset > buffer->gapOffset + || offset + slen < buffer->gapOffset) { + // search does not span gap + if (cmp (ptr, str, slen) == 0) { + return ptr; + } + } else { + // search spans gap + unsigned l = buffer->gapOffset - offset; + if (cmp (ptr, str, l) == 0 + && cmp (ptr + l + buffer->gapSize, + str + l, slen - l) == 0) { + return ptr; + } + } + } else { + ptr += dir; + } + } + return 0; +} + +static int +search (txtbuffer_t *buffer, const eb_sel_t *sel, const char *str, int dir, + eb_sel_t *find, int (*cmp)(const char *, const char *, size_t)) +{ + unsigned start = sel->start; + unsigned slen = strlen (str); + unsigned end = start + sel->length - slen; + const char *found = 0; + + find->start = 0; + find->length = 0; + + if (sel->length >= slen) { + if (dir < 0) { + const char *s = buffer->text + spanGap (buffer, end); + if ((start < buffer->gapOffset && end <= buffer->gapOffset) + || start > buffer->gapOffset) { + found = _search (buffer, s, end - start, str, slen, -1, cmp); + } else { + unsigned l = end - (buffer->gapOffset + buffer->gapSize); + found = _search (buffer, s, l, str, slen, 1, cmp); + if (!found) { + s -= l + buffer->gapSize; + l = buffer->gapOffset - start; + found = _search (buffer, s, l, str, slen, 1, cmp); + } + } + } else { + const char *s = buffer->text + spanGap (buffer, start); + if ((start < buffer->gapOffset && end <= buffer->gapOffset) + || start > buffer->gapOffset) { + found = _search (buffer, s, end - start, str, slen, 1, cmp); + } else { + unsigned l = buffer->gapOffset - start; + found = _search (buffer, s, l, str, slen, 1, cmp); + if (!found) { + s += l + buffer->gapSize; + l = end - start - l; + found = _search (buffer, s, l, str, slen, 1, cmp); + } + } + } + } + if (found) { + unsigned offset = found - buffer->text; + if (offset > buffer->gapOffset) { + offset -= buffer->gapSize; + } + find->start = offset; + find->length = slen; + return 1; + } + return 0; +} + +static int +saveFile (txtbuffer_t *buffer, const char *filename) +{ + QFile *file = Qopen (filename, "wt"); + + if (file) { + unsigned offset = buffer->gapOffset + buffer->gapSize; + Qwrite (file, buffer->text, buffer->gapOffset); + Qwrite (file, buffer->text + offset, buffer->textSize - offset); + Qclose (file); + return 1; + } + return 0; +} + +static int +loadFile (txtbuffer_t *buffer, const char *filename) +{ + QFile *file = Qopen (filename, "rtz"); + char *dst; + unsigned len; + + if (file) { + len = Qfilesize (file); + // ensure buffer is empty + TextBuffer_DeleteAt (buffer, 0, buffer->textSize); + dst = TextBuffer_OpenGap (buffer, 0, len); + Qread (file, dst, len); + + buffer->textSize += len; + buffer->gapOffset += len; + buffer->gapSize -= len; + + Qclose (file); + return 1; + } + return 0; +} + +static unsigned +formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, + int *dst, unsigned length, eb_sel_t *selection, eb_color_t *colors, + int tabSize) +{ + unsigned pos = 0; + unsigned ptr = linePtr; + unsigned sels = selection->start; + unsigned sele = selection->start + selection->length; + int coln = (colors->normal & ~0xff); + int cols = (colors->selected & ~0xff); + int col; + byte c; + int count; + + while (pos < xpos && ptr < buffer->textSize) { + c = getChar (buffer, ptr); + if (c == '\n') { + break; + } + if (c == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + col = ptr >= sels && ptr < sele ? cols : coln; + while (xpos < pos && length-- > 0) { + *dst++ = col | ' '; + } + while (length > 0) { + col = ptr >= sels && ptr < sele ? cols : coln; + c = getChar (buffer, ptr++); + if (c == '\n') { + break; + } + count = 1; + if (c == '\t') { + c = ' '; + count = tabSize - (pos % tabSize); + } + while (length-- > 0 && count-- > 0) { + *dst++ = col | c; + pos++; + } + } + col = ptr >= sels && ptr < sele ? cols : coln; + while (length-- > 0) { + *dst++ = col | ' '; + } + return ptr; +} + +//=== + +static void +bi_i_EditBuffer__init (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + txtbuffer_t *txtbuffer = TextBuffer_Create (); + editbuffer_t *buffer = editbuffer_new (res); + + buffer->txtbuffer = txtbuffer; + buffer->tabSize = 4; // FIXME + + R_INT (pr) = editbuffer_index (res, buffer); +} + +static void +bi_i_EditBuffer__initWithFile_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + const char *filename = P_GSTRING (pr, 0); + txtbuffer_t *txtbuffer = TextBuffer_Create (); + editbuffer_t *buffer = editbuffer_new (res); + + buffer->txtbuffer = txtbuffer; + buffer->tabSize = 4; // FIXME + + loadFile (buffer->txtbuffer, filename); + R_INT (pr) = editbuffer_index (res, buffer); +} + +static void +bi_i_EditBuffer__dealloc (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + TextBuffer_Destroy (buffer->txtbuffer); + editbuffer_free (res, buffer); +} + +static void +bi_i_EditBuffer__nextChar_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextChar (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevChar_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevChar (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextNonSpace (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevNonSpace (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextWord (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevWord (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextLine (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevLine (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextLine__ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned count = P_UINT (pr, 3); + + while (count-- > 0) { + unsigned oldptr = ptr; + ptr = nextLine (buffer->txtbuffer, ptr); + if (ptr == buffer->txtbuffer->textSize && ptr > 0 + && getChar (buffer->txtbuffer, ptr - 1) != '\n') { + ptr = oldptr; + break; + } + } + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__prevLine__ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned count = P_UINT (pr, 3); + + while (ptr && count-- > 0) { + ptr = prevLine (buffer->txtbuffer, ptr); + } + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__charPos_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned target = P_UINT (pr, 3); + int tabSize = buffer->tabSize; + + R_INT (pr) = charPos (buffer->txtbuffer, ptr, target, tabSize); +} + +static void +bi_i_EditBuffer__charPtr_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned target = P_UINT (pr, 3); + int tabSize = buffer->tabSize; + + R_INT (pr) = charPtr (buffer->txtbuffer, ptr, target, tabSize); +} + +static void +bi_i_EditBuffer__getWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned s = getBOW (buffer->txtbuffer, ptr); + unsigned e = getEOW (buffer->txtbuffer, ptr); + + R_PACKED (pr, eb_sel_t).start = s; + R_PACKED (pr, eb_sel_t).length = e - s; +} + +static void +bi_i_EditBuffer__getLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned s = getBOL (buffer->txtbuffer, ptr); + unsigned e = getEOL (buffer->txtbuffer, ptr); + + R_PACKED (pr, eb_sel_t).start = s; + R_PACKED (pr, eb_sel_t).length = e - s; +} + +static void +bi_i_EditBuffer__getBOL_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = getBOL (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__getEOL_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = getEOL (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__getBOT (progs_t *pr) +{ + //qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + //int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + //editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + R_INT (pr) = 0; +} + +static void +bi_i_EditBuffer__getEOT (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + R_INT (pr) = buffer->txtbuffer->textSize; +} + +static void +bi_i_EditBuffer__countLines_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + + R_INT (pr) = countLines (buffer->txtbuffer, + selection->start, selection->length); +} + +static void +bi_i_EditBuffer__search_for_direction_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + const char *str = P_GSTRING (pr, 3); + int dir = P_INT (pr, 4); + + search (buffer->txtbuffer, selection, str, dir, &R_PACKED (pr, eb_sel_t), + strncmp); +} + +static void +bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + const char *str = P_GSTRING (pr, 3); + int dir = P_INT (pr, 4); + + search (buffer->txtbuffer, selection, str, dir, &R_PACKED (pr, eb_sel_t), + strncasecmp); +} + +static void +bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned linePtr = P_UINT (pr, 2); + unsigned xpos = P_UINT (pr, 3); + int *dst = (int *) P_GPOINTER (pr, 4); + unsigned length = P_UINT (pr, 5); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 6); + __auto_type colors = &P_PACKED (pr, eb_color_t, 7); + int tabSize = buffer->tabSize; + unsigned ptr; + + ptr = formatLine (buffer->txtbuffer, linePtr, xpos, dst, length, selection, + colors, tabSize); + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__modified (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + R_INT (pr) = buffer->modified; +} + +static void +bi_i_EditBuffer__textSize (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + R_INT (pr) = buffer->txtbuffer->textSize; +} + +static void +bi_i_EditBuffer__saveFile_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + const char *filename = P_GSTRING (pr, 2); + + if (saveFile (buffer->txtbuffer, filename)) { + buffer->modified = 0; + } +} + +static void +qwaq_ebresources_clear (progs_t *pr, void *data) +{ + __auto_type res = (qwaq_ebresources_t *) data; + + for (size_t i = 0; i < res->buffers._size; i++) { + editbuffer_t *buffer = editbuffer_get (res, ~i); + if (buffer->txtbuffer) { + TextBuffer_Destroy (buffer->txtbuffer); + buffer->txtbuffer = 0; + } + } + editbuffer_reset (res); +} + +static builtin_t builtins[] = { + {"_i_EditBuffer__init", bi_i_EditBuffer__init, -1}, + {"_i_EditBuffer__initWithFile_", bi_i_EditBuffer__initWithFile_, -1}, + {"_i_EditBuffer__dealloc", bi_i_EditBuffer__dealloc, -1}, + {"_i_EditBuffer__nextChar_", bi_i_EditBuffer__nextChar_, -1}, + {"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1}, + {"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1}, + {"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1}, + {"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1}, + {"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1}, + {"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1}, + {"_i_EditBuffer__prevLine_", bi_i_EditBuffer__prevLine_, -1}, + {"_i_EditBuffer__nextLine__", bi_i_EditBuffer__nextLine__, -1}, + {"_i_EditBuffer__prevLine__", bi_i_EditBuffer__prevLine__, -1}, + {"_i_EditBuffer__charPos_at_", bi_i_EditBuffer__charPos_at_, -1}, + {"_i_EditBuffer__charPtr_at_", bi_i_EditBuffer__charPtr_at_, -1}, + {"_i_EditBuffer__getWord_", bi_i_EditBuffer__getWord_, -1}, + {"_i_EditBuffer__getLine_", bi_i_EditBuffer__getLine_, -1}, + {"_i_EditBuffer__getBOL_", bi_i_EditBuffer__getBOL_, -1}, + {"_i_EditBuffer__getEOL_", bi_i_EditBuffer__getEOL_, -1}, + {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, + {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, + {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, + {"_i_EditBuffer__search_for_direction_", + bi_i_EditBuffer__search_for_direction_, -1}, + {"_i_EditBuffer__isearch_for_direction_", + bi_i_EditBuffer__isearch_for_direction_,-1}, + {"_i_EditBuffer__formatLine_from_into_width_highlight_colors_", + bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, + {"_i_EditBuffer__modified", bi_i_EditBuffer__modified, -1}, + {"_i_EditBuffer__textSize", bi_i_EditBuffer__textSize, -1}, + {"_i_EditBuffer__saveFile_", bi_i_EditBuffer__saveFile_, -1}, + {} +}; + +void +QWAQ_EditBuffer_Init (progs_t *pr) +{ + qwaq_ebresources_t *res = calloc (sizeof (*res), 1); + res->pr = pr; + + PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear); + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/qwaq-editbuffer.h new file mode 100644 index 000000000..215937a55 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer.h @@ -0,0 +1,79 @@ +#ifndef __qwaq_editbuffer_h +#define __qwaq_editbuffer_h + +#ifdef __QFCC__ +#include + +//FIXME add unsigned to qfcc +#define unsigned int +#define umax 0x7fffffff +#endif//__QFCC__ + +typedef struct eb_sel_s { + unsigned start; + unsigned length; +} eb_sel_t; + +typedef struct eb_color_s { + int normal; + int selected; +} eb_color_t; + +#ifdef __QFCC__ +@interface EditBuffer : Object +{ + struct edit_buffer_s *buffer; +} +-init; +-initWithFile: (string) filename; +- (unsigned) nextChar: (unsigned) charPtr; +- (unsigned) prevChar: (unsigned) charPtr; +- (unsigned) nextNonSpace: (unsigned) charPtr; +- (unsigned) prevNonSpace: (unsigned) charPtr; +- (unsigned) nextWord: (unsigned) wordPtr; +- (unsigned) prevWord: (unsigned) wordPtr; +- (unsigned) nextLine: (unsigned) linePtr; +- (unsigned) prevLine: (unsigned) linePtr; +- (unsigned) nextLine: (unsigned) linePtr : (unsigned) count; +- (unsigned) prevLine: (unsigned) linePtr : (unsigned) count; + +- (unsigned) charPos: (unsigned) linePtr at: (unsigned) target; +- (unsigned) charPtr: (unsigned) linePtr at: (unsigned) target; + +- (eb_sel_t) getWord: (unsigned) wordPtr; +- (eb_sel_t) getLine: (unsigned) linePtr; +- (unsigned) getBOL: (unsigned) linePtr; +- (unsigned) getEOL: (unsigned) linePtr; +- (unsigned) getBOT; +- (unsigned) getEOT; + +- (unsigned) countLines: (eb_sel_t) selection; +- (eb_sel_t) search: (eb_sel_t) selection + for: (string) str + direction: (int) dir; +- (eb_sel_t) isearch: (eb_sel_t) selection + for: (string) str + direction: (int) dir; +- (unsigned) formatLine: (unsigned) linePtr + from: (unsigned) xpos + into: (int *) buf + width: (unsigned) length + highlight: (eb_sel_t) selection + colors: (eb_color_t) colors; + +- (BOOL) modified; +- (unsigned) textSize; +- (int) saveFile: (string) fileName; +@end +#else//__QFCC__ + +#include "QF/pr_obj.h" + +typedef struct qwaq_editbuffer_s { + pr_id_t isa; + pointer_t buffer; +} qwaq_editbuffer_t; + +#endif//!__QFCC__ + +#endif//__qwaq_editbuffer_h diff --git a/ruamoko/qwaq/qwaq-editbuffer.r b/ruamoko/qwaq/qwaq-editbuffer.r new file mode 100644 index 000000000..ce12a6edf --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer.r @@ -0,0 +1,47 @@ +#include "qwaq-editbuffer.h" + +@implementation EditBuffer +- init = #0; +- initWithFile: (string) filename = #0; +- (void) dealloc = #0; +- (unsigned) nextChar: (unsigned) charPtr = #0; +- (unsigned) prevChar: (unsigned) charPtr = #0; +- (unsigned) nextNonSpace: (unsigned) charPtr = #0; +- (unsigned) prevNonSpace: (unsigned) charPtr = #0; +- (unsigned) nextWord: (unsigned) wordPtr = #0; +- (unsigned) prevWord: (unsigned) wordPtr = #0; +- (unsigned) nextLine: (unsigned) linePtr = #0; +- (unsigned) prevLine: (unsigned) linePtr = #0; +- (unsigned) nextLine: (unsigned) linePtr : (unsigned) count = #0; +- (unsigned) prevLine: (unsigned) linePtr : (unsigned) count = #0; + +- (unsigned) charPos: (unsigned) linePtr + at: (unsigned) target = #0; +- (unsigned) charPtr: (unsigned) linePtr + at: (unsigned) target = #0; + +- (eb_sel_t) getWord: (unsigned) wordPtr = #0; +- (eb_sel_t) getLine: (unsigned) linePtr = #0; +- (unsigned) getBOL: (unsigned) linePtr = #0; +- (unsigned) getEOL: (unsigned) linePtr = #0; +- (unsigned) getBOT = #0; +- (unsigned) getEOT = #0; + +- (unsigned) countLines: (eb_sel_t) selection = #0; +- (eb_sel_t) search: (eb_sel_t) selection + for: (string) str + direction: (int) dir = #0; +- (eb_sel_t) isearch: (eb_sel_t) selection + for: (string) str + direction: (int) dir = #0; +- (unsigned) formatLine: (unsigned) linePtr + from: (unsigned) xpos + into: (int *) buf + width: (unsigned) length + highlight: (eb_sel_t) selection + colors: (eb_color_t) colors = #0; + +- (BOOL) modified = #0; +- (unsigned) textSize = #0; +- (int) saveFile: (string) fileName = #0; +@end diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 3172cd7f7..da9ec6e98 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -3,6 +3,7 @@ #include "QF/darray.h" #include "QF/progs.h" +#include "QF/sys.h" typedef struct qwaq_thread_s { pthread_t thread_id; @@ -15,6 +16,7 @@ typedef struct qwaq_thread_s { } qwaq_thread_t; void BI_Init (progs_t *pr); +void QWAQ_EditBuffer_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *);