Bladeren bron

* Make stdin input line-aware so that we don't have to wait until EOF to

display stuff.
  * Reorganise stuff and fix memory leaks.
pull/1/head
Sam Hocevar sam 18 jaren geleden
bovenliggende
commit
99f3252c73
11 gewijzigde bestanden met toevoegingen van 344 en 207 verwijderingen
  1. +1
    -1
      src/Makefile.am
  2. +16
    -1
      src/figlet.c
  3. +0
    -18
      src/figlet.h
  4. +8
    -1
      src/filter.c
  5. +1
    -0
      src/filter.h
  6. +6
    -62
      src/main.c
  7. +136
    -0
      src/mono9.c
  8. +54
    -124
      src/render.c
  9. +7
    -0
      src/render.h
  10. +113
    -0
      src/term.c
  11. +2
    -0
      src/toilet.h

+ 1
- 1
src/Makefile.am Bestand weergeven

@@ -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@


+ 16
- 1
src/figlet.c Bestand weergeven

@@ -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;


+ 0
- 18
src/figlet.h Bestand weergeven

@@ -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 *);


+ 8
- 1
src/filter.c Bestand weergeven

@@ -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;
}


+ 1
- 0
src/filter.h Bestand weergeven

@@ -17,4 +17,5 @@

extern int filter_add(context_t *, char const *);
extern int filter_do(context_t *);
extern int filter_end(context_t *);


+ 6
- 62
src/main.c Bestand weergeven

@@ -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;
}


+ 136
- 0
src/mono9.c Bestand weergeven

@@ -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;
}


+ 54
- 124
src/render.c Bestand weergeven

@@ -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;
}


+ 7
- 0
src/render.h Bestand weergeven

@@ -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 *);


+ 113
- 0
src/term.c Bestand weergeven

@@ -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;
}


+ 2
- 0
src/toilet.h Bestand weergeven

@@ -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 */


Laden…
Annuleren
Opslaan