commit 53cb5a2a0d1540a37e6e5d1c1673e8354d5208a5
parent 3dad446ab7a6e207229b56af552dd3304a9ab11b
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 26 Feb 2022 00:41:29 +0100
Migrate away from wchar_t, default to utf8
Diffstat:
21 files changed, 626 insertions(+), 379 deletions(-)
diff --git a/src/cmd.c b/src/cmd.c
@@ -10,6 +10,7 @@
#include "util.h"
#include <stdbool.h>
+#include <string.h>
#define CMD_ERROR(...) do { \
CMD_SET_STATUS(__VA_ARGS__); \
@@ -17,31 +18,35 @@
} while (0)
static const struct cmd *last_cmd;
-static wchar_t *last_args;
+static char *last_args;
-static bool cmd_save(const wchar_t *args);
-static bool cmd_move(const wchar_t *args);
-static bool cmd_add(const wchar_t *args);
-static bool cmd_reindex(const wchar_t *args);
+static bool cmd_save(const char *args);
+static bool cmd_move(const char *args);
+static bool cmd_copy(const char *args);
+static bool cmd_reindex(const char *args);
+static bool cmd_add_tag(const char *args);
+static bool cmd_rm_tag(const char *args);
const struct cmd commands[] = {
- { L"save", cmd_save },
- { L"move", cmd_move },
- { L"add", cmd_add },
- { L"reindex", cmd_reindex },
+ { "save", cmd_save },
+ { "move", cmd_move },
+ { "copy", cmd_copy },
+ { "reindex", cmd_reindex },
+ { "addtag", cmd_add_tag },
+ { "rmtag", cmd_rm_tag },
};
const size_t command_count = ARRLEN(commands);
bool
-cmd_save(const wchar_t *args)
+cmd_save(const char *args)
{
data_save();
return 0;
}
bool
-cmd_move(const wchar_t *name)
+cmd_move(const char *name)
{
struct link *link;
struct track *track;
@@ -55,10 +60,11 @@ cmd_move(const wchar_t *name)
if (!link) CMD_ERROR("No track selected");
track = UPCAST(link, struct ref)->data;
- newpath = aprintf("%s/%s", tag->fpath, track->fname);
+ newpath = aprintf("%s/%s", tag->fpath, track->name);
OOM_CHECK(newpath);
- move_file(track->fpath, newpath);
+ if (!move_file(track->fpath, newpath))
+ CMD_ERROR("Failed to move file");
free(track->fpath);
track->fpath = newpath;
@@ -69,7 +75,7 @@ cmd_move(const wchar_t *name)
}
bool
-cmd_add(const wchar_t *name)
+cmd_copy(const char *name)
{
struct link *link;
struct track *track;
@@ -84,21 +90,21 @@ cmd_add(const wchar_t *name)
if (!link) return 0;
track = UPCAST(link, struct ref)->data;
- newpath = aprintf("%s/%s", tag->fpath, track->fname);
+ newpath = aprintf("%s/%s", tag->fpath, track->name);
OOM_CHECK(newpath);
copy_file(track->fpath, newpath);
track->fpath = newpath;
- track = track_alloc(tag->fpath, track->fname, get_fid(tag->fpath));
- ref = ref_init(track);
+ track = track_alloc(tag->fpath, track->name, get_fid(tag->fpath));
+ ref = ref_alloc(track);
list_push_back(&tag->tracks, &ref->link);
return 1;
}
bool
-cmd_reindex(const wchar_t *name)
+cmd_reindex(const char *name)
{
struct link *link;
struct tag *tag;
@@ -108,19 +114,19 @@ cmd_reindex(const wchar_t *name)
if (!*name) {
link = list_at(&tags, tag_nav.sel);
+ if (!link) return false;
tag = UPCAST(link, struct tag);
- if (tag == NULL) return false;
- list_push_back(&matches, LINK(ref_init(tag)));
- } else if (!wcscmp(name, L"*")) {
+ list_push_back(&matches, LINK(ref_alloc(tag)));
+ } else if (!strcmp(name, "*")) {
for (LIST_ITER(&tags, link)) {
tag = UPCAST(link, struct tag);
- list_push_back(&matches, LINK(ref_init(tag)));
+ list_push_back(&matches, LINK(ref_alloc(tag)));
}
} else {
for (LIST_ITER(&tags, link)) {
tag = UPCAST(link, struct tag);
- if (!wcscmp(tag->name, name)) {
- list_push_back(&matches, LINK(ref_init(tag)));
+ if (!strcmp(tag->name, name)) {
+ list_push_back(&matches, LINK(ref_alloc(tag)));
break;
}
}
@@ -130,7 +136,8 @@ cmd_reindex(const wchar_t *name)
for (LIST_ITER(&matches, link)) {
tag = UPCAST(link, struct ref)->data;
- index_update(tag);
+ if (!tracks_update(tag))
+ return false;
}
refs_free(&matches);
@@ -138,6 +145,76 @@ cmd_reindex(const wchar_t *name)
return true;
}
+bool
+cmd_add_tag(const char *name)
+{
+ struct link *link;
+ struct tag *tag;
+ char *fname, *fpath;
+
+ for (LIST_ITER(&tags, link)) {
+ tag = UPCAST(link, struct tag);
+ if (!strcmp(tag->name, name))
+ CMD_ERROR("Tag already exists");
+ }
+
+ fname = aprintf("%s", name);
+ OOM_CHECK(fname);
+
+ fpath = aprintf("%s/%s", datadir, fname);
+ OOM_CHECK(fpath);
+
+ if (!make_dir(fpath)) {
+ CMD_SET_STATUS("Failed to create dir");
+ free(fname);
+ free(fpath);
+ return false;
+ }
+
+ tag = tag_alloc(datadir, fname);
+ OOM_CHECK(tag);
+
+ list_push_back(&tags, LINK(tag));
+
+ free(fname);
+ free(fpath);
+
+ return true;
+}
+
+bool
+cmd_rm_tag(const char *name)
+{
+ struct link *link;
+ struct tag *tag;
+ char *fname, *fpath;
+
+ if (!*name) {
+ link = list_at(&tags, tag_nav.sel);
+ if (!link) return false;
+ tag = UPCAST(link, struct tag);
+ } else {
+ for (LIST_ITER(&tags, link)) {
+ tag = UPCAST(link, struct tag);
+ if (!strcmp(tag->name, name))
+ break;
+ }
+
+ if (!LIST_INNER(link))
+ CMD_ERROR("No such tag");
+ }
+
+ if (!rm_dir(tag->fpath, true)) {
+ tracks_update(tag); /* in case some deleted, some not */
+ CMD_ERROR("Failed to remove dir");
+ }
+
+ link_pop(LINK(tag));
+ tag_free(tag);
+
+ return true;
+}
+
void
cmd_init(void)
{
@@ -152,19 +229,25 @@ cmd_deinit(void)
}
bool
-cmd_run(const wchar_t *query)
+cmd_run(const char *query, bool *found)
{
- const wchar_t *sep, *args;
+ const char *sep, *args;
int i, cmdlen;
bool success;
- sep = wcschr(query, L' ');
- cmdlen = sep ? sep - query : wcslen(query);
+ *found = false;
+ sep = strchr(query, ' ');
+ cmdlen = sep ? sep - query : strlen(query);
for (i = 0; i < command_count; i++) {
- if (!wcsncmp(commands[i].name, query, cmdlen)) {
+ if (!strncmp(commands[i].name, query, cmdlen)) {
last_cmd = &commands[i];
- args = sep ? sep + 1 : L"";
- last_args = wcsdup(args);
+ args = sep ? sep + 1 : "";
+
+ free(last_args);
+ last_args = strdup(args);
+ OOM_CHECK(last_args);
+
+ *found = true;
return commands[i].func(args);
}
}
@@ -181,12 +264,12 @@ cmd_rerun(void)
}
const struct cmd *
-cmd_get(const wchar_t *name)
+cmd_get(const char *name)
{
int i;
for (i = 0; i < command_count; i++) {
- if (!wcscmp(commands[i].name, name))
+ if (!strcmp(commands[i].name, name))
return &commands[i];
}
@@ -194,12 +277,12 @@ cmd_get(const wchar_t *name)
}
const struct cmd *
-cmd_find(const wchar_t *name)
+cmd_find(const char *name)
{
int i;
for (i = 0; i < command_count; i++) {
- if (wcsstr(commands[i].name, name))
+ if (strcmp(commands[i].name, name))
return &commands[i];
}
diff --git a/src/cmd.h b/src/cmd.h
@@ -1,7 +1,6 @@
#pragma once
-#include <wchar.h>
-
+#include <stdlib.h>
#include <stdbool.h>
#define CMD_SET_STATUS(...) do { \
@@ -9,21 +8,21 @@
cmd_status = aprintf(__VA_ARGS__); \
} while (0)
-typedef bool (*cmd_func)(const wchar_t *args);
+typedef bool (*cmd_func)(const char *args);
struct cmd {
- const wchar_t *name;
+ const char *name;
cmd_func func;
};
void cmd_init(void);
void cmd_deinit(void);
-bool cmd_run(const wchar_t *name);
+bool cmd_run(const char *name, bool *found);
bool cmd_rerun(void);
-const struct cmd *cmd_get(const wchar_t *name);
-const struct cmd *cmd_find(const wchar_t *name);
+const struct cmd *cmd_get(const char *name);
+const struct cmd *cmd_find(const char *name);
extern const struct cmd commands[];
extern const size_t command_count;
diff --git a/src/data.c b/src/data.c
@@ -1,11 +1,13 @@
#include "data.h"
+#include "player.h"
#include "list.h"
#include "log.h"
#include "ref.h"
#include "track.h"
#include "tag.h"
+#include <fts.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -48,7 +50,8 @@ data_load(void)
OOM_CHECK(path);
if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
- tag = tag_init(datadir, ent->d_name);
+ tag = tag_alloc(datadir, ent->d_name);
+ OOM_CHECK(tag);
tracks_load(tag);
list_push_back(&tags, LINK(tag));
}
@@ -57,8 +60,7 @@ data_load(void)
}
closedir(dir);
- /* TODO: ensure this is ok and remove */
- ASSERT(!list_empty(&tags));
+ list_sort(&tracks, track_fid_compare);
}
void
@@ -105,13 +107,21 @@ get_fid(const char *path)
return stat(path, &st) ? -1 : st.st_ino;
}
+int
+track_fid_compare(struct link *a, struct link *b)
+{
+ struct track *ta, *tb;
+
+ ta = UPCAST(a, struct ref)->data;
+ tb = UPCAST(b, struct ref)->data;
+
+ return ta->fid - tb->fid;
+}
+
void
index_update(struct tag *tag)
{
- struct track *track, *track_iter;
struct dirent *ent;
- struct link *iter;
- struct ref *ref;
struct stat st;
char *path;
FILE *file;
@@ -152,6 +162,80 @@ index_update(struct tag *tag)
fclose(file);
}
+bool
+tracks_update(struct tag *tag)
+{
+ struct dirent *ent;
+ struct stat st;
+ struct link *link;
+ struct ref *ref;
+ struct track *track;
+ char *path;
+ DIR *dir;
+ int fid;
+
+ dir = opendir(tag->fpath);
+ if (!dir) return false;
+
+ while (!list_empty(&tag->tracks)) {
+ link = list_pop_front(&tag->tracks);
+ ref = UPCAST(link, struct ref);
+ track = ref->data;
+ ref_free(ref);
+ for (LIST_ITER(&tracks, link)) {
+ ref = UPCAST(link, struct ref);
+ if (ref->data == track) {
+ link = link_pop(link);
+ ref_free(ref);
+ break;
+ }
+ }
+ if (player.track == track)
+ player.track = NULL;
+ track_free(track);
+ }
+
+ while ((ent = readdir(dir))) {
+ if (!strcmp(ent->d_name, "."))
+ continue;
+ if (!strcmp(ent->d_name, ".."))
+ continue;
+ if (!strcmp(ent->d_name, "index"))
+ continue;
+
+ /* skip files without extension */
+ if (!strchr(ent->d_name + 1, '.'))
+ continue;
+
+ path = aprintf("%s/%s", tag->fpath, ent->d_name);
+ OOM_CHECK(path);
+
+ fid = get_fid(path);
+
+ track = track_alloc(tag->fpath, ent->d_name, fid);
+ OOM_CHECK(track);
+
+ ref = ref_alloc(tag);
+ OOM_CHECK(ref);
+ list_push_back(&track->tags, LINK(ref));
+
+ ref = ref_alloc(track);
+ OOM_CHECK(ref);
+ list_push_back(&tag->tracks, LINK(ref));
+
+ ref = ref_alloc(track);
+ OOM_CHECK(ref);
+ list_push_back(&tracks, LINK(ref));
+
+ free(path);
+ }
+
+ list_sort(&tracks, track_fid_compare);
+
+ closedir(dir);
+ return true;
+}
+
void
tracks_load(struct tag *tag)
{
@@ -163,7 +247,6 @@ tracks_load(struct tag *tag)
char *index_path;
char *track_name, *sep;
int track_fid;
- bool new_track;
FILE *file;
index_path = aprintf("%s/index", tag->fpath);
@@ -188,26 +271,17 @@ tracks_load(struct tag *tag)
track_name = sep + 1;
track = track_alloc(tag->fpath, track_name, track_fid);
- ref = ref_init(tag);
+ ref = ref_alloc(tag);
OOM_CHECK(ref);
list_push_back(&track->tags, LINK(ref));
- ref = ref_init(track);
+ ref = ref_alloc(track);
OOM_CHECK(ref);
list_push_back(&tag->tracks, LINK(ref));
- new_track = true;
- for (LIST_ITER(&tracks, link)) {
- track2 = UPCAST(link, struct ref)->data;
- if (track->fid > 0 && track->fid == track2->fid)
- new_track = false;
- }
-
- if (new_track) {
- ref = ref_init(track);
- OOM_CHECK(ref);
- list_push_back(&tracks, LINK(ref));
- }
+ ref = ref_alloc(track);
+ OOM_CHECK(ref);
+ list_push_back(&tracks, LINK(ref));
}
fclose(file);
@@ -228,65 +302,122 @@ tracks_save(struct tag *tag)
OOM_CHECK(index_path);
file = fopen(index_path, "w+");
- if (!file) ERROR("Failed to write to index file: %s\n", index_path);
+ if (!file) {
+ fprintf(stderr, "Failed to write to index file: %s\n",
+ index_path);
+ free(index_path);
+ return;
+ }
for (LIST_ITER(&tag->tracks, link)) {
track = UPCAST(link, struct ref)->data;
- fprintf(file, "%i:%s\n", track->fid, track->fname);
+ fprintf(file, "%i:%s\n", track->fid, track->name);
}
fclose(file);
free(index_path);
}
-void
+bool
+make_dir(const char *path)
+{
+ return mkdir(path, S_IRWXU | S_IRWXG) == 0;
+}
+
+bool
+rm_dir(const char *path, bool recursive)
+{
+ char *files[] = { (char *) path, NULL };
+ FTSENT *ent;
+ FTS *fts;
+ int flags;
+
+ if (recursive) {
+ flags = FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV;
+ fts = fts_open(files, flags, NULL);
+ if (!fts) return false;
+
+ while ((ent = fts_read(fts))) {
+ switch (ent->fts_info) {
+ case FTS_NS:
+ case FTS_DNR:
+ case FTS_ERR:
+ fts_close(fts);
+ return false;
+ case FTS_D:
+ break;
+ default:
+ if (remove(ent->fts_accpath) < 0) {
+ fts_close(fts);
+ return false;
+ }
+ break;
+ }
+ }
+
+ fts_close(fts);
+ } else {
+ if (rmdir(path) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+bool
rm_file(const char *path)
{
- ASSERT(unlink(path) == 0);
+ return unlink(path) == 0;
}
-void
+bool
copy_file(const char *src, const char *dst)
{
FILE *in, *out;
char buf[4096];
int len, nread;
+ bool ok;
+
+ ok = false;
+ in = out = NULL;
in = fopen(src, "r");
- if (in == NULL)
- ERROR("Failed to read from file: %s\n", src);
+ if (in == NULL) goto cleanup;
out = fopen(dst, "w+");
- if (out == NULL)
- ERROR("Failed to write to file: %s\n", dst);
+ if (out == NULL) goto cleanup;
while ((nread = fread(buf, 1, sizeof(buf), in)) > 0) {
fwrite(buf, 1, nread, out);
}
if (nread < 0)
- ERROR("Failed to copy file from %s to %s\n", src, dst);
+ goto cleanup;
+
+ ok = true;
- fclose(in);
- fclose(out);
+cleanup:
+ if (in) fclose(in);
+ if (out) fclose(out);
+
+ return ok;
}
-void
+bool
move_file(const char *src, const char *dst)
{
- copy_file(src, dst);
- rm_file(src);
+ return rename(src, dst) == 0;
}
struct tag *
-tag_find(const wchar_t *query)
+tag_find(const char *query)
{
struct link *iter;
struct tag *tag;
for (LIST_ITER(&tags, iter)) {
tag = UPCAST(iter, struct tag);
- if (!wcscmp(tag->name, query)) {
+ if (!strcmp(tag->name, query)) {
return tag;
}
}
diff --git a/src/data.h b/src/data.h
@@ -7,18 +7,22 @@ void data_save(void);
void data_free(void);
int get_fid(const char *path);
+int track_fid_compare(struct link *a, struct link *b);
void index_update(struct tag *tag);
+bool tracks_update(struct tag *tag);
void tracks_load(struct tag *tag);
void tracks_save(struct tag *tag);
-void rm_file(const char *path);
-void copy_file(const char *dst, const char *src);
-void move_file(const char *dst, const char *src);
+bool make_dir(const char *path);
+bool rm_dir(const char *path, bool recursive);
+bool rm_file(const char *path);
+bool copy_file(const char *dst, const char *src);
+bool move_file(const char *dst, const char *src);
-struct tag *tag_find(const wchar_t *query);
+struct tag *tag_find(const char *query);
extern const char *datadir;
-extern struct list tracks;
-extern struct list tags;
-extern struct list tags_sel;
+extern struct list tracks; /* struct ref */
+extern struct list tags; /* struct tag */
+extern struct list tags_sel; /* struct ref */
diff --git a/src/history.c b/src/history.c
@@ -1,61 +1,25 @@
+#define _GNU_SOURCE
+
#include "history.h"
#include "util.h"
#include <string.h>
-#include <wchar.h>
-void
-history_init(struct history *history)
-{
- list_init(&history->list);
- history->input = inputln_alloc();
- history->sel = history->input;
-}
+static struct inputln *
+history_list_prev(struct inputln *cur, const char *search);
-void
-history_submit(struct history *history)
-{
- /* if chose from history free input */
- if (history->sel != history->input) {
- link_pop(LINK(history->input));
- inputln_free(history->input);
- }
-
- /* pop first in case already in history */
- link_pop(LINK(history->sel));
- history_add(history, history->sel);
-
- /* create new input buf and add to hist */
- history->input = inputln_alloc();
- history->sel = history->input;
- history_add(history, history->sel);
-}
-
-void
-history_free(struct history *history)
-{
- struct link *iter, *next;
- struct link *ln;
-
- ln = link_pop(LINK(history->input));
- inputln_free(UPCAST(ln, struct inputln));
-
- list_free(&history->list, (link_free_func) inputln_free,
- LINK_OFFSET(struct inputln, link));
-
- history->input = NULL;
- history->sel = NULL;
-}
+static struct inputln *
+history_list_next(struct inputln *cur, const char *search);
struct inputln *
-history_list_prev(struct inputln *cur, const wchar_t *search)
+history_list_prev(struct inputln *cur, const char *search)
{
struct link *iter;
struct inputln *ln;
for (iter = cur->link.prev; iter && iter->prev; iter = iter->prev) {
ln = UPCAST(iter, struct inputln);
- if (!search || !*search || wcscasestr(ln->buf, search))
+ if (!search || !*search || strcasestr(ln->buf, search))
return ln;
}
@@ -63,7 +27,7 @@ history_list_prev(struct inputln *cur, const wchar_t *search)
}
struct inputln *
-history_list_next(struct inputln *cur, const wchar_t *search)
+history_list_next(struct inputln *cur, const char *search)
{
struct link *iter;
struct inputln *ln;
@@ -71,7 +35,7 @@ history_list_next(struct inputln *cur, const wchar_t *search)
iter = cur->link.next;
while (LIST_INNER(iter)) {
ln = UPCAST(iter, struct inputln);
- if (!search || !*search || wcscasestr(ln->buf, search))
+ if (!search || !*search || strcasestr(ln->buf, search))
return ln;
iter = iter->next;
}
@@ -80,6 +44,50 @@ history_list_next(struct inputln *cur, const wchar_t *search)
}
void
+history_init(struct history *history)
+{
+ list_init(&history->list);
+ history->input = inputln_alloc();
+ history->sel = history->input;
+}
+
+void
+history_deinit(struct history *history)
+{
+ struct link *link;
+ struct inputln *ln;
+
+ link = link_pop(LINK(history->input));
+ ln = UPCAST(link, struct inputln);
+ inputln_free(ln);
+ history->input = NULL;
+
+ list_free(&history->list, (link_free_func) inputln_free,
+ LINK_OFFSET(struct inputln, link));
+
+ history->sel = NULL;
+}
+
+void
+history_submit(struct history *history)
+{
+ /* if chose from history free input */
+ if (history->sel != history->input) {
+ link_pop(LINK(history->input));
+ inputln_free(history->input);
+ }
+
+ /* pop first in case already in history */
+ link_pop(LINK(history->sel));
+ history_add(history, history->sel);
+
+ /* create new input buf and add to hist */
+ history->input = inputln_alloc();
+ history->sel = history->input;
+ history_add(history, history->sel);
+}
+
+void
history_prev(struct history *history)
{
history->sel = history_list_prev(history->sel, history->input->buf);
@@ -100,7 +108,8 @@ history_add(struct history *history, struct inputln *line)
if (list_len(&history->list) == HISTORY_MAX) {
/* pop last item to make space */
back = list_pop_back(&history->list);
- inputln_free(UPCAST(back, struct inputln));
+ ln = UPCAST(back, struct inputln);
+ inputln_free(ln);
}
list_push_front(&history->list, LINK(line));
@@ -114,9 +123,16 @@ inputln_init(struct inputln *ln)
ln->cap = 0;
ln->cur = 0;
ln->link = LINK_EMPTY;
+
inputln_resize(ln, 128);
}
+void
+inputln_deinit(struct inputln *ln)
+{
+ free(ln->buf);
+}
+
struct inputln *
inputln_alloc(void)
{
@@ -132,11 +148,23 @@ inputln_alloc(void)
void
inputln_free(struct inputln *ln)
{
- free(ln->buf);
+ inputln_deinit(ln);
free(ln);
}
void
+inputln_resize(struct inputln *ln, size_t size)
+{
+ ASSERT(size != 0);
+
+ ln->cap = size;
+ ln->buf = realloc(ln->buf, ln->cap * sizeof(char));
+ OOM_CHECK(ln->buf);
+ ln->len = MIN(ln->len, ln->cap-1);
+ ln->buf[ln->len] = '\0';
+}
+
+void
inputln_left(struct inputln *ln)
{
ln->cur = MAX(0, ln->cur-1);
@@ -149,14 +177,13 @@ inputln_right(struct inputln *ln)
}
void
-inputln_addch(struct inputln *line, wchar_t c)
+inputln_addch(struct inputln *line, char c)
{
int i;
if (line->len + 1 >= line->cap) {
line->cap *= 2;
- line->buf = realloc(line->buf,
- line->cap * sizeof(wchar_t));
+ line->buf = realloc(line->buf, line->cap);
}
for (i = line->len; i > line->cur; i--)
@@ -195,31 +222,19 @@ inputln_copy(struct inputln *dst, struct inputln *src)
dst->buf = NULL;
}
dst->len = src->len;
- dst->buf = wcsdup(src->buf);
+ dst->buf = strdup(src->buf);
OOM_CHECK(dst->buf);
dst->cap = src->len + 1;
dst->cur = dst->len;
}
void
-inputln_replace(struct inputln *line, const wchar_t *str)
+inputln_replace(struct inputln *line, const char *str)
{
- line->len = wcslen(str);
+ line->len = strlen(str);
if (line->cap <= line->len)
inputln_resize(line, line->len + 1);
- line->buf = wcscpy(line->buf, str);
+ strncpy(line->buf, str, line->len);
line->cur = line->len;
}
-void
-inputln_resize(struct inputln *ln, size_t size)
-{
- ASSERT(size != 0);
-
- ln->cap = size;
- ln->buf = realloc(ln->buf, ln->cap * sizeof(wchar_t));
- OOM_CHECK(ln->buf);
- ln->len = MIN(ln->len, ln->cap-1);
- ln->buf[ln->len] = '\0';
-}
-
diff --git a/src/history.h b/src/history.h
@@ -2,12 +2,10 @@
#include "list.h"
-#include "wchar.h"
-
#define HISTORY_MAX 100
struct inputln {
- wchar_t *buf;
+ char *buf;
int len, cap;
int cur;
@@ -20,7 +18,7 @@ struct history {
};
void history_init(struct history *history);
-void history_free(struct history *history);
+void history_deinit(struct history *history);
void history_submit(struct history *history);
@@ -29,16 +27,20 @@ void history_next(struct history *history);
void history_add(struct history *history, struct inputln *line);
-struct inputln *inputln_alloc(void);
void inputln_init(struct inputln *ln);
-void inputln_resize(struct inputln *ln, size_t size);
+void inputln_deinit(struct inputln *ln);
+
+struct inputln *inputln_alloc(void);
void inputln_free(struct inputln *ln);
+void inputln_resize(struct inputln *ln, size_t size);
+
void inputln_left(struct inputln *line);
void inputln_right(struct inputln *line);
-void inputln_addch(struct inputln *line, wchar_t c);
+void inputln_addch(struct inputln *line, char c);
void inputln_del(struct inputln *line, int n);
void inputln_copy(struct inputln *dst, struct inputln *src);
-void inputln_replace(struct inputln *line, const wchar_t *str);
+void inputln_replace(struct inputln *line, const char *str);
+
diff --git a/src/pane.c b/src/pane.c
@@ -1,5 +1,13 @@
+#define _XOPEN_SOURCE
+
#include "pane.h"
+
#include "util.h"
+#include "strbuf.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
void
pane_init(struct pane *pane, pane_handler handle, pane_updater update)
@@ -11,6 +19,12 @@ pane_init(struct pane *pane, pane_handler handle, pane_updater update)
}
void
+pane_deinit(struct pane *pane)
+{
+ delwin(pane->win);
+}
+
+void
pane_resize(struct pane *pane, int sx, int sy, int ex, int ey)
{
pane->sx = sx;
@@ -29,18 +43,20 @@ pane_resize(struct pane *pane, int sx, int sy, int ex, int ey)
}
void
-pane_clearln(struct pane *pane, int y)
+pane_clearln(struct pane *pane, int row)
{
int i;
- wmove(pane->win, y, 0);
+ wmove(pane->win, row, 0);
for (i = 0; i < pane->w; i++)
waddch(pane->win, ' ');
}
void
-pane_free(struct pane *pane)
+pane_writeln(struct pane *pane, int row, const char *str)
{
- delwin(pane->win);
+ pane_clearln(pane, row);
+ wmove(pane->win, row, 0);
+ waddstr(pane->win, str);
}
diff --git a/src/pane.h b/src/pane.h
@@ -4,11 +4,11 @@
#include <ncurses.h>
-#include <wchar.h>
+#include <stdbool.h>
struct pane;
-typedef int (*pane_handler)(wint_t c);
+typedef bool (*pane_handler)(wint_t c);
typedef void (*pane_updater)(struct pane *pane, int sel);
struct pane {
@@ -22,7 +22,9 @@ struct pane {
};
void pane_init(struct pane *pane, pane_handler handle, pane_updater update);
+void pane_deinit(struct pane *pane);
+
void pane_resize(struct pane *pane, int sx, int sy, int ex, int ey);
void pane_clearln(struct pane *pane, int y);
-void pane_free(struct pane *p);
+void pane_writeln(struct pane *pane, int y, const char *line);
diff --git a/src/player_mpd.c b/src/player_mpd.c
@@ -217,7 +217,7 @@ player_add_history(struct track *track)
if (ref->data == track) return;
}
- ref = ref_init(track);
+ ref = ref_alloc(track);
list_push_back(&player.history, LINK(ref));
}
diff --git a/src/ref.c b/src/ref.c
@@ -2,14 +2,16 @@
#include "util.h"
struct ref *
-ref_init(void *data)
+ref_alloc(void *data)
{
struct ref *ref;
ref = malloc(sizeof(struct ref));
if (!ref) return NULL;
+
ref->link = LINK_EMPTY;
ref->data = data;
+
return ref;
}
diff --git a/src/ref.h b/src/ref.h
@@ -8,7 +8,7 @@ struct ref {
struct link link;
};
-struct ref *ref_init(void *data);
+struct ref *ref_alloc(void *data);
void ref_free(void *ref);
void refs_free(struct list *list);
diff --git a/src/strbuf.c b/src/strbuf.c
@@ -0,0 +1,55 @@
+#include "strbuf.h"
+
+#include "util.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+void
+strbuf_init(struct strbuf *strbuf)
+{
+ strbuf->buf = NULL;
+ strbuf->cap = 0;
+}
+
+void
+strbuf_deinit(struct strbuf *strbuf)
+{
+ free(strbuf->buf);
+}
+
+void
+strbuf_clear(struct strbuf *strbuf)
+{
+ if (!strbuf->buf)
+ strbuf_append(strbuf, "");
+
+ strbuf->buf[0] = '\0';
+}
+
+void
+strbuf_append(struct strbuf *strbuf, const char *fmt, ...)
+{
+ va_list ap, cpy;
+ int blen, slen;
+
+ va_copy(cpy, ap);
+
+ blen = strbuf->buf ? strlen(strbuf->buf) : 0;
+
+ va_start(cpy, fmt);
+ slen = vsnprintf(NULL, 0, fmt, cpy);
+ ASSERT(slen >= 0);
+ va_end(cpy);
+
+ if (blen + slen + 1 > strbuf->cap) {
+ strbuf->cap = blen + slen + 1;
+ strbuf->buf = realloc(strbuf->buf, strbuf->cap);
+ OOM_CHECK(strbuf->buf);
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(strbuf->buf + blen, slen + 1, fmt, ap);
+ va_end(ap);
+}
diff --git a/src/strbuf.h b/src/strbuf.h
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+
+struct strbuf {
+ char *buf;
+ size_t cap;
+};
+
+void strbuf_init(struct strbuf *strbuf);
+void strbuf_deinit(struct strbuf *strbuf);
+
+void strbuf_clear(struct strbuf *strbuf);
+void strbuf_append(struct strbuf *strbuf, const char *fmt, ...);
diff --git a/src/tag.c b/src/tag.c
@@ -1,11 +1,13 @@
#include "tag.h"
+
#include "link.h"
#include "ref.h"
+#include "util.h"
#include <string.h>
struct tag *
-tag_init(const char *path, const char *fname)
+tag_alloc(const char *path, const char *fname)
{
struct tag *tag;
int len;
@@ -13,19 +15,11 @@ tag_init(const char *path, const char *fname)
tag = malloc(sizeof(struct tag));
ASSERT(tag != NULL);
- tag->fname = strdup(fname);
- ASSERT(tag->fname != NULL);
-
- tag->new_fname = NULL;
-
tag->fpath = aprintf("%s/%s", path, fname);
ASSERT(tag->fpath != NULL);
- len = mbstowcs(NULL, tag->fname, 0);
- ASSERT(len > 0);
- tag->name = calloc(len + 1, sizeof(wchar_t));
+ tag->name = strdup(fname);
ASSERT(tag->name != NULL);
- mbstowcs(tag->name, tag->fname, len + 1);
tag->link = LINK_EMPTY;
@@ -37,11 +31,8 @@ tag_init(const char *path, const char *fname)
void
tag_free(struct tag *tag)
{
- free(tag->fname);
free(tag->fpath);
free(tag->name);
-
refs_free(&tag->tracks);
-
free(tag);
}
diff --git a/src/tag.h b/src/tag.h
@@ -1,18 +1,14 @@
#pragma once
#include "list.h"
-#include "util.h"
struct tag {
- wchar_t *name;
- char *fname, *fpath;
-
- char *new_fname;
+ char *name, *fpath;
struct list tracks;
struct link link;
};
-struct tag *tag_init(const char *path, const char *fname);
+struct tag *tag_alloc(const char *path, const char *fname);
void tag_free(struct tag *tag);
diff --git a/src/track.c b/src/track.c
@@ -14,17 +14,11 @@ track_alloc(const char *dir, const char *fname, int fid)
track = malloc(sizeof(struct track));
ASSERT(track != NULL);
- track->fname = strdup(fname);
- ASSERT(track->fname != NULL);
-
track->fpath = aprintf("%s/%s", dir, fname);
ASSERT(track->fpath != NULL);
- len = mbstowcs(NULL, track->fname, 0);
- ASSERT(len >= 0);
- track->name = calloc(len + 1, sizeof(wchar_t));
+ track->name = strdup(fname);
ASSERT(track->name != NULL);
- mbstowcs(track->name, track->fname, len + 1);
track->fid = fid;
@@ -36,11 +30,8 @@ track_alloc(const char *dir, const char *fname, int fid)
void
track_free(struct track *t)
{
- free(t->fname);
free(t->fpath);
free(t->name);
-
refs_free(&t->tags);
-
free(t);
}
diff --git a/src/track.h b/src/track.h
@@ -4,9 +4,8 @@
#include "util.h"
struct track {
- wchar_t *name;
+ char *name, *fpath;
struct list tags;
- char *fname, *fpath;
int fid;
};
diff --git a/src/tui.c b/src/tui.c
@@ -1,4 +1,5 @@
#define NCURSES_WIDECHAR 1
+#define _GNU_SOURCE
#include "tui.h"
@@ -11,15 +12,15 @@
#include "listnav.h"
#include "ref.h"
#include "style.h"
+#include "strbuf.h"
#include "util.h"
#include <ncurses.h>
+#include <ctype.h>
+#include <string.h>
#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-
#undef KEY_ENTER
#define KEY_ENTER '\n'
#define KEY_SPACE ' '
@@ -35,27 +36,28 @@ enum {
IMODE_COUNT
};
-typedef wchar_t *(*completion_gen)(const wchar_t *text, int fwd, int state);
+typedef char *(*completion_gen)(const char *text, int fwd, int state);
static void pane_title(struct pane *pane, const char *title, int highlight);
-static wchar_t *command_name_gen(const wchar_t *text, int fwd, int state);
-static wchar_t *track_name_gen(const wchar_t *text, int fwd, int state);
-static wchar_t *tag_name_gen(const wchar_t *text, int fwd, int state);
+static char *command_name_gen(const char *text, int fwd, int state);
+static char *track_name_gen(const char *text, int fwd, int state);
+static char *tag_name_gen(const char *text, int fwd, int state);
static void toggle_current_tag(void);
-static int tag_pane_input(wint_t c);
+
+static bool tag_pane_input(wint_t c);
static void tag_pane_vis(struct pane *pane, int sel);
-static int track_pane_input(wint_t c);
+static bool track_pane_input(wint_t c);
static void track_pane_vis(struct pane *pane, int sel);
-static bool run_cmd(const wchar_t *name);
-static bool play_track(const wchar_t *name);
-static bool select_track(const wchar_t *name);
-static bool select_tag(const wchar_t *name);
+static bool run_cmd(const char *name);
+static bool play_track(const char *name);
+static bool select_track(const char *name);
+static bool select_tag(const char *name);
-static int cmd_pane_input(wint_t c);
+static bool cmd_pane_input(wint_t c);
static void cmd_pane_vis(struct pane *pane, int sel);
static void queue_hover(void);
@@ -125,36 +127,41 @@ pane_title(struct pane *pane, const char *title, int highlight)
style_off(pane->win, STYLE_TITLE);
}
-wchar_t *
-command_name_gen(const wchar_t *text, int fwd, int reset)
+char *
+command_name_gen(const char *text, int fwd, int reset)
{
static int index, len;
+ char *dup;
int dir;
dir = fwd ? 1 : -1;
if (reset) {
index = 0;
- len = wcslen(text);
+ len = strlen(text);
} else if (index >= -1 && index <= command_count) {
index += dir;
}
while (index >= 0 && index < command_count) {
- if (!wcsncmp(commands[index].name, text, len))
- return wcsdup(commands[index].name);
+ if (!strncmp(commands[index].name, text, len)) {
+ dup = strdup(commands[index].name);
+ OOM_CHECK(dup);
+ return dup;
+ }
index += dir;
}
return NULL;
}
-wchar_t *
-track_name_gen(const wchar_t *text, int fwd, int reset)
+char *
+track_name_gen(const char *text, int fwd, int reset)
{
static struct link *cur;
struct link *iter;
struct track *track;
+ char *dup;
if (reset) {
cur = tracks.head.next;
@@ -165,9 +172,11 @@ track_name_gen(const wchar_t *text, int fwd, int reset)
while (LIST_INNER(iter)) {
track = UPCAST(iter, struct ref)->data;
- if (wcscasestr(track->name, text)) {
+ if (strcasestr(track->name, text)) {
cur = iter;
- return wcsdup(track->name);
+ dup = strdup(track->name);
+ OOM_CHECK(dup);
+ return dup;
}
iter = fwd ? iter->next : iter->prev;
}
@@ -175,12 +184,13 @@ track_name_gen(const wchar_t *text, int fwd, int reset)
return NULL;
}
-wchar_t *
-tag_name_gen(const wchar_t *text, int fwd, int reset)
+char *
+tag_name_gen(const char *text, int fwd, int reset)
{
static struct link *cur;
struct link *iter;
struct tag *tag;
+ char *dup;
if (reset) {
cur = tags.head.next;
@@ -191,9 +201,11 @@ tag_name_gen(const wchar_t *text, int fwd, int reset)
while (LIST_INNER(iter)) {
tag = UPCAST(iter, struct tag);
- if (wcscasestr(tag->name, text)) {
+ if (strcasestr(tag->name, text)) {
cur = iter;
- return wcsdup(tag->name);
+ dup = strdup(tag->name);
+ OOM_CHECK(dup);
+ return dup;
}
iter = fwd ? iter->next : iter->prev;
}
@@ -220,7 +232,7 @@ toggle_current_tag(void)
if (refs_incl(&tags_sel, tag)) {
refs_rm(&tags_sel, tag);
} else {
- ref = ref_init(tag);
+ ref = ref_alloc(tag);
list_push_back(&tags_sel, LINK(ref));
}
@@ -229,36 +241,36 @@ toggle_current_tag(void)
for (LIST_ITER(&tags_sel, link)) {
tag = UPCAST(link, struct ref)->data;
for (LIST_ITER(&tag->tracks, iter)) {
- ref = ref_init(UPCAST(iter, struct ref)->data);
+ ref = ref_alloc(UPCAST(iter, struct ref)->data);
ASSERT(ref != NULL);
list_push_back(&player.playlist, LINK(ref));
}
}
}
-int
+bool
tag_pane_input(wint_t c)
{
switch (c) {
case KEY_UP:
listnav_update_sel(&tag_nav, tag_nav.sel - 1);
- return 1;
+ return true;
case KEY_DOWN:
listnav_update_sel(&tag_nav, tag_nav.sel + 1);
- return 1;
+ return true;
case KEY_SPACE:
toggle_current_tag();
- return 1;
+ return true;
case KEY_ENTER:
refs_free(&tags_sel);
toggle_current_tag();
- return 1;
+ return true;
case KEY_PPAGE:
listnav_update_sel(&tag_nav, tag_nav.sel - tag_nav.wlen / 2);
- return 1;
+ return true;
case KEY_NPAGE:
listnav_update_sel(&tag_nav, tag_nav.sel + tag_nav.wlen / 2);
- return 1;
+ return true;
case 'g':
listnav_update_sel(&tag_nav, 0);
break;
@@ -267,7 +279,7 @@ tag_pane_input(wint_t c)
break;
}
- return 0;
+ return false;
}
void
@@ -301,8 +313,7 @@ tag_pane_vis(struct pane *pane, int sel)
else if (index == tag_nav.sel)
style_on(pane->win, STYLE_PREV);
- wmove(pane->win, 1 + index - tag_nav.wmin, 0);
- wprintw(pane->win, "%-*.*ls", pane->w, pane->w, tag->name);
+ pane_writeln(pane, 1 + index - tag_nav.wmin, tag->name);
if (sel && tagsel && index == tag_nav.sel)
style_off(pane->win, STYLE_ITEM_HOVER_SEL);
@@ -315,7 +326,7 @@ tag_pane_vis(struct pane *pane, int sel)
}
}
-int
+bool
track_pane_input(wint_t c)
{
struct link *link;
@@ -324,24 +335,24 @@ track_pane_input(wint_t c)
switch (c) {
case KEY_UP:
listnav_update_sel(&track_nav, track_nav.sel - 1);
- return 1;
+ return true;
case KEY_DOWN:
listnav_update_sel(&track_nav, track_nav.sel + 1);
- return 1;
+ return true;
case KEY_ENTER:
link = list_at(tracks_vis, track_nav.sel);
- if (!link) return 1;
+ if (!link) return true;
track = UPCAST(link, struct ref)->data;
player_play_track(track);
- return 1;
+ return true;
case KEY_PPAGE:
listnav_update_sel(&track_nav,
track_nav.sel - track_nav.wlen / 2);
- return 1;
+ return true;
case KEY_NPAGE:
listnav_update_sel(&track_nav,
track_nav.sel + track_nav.wlen / 2);
- return 1;
+ return true;
case 'g':
listnav_update_sel(&track_nav, 0);
break;
@@ -350,7 +361,7 @@ track_pane_input(wint_t c)
break;
}
- return 0;
+ return false;
}
void
@@ -384,8 +395,7 @@ track_pane_vis(struct pane *pane, int sel)
else if (index == track_nav.sel)
style_on(pane->win, STYLE_PREV);
- wmove(pane->win, 1 + index - track_nav.wmin, 0);
- wprintw(pane->win, "%-*.*ls", pane->w, pane->w, track->name);
+ pane_writeln(pane, 1 + index - track_nav.wmin, track->name);
if (sel && index == track_nav.sel && track == player.track)
style_off(pane->win, STYLE_ITEM_HOVER_SEL);
@@ -399,35 +409,44 @@ track_pane_vis(struct pane *pane, int sel)
}
bool
-run_cmd(const wchar_t *query)
+run_cmd(const char *query)
{
- bool success;
+ bool success, found;
- success = cmd_run(query);
+ success = cmd_run(query, &found);
if (!success && !cmd_status)
- CMD_SET_STATUS("Command Failed!");
- return true;
+ CMD_SET_STATUS("FAIL");
+ else if (success && !cmd_status)
+ CMD_SET_STATUS("OK");
+
+ return found;
}
bool
-play_track(const wchar_t *query)
+play_track(const char *query)
{
struct track *track;
struct link *iter;
+ int fid;
+ fid = -1;
for (LIST_ITER(&tracks, iter)) {
track = UPCAST(iter, struct ref)->data;
- if (!wcscmp(track->name, query)) {
+ if (fid == track->fid) continue;
+
+ if (!strcmp(track->name, query)) {
player_play_track(track);
return true;
}
+
+ fid = track->fid;
}
return false;
}
bool
-select_track(const wchar_t *query)
+select_track(const char *query)
{
struct track *track;
struct link *link;
@@ -436,7 +455,7 @@ select_track(const wchar_t *query)
index = 0;
for (LIST_ITER(tracks_vis, link)) {
track = UPCAST(link, struct ref)->data;
- if (!wcscmp(track->name, query)) {
+ if (!strcmp(track->name, query)) {
listnav_update_sel(&track_nav, index);
pane_after_cmd = track_pane;
return true;
@@ -448,7 +467,7 @@ select_track(const wchar_t *query)
}
bool
-select_tag(const wchar_t *query)
+select_tag(const char *query)
{
struct tag *tag;
struct link *iter;
@@ -458,7 +477,7 @@ select_tag(const wchar_t *query)
for (LIST_ITER(&tags, iter)) {
index += 1;
tag = UPCAST(iter, struct tag);
- if (!wcscmp(tag->name, query)) {
+ if (!strcmp(tag->name, query)) {
listnav_update_sel(&tag_nav, index);
pane_after_cmd = tag_pane;
return true;
@@ -468,19 +487,19 @@ select_tag(const wchar_t *query)
return false;
}
-int
+bool
cmd_pane_input(wint_t c)
{
- wchar_t *res;
+ char *res;
int match;
switch (c) {
case KEY_ESC:
- match = wcscmp(completion_query.buf, history->input->buf);
+ match = strcmp(completion_query.buf, history->input->buf);
if (!completion_reset && match) {
inputln_copy(history->input, &completion_query);
} else if (history->sel == history->input) {
- inputln_replace(history->input, L"");
+ inputln_replace(history->input, "");
pane_sel = pane_after_cmd;
} else {
history->sel = history->input;
@@ -550,82 +569,61 @@ cmd_pane_input(wint_t c)
completion_reset = 1;
break;
default:
- if (!iswprint(c)) return 0;
+ /* TODO: wide char input support */
+ if (!isprint(c)) return 0;
inputln_addch(history->sel, c);
completion_reset = 1;
break;
}
- return 1; /* grab everything */
+ return true; /* grab everything */
}
void
cmd_pane_vis(struct pane *pane, int sel)
{
- static wchar_t *linebuf = NULL;
- static int linecap = 0;
+ static struct strbuf line = { 0 };
struct inputln *cmd;
struct link *iter;
- wchar_t *line, *end;
int index, offset;
werase(pane->win);
- /* static line buffer for perf */
- if (pane->w > linecap) {
- linecap = MAX(linecap, pane->w);
- linebuf = realloc(linebuf, linecap * sizeof(wchar_t));
- }
- end = linebuf + linecap;
-
/* track name */
style_on(pane->win, STYLE_TITLE);
pane_clearln(pane, 0);
if (player.loaded && player.track) {
- swprintf(linebuf, linecap, L"%ls", player.track->name);
- mvwaddwstr(pane->win, 0, 1, linebuf);
+ strbuf_clear(&line);
+ strbuf_append(&line, " %s", player.track->name);
+ pane_writeln(pane, 0, line.buf);
}
style_off(pane->win, STYLE_TITLE);
if (player.loaded) {
/* status line */
- line = linebuf;
- line += swprintf(line, end - line, L"%c ",
- player_state_chars[player.state]);
- line += swprintf(line, end - line, L"%s / ",
- timestr(player.time_pos));
- line += swprintf(line, end - line, L"%s",
- timestr(player.time_end));
-
- if (player.volume >= 0) {
- line += swprintf(line, end - line, L" - vol: %u%%",
- player.volume);
- }
+ strbuf_clear(&line);
+ strbuf_append(&line, "%c ", player_state_chars[player.state]);
+ strbuf_append(&line, "%s / ", timestr(player.time_pos));
+ strbuf_append(&line, "%s", timestr(player.time_end));
- if (player.status) {
- line += swprintf(line, end - line, L" | [PLAYER] %s",
- player.status);
- }
+ if (player.volume >= 0)
+ strbuf_append(&line, " - vol: %u%%", player.volume);
- if (list_len(&player.queue)) {
- line += swprintf(line, end - line,
- L" | [QUEUE] %i tracks",
+ if (player.status)
+ strbuf_append(&line, " | [PLAYER] %s", player.status);
+
+ if (list_len(&player.queue) > 0)
+ strbuf_append(&line, " | [QUEUE] %i tracks",
list_len(&player.queue));
- }
ATTR_ON(pane->win, A_REVERSE);
- pane_clearln(pane, 1);
- mvwaddwstr(pane->win, 1, 0, linebuf);
+ pane_writeln(pane, 1, line.buf);
ATTR_OFF(pane->win, A_REVERSE);
} else if (player.status) {
/* player message */
- line = linebuf;
- line += swprintf(line, linecap, L"[PLAYER] %s", player.status);
- line += swprintf(line, end - line, L"%*.*s",
- pane->w, pane->w, L" ");
-
- pane_clearln(pane, 1);
- mvwaddwstr(pane->win, 1, 0, linebuf);
+ strbuf_clear(&line);
+ strbuf_append(&line, "[PLAYER] %s", player.status);
+ pane_writeln(pane, 1, line.buf);
}
/* status bits on right of status line */
@@ -638,7 +636,7 @@ cmd_pane_vis(struct pane *pane, int sel)
if (sel || cmd_show) {
/* cmd and search input */
- line = linebuf;
+ strbuf_clear(&line);
free(cmd_status);
cmd_status = NULL;
@@ -651,18 +649,15 @@ cmd_pane_vis(struct pane *pane, int sel)
break;
index += 1;
}
- line += swprintf(line, end - line, L"[%i] ",
- iter ? index : -1);
+ strbuf_append(&line, "[%i] ", iter ? index : -1);
} else {
- line += swprintf(line, end - line, L"%c",
- imode_prefix[cmd_input_mode]);
+ strbuf_append(&line, "%c", imode_prefix[cmd_input_mode]);
}
- offset = wcslen(linebuf);
+ offset = strlen(line.buf);
- line += swprintf(line, end - line, L"%ls", cmd->buf);
+ strbuf_append(&line, "%s", cmd->buf);
- pane_clearln(pane, 2);
- mvwaddwstr(pane->win, 2, 0, linebuf);
+ pane_writeln(pane, 2, line.buf);
if (sel) { /* show cursor in text */
ATTR_ON(pane->win, A_REVERSE);
@@ -672,8 +667,9 @@ cmd_pane_vis(struct pane *pane, int sel)
ATTR_OFF(pane->win, A_REVERSE);
}
} else if (cmd_status) {
- pane_clearln(pane, 2);
- mvwprintw(pane->win, 2, 0, " %.*s", pane->w - 1, cmd_status);
+ strbuf_clear(&line);
+ strbuf_append(&line, " %s", cmd_status);
+ pane_writeln(pane, 2, line.buf);
}
}
@@ -888,7 +884,7 @@ tui_resize(void)
leftw = 0;
for (LIST_ITER(&tags, iter)) {
tag = UPCAST(iter, struct tag);
- leftw = MAX(leftw, wcslen(tag->name));
+ leftw = MAX(leftw, strlen(tag->name));
}
leftw = MAX(leftw + 1, 0.2f * scrw);
@@ -939,14 +935,16 @@ tui_deinit(void)
{
free(cmd_status);
- pane_free(&pane_left);
- pane_free(&pane_right);
- pane_free(&pane_bot);
+ inputln_deinit(&completion_query);
+
+ pane_deinit(&pane_left);
+ pane_deinit(&pane_right);
+ pane_deinit(&pane_bot);
- history_free(&track_play_history);
- history_free(&track_select_history);
- history_free(&tag_select_history);
- history_free(&command_history);
+ history_deinit(&track_play_history);
+ history_deinit(&track_select_history);
+ history_deinit(&tag_select_history);
+ history_deinit(&command_history);
if (!isendwin()) endwin();
}
diff --git a/src/tui.h b/src/tui.h
@@ -5,7 +5,6 @@
#include "pane.h"
#include <stdbool.h>
-#include <wchar.h>
void tui_init(void);
void tui_deinit(void);
diff --git a/src/util.c b/src/util.c
@@ -9,53 +9,10 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <wchar.h>
-#include <wctype.h>
static const char *allowed = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:,;-_(){}[]";
-int
-strnwidth(const char *s, int n)
-{
- mbstate_t shift_state;
- wchar_t wc;
- size_t wc_len;
- size_t width = 0;
-
- memset(&shift_state, '\0', sizeof shift_state);
-
- for (size_t i = 0; i < n; i += wc_len) {
- wc_len = mbrtowc(&wc, s + i, MB_CUR_MAX, &shift_state);
- if (!wc_len) {
- break;
- } else if (wc_len >= (size_t)-2) {
- width += MIN(n - 1, strlen(s + i));
- break;
- } else {
- width += iswcntrl(wc) ? 2 : MAX(0, wcwidth(wc));
- }
- }
-
-done:
- return width;
-}
-
-const wchar_t *
-wcscasestr(const wchar_t *haystack, const wchar_t *needle)
-{
- int hslen, nlen, i;
-
- nlen = wcslen(needle);
- hslen = wcslen(haystack) - nlen;
- for (i = 0; i < hslen; i++) {
- if (!wcsncasecmp(haystack + i, needle, nlen))
- return haystack + i;
- }
-
- return NULL;
-}
-
void
panic(const char *file, int line, const char *msg, ...)
{
diff --git a/src/util.h b/src/util.h
@@ -1,7 +1,6 @@
#pragma once
#include <stdio.h>
-#include <wchar.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) > (b) ? (b) : (a))
@@ -15,10 +14,6 @@
#define LINK(p) (&(p)->link)
#define UPCAST(iter, type) LINK_UPCAST(iter, type, link)
-int strnwidth(const char *s, int n);
-
-const wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle);
-
void panic(const char *file, int line, const char *msg, ...);
void assert(int cond, const char *file, int line, const char *condstr);
void error(const char *fmtstr, ...);