#include "a.h"

/*
* Section 2 - Font and character size control.
*/

/* 2.1 - Character set */
/* XXX
*
* \C'name' - character named name
* \N'n' - character number
* \(xx - two-letter character
* \-
* \`
* \'
* `
* '
* -
*/

Rune*
getqarg(void)
{
       static Rune buf[MaxLine];
       int c;
       Rune *p, *e;

       p = buf;
       e = p+sizeof buf-1;

       if(getrune() != '\'')
               return nil;
       while(p < e){
               c = getrune();
               if(c < 0)
                       return nil;
               if(c == '\'')
                       break;
               *p++ = c;
       }
       *p = 0;
       return buf;
}

int
e_N(void)
{
       Rune *a;
       if((a = getqarg()) == nil)
               goto error;
       return eval(a);

error:
       warn("malformed %CN'...'", backslash);
       return 0;
}

int
e_paren(void)
{
       int c, cc;
       Rune buf[2], r;

       if((c = getrune()) < 0 || c == '\n')
               goto error;
       if((cc = getrune()) < 0 || cc == '\n')
               goto error;
       buf[0] = c;
       buf[1] = cc;
       r = troff2rune(buf);
       if(r == Runeerror)
               warn("unknown char %C(%C%C", backslash, c, cc);
       return r;

error:
       warn("malformed %C(xx", backslash);
       return 0;
}

/* 2.2 - Fonts */
Rune fonttab[10][100];

/*
* \fx \f(xx \fN - font change
* number register .f - current font
* \f0 previous font (undocumented?)
*/
/* change to font f.  also \fx, \f(xx, \fN */
/* .ft LongName is okay - temporarily at fp 0 */
void
ft(Rune *f)
{
       int i;
       int fn;

       if(f && runestrcmp(f, L("P")) == 0)
               f = nil;
       if(f == nil)
               fn = 0;
       else if(isdigit(f[0]))
               fn = eval(f);
       else{
               for(i=0; i<nelem(fonttab); i++){
                       if(runestrcmp(fonttab[i], f) == 0){
                               fn = i;
                               goto have;
                       }
               }
               warn("unknown font %S", f);
               fn = 1;
       }
have:
       if(fn < 0 || fn >= nelem(fonttab)){
               warn("unknown font %d", fn);
               fn = 1;
       }
       if(fn == 0)
               fn = getnr(L(".f0"));
       nr(L(".f0"), getnr(L(".f")));
       nr(L(".f"), fn);
       runmacro1(L("font"));
}

/* mount font named f on physical position N */
void
fp(int i, Rune *f)
{
       if(i <= 0 || i >= nelem(fonttab)){
               warn("bad font position %d", i);
               return;
       }
       runestrecpy(fonttab[i], fonttab[i]+sizeof fonttab[i], f);
}

int
e_f(void)
{
       ft(getname());
       return 0;
}

void
r_ft(int argc, Rune **argv)
{
       if(argc == 1)
               ft(nil);
       else
               ft(argv[1]);
}

void
r_fp(int argc, Rune **argv)
{
       if(argc < 3){
               warn("missing arguments to %Cfp", dot);
               return;
       }
       fp(eval(argv[1]), argv[2]);
}

/* 2.3 - Character size */

/* \H'±N' sets height */

void
ps(int s)
{
       if(s == 0)
               s = getnr(L(".s0"));
       nr(L(".s0"), getnr(L(".s")));
       nr(L(".s"), s);
       runmacro1(L("font"));
}

/* set point size */
void
r_ps(int argc, Rune **argv)
{
       Rune *p;

       if(argc == 1 || argv[1][0] == 0)
               ps(0);
       else{
               p = argv[1];
               if(p[0] == '-')
                       ps(getnr(L(".s"))-eval(p+1));
               else if(p[0] == '+')
                       ps(getnr(L(".s"))+eval(p+1));
               else
                       ps(eval(p));
       }
}

int
e_s(void)
{
       int c, cc, ccc, n, twodigit;

       c = getnext();
       if(c < 0)
               return 0;
       if(c == '+' || c == '-'){
               cc = getnext();
               if(cc == '('){
                       cc = getnext();
                       ccc = getnext();
                       if(cc < '0' || cc > '9' || ccc < '0' || ccc > '9'){
                               warn("bad size %Cs%C(%C%C", backslash, c, cc, ccc);
                               return 0;
                       }
                       n = (cc-'0')*10+ccc-'0';
               }else{
                       if(cc < '0' || cc > '9'){
                               warn("bad size %Cs%C%C", backslash, c, cc);
                               return 0;
                       }
                       n = cc-'0';
               }
               if(c == '+')
                       ps(getnr(L(".s"))+n);
               else
                       ps(getnr(L(".s"))-n);
               return 0;
       }
       twodigit = 0;
       if(c == '('){
               twodigit = 1;
               c = getnext();
               if(c < 0)
                       return 0;
       }
       if(c < '0' || c > '9'){
               warn("bad size %Cs%C", backslash, c);
               ungetnext(c);
               return 0;
       }
       if(twodigit || (c < '4' && c != '0')){
               cc = getnext();
               if(c < 0)
                       return 0;
               n = (c-'0')*10+cc-'0';
       }else
               n = c-'0';
       ps(n);
       return 0;
}

void
t2init(void)
{
       fp(1, L("R"));
       fp(2, L("I"));
       fp(3, L("B"));
       fp(4, L("BI"));
       fp(5, L("CW"));

       nr(L(".s"), 10);
       nr(L(".s0"), 10);

       addreq(L("ft"), r_ft, -1);
       addreq(L("fp"), r_fp, -1);
       addreq(L("ps"), r_ps, -1);
       addreq(L("ss"), r_warn, -1);
       addreq(L("cs"), r_warn, -1);
       addreq(L("bd"), r_warn, -1);

       addesc('f', e_f, 0);
       addesc('s', e_s, 0);
       addesc('(', e_paren, 0);        /* ) */
       addesc('C', e_warn, 0);
       addesc('N', e_N, 0);
       /* \- \' \` are handled in html.c */
}