#include <u.h>
#include <libc.h>
#include <libg.h>
#include <bio.h>
#include <regexp.h>
#include "dat.h"


char    machineused[64];
char    userused[64];
int     depthused;

/*
*  translate mail address into a file name
*/
char*
tryfile(char *machine, char *user, int ld)
{
       static char file[128];
       char *cp, *p;
       Biobuf *mf;

       sprint(file, "/lib/face/48x48x%d/.dict", 1<<ld);
       mf = Bopen(file, OREAD);
       if(mf == 0)
               return 0;

       sprint(file, "%s/%s", machine, user);
       while(cp = Brdline(mf, '\n')) {
               cp[Blinelen(mf)-1] = 0;
               p = strchr(cp, ' ');
               if(p == 0)
                       continue;
               *p = 0;
               if(strcmp(cp, file) == 0) {
                       sprint(file, "/lib/face/48x48x%d/%s", 1<<ld, p+1);
                       strncpy(machineused, machine, sizeof(machineused));
                       strncpy(userused, user, sizeof(userused));
                       depthused = ld;
                       Bclose(mf);
                       return file;
               }
       }
       Bclose(mf);
       return 0;
}

char*
tryfiles(char *machine, char *user, int ld)
{
       char *cp;

       cp = tryfile(machine, user, ld);
       if(cp)
               return cp;
       if(ld == 1)
               cp = tryfile(machine, user, 0);
       return cp;
}

char*
getfile(char *machine, char *user, int ld)
{
       char *fp;
       Biobuf *mf;
       char *cp, *dp, *ep;
       Reprog *exp;
       char buf[200];
       static char alnum[]=    "abcdefghijklmnopqrstuvwxyz0123456789"
                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

       if(*user == 0)
               user = "unknown";
       if(*machine == 0)
               machine = "astro";      /* this is hopelessly provincial */

       fp = tryfiles(machine, user, ld);
       if(fp != 0)
               return fp;

       cp = strchr(machine, '.');
       ep = strrchr(machine, '.');
       while(cp != 0 && cp < ep){      /* try higher domain */
               if((fp = tryfiles(++cp, user, ld)) != 0)
                       return fp;
               cp = strchr(cp, '.');
       }

       mf = Bopen("/lib/face/.machinelist", OREAD);
       if(mf == 0)
               return 0;

       while(cp = Brdline(mf, '\n')){
               int clean = 1;
               if(*cp == '#' || (ep=strpbrk(cp, " \t")) == 0)
                       continue;
               cp[Blinelen(mf)-1] = 0;
               for(dp=&buf[1]; cp < ep; ){
                       if(strchr(alnum, *cp) == 0)
                               clean = 0;
                       *dp++ = *cp++;
               }
               *dp = '\0';
               ep += strspn(ep, "\t ");

               /*
                * skip expression processing for a simple compare
                */
               if(clean && (strcmp(&buf[1], machine) == 0))
                       return tryfiles(ep, user, ld);

               if(buf[1] != '^'){
                       buf[0] = '^';
                       cp = buf;
               } else
                       cp = buf+1;
               if(*(dp-1) != '$')
                       *dp++ = '$';
               *dp = '\0';

               exp = regcomp(cp);
               if(!exp)
                       error("error in regular expression");
               if(regexec(exp, machine, (Resub *)0, 0) != 0){
                       free(exp);
                       return tryfiles(ep, user, ld);
               }
               free(exp);
       }
       Bclose(mf);
       return 0;
}

void
makelower(char *cp)
{
       int c;

       for(; (c=*cp)!=0; cp++)
               if('A'<=c && c<='Z')
                       *cp += 'a'-'A';
}

void
geticon(SRC *into, char *machine, char *user)
{
       Biobuf *fd;
       int x, y;
       char *cp, *file;
       uchar *pp;
       ulong p, q, r;
       int depth;
       static uchar tab1[] = { 0, 85, 170, 255 };

       label = 0;

       makelower(machine);
       makelower(user);
       depth = screen.ldepth;
       if(depth > 1)
               depth = 1;

       file = getfile(machine, user, depth);
       if(file == 0)
               file = getfile(machine, "unknown", depth);
       if(file == 0)
               file = getfile("", "unknown", depth);

       if(file == 0){
   out:
               memset(into, 0, sizeof(SRC));
               label = machine;
               return;
       }

       strcpy(realmachine, machineused);

       fd = Bopen(file, OREAD);
       if(fd == 0)
               goto out;

       if(strcmp(userused, "unknown") == 0)
               label = machine;
       y = 0;
       while((cp=Brdline(fd, '\n')) != 0){
               p = strtoul(cp, &cp, 16);
               q = strtoul(cp+1, &cp, 16);     /* skip ',' */
               r = strtoul(cp+1, 0, 16);       /* skip ',' */
               pp = into->pix[y];
               for(x=0; x<16; x++){
                       if(depthused == 1){
                               pp[x] = tab1[(p&(3<<(30-2*x)))>>(30-2*x)];
                               pp[16+x] = tab1[(q&(3<<(30-2*x)))>>(30-2*x)];
                               pp[32+x] = tab1[(r&(3<<(30-2*x)))>>(30-2*x)];
                       }else{
                               pp[x]    = (p&(1<<(15-x)))?255:0;
                               pp[16+x] = (q&(1<<(15-x)))?255:0;
                               pp[32+x] = (r&(1<<(15-x)))?255:0;
                       }
               }
               if(y++ >= MAXY)
                       break;
       }
       Bclose(fd);
}