We assume a rectangualar canvase for which we can provide the measurements, as well as the location of each character and ruler in it.
A region starts and ends with a ‘\special{t4ht"}’. The entry point gets coordinates (0,0). It is configured wuth
The ‘*’ is a seperator character, and it can be replaced by other characters.
We assume C-type templates, where values are assumed to be in float decimals (e.g., ‘%.2f’; replacing 2 by 0, implies an integer).
The ‘* after-all’ can be repeated arbitrary many times (must appear at least once). The last one is found when ‘**’ is encountered.
The first character in each ‘after-all’ is treated as a code: x-min x, X-max x, y-min , Y-max y, w-dx, h-dy, otherwise-string with no value. We need the codes to enable arbitrary combinations of values.
The ‘before-char’ must be non-empty for ‘%x %y’ to be printed. The case is similar for the ruler. If both are empty, we just measure the dvi dimensions–can be used for applets.
<..pos dvi ch..>
if( pos_dvi ){ long int d;
if( *pos_text ){
<.open output file.>
(IGNORED) fprintf(cur_o_file, pos_text,
pos_x_A * (x_val - base_pos_x) + pos_x_B,
pos_y_C * (y_val - base_pos_y) + pos_y_D);
}
if( x_val < min_pos_x ) min_pos_x = x_val;
if( (d = x_val + <.ch width.>) > max_pos_x ) max_pos_x = d;
if( (d = y_val - <.ch height.>) < min_pos_y ) min_pos_y = d;
if( (d = y_val + <.ch depth.>) > max_pos_y ) max_pos_y = d;
}
-_-_-
<..end pos dvi ch..>
if( pos_dvi ){
print_f(end_pos_text);
}
-_-_-
[more]).
[?]
<..pos dvi x rule..>
long int d;
if( (up > 0) && (right > 0) ){
if( *pos_line ){
double from_x, from_y;
<.open output file.>
from_x = pos_x_A * (x_val - base_pos_x) + pos_x_B;
from_y = pos_y_C * (y_val - pos_y_E * up - base_pos_y) + pos_y_D;
switch (rect_pos){
case 1: {
(IGNORED) fprintf(cur_o_file, pos_line,
from_x, from_y,
pos_x_A * right + pos_x_B + from_x,
pos_y_C * up + pos_y_D + from_y );
break; }
case 2: {
(IGNORED) fprintf(cur_o_file, pos_line,
from_x, from_y,
pos_x_A * right + pos_x_B + from_x,
from_y,
pos_y_C * up + pos_y_D );
break; }
default: {
(IGNORED) fprintf(cur_o_file, pos_line,
from_x, from_y,
pos_x_A * right,
pos_y_C * up);
}
}
}
if( x_val < min_pos_x ) min_pos_x = x_val;
if( (d = x_val + right) > max_pos_x ) max_pos_x = d;
if( (d = y_val - up) < min_pos_y ) min_pos_y = d;
if( y_val > max_pos_y ) max_pos_y = y_val;
}
-_-_-
<..positioned content..>
if( special_n ){
<.read pos instructions.>
} else if( (pos_dvi = !pos_dvi) == TRUE ){
print_f(pos_body);
min_pos_x = max_pos_x = base_pos_x = x_val;
min_pos_y = max_pos_y = base_pos_y = y_val ;
} else { U_CHAR *p;
double dim=0.0;
BOOL dim_on;
<.open output file.>
p = end_pos_body;
while( *p ){
dim_on = TRUE;
switch( *p ){
<.dim = pos value.>
default: { dim_on = FALSE; }
}
p++;
if( dim_on ){ (IGNORED) fprintf(cur_o_file, p, dim); }
else { (IGNORED) fprintf(cur_o_file, "%s", p); }
while( * (p++) );
}
}
-_-_-
The pattern of of ‘end_pos_body’ has a ‘\0’ at the end of each segment, and the last segment is empty. Hence, it ends with a ‘\0\0’.
<..dim = pos value..>
case ’X’: { dim = pos_x_A * (max_pos_x - base_pos_x) + pos_x_B;
break; }
case ’x’: { dim = pos_x_A * (base_pos_x - min_pos_x) + pos_x_B;
break; }
case ’d’: { dim = pos_x_A * (max_pos_x - min_pos_x) + pos_x_B;
break; }
case ’y’: { dim = pos_y_C * (base_pos_y - min_pos_y - 1) + pos_y_D;
break; }
case ’Y’: { dim = pos_y_C * (max_pos_y - base_pos_y) + pos_y_D;
break; }
case ’D’: { dim = pos_y_C * (max_pos_y - min_pos_y) + pos_y_D;
break; }
-_-_-
<..vars..>+
static BOOL pos_dvi = FALSE;
static U_CHAR *pos_body, * pos_text, * pos_line,
*end_pos_body, * end_pos_text;
static double pos_x_A, pos_x_B, pos_y_C, pos_y_D, pos_y_E;
static long int base_pos_x, base_pos_y, min_pos_x,
max_pos_x, min_pos_y, max_pos_y;
static short rect_pos;
-_-_-
Note that ‘pos_body’ points to the left-most byte in the template.
<..main’s init..>+
pos_text = pos_line = end_pos_body = end_pos_text = pos_body =
m_alloc(char, (int) 1);
(IGNORED) strcpy((char *) pos_text, "" );
-_-_-
<..read pos instructions..>
{ U_CHAR * p, ch, i;
ch = get_char();
p = pos_text = pos_line = end_pos_text
= end_pos_body = pos_body
= (char *) r_alloc((void *) pos_body,(size_t) special_n + 1);
i = 0; <.scan templates for pos.>
<.scan constants for pos.>
if( (i != 10) || special_n ){
warn_i_str(39,pos_text);
*(pos_text = end_pos_body = pos_line =
end_pos_text = pos_body) = ’\0’;
}
}
-_-_-
<..scan templates for pos..>
{ BOOL after_star=0;
while( special_n-- > 0 ){
if( (*p = get_char()) == ch ){
*p = ’\0’; i++;
if( i==1 ){ end_pos_body = p + 1; after_star = FALSE; }
else if( i==2 ){ pos_text = p + 1;
if( !after_star ){ i--; after_star = TRUE; }
}
else if( i==3 ){ end_pos_text = p + 1; }
else if( i==4 ){ pos_line = p + 1; }
else { p++; break; }
} else { after_star = FALSE; }
p++;
}
}
-_-_-
<..scan constants for pos..>
{ long int v=0;
double w[5];
int j;
U_CHAR ch, sign;
BOOL done;
for(j=0;j<5;j++){
<.v = int part; sign = ....>
if( done ){
i++;
w[j] = sign * ((double) v + pos_dbl( &special_n ));
}
}
pos_x_A = w[0]; pos_x_B = w[1];
pos_y_C = w[2]; pos_y_D = w[3]; pos_y_E = w[4];
}
rect_pos = (special_n == 2);
if( rect_pos ){ special_n -= 2; rect_pos = get_char() - ’0’;}
-_-_-
<..v = int part; sign = .....>
done = FALSE; sign = 1;
if( --special_n > 0 ){
if( (ch = get_char()) == ’-’ ){ sign = -1; v=0; }
else v = ch - ’0’;
if( (v<0) || (v>9) ) done = TRUE;
}
if( !done )
while( --special_n > 0 ){
ch = get_char();
if( (’0’ <= ch ) && (ch <= ’9’ ) ){
v = v * 10 + ch - ’0’; }
else{ done = TRUE; break; }
}
-_-_-
<..header functions..>+
static double pos_dbl( ARG_I(long int *) );
-_-_-
<..functions..>+
static double pos_dbl( special_n ) long int * special_n
;{
U_CHAR ch;
double v;
int d;
v = 0.0; d = 10;
while( --(*special_n) > 0 ){
ch = get_char();
if( (’0’ <= ch ) && (ch <= ’9’ ) ){
v += (double) (ch -’0’) / d; d *= 10; }
else break;
}
return v;
}
-_-_-
<..err int pos..>
123454321
-_-_-