aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--view.c91
1 files changed, 84 insertions, 7 deletions
diff --git a/view.c b/view.c
index af237c9..f028c82 100644
--- a/view.c
+++ b/view.c
@@ -1,6 +1,10 @@
#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
#include <math.h>
#include <unistd.h>
+#include <termios.h>
#include <glib.h>
#include <gio/gio.h>
@@ -8,12 +12,73 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixdata.h>
-// TODO Unhardcode these
-const int char_width = 8;
-const int char_height = 15;
+static FILE* tty;
+static int tty_fd;
+static struct termios tty_tio;
-const int window_width = 8 * 80;
-const int window_height = 15 * 25;
+static int char_width = 8;
+static int char_height = 15;
+static int window_columns = 25;
+static int window_rows = 80;
+static int window_width = 8 * 80;
+static int window_height = 15 * 25;
+
+static bool init_terminal(int fd);
+static void close_terminal();
+
+static bool init_terminal(int fd)
+{
+ const char *name_of_tty = ttyname(fd);
+ if (!name_of_tty) {
+ return FALSE;
+ }
+
+ tty = fopen(name_of_tty, "r+");
+ if (tty == NULL) {
+ g_printerr("Cannot open terminal %s", name_of_tty);
+ return FALSE;
+ }
+ tty_fd = fileno(tty);
+
+ tcgetattr(tty_fd, &tty_tio);
+ struct termios tio = tty_tio;
+
+ tio.c_lflag &= ~(ICANON | ECHO);
+ tio.c_cc[VMIN] = 4;
+ tio.c_cc[VTIME] = 1;
+ tcsetattr(tty_fd, TCSADRAIN, &tio);
+
+ // Try to get window width and height in pixels using a xterm command
+ fprintf(tty, "\033[14;t");
+ fflush(tty);
+
+ if (fscanf(tty, "\033[4;%d;%dt", &window_height, &window_width) != 2) {
+ close_terminal();
+ return FALSE;
+ }
+
+ // Also use a xterm command to get the window size in chars,
+ // (could also use termios...)
+ fprintf(tty, "\033[18;t");
+ fflush(tty);
+
+ if (fscanf(tty, "\033[8;%d;%dt", &window_rows, &window_columns) != 2) {
+ close_terminal();
+ return FALSE;
+ }
+
+ // Now calculate char height & width based on the above data
+ char_width = window_width / window_columns;
+ char_height = window_height / window_rows;
+
+ return TRUE;
+}
+
+static void close_terminal()
+{
+ tcsetattr(tty_fd, TCSADRAIN, &tty_tio);
+ fclose(tty);
+}
static gboolean view_pixbuf(GdkPixbuf *pixbuf)
{
@@ -52,13 +117,15 @@ static gboolean view_pixbuf(GdkPixbuf *pixbuf)
guint8 *data = gdk_pixdata_serialize(&pixdata, &size);
gchar *str = g_base64_encode(data, size);
- g_print("\033]v;%s\007", str);
+ fprintf(tty, "\033]v;%s\007", str);
int rows = ceil(height / (double)char_height);
while (rows > 0) {
- g_print("\n");
+ fprintf(tty, "\n");
rows--;
}
+
+ fflush(tty);
g_free(str);
g_free(data);
@@ -80,16 +147,23 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
+ if (!init_terminal((STDOUT_FILENO))) {
+ g_printerr("Refusing to display image on non-graphical terminal\n");
+ return EXIT_FAILURE;
+ }
+
if (argc > 1) {
int i;
for (i = 1; i < argc; i++) {
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[i], &error);
if (pixbuf == NULL) {
g_printerr("Failed to open image '%s': %s\n", argv[i], error->message);
+ close_terminal();
return EXIT_FAILURE;
}
if (!view_pixbuf(pixbuf)) {
g_printerr("Failed to view image '%s'\n", argv[i]);
+ close_terminal();
return EXIT_FAILURE;
}
g_object_unref(pixbuf);
@@ -99,14 +173,17 @@ int main(int argc, char * argv[])
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_stream(input, NULL, &error);
if (pixbuf == NULL) {
g_printerr("Failed to open stdin image: %s\n", error->message);
+ close_terminal();
return EXIT_FAILURE;
}
if (!view_pixbuf(pixbuf)) {
g_printerr("Failed to view stdin image\n");
+ close_terminal();
return EXIT_FAILURE;
}
g_object_unref(pixbuf);
}
+ close_terminal();
return EXIT_SUCCESS;
}