diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/draw/curses.c | 2 | ||||
| -rw-r--r-- | lib/internal.h | 12 | ||||
| -rw-r--r-- | lib/menu.c | 40 | ||||
| -rw-r--r-- | lib/util.c | 41 | 
4 files changed, 56 insertions, 39 deletions
| diff --git a/lib/draw/curses.c b/lib/draw/curses.c index 946275e..3d7871e 100644 --- a/lib/draw/curses.c +++ b/lib/draw/curses.c @@ -182,7 +182,7 @@ static void _bmDrawCursesRender(const bmMenu *menu)      curses.erase();      int titleLen = (menu->title ? strlen(menu->title) + 1 : 0); -    _bmDrawCursesDrawLine(0, 0, "%*s%s", titleLen, "", menu->filter); +    _bmDrawCursesDrawLine(0, 0, "%*s%s", titleLen, "", (menu->filter ? menu->filter : ""));      if (menu->title) {          curses.attron(COLOR_PAIR(1)); diff --git a/lib/internal.h b/lib/internal.h index 6d116a0..4f6afbe 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -103,9 +103,8 @@ struct _bmMenu {      /**       * Text used to filter matches. -     * XXX: Change this to a pointer?       */ -    char filter[1024]; +    char *filter;      /**       * Used as optimization. @@ -113,6 +112,11 @@ struct _bmMenu {      char *oldFilter;      /** +     * Size of filter buffer +     */ +    size_t filterSize; + +    /**       * Current byte offset on filter text.       */      unsigned int cursor; @@ -173,7 +177,7 @@ size_t _bmUtf8RuneNext(const char *string, size_t start);  size_t _bmUtf8RunePrev(const char *string, size_t start);  size_t _bmUtf8RuneWidth(const char *rune, unsigned int u8len);  size_t _bmUtf8RuneRemove(char *string, size_t start, size_t *outRuneWidth); -size_t _bmUtf8RuneInsert(char *string, size_t bufSize, size_t start, const char *rune, unsigned int u8len, size_t *outRuneWidth); -size_t _bmUnicodeInsert(char *string, size_t bufSize, size_t start, unsigned int unicode, size_t *outRuneWidth); +size_t _bmUtf8RuneInsert(char **string, size_t *bufSize, size_t start, const char *rune, unsigned int u8len, size_t *outRuneWidth); +size_t _bmUnicodeInsert(char **string, size_t *bufSize, size_t start, unsigned int unicode, size_t *outRuneWidth);  /* vim: set ts=8 sw=4 tw=0 :*/ @@ -71,6 +71,9 @@ void bmMenuFree(bmMenu *menu)      if (menu->title)          free(menu->title); +    if (menu->filter) +        free(menu->filter); +      if (menu->oldFilter)          free(menu->oldFilter); @@ -126,12 +129,11 @@ void bmMenuSetFilter(bmMenu *menu, const char *filter)  {      assert(menu); -    if (!filter) { -        memset(menu->filter, 0, sizeof(menu->filter)); -        return; -    } +    if (menu->filter) +        free(menu->filter); -    strncpy(menu->filter, filter, sizeof(menu->filter)); +    menu->filter = (filter ? _bmStrdup(filter) : NULL); +    menu->filterSize = (filter ? strlen(filter) : 0);  }  /** @@ -426,7 +428,7 @@ bmItem** bmMenuGetFilteredItems(const bmMenu *menu, unsigned int *outNmemb)  {      assert(menu); -    if (strlen(menu->filter)) +    if (menu->filter && strlen(menu->filter))          return _bmItemListGetItems(&menu->filtered, outNmemb);      return _bmItemListGetItems(&menu->items, outNmemb); @@ -459,7 +461,7 @@ void bmMenuFilter(bmMenu *menu)      assert(menu);      char addition = 0; -    size_t len = strlen(menu->filter); +    size_t len = (menu->filter ? strlen(menu->filter) : 0);      if (!len || !menu->items.list || menu->items.count <= 0) {          _bmItemListFreeList(&menu->filtered); @@ -561,7 +563,7 @@ bmRunResult bmMenuRunWithKey(bmMenu *menu, bmKey key, unsigned int unicode)              break;          case BM_KEY_END: -            menu->cursor = strlen(menu->filter); +            menu->cursor = (menu->filter ? strlen(menu->filter) : 0);              menu->cursesCursor = _bmUtf8StringScreenWidth(menu->filter);              break; @@ -619,17 +621,17 @@ bmRunResult bmMenuRunWithKey(bmMenu *menu, bmKey key, unsigned int unicode)          case BM_KEY_WORD_DELETE:              { -                while (menu->cursor < strlen(menu->filter) && !isspace(menu->filter[menu->cursor])) { +                while (menu->cursor < (menu->filter ? strlen(menu->filter) : 0) && !isspace(menu->filter[menu->cursor])) {                      unsigned int oldCursor = menu->cursor;                      menu->cursor += _bmUtf8RuneNext(menu->filter, menu->cursor);                      menu->cursesCursor += _bmUtf8RuneWidth(menu->filter + oldCursor, menu->cursor - oldCursor);                  } -                while (menu->cursor > 0 && isspace(menu->filter[menu->cursor - 1])) { +                while (menu->cursor > 0 && menu->filter && isspace(menu->filter[menu->cursor - 1])) {                      unsigned int oldCursor = menu->cursor;                      menu->cursor -= _bmUtf8RunePrev(menu->filter, menu->cursor);                      menu->cursesCursor -= _bmUtf8RuneWidth(menu->filter + menu->cursor, oldCursor - menu->cursor);                  } -                while (menu->cursor > 0 && !isspace(menu->filter[menu->cursor - 1])) { +                while (menu->cursor > 0 && menu->filter && !isspace(menu->filter[menu->cursor - 1])) {                      size_t width;                      menu->cursor -= _bmUtf8RuneRemove(menu->filter, menu->cursor, &width);                      menu->cursesCursor -= width; @@ -640,24 +642,18 @@ bmRunResult bmMenuRunWithKey(bmMenu *menu, bmKey key, unsigned int unicode)          case BM_KEY_UNICODE:              {                  size_t width; -                menu->cursor += _bmUnicodeInsert(menu->filter, sizeof(menu->filter) - 1, menu->cursor, unicode, &width); +                menu->cursor += _bmUnicodeInsert(&menu->filter, &menu->filterSize, menu->cursor, unicode, &width);                  menu->cursesCursor += width;              }              break;          case BM_KEY_TAB:              { +                const char *text;                  bmItem *highlighted = bmMenuGetHighlightedItem(menu); -                if (highlighted && bmItemGetText(highlighted)) { -                    const char *text = bmItemGetText(highlighted); -                    size_t len = strlen(text); - -                    if (len > sizeof(menu->filter) - 1) -                        len = sizeof(menu->filter) - 1; - -                    memset(menu->filter, 0, strlen(menu->filter)); -                    memcpy(menu->filter, text, len); -                    menu->cursor = strlen(menu->filter); +                if (highlighted && (text = bmItemGetText(highlighted))) { +                    bmMenuSetFilter(menu, text); +                    menu->cursor = (menu->filter ? strlen(menu->filter) : 0);                      menu->cursesCursor = _bmUtf8StringScreenWidth(menu->filter);                  }              } @@ -228,29 +228,45 @@ size_t _bmUtf8RuneRemove(char *string, size_t start, size_t *outRuneWidth)  /**   * Insert UTF8 rune to buffer.   * - * @param string Null terminated C "string". - * @param bufSize Size of the buffer. + * @param inOutString Reference to buffer. + * @param inOutBufSize Reference to size of the buffer.   * @param start Start offset where to insert to. (cursor)   * @param rune Buffer to insert to string.   * @param u8len Byte length of the rune.   * @param outRuneWidth Reference to size_t, return number of columns for inserted rune, or -1 on failure.   * @return Number of bytes inserted to buffer.   */ -size_t _bmUtf8RuneInsert(char *string, size_t bufSize, size_t start, const char *rune, unsigned int u8len, size_t *outRuneWidth) +size_t _bmUtf8RuneInsert(char **inOutString, size_t *inOutBufSize, size_t start, const char *rune, unsigned int u8len, size_t *outRuneWidth)  { -    assert(string); +    assert(inOutString); +    assert(inOutBufSize);      if (outRuneWidth)          *outRuneWidth = 0; -    size_t len = strlen(string); -    if (len + u8len >= bufSize) +    size_t len = (*inOutString ? strlen(*inOutString) : 0); +    if (!*inOutString && !(*inOutString = calloc(1, (*inOutBufSize = u8len + 1))))          return 0; +    if (len + u8len >= *inOutBufSize) { +        void *tmp; +        if (!(tmp = realloc(*inOutString, (*inOutBufSize * 2)))) { +            if (!(tmp = malloc((*inOutBufSize * 2)))) +                return 0; + +            memcpy(tmp, *inOutString, *inOutBufSize); +            free(*inOutString); +        } + +        memset(tmp + *inOutBufSize, 0, *inOutBufSize); +        *inOutString = tmp; +        *inOutBufSize *= 2; +    } +      if (u8len == 1 && !isprint(*rune))          return 0; -    char *str = string + start; +    char *str = *inOutString + start;      memmove(str + u8len, str, len - start);      memcpy(str, rune, u8len); @@ -262,16 +278,17 @@ size_t _bmUtf8RuneInsert(char *string, size_t bufSize, size_t start, const char  /**   * Insert unicode character to UTF8 buffer.   * - * @param string Null terminated C "string". - * @param bufSize Size of the buffer. + * @param inOutString Reference to buffer. + * @param inOutBufSize Reference to size of the buffer.   * @param start Start offset where to insert to. (cursor)   * @param unicode Unicode character to insert.   * @param outRuneWidth Reference to size_t, return number of columns for inserted rune, or -1 on failure.   * @return Number of bytes inserted to buffer.   */ -size_t _bmUnicodeInsert(char *string, size_t bufSize, size_t start, unsigned int unicode, size_t *outRuneWidth) +size_t _bmUnicodeInsert(char **inOutString, size_t *inOutBufSize, size_t start, unsigned int unicode, size_t *outRuneWidth)  { -    assert(string); +    assert(inOutString); +    assert(inOutBufSize);      char u8len = ((unicode < 0x80) ? 1 : ((unicode < 0x800) ? 2 : ((unicode < 0x10000) ? 3 : 4)));      char mb[5] = { 0, 0, 0, 0 }; @@ -285,7 +302,7 @@ size_t _bmUnicodeInsert(char *string, size_t bufSize, size_t start, unsigned int          mb[0] |= (unicode >> (i * 6 - 6));      } -    return _bmUtf8RuneInsert(string, bufSize, start, mb, u8len, outRuneWidth); +    return _bmUtf8RuneInsert(inOutString, inOutBufSize, start, mb, u8len, outRuneWidth);  }  /* vim: set ts=8 sw=4 tw=0 :*/ | 
