#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define BUFSIZE 512

/* usage: $0 * < *.flf > *.fs */
/* font usage: *-string-xy ( x y c-addr u -- ) */
int main(int argc, char** argv) {

  char buffer[BUFSIZE];
  char *magicchars[] = {
    " ", "▘", "▝", "▀", "▖", "▌", "▞", "▛", "▗", "▚", "▐",
    "▜", "▄", "▙", "▟", "█"
  };
  
  int x = 0, height = 0, width = 0, i;
  char s = 0;
  char *cbuf;
  int ch = 0;
  int w = 0;
  int eol = 0;
  int l = 0;


  /* no error checking makes flf2fs a dull program */
  /* messy programming compensates */

  if (argc != 2)
    exit(2);


  // read height and maxwidth from header
  if (!fgets(buffer, BUFSIZE, stdin)) exit(1);

  char* bptr = buffer+5;
  
  s = *bptr;
  
  bptr+=2;

  while (*bptr != ' ') {
    height = 10*height + (*bptr) - '0';
    bptr++;
  }
  
  bptr++;

  while (*bptr != ' ') {
    width = 10*width + (*bptr) - '0';
    bptr++;
  }

  width+=2;

  fprintf(stderr, "h = %d w = %d\n", height, width);

  //exit(2);

  // ignore line 2
  fgets(buffer, BUFSIZE, stdin);


  // ignore all subsequent lines until they end in @

  do {
    if (!fgets(buffer, BUFSIZE, stdin)) exit(1);
    x = strlen(buffer);
    while (buffer[x-1] == ' ' || buffer[x-1] == '\n' || buffer[x-1] == '\r' && x > 0) x--;

    if (buffer[x-1]!='@'){buffer[x]=0;printf("\\ %s\n", buffer);}
  } while (buffer[x-1] != '@');

  cbuf = malloc(sizeof(char)*(width+1)/2*(height+1)/2);

  ch = 32;

  while (bptr != NULL) {
    x = strlen(buffer);
    while (buffer[x-1] == ' ' || buffer[x-1] == '\n' || buffer[x-1] == '\r' && x > 0) x--;

    if (buffer[x-1] != '@')
      break;

    w = 0;
    for (i = 0; i < (width+1)/2*(height+1)/2; i++) cbuf[i] = 0;

    for (i = 0; i < height; i++) {
      // dump everything into the array
      l = 0;
      bptr = buffer;
      while (*bptr) {
	switch (*bptr) {
	case ' ':
	  l++;
	  break;
	case '#':
	  cbuf[(l/2)+(i/2)*((width+1)/2)] |= 1<<((l%2)+2*(i%2));
	  l++;
	  break;
	case '$':
	  break;
	case '@':
	case '\n':
	  *(bptr+1) = 0;
	  break;
	}
	
	bptr++;
      }
      
      if (w < l)
	w = l;

      if (!fgets(buffer, BUFSIZE, stdin)) { bptr = NULL; break; }
    }

    // now output the whole thing
    printf(": %s-char-%d ( x y -- w ) \\ %c\n", argv[1], ch, ch);
    
    for (i = 0; i < (height+1)/2; i++) {
      printf("2dup at-xy .\" ");
      for (x = 0; x < ((w+1)/2); x++)
	printf(magicchars[cbuf[i*((width+1)/2)+x]]);

      printf("\" 1+\n");
    }
    printf("2drop %d ;\n", (1+w)/2);

    ch++;

  }

  free(cbuf);

  // EWWWWWWWWWWWWWWWWWWWWWWWW - however, .. well
  printf("create %s-char-table %d cells allot\n %s-char-table\n", argv[1], ch-32, argv[1]);
    
  //  note: we could use noname
  for (i = 32; i < ch; i++) {
    printf("' %s-char-%d over ! cell+\n", argv[1], i);
  }

  printf("drop\n");
  printf(": %s-char-xy 32 - dup 0>= over %d < and if "
	 "cells %s-char-table + @ execute else "
	 ">r at-xy r> 32 + emit 1 then ;\n",
	 argv[1], ch-32, argv[1]);

  printf(": %s-string-xy ( x y c-addr u -- ) \n\
     begin				      \n\
     dup				      \n\
     while				      \n\
     over c@ >r 2over r> %s-char-xy >r        \n\
     2swap swap r> + swap 2swap 1 /string     \n\
     repeat				      \n\
     2drop 2drop			      \n\
     ;\n", argv[1], argv[1]);
  
}
