display stuff. * Reorganise stuff and fix memory leaks.pull/1/head
@@ -5,7 +5,7 @@ toilet_SOURCES = main.c \ | |||
io.c io.h \ | |||
render.c render.h \ | |||
filter.c filter.h \ | |||
figlet.c figlet.h | |||
term.c mono9.c figlet.c | |||
toilet_CFLAGS = `pkg-config --cflags cucul` | |||
toilet_LDFLAGS = `pkg-config --libs cucul` @GETOPT_LIBS@ @ZLIB_LIBS@ | |||
@@ -26,13 +26,14 @@ | |||
#include <cucul.h> | |||
#include "toilet.h" | |||
#include "render.h" | |||
#include "io.h" | |||
#include "figlet.h" | |||
#define STD_GLYPHS (127 - 32) | |||
#define EXT_GLYPHS (STD_GLYPHS + 7) | |||
static int feed_figlet(context_t *, uint32_t); | |||
static int flush_figlet(context_t *); | |||
static int end_figlet(context_t *); | |||
static int open_font(context_t *cx); | |||
@@ -47,6 +48,7 @@ int init_figlet(context_t *cx) | |||
cx->cv = cucul_create_canvas(1, 1); | |||
cx->feed = feed_figlet; | |||
cx->flush = flush_figlet; | |||
cx->end = end_figlet; | |||
return 0; | |||
@@ -108,9 +110,22 @@ static int feed_figlet(context_t *cx, uint32_t ch) | |||
return 0; | |||
} | |||
static int flush_figlet(context_t *cx) | |||
{ | |||
cx->torender = cx->cv; | |||
cucul_set_canvas_size(cx->torender, cx->w, cx->h); | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(1, 1); | |||
return 0; | |||
} | |||
static int end_figlet(context_t *cx) | |||
{ | |||
cucul_free_canvas(cx->image); | |||
cucul_free_canvas(cx->cv); | |||
free(cx->lookup); | |||
return 0; | |||
@@ -1,18 +0,0 @@ | |||
/* | |||
* TOIlet The Other Implementation’s letters | |||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the Do What The Fuck You Want To | |||
* Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
/* | |||
* This header defines functions for handling FIGlet fonts. | |||
*/ | |||
extern int init_figlet(context_t *); | |||
@@ -92,7 +92,14 @@ int filter_do(context_t *cx) | |||
unsigned int i; | |||
for(i = 0; i < cx->nfilters; i++) | |||
cx->filters[i](cx->cv); | |||
cx->filters[i](cx->torender); | |||
return 0; | |||
} | |||
int filter_end(context_t *cx) | |||
{ | |||
free(cx->filters); | |||
return 0; | |||
} | |||
@@ -17,4 +17,5 @@ | |||
extern int filter_add(context_t *, char const *); | |||
extern int filter_do(context_t *); | |||
extern int filter_end(context_t *); | |||
@@ -27,13 +27,11 @@ | |||
# include <sys/ioctl.h> | |||
#endif | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <stdlib.h> | |||
#include <cucul.h> | |||
#include "toilet.h" | |||
#include "render.h" | |||
#include "figlet.h" | |||
#include "filter.h" | |||
static void version(void); | |||
@@ -46,10 +44,6 @@ int main(int argc, char *argv[]) | |||
context_t struct_cx; | |||
context_t *cx = &struct_cx; | |||
cucul_buffer_t *buffer; | |||
int i, j, ret; | |||
int infocode = -1; | |||
cx->export = "utf8"; | |||
@@ -183,66 +177,16 @@ int main(int argc, char *argv[]) | |||
return 0; | |||
} | |||
if(!strcasecmp(cx->font, "mono9")) | |||
ret = init_big(cx); | |||
else if(!strcasecmp(cx->font, "term")) | |||
ret = init_tiny(cx); | |||
else | |||
ret = init_figlet(cx); | |||
if(ret) | |||
if(render_init(cx) < 0) | |||
return -1; | |||
if(optind >= argc) | |||
{ | |||
char buf[10]; | |||
unsigned int len; | |||
uint32_t ch; | |||
i = 0; | |||
/* Read from stdin */ | |||
while(!feof(stdin)) | |||
{ | |||
buf[i++] = getchar(); | |||
buf[i] = '\0'; | |||
ch = cucul_utf8_to_utf32(buf, &len); | |||
if(!len) | |||
continue; | |||
cx->feed(cx, ch); | |||
i = 0; | |||
} | |||
} | |||
else for(i = optind; i < argc; i++) | |||
{ | |||
/* Read from commandline */ | |||
unsigned int len; | |||
if(i != optind) | |||
cx->feed(cx, ' '); | |||
for(j = 0; argv[i][j];) | |||
{ | |||
cx->feed(cx, cucul_utf8_to_utf32(argv[i] + j, &len)); | |||
j += len; | |||
} | |||
} | |||
cx->end(cx); | |||
/* Apply optional effects to our string */ | |||
filter_do(cx); | |||
/* Output char */ | |||
buffer = cucul_export_canvas(cx->cv, cx->export); | |||
fwrite(cucul_get_buffer_data(buffer), | |||
cucul_get_buffer_size(buffer), 1, stdout); | |||
cucul_free_buffer(buffer); | |||
render_stdin(cx); | |||
else | |||
render_list(cx, argc - optind, argv + optind); | |||
cucul_free_canvas(cx->cv); | |||
render_end(cx); | |||
filter_end(cx); | |||
return 0; | |||
} | |||
@@ -0,0 +1,136 @@ | |||
/* | |||
* TOIlet The Other Implementation’s letters | |||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the Do What The Fuck You Want To | |||
* Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
/* | |||
* This file contains text to canvas rendering functions. | |||
*/ | |||
#include "config.h" | |||
#if defined(HAVE_INTTYPES_H) | |||
# include <inttypes.h> | |||
#endif | |||
#include <stdlib.h> | |||
#include <cucul.h> | |||
#include "toilet.h" | |||
#include "render.h" | |||
static int feed_big(context_t *, uint32_t); | |||
static int flush_big(context_t *); | |||
static int end_big(context_t *); | |||
int init_big(context_t *cx) | |||
{ | |||
char const * const * fonts; | |||
fonts = cucul_get_font_list(); | |||
cx->f = cucul_load_font(fonts[0], 0); | |||
cx->buf = malloc(4 * cucul_get_font_width(cx->f) | |||
* cucul_get_font_height(cx->f)); | |||
cx->onechar = cucul_create_canvas(1, 1); | |||
cucul_set_color(cx->onechar, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK); | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(1, 1); | |||
cx->feed = feed_big; | |||
cx->flush = flush_big; | |||
cx->end = end_big; | |||
return 0; | |||
} | |||
static int feed_big(context_t *cx, uint32_t ch) | |||
{ | |||
unsigned int w = cucul_get_font_width(cx->f); | |||
unsigned int h = cucul_get_font_height(cx->f); | |||
unsigned int x, y; | |||
switch(ch) | |||
{ | |||
case (uint32_t)'\r': | |||
return 0; | |||
case (uint32_t)'\n': | |||
cx->x = 0; | |||
cx->y += h; | |||
return 0; | |||
case (uint32_t)'\t': | |||
cx->x = (((cx->x / w) & ~7) + 8) * w; | |||
return 0; | |||
} | |||
/* Check whether we reached the end of the screen */ | |||
if(cx->x && cx->x + w > cx->term_width) | |||
{ | |||
cx->x = 0; | |||
cx->y += h; | |||
} | |||
/* Check whether the current canvas is large enough */ | |||
if(cx->x + w > cx->w) | |||
cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width; | |||
if(cx->y + h > cx->h) | |||
cx->h = cx->y + h; | |||
cucul_set_canvas_size(cx->cv, cx->w, cx->h); | |||
/* Render our char */ | |||
cucul_putchar(cx->onechar, 0, 0, ch); | |||
cucul_render_canvas(cx->onechar, cx->f, cx->buf, w, h, 4 * w); | |||
for(y = 0; y < h; y++) | |||
for(x = 0; x < w; x++) | |||
{ | |||
unsigned char c = cx->buf[4 * (x + y * w) + 2]; | |||
if(c >= 0xa0) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "█"); | |||
else if(c >= 0x80) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▓"); | |||
else if(c >= 0x40) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▒"); | |||
else if(c >= 0x20) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "░"); | |||
} | |||
/* Advance cursor */ | |||
cx->x += w; | |||
return 0; | |||
} | |||
static int flush_big(context_t *cx) | |||
{ | |||
cx->torender = cx->cv; | |||
cucul_set_canvas_size(cx->torender, cx->w, cx->h); | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(1, 1); | |||
return 0; | |||
} | |||
static int end_big(context_t *cx) | |||
{ | |||
cucul_free_canvas(cx->onechar); | |||
cucul_free_canvas(cx->cv); | |||
free(cx->buf); | |||
cucul_free_font(cx->f); | |||
return 0; | |||
} | |||
@@ -21,169 +21,99 @@ | |||
# include <inttypes.h> | |||
#endif | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <stdio.h> | |||
#include <cucul.h> | |||
#include "toilet.h" | |||
#include "render.h" | |||
#include "filter.h" | |||
static int feed_tiny(context_t *, uint32_t); | |||
static int end_tiny(context_t *); | |||
static int feed_big(context_t *, uint32_t); | |||
static int end_big(context_t *); | |||
int init_tiny(context_t *cx) | |||
int render_init(context_t *cx) | |||
{ | |||
cx->ew = 16; | |||
cx->eh = 2; | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(cx->ew, cx->eh); | |||
if(!strcasecmp(cx->font, "mono9")) | |||
return init_big(cx); | |||
cx->feed = feed_tiny; | |||
cx->end = end_tiny; | |||
if(!strcasecmp(cx->font, "term")) | |||
return init_tiny(cx); | |||
return 0; | |||
return init_figlet(cx); | |||
} | |||
static int feed_tiny(context_t *cx, uint32_t ch) | |||
int render_stdin(context_t *cx) | |||
{ | |||
switch(ch) | |||
{ | |||
case (uint32_t)'\r': | |||
return 0; | |||
case (uint32_t)'\n': | |||
cx->x = 0; | |||
cx->y++; | |||
return 0; | |||
case (uint32_t)'\t': | |||
cx->x = (cx->x & ~7) + 8; | |||
return 0; | |||
} | |||
char buf[10]; | |||
unsigned int i = 0, len; | |||
uint32_t ch; | |||
/* Check whether we reached the end of the screen */ | |||
if(cx->x && cx->x + 1 > cx->term_width) | |||
/* Read from stdin */ | |||
while(!feof(stdin)) | |||
{ | |||
cx->x = 0; | |||
cx->y++; | |||
} | |||
buf[i++] = getchar(); | |||
buf[i] = '\0'; | |||
/* Check whether the current canvas is large enough */ | |||
if(cx->x + 1 > cx->w) | |||
{ | |||
cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width; | |||
if(cx->w > cx->ew) | |||
cx->ew = cx->ew + cx->ew / 2; | |||
} | |||
ch = cucul_utf8_to_utf32(buf, &len); | |||
if(cx->y + 1 > cx->h) | |||
{ | |||
cx->h = cx->y + 1; | |||
if(cx->h > cx->eh) | |||
cx->eh = cx->eh + cx->eh / 2; | |||
} | |||
if(!len) | |||
continue; | |||
cucul_set_canvas_size(cx->cv, cx->ew, cx->eh); | |||
cx->feed(cx, ch); | |||
i = 0; | |||
cucul_putchar(cx->cv, cx->x, cx->y, ch); | |||
cx->x++; | |||
if(ch == '\n') | |||
render_line(cx); | |||
} | |||
return 0; | |||
} | |||
static int end_tiny(context_t *cx) | |||
int render_list(context_t *cx, unsigned int argc, char *argv[]) | |||
{ | |||
cucul_set_canvas_size(cx->cv, cx->w, cx->h); | |||
return 0; | |||
} | |||
unsigned int i, j; | |||
int init_big(context_t *cx) | |||
{ | |||
char const * const * fonts; | |||
for(i = 0; i < argc; i++) | |||
{ | |||
/* Read from commandline */ | |||
unsigned int len; | |||
fonts = cucul_get_font_list(); | |||
cx->f = cucul_load_font(fonts[0], 0); | |||
cx->buf = malloc(4 * cucul_get_font_width(cx->f) | |||
* cucul_get_font_height(cx->f)); | |||
cx->onechar = cucul_create_canvas(1, 1); | |||
cucul_set_color(cx->onechar, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK); | |||
if(i) | |||
cx->feed(cx, ' '); | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(1, 1); | |||
for(j = 0; argv[i][j];) | |||
{ | |||
cx->feed(cx, cucul_utf8_to_utf32(argv[i] + j, &len)); | |||
j += len; | |||
} | |||
} | |||
cx->feed = feed_big; | |||
cx->end = end_big; | |||
render_line(cx); | |||
return 0; | |||
} | |||
static int feed_big(context_t *cx, uint32_t ch) | |||
int render_line(context_t *cx) | |||
{ | |||
unsigned int w = cucul_get_font_width(cx->f); | |||
unsigned int h = cucul_get_font_height(cx->f); | |||
unsigned int x, y; | |||
switch(ch) | |||
{ | |||
case (uint32_t)'\r': | |||
return 0; | |||
case (uint32_t)'\n': | |||
cx->x = 0; | |||
cx->y += h; | |||
return 0; | |||
case (uint32_t)'\t': | |||
cx->x = (((cx->x / w) & ~7) + 8) * w; | |||
return 0; | |||
} | |||
/* Check whether we reached the end of the screen */ | |||
if(cx->x && cx->x + w > cx->term_width) | |||
{ | |||
cx->x = 0; | |||
cx->y += h; | |||
} | |||
/* Check whether the current canvas is large enough */ | |||
if(cx->x + w > cx->w) | |||
cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width; | |||
if(cx->y + h > cx->h) | |||
cx->h = cx->y + h; | |||
cucul_buffer_t *buffer; | |||
cucul_set_canvas_size(cx->cv, cx->w, cx->h); | |||
/* Flush current line */ | |||
cx->flush(cx); | |||
/* Render our char */ | |||
cucul_putchar(cx->onechar, 0, 0, ch); | |||
cucul_render_canvas(cx->onechar, cx->f, cx->buf, w, h, 4 * w); | |||
for(y = 0; y < h; y++) | |||
for(x = 0; x < w; x++) | |||
{ | |||
unsigned char c = cx->buf[4 * (x + y * w) + 2]; | |||
if(c >= 0xa0) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "█"); | |||
else if(c >= 0x80) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▓"); | |||
else if(c >= 0x40) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▒"); | |||
else if(c >= 0x20) | |||
cucul_putstr(cx->cv, cx->x + x, cx->y + y, "░"); | |||
} | |||
/* Apply optional effects to our string */ | |||
filter_do(cx); | |||
/* Advance cursor */ | |||
cx->x += w; | |||
/* Output line */ | |||
buffer = cucul_export_canvas(cx->torender, cx->export); | |||
fwrite(cucul_get_buffer_data(buffer), | |||
cucul_get_buffer_size(buffer), 1, stdout); | |||
cucul_free_buffer(buffer); | |||
cucul_free_canvas(cx->torender); | |||
return 0; | |||
} | |||
static int end_big(context_t *cx) | |||
int render_end(context_t *cx) | |||
{ | |||
cucul_free_canvas(cx->onechar); | |||
free(cx->buf); | |||
cucul_free_font(cx->f); | |||
cx->end(cx); | |||
return 0; | |||
} | |||
@@ -17,4 +17,11 @@ | |||
extern int init_tiny(context_t *); | |||
extern int init_big(context_t *); | |||
extern int init_figlet(context_t *); | |||
extern int render_init(context_t *); | |||
extern int render_stdin(context_t *); | |||
extern int render_list(context_t *, unsigned int, char *[]); | |||
extern int render_line(context_t *); | |||
extern int render_end(context_t *); | |||
@@ -0,0 +1,113 @@ | |||
/* | |||
* TOIlet The Other Implementation’s letters | |||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the Do What The Fuck You Want To | |||
* Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
/* | |||
* This file contains text to canvas rendering functions. | |||
*/ | |||
#include "config.h" | |||
#if defined(HAVE_INTTYPES_H) | |||
# include <inttypes.h> | |||
#endif | |||
#include <stdlib.h> | |||
#include <cucul.h> | |||
#include "toilet.h" | |||
#include "render.h" | |||
static int feed_tiny(context_t *, uint32_t); | |||
static int flush_tiny(context_t *); | |||
static int end_tiny(context_t *); | |||
int init_tiny(context_t *cx) | |||
{ | |||
cx->ew = 16; | |||
cx->eh = 2; | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(cx->ew, cx->eh); | |||
cx->feed = feed_tiny; | |||
cx->flush = flush_tiny; | |||
cx->end = end_tiny; | |||
return 0; | |||
} | |||
static int feed_tiny(context_t *cx, uint32_t ch) | |||
{ | |||
switch(ch) | |||
{ | |||
case (uint32_t)'\r': | |||
return 0; | |||
case (uint32_t)'\n': | |||
cx->x = 0; | |||
cx->y++; | |||
return 0; | |||
case (uint32_t)'\t': | |||
cx->x = (cx->x & ~7) + 8; | |||
return 0; | |||
} | |||
/* Check whether we reached the end of the screen */ | |||
if(cx->x && cx->x + 1 > cx->term_width) | |||
{ | |||
cx->x = 0; | |||
cx->y++; | |||
} | |||
/* Check whether the current canvas is large enough */ | |||
if(cx->x + 1 > cx->w) | |||
{ | |||
cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width; | |||
if(cx->w > cx->ew) | |||
cx->ew = cx->ew + cx->ew / 2; | |||
} | |||
if(cx->y + 1 > cx->h) | |||
{ | |||
cx->h = cx->y + 1; | |||
if(cx->h > cx->eh) | |||
cx->eh = cx->eh + cx->eh / 2; | |||
} | |||
cucul_set_canvas_size(cx->cv, cx->ew, cx->eh); | |||
cucul_putchar(cx->cv, cx->x, cx->y, ch); | |||
cx->x++; | |||
return 0; | |||
} | |||
static int flush_tiny(context_t *cx) | |||
{ | |||
cx->torender = cx->cv; | |||
cucul_set_canvas_size(cx->torender, cx->w, cx->h); | |||
cx->ew = 16; | |||
cx->eh = 2; | |||
cx->x = cx->y = 0; | |||
cx->w = cx->h = 0; | |||
cx->cv = cucul_create_canvas(cx->ew, cx->eh); | |||
return 0; | |||
} | |||
static int end_tiny(context_t *cx) | |||
{ | |||
cucul_free_canvas(cx->cv); | |||
return 0; | |||
} | |||
@@ -24,10 +24,12 @@ struct toilet_context | |||
unsigned int term_width; | |||
cucul_canvas_t *cv; | |||
cucul_canvas_t *torender; | |||
unsigned int w, h, ew, eh, x, y; | |||
/* Render methods */ | |||
int (*feed)(struct toilet_context *, uint32_t); | |||
int (*flush)(struct toilet_context *); | |||
int (*end)(struct toilet_context *); | |||
/* Used by the big driver */ | |||