/***************************************************************************
*
*                         UFS (Universal Fontselector)              25.12.91
*                              Modul: FONTSEL.C
*                            (c) by TheoSoft '91
*
***************************************************************************/
#include <portab.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aes.h>
#include <vdi.h>
#include <tos.h>

#include "ufsl.h"
#include "cookie.h"

#include "FONTNSEL.RSH"
#include "FONTNSEL.RH"

#define SCREEN      1
#define MAXENTRIES  5
#define MAXLETTERS 32
#define MAXSPACES  18
#define notnull(a) (((a)>0)?(a):(1))

#define MAXSIZES   	 16
#define PROPORTIONAL  0x0001
#define FREESCALABLE  0x0002
#define POINT_MAX  	 32767

#define DIALOG 0
#define WINDOW 1

#define FL3DMASK    0x0600
#define FL3DNONE    0x0000
#define FL3DIND     0x0200
#define FL3DBAK     0x0400
#define FL3DACT     0x0600

int cdecl draw_uline (PARMBLK *pb);
int cdecl draw_selfont (PARMBLK *pb);

USERBLK	u_line = {	draw_uline,
			0l };

USERBLK	selfont = {	draw_selfont,
			0l };

extern int	wk_handle, boxh, windials;

int cdecl fontsel_init(void); 
int cdecl fontsel_input(int vdihandle, int dummy, int ftype, char *text, int *id, int *size);
int cdecl fontsel_exinput(int vdihandle, int ftype, char *text, int *id, int *size);
void form_open(OBJECT *tree,int modus);
int form_close(OBJECT *tree, int exit_obj,int modus);
void form_write(OBJECT *tree, int item, char *string, int modus);
char *form_read(OBJECT *tree, int item, char *string);

static char info[]="\r\n\r\n\33pUFSL Universal Fontselector    \33q\r\nVersion %X.%02X vom %s\r\n(c) 1991-94 bei Michael Th„nitz\r\n\r\n";
static char alertstr[140];

static int internal_vdihandle,
           number_of_fonts,
           tid,
           tsize,
           headfontid=1,    /* Defaultwerte */
           headfontsize=10;

#include "ltmf_lib.c"

typedef struct
{
   char name[33];
   int id;
   int attr;
   int vektor; /* neu: Flag fr Vektor-Fonts */
   int size[MAXSIZES+1];
}FONTINFO;

static FONTINFO *fip=NULL;

UFSL fselptr=
{
   'UFSL',
   0x0097,
   DIALOG,
   fontsel_init,
   fontsel_input,
   &rs_object[FSHELP],
   NULL,
   NULL,
   NULL,
   fontsel_exinput
};

GRECT coords[NUM_OBS];

static int install_cookie(long cookie, long *ptr)
{
   int state;
   long savessp;

	savessp = Super((void *)1L);
	if(savessp == NULL)
	   savessp=Super(NULL);
   CK_SetOptions(8, cookie);
   state=CK_WriteJar(cookie, (long)ptr);
	if(savessp != -1L)
	   Super((void *) savessp);
	return(state);
}

/*****************************************************************************/
LOCAL VOID set_clip (handle, x, y, w, h)
WORD handle, x, y, w, h;
{
  WORD pxy [4];

  pxy [0] = x;
  pxy [1] = y;
  pxy [2] = x + w - 1;
  pxy [3] = y + h - 1;

  vs_clip (handle, TRUE, pxy);
} /* set_clip */

LOCAL VOID reset_clip (handle, x, y, w, h)
WORD handle, x, y, w, h;
{
  WORD pxy [4];

  pxy [0] = x;
  pxy [1] = y;
  pxy [2] = x + w - 1;
  pxy [3] = y + h - 1;

  vs_clip (handle, FALSE, pxy);
} /* set_clip */

/*****************************************************************************/
/* Zeichnet selektierten Font in der Fontbox						   				  */
/*****************************************************************************/

static int cdecl draw_selfont (PARMBLK *pb)
{
   int obx,oby,w,h,ret;
   int pxyarray[14];
/*
   char examplestr[32+1+3+2+1];
*/   
   char examplestr[40];

   pxyarray[10]=pb->pb_x;
   pxyarray[11]=pb->pb_y;
   pxyarray[12]=pb->pb_w;
   pxyarray[13]=pb->pb_h;
   if(rc_intersect(&pb->pb_xc,&pxyarray[10]))
   {
      set_clip (internal_vdihandle,pxyarray[10]+1,pxyarray[11]+1,pxyarray[12]-2,pxyarray[13]-2);

		vst_alignment(internal_vdihandle,0,ALI_DESCENT,&ret,&ret); /* Ausrichtung */
		vst_rotation(internal_vdihandle,0);
		vswr_mode(internal_vdihandle,MD_REPLACE);			 /* replace */
		vsf_interior(internal_vdihandle,FIS_SOLID);			 /* Fllung */
		vsf_color(internal_vdihandle,WHITE);				  /* farbe weiž */
		vst_color(internal_vdihandle,BLACK);

		pxyarray[0] = pb->pb_x + 1;
		pxyarray[1] = pb->pb_y + 1;
		pxyarray[2] = pb->pb_x + pb->pb_w - 2;
		pxyarray[3] = pb->pb_y + pb->pb_h - 2;
   	vr_recfl(internal_vdihandle,pxyarray);

      vst_font(internal_vdihandle,tid);
	   if(fip->vektor && vq_vgdos()==0x5F46534DL) /* Vektor-GDOS */
	      vst_arbpt(internal_vdihandle,tsize,&ret,&ret,&w,&h);
	   else
	      vst_point(internal_vdihandle,tsize,&ret,&ret,&w,&h);
      oby =  pb->pb_y;
      oby += (pb->pb_h - h)/2;
      if(fselptr.examplestr)
	      v_gtext(internal_vdihandle,pb->pb_x+1,pb->pb_y+pb->pb_h-2,fselptr.examplestr);
/*
	      v_gtext(internal_vdihandle,pb->pb_x+1,oby,fselptr.examplestr);
*/
      else
      {
      	sprintf(examplestr,"%d.%s",tsize,fip->name);
   	   v_gtext(internal_vdihandle,pb->pb_x+1,pb->pb_y+pb->pb_h-2,examplestr);
/*
   	   v_gtext(internal_vdihandle,pb->pb_x+1,oby,"The quick brown fox jumps over the lazy dog.");
*/
   	}

      set_clip (internal_vdihandle,pxyarray[10],pxyarray[11],pxyarray[12],pxyarray[13]);

		pxyarray[0] = pb->pb_x;
		pxyarray[1] = pb->pb_y;
		pxyarray[2] = pb->pb_x + pb->pb_w - 1;
		pxyarray[3] = pb->pb_y;
		pxyarray[4] = pxyarray[2];
		pxyarray[5] = pb->pb_y + pb->pb_h - 1;
		pxyarray[6] = pb->pb_x;
		pxyarray[7] = pxyarray[5];
		pxyarray[8] = pb->pb_x;
		pxyarray[9] = pb->pb_y;
   	vsl_type (internal_vdihandle, SOLID);
	   vsl_ends (internal_vdihandle, SQUARED, SQUARED);
   	vsl_width (internal_vdihandle, 1);
	   vsl_color (internal_vdihandle, BLACK);
		v_pline (internal_vdihandle, 5, pxyarray);

      reset_clip (internal_vdihandle,pxyarray[10],pxyarray[11],pxyarray[12],pxyarray[13]);
   }
	return (pb->pb_currstate);
}

static int cdecl draw_uline (PARMBLK *pb)
{
	int x, width, ret, pxy[4], pxyarray[4], attrib[18];

   set_clip (internal_vdihandle,pb->pb_xc,pb->pb_yc,pb->pb_wc,pb->pb_hc);
	vst_alignment(internal_vdihandle,0,5,&ret,&ret); /* Ausrichtung */
	vswr_mode (internal_vdihandle, MD_TRANS);
	vst_color (internal_vdihandle, BLACK);

/* nicht mehr ben”tigt
   vqt_attributes(wk_handle,attrib);
   vst_font(internal_vdihandle,attrib[0]);
*/

   vst_font(internal_vdihandle,headfontid);
   vst_point(internal_vdihandle,headfontsize,
             &ret,&ret,&ret,&ret);

	v_gtext(internal_vdihandle,pb->pb_x,pb->pb_y,(char *)((TEDINFO *)pb->pb_parm)->te_ptext);
	width=strlen((char *)((TEDINFO *)pb->pb_parm)->te_ptext)*8+2;

	pxy[0]=pb->pb_x - 1;
	pxy[1]=pb->pb_y + pb->pb_h;
	pxy[2]=pb->pb_x - 1 + width - 1;
	pxy[3]=pxy[1];
	vswr_mode (internal_vdihandle, MD_REPLACE);
	vsl_type(internal_vdihandle, 1);
	vsl_color (internal_vdihandle, BLACK);
	vsl_width(internal_vdihandle, 1);
	v_pline(internal_vdihandle,2,pxy);

	return (pb->pb_currstate);
} /* draw_uline */

void init_userdef(OBJECT *tree)
{
	tree[ROOT+2].ob_type = G_USERDEF;
	u_line.ub_parm=tree[ROOT+2].ob_spec.userblk;
	tree[ROOT+2].ob_spec.userblk = &u_line;

	tree[FSSHOW].ob_x      -= 1;
	tree[FSSHOW].ob_y      -= 1;
	tree[FSSHOW].ob_width  += 2;
	tree[FSSHOW].ob_height += 2;

	tree[FSSHOW].ob_type = G_USERDEF;
	tree[FSSHOW].ob_spec.userblk = &selfont;
}

static void fix_tree(int n_tree)
{
  register int tree,     /* index for trees */
               object;   /* index for objects */
  OBJECT       *pobject;
  for (tree = 0; tree < n_tree; tree++) /* fix trees */
  {
    object  = 0;
    pobject = rs_trindex [tree];
    do
    {
      rsrc_obfix(pobject,object);
    } while (! (pobject [object++].ob_flags & LASTOB));
  } /* for */
} /* fix_tree */

static void unfix_tree(int n_obs)
{
 int i;

 for(i=0;i<n_obs;i++) *(GRECT*)&rs_object[i].ob_x=coords[i];
}

static void savecoords(int n_obs)
{
 int i;

 for(i=0;i<n_obs;i++) coords[i]=*(GRECT*)&rs_object[i].ob_x;
}

void objc_update(OBJECT *tree, int obj, int depth)
{
	int obx,oby;
	int full[4],area[4],array[4];
	extern int windials, dial_handle;
		
	objc_offset(tree,obj,&array[0],&array[1]);
	if(TRUE/*obj==ROOT*/) /* 3 Pixel Rand beachten, vorsicht 3D beachten */
	{
		array[0]-=3;
		array[1]-=3;
		array[2]=tree[obj].ob_width+6;
		array[3]=tree[obj].ob_height+6;
	}
/*
	else
	{
		array[2]=tree[obj].ob_width;
		array[3]=tree[obj].ob_height;
	}
*/
	if((windials) && (dial_handle!=-1))
	{
		wind_update(BEG_UPDATE);
		wind_get( 0, WF_WORKXYWH,  &full[0], &full[1], &full[2], &full[3]);
		wind_get(dial_handle, WF_FIRSTXYWH, &area[0], &area[1], &area[2], &area[3]);
		while( area[2] && area[3] )
		{
			if(rc_intersect(full,area))
				if(rc_intersect(array,area))
					objc_draw(tree,obj,depth,area[0],area[1],area[2],area[3]);
			wind_get(dial_handle, WF_NEXTXYWH,&area[0],&area[1],&area[2],&area[3]);
		}
		wind_update(END_UPDATE);
	}
	else
	{
		objc_draw(tree,obj,depth,array[0],array[1],array[2],array[3]);
	}
}

static void set_vslider(OBJECT *tree, int ext, int slide,  int newpos)
{
   long oldpos;
   oldpos=tree[ext].ob_height-tree[slide].ob_height;
   tree[slide].ob_y=(int)(oldpos*(long)newpos/1000L);
}

static void set_hslider(OBJECT *tree, int ext, int slide,  int newpos)
{
   long oldpos;
   oldpos=tree[ext].ob_width-tree[slide].ob_width;
   tree[slide].ob_x=(int)(oldpos*(long)newpos/1000L);
}

/*
 * Derzeit auf der angeg. WK eingestellte Punktgr”že ermitteln. Wenn keine
 * passende Punktgr”že gefunden wird, wird -1 geliefert
 */

static int cur_point(int handle, int *fontid, int *fontsize)
{
   int size, prev_size;
   int attrib[10], w, h, ld, rd, dummy;

   vqt_attributes(handle, attrib);
   size = prev_size = POINT_MAX + 1;
   while (--size)
   {
      size = vst_point(handle, size, &dummy, &dummy, &w, &h);
      if (size == prev_size)
         break;
      if (w == attrib[8] && h == attrib[9]) /* Aktuelle Gr”že? */
      {
         *fontid=attrib[0];
         *fontsize=size;
         return(TRUE);                      /* Gefunden */
      }
      prev_size = size;
   }                             /* Anfangszustand wiederherstellen */
   vst_height(handle, attrib[7], &dummy, &dummy, &dummy, &dummy);
   return(-3);                   /* Nicht als Punktgr”že vorhanden */
}

static int selfontsize(int size, int sizearray[])
{
   register int i;
   for(i=0; sizearray[i]!=-1; i++)
      if(size==sizearray[i])
         return(i);
   for(i=1; sizearray[i]!=-1; i++)
      if(size>sizearray[i-1] && size<sizearray[i])
      {
         if(abs(size-sizearray[i-1]) < abs(size-sizearray[i]))
            return(i-1);
         else
            return(i);
      }
   return(0);
}

static int isprop(int handle, int id)
{
   int ret, width, tst_width, dummy[5];

   vst_point(handle,10,&ret,&ret,&ret,&ret);
   vqt_width(handle, 'l', &width, dummy, dummy);      /* Breite 1. Zeichen */
   vqt_width(handle, 'W', &tst_width, dummy, dummy);  /* Breite 2. Zeichen */
   if (tst_width != width)  /* Ungleich? */
      return(PROPORTIONAL); /* Ja -> Font ist proportional */
   return(FALSE);           /* Alle Zeichen gleich breit -> Font ist monospaced */
}

static void fsreverse(int *a, int *b, int cnt)
{
   register int i;
   for(i=cnt; i>0; i--)
      *a++ = *b--;
}

static int scan_font_names(int handle, FONTINFO font[], int count, int ftype)
{
   FONTINFO *fiptr;
   int id,i,j,k,m,ret,vekt;
   char *cp,name[64];
   int prop=0,fstemp[MAXSIZES+1];

   for(i=1,m=0; i<=count; i++)
   {
      name[63]=0;
      id=vqt_name(handle,i,name);
      vekt=name[32];
      name[32]=0;

      if(stricmp(name,"dummy font"))
      {
       vst_font(handle,id);

       if(ftype && isprop(handle, id))
       {
          prop++;
       }
       else
       {
        fiptr=&font[m++];
        strcpy(fiptr->name,name);
        /* mehrfache Blanks killen */
        cp=strchr(fiptr->name,' ');
        while(cp)
        {
           if(*(cp+1L) == ' ')
              strcpy(cp,cp+1L);
           cp=strchr((*(cp+1L)==' '?cp:cp+1L),' ');
        }
        fiptr->id=id;
        fiptr->attr=ftype;
        fiptr->vektor=vekt;
        fstemp[0]=-1;
        for(j=POINT_MAX,k=1; j>0 && k<=MAXSIZES; /* nix */)
        {
           fstemp[k]=j=vst_point(handle,j,&ret,&ret,&ret,&ret);
           if(fstemp[k]==fstemp[k-1])
              break;
           else
             j--,k++;
        }
        fsreverse(fiptr->size,&fstemp[k-1],k);
       }
      }
   }
   return(count-prop);
}

static int work_in[103],work_out[57];

static int open_work (int device)
{
   register int i;
   int handle;

   for (i = 0; i < 103; i++) work_in [i] = 1;
   work_in [0]  = device;                         /* device handle */
   work_in [10] = 2;                         /* Raster Koordinaten */

   if (device == SCREEN)
   {
     handle=wk_handle;
     v_opnvwk (work_in, &handle, work_out);     /* virtuell ”ffnen */
   }
   else                                        /* nicht Bildschirm */
   {
     v_opnwk (work_in, &handle, work_out);  /* physikalisch ”ffnen */
   }
   return (handle);
}

void close_work (int handle, int device)
{
  switch (device)
  {
    case SCREEN:
       v_clsvwk (handle);
       break;
    default:
       v_clswk (handle);
       break;
  }
}

int cdecl fontsel_init(void)
{
   static int firstentry=TRUE;
   static int  oboxw=0,  oboxh=0, ocharw=0, ocharh=0;
   static int oxdesk=0, oydesk=0, owdesk=0, ohdesk=0;
          int xdesk, ydesk, wdesk, hdesk;
          int boxw, charw, charh;
   
   OBJECT *tree;
   int i;

   if(firstentry)
   {
      savecoords(NUM_OBS);
   }
   wk_handle = graf_handle(&boxw, &boxh, &charw, &charh);
	wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
   if((xdesk != oxdesk) || /* Aufl”sungswechsel? */
      (ydesk != oydesk) ||
      (wdesk != owdesk) ||
      (hdesk != ohdesk) ||
      ( boxw !=  oboxw) || 
      ( boxh !=  oboxh) || 
      (charw != ocharw) || 
      (charh != ocharh)  
     )
   {
      unfix_tree(NUM_OBS);
      fix_tree(NUM_TREE);
      tree=(OBJECT *)rs_trindex[FONTSEL];
      form_center(tree,&i,&i,&i,&i);
      oboxw  =  boxw;
      oboxh  =  boxh;
      ocharw = charw;
      ocharh = charh;
      oxdesk = xdesk;
      oydesk = ydesk;
      owdesk = wdesk;
      ohdesk = hdesk;
   }
   if(firstentry)
   {
      tree=(OBJECT *)rs_trindex[FONTSEL];
      init_userdef(tree);
      if(!init_flyobj(tree))
			tree[ROOT+1].ob_flags|=HIDETREE;
      form_center(tree,&i,&i,&i,&i);
		if(get_cookie('MiNT') && (_GemParBlk.global[1] != 1)) /* MultiTOS */
		{
			tree[FNTITLE].ob_spec.tedinfo->te_color&=~(7<<4); /* l”schen */
			tree[FNTITLE].ob_spec.tedinfo->te_color|=(4<<4);  /* neues Muster 4 */
			tree[FSTITLE].ob_spec.tedinfo->te_color&=~(7<<4); /* l”schen */
			tree[FSTITLE].ob_spec.tedinfo->te_color|=(4<<4);  /* neues Muster 4 */
			tree[FTBOX  ].ob_spec.obspec.fillpattern=4;
			tree[FTHBOX ].ob_spec.obspec.fillpattern=4;
			tree[FSBOX  ].ob_spec.obspec.fillpattern=4;
		   tree[FSINFO ].ob_state&=~SHADOWED;
  			tree[FSINFO ].ob_flags|=FL3DBAK;
		}
		else if(get_cookie('LTMF'))
		{
		   tree[FSOK].ob_y--;
		   tree[FSOK].ob_height+=2;
		   tree[FSABBR].ob_y--;
		   tree[FSABBR].ob_height+=2;
		}
      firstentry=FALSE;
   }   
	internal_vdihandle=open_work(SCREEN);
   if(cur_point(internal_vdihandle, &headfontid, &headfontsize)==-3)
   {
      headfontid=1;    /* Defaultwerte */
      headfontsize=10;
   }
   if(vq_gdos())
      number_of_fonts=vst_load_fonts(internal_vdihandle,0)+work_out[10];
   else
      number_of_fonts=work_out[10]; /* Nur 6x6 system font */

   if(fselptr.helpfunc)
      tree[FSHELP].ob_flags&=~HIDETREE;
	else
      tree[FSHELP].ob_flags|=HIDETREE;

   if(vq_vgdos()==0x5F46534D) /* Vektor-GDOS */
   {
      tree[FSARBPT].ob_flags&=~HIDETREE;
      tree[FSARBPT].ob_flags|=EDITABLE;
   }
	else
	{
      tree[FSARBPT].ob_flags|=HIDETREE;
      tree[FSARBPT].ob_flags&=~EDITABLE;
   }

   windials=fselptr.dialtyp;
}
 
static int fontsel_exit(void)
{
   OBJECT *tree;
   tree=(OBJECT *)rs_trindex[FONTSEL];
	strcpy((char *)((TEDINFO *)tree[ROOT+2].ob_spec.userblk->ub_parm)->te_ptext,"FONTAUSWAHL:");
   fselptr.dialtyp=DIALOG;
   fselptr.helpfunc=NULL;
   fselptr.examplestr=NULL;
   fselptr.msgfunc=NULL;
   tree[FSHELP].ob_flags|=HIDETREE;

   if(vq_gdos())
      vst_unload_fonts(internal_vdihandle,0);
   close_work(internal_vdihandle,SCREEN);
}

int cdecl fontsel_input(int vdihandle, int dummy, int ftype, char *text, int *id, int *size)
{
/*
   static FONTINFO *fip;
*/
   static long nf2=0,sf2=0;
   static int inuse=FALSE;
   
   FONTINFO *font;
   OBJECT *tree;

   long nfirst,sfirst,hfirst,scount;
   int exit_obj,done=FALSE;
   int kstate,i,k,ret,mx,my,newpos=0;
   int obx,oby;
   int fontid, fontsize, saveid, savesize;
   
   char string[33];

   if(inuse)
      return(-2);
   
   fontsel_init();

   if(number_of_fonts==0)
   {
	   fontsel_exit();
      return(-4); /* Anzahl Fonts = 0 */
   }
      
   saveid   =   *id;
   savesize = *size;

   tree=(OBJECT *)rs_trindex[FONTSEL];
   if((font=(FONTINFO *)Malloc(number_of_fonts*sizeof(FONTINFO)))==NULL)
   {
	   fontsel_exit();
      return(-1); /* Fehler! */
   }
	memset(font,0,number_of_fonts*sizeof(FONTINFO));
   if(cur_point(vdihandle, &fontid, &fontsize)==-3)
   {
      Mfree(font);
	   fontsel_exit();
      return(-3); /* Fehler! */
   }
   
   inuse=TRUE;

   number_of_fonts=scan_font_names(internal_vdihandle, font, number_of_fonts, ftype);

   /* Fontnamenslidergr”že „ndert sich nie */
   tree[FTHSLD].ob_width=MAXSPACES*tree[FTHBOX].ob_width/MAXLETTERS;
   set_hslider(tree,FTHBOX,FTHSLD,0);
   tree[FTSLIDE].ob_height=MAXENTRIES*tree[FTBOX].ob_height/max(MAXENTRIES,number_of_fonts);
   set_vslider(tree,FTBOX,FTSLIDE,0);

/**************************************************************************/
/* letzte OK-Werte einstellen, falls verstellt und Abbruch gedrckt wurde */
/**************************************************************************/

   nfirst=nf2;
   sfirst=sf2;
   hfirst=0;

   for(i=nfirst; i<number_of_fonts /*&& i<MAXFONTS*/; i++) /* erstmal suchen,... */
      if(font[i].id==fontid)              /* falls nicht in Box */
      {
         fip=&font[i];
         if((i-nfirst)>MAXENTRIES)
            nf2=nfirst=(i-MAXENTRIES+1);
      }

   /* Namenseinstellung */
   for(i=FTYPE1; i<=FTYPE5; i++)
   {
      tree[i].ob_state&=~SELECTED;
      tree[i].ob_flags&=~SELECTABLE;
   }
   newpos=(int)(nfirst*1000L)/notnull(number_of_fonts-MAXENTRIES);
   newpos=min(newpos,1000);
   newpos=max(0,newpos);
   set_vslider(tree,FTBOX,FTSLIDE,newpos);
   newpos=(int)(hfirst*1000L)/(MAXLETTERS-MAXSPACES);
   newpos=min(newpos,1000);
   newpos=max(0,newpos);
   set_hslider(tree,FTHBOX,FTHSLD,newpos);
   for(i=nfirst,k=0; i<number_of_fonts /*&& i<MAXFONTS*/ && k<MAXENTRIES; i++,k++)
   {
      sprintf(string," %-16s ",&font[i].name[hfirst]);
      string[MAXSPACES]=0;
      form_write(tree,FTYPE1+k,string,FALSE);
      tree[FTYPE1+k].ob_flags|=SELECTABLE;
      if(font[i].id==fontid)
      {
         tree[FTYPE1+k].ob_state|=SELECTED;
         fip=&font[i];
      }
   }
	for(; k<MAXENTRIES; k++)
	{
		memset(string,' ',MAXLETTERS);
		string[MAXLETTERS]=0;
		form_write(tree,FTYPE1+k,string,FALSE);
	}

   /* Punkteinstellung */
   for(i=FSIZE1; i<=FSIZE5; i++)
   {
      form_write(tree,i,"",FALSE);
      tree[i].ob_state&=~SELECTED;
      tree[i].ob_flags&=~SELECTABLE;
   }
   for(scount=0; fip->size[scount]!=-1; scount++)
      ;
   for(i=sfirst; i<scount && i<MAXSIZES; i++) /* erstmal suchen,... */
      if(fip->size[i]==fontsize)              /* falls nicht in Box */
      {
         if((i-sfirst)>MAXENTRIES)
            sf2=sfirst=(i-MAXENTRIES+1);
      }
   tree[FSSLIDE].ob_height=MAXENTRIES*tree[FSBOX].ob_height/max(MAXENTRIES,scount);
   newpos=(int)(sfirst*1000L)/notnull(scount-MAXENTRIES);
	newpos=min(newpos,1000);
	newpos=max(0,newpos);
   set_vslider(tree,FSBOX,FSSLIDE,newpos);

   for(i=sfirst,k=0; i<MAXSIZES && k<MAXENTRIES && i<scount; i++,k++)
   {
      sprintf(tree[FSIZE1+k].ob_spec.tedinfo->te_ptext," %3d ",fip->size[i]);
      tree[FSIZE1+k].ob_flags|=SELECTABLE;
      if(fip->size[i]==fontsize)
      {
         tree[FSIZE1+k].ob_state|=SELECTED;
         sprintf(string,"%3d",fontsize);
         form_write(tree,FSARBPT,string,FALSE);
      }
   }

/**************************************************************************/

	if(text)
		strcpy((char *)((TEDINFO *)tree[ROOT+2].ob_spec.userblk->ub_parm)->te_ptext,text);
	else
		strcpy((char *)((TEDINFO *)tree[ROOT+2].ob_spec.userblk->ub_parm)->te_ptext,"FONTAUSWAHL:");

	tid=*id=fontid, tsize=*size=fontsize;

   form_open(tree,0);
   do
   {
      exit_obj=form_exdo(tree,0);
		graf_mkstate(&mx,&my,&ret,&kstate);
      switch(exit_obj)
      {
         case FSINFO:
sprintf(alertstr,
"[0][  UFSL Universal Fontselector| Version %X.%02X vom %s|(c) 1991-94 bei Michael Th„nitz][  OK  ]",
fselptr.version>>8,fselptr.version&0xFF,__DATE__);
			   form_alert(1,alertstr);
				objc_change(tree,exit_obj,0,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height,tree[exit_obj].ob_state&~SELECTED,TRUE);
			   break;
         case FTLF:
            if(hfirst>0)
               hfirst--;
            else
               exit_obj=-1;  /* l”schen */
            break;
         case FTRT:
            if(hfirst<(MAXLETTERS-MAXSPACES)) /* MAXSPACES+8=MAXLETTERS */
               hfirst++;
            else
               exit_obj=-1;
            break;
         case FTUP:
				if(kstate & (K_LSHIFT|K_RSHIFT))
				{
					if((nfirst-MAXENTRIES)>0)
						nfirst-=MAXENTRIES;
					else
						nfirst=0;
				}
				else
				{
	            if(nfirst>0)
	               nfirst--;
	            else
	               exit_obj=-1;
	         }
            break;
         case FTDN:
				if(kstate & (K_LSHIFT|K_RSHIFT))
				{
					if((nfirst+MAXENTRIES)<(number_of_fonts-MAXENTRIES))
						nfirst+=MAXENTRIES;
					else
						nfirst=number_of_fonts-MAXENTRIES;
				}
				else
				{
	            if(nfirst<number_of_fonts-MAXENTRIES)
	               nfirst++;
	            else
	               exit_obj=-1;
	         }
            break;
         case FSUP:
            if(sfirst>0)
               sfirst--;
            else
               exit_obj=-1;
            break;
         case FSDN:
            if(sfirst<scount-MAXENTRIES)
               sfirst++;
            else
               exit_obj=-1;
            break;
         case FTHSLD:
            graf_mouse(FLAT_HAND,NULL);
            newpos=graf_slidebox(tree,FTHBOX,FTHSLD,0);
            graf_mouse(ARROW,NULL);
            hfirst=((newpos*(MAXLETTERS-MAXSPACES))/1000L);
            break;
         case FTSLIDE:
            graf_mouse(FLAT_HAND,NULL);
            newpos=graf_slidebox(tree,FTBOX,FTSLIDE,1);
            graf_mouse(ARROW,NULL);
            nfirst=((newpos*(number_of_fonts-MAXENTRIES))/1000L);
            break;
         case FSSLIDE:
            graf_mouse(FLAT_HAND,NULL);
            newpos=graf_slidebox(tree,FSBOX,FSSLIDE,1);
            graf_mouse(ARROW,NULL);
            sfirst=((newpos*(scount-MAXENTRIES))/1000L);
            break;
         case FTHBOX:
            objc_offset(tree,FTHSLD,&obx,&oby);
            if(mx>obx)
            {
               if((hfirst+MAXSPACES)<(MAXLETTERS-MAXSPACES))
                  hfirst+=MAXSPACES;
               else
                  hfirst=MAXLETTERS-MAXSPACES;
            }
            else
            {
               if((hfirst-MAXSPACES)>0)
                  hfirst-=MAXSPACES;
               else
                  hfirst=0;
            }
            break;
         case FTBOX:
            objc_offset(tree,FTSLIDE,&obx,&oby);
            if(my>oby)
            {
               if((nfirst+MAXENTRIES)<(number_of_fonts-MAXENTRIES))
                  nfirst+=MAXENTRIES;
               else
                  nfirst=number_of_fonts-MAXENTRIES;
            }
            else
            {
               if((nfirst-MAXENTRIES)>0)
                  nfirst-=MAXENTRIES;
               else
                  nfirst=0;
            }
            break;
         case FSBOX:
            objc_offset(tree,FSSLIDE,&obx,&oby);
            if(my>oby)
            {
               if((sfirst+MAXENTRIES)<(scount-MAXENTRIES))
                  sfirst+=MAXENTRIES;
               else
                  sfirst=scount-MAXENTRIES;
            }
            else
            {
               if((sfirst-MAXENTRIES)>0)
                  sfirst-=MAXENTRIES;
               else
                  sfirst=0;
            }
            break;
         case FTYPE1:
         case FTYPE1+1:
         case FTYPE1+2:
         case FTYPE1+3:
         case FTYPE1+4:
         case FTYPE1+5:
            if(tree[exit_obj].ob_flags & SELECTABLE &&
             !(tree[exit_obj].ob_state & DISABLED))
            {
               for(i=FSIZE1; i<=FSIZE5; i++)
               {
                  tree[i].ob_state &= ~SELECTED;
                  tree[i].ob_flags &= ~SELECTABLE;
               }
               fip=&font[exit_obj-FTYPE1+nfirst];
               *id=fip->id;
               for(scount=0; fip->size[scount]!=-1; scount++)
                  ;
               tree[FSSLIDE].ob_height=MAXENTRIES*tree[FSBOX].ob_height/max(MAXENTRIES,scount);
               set_vslider(tree,FSBOX,FSSLIDE,0);
               objc_update(tree,FSBOX,MAX_DEPTH);
               k=selfontsize(fontsize,fip->size);
               *size=fip->size[k];
               for(i=0; i<=(FSIZE5-FSIZE1)  && fip->size[i]!=-1; i++)
               {
                  tree[FSIZE1+i].ob_flags |= SELECTABLE;
                  sprintf(tree[FSIZE1+i].ob_spec.tedinfo->te_ptext,
                     " %3d ",fip->size[i]);
                  if(k==i) /* Fontsize == Eintrag? */
                  {
                     tree[FSIZE1+i].ob_state |= SELECTED;
				         sprintf(string,"%3d",fip->size[i]);
				         form_write(tree,FSARBPT,string,TRUE);
                  }
                  objc_draw(tree,FSIZE1+i,0,tree->ob_x,tree->ob_y,
                     tree->ob_width,tree->ob_height);
               }
               for(; i<=(FSIZE5-FSIZE1); i++)
                  form_write(tree,FSIZE1+i,"     ",TRUE);
               sfirst=0;
            }
            break;
			case FSHELP:
			   if(fselptr.helpfunc)
				   fselptr.helpfunc();
				else
					Bconout(2,7);
				objc_change(tree,exit_obj,0,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height,tree[exit_obj].ob_state&~SELECTED,TRUE);
				break;
         case FSOK:
         case FSABBR:
            done=TRUE;
            break;
      }
      if(exit_obj&0x8000) /* verlassen bei Doppelklick */
      {
         switch(exit_obj&=0x7fff)
         {
	         case FTYPE1:
	         case FTYPE1+1:
	         case FTYPE1+2:
	         case FTYPE1+3:
	         case FTYPE1+4:
	         case FTYPE1+5:
	         case FSIZE1:
	         case FSIZE1+1:
	         case FSIZE1+2:
	         case FSIZE1+3:
	         case FSIZE1+4:
	         case FSIZE1+5:
               objc_change(tree,FSOK,0,tree->ob_x,tree->ob_y,
                           tree->ob_width,tree->ob_height,SELECTED,TRUE);
	            done=TRUE;
	            break;
				case FTLF:
					if(hfirst>0)
						hfirst=0;
					else
						exit_obj=-1;  /* l”schen */
					break;
				case FTRT:
					if(hfirst<MAXLETTERS-MAXSPACES) /* MAXSPACES+8=MAXLETTERS */
						hfirst=MAXLETTERS-MAXSPACES;
					else
						exit_obj=-1;
					break;
				case FTUP:
					if(nfirst>0)
						nfirst=0;
					else
						exit_obj=-1;
					break;
				case FTDN:
					if(nfirst<number_of_fonts-MAXENTRIES)
						nfirst=number_of_fonts-MAXENTRIES;
					else
						exit_obj=-1;
					break;
				case FSUP:
					if(sfirst>0)
						sfirst=0;
					else
						exit_obj=-1;
					break;
				case FSDN:
					if(sfirst<scount-MAXENTRIES)
						sfirst=scount-MAXENTRIES;
					else
						exit_obj=-1;
					break;
				case FSSHOW:
            case FSARBPT:
		         form_read(tree,FSARBPT,string);
      		   if(*size!=atoi(string))
      		   {
            		*size=atoi(string);
						tid=*id,tsize=*size;
						objc_update(tree,FSSHOW,0);
					}
               break;
         }
      }
      switch(exit_obj)
      {
         case FTLF:
         case FTRT:
         case FTHBOX:
         case FTHSLD:
            newpos=(int)(hfirst*1000L)/(MAXLETTERS-MAXSPACES);
            newpos=min(newpos,1000);
            newpos=max(0,newpos);
            set_hslider(tree,FTHBOX,FTHSLD,newpos);
            objc_update(tree,FTHBOX,MAX_DEPTH);
            for(i=nfirst,k=0; k<MAXENTRIES && k<number_of_fonts; i++,k++)
            {
               sprintf(string," %-16s ",&font[i].name[hfirst]);
               string[MAXSPACES]=0;
               form_write(tree,FTYPE1+k,string,TRUE);
            }
            break;
         case FTUP:
         case FTDN:
         case FTBOX:
         case FTSLIDE:
            if(number_of_fonts>MAXENTRIES)
            {
               for(i=FTYPE1; i<=FTYPE5; i++)
                  tree[i].ob_state&=~SELECTED;
               newpos=(int)(nfirst*1000L)/notnull(number_of_fonts-MAXENTRIES);
               newpos=min(newpos,1000);
               newpos=max(0,newpos);
               set_vslider(tree,FTBOX,FTSLIDE,newpos);
               objc_update(tree,FTBOX,MAX_DEPTH);
               for(i=nfirst,k=0; k<MAXENTRIES; i++,k++)
               {
                  sprintf(string," %-16s ",&font[i].name[hfirst]);
                  string[MAXSPACES]=0;
                  form_write(tree,FTYPE1+k,string,TRUE);
                  if(font[i].id==*id)
                  {
                     tree[FTYPE1+k].ob_state|=SELECTED;
                     objc_update(tree,FTYPE1+k,0);
                  }
               }
            }
            break;
         case FSUP:
         case FSDN:
         case FSBOX:
         case FSSLIDE:
            if(scount>MAXENTRIES)
            {
               for(i=FSIZE1; i<=FSIZE5; i++)
                  tree[i].ob_state&=~SELECTED;
               newpos=(int)(sfirst*1000L)/notnull(scount-MAXENTRIES);
               newpos=min(newpos,1000);
               newpos=max(0,newpos);
               set_vslider(tree,FSBOX,FSSLIDE,newpos);
               objc_update(tree,FSBOX,MAX_DEPTH);
               for(i=sfirst,k=0; i<MAXSIZES && k<MAXENTRIES; i++,k++)
               {
                  if(fip->size[i]==*size)
                  {
                     tree[FSIZE1+k].ob_state|=SELECTED;
				         sprintf(string,"%3d",fip->size[i]);
				         form_write(tree,FSARBPT,string,TRUE);
				      }
                  sprintf(tree[FSIZE1+k].ob_spec.tedinfo->te_ptext,
                     " %3d ",fip->size[i]);
                  objc_update(tree,FSIZE1+k,0);
               }
            }
            break;
      }
      switch(exit_obj)
      {
         case FTYPE1:
         case FTYPE1+1:
         case FTYPE1+2:
         case FTYPE1+3:
         case FTYPE1+4:
         case FTYPE1+5:
         case FSIZE1:
         case FSIZE1+1:
         case FSIZE1+2:
         case FSIZE1+3:
         case FSIZE1+4:
         case FSIZE1+5:
            for(i=FTYPE1,k=0; i<=FTYPE5; i++,k++)
               if(tree[i].ob_state & SELECTED)
               {
                  fip=&font[k+nfirst];
                  *id=fip->id;
                  break;
               }
            for(i=FSIZE1,k=0; i<=FSIZE5; i++,k++)
               if(tree[i].ob_state & SELECTED)
               {
                  *size=fip->size[k+sfirst];
						tid=*id,tsize=*size;
						objc_update(tree,FSSHOW,0);
			         sprintf(string,"%3d",*size);
			         form_write(tree,FSARBPT,string,TRUE);
               }
            break;
      }
   }
   while(done!=TRUE);
   form_close(tree, exit_obj,0);
   tree[FSOK].ob_state&=~SELECTED;
   Mfree(font);
   inuse=FALSE;

   fontsel_exit();             /* alles auf NULL */
   
   switch(exit_obj&=0x7FFF)
   {
      case FTYPE1:
      case FTYPE1+1:
      case FTYPE1+2:
      case FTYPE1+3:
      case FTYPE1+4:
      case FTYPE1+5:
      case FSIZE1:
      case FSIZE1+1:
      case FSIZE1+2:
      case FSIZE1+3:
      case FSIZE1+4:
      case FSIZE1+5:
      case FSOK:
         nf2=nfirst;
         sf2=sfirst;
         form_read(tree,FSARBPT,string);
         if(*size!=atoi(string))
            *size =atoi(string);
         return(TRUE);
   }
   *id=saveid;
   *size=savesize;
   return(FALSE);
}

int cdecl fontsel_exinput(int vdihandle, int ftype, char *text, int *id, int *size)
{
   OBJECT *tree;
   tree=(OBJECT *)rs_trindex[FONTSEL];
   tree[FSHELP].ob_flags|=HIDETREE;
   fselptr.helpfunc=NULL;

   return(fontsel_input(vdihandle, 0, ftype, text, id, size));
}

void main(void)
{
   UFSL *ufsl;

   ufsl=get_cookie('UFSL');
   if(!ufsl)
   {
		if(install_cookie('UFSL',(long *)&fselptr))
		{
			sprintf(alertstr,info,fselptr.version>>8,fselptr.version&0xFF,__DATE__);
		   Cconws(alertstr);
	   	Ptermres(_PgmSize,0);
   	}
   	else
   	   Cconws("\r\nUFSL: Fehler bei der Cookieinstallation!\r\n");
   }
   else
   {
      if(ufsl->version <  fselptr.version)
	      Cconws("\r\nEine „ltere Version von UFSL schon installiert!\r\n");
      if(ufsl->version >  fselptr.version)
	      Cconws("\r\nEine neuere Version von UFSL schon installiert!\r\n");
      if(ufsl->version == fselptr.version)
   	   Cconws("\r\nUFSL schon installiert!\r\n");
   }
}
