#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <libps/pslib.h>
#ifdef MEMORY_DEBUGGING
#include <libps/pslib-mp.h>
#endif

void errorhandler(PSDoc *p, int error, const char *str, void *data) {
	fprintf(stderr, "PSLib: %s\n", str);
}

int main() {
	PSDoc *psdoc;
	int fraktur, antiqua;
	float boxwidth, boxheight, baseline, colsep, leftmargin;
	float fontsize;
	int boxed, line;

	boxwidth = 100;
	boxheight = 630;
	baseline = 100;
	colsep = 20;
	leftmargin = 100;
	boxed = 0;
	fontsize = 10.0;

	PS_boot();
#ifdef MEMORY_DEBUGGING
	PS_mp_init();
#endif

#ifdef MEMORY_DEBUGGING
	psdoc = PS_new2(errorhandler, PS_mp_malloc, PS_mp_realloc, PS_mp_free, NULL);
#else
	psdoc = PS_new();
#endif
	PS_open_file(psdoc, "ligatures.ps");
	PS_set_info(psdoc, "Creator", __FILE__);
	PS_set_info(psdoc, "Author", "Uwe Steinmann");
	PS_set_info(psdoc, "Title", "Ligaturs");
	PS_set_info(psdoc, "Keywords", "Font, Ligatures");
	PS_set_info(psdoc, "BoundingBox", "0 0 596 842");

	fraktur = PS_findfont(psdoc, "AlteSchwabacher", "AlteSchwabacher.enc", 1);
//	fraktur = PS_findfont(psdoc, "AlteSchwabacher", "", 1);
	antiqua = PS_findfont(psdoc, "Helvetica", "", 0);

	PS_begin_page(psdoc, 596, 842);

	PS_setfont(psdoc, antiqua, 10.0);
	PS_set_value(psdoc, "leading", 15.0);
	PS_show_boxed(psdoc, "pslib supports ligatures if the used font contains any. The most common ligatures are fi, ff, and fl, which are available in many fonts. Sometimes also ffi and ffl exist. Those ligatures are recognized by pslib automatically, even if they are not declared as a ligature in the fonts afm file. Old german fonts like Fraktur or Schwabacher provide much more ligatures which are quite often available under very misleading glyph names. The font AlteSchwabacher used in this document has a sch-Ligature named as 'logicalnot'. Accessing these ligatures requires some manual intervention. In order to understand what needs to be done for using such ligatures, one should first understand how pslib checks for ligatures. pslib checks for each character if it forms a ligature with the following character. If that is the case it will further check if this ligature forms a ligature with next character. It does it until no more ligatures are found. If the current char and the next char do not form a ligature, pslib will check if the next char and the one following the next char form a ligature. If that is the case, it will check again for the current char and the just found ligature. This sounds very complicated but it provides great flexibility in defining ligatures. The definition of new ligatures is done in the encoding file (see AlteSchwabacher.enc for examples). Each definition specifies two glyph names constructing the ligature and the glyph name of the ligature. The glyph name of the ligature is the name as it is used in the afm file. In the case of the ligature sch it would be 'logicalnot'. A formerly defined ligature can be used in the following ligature definition. This is required if a ligature is made of more than two characters like the sch ligature. One has to define first the ch ligature and than the sch ligature. If a ligature is defined but the font does not contain the appropriate glyph, then it will be automatically disolved and a warning is issued.", leftmargin, 400, 400, 380, "left", NULL);

	PS_setfont(psdoc, antiqua, 15.0);
	line = 15;
	PS_show_xy(psdoc, "Ligatures found in Alte Schwabacher", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "f¦i Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "f¦l Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "f¦t Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "f¦f Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "ch Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "ck Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "ll Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "tt Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "tz Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "sch Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "si Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "st Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "ss Ligature", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "Long s", leftmargin, baseline+line--*20);
	PS_show_xy(psdoc, "Round s", leftmargin, baseline+line--*20);

	PS_setfont(psdoc, fraktur, 15.0);
	line = 14;
	PS_show_xy(psdoc, "fi (f¦i)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "fl (f¦l)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ft (f¦t)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ff (f¦f)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ch (c¦h)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ck (c¦k)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ll (l¦l)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "tt (t¦t)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "tz (t¦z)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "sch (s¦c¦h)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "si (:s¦i)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "st (:s¦t)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "ss (:s¦:s)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, ":s (:¦s)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_show_xy(psdoc, "s (s)", leftmargin+boxwidth+colsep, baseline+line--*20);
	PS_end_page(psdoc);

	PS_deletefont(psdoc, fraktur);
	PS_deletefont(psdoc, antiqua);
	PS_close(psdoc);
	PS_delete(psdoc);
#ifdef MEMORY_DEBUGGING 
	PS_mp_list_unfreed();
#endif  
	PS_shutdown();
	exit(0);
}
