summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2021-01-11 18:05:22 -0500
committerJune McEnroe <june@causal.agency>2021-01-11 18:05:22 -0500
commit51c92f94ff2728a6db539a82fb4c501f45118062 (patch)
treea4267a63286a986c071cae823f678e332e76e6da
parentDon't pass nick to urlScan for MOTD and help (diff)
downloadcatgirl-51c92f94ff2728a6db539a82fb4c501f45118062.tar.gz
catgirl-51c92f94ff2728a6db539a82fb4c501f45118062.zip
Save and load the URL ring in the save file 1.4
-rw-r--r--chat.h2
-rw-r--r--ui.c40
-rw-r--r--url.c44
3 files changed, 72 insertions, 14 deletions
diff --git a/chat.h b/chat.h
index 41a3683..b5e546a 100644
--- a/chat.h
+++ b/chat.h
@@ -356,6 +356,8 @@ void urlScan(uint id, const char *nick, const char *mesg);
 void urlOpenCount(uint id, uint count);
 void urlOpenMatch(uint id, const char *str);
 void urlCopyMatch(uint id, const char *str);
+int urlSave(FILE *file);
+void urlLoad(FILE *file, size_t version);
 
 enum { IgnoreCap = 64 };
 extern struct Ignore {
diff --git a/ui.c b/ui.c
index 2958c30..0a0342e 100644
--- a/ui.c
+++ b/ui.c
@@ -946,7 +946,8 @@ static const time_t Signatures[] = {
 	0x6C72696774616302, // no self.pos
 	0x6C72696774616303, // no buffer line heat
 	0x6C72696774616304, // no mute
-	0x6C72696774616305,
+	0x6C72696774616305, // no URLs
+	0x6C72696774616306,
 };
 
 static size_t signatureVersion(time_t signature) {
@@ -967,25 +968,35 @@ int uiSave(const char *name) {
 	FILE *file = dataOpen(name, "w");
 	if (!file) return -1;
 
-	if (writeTime(file, Signatures[4])) return -1;
-	if (writeTime(file, self.pos)) return -1;
+	int error = 0
+		|| writeTime(file, Signatures[5])
+		|| writeTime(file, self.pos);
+	if (error) return error;
 	for (uint num = 0; num < windows.len; ++num) {
 		const struct Window *window = windows.ptrs[num];
-		if (writeString(file, idNames[window->id])) return -1;
-		if (writeTime(file, window->mute)) return -1;
-		if (writeTime(file, window->heat)) return -1;
-		if (writeTime(file, window->unreadSoft)) return -1;
-		if (writeTime(file, window->unreadWarm)) return -1;
+		error = 0
+			|| writeString(file, idNames[window->id])
+			|| writeTime(file, window->mute)
+			|| writeTime(file, window->heat)
+			|| writeTime(file, window->unreadSoft)
+			|| writeTime(file, window->unreadWarm);
+		if (error) return error;
 		for (size_t i = 0; i < BufferCap; ++i) {
 			const struct Line *line = bufferSoft(window->buffer, i);
 			if (!line) continue;
-			if (writeTime(file, line->time)) return -1;
-			if (writeTime(file, line->heat)) return -1;
-			if (writeString(file, line->str)) return -1;
+			error = 0
+				|| writeTime(file, line->time)
+				|| writeTime(file, line->heat)
+				|| writeString(file, line->str);
+			if (error) return error;
 		}
-		if (writeTime(file, 0)) return -1;
+		error = writeTime(file, 0);
+		if (error) return error;
 	}
-	return fclose(file);
+	return 0
+		|| writeString(file, "")
+		|| urlSave(file)
+		|| fclose(file);
 }
 
 static time_t readTime(FILE *file) {
@@ -1026,7 +1037,7 @@ void uiLoad(const char *name) {
 
 	char *buf = NULL;
 	size_t cap = 0;
-	while (0 < readString(file, &buf, &cap)) {
+	while (0 < readString(file, &buf, &cap) && buf[0]) {
 		struct Window *window = windows.ptrs[windowFor(idFor(buf))];
 		if (version > 3) window->mute = readTime(file);
 		if (version > 0) {
@@ -1045,6 +1056,7 @@ void uiLoad(const char *name) {
 			window->buffer, COLS, window->ignore, window->unreadSoft
 		);
 	}
+	urlLoad(file, version);
 
 	free(buf);
 	fclose(file);
diff --git a/url.c b/url.c
index 53fe271..21f946c 100644
--- a/url.c
+++ b/url.c
@@ -230,3 +230,47 @@ void urlCopyMatch(uint id, const char *str) {
 		}
 	}
 }
+
+static int writeString(FILE *file, const char *str) {
+	return (fwrite(str, strlen(str) + 1, 1, file) ? 0 : -1);
+}
+static ssize_t readString(FILE *file, char **buf, size_t *cap) {
+	ssize_t len = getdelim(buf, cap, '\0', file);
+	if (len < 0 && !feof(file)) err(EX_IOERR, "getdelim");
+	return len;
+}
+
+int urlSave(FILE *file) {
+	for (size_t i = 0; i < Cap; ++i) {
+		const struct URL *url = &ring.urls[(ring.len + i) % Cap];
+		if (!url->url) continue;
+		int error = 0
+			|| writeString(file, idNames[url->id])
+			|| writeString(file, (url->nick ?: ""))
+			|| writeString(file, url->url);
+		if (error) return error;
+	}
+	return writeString(file, "");
+}
+
+void urlLoad(FILE *file, size_t version) {
+	if (version < 5) return;
+	size_t cap = 0;
+	char *buf = NULL;
+	while (0 < readString(file, &buf, &cap) && buf[0]) {
+		struct URL *url = &ring.urls[ring.len++ % Cap];
+		free(url->nick);
+		free(url->url);
+		url->id = idFor(buf);
+		url->nick = NULL;
+		readString(file, &buf, &cap);
+		if (buf[0]) {
+			url->nick = strdup(buf);
+			if (!url->nick) err(EX_OSERR, "strdup");
+		}
+		readString(file, &buf, &cap);
+		url->url = strdup(buf);
+		if (!url->url) err(EX_OSERR, "strdup");
+	}
+	free(buf);
+}