Beispiel #1
0
void std_interpret_ansi(struct virtscreen *cur, unsigned char ch)
{
  switch (ch)
  {
    case '(':  cur->next_char_send = special_ansi_charset_0;
               return;
    case ')':  cur->next_char_send = special_ansi_charset_1;
               return;
    case '[':  cur->cur_ansi_number = 0;
               cur->ansi_elements = 0;
               cur->ansi_reading_number = 0;
               cur->next_char_send = special_reading_ansi;
               return;
    case '7':  cur->old_attrib = cur->attrib;
               cur->old_xpos = cur->xpos;
               cur->old_ypos = cur->ypos;
               break;
    case '8':  change_attribute(cur,cur->old_attrib);
               position_console(cur,cur->ypos,cur->xpos,0);
               break;
    case 'E':  cur->xpos = 0;
    case 'D':  cur->ypos++;
               if (cur->ypos >= cur->bottom_scroll)
               {
                 scroll_virtscreen(cur);
                 cur->ypos--;
               }
               move_cursor(cur);
               break; 
    case 'M':  cur->ypos--;
               if (cur->ypos < cur->top_scroll)
               {
                 cur->ypos++;
                 scroll_virt_up_at_cursor(cur,0);
               }
               move_cursor(cur);
               break;    /* recalculate screen pos */
  }
  if (ch != 27)
    cur->next_char_send = std_interpret_char;
}
Beispiel #2
0
void special_reading_ansi(struct virtscreen *cur, unsigned char ch)
{
  if ((ch>='0') && (ch<='9'))
  {
    cur->cur_ansi_number = (cur->cur_ansi_number * 10) + (ch - '0');
    cur->ansi_reading_number = 1;
    return;
  }

  if ((cur->ansi_reading_number) || (ch == ';'))
  {
     if (cur->ansi_elements<MAX_ANSI_ELEMENTS)
      cur->ansi_element[cur->ansi_elements++] = cur->cur_ansi_number;
     cur->ansi_reading_number = 0;
  }
  cur->cur_ansi_number = 0;
  switch (ch)
  {
    case '?':
    case ';':   return;
    case 'D':   position_console(cur,0,(cur->ansi_elements) ?
			 -cur->ansi_element[0] : -1,1);
                break;
    case 'a':
    case 'C':   position_console(cur,0,(cur->ansi_elements) ?
			 cur->ansi_element[0] : 1,1);
                break;
    case 'A':   position_console(cur,(cur->ansi_elements) ? 
		         -cur->ansi_element[0] : -1,0,1);
                break;
    case 'e':
    case 'B':   position_console(cur,(cur->ansi_elements) ?
			 cur->ansi_element[0] : 1,0,1);
                break;
    case '`':
    case 'G':   
                {
                  int temp = cur->ansi_elements ? cur->ansi_element[0] : 1;
		  if (temp)
		    temp--;
                  position_console(cur,cur->ypos,temp,0);
		}
                break;
    case 'E':   position_console(cur,cur->ypos + 
		         ((cur->ansi_elements) ? cur->ansi_element[0] : 1),
			 0,0);
                break;
    case 'F':   position_console(cur,cur->ypos - 
		         ((cur->ansi_elements) ? cur->ansi_element[0] : 1),
			 0,0);
                break;
    case 'd':   
                {
                  int temp = cur->ansi_elements ? cur->ansi_element[0] : 1;
		  if (temp)
		    temp--;
                  position_console(cur,temp,cur->xpos,0);
		}
                break;
    case 'f':
    case 'H':
      {
        int row = (cur->ansi_elements > 0) ? cur->ansi_element[0] : 1;
        int col = (cur->ansi_elements > 1) ? cur->ansi_element[1] : 1;
	if (row)
	  row--;
	if (col)
	  col--;
        position_console(cur,row,col,0);
      }
      break;
    case 'J':   clear_virtscreen(cur,(cur->ansi_elements) ?
		       cur->ansi_element[0]: 0);
                break;
    case 'L':   {
                  int lines = (cur->ansi_elements) ? 
		     cur->ansi_element[0] : 1;
                  while (lines>0)
                  {
                    scroll_virt_up_at_cursor(cur,0);
                    lines--;
                  }
                }
                break;
    case 'M':   {
                  int lines = (cur->ansi_elements) ? 
		     cur->ansi_element[0] : 1;
                  while (lines>0)
                  {
                    scroll_virt_up_at_cursor(cur,1);
                    lines--;
                  }
                }
                break;
    case 'P':   delete_chars_in_line(cur,(cur->ansi_elements) ? 
			 cur->ansi_element[0] : 1);
                break;
    case 'K':   clear_to_eol(cur,cur->ansi_elements ? 
		    cur->ansi_element[0] : 0);
                break;
    case 's':   cur->old_xpos = cur->xpos;
                cur->old_ypos = cur->ypos;
                break;
    case 'u':   position_console(cur,cur->old_ypos,cur->old_xpos,0);
                break;
    case 'r':   {
                  int low = (cur->ansi_elements > 0) ?
		      cur->ansi_element[0] : 1;
                  int high = (cur->ansi_elements > 1) ?
		      cur->ansi_element[1] : cur->rows;
                  if (low<=high)
                    set_scroll_region(cur,low,high);
                }
                break;
    case 'm':
       {
          int count = 0;
          int cthing;
          if (!cur->ansi_elements)
            change_attribute(cur,0x07);
          while (count < cur->ansi_elements)
          {
            cthing = cur->ansi_element[count];
            switch (cthing)
            {
              case 0:
              case 27: change_attribute(cur,0x07);
                       break;
              case 1:  change_attribute(cur,cur->attrib | 0x08);
                       break;
              case 5:  change_attribute(cur,cur->attrib | 0x80);
                       break;
              case 7:  change_attribute(cur,0x70);
                       break;
              case 21:
              case 22: change_attribute(cur,cur->attrib & 0xF7);
                       break;
              case 25: change_attribute(cur,cur->attrib & 0x7F);
                       break;
              default:
                if ((cthing>=30) && (cthing<=37))
		  {
		    change_attribute(cur,(cur->attrib & 0xF8) | (cthing-30));
		  }
                if ((cthing>=40) && (cthing<=47))
		  {
		    change_attribute(cur,(cur->attrib & 0x8F) | 
				     ((cthing-40) << 4));
		  }
                break;
	      }
            count++;
	  }
	}
      break;
      
  }
  cur->next_char_send = std_interpret_char;
}
Beispiel #3
0
int load_font_config(PathInfo pmap, char *confname)
{
    FILE *f;
    FONTREC **flist=&fontlist;
    ATTRIBREC **alist=&attriblist;
    ENCODINGREC **elist=&encodinglist;
    RANGEREC **rlist=&rangelist;
    FONTREC *frec;
    char buffer[512];
    char *bpos;
    int linecount=0;
    f=open_file(pmap, confname, "r");
    if (!f) {
	fprintf(stderr, "Unable to load font configuration\n");
	return 0;
    }
    while (*flist) flist=&(*flist)->next;
    while (*alist) {
	if ((*alist)->value==-1) lastattrib++;
	alist=&(*alist)->next;
    }
    while (*elist) elist=&(*elist)->next;
    while (*rlist) rlist=&(*rlist)->next;
    frec=NULL;
    while (fgets(buffer, 511, f)) {
	linecount++;
	bpos=buffer;
	skip_spaces(bpos);
	if (!*bpos || *bpos=='#') continue;
	if (!strncmp(bpos,"ATTRIBUTE", 9)) {
	    /* define a new attribute:
	    ** ATTRIBUTE name value0 value1 value2 value3
	    ** value? is a string used as a reference
	    ** defval is the default value
	    ** name is the name used to define the attribute
	    ** (so, a line of the form 'name value1' defines the attribute
	    **  name to be equal to value1 for the current font)
	    **
	    ** The font attribute detection algorithm uses these values
	    ** to find default attributes for fonts from their name.
	    */
	    char *c,*h;
	    char tc;
	    int i=-1;
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    while (h) {
		*alist=malloc(sizeof(ATTRIBREC));
		(*alist)->name=
		add_alias(h,
			  ((i<0)?ATTRIBGROUPALIAS:ATTRIBVALUEALIAS(lastattrib)),
			  *alist);
		(*alist)->value=i;
		(*alist)->num=lastattrib;
		h=get_string(&c,&tc);
		i++;
		(*alist)->next=NULL;
		alist=&(*alist)->next;
	    }
	    /* at least one (perhaps two?) value should be specified */
	    if (i>=0) {
		if (!i) {
                    /* no values given */
		    /* h still points to name of the attribute */
		    fprintf(stderr,
			    "%s:%i: No values given for attribute %s\n"
			    "%s:%i: Assuming attribute is not used\n",
			    confname, linecount, h,confname,linecount);
		    i=1;
		}
		attribinfo[lastattrib].max=i;
		if (lastattrib) i=i*attribinfo[lastattrib-1].multby;
		attribinfo[lastattrib].multby=i;
		attribinfo[lastattrib].divby=i/attribinfo[lastattrib].max;
		attribinfo[lastattrib].def=0;
		lastattrib++;
	    } else if (i<0) {
		fprintf(stderr, "%s:%i: No attribute name given\n",
			confname, linecount);
	    }
	} else if (!strncmp(bpos, "ATTRALIAS", 9)) {
	    /* Redefine the attributes for a certain group */
	    /* For example:
	    ** ATTRIBUTE Weight Medium Bold
	    ** ...
	    ** ATTRALIAS Weight Gewicht Normaal Vet
	    */
	    char *c,*h;
	    char tc;
	    int aliastype;
	    void *aliasdata;
	    ATTRIBREC *ar;
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    aliasdata=find_alias(h,ATTRIBGROUPALIAS);
	    if (!find_alias) {
		fprintf(stderr, "%s:%i: Unknow attribute name %s\n",
			confname, linecount, h);
		continue;
	    }
	    ar=aliasdata;
	    aliastype=ar->num;
	    h=get_string(&c,&tc);
	    while (ar && (ar->num==aliastype) && h) {
		ar->name=add_alias(h,(ar->value>=0?
				      ATTRIBVALUEALIAS(aliastype):
				      ATTRIBGROUPALIAS),
				   ar);
		ar=ar->next;
		h=get_string(&c,&tc);
	    }
	    if (h) {
		fprintf(stderr, "%s:%i: Too many attributes given\n.",
			confname, linecount);
	    }
	    if (ar && (ar->num==aliastype)) {
		fprintf(stderr, "%s:%i: Not enough values given\n",
			confname, linecount);
	    }
	} else if (!strncmp(bpos, "ALIAS",5)) {
	    /* Define an alias for some identifier. */
	    char *c,*h;
	    char tc;
	    int aliastype;
	    void *aliasdata;
	    c=bpos+5;
	    tc=*c;
	    h=get_string(&c,&tc);
	    aliasdata=find_aliasname(h,&aliastype);
	    if (!aliasdata) {
		fprintf(stderr, "%s:%i: identifier %s unknown\n",
			confname, linecount, h);
		continue;
	    }
	    h=get_string(&c,&tc);
	    while (h) {
		/* check if h is already defined for that type */
		if (!find_alias(h,aliastype)) {
		    add_alias(h,aliastype, aliasdata);
		}
		h=get_string(&c,&tc);
	    }
	} else if (!strncmp(bpos, "RANGE", 5)) {
	    /* define a range.
	    ** syntax: RANGE name n k-l s-t
	    ** n,k,l,s and t are integers in one of the following formats:
	    ** decimal 65, octal 0101, hexadecimal 0x41, character 'A',
	    ** Unicode U+0041.  Sorry, no internationalisation for numbers.
	    */
	    char *c, *h;
	    char tc;
	    RANGEREC *rr;
	    int len, actnum;
	    c=bpos+5;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No name spacified\n",
			confname, linecount);
		continue;
	    }
	    (*rlist)=rr=malloc(sizeof(RANGEREC));
	    rr->name=add_alias(h,RANGEALIAS, rr);
	    rr->next=NULL;
	    rlist=&rr->next;
	    *c=tc;
	    /* upper limit to the length of the needed array is the length
	    ** of the string, since each number takes at least two positions
	    ** Add 2 for a termination pair.
	    */
	    skip_spaces(c);
	    len=strlen(c);
	    actnum=0;
	    rr->ranges=malloc(sizeof(int)*(len+2));
	    while (*c && actnum+1<len) {
		h=c;
		c=get_integer(c, rr->ranges+actnum);
		actnum++;
		if (*c=='-') {
		    c++;
		    c=get_integer(c,rr->ranges+actnum);
		} else {
		    rr->ranges[actnum]=rr->ranges[actnum-1];
		}
		actnum++;
		if (!isspace(*c)) {
		    find_spaces(c);
		    tc=*c;
		    *c=0;
		    fprintf(stderr, "%s:%i: strange range item %s\n",
			    confname, linecount, h);
		    *c=tc;
		}
		skip_spaces(c);
	    }
	    rr->ranges[actnum++]= -1;
	} else if (!strncmp(bpos, "ENCODING", 8)) {
	    /* define an encoding for a font. */
	    char *c,*h;
	    char tc;
	    c=bpos+8;
	    tc=*c;
	    h=get_string(&c,&tc);
	    while (h) {
		*elist=malloc(sizeof(ENCODINGREC));
		(*elist)->encmap=0;
		(*elist)->mapfilename=add_alias(h, ENCODINGALIAS, *elist);
		(*elist)->next=0;
		elist=&(*elist)->next;
		h=get_string(&c,&tc);
	    }
	} else if (!strncmp(bpos, "FONTENC",7)) {
	    char *c, *h;
	    char tc;
	    ENCODINGREC *er;
	    if (!frec) {
		fprintf(stderr, "%s:%i: Not defining a font yet\n",
			confname,linecount);
		continue;
	    }
	    c=bpos+7;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No encoding specified\n",
			confname, linecount);
		continue;
	    }
	    er=find_alias(h, ENCODINGALIAS);
	    if (!er) {
		fprintf(stderr, "%s:%i: Unknown encoding %s\n",
			confname, linecount, h);
	    } else {
		frec->encoding=er;
	    }
	} else if (!strncmp(bpos, "FONTRANGE",9)) {
	    char *c, *h;
	    char tc;
	    RANGEREC *rr;
	    if (!frec) {
		fprintf(stderr, "%s:%i: Not defining a font yet\n",
			confname,linecount);
		continue;
	    }
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No range specified\n",
			confname, linecount);
		continue;
	    }
	    rr=find_alias(h, RANGEALIAS);
	    if (!rr) {
		fprintf(stderr, "%s:%i: Unknown range %s\n",
			confname, linecount, h);
	    } else {
		frec->range=rr;
	    }
	} else if (!strncmp(bpos, "FONT",4)) {
	    /* Start defining a new font with auto-detection of attributes
	    ** and encoding.
	    */
	    char *c,*h;
	    char tc;

	    c=bpos+4;
	    tc=*c;
	    h=get_string(&c,&tc);
	    frec = (*flist) = malloc(sizeof(FONTREC));
	    frec->fontname=malloc(sizeof(char)*(c-h+1)); /* c-h==strlen(h) */
	    strcpy(frec->fontname, h);
	    frec->attribpos=0;
	    frec->encoding=NULL;
	    frec->range=NULL;
	    frec->fonttype=frec->bt=frec->bm=frec->bmax=0;
	    frec->font=0;
	    frec->fstruct=NULL;
	    frec->next=NULL;
	    flist=&frec->next;
	    /* detect attributes:  !!! X11 specific code
	    ** * divide the font name in parts between '-' signs
	    ** * for each part, check if it is an alias
	    ** If the encoding is not set at the end, combine the
	    ** last two parts and check if that is an alias.
	    ** Keep track which attributes are already set to make
	    ** sure no redefinitions are made.
	    */
	    {  int attrset[MAXATTRIB];
	       char *t;
	       void *aliasdata;
	       int aliastype;
	       int tosetleft;
	       int i;
	       /* add an '-' at the end to process the last item */
	       c[0]='-';c[1]='\0';
	       c=h;
	       for (i=0; i<lastattrib; i++) attrset[i]=0;
	       tosetleft=lastattrib+2; /* range and encoding */
	       t=strchr(h,'-');
	       while (t && tosetleft) {
		   /* skip field of the form "*" and "" */
		   if (*c!='*' && *c!='-') {
		       *t='\0';
		       aliasdata=find_aliasname(c,&aliastype);
		       while (aliasdata) {
			   switch (aliastype) {
			   case RANGEALIAS:
			       if (!frec->range) {
				   frec->range=aliasdata;
				   tosetleft--;
			       }
			       break;
			   case ENCODINGALIAS:
			       if (!frec->encoding) {
				   frec->encoding=aliasdata;
				   tosetleft--;
			       }
			       break;
			   case ATTRIBGROUPALIAS:
			       break;
			   default:
			       /* ATTRIBVALUEALIAS(n) */
			       for (i=0; i<lastattrib; i++) {
				   if (!attrset[i] &&
				       aliastype==ATTRIBVALUEALIAS(i)) {
				       ATTRIBREC *ar=aliasdata;
				       attrset[i]=1;
				       tosetleft--;
				       frec->attribpos =
                                       change_attribute(frec->attribpos,
							ar->num, ar->value);
				       continue;
				   }
			       }
			       break;
			   }
			   aliasdata=find_nextname(&aliastype);
		       }
		       *t='-';
		   }
		   t++;
		   c=t;
		   t=strchr(t,'-');
	       }
	    }
	    if (!frec->encoding) {
		/* try to find encoding in last two items
		** c is at a last position, after the added '-'
		** Remove it and search backward.
		*/
		c--;
		*c='\0';
		while (c>h && *c!='-') c--;   c--;
		while (c>h && *c!='-') c--;
		if (c!=h) {
		    c++;
		    frec->encoding=find_alias(c,ENCODINGALIAS);
		}
	    }
	} else {
	    /* The line starts the name of an attribute followed by
	    ** its value. Find the attribute and the value and change
	    ** the attribute of the current font.
	    */
	    char *c,*h;
	    char tc;
	    ATTRIBREC *ar;
	    ATTRIBREC *aval;
	    int agr;
	    c=bpos;
	    tc=*c;
	    /* get attribute name and look it up */
	    h=get_string(&c,&tc);
	    ar=find_alias(h,ATTRIBGROUPALIAS);
	    if (!ar) {
		fprintf(stderr,"%s:%i: unknow attribute group %s\n",
			confname, linecount, h);
		continue;
	    }
	    agr=ar->num;
	    /* get attribute value and look it up */
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr,"%s:%i: no attribute value specified.\n",
			confname, linecount);
		aval=NULL;
	    } else {
		aval=find_alias(h,ATTRIBVALUEALIAS(agr));
	    }
	    if (!aval) {
		char *vname;
		fprintf(stderr,"%s:%i: invalid attribute %s\n",
			confname, linecount, h);
		fprintf(stderr,"%s:%i: use one of:", confname, linecount);
		vname=find_type(ATTRIBVALUEALIAS(agr));
		while (vname) {
		    fprintf(stderr, " %s", vname);
		    vname=find_type_next();
		}
		fprintf(stderr, "\n");
		continue;
	    } else if (frec) {
		/* change font attribute of current font */
		frec->attribpos=change_attribute(frec->attribpos, aval->num,
						 aval->value);
	    } else {
		fprintf(stderr, "%s:%i: Not defining a font yet\n",
			confname, linecount);
	    }
	}
    }
    close_file(f);
    return 0;
}
Beispiel #4
0
/* change one attribute in the given font */
int font_change_attribute(int attribcombo,  int attrnr, int value)
{
  if (attrnr<0 || value<0 || attrnr>=maxattrib ||
      value >=attribinfo[attrnr].max) return attribcombo;
  return change_attribute(attribcombo, attrnr, value);
}
Beispiel #5
0
/* set attribute ATTRNR to VALUE */
void font_set_attribute(int attrnr, int value)
{
    if (attrnr<0 || value<0 || attrnr>=maxattrib ||
	value >= attribinfo[attrnr].max) return;
    current_attr=change_attribute(current_attr,attrnr,value);
}
Beispiel #6
0
int font_load_config(char *confname)
{
    FILE *f;
    FONTREC **flist=&fontlist;
    ATTRIBREC **alist=&attriblist;
    ENCODINGREC **elist=&encodinglist;
    RANGEREC **rlist=&rangelist;
    REMAPREC **rmlist=&remaplist;
    FONTREC *frec;
    char buffer[512];
    char *bpos;
    int linecount=0;
    if (!pmap) {
	pmap=make_pathinfo("MAPPATH",DEFAULTMAPPATH,".map,.ufont");
    }
    f=open_file(pmap, confname, "r");
    if (!f) {
	fprintf(stderr, "Unable to find font configuration '%s'\n", confname);
	return 0;
    }
    /* find the end of these lists */
    while (*flist) flist=&(*flist)->next;
    while (*alist) {
	if ((*alist)->value==-1) maxattrib++;
	alist=&(*alist)->next;
    }
    while (*elist) elist=&(*elist)->next;
    while (*rlist) rlist=&(*rlist)->next;
    while (*rmlist) rmlist=&(*rmlist)->next;
    frec=NULL;
    /* read in the file, line by line */
    /* a buffer of 511 character should suffice */
    while (fgets(buffer, 511, f)) {
	linecount++;
	bpos=buffer;
	skip_spaces(bpos);
	/* skip empty line or comments (starting with #) */
	if (!*bpos || *bpos=='#') continue;
	if (!strncmp(bpos,"ATTRIBUTE", 9)) {
	    /* define a new attribute:
	    ** ATTRIBUTE name value0 value1 value2 value3
	    ** value? is a string used as a reference
	    ** name is the name used to define the attribute
	    ** (so, a line of the form 'name value1' defines the attribute
	    **  name to be equal to value1 for the current font)
	    **
	    ** The font attribute detection algorithm uses these values
	    ** to find default attributes for fonts from their name.
	    */
	    char *c,*h;
	    char tc;
	    int i= -1;
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    while (h) {
		*alist=malloc(sizeof(ATTRIBREC));
		(*alist)->name=
		add_alias(h,
			  ((i<0)?ATTRIBGROUPALIAS:ATTRIBVALUEALIAS(maxattrib)),
			  *alist);
		(*alist)->value=i;
		(*alist)->num=maxattrib;
		h=get_string(&c,&tc);
		i++;
		(*alist)->next=NULL;
		alist=&(*alist)->next;
	    }
	    /* at least one (perhaps two?) value should be specified */
	    if (i>=0) {
		if (!i) {
                    /* no values given */
		    /* h still points to name of the attribute */
		    fprintf(stderr,
			    "%s:%i: No values given for attribute %s\n"
			    "%s:%i: Assuming attribute is not used\n",
			    confname, linecount, h,confname,linecount);
		    i=1;
		}
		attribinfo[maxattrib].max=i;
		if (maxattrib) i=i*attribinfo[maxattrib-1].multby;
		attribinfo[maxattrib].multby=i;
		attribinfo[maxattrib].divby=i/attribinfo[maxattrib].max;
		attribinfo[maxattrib].def=0;
		maxattrib++;
	    } else if (i<0) {
		fprintf(stderr, "%s:%i: No attribute name given\n",
			confname, linecount);
	    }
	} else if (!strncmp(bpos, "ATTRALIAS", 9)) {
	    /* Redefine the attributes for a certain group. These
	    ** attributes might be used in menus and you can adjust
	    ** the menus by changing the attribute names.  Useful
	    ** for localization, for example:
	    ** ATTRIBUTE Weight Medium Bold
	    ** ...
	    ** ATTRALIAS Weight Gewicht Normaal Vet
	    */
	    char *c,*h;
	    char tc;
	    int aliastype;
	    void *aliasdata;
	    ATTRIBREC *ar;
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    aliasdata=find_alias(h,ATTRIBGROUPALIAS);
	    if (!aliasdata) {
		fprintf(stderr, "%s:%i: Unknow attribute name %s\n",
			confname, linecount, h);
		continue;
	    }
	    ar=aliasdata;
	    aliastype=ar->num;
	    h=get_string(&c,&tc);
	    while (ar && (ar->num==aliastype) && h) {
		ar->name=add_alias(h,(ar->value>=0?
				      ATTRIBVALUEALIAS(aliastype):
				      ATTRIBGROUPALIAS),
				   ar);
		ar=ar->next;
		h=get_string(&c,&tc);
	    }
	    if (h) {
		fprintf(stderr, "%s:%i: Too many attributes given\n.",
			confname, linecount);
	    }
	    if (ar && (ar->num==aliastype)) {
		fprintf(stderr, "%s:%i: Not enough values given\n",
			confname, linecount);
	    }
	} else if (!strncmp(bpos, "ATTRREMAP", 9)) {
	    /* Add an entry for remapping an attribute within a group */
	    char *c, *h;
	    char tc;
	    int aliastype;
	    void *aliasdata;
	    ATTRIBREC *ar;
	    ATTRIBREC *oav, *nav;
	    c = bpos+9;
	    tc = *c;
	    h=get_string(&c,&tc);
	    aliasdata=find_alias(h, ATTRIBGROUPALIAS);
	    if (!aliasdata) {
	      fprintf(stderr, "%s:%i: Unknown attribute name %s\n",
		      confname, linecount, h);
	      continue;
	    }
	    ar = aliasdata;
	    aliastype = ar->num;
	    h=get_string(&c, &tc);
	    oav=NULL; nav=NULL;
	    if (h) {
	      oav = find_alias(h, ATTRIBVALUEALIAS(aliastype));
	    }
	    if (oav) {
	      h=get_string(&c, &tc);
	      if (h) {
		nav = find_alias(h, ATTRIBVALUEALIAS(aliastype));
		if (!nav) {
		  fprintf(stderr,
			  "%s:%i: Unknown attribute value %s for group %s\n",
			  confname, linecount, h, ar->name);
		}
	      }
	    } else {
	      fprintf(stderr,
		      "%s:%i: Unknown attribute value %s for group %s\n",
		      confname, linecount, h, ar->name);
	    }
	    if (ar && oav && nav) {
	      *rmlist = malloc(sizeof(REMAPREC));
	      (*rmlist)->attrgroup = aliastype;
	      (*rmlist)->oldval = oav->value;
	      (*rmlist)->newval = nav->value;
	      (*rmlist)->next =0;
	      rmlist = &((*rmlist)->next);
	    }
	} else if (!strncmp(bpos, "ALIAS",5)) {
	    /* Define an alias for some identifier. */
	    char *c,*h;
	    char tc;
	    int aliastype;
	    void *aliasdata;
	    c=bpos+5;
	    tc=*c;
	    h=get_string(&c,&tc);
	    aliasdata=find_aliasname(h,&aliastype);
	    if (!aliasdata) {
		fprintf(stderr, "%s:%i: identifier %s unknown\n",
			confname, linecount, h);
		continue;
	    }
	    h=get_string(&c,&tc);
	    while (h) {
		/* check if h is already defined for that type */
		if (!find_alias(h,aliastype)) {
		    add_alias(h,aliastype, aliasdata);
		}
		h=get_string(&c,&tc);
	    }
	} else if (!strncmp(bpos, "RANGE", 5)) {
	    /* define a range.
	    ** syntax: RANGE name n k-l s-t
	    ** n,k,l,s and t are integers in one of the following formats:
	    ** decimal 65, octal 0101, hexadecimal 0x41, character 'A',
	    ** Unicode U+0041.  Sorry, no i18n for numbers yet.
	    ** The integers indicate the positions in the encoding of
	    ** the font, not in the Unicode encoding.
	    */
	    char *c, *h;
	    char tc;
	    RANGEREC *rr;
	    int len, actnum;
	    c=bpos+5;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No name specified\n",
			confname, linecount);
		continue;
	    }
	    (*rlist)=rr=malloc(sizeof(RANGEREC));
	    rr->name=add_alias(h,RANGEALIAS, rr);
	    rr->next=NULL;
	    rlist=&rr->next;
	    *c=tc;
	    /* upper limit to the length of the needed array is the length
	    ** of the string, since each number takes at least two positions
	    ** Add 2 for a termination pair.
	    */
	    skip_spaces(c);
	    len=strlen(c);
	    actnum=0;
	    rr->ranges=malloc(sizeof(int)*(len+2));
	    while (*c && actnum+1<len) {
		h=c;
		c=get_integer(c, rr->ranges+actnum);
		actnum++;
		if (*c=='-') {
		    c++;
		    c=get_integer(c,rr->ranges+actnum);
		} else {
		    rr->ranges[actnum]=rr->ranges[actnum-1];
		}
		actnum++;
		if (!isspace(*c)) {
		    find_spaces(c);
		    tc=*c;
		    *c=0;
		    fprintf(stderr, "%s:%i: strange range item %s\n",
			    confname, linecount, h);
		    *c=tc;
		}
		skip_spaces(c);
	    }
	    rr->ranges[actnum++]= -1;
	} else if (!strncmp(bpos, "ENCODING", 8)) {
	    /* Define an encoding for a font.
	    ** Multiple encoding can occur on the same line.
	    ** The encoding is only loaded when it is actually used.
	    */
	    char *c,*h;
	    char tc;
	    c=bpos+8;
	    tc=*c;
	    h=get_string(&c,&tc);
	    while (h) {
		*elist=malloc(sizeof(ENCODINGREC));
		(*elist)->encmap=0;
		(*elist)->mapfilename=add_alias(h, ENCODINGALIAS, *elist);
		(*elist)->next=0;
		elist=&(*elist)->next;
		h=get_string(&c,&tc);
	    }
	} else if (!strncmp(bpos, "FONTENC",7)) {
	    /* Define the encoding of the current font.
	    ** The name of the encoding has to be defined in an
	    ** "ENCODING" line, or as an alias for an encoding.
	    */
	    char *c, *h;
	    char tc;
	    ENCODINGREC *er;
	    if (!frec) {
		fprintf(stderr, "%s:%i: Not defining a font yet\n",
			confname,linecount);
		continue;
	    }
	    c=bpos+7;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No encoding specified\n",
			confname, linecount);
		continue;
	    }
	    er=find_alias(h, ENCODINGALIAS);
	    if (!er) {
		fprintf(stderr, "%s:%i: Unknown encoding %s\n",
			confname, linecount, h);
	    } else {
		frec->encoding=er;
	    }
	} else if (!strncmp(bpos, "FONTRANGE",9)) {
	    /* Define the range of a font. Certain fonts might be too
	    ** large or contain too many bad characters.  The range
	    ** is used to select certain characters from a font.
	    ** It will be used when the virtual font is defined and
	    ** when the font is loaded.
	    */
	    char *c, *h;
	    char tc;
	    RANGEREC *rr;
	    if (!frec) {
		fprintf(stderr, "%s:%i: Not defining a font yet\n",
			confname,linecount);
		continue;
	    }
	    c=bpos+9;
	    tc=*c;
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr, "%s:%i: No range specified\n",
			confname, linecount);
		continue;
	    }
	    rr=find_alias(h, RANGEALIAS);
	    if (!rr) {
		fprintf(stderr, "%s:%i: Unknown range %s\n",
			confname, linecount, h);
	    } else {
		frec->range=rr;
	    }
	} else if (!strncmp(bpos, "FONT",4)) {
	    /* Start defining a new font with auto-detection of attributes
	    ** and encoding. The auto-detection should not load the font
	    ** itself, but rather use the name of the font to detect
	    ** attributes: matching alias names, using a database.
	    */
	    char *c,*h;
	    char tc;
	    FONTREC *reslist;

	    c=bpos+4;
	    tc=*c;
	    h=get_string(&c,&tc);
	    frec = malloc(sizeof(FONTREC));
	    frec->fontname=malloc(sizeof(char)*(c-h+1)); /* c-h==strlen(h) */
	    strcpy(frec->fontname, h);
	    frec->attribpos=0;
	    frec->encoding=NULL;
	    frec->range=NULL;
	    frec->fonttype=frec->loaded=frec->bt=frec->bm=frec->bmax=0;
	    frec->font=0;
	    frec->systemdata=NULL;
	    frec->next=NULL;
	    /* system specific attribute detection */
	    reslist = multi_detect_attributes(frec);
	    /* Could check if reslist empty. However, it would indicate
	    ** that the font is not available.  Just ignore it or complain.
	    ** If the font would be added anyhow, it could result in messages
	    ** when the font has to be loaded.
	    */
	    if (reslist) {
	      free(frec->fontname);
	      free(frec);
	      *flist = reslist;
	      frec = reslist;
	      while (*flist) flist = &((*flist)->next);
	    } else {
	      free(frec->fontname);
	      free(frec);
	    }
	} else {
	    /* The line starts the name of an attribute followed by
	    ** its value. Find the attribute and the value and change
	    ** the attribute of the current font.
	    */
	    char *c,*h;
	    char tc;
	    ATTRIBREC *ar;
	    ATTRIBREC *aval;
	    int agr;
	    c=bpos;
	    tc=*c;
	    /* get attribute name and look it up */
	    h=get_string(&c,&tc);
	    ar=find_alias(h,ATTRIBGROUPALIAS);
	    if (!ar) {
		fprintf(stderr,"%s:%i: Unknow attribute group %s\n",
			confname, linecount, h);
		continue;
	    }
	    agr=ar->num;
	    /* get attribute value and look it up */
	    h=get_string(&c,&tc);
	    if (!h) {
		fprintf(stderr,"%s:%i: No attribute value specified.\n",
			confname, linecount);
		aval=NULL;
	    } else {
		aval=find_alias(h,ATTRIBVALUEALIAS(agr));
	    }
	    if (!aval) {
		/* Invalid attribute value.
		** Print valid attribute values as feedback.
		*/
		char *vname;
		fprintf(stderr,"%s:%i: Invalid attribute %s\n",
			confname, linecount, h);
		fprintf(stderr,"%s:%i: use one of:", confname, linecount);
		vname=find_type(ATTRIBVALUEALIAS(agr));
		while (vname) {
		    fprintf(stderr, " %s", vname);
		    vname=find_type_next();
		}
		fprintf(stderr, "\n");
		continue;
	    } else if (frec) {
		/* change font attribute of current collection of fonts */
	        FONTREC *flist;
		flist = frec;
		while (flist) {
		  flist->attribpos=change_attribute(flist->attribpos,
						    aval->num,
						    aval->value);
		  flist=flist->next;
		}
	    } else {
		fprintf(stderr, "%s:%i: Not defining a font yet or previous font not found.\n",
			confname, linecount);
	    }
	}
    }
    close_file(f);
    return build_font_structure();
}