diff --git a/Display.c b/Display.c index 44f87c5..66baf9f 100644 --- a/Display.c +++ b/Display.c @@ -4,7 +4,7 @@ #include -#if HAVE_CURSES_H +#if HAVE_CURSES static SCREEN* CRT_term; @@ -26,13 +26,22 @@ static Hashtable* Display_terminalSequences; #endif /*{ - -#ifdef HAVE_LIBNCURSES -#define HAVE_CURSES_H 1 -#endif - -#if HAVE_CURSES_H +#include "config.h" + +#ifdef HAVE_NCURSESW_CURSES_H + #include + #define HAVE_CURSES 1 + #undef mvaddchnstr + #define mvaddchnstr mvadd_wchnstr +#elif HAVE_NCURSES_NCURSES_H + #include + #define HAVE_CURSES 1 +#elif HAVE_NCURSES_H + #include + #define HAVE_CURSES 1 +#elif HAVE_CURSES #include + #define HAVE_CURSES 1 #else typedef unsigned long chtype; @@ -191,7 +200,7 @@ typedef struct mevent { }*/ void Display_getScreenSize(int* w, int* h) { -#if HAVE_CURSES_H +#if HAVE_CURSES *w = COLS; *h = LINES; #else @@ -207,7 +216,7 @@ void Display_getScreenSize(int* w, int* h) { #endif } -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_printAt mvprintw #else void Display_printAt(int y, int x, const char* fmt, ...) { @@ -219,7 +228,7 @@ void Display_printAt(int y, int x, const char* fmt, ...) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_writeAt mvaddstr #define Display_writeAtn mvaddnstr #define Display_writeChAt mvaddch @@ -238,7 +247,7 @@ void Display_writeChAt(int y, int x, const char ch) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_move move #else void Display_move(int y, int x) { @@ -248,7 +257,7 @@ void Display_move(int y, int x) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_mvhline mvhline #else void Display_mvhline(int y, int x, char c, int qty) { @@ -258,7 +267,7 @@ void Display_mvhline(int y, int x, char c, int qty) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_mvvline mvvline #else void Display_mvvline(int y, int x, char c, int qty) { @@ -268,7 +277,7 @@ void Display_mvvline(int y, int x, char c, int qty) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_attrset attrset #else @@ -314,7 +323,7 @@ void Display_attrset(unsigned long attr) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_clear clear #else void Display_clear() { @@ -322,10 +331,10 @@ void Display_clear() { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_writeChstrAtn mvaddchnstr #else -void Display_writeChstrAtn(int y, int x, const chtype *chstr, int n) { +void Display_writeChstrAtn(int y, int x, CharType* chstr, int n) { printf("\033[%d;%df", y+1, x+1, y, x, n); /* char str[n]; @@ -360,7 +369,7 @@ void Display_writeChstrAtn(int y, int x, const chtype *chstr, int n) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_clearToEol clrtoeol #else void Display_clearToEol() { @@ -368,7 +377,7 @@ void Display_clearToEol() { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES void Display_getyx(int* y, int* x) { getyx(stdscr, *y, *x); } @@ -379,7 +388,7 @@ void Display_getyx(int* y, int* x) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_getch getch #else int Display_getch() { @@ -404,7 +413,7 @@ int Display_getch() { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_defineKey define_key #else void Display_defineKey(const char* sequence, int keynum) { @@ -412,7 +421,7 @@ void Display_defineKey(const char* sequence, int keynum) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_bkgdset bkgdset #else void Display_bkgdset(int color) { @@ -420,7 +429,7 @@ void Display_bkgdset(int color) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_beep beep #else void Display_beep() { @@ -428,7 +437,7 @@ void Display_beep() { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_getmouse getmouse #else int Display_getmouse(MEVENT* mevent) { @@ -437,7 +446,7 @@ int Display_getmouse(MEVENT* mevent) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES #define Display_refresh refresh #else void Display_refresh() { @@ -445,7 +454,7 @@ void Display_refresh() { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES bool Display_init(char* term) { CRT_term = newterm(term, stdout, stdin); raw(); @@ -491,7 +500,7 @@ bool Display_init(char* term) { } #endif -#if HAVE_CURSES_H +#if HAVE_CURSES void Display_done() { curs_set(1); endwin(); diff --git a/Hashtable.c b/Hashtable.c index 6f74b82..eebb453 100644 --- a/Hashtable.c +++ b/Hashtable.c @@ -1,4 +1,5 @@ +#define _GNU_SOURCE #include #include diff --git a/Line.c b/Line.c index e8f0465..26c036c 100644 --- a/Line.c +++ b/Line.c @@ -1,4 +1,5 @@ +#define _GNU_SOURCE #include #include #include @@ -148,8 +149,8 @@ void Line_display(Object* cast, RichString* str) { } if (str && outIndex >= scrollH) { - RichString_append(str, out + scrollH, outIndex - scrollH); - RichString_setAttrs(str, attrs + scrollH); + RichString_appendn(str, 0, out + scrollH, outIndex - scrollH); + RichString_paintAttrs(str, attrs + scrollH); } this->context = Highlight_getContext(hl); } diff --git a/Object.c b/Object.c index 94e65fd..20c8339 100644 --- a/Object.c +++ b/Object.c @@ -51,7 +51,7 @@ void Object_delete(Object* this) { void Object_display(Object* this, RichString* out) { unsigned char objAddress[50]; sprintf((char*)objAddress, "O:%p C:%p", (void*) this, (void*) this->class); - RichString_write(out, objAddress); + RichString_write(out, 0, objAddress); } bool Object_equals(const Object* this, const Object* o) { diff --git a/Panel.c b/Panel.c index 874a11f..2597b65 100644 --- a/Panel.c +++ b/Panel.c @@ -58,6 +58,7 @@ Panel* Panel_new(int x, int y, int w, int h, int color, ListItemClass* class, bo void Panel_delete(Object* cast) { Panel* this = (Panel*)cast; + RichString_end(this->header); Panel_done(this); free(this); } @@ -79,7 +80,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, int color, ListItemClas this->cursorX = 0; this->displaying = 0; this->focus = true; - RichString_prune(&(this->header)); + RichString_beginAllocated(this->header); } void Panel_done(Panel* this) { @@ -108,7 +109,7 @@ void Panel_move(Panel* this, int x, int y) { void Panel_resize(Panel* this, int w, int h) { assert (this != NULL); - if (this->header.len > 0) + if (RichString_sizeVal(this->header) > 0) h--; this->w = w; this->h = h; @@ -228,13 +229,14 @@ void Panel_draw(Panel* this) { assert(first >= 0); assert(last <= itemCount); - if (this->header.len > 0) { + int headerLen = RichString_sizeVal(this->header); + if (headerLen > 0) { Display_attrset(CRT_colors[HeaderColor]); Display_mvhline(y, x, ' ', w); - if (scrollH < this->header.len) { - assert(this->header.len > 0); + if (scrollH < headerLen) { + assert(headerLen > 0); Display_writeChstrAtn(y, x, this->header.chstr + scrollH, - MIN(this->header.len - scrollH, w)); + MIN(headerLen - scrollH, w)); } y++; } @@ -254,10 +256,10 @@ void Panel_draw(Panel* this) { for(int i = first, j = 0; j < h && i < last; i++, j++) { Object* itemObj = (Object*) List_get(this->items, i); assert(itemObj); - RichString itemRef; RichString_init(&itemRef); + RichString_begin(itemRef); this->displaying = i; Msg(Object, display, itemObj, &itemRef); - int amt = MIN(itemRef.len - scrollH, w); + int amt = MIN(RichString_sizeVal(itemRef) - scrollH, w); if (i == this->selected) { if (this->highlightBar) { Display_attrset(highlight); @@ -275,6 +277,7 @@ void Panel_draw(Panel* this) { if (amt > 0) Display_writeChstrAtn(y+j, x+0, itemRef.chstr + scrollH, amt); } + RichString_end(itemRef); } for (int i = y + (last - first); i < y + h; i++) Display_mvhline(i, x+0, ' ', w); @@ -305,26 +308,30 @@ void Panel_draw(Panel* this) { } else { Object* oldObj = (Object*) List_get(this->items, this->oldSelected); - RichString oldRef; RichString_init(&oldRef); + RichString_begin(oldRef); this->displaying = this->oldSelected; Msg(Object, display, oldObj, &oldRef); Object* newObj = (Object*) List_get(this->items, this->selected); - RichString newRef; RichString_init(&newRef); + RichString_begin(newRef); this->displaying = this->selected; Msg(Object, display, newObj, &newRef); Display_mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', w); - if (scrollH < oldRef.len) - Display_writeChstrAtn(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + scrollH, MIN(oldRef.len - scrollH, w)); + int oldLen = RichString_sizeVal(oldRef); + if (scrollH < oldLen) + Display_writeChstrAtn(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + scrollH, MIN(oldLen - scrollH, w)); if (this->highlightBar) Display_attrset(highlight); cursorY = y+this->selected - this->scrollV; Display_mvhline(cursorY, x+0, ' ', w); if (this->highlightBar) RichString_setAttr(&newRef, highlight); - if (scrollH < newRef.len) - Display_writeChstrAtn(y+this->selected - this->scrollV, x+0, newRef.chstr + scrollH, MIN(newRef.len - scrollH, w)); + int newLen = RichString_sizeVal(newRef); + if (scrollH < newLen) + Display_writeChstrAtn(y+this->selected - this->scrollV, x+0, newRef.chstr + scrollH, MIN(newLen - scrollH, w)); if (this->highlightBar) Display_attrset(this->color); + RichString_end(oldRef); + RichString_end(newRef); } this->oldSelected = this->selected; diff --git a/RichString.c b/RichString.c index 87fe18b..4df1c99 100644 --- a/RichString.c +++ b/RichString.c @@ -1,65 +1,172 @@ +#define _GNU_SOURCE #include #include #include #include "Prototypes.h" +#include +#include + /*{ +#include "config.h" +#include + +#define RICHSTRING_MAXLEN 300 + +#include +#ifdef HAVE_NCURSESW_CURSES_H + #include +#elif HAVE_NCURSES_NCURSES_H + #include +#elif HAVE_NCURSES_H + #include +#elif HAVE_CURSES_H + #include +#endif + +#define RichString_size(this) ((this)->chlen) +#define RichString_sizeVal(this) ((this).chlen) + +#define RichString_begin(this) RichString (this); (this).chlen = 0; (this).chptr = (this).chstr; +#define RichString_beginAllocated(this) (this).chlen = 0; (this).chptr = (this).chstr; +#define RichString_end(this) RichString_prune(&(this)); -#define RICHSTRING_SIZE 300 +#ifdef HAVE_LIBNCURSESW +#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr) +#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n) +#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255) +#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0) +#define CharType cchar_t +#define CharType_setAttr(ch, attrs) (ch)->attr = (attrs) +#else +#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr) +#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n) +#define RichString_getCharVal(this, i) ((this).chptr[i]) +#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0) +#define CharType chtype +#define CharType_setAttr(ch, attrs) *(ch) = (*(ch) & 0xff) | (attrs) +#endif struct RichString_ { - int len; - chtype chstr[RICHSTRING_SIZE+2]; + int chlen; + CharType chstr[RICHSTRING_MAXLEN+1]; + CharType* chptr; }; }*/ -void RichString_init(RichString* this) { - this->len = 0; +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#define charBytes(n) (sizeof(CharType) * (n)) + +static inline void RichString_setLen(RichString* this, int len) { + if (this->chlen <= RICHSTRING_MAXLEN) { + if (len > RICHSTRING_MAXLEN) { + this->chptr = malloc(charBytes(len+1)); + memcpy(this->chptr, this->chstr, charBytes(this->chlen+1)); + } + } else { + if (len <= RICHSTRING_MAXLEN) { + memcpy(this->chstr, this->chptr, charBytes(this->chlen)); + free(this->chptr); + this->chptr = this->chstr; + } else { + this->chptr = realloc(this->chptr, charBytes(len+1)); + } + } + RichString_setChar(this, len, 0); + this->chlen = len; } -void RichString_prune(RichString* this) { - this->len = 0; +#ifdef HAVE_LIBNCURSESW + +static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) { + wchar_t data[len+1]; + len = mbstowcs(data, data_c, len); + if (len<0) + return; + int newLen = from + len; + RichString_setLen(this, newLen); + memset(&this->chptr[from], 0, sizeof(CharType) * (newLen - from)); + for (int i = from, j = 0; i < newLen; i++, j++) { + this->chptr[i].chars[0] = data[j]; + this->chptr[i].attr = attrs; + } + this->chptr[newLen].chars[0] = 0; } -inline void RichString_append(RichString* this, unsigned char* data, int len) { - int maxToWrite = RICHSTRING_SIZE - this->len; - int wrote = MIN(maxToWrite, len); - for (int i = 0; i < wrote; i++) - this->chstr[this->len + i] = data[i]; - this->len += wrote; - this->chstr[this->len] = 0; +int RichString_findChar(RichString* this, char c, int start) { + wchar_t wc = btowc(c); + cchar_t* ch = this->chptr + start; + for (int i = start; i < this->chlen; i++) { + if (ch->chars[0] == wc) + return i; + ch++; + } + return -1; } -void RichString_write(RichString* this, unsigned char* data) { - this->len = 0; - RichString_append(this, data, strlen((char*)data)); +#else + +static inline void RichString_writeFrom(RichString* this, int attrs, const char* data_c, int from, int len) { + int newLen = from + len; + RichString_setLen(this, newLen); + for (int i = from, j = 0; i < newLen; i++, j++) + this->chptr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs; + this->chptr[newLen] = 0; } -inline void RichString_appendChar(RichString* this, int attrs, char data) { - this->chstr[this->len++] = data | attrs; - this->chstr[this->len] = 0; +int RichString_findChar(RichString* this, char c, int start) { + chtype* ch = this->chptr + start; + for (int i = start; i < this->chlen; i++) { + if ((*ch & 0xff) == (chtype) c) + return i; + ch++; + } + return -1; } -void RichString_setAttr(RichString *this, int attrs) { - for (int i = 0; i < this->len; i++) { - unsigned char c = this->chstr[i] & 0xff; - this->chstr[i] = c | attrs; +#endif + +void RichString_setAttrn(RichString* this, int attrs, int start, int finish) { + CharType* ch = this->chptr + start; + for (int i = start; i <= finish; i++) { + CharType_setAttr(ch, attrs); + ch++; } } -void RichString_setAttrs(RichString *this, int* attrs) { - for (int i = 0; i < this->len; i++) { - unsigned char c = this->chstr[i]; - this->chstr[i] = c | attrs[i]; +void RichString_paintAttrs(RichString* this, int* attrs) { + CharType* ch = this->chptr; + for (int i = 0; i <= this->chlen; i++) { + CharType_setAttr(ch, attrs[i]); + ch++; } } -RichString RichString_quickString(int attrs, unsigned char* data) { - RichString str; RichString_init(&str); - RichString_write(&str, data); - return str; +void RichString_prune(RichString* this) { + if (this->chlen > RICHSTRING_MAXLEN) + free(this->chptr); + this->chptr = this->chstr; + this->chlen = 0; +} + +void RichString_setAttr(RichString* this, int attrs) { + RichString_setAttrn(this, attrs, 0, this->chlen - 1); +} + +void RichString_append(RichString* this, int attrs, const char* data) { + RichString_writeFrom(this, attrs, data, this->chlen, strlen(data)); } +void RichString_appendn(RichString* this, int attrs, const char* data, int len) { + RichString_writeFrom(this, attrs, data, this->chlen, len); +} + +void RichString_write(RichString* this, int attrs, const char* data) { + RichString_writeFrom(this, attrs, data, 0, strlen(data)); +} diff --git a/StringBuffer.c b/StringBuffer.c index 3ed8afe..0f99999 100644 --- a/StringBuffer.c +++ b/StringBuffer.c @@ -1,4 +1,5 @@ +#define _GNU_SOURCE #include #include #include diff --git a/config.h.in b/config.h.in index a7a4d39..094f1fa 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,9 @@ /* Define to 1 if the `closedir' function returns void instead of `int'. */ #undef CLOSEDIR_VOID +/* Define to 1 if you have the header file. */ +#undef HAVE_CURSES_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H @@ -19,6 +22,9 @@ /* Define to 1 if you have the `ncurses' library (-lncurses). */ #undef HAVE_LIBNCURSES +/* Define to 1 if you have the `ncursesw' library (-lncursesw). */ +#undef HAVE_LIBNCURSESW + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H @@ -47,6 +53,15 @@ /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR +/* Define to 1 if you have the header file. */ +#undef HAVE_NCURSESW_CURSES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NCURSES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NCURSES_NCURSES_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H @@ -120,6 +135,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Set if Unicode was enabled. */ +#undef HAVE_UNICODE + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H diff --git a/configure.ac b/configure.ac index 9a7aae3..e6e7af0 100644 --- a/configure.ac +++ b/configure.ac @@ -15,21 +15,37 @@ AM_PROG_CC_C_O AC_CHECK_LIB([m], [ceil], [], [missing_libraries="$missing_libraries libm"]) AC_ARG_ENABLE(ncurses, [AC_HELP_STRING([--enable-ncurses], [use ncurses (switch to low-level hacks if disabled)])],, enable_ncurses="yes") -extra_headers= -if test "x$enable_ncurses" = xyes -then - AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"]) - extra_headers=curses.h + +# Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC + +AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes") +if test "x$enable_unicode" = xyes; then + AC_DEFINE([HAVE_UNICODE], [1], [Set if Unicode was enabled.]) + if test "x$enable_ncurses" = xyes + then + AC_CHECK_LIB([ncursesw], [refresh], [], [ + missing_libraries="$missing_libraries libncursesw" + AC_MSG_ERROR([You may want to use --disable-unicode or install libncursesw.]) + ]) + AC_CHECK_HEADERS([ncursesw/curses.h],[:], + [AC_CHECK_HEADERS([ncurses/ncurses.h],[:], + [AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])]) + fi +else + if test "x$enable_ncurses" = xyes + then + AC_CHECK_LIB([ncurses], [refresh], [], [missing_libraries="$missing_libraries libncurses"]) + AC_CHECK_HEADERS([curses.h],[:],[missing_headers="$missing_headers $ac_header"]) + fi fi if test ! -z "$missing_libraries"; then AC_MSG_ERROR([missing libraries: $missing_libraries]) fi -# Checks for header files. -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_CHECK_HEADERS([limits.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/time.h unistd.h $extra_headers],[:],[ +AC_CHECK_HEADERS([limits.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/time.h unistd.h],[:],[ missing_headers="$missing_headers $ac_header" ]) diff --git a/tools/GenHeaders b/tools/GenHeaders index 66c571f..379b8bc 100755 --- a/tools/GenHeaders +++ b/tools/GenHeaders @@ -69,7 +69,7 @@ then do_all includes | sort -u | tac >> "$new" do_all proto - echo "#if HAVE_CURSES_H" >> "$new" + echo "#if HAVE_CURSES" >> "$new" do_all defines >> "$new" echo "#endif" >> "$new"