The Punched Paper Project website has moved.

This website is from 2008 and the information is most likely quite outdated. Please see the technikum29 Labs for the new website. You might also want to check the technikum29 Computer Museum main website.
-- Sven, July 2013

Paper Tape Font files

I have developed a portable and easy to use ASCII storage format for paper tape fonts, called Paper Tape Font file. While paper tape fonts were formerly implemented as (perl) scripts, with C (and C++) that's no more practical, because setting up big nested hashes is not really possible. Apart from that, it would not be a good style to set up a giant header file with so much static data.

I have considered using popular and approved data formats like XML or Jason instead of a "proprietary" new, perhaps even binary data format. On the one hand, using XML would have been really portable, but also very unhandy, because I would have to look for XML processors for Windows, and compiling would be get complex and even more complex.

Therefore I've decided in favor of simple ASCII files with some not very strict layout. It's really obvious how it works:

|***.***  |a   You can write texts almost everywhere in the file,
|   .*  * |a   just the very first letters, which actually
|***.***  |a   *look* like a papertape (direction of movement, of
|   .     |    course, from top down), define the bytes from
|***.*****|e   that the letters are made up, which stand directly
|*  .*   *|e   next to the paper tape.
|*  .*   *|e   Yes, that's it! This file is a complete papertape
|*  .    *|e   font file, containing (until now) the letters a and e.

Specification of Paper Tape files

This is a typical paper tape file:

---- Start of example file ----
The Paper Tape Project -- PAPERTAPE_FONT file.
The content of this file describes a paper tape font...
See this small key how the document is structured:
 bits     |identification
 123.45678|char/string
|   .     |
|+++.+++++|m
|   .   + |m
|   .  +  |m    this is a comment.
|   .   + |m
|+++.+++++|m
|+  .    +|I
|+++.+++++|I
|+  .    +|I
|   .     |
|   .     |
|   .     |
|   .     |
|+++.+++++|0
  Comments can be typed
right anywhere, everything that doesn't look like
a paper tape on the right place, is ignored.
  |+  .   ++| <- even this one.
|+  .    +|0
|+++.+++++|0
|   .     |
|   .     | =white_space    this is a comment, too.
|   .     | =white_space
|   .     |

----  End of example file  ----

As you see, paper tape files are quite funny ASCII files. Here are the rules you have to observe:

Specification of the papertapefont.h library

I've developed a tiny stand alone C library which does not need auxillary libraries like Glib and which will compile at windows, too. It's quite simple to use that library. At first, there even exists a command line interface that implements most of the features. But here's how to use the C functions:

The main "object like" structure is the PAPERTAPE_FONT structure. It can be built directly by parsing an already opened file:

    #include <stdio.h>
    #include "papertapefont.h"

    FILE* font_file = fopen("/path/to/your/font.file", "r");
    PAPERTAPE_FONT* font = papertape_font_new_from_file(font_file);

Now the file has been parsed and every available letter is stored in RAM. So you can directly go and generate labels:

    int label_size;
    byte_t* label_bytes;

    label_bytes = papertape_font_get_label(font,
                  "Hello World!", &label_size);

    // further use, e.g. with LOCHSTREIFEN*:
    LOCHSTREIFEN* papertape = lochstreifen_new();
    lochstreifen_set_data(label_bytes, label_size);

Of course you can check if your string can be fully generated, too:

    if(! papertape_font_string_is_printable(font, "{H4x05]!")) {
        printf("Sorry dude, the current font is not"
               "script kiddie compatible.\n");
    }

And after all, changing the papertape is fully implemented:

    bytes_t* user_generated;
    int len;

    let_user_generate_letter("Please make an 'A'",
      &user_generated, &len);

    papertape_font_set_char(font, 'A', user_generated, len);

This will change the letter immediately. So the following output will give out "ABBA" on the papertape at the end (and not "ABAB"):

    bytes_t* output, buf_for_a, buf_for_b;
    int      o_len,  a_len,     b_len;

    // print out "ab" on papertape
    output = papertape_font_get_label(font, "ab", &o_len);
    send_to_papertape_puncher(output, o_len);

    // flip a and b
    buf_for_a = papertape_font_get_label(font, "a", &a_len);
    buf_for_b = papertape_font_get_label(font, "b", &b_len);
    papertape_font_set_char(font, 'B', buf_for_a, a_len);
    papertape_font_set_char(font, 'A', buf_for_b, b_len);

    // print out "ab" on papertape...
    output = papertape_font_get_label(font, "ab", &o_len);
    send_to_papertape_puncher(output, o_len);

If you feel destructive, you can also delete characters:

    // clean up all the mess by deleting everything!!111
    papertape_font_del_char(font, 'a');
    papertape_font_del_char(font, 'b');
    if(!papertape_font_del_char(font, 'b'))
        printf("There is no more 'b'. Of course!");
    output = papertape_font_get_label(font, "abba", &len);
    // this will give out 4 errors at stderr, because
    // no character can be generated.

At last, after messing around you can save the whole changed thing (back) to a file.

    FILE* target = fopen("/existing/or/new.font.txt", "w");
    papertape_font_write_to_file(font, target);

Be aware that the following example will stripe out *ALL* comments out of your font file:

    FILE* needs_cleanup = fopen("font.txt", "r+");
    PAPERTAPE_FONT* font = papertape_font_new_from_file(needs_cleanup);
    papertape_font_write_to_file(font, needs_cleanup);

In the end, an issue that is a bit more complicated: Special characters. This includes white spaces, letter spacing, etc. The names for these special characters are noted in the papertapefont.h header file, so you can access them directly, too, if you want:

    byte_t *white = calloc(sizeof(byte_t), 100);
    papertape_font_set_special(font, PAPERTAPE_FONT_SPACE_NAME,
      white, 100);
    // about 1k of bytes:
    papertape_font_get_label(font, "A fairly long text ! ! ! ", &somewhere)
    // deletion sets the space to some kind of default value
    papertape_font_del_special(font, PAPERTAPE_FONT_SPACE_NAME);
    // so this is quite short:
    papertape_font_get_label(font, "  s h o r t  ", &somewhere);

I think that's all, for the moment. Happy coding :-)

-- Sven Köppel, 04.09.2008