/*
 *  File:    CompositeCalligraphy.cpp
 *  Author:  S Harry White
 *  Created: 2014-07-07
 *  Updated: 2021-12-22
 *    Tidy code.
 *  Updated: 2022-07-26
 *    Change sizeof(int) to sizeof(bool) in allocateBoolSquare
 *  Updated: 2023-01-27
 *    Change to compile with g++ for macOS.
 */

/*
 *  Makes a composite square of order m*n from character squares of order m and a square of order n.
 *  The order m magic squares show the characters as retained water. 
 *  Uppercase letter, number, and space squares created by Craig Knecht, are contained in this file. 
 *  The other keyboard characters, (except lowercase letters), have been added.
 */

//#include <ctype.h>
#include <curses.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
//#include <sys/types.h>
#include <time.h>
#include <unistd.h>

typedef unsigned int Uint;
const bool F=false, T=true;
#define max(a,b) (((a)>(b))?(a):(b))
//============================== characters start  =================================

const int fontN=11, fontNN=fontN*fontN, ASCIItableSize=128;
typedef char t_chSquare[fontNN-fontN-fontN];
typedef char *t_chPtr[ASCIItableSize]; typedef char t_chRot[ASCIItableSize];

t_chSquare // Character squares that drain left.
spL={
59,40,41,97,48,46,86,121,50,3,33,85,111,60,44,89,54,66,99,75,76,106,37,38,39,
43,52,63,116,83,74,79,36,61,42,64,53,56,98,1,4,32,35,115,112,95,117,113,23,84,
5,6,108,55,58,73,101,71,22,110,105,7,8,51,104,107,19,20,21,91,82,62,9,65,57,
72,18,45,70,94,109,93,10,11,12,13,17,78,114,2,47,68,102,80,67,14,103,81,30
},
exL={
88,115,15,16,17,31,73,74,83,87,13,14,113,18,19,49,84,105,91,11,12,117,45,96,20,
21,93,104,114,75,90,111,40,55,65,22,52,67,57,118,119,120,41,51,89,23,24,25,26,
95,112,116,42,47,50,70,44,32,27,102,101,46,43,53,63,64,66,71,28,6,8,9,107,103,
100,110,61,30,29,85,94,106,4,62,60,58,56,33,54,3,5,7,121,92,98,109,48,39,68
},
dqL={
62,79,63,51,64,52,81,58,57,108,96,98,37,24,33,23,82,75,47,119,27,31,32,22,116,
25,114,86,46,3,26,29,103,34,113,121,97,44,45,88,36,92,85,35,80,50,42,43,61,
95,100,66,65,38,39,40,41,54,73,4,5,6,7,107,20,118,104,76,109,99,93,28,8,9,10,
111,83,69,89,2,105,68,87,117,11,12,21,67,110,1,30,112,102,120,106,13,14,84,19
},
otL={
98,102,16,17,18,19,75,72,74,117,92,14,15,118,22,84,46,45,48,3,6,12,106,59,103,
56,83,43,105,2,97,114,71,50,85,65,68,41,40,5,107,120,66,55,47,49,64,82,39,4,
11,13,110,58,77,60,93,100,109,112,94,115,51,57,1,53,42,67,44,7,8,121,90,52,
108,63,69,87,32,111,9,10,101,61,88,62,79,30,31,113,54,20,21,119,96,78,28,29,33
},
doL={
101,117,13,14,16,19,21,103,92,94,8,10,17,18,116,106,91,69,66,3,7,23,100,115,
59,90,78,64,65,2,109,108,105,29,50,32,4,62,84,5,93,85,1,98,55,70,96,49,48,53,
97,82,111,15,60,20,89,47,46,73,74,75,110,81,57,63,6,45,44,120,12,99,39,40,52,
22,79,95,72,9,11,68,121,118,61,114,58,36,37,104,24,25,26,113,112,102,34,35,42
},
pcL={
1,2,86,114,103,16,84,98,26,101,115,90,113,14,15,17,18,19,100,76,108,13,10,9,
85,107,97,49,52,121,7,12,11,8,116,112,20,105,72,5,6,73,93,119,92,23,94,55,54,
3,82,68,88,95,24,74,70,63,53,4,25,62,75,22,104,110,89,64,66,109,27,28,21,120,
102,31,34,91,60,96,83,111,29,30,36,32,33,118,56,77,117,67,58,71,37,38,39,40,81
},
amL={
83,64,8,9,18,96,75,107,88,5,6,7,105,19,121,73,109,117,56,15,79,60,102,12,20,29,
119,101,87,72,95,106,22,114,10,59,58,44,45,113,97,82,21,115,11,23,25,30,103,
70,112,89,77,17,71,99,38,31,33,110,84,67,32,90,14,94,16,37,35,85,63,61,36,57,
118,24,39,62,52,13,66,76,91,28,26,50,27,78,100,1,2,111,108,120,86,65,40,41,48
},
cqL={
76,71,59,66,77,51,52,57,58,120,99,34,24,25,37,70,87,80,47,102,31,32,26,27,85,
95,93,81,46,3,29,33,116,23,118,100,104,44,45,112,36,107,22,35,98,50,42,43,62,
86,82,79,88,38,39,40,41,54,61,4,5,6,7,119,20,89,114,84,117,96,113,28,8,9,10,
90,83,68,92,2,103,75,105,94,11,12,21,65,110,1,30,121,108,109,111,13,14,78,19
},
opL={
7,76,94,121,82,25,26,27,28,8,56,85,115,88,24,105,59,29,30,120,79,78,117,22,
23,77,39,53,31,102,75,63,69,21,90,40,66,62,50,107,60,57,96,20,101,41,65,52,38,
103,95,55,18,19,100,42,70,67,54,108,9,15,16,84,91,43,104,89,61,3,4,10,80,106,
109,44,71,112,64,110,99,11,12,114,37,45,6,83,73,2,113,87,13,98,36,97,46,47,58
},
cpL={
31,119,15,16,17,18,93,69,105,120,13,14,76,78,19,49,66,80,85,11,12,121,39,95,
20,21,79,103,100,98,90,114,58,40,59,22,52,63,38,115,113,117,75,41,77,23,24,25,
26,96,101,112,61,42,50,60,54,32,27,108,109,45,46,43,64,65,62,67,28,6,8,9,118,
44,116,111,94,30,29,82,99,107,4,74,57,56,55,33,51,3,5,7,97,110,102,88,48,47,92
},
asL={
120,112,74,23,24,25,26,27,64,102,20,21,22,101,92,96,28,29,89,1,8,107,118,2,
119,3,105,35,103,57,56,66,99,98,7,86,91,36,37,113,116,93,34,33,32,31,30,90,39,
78,88,63,62,97,6,73,61,55,40,10,117,83,106,4,110,5,58,94,41,9,75,68,104,79,77,
69,54,50,42,49,52,67,72,100,76,59,53,51,47,11,12,13,14,115,108,109,80,82,81
},
plL={
96,110,117,20,21,22,23,24,82,113,75,18,19,67,121,71,25,26,55,1,2,17,116,74,
118,68,89,27,79,107,15,16,102,85,40,48,34,28,106,76,93,94,92,52,41,73,56,29,
30,86,103,114,47,46,13,45,44,83,31,4,88,108,95,78,42,50,70,65,32,3,112,101,98,
72,43,53,54,66,33,61,58,69,63,64,97,62,60,51,49,5,6,7,8,100,120,87,111,105,84
},
cmL={
57,95,80,118,81,21,28,29,36,4,5,6,7,121,20,116,120,109,58,35,99,39,8,9,10,101,
103,88,89,56,98,77,84,113,11,12,30,50,71,1,2,75,119,104,114,13,14,96,68,97,82,
76,117,87,91,55,15,16,17,107,83,78,24,25,37,70,85,32,111,93,33,34,26,27,110,
94,67,66,61,3,31,92,38,23,115,86,102,59,49,106,64,51,22,40,100,53,62,74,47
},
miL={
70,101,119,20,21,22,23,24,92,118,87,18,19,97,86,34,25,26,84,1,2,17,120,100,90,
79,73,27,91,107,15,16,80,82,75,78,68,28,57,55,76,106,113,59,54,53,44,29,30,98,
109,121,40,41,42,13,43,50,31,4,89,114,110,51,45,46,67,74,32,3,96,108,103,49,
56,60,61,66,33,93,81,35,47,48,72,64,69,63,62,5,6,7,8,111,115,116,95,112,58
},
dtL={
95,83,70,81,118,21,22,23,28,4,5,6,7,114,20,108,113,107,68,115,93,48,8,9,10,
100,75,65,60,63,85,62,73,98,11,12,66,89,59,1,2,111,102,94,117,13,14,87,101,76,
71,84,112,67,105,90,15,16,17,30,31,32,96,38,104,64,106,82,69,121,109,33,24,25,
34,35,36,37,97,3,57,78,26,27,116,110,99,54,49,77,56,55,39,40,91,74,80,61,47
},
fsL={
120,69,73,27,15,16,17,18,118,1,2,94,108,14,89,112,19,57,87,103,65,72,12,13,41,
49,25,96,105,62,113,10,11,85,70,71,21,28,117,76,8,9,121,114,82,22,102,29,30,
111,7,26,86,115,24,104,92,35,31,5,6,110,79,23,75,74,109,119,32,4,80,84,20,107,
101,64,97,45,33,3,106,67,81,77,63,56,93,54,34,91,116,60,58,53,51,50,47,46,61
},
n0L={
89,50,15,16,17,59,60,96,107,10,13,14,92,21,72,81,109,67,121,118,52,85,116,18,
19,20,28,65,103,1,95,82,41,119,62,108,22,61,34,4,102,94,40,110,73,27,23,66,33,
111,76,75,39,74,42,101,24,48,32,3,105,90,38,44,117,58,25,63,31,113,84,78,37,98,
88,45,26,29,30,106,80,115,104,6,7,8,120,54,35,2,5,11,91,87,64,93,112,55,100
},
n1L={
63,93,78,75,14,15,16,110,103,116,96,113,10,13,115,17,18,37,38,4,6,7,8,117,43,
112,19,120,121,86,80,88,52,3,44,62,20,95,90,102,92,99,73,61,45,66,21,22,40,34,
35,36,76,77,46,69,107,23,101,84,87,53,60,71,47,56,106,24,25,2,79,83,64,74,48,
59,97,82,26,94,89,91,72,42,49,41,108,30,27,1,5,11,111,118,119,105,32,31,109
},
n2L={
84,115,83,18,19,20,21,22,106,120,14,16,17,86,54,119,23,24,109,6,13,99,112,35,
34,33,121,25,111,104,117,69,1,59,79,78,26,27,55,3,15,97,102,94,113,110,7,28,
29,72,108,76,70,60,9,8,90,80,30,4,81,58,64,51,53,98,103,66,31,95,88,57,45,52,
63,61,75,67,32,74,105,93,41,42,43,44,40,87,65,2,5,12,101,77,85,50,116,114,71
},
n3L={
101,3,4,5,118,72,43,53,85,1,2,99,60,91,77,42,76,87,102,93,100,75,113,10,13,14,
41,115,64,61,111,51,28,74,109,120,24,30,31,48,49,50,119,83,114,29,25,56,63,55,
78,65,73,88,22,21,103,59,71,58,68,81,106,94,23,96,26,44,38,66,121,79,17,70,
20,108,27,57,39,110,116,90,52,6,7,8,105,45,40,9,11,62,82,19,97,86,84,46,80
},
n4L={
103,5,6,7,8,72,119,48,88,1,2,98,111,110,89,120,47,32,31,60,70,80,71,64,33,40,
49,58,117,50,51,52,53,34,105,41,67,74,116,57,69,86,35,113,59,42,82,75,26,85,
108,97,36,37,38,43,39,76,25,3,4,9,118,104,90,44,106,78,24,73,107,10,11,79,62,
45,100,93,23,77,109,84,12,13,92,46,96,21,22,101,81,83,115,14,15,114,19,20,54
},
n5L={
114,3,4,120,104,48,117,29,28,1,2,76,103,86,47,69,105,95,26,101,84,96,39,40,41,
42,43,100,25,72,78,99,6,62,92,91,68,23,24,44,45,46,7,71,119,74,102,22,83,67,
85,88,38,37,36,35,93,21,108,5,8,9,121,79,118,112,11,20,106,81,90,10,18,115,64,
19,12,110,98,107,109,57,17,16,15,14,94,116,73,13,70,75,89,30,59,65,80,87,51
},
n6L={
49,50,56,90,119,41,39,32,31,9,54,68,110,121,43,97,82,30,29,73,100,57,91,12,13,
14,113,67,104,79,69,55,33,120,84,44,20,65,76,37,74,61,7,98,75,95,103,72,24,58,
66,88,38,10,36,35,96,106,23,63,71,59,34,117,70,83,17,21,22,109,105,64,40,42,
99,19,16,86,45,108,77,78,111,6,15,11,51,60,107,1,2,81,112,18,94,118,52,53,92
},
n7L={
86,10,11,95,47,84,99,80,54,2,5,12,66,46,109,103,113,92,81,119,75,101,36,35,
34,33,32,67,98,93,79,87,1,82,104,72,31,43,39,3,58,102,70,94,117,44,8,68,38,4,
48,49,74,83,45,9,116,110,37,111,85,105,51,50,6,73,78,27,28,29,90,61,88,76,7,77,
106,26,55,13,14,15,114,121,30,118,24,25,108,120,107,16,17,18,115,22,23,97,71
},
n8L={
58,57,8,9,18,79,94,121,74,5,6,7,118,19,106,120,116,64,63,83,67,82,109,13,11,
12,103,76,69,107,84,102,22,95,73,23,10,66,44,52,114,85,21,92,80,72,20,25,29,97,
90,62,113,17,16,15,56,98,30,59,61,53,32,117,115,119,14,37,31,54,86,65,36,70,
68,38,24,88,108,55,101,104,50,28,26,27,96,60,89,1,2,99,110,111,48,39,40,41,87
},
n9L={
53,54,55,58,89,44,88,67,49,2,57,56,59,96,43,108,83,48,74,86,80,79,90,11,15,6,
110,47,115,39,113,77,16,114,75,42,40,46,78,68,92,65,17,73,76,118,34,69,29,112,
52,62,105,35,36,10,38,94,28,8,9,37,84,120,91,106,7,97,27,109,60,70,20,82,93,
41,33,71,26,98,101,102,100,14,13,12,121,24,25,95,50,64,117,19,81,21,22,23,107
},
clL={
56,88,63,106,79,34,45,46,50,85,72,7,8,9,10,102,96,109,103,82,5,6,120,110,11,
12,68,75,111,3,4,38,78,108,93,13,62,97,101,86,114,113,22,23,84,14,15,52,61,80,
116,91,25,24,99,98,16,17,48,1,2,117,121,81,104,73,69,18,19,118,35,40,27,26,107,
119,92,54,20,94,115,90,28,29,42,89,100,32,21,36,37,39,41,105,43,59,58,112,76
},
scL={
59,77,61,94,101,34,45,46,50,100,91,7,8,9,10,83,90,116,86,73,5,6,118,120,11,12,
68,88,96,3,4,103,22,23,119,13,87,104,98,105,114,82,25,24,81,14,15,52,97,1,2,
93,115,113,107,102,16,17,48,99,35,40,27,26,111,121,109,18,19,72,106,110,28,29,
69,80,70,54,20,67,108,89,112,30,42,76,63,32,21,36,37,39,38,117,43,78,58,85,75
},
oaL={
36,9,11,35,46,55,110,77,105,1,5,12,59,103,76,107,70,101,64,47,45,80,62,63,79,
53,37,54,56,48,60,61,65,78,68,38,50,86,84,88,91,102,74,83,39,52,49,30,31,2,3,
4,116,40,87,121,34,29,120,119,118,6,7,51,41,57,113,28,27,96,97,111,8,10,85,
42,71,100,26,98,89,75,44,13,14,58,43,99,114,69,82,117,108,90,15,16,109,20,22
},
eqL={
97,114,111,20,21,22,23,24,66,108,67,18,19,100,78,81,25,26,90,1,2,17,119,83,82,
79,98,27,105,110,15,16,95,92,72,68,89,28,29,93,112,120,40,44,42,13,43,99,30,
71,80,86,113,51,54,52,50,49,31,4,116,117,41,14,39,45,38,118,32,3,76,96,121,87,
55,70,48,46,33,64,74,73,84,61,60,62,56,47,53,5,6,7,8,106,102,103,109,77,63
},
caL={
74,116,15,16,17,18,90,68,77,113,13,14,48,92,19,58,59,72,105,11,12,114,37,100,
20,21,82,87,112,111,96,103,66,38,84,22,23,65,31,102,115,106,93,56,39,50,24,25,
26,88,121,91,71,55,52,40,46,44,27,76,110,109,63,49,41,47,60,54,28,6,8,9,117,42,
119,118,85,30,29,86,73,99,43,61,70,51,45,33,53,3,5,7,107,94,89,79,81,80,62
},
quL={
2,9,11,107,81,119,101,85,51,1,92,12,13,17,104,111,103,50,86,120,112,33,100,14,
15,4,36,49,121,108,90,62,16,18,80,87,31,48,77,5,109,94,10,106,115,59,35,47,46,
110,98,78,19,20,69,34,71,60,68,105,23,79,84,22,21,76,83,72,63,116,8,55,56,89,
25,114,64,61,41,6,7,93,57,117,24,30,102,99,40,3,58,88,118,113,26,27,32,97,39
},
atL={
93,13,14,26,27,119,50,92,83,11,12,74,109,28,120,30,98,66,62,15,108,80,118,8,10,
9,100,82,81,110,115,87,31,79,1,29,7,88,67,114,91,78,32,95,2,116,6,38,48,111,
103,52,33,106,3,4,5,94,85,16,17,70,24,121,104,117,34,35,69,76,23,36,25,37,105,
99,107,41,59,58,97,101,112,21,22,20,102,42,43,18,19,39,90,77,96,113,65,56,44
},
lAL={
102,114,118,121,19,20,21,22,23,100,92,16,17,18,70,89,101,24,84,108,81,15,116,
77,7,87,62,25,39,110,13,14,74,6,106,8,112,85,40,4,10,41,35,69,104,94,34,93,107,
73,88,120,29,36,37,38,30,76,78,3,65,111,28,113,75,91,31,63,45,97,95,96,27,67,
48,47,32,68,44,71,99,117,26,61,49,79,33,42,43,2,5,12,115,119,57,58,105,82,64
},
lBL={
1,4,5,120,79,81,85,99,59,2,11,12,118,73,83,82,101,57,64,95,116,114,45,6,7,
8,100,53,58,77,113,63,39,72,80,51,13,52,55,3,32,84,43,105,88,89,33,50,70,90,
117,86,42,9,25,19,98,49,61,66,112,60,41,78,54,93,34,48,47,10,14,110,40,109,87,
91,35,71,67,108,15,102,44,24,46,21,103,107,65,104,16,17,119,94,97,106,28,29,30
},
lCL={
1,5,6,114,82,72,75,78,60,110,85,9,88,62,49,77,46,47,48,101,93,89,90,22,21,
20,45,84,55,3,4,107,27,104,92,106,7,95,74,108,102,86,26,38,37,36,44,63,65,119,
81,71,25,76,112,35,34,33,43,91,68,64,24,113,54,67,79,32,39,115,105,94,23,98,53,
30,8,31,73,11,12,116,118,19,18,17,121,87,96,10,13,14,120,29,80,111,109,70,58
},
lDL={
15,9,11,112,72,74,93,95,61,2,5,12,117,49,94,109,108,60,64,101,84,82,46,23,22,
79,88,54,53,3,17,98,45,91,92,18,83,70,116,105,107,86,44,69,65,59,1,62,36,104,
100,67,43,50,55,87,16,48,35,102,97,85,42,57,73,63,4,56,34,6,7,113,41,96,99,
19,114,75,33,119,120,90,40,25,24,89,30,31,32,8,10,13,121,118,47,28,29,76,111
},
lEL={
71,24,22,115,67,55,56,84,51,3,14,19,121,98,54,82,100,50,52,114,116,108,31,13,5,
7,23,49,96,75,110,89,30,72,92,65,33,34,35,1,15,32,29,74,105,106,107,95,70,104,
117,103,28,9,17,47,48,91,69,2,18,83,27,97,101,81,102,64,57,85,111,62,26,61,66,
60,77,42,41,113,118,112,25,11,6,8,10,87,88,4,12,20,120,90,94,86,43,63,59
},
lFL={
1,4,11,117,87,86,114,60,62,2,5,12,121,97,64,102,48,68,72,110,118,95,45,6,7,
8,35,69,84,3,13,107,44,90,119,103,46,33,32,75,82,58,43,98,65,78,54,53,31,106,
108,71,42,9,10,92,83,73,30,91,112,101,41,67,113,26,27,28,29,57,93,70,40,61,77,
25,100,55,56,14,15,111,39,115,23,24,79,104,109,116,16,17,120,21,22,49,88,74,89
},
lGL={
1,4,5,111,76,77,79,103,73,2,11,12,115,69,74,82,106,72,70,87,108,96,88,6,7,
8,90,56,68,33,112,67,39,62,71,53,50,51,78,3,40,52,32,118,91,81,114,48,47,101,
119,75,42,54,46,29,9,66,86,97,109,64,41,61,60,102,13,49,37,10,15,98,43,89,99,
92,14,95,36,117,16,84,121,30,31,28,35,110,34,116,17,18,19,85,93,94,113,26,27
},
lHL={
111,115,13,14,16,19,21,110,68,102,8,10,117,17,18,101,112,51,47,3,7,113,59,114,
54,99,56,77,46,2,96,75,50,87,95,74,36,65,49,5,91,73,55,103,83,85,20,67,48,100,
119,105,60,4,1,6,58,80,98,44,81,64,57,79,76,70,53,63,45,9,11,93,52,106,108,
84,15,66,89,71,12,78,61,92,82,72,62,69,35,120,22,23,121,27,28,29,118,33,34
},
lIL={
100,116,110,20,21,22,23,24,72,112,74,18,19,70,114,87,25,26,60,119,115,17,69,7,
39,6,101,27,88,14,15,16,64,92,40,117,108,28,93,105,95,76,56,48,41,104,34,29,
30,4,46,118,73,98,42,47,35,99,31,102,77,75,57,49,43,65,54,62,32,3,13,111,86,85,
44,113,68,79,33,109,106,107,58,10,45,8,67,63,61,2,5,12,80,94,120,50,103,96,71
},
lJL={
86,96,77,72,68,65,28,29,37,3,58,83,110,91,26,27,103,61,39,6,7,101,57,115,25,
98,30,102,40,120,8,55,56,106,24,95,31,93,41,118,23,84,107,21,22,79,32,62,80,117,
81,60,19,20,74,66,34,71,85,5,111,92,10,112,109,59,35,47,46,100,94,63,16,18,105,
64,36,48,73,113,76,33,97,14,15,4,104,49,99,1,108,12,13,17,119,69,116,50,78
},
lKL={
66,9,11,109,55,57,75,82,69,2,5,12,120,53,81,96,116,95,61,1,121,94,48,52,80,103,
37,78,28,77,108,79,47,60,58,38,51,54,27,105,104,98,46,56,39,50,33,25,26,101,
63,84,45,41,62,85,34,24,59,35,36,49,44,65,40,74,107,23,88,112,100,111,43,87,
106,18,20,21,22,3,4,118,42,113,119,19,17,90,114,102,6,7,117,76,15,16,83,99,86
},
lLL={
92,105,18,19,20,89,50,51,52,109,16,17,118,21,22,49,95,74,81,14,15,85,39,112,23,
24,115,106,100,98,88,71,40,58,67,25,84,35,68,120,113,101,41,60,90,26,27,28,29,
4,104,82,42,47,56,93,80,78,30,111,87,57,43,59,70,72,54,53,31,3,13,107,44,103,
97,114,46,33,32,117,116,110,45,6,7,8,10,73,96,2,5,12,121,94,64,108,48,77,65
},
lML={
1,5,8,111,62,86,61,118,60,2,100,9,117,55,78,53,116,51,50,24,105,93,47,54,90,
52,31,87,49,110,104,89,46,3,108,4,30,74,65,92,97,83,45,80,22,94,29,58,35,103,
113,101,44,88,23,67,28,33,34,6,7,48,43,114,109,99,27,66,71,107,10,96,42,98,21,
32,26,70,84,112,11,115,41,82,20,69,25,56,64,102,13,14,119,18,19,63,121,57,72
},
lNL={
117,111,12,13,14,16,18,112,51,102,10,11,118,70,17,78,113,48,46,3,7,114,59,96,
87,91,56,66,45,2,100,74,61,72,88,85,36,67,44,5,110,86,55,19,94,89,20,69,83,
107,93,75,60,84,9,77,15,68,43,1,101,99,57,76,81,21,53,64,79,4,6,82,52,95,97,
90,62,65,80,104,8,71,50,92,49,63,54,108,35,120,22,23,121,27,28,29,119,33,34
},
lOL={
101,53,15,16,17,52,76,87,49,10,13,14,64,21,102,119,106,48,94,120,104,67,98,18,
19,20,27,47,108,121,93,95,41,45,55,78,22,46,33,4,86,103,40,69,68,81,23,83,32,
107,62,61,39,75,77,74,24,58,31,3,71,73,38,113,100,70,25,57,30,85,79,115,37,
109,65,44,26,28,29,117,96,105,90,6,7,8,114,59,34,2,5,11,97,88,60,50,118,112,92
},
lPL={
1,4,11,118,79,87,102,91,56,2,5,12,119,78,98,86,89,55,62,116,111,117,45,6,7,
8,53,54,71,3,13,47,44,88,101,112,35,66,68,93,61,74,43,95,81,77,10,57,32,113,
109,90,42,9,31,46,75,59,30,72,107,84,41,73,82,92,27,28,29,34,120,97,40,103,33,
25,26,76,80,14,15,104,39,99,23,24,114,105,96,108,16,17,121,21,22,49,100,63,85
},
lQL={
23,51,57,58,69,60,50,96,49,114,82,77,101,61,75,22,24,25,26,85,83,90,107,6,7,8,
116,76,37,121,112,63,15,21,79,35,34,80,38,4,10,87,16,52,111,118,33,98,39,115,
14,20,17,89,105,117,32,81,40,99,102,62,18,108,13,70,30,53,74,3,109,106,19,88,
72,27,36,68,100,104,94,86,97,28,29,45,31,46,67,1,5,11,113,78,55,95,119,47,93
},
lRL={
1,4,5,119,86,74,76,100,54,2,11,12,118,85,52,81,104,53,88,109,121,117,45,6,7,
8,48,51,96,75,113,66,39,78,84,72,13,47,46,3,32,90,43,108,92,99,33,57,77,97,114,
89,42,9,25,19,102,70,68,71,116,60,41,64,62,101,26,61,34,10,14,103,40,105,112,
106,27,30,31,95,15,94,44,87,73,29,28,107,49,110,16,17,120,22,23,24,111,82,55
},
lSL={
6,7,9,13,73,105,95,107,50,72,100,66,14,59,54,70,84,49,51,111,113,116,17,12,11,
10,18,48,121,99,96,101,16,60,71,103,8,19,20,27,81,82,15,79,56,106,97,85,21,57,
65,63,92,41,42,40,67,69,112,34,46,47,108,76,58,44,36,80,118,83,89,102,53,61,
62,90,37,43,26,64,68,77,104,38,39,35,75,88,28,1,2,3,119,74,86,45,110,109,29
},
lTL={
61,63,53,54,56,80,59,84,65,2,4,17,106,90,115,55,116,73,60,118,110,109,35,3,51,
38,5,67,103,6,7,18,83,102,50,77,112,93,92,74,69,100,68,58,49,57,101,36,29,89,
64,111,79,71,48,52,43,42,28,8,9,10,119,66,47,72,120,98,27,114,104,11,85,88,46,
70,24,25,26,107,105,12,13,81,45,75,23,37,86,1,39,113,14,40,121,96,22,41,76
},
lUL={
79,9,11,109,57,45,59,119,50,2,5,12,117,100,44,107,120,49,83,111,112,40,34,76,
43,86,18,48,72,113,116,93,39,41,42,84,22,33,58,1,110,114,36,77,102,71,21,29,82,
90,87,106,37,67,108,78,20,25,26,3,7,105,38,75,88,61,19,104,74,101,96,69,35,66,
63,24,23,51,52,80,62,92,95,6,4,8,121,85,53,81,54,15,16,17,68,46,118,103,55
},
lVL={
1,5,11,120,118,109,44,45,46,2,9,12,102,83,68,43,117,114,55,103,94,95,34,48,47,
42,35,71,49,3,97,80,30,79,65,85,27,107,41,104,78,72,31,74,54,50,26,86,40,4,
101,90,32,70,61,82,25,108,39,110,84,76,33,58,64,96,24,37,38,6,7,112,89,29,98,
28,121,36,93,113,8,10,87,81,19,91,116,23,63,119,77,13,14,15,69,92,115,22,73
},
lXL={
62,102,93,85,82,57,18,19,20,64,111,88,105,15,16,17,103,63,22,69,109,74,10,14,
68,96,32,110,23,70,118,13,8,117,84,108,31,73,24,100,6,7,51,47,52,46,120,97,119,
3,4,76,95,92,50,86,94,58,80,38,99,89,72,49,60,48,78,43,61,65,106,87,27,81,77,
90,30,37,36,1,2,121,28,53,107,39,29,71,116,101,5,11,115,42,41,40,44,45,114
},
lYL={
116,5,11,84,53,54,64,91,80,1,2,9,99,46,110,76,121,102,67,90,96,44,29,45,94,
63,31,82,60,77,78,95,28,87,68,59,30,58,55,86,66,101,93,26,88,27,112,23,24,3,
47,48,100,43,32,74,118,22,71,83,72,49,50,65,33,70,98,21,61,4,106,111,104,105,
34,89,19,20,39,85,75,81,62,73,35,42,18,108,51,6,7,8,10,115,109,92,17,103,107
},
lZL={
70,5,6,77,73,81,68,110,58,1,2,88,104,60,109,67,39,51,79,108,118,103,8,20,21,
22,23,111,94,3,7,98,113,92,112,99,24,40,41,86,120,87,15,16,19,17,25,90,95,100,
116,13,14,97,18,84,26,27,74,119,11,12,117,52,54,69,105,28,29,9,10,38,36,106,
121,89,115,80,30,93,114,107,35,34,33,32,31,72,76,4,85,62,96,66,50,61,91,65,46
},
obL={
110,69,70,103,82,25,26,27,28,8,58,108,118,23,24,117,105,49,30,91,77,104,109,
22,97,46,39,7,47,95,89,75,35,21,74,40,98,56,55,67,73,68,113,20,78,41,60,63,54,
114,93,59,18,19,48,42,61,79,76,99,9,15,16,119,84,43,50,92,80,3,4,10,120,112,
83,44,57,101,71,81,100,11,12,115,85,45,6,38,90,2,94,65,13,121,37,111,72,51,52
},
cbL={
106,10,11,14,15,19,103,120,98,3,7,97,69,111,20,21,107,79,49,95,96,52,54,59,
86,22,75,45,44,2,121,99,80,56,112,23,24,36,76,4,5,6,105,55,117,109,25,104,100,
94,114,85,64,60,63,58,26,33,34,83,82,68,66,57,70,67,74,32,35,84,101,73,65,62,
72,50,47,31,48,89,118,53,51,61,77,78,29,30,46,1,8,115,90,119,18,27,28,92,71
},
ctL={
65,85,106,108,110,72,17,18,19,80,81,94,78,75,45,16,103,20,22,119,96,73,114,14,
12,15,98,83,23,118,109,64,41,9,79,11,44,60,111,120,115,8,7,13,46,112,10,93,
121,4,5,6,117,104,58,116,89,107,33,43,52,99,59,113,54,42,38,37,34,91,63,69,47,
48,49,77,53,51,61,1,2,87,39,40,101,82,56,66,95,3,28,29,30,90,84,86,92,67,74
},
usL={
101,9,10,11,80,81,82,87,78,5,6,7,8,117,104,108,114,105,59,97,102,35,40,41,68,
63,70,53,65,3,107,110,112,42,61,62,55,50,33,4,34,118,119,43,44,46,100,92,32,
69,94,67,103,60,45,48,49,47,31,73,89,66,106,52,51,57,54,29,30,1,2,16,113,91,
85,93,72,28,99,120,15,17,20,111,95,75,26,27,79,121,98,109,18,12,14,13,19,88,83
},
oqL={
49,107,35,36,37,38,105,73,54,111,33,34,82,79,39,25,24,48,115,30,31,88,90,99,
104,27,26,40,41,86,32,87,58,59,60,23,116,62,42,78,92,71,53,57,64,100,22,47,43,
89,29,91,52,51,56,84,69,50,55,4,5,6,7,21,97,102,119,113,101,109,121,20,8,9,10,
106,83,67,68,2,120,28,94,80,11,12,110,66,63,1,3,118,114,103,117,13,14,108,61
},
ocL={
7,99,100,101,92,25,26,27,28,8,46,115,120,23,24,91,116,29,30,103,72,76,87,22,
85,63,39,61,31,107,77,74,82,21,78,40,56,53,50,117,75,70,19,20,96,41,71,90,38,
97,81,67,18,79,42,62,59,58,57,118,9,15,16,95,104,43,86,73,60,3,4,10,113,110,
109,44,66,93,65,108,84,11,88,80,37,45,6,89,68,2,119,12,13,112,36,105,47,48,94
},
vbL={
95,3,4,5,7,121,91,104,102,1,2,119,6,8,120,79,89,99,67,92,103,85,16,98,45,48,
53,57,35,78,96,87,75,68,40,50,51,54,34,9,100,109,118,71,41,49,73,32,33,10,12,
111,116,93,42,60,83,31,76,11,13,14,15,107,46,94,112,30,115,110,105,17,82,86,
43,47,28,29,61,80,84,18,101,90,44,52,27,55,58,113,56,19,20,21,106,77,26,108,59
},
ccL={
31,119,15,16,17,18,90,79,105,120,13,14,82,70,19,49,63,72,93,11,12,118,39,91,20,
21,80,107,97,88,100,111,59,40,58,22,52,66,38,116,114,117,77,41,73,23,24,25,26,
92,101,113,60,57,42,61,50,32,27,109,110,45,46,43,68,65,54,69,28,6,8,9,115,44,
121,108,99,30,29,94,87,112,4,64,62,56,55,33,51,3,5,7,89,106,104,95,48,47,96
},
tiL={
98,117,116,20,21,22,23,24,71,111,94,18,19,83,88,34,25,26,72,1,2,17,118,97,76,
106,69,27,68,93,15,16,80,73,67,75,62,28,107,78,79,104,99,41,57,59,44,29,30,
70,92,113,40,74,42,45,43,63,31,4,89,121,120,65,46,13,61,81,32,3,102,114,109,
49,53,52,56,64,33,96,66,35,47,48,91,54,87,60,50,5,6,7,8,108,115,100,95,103,86
};

t_chPtr leftC={ // ASCII table of pointers to left draining character squares.
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// NUL SOH  STX  ETX  EOT  ENQ  ACK  BEL  BS   HT   LF   VT   FF   CR   SO   SI
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// DLE DC1  DC2  DC3  DC4  NAK  SYN  ETB  CAN  EM   SUB  ESC  FS   GS   RS   US
  spL, exL, dqL, otL, doL, pcL, amL, cqL, opL, cpL, asL, plL, cmL, miL, dtL, fsL,
// sp   !    "    #    $    %    &    '    (    )    *    +    ,    -    .    /
  n0L, n1L, n2L, n3L, n4L, n5L, n6L, n7L, n8L, n9L, clL, scL, oaL, eqL, caL, quL,
// 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ?
  atL, lAL, lBL, lCL, lDL, lEL, lFL, lGL, lHL, lIL, lJL, lKL, lLL, lML, lNL, lOL,
// @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O
  lPL, lQL, lRL, lSL, lTL, lUL, lVL, lML, lXL, lYL, lZL, obL, fsL, cbL, ctL, usL,
// P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _
  oqL, lAL, lBL, lCL, lDL, lEL, lFL, lGL, lHL, lIL, lJL, lKL, lLL, lML, lNL, lOL,
// `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o
  lPL, lQL, lRL, lSL, lTL, lUL, lVL, lML, lXL, lYL, lZL, ocL, vbL, ccL, tiL,NULL
// p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL
};

t_chRot leftR={ // Character rotation
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
//    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,6,0,0,0,
//  @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0
//  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
};

t_chSquare // Character squares that drain right.
exR={
99,104,28,27,26,107,92,106,67,51,30,29,97,25,24,57,109,73,68,35,31,84,39,56,23,
70,87,71,86,36,79,54,40,78,22,21,80,69,101,37,38,45,41,113,59,20,95,66,74,55,
77,52,42,64,96,19,18,65,102,61,93,50,43,53,76,72,16,15,98,62,75,58,100,60,88,
85,121,10,9,63,47,46,6,44,111,103,12,11,116,90,48,105,117,34,33,115,13,110,4
},
amR={
85,77,72,70,76,113,15,9,8,101,84,103,60,109,121,18,57,7,6,105,104,78,23,12,20,
19,92,44,108,52,111,25,22,87,10,29,110,116,96,38,61,30,21,50,11,91,88,90,74,
34,33,31,94,17,79,95,71,82,68,58,35,37,32,45,14,93,16,119,102,46,40,39,36,54,
99,24,65,80,73,48,41,100,118,28,26,112,27,62,56,49,42,75,98,86,64,106,89,59,2
},
cmR={
50,46,45,44,43,42,41,111,86,51,47,60,102,82,53,40,39,70,63,52,49,54,121,119,
106,120,38,9,2,27,66,74,92,80,56,34,32,31,89,25,88,37,113,105,75,48,118,30,29,
24,19,18,109,77,78,57,94,35,79,59,36,17,6,5,61,83,108,96,107,67,62,85,7,4,55,
68,20,91,95,99,69,112,26,8,16,15,14,110,98,103,116,97,23,115,71,100,13,12,11
},
dtR={
59,46,45,44,43,42,41,90,103,51,47,84,70,96,67,40,39,55,62,52,49,86,97,106,91,
111,38,28,10,87,110,37,36,35,34,33,32,31,117,25,53,109,79,63,108,61,88,30,29,24,
19,18,72,83,75,69,73,78,71,68,56,17,105,93,113,64,104,48,2,66,65,16,13,12,85,
27,80,92,101,82,95,94,14,11,15,9,8,102,121,99,74,115,118,107,20,116,7,6,5
},
n1R={
67,66,65,17,16,15,14,81,114,68,104,108,18,71,110,13,10,8,60,120,121,20,19,115,
43,98,118,7,6,54,77,21,50,3,44,58,89,88,85,53,23,22,105,70,45,57,34,95,87,90,
24,116,109,73,46,91,32,31,30,26,25,72,52,51,47,76,33,94,96,27,63,92,59,75,48,
55,38,100,112,28,35,79,83,42,49,41,69,111,78,64,36,37,119,93,117,82,106,11,5
},
n2R={
94,77,99,20,19,18,17,16,93,76,47,22,21,108,106,49,15,14,121,80,118,23,117,35,34,
33,120,13,10,79,113,24,1,98,107,101,26,115,4,57,27,25,75,91,66,85,7,86,90,69,
28,50,51,53,6,8,103,102,119,30,29,72,110,52,71,111,73,46,39,31,64,63,45,54,56,
55,96,65,84,32,83,95,41,42,43,44,40,116,74,36,37,109,112,59,97,100,105,9,5
},
n3R={
73,68,55,45,46,47,116,102,54,34,100,53,44,87,63,119,109,59,2,33,97,70,43,10,13,
14,107,82,121,32,31,88,28,76,98,42,24,64,113,95,30,83,57,78,66,120,25,40,39,72,
29,56,108,79,23,22,41,84,99,106,21,20,19,94,77,85,26,65,69,36,35,52,17,18,112,
114,27,67,101,37,96,93,103,6,7,8,80,71,110,48,49,50,117,86,104,16,118,74,5
},
n4R={
82,74,31,32,47,66,121,72,78,27,68,30,97,103,76,120,58,89,2,26,28,29,111,56,33,
40,57,81,116,25,102,115,67,34,73,41,55,54,53,24,23,109,35,65,70,42,71,77,91,105,
22,118,36,37,38,43,39,85,79,59,21,20,106,98,107,44,110,99,4,60,112,19,18,113,95,
45,100,7,6,61,80,101,17,16,86,46,88,8,93,119,90,49,48,15,14,117,10,9,108
},
n5R={
94,109,87,117,31,30,29,5,4,28,81,70,114,110,99,111,52,3,2,27,106,62,39,40,41,
42,43,78,77,26,55,53,6,56,65,73,105,84,66,25,24,69,7,71,80,96,113,112,64,59,23,
61,38,37,36,35,121,98,91,101,22,102,119,68,100,118,11,13,9,92,21,20,19,115,104,
18,12,108,79,85,93,48,17,16,15,14,120,63,103,76,86,49,107,67,54,89,44,34,33
},
n7R={
80,92,49,48,89,119,78,53,5,40,74,117,47,60,116,95,107,10,3,39,71,111,36,35,34,
33,32,108,105,38,37,83,1,58,100,63,31,120,84,70,30,86,81,59,68,46,8,104,62,90,
29,106,109,76,45,9,96,88,12,69,28,27,121,103,6,91,97,14,13,87,101,26,112,82,7,
18,16,15,113,51,50,21,20,19,17,75,110,79,115,52,93,22,72,65,98,99,44,43,42
},
clR={
64,59,48,51,50,54,61,62,68,92,114,33,32,31,30,100,119,113,4,93,35,34,120,116,21,
20,111,118,2,56,36,63,74,60,58,19,57,67,104,38,37,107,22,23,75,18,17,101,121,39,
76,95,25,24,89,73,16,15,117,40,79,94,84,97,69,78,91,14,13,41,43,55,27,26,52,
65,98,72,106,42,44,49,28,29,53,66,80,85,108,70,45,46,99,105,82,81,11,10,7
},
scR={
71,68,53,96,108,20,74,64,63,73,33,32,31,30,19,58,70,97,119,92,34,79,115,116,18,
17,77,120,2,98,35,57,22,23,89,16,103,84,82,37,36,80,25,24,112,15,14,104,114,38,
113,54,100,83,49,48,13,12,86,39,105,52,27,26,50,102,60,11,106,41,42,85,28,29,95,
121,94,10,9,59,43,88,107,40,72,87,65,101,5,47,44,45,21,81,69,66,56,61,90
},
quR={
73,91,67,109,101,92,18,98,11,72,70,64,108,96,116,17,13,12,102,89,113,63,19,15,
16,4,90,33,111,54,65,48,14,61,77,82,31,49,75,45,46,47,10,94,106,95,35,105,83,
44,68,50,20,21,87,34,51,76,103,43,60,66,107,23,22,53,52,97,36,42,41,59,104,86,
25,74,56,55,8,69,40,93,114,119,24,110,57,32,7,78,39,84,37,27,26,99,100,120,58
},
atR={
71,65,55,52,50,117,106,15,14,86,77,78,121,28,118,27,26,87,12,70,69,67,58,8,
10,9,110,84,92,82,88,85,31,36,1,29,7,83,115,56,54,48,32,89,2,120,6,76,95,73,
68,66,33,105,3,4,5,90,116,41,40,39,34,102,109,99,111,63,17,44,42,38,35,97,107,
98,104,64,24,45,72,91,119,21,22,20,112,43,103,46,47,53,96,74,101,80,100,30,25
},
lBR={
67,55,56,111,91,83,85,113,5,75,53,65,118,73,72,93,97,12,11,68,52,77,45,6,7,
8,98,107,115,76,51,50,39,61,79,49,13,59,116,66,62,60,43,99,86,117,33,70,32,63,
71,69,42,9,25,19,106,64,119,38,47,48,41,105,58,54,34,57,109,37,89,81,40,82,92,
101,35,90,14,36,74,108,44,24,46,21,104,96,15,31,30,29,121,95,100,102,18,17,16
},
lCR={
95,76,64,96,40,39,84,91,75,47,120,63,109,74,38,89,11,10,9,46,56,60,61,22,21,
20,62,119,92,45,35,58,27,32,80,98,7,71,113,59,34,33,26,117,88,116,100,73,13,66,
86,114,25,82,121,28,16,15,14,55,37,36,24,108,72,29,81,69,111,68,87,41,23,31,93,
30,8,78,115,65,43,42,102,19,18,17,107,90,85,48,44,106,99,94,50,103,118,4,3
},
lDR={
65,100,63,117,75,56,95,15,12,53,52,51,106,60,55,105,97,81,9,74,90,49,40,1,22,
82,110,94,104,38,115,69,43,98,89,18,73,108,17,37,39,47,44,57,85,71,23,114,61,36,
77,67,45,50,54,80,16,76,83,35,34,64,42,78,88,58,4,48,121,111,33,116,41,109,101,
19,120,8,7,59,32,86,46,24,25,102,103,10,66,91,31,30,119,92,70,20,14,13,79
},
lER={
47,64,65,119,74,56,54,46,22,42,93,66,121,96,89,95,33,19,14,41,113,97,31,13,5,
7,23,107,120,40,35,34,25,94,84,82,77,79,115,91,36,72,29,49,104,80,92,102,15,48,
37,63,28,2,17,68,98,87,112,83,38,71,27,81,90,78,103,73,18,45,39,43,26,67,50,
62,60,61,110,105,101,52,30,20,32,8,10,88,116,70,58,53,118,99,75,86,85,12,11
},
lFR={
84,67,64,118,54,53,52,83,38,88,58,59,120,69,51,50,101,37,36,65,57,86,45,32,34,
33,35,76,105,100,56,61,44,91,95,89,117,7,6,29,30,48,43,107,87,72,10,8,116,28,
110,81,42,9,31,90,11,94,66,27,113,62,41,114,77,97,12,78,46,26,25,82,40,98,99,
14,13,112,47,79,24,85,39,60,16,15,92,80,75,71,23,22,119,18,17,63,93,73,70
},
lGR={
101,106,98,121,97,105,15,12,10,67,103,21,20,19,76,16,92,59,85,52,23,22,117,6,7,
8,115,91,120,94,24,58,39,48,66,89,50,64,77,102,25,88,32,119,78,82,107,18,17,68,
26,84,42,100,46,29,9,44,111,33,27,74,41,81,70,118,13,65,80,34,109,56,43,71,60,
104,14,93,47,37,79,61,73,30,31,28,35,96,114,38,86,54,53,49,57,99,116,36,11
},
lJR={
76,89,77,94,64,63,71,120,11,27,84,74,90,113,62,80,118,12,9,26,85,53,82,38,46,
47,30,91,73,25,92,52,72,37,49,83,31,86,111,24,67,39,28,29,50,96,32,98,105,23,
22,21,20,106,104,61,34,102,109,75,42,41,18,97,60,59,35,78,87,119,43,101,17,19,
107,112,36,110,4,117,44,114,115,8,7,6,121,13,10,93,45,48,81,95,68,16,15,14,88
},
lKR={
87,108,100,118,105,109,16,10,8,65,67,51,117,19,18,17,90,50,98,46,35,48,26,32,
57,112,60,63,107,52,34,33,30,54,78,22,64,101,104,37,36,45,29,62,4,86,97,89,92,
38,53,49,28,24,66,81,82,84,93,39,95,61,27,59,15,96,111,106,41,40,42,56,31,55,74,
14,88,58,110,120,43,80,25,115,113,116,13,23,12,70,44,72,121,71,69,91,47,83,2
},
lLR={
72,96,28,27,26,101,102,87,66,60,30,29,117,25,24,85,80,95,113,35,31,81,39,68,23,
22,63,112,86,36,74,94,40,84,93,21,33,70,71,37,38,46,41,92,32,20,88,82,76,50,
64,91,42,75,34,19,18,78,79,51,52,57,43,105,59,97,17,16,58,62,69,77,44,83,100,
98,106,15,14,99,107,47,45,6,7,8,9,114,109,65,49,48,118,53,108,110,103,11,4
},
lPR={
53,84,50,115,70,66,65,64,11,37,48,49,120,106,99,92,103,12,3,36,118,96,45,6,7,8,
121,116,117,34,97,51,44,69,77,59,35,54,56,33,94,55,43,68,76,79,10,87,88,32,30,
104,42,9,31,46,47,111,110,112,29,108,41,114,113,107,15,14,13,100,28,52,40,101,
80,17,16,58,86,75,27,57,39,85,19,18,102,73,71,78,26,25,119,21,20,98,91,72,61
},
lQR={
116,75,80,85,110,23,22,21,20,58,55,61,92,93,24,76,120,78,10,57,44,52,118,6,
7,8,114,82,87,86,43,53,15,25,121,35,34,97,106,38,37,26,16,108,104,79,33,48,94,
39,98,59,17,69,101,112,32,67,74,40,109,54,18,66,13,71,30,68,89,41,60,64,19,73,
72,27,36,77,83,42,49,62,90,28,29,45,31,111,100,91,50,95,102,46,70,81,117,12,5
},
lRR={
70,53,52,116,104,73,94,102,4,57,56,51,80,58,60,62,86,11,63,68,71,50,37,6,7,
8,113,103,109,95,40,39,36,78,115,77,19,84,83,42,41,49,35,88,67,117,25,85,110,43,
69,61,34,9,33,13,118,93,90,44,81,59,32,105,66,92,26,91,72,45,111,74,31,82,100,
101,27,76,14,46,47,96,30,38,98,64,28,89,15,106,48,75,121,24,23,22,107,17,16
};

t_chPtr rightC={ // ASCII table of pointers to right draining character squares.
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// NUL SOH  STX  ETX  EOT  ENQ  ACK  BEL  BS   HT   LF   VT   FF   CR   SO   SI
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// DLE DC1  DC2  DC3  DC4  NAK  SYN  ETB  CAN  EM  SUB  ESC   FS   GS   RS   US
  spL, exR, dqL, otL, doL, pcL, amR, oqL, cpL, opL, asL, plL, cmR, miL, dtR, fsL,
// sp   !    "    #    $    %    &    '    (    )    *    +    ,    -    .    /
  n0L, n1R, n2R, n3R, n4R, n5R, n9L, n7R, n8L, n6L, clR, scR, caL, eqL, oaL, quR,
// 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ?
  atR, lAL, lBR, lCR, lDR, lER, lFR, lGR, lHL, lIL, lJR, lKR, lLR, lML, lNL, lOL,
// @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O
  lPR, lQR, lRR, lSL, lTL, lUL, lVL, lML, lXL, lYL, lZL, cbL, fsL, obL, ctL, usL,
// P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _
  cqL, lAL, lBR, lCR, lDR, lER, lFR, lGR, lHL, lIL, lJR, lKR, lLR, lML, lNL, lOL,
// `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o
  lPR, lQR, lRR, lSL, lTL, lUL, lVL, lML, lXL, lYL, lZL, ccL, vbL, ocL, tiL,NULL
// p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL
};

t_chRot rightR={ // Character rotation
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    2,0,4,2,2,2,0,4,2,2,4,2,0,2,0,2,2,0,0,0,0,0,2,0,2,2,0,0,2,2,2,0,
//    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
    0,4,0,0,0,0,0,0,2,2,0,0,0,4,2,2,0,0,0,2,4,4,4,2,2,4,2,2,4,2,4,4,
//  @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
    4,4,0,0,0,0,0,0,2,2,0,0,0,4,2,2,0,0,0,2,4,4,4,2,2,4,2,2,2,2,2,0
//  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
};

t_chSquare // Character squares that drain up.
exU={
53,70,1,92,3,4,109,110,101,65,30,2,97,98,5,7,72,89,88,35,31,71,39,56,29,8,116,
75,91,36,105,95,40,73,68,9,10,74,81,37,38,45,41,63,114,96,11,99,66,64,106,86,
42,84,51,27,12,28,111,76,90,117,43,93,115,79,13,14,15,58,57,59,52,54,107,85,
87,77,18,102,47,46,6,44,113,104,103,67,19,83,48,55,119,34,33,121,112,23,22
},
dqU={
102,2,36,30,78,1,116,90,117,108,120,37,79,24,31,23,119,121,5,66,106,38,34,22,
35,25,115,113,6,41,40,39,100,85,112,114,105,8,7,42,80,67,60,68,88,81,10,9,75,
43,74,63,58,57,72,26,11,104,77,44,59,82,62,53,28,27,12,118,94,45,46,109,71,87,
29,21,13,33,107,56,47,65,64,70,98,50,14,15,89,69,48,51,52,54,76,93,83,16,97
},
otU={
9,108,5,3,118,2,120,107,8,10,77,12,7,105,88,113,103,18,21,11,13,82,111,63,95,
20,100,50,22,17,14,115,109,16,102,62,73,112,25,24,23,114,58,56,53,61,15,121,
119,98,46,47,101,6,65,57,66,72,85,116,96,80,1,60,48,54,4,84,99,106,86,75,69,
55,68,36,64,51,31,97,70,52,87,59,71,19,67,43,32,93,49,45,83,92,40,91,35,34,33
},
doU={
4,117,6,95,8,116,87,98,13,5,99,7,89,119,103,70,75,79,15,14,77,16,74,113,48,
65,66,82,25,17,94,96,86,41,52,40,39,83,26,18,19,100,3,109,46,105,72,76,30,110,
20,120,88,2,38,11,84,61,35,106,21,101,92,121,44,69,1,37,36,107,22,112,12,32,
45,29,71,78,114,85,23,24,73,59,57,81,56,55,108,90,111,27,28,33,80,67,58,54,60
},
pcU={
107,1,102,119,116,5,101,4,64,72,88,85,112,12,6,7,110,65,111,70,86,81,10,9,26,
90,92,114,47,27,100,13,11,8,120,115,20,74,79,16,15,14,96,108,106,23,97,61,60,
17,63,62,77,91,24,80,76,57,58,18,19,35,99,22,105,87,98,56,59,82,25,28,21,113,
117,31,34,55,71,83,103,121,29,30,36,32,33,44,51,84,118,78,48,93,37,38,39,40,42
},
amU={
56,19,9,111,97,120,13,104,25,81,57,18,85,107,113,17,84,35,72,78,53,38,79,12,
114,66,83,51,94,87,41,39,32,121,22,118,93,109,5,43,42,76,36,40,21,90,106,110,6,
44,67,75,99,15,64,77,86,55,7,45,119,108,14,89,23,117,16,20,8,63,103,102,24,37,
29,11,28,61,115,54,58,69,96,27,26,70,10,74,92,52,50,49,48,80,105,59,30,60,65
},
opU={
51,78,73,111,100,4,98,3,1,117,88,85,95,7,5,106,64,2,30,119,91,113,115,8,29,45,
6,79,31,80,81,99,10,9,105,44,52,63,92,61,66,87,11,104,94,43,77,53,38,60,118,
28,12,27,68,42,67,83,110,16,15,14,13,82,120,41,108,102,76,17,18,70,69,121,116,
40,46,59,57,20,19,55,96,101,65,107,39,47,48,21,22,23,114,86,33,34,97,89,49
},
cpU={
62,90,1,3,98,4,100,111,73,72,30,2,64,106,5,7,95,85,88,35,31,79,6,45,29,8,115,
113,91,36,92,63,52,44,105,9,10,99,81,37,38,53,77,43,94,104,11,87,66,56,110,
83,67,42,68,27,12,28,118,84,76,102,108,41,120,82,13,14,15,58,57,59,46,40,116,
121,69,70,18,74,48,47,39,107,65,101,96,55,19,103,49,89,97,34,33,86,114,23,22
},
asU={
108,11,84,9,10,109,113,18,1,15,12,53,93,117,119,115,100,8,19,16,13,111,95,2,
107,3,94,121,88,17,14,44,99,104,7,82,114,98,70,102,116,85,34,33,32,31,30,110,
75,77,103,59,76,112,6,89,74,26,25,66,61,57,87,4,101,5,80,27,78,69,83,50,56,91,
54,71,29,28,48,73,106,42,39,38,37,36,35,120,49,65,97,41,40,81,47,68,46,60,62
},
cmU={
106,4,101,87,67,3,26,117,1,84,5,83,82,68,69,29,110,2,61,105,6,27,102,79,57,
30,31,75,55,90,7,8,113,80,94,77,32,38,39,62,116,9,88,81,97,48,33,56,40,21,20,
10,17,107,99,98,34,114,109,22,115,89,12,13,100,53,35,118,71,23,111,95,15,14,91,
70,36,112,60,28,121,108,66,11,18,119,37,54,64,58,63,65,16,92,19,96,120,49,47
},
miU={
115,5,62,3,4,80,102,117,1,9,6,64,93,112,85,89,15,2,88,10,7,70,113,119,100,
83,16,17,18,11,8,53,109,101,98,96,72,84,19,12,105,48,47,51,49,59,76,106,97,14,
121,99,43,13,42,41,40,120,116,94,111,60,55,46,44,45,68,71,54,103,104,65,58,79,35,
34,66,78,25,107,110,61,81,75,50,29,28,27,26,114,56,52,33,32,31,30,87,74,67
},
dtU={
92,4,100,110,1,101,26,88,3,90,5,95,85,2,74,27,99,60,58,89,6,48,104,87,57,29,
30,61,55,113,7,8,79,112,94,68,31,38,39,75,115,9,69,81,91,62,32,56,40,21,20,10,
15,120,96,109,33,103,102,22,116,111,16,71,80,66,34,53,59,23,119,121,12,13,17,
108,35,106,73,28,118,36,11,14,18,114,117,72,98,54,83,63,86,77,19,37,107,52,47
},
n0U={
80,106,3,98,1,68,2,87,13,92,76,4,96,31,57,120,85,14,15,118,6,5,115,28,29,30,
110,105,16,108,7,82,36,101,74,44,41,70,17,119,8,104,35,95,103,43,38,89,18,10,
9,97,33,102,46,121,39,77,117,11,93,71,32,47,72,111,40,66,107,12,116,94,42,112,
90,45,37,78,23,24,100,84,48,25,26,27,88,53,113,34,86,65,75,69,51,49,50,52,73
},
n1U={
4,109,67,1,94,118,81,2,73,5,59,89,24,71,120,68,39,96,91,6,50,100,86,104,33,
41,40,82,119,7,113,99,80,3,32,105,97,112,12,15,16,101,111,69,31,42,107,63,13,116,
17,18,55,87,30,79,64,85,14,117,72,19,88,75,29,77,43,21,20,95,60,23,54,53,28,
78,76,22,90,115,61,57,70,26,27,25,93,34,65,108,52,51,56,44,102,37,36,35,84
},
n2U={
66,95,2,102,111,28,20,21,6,98,81,3,15,19,110,109,114,7,8,82,85,92,91,16,17,
18,100,101,9,77,90,23,1,22,106,105,45,104,10,58,25,24,97,83,96,108,46,47,11,103,
26,118,113,117,4,5,48,112,12,57,29,93,72,42,49,64,59,73,119,31,30,41,40,84,87,
80,70,65,116,32,79,115,35,36,37,38,39,62,120,33,75,71,52,74,69,61,43,44,94
},
n3U={
110,91,2,81,85,77,72,111,3,70,5,4,88,87,76,63,119,57,50,109,9,99,49,6,7,
8,120,78,83,11,10,121,29,62,112,48,27,97,61,15,69,68,65,92,80,106,26,53,60,16,
82,86,89,98,18,19,47,75,105,17,20,21,25,96,108,116,22,107,104,74,95,73,24,28,101,
115,23,71,33,114,118,100,113,12,13,14,30,31,32,56,55,51,66,64,39,67,102,54,58
},
n4U={
7,117,116,98,8,80,113,21,20,97,110,108,10,9,75,114,76,67,2,102,104,12,11,107,28,
37,83,68,115,120,14,13,121,29,118,32,101,112,6,87,15,94,30,85,61,38,52,53,77,105,
16,111,34,33,39,41,31,72,96,22,17,18,106,91,74,40,57,71,86,23,82,19,73,99,56,
36,55,62,88,24,100,84,81,103,45,35,46,47,48,25,26,27,42,43,44,119,95,49,92
},
n5U={
56,1,31,118,95,33,78,81,90,3,2,76,116,87,44,92,57,91,5,86,111,103,43,6,37,42,
41,82,8,47,46,45,40,102,101,94,83,15,9,48,77,54,7,85,80,73,58,18,96,79,107,
72,38,10,36,35,109,19,114,71,30,74,117,88,100,105,17,20,24,59,29,23,22,120,121,
21,16,115,119,93,108,70,11,12,13,14,106,104,113,64,63,62,99,32,67,68,53,66,69
},
n6U={
92,1,37,79,102,18,120,77,82,3,2,61,110,112,19,121,80,67,41,4,98,66,117,12,13,
14,90,95,78,5,96,105,33,118,104,21,20,22,56,8,63,85,7,62,88,113,97,23,52,106,
99,89,38,10,36,35,51,24,107,109,75,53,34,94,74,119,17,25,32,83,59,65,40,100,101,
26,16,81,58,103,50,49,115,6,15,11,108,111,60,86,57,31,69,27,87,45,68,93,64
},
n7U={
89,1,52,76,66,65,86,83,4,3,2,81,99,103,96,74,111,5,6,113,102,67,31,35,34,
33,32,116,7,87,49,48,37,60,88,110,36,69,10,97,84,56,54,59,104,61,8,47,11,30,
114,73,55,115,92,9,120,13,12,29,107,100,72,78,19,79,15,14,119,28,108,62,85,70,18,
20,16,118,106,27,26,58,68,21,17,75,112,109,117,105,25,24,23,22,95,80,93,94,64
},
n8U={
54,19,9,91,83,90,99,119,25,55,87,18,73,92,94,74,56,35,85,75,93,38,104,12,11,
13,114,88,120,97,41,39,32,103,112,111,22,105,5,43,42,108,36,40,89,106,21,82,6,44,
72,80,118,15,16,17,107,79,7,45,63,100,14,115,102,95,10,23,8,65,69,68,24,37,70,
29,20,67,113,62,64,86,84,27,26,28,117,58,59,53,50,49,48,101,30,66,51,52,110
},
n9U={
83,9,91,57,62,18,119,79,50,15,11,120,96,86,19,113,114,92,2,109,61,100,116,14,13,
12,75,59,108,112,104,66,16,20,115,46,40,54,93,71,87,21,17,117,106,74,34,69,67,64,
97,22,85,35,36,10,38,76,90,27,26,23,99,89,98,77,7,68,73,28,72,25,24,94,107,
88,33,47,48,29,110,111,80,41,37,6,101,51,49,30,31,32,39,70,78,81,55,52,82
},
clU={
82,109,4,93,79,5,98,30,110,85,114,32,70,56,6,76,116,83,2,89,34,33,112,118,7,
8,115,104,3,50,35,66,87,101,21,9,72,73,105,37,36,95,22,23,119,10,11,106,120,38,
81,102,25,24,117,108,12,49,53,39,40,99,67,63,90,68,13,80,54,88,41,42,27,26,113,
100,14,15,121,51,43,107,28,29,55,57,86,16,96,47,44,45,69,77,64,59,91,17,97
},
scU={
105,85,4,91,88,5,96,30,90,80,116,32,103,94,6,101,50,56,2,78,34,33,111,114,7,
8,118,117,3,69,35,82,22,23,89,9,120,110,60,37,36,107,25,24,97,10,11,112,119,38,
54,70,68,81,108,79,12,49,53,39,87,73,27,26,67,104,13,71,100,41,42,113,28,29,115,
51,14,15,121,63,43,66,83,40,57,55,99,16,84,47,44,45,21,77,58,86,106,17,109
},
oaU={
96,77,117,101,109,4,69,67,1,103,87,112,115,6,5,79,99,2,28,84,62,61,51,7,121,
105,43,72,29,94,102,114,9,8,118,42,50,73,30,65,98,11,10,47,41,49,52,90,111,64,
89,12,60,40,55,76,53,59,88,16,15,13,14,119,39,66,107,100,108,17,18,104,78,83,
110,38,48,54,63,20,19,80,92,106,113,45,37,46,56,21,22,23,116,120,33,34,44,93,70
},
eqU={
119,5,66,3,4,93,73,101,1,9,6,48,97,96,86,82,75,2,64,10,7,87,102,121,89,100,
17,16,18,11,8,60,81,78,61,112,110,111,19,12,120,103,40,44,42,13,43,117,116,15,
108,63,79,70,52,72,76,65,49,114,115,53,41,14,39,45,38,80,109,113,67,54,55,94,
47,46,56,90,25,98,91,51,105,84,74,29,28,27,26,99,107,50,33,32,31,30,59,85,62
},
caU={
27,3,1,67,69,4,109,101,117,35,28,2,99,79,5,6,115,112,87,36,29,72,43,105,121,7,
51,61,62,31,30,73,50,42,118,8,9,114,102,97,111,90,52,49,41,47,10,11,98,75,88,
59,53,76,55,40,60,12,89,74,108,100,107,66,39,119,14,13,15,58,63,54,48,38,110,
83,78,104,18,57,56,46,37,45,113,106,92,80,19,95,70,93,44,34,33,120,116,23,22
},
quU={
4,71,24,119,114,120,8,112,11,19,77,32,118,101,107,17,13,12,94,102,97,115,20,7,5,
16,100,33,92,93,99,45,14,113,117,18,3,31,34,72,47,46,10,91,96,121,6,106,35,73,
75,50,21,22,82,15,98,105,88,70,52,95,108,23,2,51,66,87,74,54,40,76,85,65,25,
89,63,68,62,59,39,55,110,80,1,109,60,57,53,67,38,103,37,27,26,116,64,83,61
},
atU={
14,90,9,119,2,99,1,103,3,15,113,13,114,108,112,111,70,4,5,84,58,20,93,41,40,
39,102,115,54,95,92,21,17,118,33,98,7,79,85,72,61,101,18,104,36,105,28,60,59,
78,57,116,19,106,37,38,29,97,64,55,52,100,16,22,76,83,63,66,73,32,31,24,8,23,
107,94,86,81,68,74,34,120,109,12,11,10,91,75,46,56,35,80,87,82,69,42,43,44,45
},
lAU={
1,5,11,105,110,111,3,121,76,2,9,12,114,90,83,4,120,108,116,70,61,73,68,63,7,
91,80,56,88,109,79,51,104,6,53,8,72,55,119,103,106,50,35,112,52,92,34,54,17,99,
98,94,29,36,37,38,30,75,18,85,45,44,28,66,97,100,31,67,19,47,46,96,27,62,65,
115,32,59,20,48,84,77,26,43,69,95,33,74,21,49,60,81,71,42,57,86,93,23,22
},
lBU={
1,4,5,120,112,3,121,113,66,2,11,12,86,101,96,84,81,67,117,89,111,103,45,24,8,
13,72,83,108,73,55,54,39,87,98,48,33,69,99,57,56,75,43,114,110,76,34,71,18,105,
119,90,42,9,25,19,94,30,20,63,74,61,41,68,77,92,46,49,22,58,51,50,40,65,104,
82,35,70,23,97,52,102,44,6,7,21,100,109,26,62,53,59,91,47,106,79,31,28,27
},
lCU={
3,4,84,116,115,109,13,120,101,83,6,55,121,105,108,14,114,54,9,62,113,77,73,12,11,
10,78,85,76,52,118,69,18,23,49,107,7,65,88,51,26,25,19,89,50,103,86,63,80,71,
27,61,20,87,117,36,35,34,91,29,28,58,21,96,70,111,93,33,60,30,119,68,22,24,66,
110,8,32,97,90,100,81,104,17,16,15,31,106,67,98,48,47,112,64,37,99,40,41,42
},
lDU={
54,74,1,120,2,83,3,111,94,71,17,16,119,35,96,4,5,104,117,106,18,103,34,23,22,
118,6,7,121,38,26,90,33,114,97,60,110,8,9,46,77,78,32,91,69,84,21,100,10,56,
93,89,31,45,58,95,20,105,11,59,81,66,30,92,79,75,19,101,12,64,99,80,29,112,70,
40,109,14,13,76,85,47,28,25,24,98,115,15,116,50,49,48,108,67,36,55,82,61,72
},
lEU={
97,3,78,116,2,98,1,109,80,105,4,5,110,99,59,76,92,106,7,121,9,96,45,44,43,
42,41,103,15,11,10,47,35,117,94,113,100,17,16,12,101,62,34,65,66,82,19,18,119,13,
107,88,33,30,29,68,20,79,115,14,90,87,32,83,70,63,21,22,118,102,114,60,31,72,69,
77,74,23,24,84,108,48,40,39,38,37,36,95,120,55,50,49,91,64,52,58,73,67,85
},
lFU={
1,104,3,113,2,111,102,117,4,74,21,20,98,75,100,65,95,110,7,118,22,119,45,32,34,
33,35,120,8,72,23,73,44,76,86,67,96,10,9,25,24,52,43,90,81,70,108,11,83,49,
106,69,42,30,31,91,13,12,107,53,92,99,41,101,112,78,14,26,27,88,82,68,40,103,17,
16,15,116,97,61,58,55,39,77,18,63,89,94,71,64,80,56,87,37,19,36,38,114,93
},
lGU={
99,100,36,115,1,106,94,111,2,69,63,37,113,10,70,64,103,58,79,71,83,38,121,6,7,
8,108,61,87,62,76,97,11,18,40,85,50,59,84,34,66,80,12,116,41,82,51,56,60,33,
96,92,15,118,39,29,9,74,78,32,101,77,16,117,93,72,13,42,43,27,20,19,17,120,102,
112,14,91,44,104,21,114,119,30,31,28,35,98,45,54,22,57,107,109,52,48,67,55,53
},
lHU={
9,119,5,118,3,8,84,108,2,10,121,12,116,7,50,90,113,22,23,11,13,117,62,112,59,
87,61,100,24,21,14,81,15,102,98,67,52,89,106,18,17,68,53,109,86,64,57,73,99,120,
110,88,58,6,1,4,60,91,105,115,51,69,20,78,83,70,55,71,30,49,48,76,36,96,95,
65,19,74,31,103,47,66,56,75,79,63,16,80,32,114,46,45,94,41,40,39,93,34,33
},
lIU={
54,90,106,2,51,62,68,1,105,89,113,10,4,98,119,78,3,5,99,93,118,11,73,9,45,
8,96,19,108,112,13,12,60,84,44,100,61,20,82,77,14,101,117,58,43,57,92,21,22,87,
15,120,38,46,42,64,71,86,23,17,16,36,37,76,41,88,115,114,24,18,63,81,66,59,40,
94,95,104,25,34,110,97,103,7,39,6,74,65,109,35,47,48,121,116,111,75,31,30,29
},
lJU={
26,103,76,108,68,3,58,117,6,27,79,115,110,116,4,92,114,7,2,28,88,63,109,89,8,
59,30,81,83,29,98,62,78,10,9,104,31,94,82,91,71,13,12,11,120,57,32,99,95,101,
15,14,46,69,107,75,34,72,86,65,16,85,41,102,121,56,35,49,50,67,17,93,40,47,119,
48,36,96,55,100,18,19,84,39,38,37,113,80,66,64,54,20,21,97,118,60,87,44,45
},
lKU={
112,1,11,121,21,70,87,90,76,5,2,12,119,41,93,111,105,75,101,6,99,62,31,86,72,
108,32,69,98,9,110,109,30,94,67,22,68,89,63,106,91,103,29,100,4,78,71,58,16,
48,80,74,28,24,60,64,65,97,17,47,102,61,27,84,23,82,88,19,18,46,45,83,26,104,
107,14,33,20,77,115,43,42,25,40,85,34,13,66,95,81,44,59,118,39,53,35,49,50,51
},
lLU={
1,5,11,108,72,3,120,114,112,2,9,12,83,89,4,100,110,115,55,6,117,116,39,46,7,
8,119,64,56,28,29,85,40,68,53,10,61,95,106,109,30,102,41,67,111,13,14,15,90,70,
31,80,42,52,104,101,32,16,81,105,94,71,43,51,121,99,33,17,18,86,82,50,44,60,75,
73,58,57,66,103,113,47,45,38,37,36,35,78,118,74,54,48,98,63,59,84,69,77,23
},
lMU={
115,89,1,116,2,3,5,121,13,113,7,4,117,92,12,79,118,15,16,9,8,104,32,84,109,
75,38,90,17,10,87,85,39,31,108,43,44,100,18,14,96,88,41,94,6,81,36,93,19,30,
107,95,34,83,71,76,35,99,20,45,46,78,29,70,101,68,11,82,119,102,47,48,33,65,66,
67,37,72,111,97,61,55,40,49,73,64,42,52,114,74,63,56,110,50,69,59,112,27,26
},
lNU={
115,109,5,111,1,21,4,99,2,121,9,7,105,3,120,51,118,6,23,11,10,119,53,106,
104,116,19,84,24,12,17,95,62,92,70,89,52,83,73,13,98,68,56,18,69,94,57,86,85,
14,114,87,36,88,8,79,60,77,80,48,54,63,58,78,81,22,55,82,101,93,71,66,20,100,
59,75,61,65,31,67,47,72,15,102,49,64,16,117,32,74,46,45,112,41,40,39,97,34,33
},
lOU={
84,118,3,100,1,86,2,85,13,105,78,4,108,42,57,92,79,14,15,120,6,5,115,28,29,
30,114,89,16,94,7,81,36,107,87,43,37,66,17,104,8,112,35,67,69,111,38,90,18,10,
9,95,33,97,63,116,39,72,117,11,102,68,32,48,62,98,40,76,113,12,106,103,31,110,99,
44,41,80,23,24,101,71,45,25,26,27,88,64,109,34,75,74,82,93,46,49,50,51,52
},
lPU={
87,2,11,112,104,71,91,103,1,9,5,12,115,63,69,95,96,83,120,50,77,121,40,32,34,
7,88,119,97,52,55,100,39,70,89,101,33,109,13,64,105,93,38,90,94,42,8,74,14,65,
80,62,37,28,31,29,107,111,15,57,48,47,36,116,81,117,18,17,16,59,92,82,35,78,99,
20,19,26,76,98,102,43,30,41,22,21,66,27,113,46,45,44,110,24,23,75,72,51,67
},
lQU={
96,3,59,98,10,105,73,118,11,101,4,60,88,106,89,87,120,9,2,119,12,84,109,6,7,8,
107,80,113,21,14,20,15,110,99,100,34,83,111,22,102,72,16,108,90,61,33,44,45,
23,103,79,17,76,77,82,32,69,46,24,116,94,18,115,13,74,30,92,47,25,117,40,19,35,
55,27,37,121,91,95,85,53,112,28,29,36,31,63,71,70,58,54,65,38,66,81,86,50,51
},
lRU={
1,4,5,119,3,103,113,112,120,2,11,12,116,41,91,89,105,99,92,86,87,121,40,6,7,
8,108,114,80,84,101,97,37,110,85,90,17,19,16,70,53,51,36,109,68,79,18,20,61,75,
54,104,39,9,31,26,111,21,83,57,56,76,38,93,69,107,22,25,33,65,63,64,35,82,62,
55,23,78,50,98,102,46,34,115,96,27,24,42,43,67,88,47,77,71,29,28,73,74,72
},
lSU={
4,100,6,121,68,13,83,102,64,5,118,7,9,98,115,110,112,92,3,114,87,107,16,12,11,
10,17,105,104,103,81,84,14,59,78,62,8,18,91,119,21,20,15,82,95,108,97,19,28,113,
22,96,43,41,42,40,94,66,29,24,23,32,120,101,99,44,36,76,30,25,89,93,53,70,80,
72,37,61,31,26,63,106,117,38,39,35,45,58,79,27,33,74,116,54,50,51,52,55,90
},
lTU={
1,2,11,97,79,116,75,106,107,5,9,12,94,60,117,66,115,108,4,93,85,103,37,40,47,
39,38,105,6,100,83,112,70,59,46,58,65,8,7,32,31,30,111,71,45,62,101,10,110,33,
73,29,91,72,44,64,104,13,96,34,120,28,27,99,43,119,15,14,121,118,92,114,26,56,42,
88,16,35,36,82,54,53,25,90,41,61,17,86,113,89,55,102,24,23,109,19,18,87,95
},
lUU={
6,116,1,118,17,70,5,112,7,98,3,2,121,23,71,102,119,8,9,88,4,111,24,44,79,
80,30,94,10,96,21,104,28,103,73,91,31,101,11,78,22,37,27,110,69,68,32,106,109,47,
45,84,26,87,83,77,33,62,113,48,117,75,25,82,67,92,34,100,16,49,120,85,29,86,59,
39,35,38,36,50,99,58,108,20,19,18,90,46,97,51,52,53,76,57,40,56,74,54,93
},
lVU={
101,92,6,113,4,70,5,83,15,118,8,7,110,40,68,87,93,16,17,119,9,56,35,41,71,
108,34,84,18,114,10,69,27,90,72,58,30,104,19,12,11,85,26,98,89,75,31,115,20,13,
111,91,25,112,64,81,32,99,21,14,117,100,24,88,63,45,33,43,121,38,105,97,77,1,67,
2,94,42,120,39,86,65,106,73,3,95,102,37,36,44,46,47,79,74,53,60,82,54,80
},
lWU={
104,73,1,121,2,3,11,118,13,101,7,4,120,89,12,94,119,16,17,9,8,114,27,99,41,
105,37,103,18,14,86,65,28,71,106,68,36,88,19,15,45,50,40,83,113,81,35,87,20,98,
96,109,39,70,60,78,34,44,21,75,84,79,38,64,6,85,43,67,107,74,80,93,32,10,100,
5,42,95,116,66,76,51,33,63,97,47,26,72,115,58,62,52,111,61,77,48,112,31,30
},
lXU={
116,2,1,100,3,6,121,104,73,9,5,106,114,4,7,8,113,97,96,11,12,120,29,118,111,
14,10,69,99,85,110,83,30,90,95,117,13,15,16,64,39,81,82,48,79,49,94,58,59,53,
38,37,84,55,50,107,89,72,67,62,103,36,91,46,54,47,51,86,75,70,119,35,31,108,102,
115,23,25,22,60,57,56,32,92,76,26,24,66,77,61,88,71,34,33,28,27,109,68,65
},
lYU={
94,1,61,85,3,115,4,118,79,5,2,55,114,42,80,6,96,111,103,9,119,89,31,43,117,
10,7,92,101,11,108,75,30,121,60,120,8,12,74,110,91,66,44,27,48,26,113,13,82,72,
84,46,45,102,32,95,116,14,15,41,69,59,47,76,33,109,86,77,16,40,39,54,70,107,34,
78,64,100,17,104,38,67,105,97,35,112,20,19,18,87,37,36,29,28,93,88,21,81,106
},
lZU={
94,86,5,4,107,108,75,115,1,76,7,6,104,106,97,72,99,3,50,112,9,111,31,32,33,
34,35,120,101,71,10,61,96,84,82,66,36,56,55,30,11,12,105,81,91,60,87,70,65,37,
100,13,14,17,16,103,117,92,83,38,98,95,119,15,18,19,25,89,88,39,109,116,24,42,118,
113,26,27,28,40,110,121,23,22,21,20,8,114,102,41,62,63,78,85,43,64,77,52,49
},
obU={
1,102,91,98,110,17,26,65,28,2,109,103,106,19,18,118,86,49,30,3,121,120,119,20,
117,46,39,7,47,4,5,99,108,21,82,40,97,95,87,115,8,101,25,22,80,41,74,96,75,
113,9,83,35,23,48,42,69,88,77,27,10,11,36,116,79,43,70,92,94,105,72,12,37,85,
52,44,64,71,63,111,89,13,76,107,57,45,6,38,56,90,78,14,15,81,59,112,50,53,58
},
cbU={
104,29,28,65,26,17,110,98,91,31,30,49,86,118,18,19,106,103,109,32,47,7,39,46,
117,20,119,120,121,33,87,95,97,40,82,21,108,99,5,34,75,96,74,41,80,22,25,101,
8,84,77,88,69,42,48,23,35,83,9,93,94,92,70,43,79,116,36,11,10,66,63,71,64,44,
52,85,37,12,72,73,56,38,6,45,57,107,76,13,89,61,58,53,50,112,59,81,15,14,78
},
ctU={
85,32,31,30,96,75,110,97,112,34,33,68,29,18,67,102,98,105,114,35,117,106,119,
17,13,14,120,121,5,36,95,92,103,15,84,11,107,7,6,37,94,76,16,100,88,12,8,9,118,
38,39,72,90,93,63,20,19,10,116,87,40,41,42,43,51,54,21,104,109,73,52,44,58,66,
53,77,22,82,70,101,71,45,46,83,56,108,23,24,25,86,48,47,81,78,60,99,91,28,26
},
usU={
121,5,103,3,4,110,2,118,1,9,6,78,8,81,83,15,97,113,93,10,7,62,114,111,105,
16,19,20,107,11,115,68,86,101,18,17,39,21,99,12,116,67,95,57,46,85,72,22,23,
14,33,45,89,70,48,112,73,94,24,104,34,35,80,54,49,75,65,106,25,92,109,36,38,59,
56,98,51,79,26,90,77,37,55,63,53,102,50,64,52,117,82,74,43,13,42,41,40,119,71
},
oqU={
3,121,112,86,1,34,105,90,36,4,5,116,106,101,35,25,24,37,99,59,6,87,97,88,79,
27,26,38,108,98,7,8,113,70,118,23,114,39,40,93,55,9,10,53,61,110,22,96,120,
69,66,103,11,51,71,77,62,60,58,76,85,84,12,20,75,83,73,65,54,78,100,104,13,21,
28,95,74,67,46,80,117,15,14,115,29,63,89,52,47,92,91,16,102,57,30,31,64,72,48
},
ocU={
105,53,82,91,81,4,116,3,1,99,76,85,120,7,5,93,95,2,30,89,98,119,109,8,29,44,
6,103,31,65,110,87,10,9,111,42,51,78,72,64,63,62,11,27,114,43,100,84,66,79,107,
28,12,97,38,45,52,70,83,16,15,14,13,101,117,41,92,68,108,17,18,73,58,106,121,
40,46,61,54,20,19,74,104,94,67,102,39,47,48,21,22,23,118,115,33,34,112,88,49
},
vbU={
84,5,99,3,4,121,68,107,1,9,6,113,94,69,120,63,15,2,76,10,7,111,110,117,45,102,
16,17,18,11,8,13,105,114,40,106,116,119,19,12,109,14,78,52,41,53,101,92,98,
85,97,30,60,55,42,51,61,81,87,93,90,33,62,49,46,50,75,80,70,100,103,79,47,48,
43,57,56,89,25,96,108,59,39,74,44,58,28,27,26,88,65,38,37,54,95,31,29,77,66
},
ccU={
55,80,1,3,116,4,81,91,82,59,30,2,95,93,5,7,120,85,76,35,31,103,6,44,29,8,109,
119,98,36,72,78,51,42,111,9,10,87,110,37,66,84,100,43,114,27,11,62,63,60,83,
70,52,45,38,97,12,28,107,86,108,68,92,41,117,101,13,14,15,77,54,61,46,40,121,
106,58,73,18,57,48,47,39,102,67,94,104,74,19,56,49,88,112,34,33,115,118,23,22
},
tiU={
121,5,66,3,4,98,90,102,1,9,6,75,92,78,103,110,15,2,67,10,7,72,118,117,94,89,
16,17,18,11,8,53,101,108,68,100,86,97,19,12,119,49,48,13,47,59,106,115,82,14,
120,88,43,51,42,45,40,111,95,87,112,58,55,62,46,41,64,69,54,104,91,60,65,74,
50,44,71,63,25,107,109,61,77,93,35,29,28,27,26,116,56,52,33,32,31,30,73,84,81
};

t_chPtr upC={ // ASCII table of pointers to up draining character squares.
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// NUL SOH  STX  ETX  EOT  ENQ  ACK  BEL  BS   HT   LF   VT   FF   CR   SO   SI
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// DLE DC1  DC2  DC3  DC4  NAK  SYN  ETB  CAN  EM   SUB  ESC   FS   GS   RS   US
  spL, exU, dqU, otU, doU, pcU, amU, oqU, opU, cpU, asU, plL, cmU, miU, dtU, fsL,
// sp   !    "    #    $    %    &    '    (    )    *    +    ,    -    .    /
  n0U, n1U, n2U, n3U, n4U, n5U, n6U, n7U, n8U, n9U, clU, scU, oaU, eqU, caU, quU,
// 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ?
  atU, lAU, lBU, lCU, lDU, lEU, lFU, lGU, lHU, lIU, lJU, lKU, lLU, lMU, lNU, lOU,
// @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O
  lPU, lQU, lRU, lSU, lTU, lUU, lVU, lWU, lXU, lYU, lZU, obU, fsL, cbU, ctU, usU,
// P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _
  oqU, lAU, lBU, lCU, lDU, lEU, lFU, lGU, lHU, lIU, lJU, lKU, lLU, lMU, lNU, lOU,
// `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o
  lPU, lQU, lRU, lSU, lTU, lUU, lVU, lWU, lXU, lYU, lZU, ocU, vbU, ccU, tiU,NULL
// p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL
};

t_chRot upR={ // Character rotation
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    1,0,0,0,0,0,0,4,0,0,0,1,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
//    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
//  @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
//  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
};

t_chSquare // Character squares that drain down.
exD={
51,49,87,115,53,32,26,25,24,75,48,98,82,34,33,119,116,23,22,72,47,46,39,44,94,
109,118,63,19,58,57,59,40,54,85,114,73,96,18,95,102,103,41,97,113,62,13,14,15,
74,106,110,42,55,68,27,12,28,89,37,38,45,43,65,107,90,11,108,66,36,93,56,52,
76,101,9,10,77,81,35,31,64,6,111,29,8,92,83,91,71,30,2,99,79,5,7,84,86,88
},
dqD={
116,49,75,35,34,87,104,117,17,59,48,66,98,24,33,23,113,16,111,77,47,68,89,22,
32,25,107,15,106,45,46,110,31,30,29,114,13,14,120,44,81,57,53,92,28,27,12,79,
105,43,78,60,56,72,86,26,11,101,64,42,118,85,97,103,84,20,10,9,8,41,40,39,69,
71,73,99,90,91,7,55,54,38,52,58,61,76,109,112,6,67,108,37,70,65,62,63,88,102,5
},
amD={
52,67,78,47,46,45,40,35,64,51,50,49,48,54,71,96,34,38,88,53,65,57,77,12,76,
69,33,31,100,62,90,114,32,55,22,105,94,30,28,59,81,84,27,60,21,58,80,82,8,44,
43,83,95,15,56,75,73,72,7,68,42,113,14,74,23,86,16,109,6,85,41,37,24,117,119,
11,107,121,5,70,110,29,89,36,26,101,10,79,118,66,63,18,106,99,97,17,87,25,91
},
asD={
97,84,78,51,40,60,79,44,45,85,98,77,38,39,41,42,43,50,99,70,35,36,37,2,108,
3,86,68,120,33,34,57,101,62,7,63,95,65,66,32,90,119,29,30,31,28,27,64,110,26,
74,75,76,61,6,100,55,54,71,25,58,105,103,4,102,5,89,53,109,24,23,94,104,96,87,
115,49,48,14,69,22,21,20,107,82,114,91,116,13,92,81,8,19,117,80,112,83,52,12
},
cmD={
48,51,52,79,19,18,68,69,90,46,47,49,61,102,17,77,71,89,58,45,59,53,57,62,16,
85,50,93,115,44,81,65,67,103,15,14,30,107,116,43,63,78,94,70,55,13,12,98,117,42,
111,104,120,37,74,121,11,10,20,41,40,88,27,25,91,76,64,9,118,100,39,38,26,24,96,
108,112,8,7,82,75,110,34,23,66,106,56,33,6,83,73,31,22,87,114,2,95,99,5
},
dtD={
55,51,52,110,19,18,29,53,98,46,47,49,101,84,17,82,59,60,68,45,64,54,36,107,16,
87,61,71,102,44,63,86,35,112,15,14,56,104,119,43,81,80,34,85,94,13,12,92,115,42,
105,95,33,117,99,118,11,10,20,41,40,66,32,37,69,97,96,9,111,109,39,38,27,25,106,
120,79,8,7,77,50,78,26,24,62,108,89,48,6,76,57,70,116,31,75,2,65,83,5
},
n1D={
76,52,51,37,38,113,55,48,49,70,61,57,36,56,108,54,47,53,64,83,81,22,35,60,33,
58,46,45,105,92,94,21,86,3,32,62,89,44,34,99,101,20,63,77,31,42,41,66,24,118,
15,19,96,91,30,80,40,39,23,111,14,73,74,90,29,98,75,72,18,7,13,93,88,69,28,
59,104,78,116,6,112,106,68,26,27,25,84,97,110,5,11,100,87,79,121,67,95,85,12
},
n2D={
95,109,36,35,34,33,32,31,85,63,82,37,75,70,68,59,30,56,60,62,108,77,114,20,21,
22,29,88,83,57,119,103,8,23,112,102,24,38,39,27,92,72,18,19,104,107,7,79,98,26,
117,16,17,116,6,1,118,99,105,25,14,15,97,52,93,76,120,61,67,66,13,58,45,84,69,
64,110,55,54,86,10,111,41,42,43,44,40,87,78,91,4,81,121,115,94,90,49,12,5
},
n3D={
79,117,46,42,41,40,43,44,45,56,55,51,66,64,39,67,102,54,58,114,118,100,113,12,13,
14,30,31,32,74,95,73,24,28,101,115,23,71,33,17,20,21,25,96,108,116,22,107,104,16,
82,86,89,98,18,19,47,75,105,15,69,68,65,92,80,106,26,53,60,11,10,121,29,62,112,
48,27,97,61,109,9,99,49,6,7,8,120,78,83,70,5,4,88,87,76,63,119,57,50
},
n4D={
54,51,50,74,77,60,79,56,47,59,58,49,75,64,57,86,53,32,71,85,82,21,22,52,36,
37,83,31,108,119,19,20,121,35,120,38,112,30,29,17,18,106,34,92,89,39,68,65,116,16,
98,117,33,44,43,41,42,93,118,15,14,13,103,88,104,40,69,87,113,84,99,10,7,109,110,
46,81,78,23,91,96,90,6,5,48,45,97,70,12,76,73,100,102,4,3,115,8,72,11
},
n5D={
83,84,96,86,74,82,29,28,27,65,63,55,68,61,60,64,102,69,25,104,112,54,43,40,37,
42,41,103,24,72,76,87,6,62,75,85,106,22,23,70,45,46,7,77,67,73,111,21,95,88,
44,110,38,10,36,35,118,20,114,32,33,93,90,66,79,91,17,19,98,31,94,101,97,80,81,
18,16,50,51,30,117,15,11,12,13,14,121,119,120,4,2,9,116,100,107,115,8,113,48
},
n7D={
54,24,25,26,27,74,75,70,95,53,23,101,86,56,79,107,40,41,42,85,22,117,31,35,34,
33,32,62,102,60,21,73,37,57,81,78,36,55,58,87,20,19,116,61,119,106,8,44,45,65,
113,18,17,98,38,9,39,82,71,64,96,28,16,15,13,112,104,109,108,59,91,29,68,89,12,
120,77,52,69,49,114,66,97,94,11,14,88,51,83,48,80,103,84,76,110,10,105,50,2
},
clD={
62,99,46,57,61,63,67,87,79,47,44,45,50,106,71,98,113,49,18,53,43,97,72,75,64,
65,77,56,17,41,42,85,94,73,60,104,90,15,16,39,80,78,22,23,59,86,107,14,95,38,
54,55,25,24,83,121,118,13,20,37,36,108,103,66,91,40,11,12,74,70,35,88,27,26,58,
69,10,105,81,82,34,33,28,29,96,8,9,116,117,110,89,32,84,76,21,7,48,101,100
},
scD={
59,77,46,70,73,66,67,80,83,47,44,45,97,94,65,69,113,49,18,53,43,103,72,62,63,
64,86,56,17,41,42,114,22,23,78,93,116,15,16,39,101,60,25,24,61,81,107,14,75,38,
54,55,89,108,68,85,90,13,20,37,36,100,27,26,76,120,11,12,117,82,35,79,28,29,58,
71,10,91,92,50,34,33,105,40,57,8,9,121,112,106,95,32,21,88,74,7,48,99,98
},
quD={
59,32,30,29,28,80,82,101,73,54,51,93,92,27,26,78,95,69,39,66,64,102,77,7,5,
16,105,121,38,91,104,120,14,114,25,24,3,36,37,48,62,75,10,94,108,23,6,87,100,46,
50,84,74,63,119,15,52,55,56,45,61,107,110,21,2,22,35,96,112,44,34,18,19,20,106,
97,90,83,89,49,65,17,99,111,1,115,109,31,33,53,76,13,68,88,86,81,67,11,85
},
atD={
66,54,53,51,47,68,103,50,56,100,63,55,52,46,65,48,49,58,60,23,111,70,89,12,11,
10,73,72,87,22,99,78,34,44,24,118,31,104,84,21,94,64,35,109,25,86,32,107,71,
20,102,69,39,120,37,40,41,97,80,19,18,67,38,101,108,85,59,88,79,105,17,98,36,
43,96,110,74,77,7,119,16,90,115,30,29,28,112,5,6,95,15,14,76,117,92,42,57,4,45
},
lAD={
48,47,46,45,44,55,58,63,80,49,86,57,87,43,72,25,24,23,114,50,82,95,66,42,7,
61,98,22,92,104,105,103,93,6,74,8,118,21,20,81,65,62,35,40,60,88,34,110,78,90,
94,89,29,36,37,38,30,102,109,54,53,106,28,120,69,68,31,111,15,75,52,51,27,64,71,
97,32,112,14,117,73,39,26,67,77,59,33,83,13,2,5,12,119,96,108,99,101,4,10
},
lFD={
62,78,49,105,71,90,95,32,31,51,50,48,74,54,64,65,55,116,67,52,101,47,41,42,43,
44,45,121,109,53,61,59,40,58,68,69,46,118,76,63,89,75,39,56,86,81,19,120,21,82,
117,102,38,33,34,115,18,17,16,29,25,60,37,73,87,84,72,119,15,77,24,107,36,88,10,
111,97,13,14,79,12,108,35,96,6,4,104,8,113,57,11,9,114,80,92,2,98,5,110
},
lGD={
108,51,26,86,101,53,33,34,36,77,71,25,93,58,59,32,107,54,38,94,79,24,121,6,7,
8,104,103,40,110,61,23,11,27,76,97,50,80,41,60,49,48,12,112,74,84,102,43,42,90,
72,120,15,88,39,29,9,44,119,65,63,81,16,83,55,118,13,62,68,20,21,22,17,98,91,
69,14,99,105,19,70,89,111,30,31,28,35,92,100,18,52,96,75,67,73,64,87,56,78
},
lJD={
68,44,39,78,60,92,24,66,67,112,119,28,27,26,22,23,102,105,52,88,62,61,85,69,21,
108,30,47,49,91,113,57,18,19,20,46,31,86,110,90,14,16,17,97,65,118,32,77,103,94,
13,56,95,79,53,48,34,82,76,99,12,71,15,101,75,104,35,81,38,10,11,87,37,93,107,
54,45,114,7,9,117,121,120,29,33,36,111,5,6,8,50,63,64,73,83,109,89,4,58
},
lLD={
50,51,52,117,19,18,65,63,58,49,73,57,121,60,17,46,47,48,99,45,61,55,31,71,16,
93,81,74,91,44,90,66,30,83,15,14,85,108,113,43,97,80,29,64,101,13,12,95,115,42,
114,110,28,120,79,116,11,10,20,41,40,56,27,59,69,82,96,9,105,107,39,38,26,102,112,
78,68,8,7,104,103,92,25,32,33,34,35,98,6,76,2,3,118,37,100,94,84,75,5
},
lPD={
67,63,62,75,73,47,66,49,48,104,92,61,120,43,42,41,27,26,25,91,87,60,40,32,34,
33,102,117,24,81,59,85,39,86,88,74,7,79,23,101,58,45,38,98,114,118,6,20,21,96,
57,99,37,4,31,29,110,19,100,54,53,46,36,119,95,84,17,18,78,56,80,83,35,97,82,
15,16,68,69,11,72,113,30,108,13,14,105,76,65,9,28,12,112,8,10,103,121,107,106
},
lQD={
62,92,43,42,41,40,56,113,58,25,111,44,99,59,39,55,90,46,51,24,119,106,117,4,
30,10,38,45,78,23,22,21,19,105,77,86,34,97,91,54,101,57,7,82,68,66,33,75,65,
67,114,61,8,98,76,71,32,47,48,53,50,73,18,108,13,70,31,93,83,87,17,20,6,110,89,
29,37,85,107,69,16,94,118,26,27,36,28,102,74,95,15,80,116,35,103,88,120,12,5
},
lRD={
66,76,52,51,50,48,60,61,59,63,54,53,101,49,47,56,57,58,103,78,102,69,42,19,20,
25,98,79,115,34,35,46,41,96,71,108,31,80,117,33,113,65,40,74,64,55,32,70,114,23,
120,110,39,44,45,36,116,119,9,22,18,89,38,91,77,111,21,84,8,94,17,85,37,86,82,
100,26,28,7,88,16,75,43,68,72,90,27,87,6,97,15,14,121,92,83,29,107,4,5
},
lTD={
109,46,45,44,52,95,48,49,57,72,67,60,43,50,99,47,96,59,24,112,105,114,7,28,37,
30,8,106,23,93,81,63,88,55,36,51,103,21,22,110,76,42,41,107,35,53,19,20,100,94,
69,73,40,39,34,61,18,78,86,27,31,65,56,84,33,108,17,70,98,26,85,90,89,83,32,
38,16,15,117,25,91,102,74,66,29,71,111,14,13,2,11,12,97,104,120,77,119,113,10
},
lUD={
55,82,45,93,59,43,58,76,47,54,78,39,81,51,42,41,77,46,101,53,100,38,28,69,52,
40,29,44,120,50,121,88,27,71,63,66,30,35,17,49,113,111,26,73,67,96,31,74,16,48,
36,37,25,83,86,89,32,106,115,68,22,105,24,75,70,64,33,85,112,87,5,114,23,92,90,
94,34,109,11,62,4,91,117,20,19,18,118,110,10,80,3,2,119,72,79,84,116,8,9
},
lVD={
69,63,50,67,45,42,41,55,76,95,58,49,47,46,48,40,51,72,103,119,113,70,35,71,79,
39,34,38,37,97,91,54,27,52,57,59,30,92,89,22,99,56,26,53,73,80,31,106,105,21,
110,85,25,66,104,75,32,118,17,8,7,87,24,107,84,74,33,120,16,121,6,68,114,28,78,
29,90,14,15,116,4,5,93,61,19,65,94,13,101,2,3,64,98,60,44,81,109,12,102
},
lYD={
98,112,20,22,23,24,25,73,70,63,18,19,107,87,84,36,37,48,91,55,17,117,31,79,78,
51,29,56,92,54,16,72,30,80,90,110,28,59,85,53,15,105,118,27,77,26,38,60,106,49,
14,13,121,119,32,39,102,93,44,65,104,12,120,75,33,40,41,42,43,64,76,10,8,71,34,
94,99,58,89,61,116,108,7,103,35,50,74,97,9,57,100,113,6,4,115,114,88,67,2
},
ctD={
54,22,21,20,19,59,92,93,121,24,23,53,103,18,77,57,87,76,79,25,96,73,91,17,13,
14,116,50,105,26,101,107,113,15,84,11,82,31,32,27,109,98,16,86,89,12,9,30,120,
28,33,51,52,106,70,112,10,8,118,111,34,37,38,42,67,102,117,7,6,104,65,43,72,
97,49,48,47,100,5,114,62,44,45,108,61,40,39,99,4,94,66,115,58,85,56,88,36,68,3
},
usD={
85,80,71,36,48,33,42,39,46,95,112,52,35,44,31,37,38,72,76,75,105,27,28,29,30,
34,61,66,119,24,25,26,65,70,32,43,68,107,118,23,87,78,50,45,40,41,54,81,98,22,
92,84,49,47,51,53,60,83,116,21,121,117,89,73,110,88,16,15,9,20,19,120,86,91,
108,99,96,13,8,104,17,18,62,63,64,67,69,94,7,102,10,77,57,58,59,56,55,90,6
},
oqD={
19,18,17,117,105,34,35,104,97,68,113,16,74,98,33,25,24,77,48,108,103,15,14,115,
32,27,26,94,47,85,87,89,13,114,31,23,86,52,46,84,118,110,12,29,30,50,22,56,116,
73,70,112,11,28,67,93,53,57,64,66,63,9,10,20,106,107,58,88,102,100,7,8,121,21,
92,91,111,39,40,61,6,101,83,71,65,62,51,38,78,4,5,75,120,69,109,59,54,37,79
};

t_chPtr downC={ // ASCII table of pointers to down draining character squares.
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// NUL SOH  STX  ETX  EOT  ENQ  ACK  BEL  BS   HT   LF   VT   FF   CR   SO   SI
  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
// DLE DC1  DC2  DC3  DC4  NAK  SYN  ETB  CAN  EM   SUB  ESC   FS   GS   RS   US
  spL, exD, dqD, otU, doU, pcU, amD, oqD, opU, cpU, asD, plL, cmD, miU, dtD, fsL,
// sp   !    "    #    $    %    &    '    (    )    *    +    ,    -    .    /
  n0U, n1D, n2D, n3D, n4D, n5D, n9U, n7D, n8U, n6U, clD, scD, oaU, eqU, caU, quD,
// 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ?
  atD, lAD, lBU, lCU, lDU, lEU, lFD, lGD, lHU, lIU, lJD, lKU, lLD, lWU, lNU, lOU,
// @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O
  lPD, lQD, lRD, lSU, lTD, lUD, lVD, lMU, lXU, lYD, lZU, obU, fsL, cbU, ctD, usD,
// P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _
  oqD, lAD, lBU, lCU, lDU, lEU, lFD, lGD, lHU, lIU, lJD, lKU, lLD, lWU, lNU, lOU,
// `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o
  lPD, lQD, lRD, lSU, lTD, lUD, lVD, lMU, lXU, lYD, lZU, ocU, vbU, ccU, tiU,NULL
// p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL
};

t_chRot downR={ // Character rotation
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    3,0,0,2,2,2,0,4,6,6,0,3,0,2,0,5,2,0,0,0,0,0,2,0,2,2,0,0,6,2,6,0,
//    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
    0,0,6,6,6,6,0,0,2,2,0,6,0,2,2,2,0,0,0,2,0,0,0,2,2,0,2,6,3,6,0,0,
//  @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
    0,0,6,6,6,6,0,0,2,2,0,6,0,2,2,2,0,0,0,2,0,0,0,2,2,0,2,6,6,6,2,0
//  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
};
//==================================== water retention start =========================================

const char *storeAllocFail="Storage allocation failed";
void reportError(const char *msg) { printf("\a\nError: %s.\n", msg); }
//   -----------

bool **drainL=NULL, **drainR=NULL, **drainU=NULL, **drainD=NULL, **textWet;
int  **cWater=NULL, **iWater=NULL, **oWater=NULL, maxNumIn, maxNumOut, allocatedQueueSize=0, qIndex=0;
struct t_Cell { int priority, row, col; }; t_Cell *Queue=NULL;

void freeQueue() { if (Queue!=NULL) { free(Queue); Queue=NULL; } }
//   ---------

bool allocateQueue(const int size) {
//   -------------
  bool ok=T;
  if (allocatedQueueSize<size) { freeQueue();
    Queue=(t_Cell *) malloc(size*sizeof(t_Cell)); if ((ok=(Queue!=NULL))) allocatedQueueSize=size;
  }
  return ok;
} // allocateQueue

bool increaseQueue() {
//   -------------
  const int size=allocatedQueueSize+allocatedQueueSize;

  t_Cell *tmp=(t_Cell *) malloc(size*sizeof(t_Cell));
  if (tmp==NULL) { reportError(storeAllocFail); return F; }
  for (int i=0; i<qIndex; i++) tmp[i]=Queue[i];
  freeQueue(); Queue=tmp; allocatedQueueSize=size; return T;
} // increaseQueue;

void initBounds(const int n, const int maxNum, int **square, int **water) {
//   ----------
  const int m=n-1;
  for (int r=0; r<n; r++) { water[r][0]=square[r][0]; water[r][m]=square[r][m]; }
  for (int c=1; c<m; c++) {	water[0][c]=square[0][c]; water[m][c]=square[m][c]; }
  for (int r=1; r<m; r++) for (int c=1; c<m; c++) water[r][c]=maxNum; qIndex=0;
} // initBounds

void pushQueue(const int priority, const int row, const int col) {
//   ---------
  t_Cell cell; cell.priority=priority; cell.row=row; cell.col=col; Queue[qIndex++]=cell;
} //  pushQueue

bool insertQueue(const int priority, const int row, const int col) {
//   -----------
  if ((qIndex>=allocatedQueueSize)&&!increaseQueue()) return F;
  t_Cell cell; cell.priority=priority; cell.row=row; cell.col=col;

  int i=qIndex-1; while (Queue[i].priority<priority) { Queue[i+1]=Queue[i]; if (--i<0) break; }
  Queue[++i]=cell; ++qIndex; return T;
} // insertQueue

void popQueue(t_Cell *cell) { *cell=Queue[--qIndex]; }
//   --------

bool queueBorder(const int m, int **water) {
//   -----------
  pushQueue(water[1][0], 1, 0); if (!insertQueue(water[1][m], 1, m)) return F;

  for (int r=2; r<m; r++) {
	  if (!insertQueue(water[r][0], r, 0)) return F; if (!insertQueue(water[r][m], r, m)) return F;
  }
  for (int c=1; c<m; c++) {
	  if (!insertQueue(water[0][c], 0, c)) return F; if (!insertQueue(water[m][c], m, c)) return F;
  }
  return T;
} // queueBorder

bool computeBounds(const int p, const int r, const int c, const int m, int **square, int **water) {
//   -------------
  if ( ((0<r)&(r<(m)))&((0<c)&(c<(m))) ) {
    int *bp=&water[r][c]; const int tmp=max(square[r][c],p);
	  if (tmp<*bp) { *bp=tmp; if (!insertQueue(tmp, r, c)) return F; }
  } return T;
} // computeBounds

/*
 *  Based on an algorithm of Gareth McCaughan supplied by Craig Knecht.
 */
bool getWater(const int n, const int maxNum, int **square, int **water) {
//   --------
  const int m=n-1; initBounds(n, maxNum, square, water);
  if (n>1) { if (!queueBorder(m, water)) return F;
    while (qIndex!=0) {
   	  t_Cell cell; popQueue(&cell); const int p=cell.priority, r=cell.row, c=cell.col;
	    if (!computeBounds(p, r-1, c, m, square, water)) return F;
      if (!computeBounds(p, r+1, c, m, square, water)) return F;
 	    if (!computeBounds(p, r, c-1, m, square, water)) return F;
      if (!computeBounds(p, r, c+1, m, square, water)) return F;
    }
  } return T;
} // getWater

void getDrainage(const int n, int **x, int **w) {
//   -----------
  if (n==1) { drainL[0][0]=T; drainR[0][0]=T; drainU[0][0]=T; drainD[0][0]=T; }
  else {
    const int m=n-1, l=m-1;
    for (int r=0; r<n; ++r) {
      drainL[r][0]=T; drainR[r][0]=(x[r][0]>w[r][1]); drainR[r][m]=T; drainL[r][m]=(x[r][m]>w[r][l]);
      if (r>0) { drainU[r][0]=(x[r][0]>w[r-1][0]); drainU[r][m]=(x[r][m]>w[r-1][m]); }
      if (r<m) { drainD[r][0]=(x[r][0]>w[r+1][0]); drainD[r][m]=(x[r][m]>w[r+1][m]); }
    }
    for (int c=0; c<n; ++c) {
      drainU[0][c]=T; drainD[0][c]=(x[0][c]>w[1][c]); drainD[m][c]=T; drainU[m][c]=(x[m][c]>w[l][c]);
      if (c>0) { drainL[0][c]=(x[0][c]>w[0][c-1]); drainL[m][c]=(x[m][c]>w[m][c-1]); }
      if (c<m) { drainR[0][c]=(x[0][c]>w[0][c+1]); drainR[m][c]=(x[m][c]>w[m][c+1]); }
    }

    for (int r=1; r<m; ++r) for (int c=1; c<m; ++c) {
      drainL[r][c]=(x[r][c]>w[r][c-1]); drainR[r][c]=(x[r][c]>w[r][c+1]);
      drainU[r][c]=(x[r][c]>w[r-1][c]); drainD[r][c]=(x[r][c]>w[r+1][c]);
    }
  }
} // getDrainage
//=========================================== squares start ===========================================

bool *numberUsed=NULL, zeroBased; char *textLine=NULL;
const int startSize=25, maxNout=400; // Max order of square for Square.html and Water.html.
int **cSquare=NULL, **tSquare=NULL, **iSquare=NULL, **oSquare=NULL, allocatedSize, lineLength,
    smallestRead=INT_MAX, biggestRead=INT_MIN; Uint MagicConstant; 
enum magicType { notMagic, otherMagic, normalMagic };

void getMagicConstant(const Uint n) { const Uint nn=n*n, nnp1=nn+1; MagicConstant=n&1 ? nnp1/2*n : n/2*nnp1; }
//   -----------------

magicType isMagic(const int n) {
//        -------
  int **x=iSquare, sumX, sumY, sumXY=0, sumYX=0, chkSum=0; const int m=n-1;

  for (int i=0; i<n; i++) {
    sumX=0; sumY=0;
    for (int j=0; j<n; j++) { sumX+=x[i][j]; sumY+=x[j][i]; } if (i==0) chkSum=sumX;
    if ((sumX!=chkSum)|(sumY!=chkSum)) return notMagic; sumXY+=x[i][m-i]; sumYX+=x[i][i];
  }
  if ((sumXY!=chkSum)|(sumYX!=chkSum)) return notMagic; return otherMagic;
} // isMagic

magicType isNormal(const int n) {
//        --------
  const int min=zeroBased ? 0 : 1, max=n*n+min-1, m=n-1;
  int **x=iSquare, chkSum=0, sumX, sumY, sumXY=0, sumYX=0;
  const Uint magicConstant=zeroBased ? MagicConstant-n : MagicConstant;

  for (int i=min; i<=max; i++) numberUsed[i]=F;
  for (int i=0; i<n; i++) {
    sumX=0; sumY=0;
    for (int j=0; j<n; j++) { const int tmp=x[i][j]; numberUsed[tmp]=T; sumX+=tmp; sumY+=x[j][i]; }
    if (i==0) chkSum=sumX; if ((sumX!=chkSum)|(sumY!=chkSum)) return notMagic;
    sumXY+=x[i][m-i]; sumYX+=x[i][i];
  }
  if ((sumXY!=chkSum)|(sumYX!=chkSum)) return notMagic;
  if (chkSum!=magicConstant) return otherMagic;
  for (int i=min; i<=max; i++) if (!numberUsed[i]) return otherMagic; return normalMagic;
} // isNormal
 
bool checkSquare(const int n, bool input, char *iSqFn) {
//   -----------
  magicType mt; if ( (smallestRead<0)|(biggestRead>n*n) ) mt=isMagic(n); else mt=isNormal(n);
  if ((mt==notMagic)|(mt==otherMagic)) {
    if (input) printf("The square %s is not %smagic.\n", iSqFn, mt==notMagic ? "" : "normal ");
    else if (n!=2) { printf("\aProgram error: The default square is not normal magic.\n"); return F; } 
  } return T;
} // checkSquare

void getNextLine(FILE *rfpT) {
//   -----------
  int c=getc(rfpT);
  for (int i=0; i<lineLength; ++i) {
    if (c=='\t') c=' '; if ((c=='\n')|(c=='\r')|(c==EOF)) textLine[i]=' '; else { textLine[i]=c; c=getc(rfpT); }
  }
  while ((c!='\n')&(c!='\r')&(c!=EOF)) c=getc(rfpT);
} // getNextLine

typedef void (*t_Rotate)(const int, const int, const int);
void rotate_0  (const int n, const int i, const int j) { cSquare[i][j]    =tSquare[i][j]; };
void rotate_90 (const int n, const int i, const int j) { cSquare[j][n-i]  =tSquare[i][j]; };
void rotate_180(const int n, const int i, const int j) { cSquare[n-i][n-j]=tSquare[i][j]; };
void rotate_270(const int n, const int i, const int j) { cSquare[n-j][i]  =tSquare[i][j]; };
void rotate_Y  (const int n, const int i, const int j) { cSquare[i][n-j]  =tSquare[i][j]; };
void rotate_XY (const int n, const int i, const int j) { cSquare[n-j][n-i]=tSquare[i][j]; };
void rotate_X  (const int n, const int i, const int j) { cSquare[n-i][j]  =tSquare[i][j]; };
void rotate_YX (const int n, const int i, const int j) { cSquare[j][i]    =tSquare[i][j]; };
static t_Rotate rotateCell[] =
{ rotate_0,    // no rotation
  rotate_90,   
  rotate_180,
  rotate_270,
  rotate_Y,    // about vertical axis,    (mirror)
  rotate_XY,   // about forward diagonal, (mirror + rotate_90)
  rotate_X,    // about horizontal axis,  (mirror + rotate_180)
  rotate_YX    // about back diagonal,    (mirror + rotate_270)
};

void rotateSquare(const int rotation) {
//   ------------
  t_Rotate rotate=rotateCell[rotation];
  for (int i=0; i<fontN; i++) for (int j=0; j<fontN; j++) rotate(fontN-1, i, j);
} // rotateSquare

void fillSquare(char *t) {
//   ----------
  const int m=fontN-1, l=m-1, mc=(fontNN+1)/2*fontN; int **x=tSquare, i=0;

  for (int c=0; c<l; ++c) x[0][c]=t[i++];
  for (int r=1; r<m; ++r) for (int c=0; c<m; ++c) x[r][c]=t[i++];
  for (int r=1; r<m; ++r) { x[r][m]=mc; for (int c=0; c<m; ++c) x[r][m]-=x[r][c]; }
  for (int c=0; c<l; ++c) { x[m][c]=mc; for (int r=0; r<m; ++r) x[m][c]-=x[r][c]; }
  x[m][m]=mc; for (int r=0; r<m; ++r) x[m][m]-=x[r][r];
  x[0][m]=mc; for (int r=1; r<=m; ++r) x[0][m]-=x[r][m];
  x[0][l]=mc-x[0][m]; x[m][l]=mc-x[m][m];
  for (int c=0; c<l; ++c) { x[0][l]-=x[0][c]; x[m][l]-=x[m][c]; }
} // fillSquare

int firstChar=' ';
void getcSquare(FILE *rfpT, const int i, const int j, bool *wet) {
//   ----------
  if (j==0) getNextLine(rfpT); int c=textLine[j], r=0; char *t=NULL;

  *wet=(iWater[i][j]>iSquare[i][j]);
  if (*wet&(c!=' ')) printf("%c at row %d, col %d in water is not visible.\n", c, i+1, j+1);
  t=drainL[i][j] ? leftC[c] : drainR[i][j] ? rightC[c] : drainU[i][j] ? upC[c] : downC[c];
  r=drainL[i][j] ? leftR[c] : drainR[i][j] ? rightR[c] : drainU[i][j] ? upR[c] : downR[c];
  if (t==NULL) { printf("Program error: Character %d is not available.\n", c); c=' '; t=leftC[c]; r=0; }
  if ((i==0)&(j==0)) firstChar=c; fillSquare(t); rotateSquare(r);
} // getcSquare

void getCharSquare(const int drain) {
//   -------------
  char *t=NULL; const int c=firstChar; int r=0;
  switch (drain) {
    case 'R': t=rightC[c]; r=rightR[c]; break;
    case 'U': t=upC[c];    r=upR[c];    break;
    case 'D': t=downC[c];  r=downR[c];  break;
    default:  t=leftC[c];  r=leftR[c];  break;
  };
  fillSquare(t); rotateSquare(r);
} // getCharSquare

bool validOrder(const int n) {
//   ----------
  if (n<=0) { printf("\aError: Order %d is not a positive integer.\n", n); return F; } return T;
}// validOrder

bool checkOrder(const int n) {
//   ----------
  if (validOrder(n)) {
    const int mn=fontN*n, q=INT_MAX/mn;
    if ((mn<0)|(mn>q)) { printf("\aError: Integer overflow for (%d x %d) squared.\n", fontN, n);
      return F;
    }
    return T;
  }
  return F;
} // checkOrder

int textLineLength(FILE *rfpT, const int maxN) {
//  --------------
  int lines=0, longest=0; bool fileEnd=F;

  while (!fileEnd) { int l=0;
    while (T) { const int c=getc(rfpT);
      if ((c=='\n')|(c=='\r')|(c==EOF)) { if (l>longest) longest=l;
        if (c==EOF) { if (l==0) --lines; fileEnd=T; } break;
      } ++l;
    } ++lines;
  }
  int n=max(lines,longest);
  if (n>maxN) {
    if (n==lines) printf("\aError: Number of text lines limited to %d.\n", maxN);
    else printf("\aError: Text line limited to %d characters.\n", maxN); n=0;
  } else if (n==0) printf("\aError: No text in file.\n"); else if (!checkOrder(n)) n=0;
  rewind(rfpT); return n;
} // textLineLength
//---------------------------------- zero retention square start -------------------------------------

void makeActual(int **x, const int n) {
//   ----------
  const int nn=n*n;
  if (n&1) {
    const int midc=(nn+1)/2; for (int i=0; i<n; i++) for (int j=0; j<n; j++) x[i][j]+=midc;
  } else {
    const int pPlus=nn/2, mPlus=pPlus+1;
    for (int i=0; i<n; i++) for (int j=0; j<n; j++) x[i][j]+=x[i][j]>0 ? pPlus : mPlus;
  }
} // makeActual

void seed_rand() { srand((unsigned int)time(NULL)); }
//   ---------

int random_(int x) { return rand()%x; }
//  -------

void get2x2(int **x) {
//   ------
  bool used[4]={ F, F, F, F }; int v=random_(4); used[v]=T; x[0][0]=++v;
  v=random_(4); while (used[v]) v=random_(4); used[v]=T; x[0][1]=++v;
  v=random_(4); while (used[v]) v=random_(4); used[v]=T; x[1][0]=++v;
  for (int i=0; i<4; ++i) if (!used[i]) { x[1][1]=i+1; break; }
} // get2x2

void makeEven(int **x, const int size) {
//   --------
  if (size==2) get2x2(x);
  else {
    int i, j, k, o, n, m, v=1; // 0.5;

    // fill center 4x4
    o=(size-4)/2; k=o+1; m=o+2; n=o+3;
    x[m][k]=-v; x[m][m]=v++; x[n][m]=-v; x[n][k]=v++; x[n][n]=-v; x[n][o]=v++; x[m][o]=-v; x[m][n]=v++;
    x[o][m]=-v; x[o][k]=v++; x[k][k]=-v; x[k][m]=v++; x[k][o]=-v; x[k][n]=v++; x[o][n]=-v; x[o][o]=v++;
   
    for (i=6; i<=size; i+=2) {
      o=(size-i)/2; n=o+i-1; k=(o+n-1)/2; m=k+1; int tm=m-1, tp=o+1, lm=o+1, lp=m;
      if (i%4!=0) { //------------------------------   // singly even     
        j=(k-o+1)/2; while (j--) { x[o][tm]=-v; x[n][tm++]=v++; x[n][tp]=-v; x[o][tp++]=v++; }
        x[o][tm]=-v; x[n][tm++]=v++; x[lm][o]=-v; x[lm++][n]=v++; 
        j=(k-o-1)/2; while (j--) { x[lp][n]=-v; x[lp++][o]=v++; x[lm][o]=-v; x[lm++][n]=v++; }
        x[n][n]=-v; x[o][o]=v++; /* NW */ x[n][o]=-v; x[o][n]=v++; /* NE */ x[lp][n]=-v; x[lp++][o]=v++;
        j=(n-m-1)/2; while (j--) { x[lm][o]=-v; x[lm++][n]=v++; x[lp][n]=-v; x[lp++][o]=v++; }
        x[lp][n]=-v; x[lp++][o]=v++; x[o][tm]=-v; x[n][tm++]=v++;
        j=(n-m-1)/2; while (j--) { x[n][tp]=-v; x[o][tp++]=v++; x[o][tm]=-v; x[n][tm++]=v++; }
        x[lm][o]=-v; x[lm][n]=v++;
      } else { //-----------------------------------   // doubly even
        x[o][tm]=-v; x[n][tm++]=v++;
        j=(k-o)/2; while (j--) { x[n][tp]=-v; x[o][tp++]=v++; x[o][tm]=-v; x[n][tm++]=v++; }
        if (i==8) { x[lp][n]=-v; x[lp++][o]=v++; }
        else { x[lm][o]=-v; x[lm++][n]=v++; x[lp][n]=-v; x[lp++][o]=v++;
          j=(k-o-5)/2; while (j--) { x[lm][o]=-v; x[lm++][n]=v++; x[lp][n]=-v; x[lp++][o]=v++; }
          x[lp][n]=-v; x[lp++][o]=v++;
        } 
        x[lm][o]=-v; x[lm++][n]=v++; x[lm][o]=-v; x[lm++][n]=v++;
        x[n][n] =-v; x[o][o]=v++; /* NW */ x[n][o] =-v; x[o][n]=v++; /* NE */
        x[lp][n]=-v; x[lp++][o]=v++; x[lp][n]=-v; x[lp++][o]=v++;
        j=(n-m-2)/2; while (j--) { x[lm][o]=-v; x[lm++][n]=v++; x[lp][n]=-v; x[lp++][o]=v++; }
        x[k][o]=-v; x[k][n]=v++;
        j=(n-m)/2; while (j--) {  x[o][tm]=-v; x[n][tm++]=v++; x[n][tp]=-v; x[o][tp++]=v++; }
        x[o][tm]=-v; x[n][tm]=v++;
      }
    }
    makeActual(x, size);
  }
} // makeEven

void makeOdd(int **x, const int size) {
//   -------
  int i, j, o, n, m, v=1; m=(size-1)/2; x[m][m]=0;
  for (i=3; i<=size; i+=2) { o=(size-i)/2; n=o+i-1; m=(o+n)/2;
    for (j=o+1; j<m; j++) { x[n][j]=-v; x[o][j]=v++; /* NNW */ x[j][o]=-v; x[j][n]=v++; /* ENE */ }
    x[n][o]=-v; x[o][n]=v++; /* NE */ x[m][o]=-v; x[m][n]=v++; /* E */
    x[n][n]=-v; x[o][o]=v++; /* NW */ x[o][m]=-v; x[n][m]=v++; /* S */
    for (j=m+1; j<n; j++) { x[o][j]=-v; x[n][j]=v++; /* SSE */ x[j][n]=-v; x[j][o]=v++; /* WSW */ }
  }
  makeActual(x, size);
} // makeOdd
//==================================== store allocation start ======================================

void freeBoolSquare(bool ***square, const int size) {
//   --------------
  if (*square!=NULL) {
    for (int i=0; i<size; i++) free((*square)[i]); free(*square); *square=NULL;
  }
} // freeBoolSquare

void freeIntSquare(int ***square, const int size) {
//   -------------
  if (*square!=NULL) { for (int i=0; i<size; i++) free((*square)[i]); free(*square); *square=NULL; }
} // freeIntSquare

void freeStore() {
//   ---------
  free(textLine); textLine=NULL; freeIntSquare(&cSquare, fontN);
  freeIntSquare(&tSquare, fontN); freeIntSquare(&cWater, fontN);
  freeIntSquare(&iSquare, allocatedSize); freeIntSquare(&iWater, allocatedSize);
  freeIntSquare(&oSquare, fontN*allocatedSize); freeIntSquare(&oWater, fontN*allocatedSize);
  freeBoolSquare(&drainL, allocatedSize); freeBoolSquare(&drainR, allocatedSize);
  freeBoolSquare(&drainU, allocatedSize); freeBoolSquare(&drainD, allocatedSize);
  freeBoolSquare(&textWet, allocatedSize); free(numberUsed); numberUsed=NULL;
  freeQueue(); allocatedSize=0; allocatedQueueSize=0;
} // freeStore

bool allocateIntSquare(int ***square, const int size) {
//   -----------------
  *square=(int**) malloc(size*sizeof(int*)); bool ok=(*square!=NULL);
  if (ok) {
    int numAllocated=size;
    for(int i=0; i<size; i++) {
      int *p=(int*) malloc(size*sizeof(int)); (*square)[i]=p;
      if (p==NULL) { numAllocated=i; ok=F; break; }
    }
    if (!ok) freeIntSquare(square, numAllocated);
  }
  return ok;
} // allocateIntSquare

bool allocateBoolSquare(bool ***square, const int size) {
//   ------------------
  *square=(bool**) malloc(size*sizeof(bool*)); bool ok=(*square!=NULL);
  if (ok) {
    int numAllocated=size;
    for(int i=0; i<size; i++) {
      bool *p=(bool*) malloc(size*sizeof(bool)); (*square)[i]=p;
      if (p==NULL) { numAllocated=i; ok=F; break; }
    }
    if (!ok) freeBoolSquare(square, numAllocated);
  }
  return ok;
} // allocateBoolSquare 

bool allocateStore(int size) {
//   -------------
  bool ok=T; if (size<startSize) size=startSize;
  if (size>allocatedSize) {
    const int oSize=fontN*size; freeStore();
    ok=((textLine=(char *)malloc(size*sizeof(char)))!=NULL);
    if (ok) ok=allocateIntSquare(&cSquare, fontN); if (ok) ok=allocateIntSquare(&tSquare, fontN);
    if (ok) ok=allocateIntSquare(&cWater, fontN); if (ok) ok=allocateIntSquare(&iSquare, size);
    if (ok) ok=allocateIntSquare(&iWater, size); if (ok) ok=allocateIntSquare(&oSquare, oSize);
    if (ok) ok=allocateIntSquare(&oWater, oSize); if (ok) ok=allocateBoolSquare(&textWet, oSize);
    if (ok) ok=allocateBoolSquare(&drainL, size); if (ok) ok=allocateBoolSquare(&drainR, size);
    if (ok) ok=allocateBoolSquare(&drainU, size); if (ok) ok=allocateBoolSquare(&drainD, size);
    if (ok) ok=allocateQueue(fontNN*size*size);
    if (ok) ok=((numberUsed=(bool *)malloc((size*size+1)*sizeof(bool)))!=NULL);
    if (ok) allocatedSize=size; else freeStore();
  }
  return ok;
} //allocateStore
//================================== html start ===================================

const int bufSize=1024, msgSize=bufSize+100;
int tableWidth(const int n) { return n*25; }
//  ----------

bool writeHead(FILE *wfp, const int n, const int which) {
//   ---------
  const char *title=which==1 ? "Composite Square" : which==2 ? "Water Retained" :
                    which==3 ? "Water Text" : "Character";
  if (fprintf(wfp,
    "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
    " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
    "<html lang=\"en\" xml:lang=\"en\" "
    "xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
    "<head>\n<title>%s</title>\n"
    "<style type=\"text/css\" id=\"internalStyle\">\n"
    "  body { font-family : Verdana, Arial, Helvetica,"
    " sans-serif; color : #000080 }\n"
    "  caption { font-size : medium; font-weight : bold; }\n", title)<0)
    return F;

  if (which==3) {
    return fprintf(wfp,
      "  td { width : 0.5px; height : 0.5px; }\n"
      "   .wd { background-color : #0050f0; }\n"
      "   .ww { background-color : #0050f0; }\n"
      "   .dw { background-color : #f4f4f4; }\n"
      "   .dd { background-color : #f8f8f8; }\n"
      "</style>\n</head>\n\n<body>\n\n")>0;
  } else {
    const int cellHeight=tableWidth(n)*(n<100 ? 8 : 9)/(10*n)-2; 
    const double fontSize=n<10 ? 10.5 : n<32 ? 8. : 5.6;
      // Numbers > 9999 are split over 2 lines, forcing a higher profile.
    return fprintf(wfp,
      "  td { font-size : %.1fpt; text-align : center; height : %dpx; }\n"
      "    .wd, .dw, .dd { border : inset white thin; }\n"
      "    .wd { background-color : #00ffff; }\n"
      "    .dw { background-color : #ececec; }\n"
      "    .dd { background-color : #f8f8f8; }\n"
      "</style>\n</head>\n\n<body>\n\n", fontSize, cellHeight)>0;
  }
} // writeHead

void computeCapacity(const int n, Uint *unitsB, Uint *units, Uint *cells) {
//   ---------------
  const Uint b=1000000000; Uint count=0, uB=0, u=0;
  for (int r=0; r<n; r++) for (int c=0; c<n; c++) {
	  Uint delta=oWater[r][c]-oSquare[r][c];
    if (delta!=0) { ++count; u+=delta; if (u>=b) { ++uB; u-=b; } }
 	}
  *unitsB=uB; *units=u ; *cells=count;
} // computeCapacity

void formatNum(char *s, const Uint b, const Uint u) {
//   ---------
  const int ct=1000, cm=ct*ct; const Uint m=u/cm, t=(u%cm)/ct, r=u%ct;
  if (b>0) snprintf(s, 20, "%u,%03u,%03u,%03u", b, m, t, r);
  else if (m>0) snprintf(s, 20, "%u,%03u,%03u", m, t, r);
  else if (t>0) snprintf(s, 20, "%u,%03u", t, r); else snprintf(s, 20, "%u", r);
} // formatNum

bool writeCapacity(FILE *wfp, const int n) {
//   -------------
  Uint unitsB, units, cells; computeCapacity(n, &unitsB, &units, &cells);
  char u[20], c[20]; formatNum(u, unitsB, units); formatNum(c, 0, cells);
  return fprintf(wfp, "<h4>Order %d, cells retaining water %s (%2.1f%%), units retained %s</h4>\n",
                      n, c, (double)(100*cells)/(n*n), u)>0;
} // writeCapacity

bool writeEmplyCell(FILE *wfp, const int n, const char *_class, const int r) {
//   --------------
  char v[bufSize];
  if (r==0) {
    strcpy(v, "&nbsp;&nbsp;"); if (n>9) strcat(v, "&nbsp;&nbsp;");
    if (n>31) strcat(v, "&nbsp;&nbsp;");
  } else strcpy(v, "");
  return fprintf(wfp, "<td class=\"%s\">%s\n", _class, v)>0;
} // writeEmplyCell

bool writeCharCell(FILE *wfp, const char *_class, const int v) {
//   -------------
  char x[bufSize];
  if (v<100) snprintf(x, bufSize, "&nbsp;%d&nbsp;", v); else snprintf(x, bufSize, "%d", v);
  return fprintf(wfp, "<td class=\"%s\">%s\n", _class, x)>0;
} // writeCharCell

bool writeCell(FILE *wfp, const char *_class, const int v) {
//   ---------
  if (v>9999) return fprintf(wfp, "<td class=\"%s\">%d,<br/>&nbsp;%03d\n", _class, v/1000, v%1000)>0;
  return fprintf(wfp, "<td class=\"%s\">%d\n", _class, v)>0;
} // writeCell

bool writeMinCell(FILE *wfp, const char *_class) { return fprintf(wfp, "<td class=\"%s\">\n", _class)>0; }
//   ------------

bool writeWaterSquare(FILE *wfp, const int n, const int which, const char *drain) {
//   ----------------
  if (which==3) {
    if (fprintf(wfp, "<table summary=\"Square shows water retained.\">\n")<0) return F;
    if (fprintf(wfp, "<caption>Water Text</caption>\n")<0) return F;
    for (int r=0; r<n; r++) {
      if (fprintf(wfp, "<tr>\n")<0) return F;
	     for (int c=0; c<n; c++) {
	       const int v=oSquare[r][c], w=oWater[r][c];
         const char *s=v==w ? "dw" : textWet[r][c] ? "ww" : "wd"; if (!writeMinCell(wfp, s)) return F;
	     }
    }
  } else {
    const int tw=tableWidth(n), cw=tw/n-2;
    const char *summary=((which==1)|(which==4))
            ? "Square with cells retaining water colored aqua."
            : "Square shows the units of water retained.",
         *caption=which==1 ? "Composite Square" : which==4 ? drain : "Retained Water";
    if (fprintf(wfp,
          "<table width =\"%d\" border=\"1\" summary=\"%s\" \n"
          "<colgroup span=\"%d\" width=\"%d\"></colgroup>\n",
          tw, summary, n, cw)<0) return F;
    if (fprintf(wfp, "<caption>%s</caption>\n", caption)<0) return F;
    if ((which==1)|(which==4)) {
      for (int r=0; r<n; r++) {
        if (fprintf(wfp, "<tr>\n")<0) return F;
   	    for (int c=0; c<n; c++) {
	        const int v=oSquare[r][c]; const char *s=v==oWater[r][c] ? "dd" : "wd";
          if (n==fontN) { if (!writeCharCell(wfp, s, v)) return F; }
          else { if (!writeCell(wfp, s, v)) return F; }
	      }
      }
    } else {
      for (int r=0; r<n; r++) {
        if (fprintf(wfp, "<tr>\n")<0) return F;
	      for (int c=0; c<n; c++) {
	        const int v=oSquare[r][c], w=oWater[r][c];
          if (v==w) { if (!writeEmplyCell(wfp, n, "dw", r)) return F; }
          else { if (!writeCell(wfp, "wd", w-v)) return F; }
	      }
      }
    }
  }
  return (fprintf(wfp, "</table>\n")>0);
} // writeWaterSquare

bool writeFoot(FILE *wfp) { return fprintf(wfp, "</body>\n</html>")>0; }
//   ---------

bool outputHTML(FILE *wfp, const int n, const int which, const char *drain) {
//   ----------
  if (!writeHead(wfp, n, which)) return F; if (!writeCapacity(wfp, n)) return F;
  if (!writeWaterSquare(wfp, n, which, drain)) return F; return writeFoot(wfp);
} // outputHTML
//============================================= I/O start ==============================================

void zeroBase(int **x, const int n) {
//   --------
  for (int r=0; r<n; r++) for (int c=0; c<n; c++) --x[r][c]; --smallestRead; --biggestRead; zeroBased=T;
} // zeroBase

bool readSquare(FILE *rfp, const int n, int **x, char *FName) {
//   ----------
  int smallest=INT_MAX, biggest=INT_MIN;

  for (int r=0; r<n; r++) {
    for (int c=0; c<n; c++) {
	    int tmp, rv;

      if ( (rv=fscanf(rfp, "%d", &tmp))==1) {
        if (tmp<smallest) smallest=tmp; if (tmp>biggest) biggest=tmp; x[r][c]=tmp;
      } else {
        if ( (rv!=EOF)|(r!=0)|(c!=0) ) printf("\a\nError reading square from file %s\n", FName); return F;
      }
    }
  }
  smallestRead=smallest; biggestRead=biggest; zeroBased=smallestRead==0;
  if (!zeroBased) zeroBase(x, n); return T;
} // readSquare

void ckearLine(int c) { while (c!='\n') c=getchar(); }
//   ---------

bool getFileName(char *buf, const int size) {
//   -----------
  int c, i=0; char *s=buf;
  do { c=getchar(); } while ((c==' ')|(c=='\t')|(c=='\n') ); *s=c;
  while (i++<size) if ( (*++s=getchar())=='\n') break;
  if (*s!='\n') { printf("\nFile name too long.\n"); ckearLine(*s); return F; }
  *s='\0'; return T;
} // getFileName

bool getY() {
//   ----
  int c; do { c=getchar(); } while ((c==' ')|(c=='\t')|(c=='\n'));
  ckearLine(c); return (c=='Y')|(c=='y');
} // getY

void adjustName(char *buf) {
//   ----------
  char *s=buf; bool txt=F;
  if ((*s!='.')&(*s!='/')) { // Assume in current folder.
    char tmp[bufSize]; snprintf(tmp, bufSize, "./%s", buf); strcpy(buf, tmp);
  }
  if (access(buf, R_OK)!=0) {
    while (*s++!='\0')
      ; --s;  if ((strlen(buf)>6)&&(*s--=='t')&&(*s--=='x')&&(*s--=='t')&&(*s=='.')) txt=T;
    if (!txt) strcat(buf, ".txt"); // no .txt entered, add it
  }
} // adjustName

FILE *openInput(const char *rFname) {
//    ---------
  char buf[bufSize]; FILE *rfp=NULL;
  strcpy(buf, rFname); adjustName(buf);
  if ((rfp=fopen(buf, "r"))==NULL) {
    char msg[msgSize]; snprintf(msg, msgSize, "\a\nCan't open for read %s", buf); perror(msg);
  }
  return rfp;
} // openInput

char iSquareFn[bufSize]; const char *yesNo="? y (yes) or n (no): ";
FILE *openInputFile(const int which, const int n) {
//    -------------
  char buf[bufSize], *rFname=NULL;
  do {
    if (which==1) printf("\nYour order %d square file name? ", n); else printf("\nText file name? ");
    if (getFileName(buf, bufSize-6)) { rFname=buf; break; }
    printf("\a\nCan't read the file name. Try again%s", yesNo); if (!getY()) break;
  } while (T);
  if (which==1) strcpy(iSquareFn, buf); 
  if (rFname==NULL) return NULL; else return openInput(buf);
} // openInputFile

bool changeDir(const char *toDir) {
//   ---------
  if (chdir(toDir)!=0) {
    char msg[msgSize]; snprintf(msg, msgSize, "Can't open folder %s", toDir); perror(msg); return F;
  }
  return T;
} // changeDir

char dirName[bufSize];
bool openDir(const int n) {
//   -------
  char buf[bufSize], baseName[bufSize]; int sub=0;
  snprintf(baseName, bufSize, "./%d-%d-CompositeSquare", fontN, n); strcpy(buf, baseName);
  do {
    if (mkdir(buf, 0775)==0) break;
    if (errno!=EEXIST) {
      char msg[msgSize]; snprintf(msg, msgSize, "Can't make folder %s", buf); perror(msg); return F;
    }
    snprintf(buf, bufSize, "%s_%d", baseName, ++sub);
  } while (T);
  if (changeDir(buf)) {
    printf("Output files are in folder %s\n\n", buf); strcpy(dirName, buf); return T;
  } 
  return F;
} // openDir

FILE *openOutput(const char *fn) {
//    ----------
  FILE *wfp=NULL;
  if ((wfp=fopen(fn, "w"))==NULL) {
    char msg[msgSize]; snprintf(msg, msgSize, "\a\nCan't open for write %s", fn); perror(msg);
  }
  return wfp;
} // openOutput

int fieldWidth() { // including 1 space
//  ----------
  int fw, max12, tmp; bool neg=smallestRead<0;

  max12=fontNN*smallestRead; if (max12<0) max12=-max12;
  tmp=fontNN*biggestRead; if (tmp<0) tmp=-tmp; if (tmp>max12) max12=tmp;
  tmp=fontNN-1+fontNN*smallestRead; if (tmp<0) tmp=-tmp; if (tmp>max12) max12=tmp;
  tmp=fontNN-1+fontNN*biggestRead; if (tmp<0) tmp=-tmp; if (tmp>max12) max12=tmp;

  if (max12<=1) { fw=neg ? 3 : 2; }
  else { int i=max12, width=1; while ((i=i/10)!=0) ++width; if (neg) ++width; fw=width+1; }
  return fw;
} // fieldWidth

typedef bool (*t_fprintFW)(FILE *fp, const int i);

bool fprintFW1(FILE *fp, const int i) { return fprintf(fp, "%1d",  i)>0; }
bool fprintFW2(FILE *fp, const int i) { return fprintf(fp, "%2d",  i)>0; }
bool fprintFW3(FILE *fp, const int i) { return fprintf(fp, "%3d",  i)>0; }
bool fprintFW4(FILE *fp, const int i) { return fprintf(fp, "%4d",  i)>0; }
bool fprintFW5(FILE *fp, const int i) { return fprintf(fp, "%5d",  i)>0; }
bool fprintFW6(FILE *fp, const int i) { return fprintf(fp, "%6d",  i)>0; }
bool fprintFW7(FILE *fp, const int i) { return fprintf(fp, "%7d",  i)>0; }
bool fprintFW8(FILE *fp, const int i) { return fprintf(fp, "%8d",  i)>0; }
bool fprintFW9(FILE *fp, const int i) { return fprintf(fp, "%9d",  i)>0; }
bool fprintFWa(FILE *fp, const int i) { return fprintf(fp, "%10d", i)>0; }
bool fprintFWb(FILE *fp, const int i) { return fprintf(fp, "%11d", i)>0; }

static t_fprintFW fprintFW[]={
  NULL,      fprintFW1, fprintFW2, fprintFW3, fprintFW4, fprintFW5,
  fprintFW6, fprintFW7, fprintFW8, fprintFW9, fprintFWa, fprintFWb
};

const int maxFieldWidth=11; bool filesOutput;
bool outputSquare(FILE *wfp, const int n, const int fw) {
//   ------------
  const int fw0=fw-1;
  if (fw>maxFieldWidth) { printf("Output format overflow.\n"); return F; }
  for (int r=0; r<n; ++r) {
    if (!fprintFW[fw0](wfp, oSquare[r][0])) return F;
    for (int c=1; c<n; ++c) { if (!fprintFW[fw](wfp, oSquare[r][c])) return F; }
    if (fputc('\n', wfp)==EOF) return F;
  }
  return fputc('\n', wfp)!=EOF;
} // outputSquare

void copySquare(int **from, int **to, const int n) {
//   ----------
  for (int r=0; r<n; ++r) for (int c=0; c<n; ++c) to[r][c]=from[r][c];
} // copySquare

const bool noWriteError=T;
bool outputCharacterSquare(FILE *wfp, const char *drain, const int fw) {
//   ---------------------
  char buf[bufSize]; snprintf(buf, bufSize, "Drain %s", drain); getCharSquare(drain[0]);
  if (!getWater(fontN, fontNN, cSquare, cWater)) return noWriteError;
  copySquare(cSquare, oSquare, fontN); copySquare(cWater, oWater, fontN);
  return outputHTML(wfp, fontN, 4, buf);
} // outputCharacterSquare

bool outputCharacterSquares(const int fw) {
//   ----------------------
  if (iSquare[0][0]!=0) return T; bool ok=T;
  FILE *wfp=openOutput("./Characters.html");
  if (wfp!=NULL) {
    ok=outputCharacterSquare(wfp, "Left", fw)&&outputCharacterSquare(wfp, "Right", fw)&&
       outputCharacterSquare(wfp, "Up", fw)&&outputCharacterSquare(wfp, "Down", fw); fclose(wfp);
  }
  return ok;
} // outputCharacterSquares

bool outputSquares(const int n, const int fw) {
//   ------------
  if (!getWater(n, maxNumOut, oSquare, oWater)) return noWriteError;
  char buf[bufSize]; snprintf(buf, bufSize, "./%dSquare.txt", n);
  FILE *wfp=openOutput(buf);
  if (wfp!=NULL) {
    bool ok=outputSquare(wfp, n, fw); if (ok) fclose(wfp); else return F;
    if (n<=maxNout) {
      wfp=openOutput("./Square.html");
      if (wfp!=NULL) {
        ok=outputHTML(wfp, n, 1, NULL);
        if (ok) fclose(wfp); else return F; wfp=openOutput("./Water.html");
        if (wfp!=NULL) {
          ok=outputHTML(wfp, n, 2, NULL); if (ok) fclose(wfp); else return F;
        } // if (wfp!=NULL)
      } // if (wfp!=NULL)
    } // if (n<=maxNout)
    wfp=openOutput("./Text.html");
    if (wfp!=NULL) { ok=outputHTML(wfp, n, 3, NULL); if (ok) fclose(wfp); else return F;
    } // if (wfp!=NULL)
  }
  if (n==fontN) return outputCharacterSquares(fw); return T;
} // outputSquares
//============================================ I/O end ==========================================

bool makeSquare(const int n, FILE *rfpT) {
//   ----------
  if (!getWater(n, maxNumIn, iSquare, iWater)) return noWriteError;
  getDrainage(n, iSquare, iWater);
  for (int i=0; i<n; ++i) {
    const int ro=i*fontN;
    for (int j=0; j<n; ++j) {
      const int co=j*fontN; bool wet=F; getcSquare(rfpT, i, j, &wet);
      for (int r=0; r<fontN; ++r) for (int c=0; c<fontN; ++c) {
        const int v=cSquare[r][c]+fontNN*iSquare[i][j];
        if (v>maxNumOut) maxNumOut=v; oSquare[r+ro][c+co]=v;
        if (wet) { if (!getWater(fontN, fontNN, cSquare, cWater)) return noWriteError; }
        textWet[r+ro][c+co]=wet&(cSquare[r][c]<cWater[r][c]);
      }
    } // for (int j=0
  } // for (int i=0
  if (outputSquares(fontN*n, fieldWidth())) return filesOutput=T;
  return F;
} // makeSquare

bool getOrderNSquare(const int n, FILE **rfpS) {
//   ----------------
  printf("Use default square%s", yesNo); bool input=F;
  if (getY()) {
    if (n&1) makeOdd(iSquare, n); else makeEven(iSquare, n);
    smallestRead=1; biggestRead=n*n; zeroBase(iSquare, n); 
  } else {
    *rfpS=openInputFile(1, n); if (*rfpS==NULL) return F;
    if (!(readSquare(*rfpS, n, iSquare, iSquareFn))) return F; input=T;
  }
  maxNumIn=biggestRead; return checkSquare(n, input, iSquareFn);
} // getOrderNSquare
//=============================================== main =================================================

void outputLocalTime() {
//   ---------------
  time_t startTime=time(NULL); struct tm *local=localtime(&startTime);
  if (local!=NULL) {
    char dateTime[100];
    size_t slen=strftime(dateTime, 100, "%A %Y-%m-%d %X %Z\n\0", local); printf("\n%s", dateTime);
  }
} // outputLocalTime

void printElapsedTime(time_t startTime) {
//   ---------------- 
  const int et=(int)difftime(time(NULL), startTime);
  if (et>0) printf("\nelapsed time %d:%02d:%02d\n", et/3600, et%3600/60, et%60);
} // printElapsedTime

void checkContinue(bool *another) { if (*another) { printf("\nContinue%s", yesNo); *another=getY(); } }
//   -------------

int main() {
//  ----
  bool another=T, writeError=F, ok=F; outputLocalTime(); seed_rand();
  do {
    FILE *rfpT=openInputFile(0, 0);
    if (rfpT!=NULL) {
      const int n=textLineLength(rfpT, bufSize);
      if (n>0) {
        getMagicConstant(n); 
        if (allocateStore(n)) {
          FILE *rfpS=NULL;
          if (getOrderNSquare(n, &rfpS)) {
            if (openDir(n)) {
              time_t startTime=time(NULL);
              filesOutput=F; lineLength=n; maxNumOut=INT_MIN; writeError=!makeSquare(n, rfpT);
              if (!changeDir("..")) writeError=T; if (!filesOutput) rmdir(dirName);
              printElapsedTime(startTime);
            }
          } // if (getSquare
          if (rfpS!=NULL) fclose(rfpS);
        } else { printf("\a\nError: Storage allocation failed.\n"); }
      } // if (n>0)
      fclose(rfpT);
    } // if (rfpT!=NULL)
    if (writeError) { perror("\a\nError writing file"); another=F; } else ok=T;
    checkContinue(&another);
  } while (another);
  freeStore(); printf("\nHit return to close the console.");
  while (T) if (getchar()=='\n') break; return ok ? EXIT_SUCCESS : EXIT_FAILURE;
} // main