/************************/
/*			*/
/* Font loading, saving */
/* and previewing.	*/
/*			*/
/************************/

#include "Typeface.h"

struct Window *PreviewWnd;
struct ClipboardHandle *Clip, *Undo;
Object *PreviewWndObj, *PreviewStr, *PreviewScroll;
UBYTE *PreviewFont;

struct Window *QueryWnd;
Object *QueryWndObj, *QueryWidthNum;

struct TextFont *tfh;
struct NewMenu PreviewMenus[] = { PROJECT_MENU,FONT_MENU,PREVIEW_MENU,End };

extern struct Screen *Screen;
extern struct MsgPort *WndMsgPort;
extern struct Character CharBuffer[257];
extern struct Window *SaveWnd;
extern struct TextFont *NewFont;
extern Object *SaveWndObj, *FontWndObj;
extern ULONG FirstChar, LastChar;
extern char WinTitle[256];

void OpenPreviewWnd(void)
{
Object *all, *cancel, *update, *clear;

  if (PreviewWnd)
  {
    WindowToFront(PreviewWnd);
    ActivateWindow(PreviewWnd);
    SetPreviewFont();
    SetPreviewScroller();
    ActivateGadget((struct Gadget *)PreviewStr,PreviewWnd,NULL);
  }
  else
  {
    if (PreviewWndObj == NULL)
    {
      Clip = OpenClipboard(PRIMARY_CLIP);
      Undo = OpenClipboard(1);
      SetupMenus(PreviewMenus);
      PreviewWndObj = WindowObject,
	WINDOW_Screen,Screen,
	WINDOW_SharedPort,WndMsgPort,
	WINDOW_MenuStrip,PreviewMenus,
	WINDOW_Title,GetString(msgPreviewTitle),
	WINDOW_HelpFile,NAME".guide",
	WINDOW_HelpNode,"preview",
	WINDOW_ScaleWidth,70,
	WINDOW_ScaleHeight,70,
	WINDOW_SmartRefresh,TRUE,
	WINDOW_CloseOnEsc,TRUE,
	WINDOW_MasterGroup,
	  VGroupObject,
	    HOffset(SizeX(8)),VOffset(SizeY(4)),Spacing(SizeY(4)),
	    GROUP_BackFill,SHINE_RASTER,
	    StartMember,
	      HGroupObject,
		HOffset(SizeX(8)),VOffset(SizeY(4)),
		ButtonFrame,
		FRM_Recessed,TRUE,
		StartMember,
		  PreviewStr = ExternalObject,
		    EXT_Class,TEXTFIELD_GetClass(),
		    EXT_NoRebuild,TRUE,
		    TEXTFIELD_BlockCursor,TRUE,
		    TEXTFIELD_Border,TEXTFIELD_BORDER_DOUBLEBEVEL,
		    TEXTFIELD_PassCommand,TRUE,
		    TEXTFIELD_NonPrintChars,TRUE,
		    TEXTFIELD_ClipStream,Clip,
		    TEXTFIELD_UndoStream,Undo,
		    GA_ID,ID_PREVIEWSTR,
		  EndObject,
		EndMember,
		StartMember,
		  PreviewScroll = VertScroller(NULL,0,0,0,ID_PREVIEWSCROLL),
		  FixMinWidth,
		EndMember,
	      EndObject,
	    EndMember,
	    StartMember,
	      HGroupObject,
		Spacing(SizeX(8)),
		EqualWidth,
		StartMember,
		  update = KeyButton(GetString(gadgUpdate),ID_UPDATE),
		EndMember,
		StartMember,
		  all = KeyButton(GetString(gadgShowAll),ID_ALL),
		EndMember,
        	StartMember,
		  clear = KeyButton(GetString(gadgClear),ID_CLEAR),
		EndMember,
        	StartMember,
		  cancel = KeyButton(GetString(gadgCancel),ID_CANCEL),
		EndMember,
	      EndObject,
	      FixMinHeight,
	    EndMember,
	  EndObject,
	EndObject;
      if (PreviewWndObj == NULL) ErrorCode(NEWWINDOW);
      SetLabelKey(PreviewWndObj,update,gadgUpdate);
      SetLabelKey(PreviewWndObj,all,gadgShowAll);
      SetLabelKey(PreviewWndObj,clear,gadgClear);
      SetLabelKey(PreviewWndObj,cancel,gadgCancel);
    }
    SetPreviewFont();
    if ((PreviewWnd = WindowOpen(PreviewWndObj)) == NULL)
      ErrorCode(OPENWINDOW);
    SetPreviewScroller();
    ActivateGadget((struct Gadget *)PreviewStr,PreviewWnd,NULL);
  }
}

void ClosePreviewWnd(BOOL all)
{
  ClrWindowClose(&PreviewWndObj,&PreviewWnd);
  if (all)
  {
    ClrDisposeObject(&PreviewWndObj);
    if (Clip) { CloseClipboard(Clip); Clip = NULL; }
    if (Undo) { CloseClipboard(Undo); Undo = NULL; }
    if (PreviewFont) { FreeVec(PreviewFont); PreviewFont = NULL; }
  }
}

void SetPreviewFont()
{
ULONG fchar, lchar;
UBYTE *oldfont;

  oldfont = PreviewFont;
  fchar = FirstChar;
  lchar = LastChar;
  FirstChar = 0;
  LastChar = 255;
  PreviewFont = SaveFont(TRUE,TRUE);
  FirstChar = fchar;
  LastChar = lchar;
  if (PreviewWnd)
  {
    SetGadgetAttrs((struct Gadget *)PreviewStr,PreviewWnd,NULL,
      TEXTFIELD_TextFont,PreviewFont ? tfh : NULL,TAG_DONE);
  }
  else
  {
    SetAttrs(PreviewStr,
      TEXTFIELD_TextFont,PreviewFont ? tfh : NULL,TAG_DONE);
  }
  if (oldfont) FreeVec(oldfont);
}

void PreviewMsgs(ULONG code)
{
ULONG top;

  switch (code)
  {
    case ID_CLEAR:
      SetGadgetAttrs((struct Gadget *)PreviewStr,PreviewWnd,NULL,
	TEXTFIELD_Text,"",TAG_DONE);
      ActivateGadget((struct Gadget *)PreviewStr,PreviewWnd,NULL);
      break;
    case ID_ALL:
      PreviewAll();
      break;
    case ID_UPDATE:
      SetPreviewFont();
      break;
    case ID_PREVIEWSCROLL:
      GetAttr(PGA_Top,PreviewScroll,&top);
      SetGadgetAttrs((struct Gadget *)PreviewStr,PreviewWnd,NULL,
	TEXTFIELD_Top,top,TAG_DONE);
      break;
    case ID_PREVIEWSTR:
      SetPreviewScroller();
      break;
    default:
      SharedMsgs(code,NULL);
      break;
  }
}

void SetPreviewScroller()
{
ULONG lines,visible,top;

  GetAttr(TEXTFIELD_Lines,PreviewStr,&lines);
  GetAttr(TEXTFIELD_Visible,PreviewStr,&visible);
  GetAttr(TEXTFIELD_Top,PreviewStr,&top);
  SetGadgetAttrs((struct Gadget *)PreviewScroll,PreviewWnd,NULL,
    PGA_Total,lines,
    PGA_Visible,visible,
    PGA_Top,top,TAG_DONE);
}

#define PREVIEW_WIDTH 32

void PreviewAll(void)
{
int i,j;
char listtext[((PREVIEW_WIDTH+1)*(256/PREVIEW_WIDTH))+1];

  for (i = 0; i < 256/PREVIEW_WIDTH; i++)
  {
    for (j = 0; j < PREVIEW_WIDTH; j++)
    {
      switch ((i*PREVIEW_WIDTH)+j)
      {
	case '\0':
	case '\n':
	case 0x0D:
	  listtext[(i*(PREVIEW_WIDTH+1))+j] = ' ';
	  break;
	default:
	  listtext[(i*(PREVIEW_WIDTH+1))+j] = (i*PREVIEW_WIDTH)+j;
	  break;
      }
    }
    listtext[(i*(PREVIEW_WIDTH+1))+PREVIEW_WIDTH] = '\n';
  }
  listtext[((PREVIEW_WIDTH+1)*(256/PREVIEW_WIDTH))] = '\0';
  SetGadgetAttrs((struct Gadget *)PreviewStr,PreviewWnd,NULL,
    TEXTFIELD_Text,listtext,TAG_DONE);
  ActivateGadget((struct Gadget *)PreviewStr,PreviewWnd,NULL);
}

UBYTE *SaveFont(BOOL tables,BOOL preview)
{
char fontpath[256], filename[256], datestr[LEN_DATSTRING];
ULONG filesize = 0, numchars, bitwidth = 0, i, offbit, hunkstart;
struct DateTime dt;
struct DiskFontHeader *dfh;
struct FontContentsHeader *fch;
ULONG *longptr, *relocstart;
UBYTE *buffer, *mptr, *fontdataptr;
struct charDef *fontlocptr;
WORD *fontkernptr;
BPTR fontfile, contfile, lock;

extern ULONG Proportional, Normal, Bold, Italic, ULine, Extended, Reversed;
extern ULONG Height, Width, Baseline, Smear, Aspect;
extern WORD SpaceTable[257], KernTable[257];
extern BOOL DataChanged;
extern char SavePath[256], FontName[256];

  strcpy(fontpath,SavePath);
  AddPart(fontpath,FontName,256);
  sprintf(filename,"%s/%ld",fontpath,Height);

  DateStamp(&(dt.dat_Stamp));
  dt.dat_Format = FORMAT_CDN;
  dt.dat_Flags = 0;
  dt.dat_StrDay = NULL;
  dt.dat_StrDate = datestr;
  dt.dat_StrTime = NULL;
  DateToStr(&dt);
  while ((mptr = strchr(datestr,'-')) != NULL) *mptr = '.';

  numchars = LastChar-FirstChar+2;
  filesize += 14*4;			/* Hunk structure */
  filesize += sizeof(struct DiskFontHeader);
  filesize += 4*4;			/* Relocatable addresses */
  for (i = FirstChar; i < LastChar+1; i++)
    bitwidth += (CharBuffer+i)->chr_Width;
  bitwidth += (CharBuffer+256)->chr_Width;
  if (bitwidth % 16 > 0) bitwidth = ((bitwidth/16)+1)*16;
  filesize += (bitwidth/8)*Height;	/* Character data */
  filesize += numchars*sizeof(struct charDef);
  if (tables)
  {
    filesize += numchars*4;		/* Space and kern tables */
    filesize += 2*4;			/* Table relocs */
  }
  if (filesize % 4 > 0) filesize = ((filesize/4)+1)*4;
  if ((buffer = AllocVec(filesize,MEMF_CLEAR)) != NULL)
  {
    longptr = (ULONG *)buffer;
    *longptr++ = 0x000003F3;		/* Hunk structure */
    *longptr++ = 0x00000000;
    *longptr++ = 0x00000001;
    *longptr++ = 0x00000000;
    *longptr++ = 0x00000000;
    *longptr++ = (filesize - ((tables ? 19 : 17)*4))/4;
    *longptr++ = 0x000003E9;		/* Hunk size (twice) */
    *longptr++ = (filesize - ((tables ? 19 : 17)*4))/4;
    if (preview)
      hunkstart = 0;
    else
      hunkstart = (ULONG)longptr;	/* All relocs relative to here */
    *longptr++ = 0x70FF4E75;		/* MOVEQ #-1,D0 RTS */
    relocstart = (ULONG *)(buffer+filesize-((9+(tables ? 2 : 0))*4));

    dfh = (struct DiskFontHeader *)longptr;
    dfh->dfh_DF.ln_Type = NT_FONT;
    dfh->dfh_DF.ln_Name = (UBYTE *)((ULONG)dfh->dfh_Name-hunkstart);
    dfh->dfh_FileID = DFH_ID;
    sprintf(dfh->dfh_Name,"$VER: %s%d 39.0 (%s)",FontName,Height,datestr);

    fontdataptr = ((UBYTE *)dfh)+sizeof(struct DiskFontHeader);
    fontlocptr = (struct CharDef *)(fontdataptr+((bitwidth/8)*Height));
    if ((ULONG)fontlocptr % 2 > 0)
      fontlocptr = (struct charDef *)((((ULONG)fontlocptr/2)+1)*2);
    fontkernptr = (WORD *)((UBYTE *)fontlocptr+
      numchars*sizeof(struct charDef));

    tfh = &(dfh->dfh_TF);
    tfh->tf_Message.mn_Node.ln_Type = NT_FONT;
    tfh->tf_Message.mn_Node.ln_Name = dfh->dfh_DF.ln_Name;
    tfh->tf_YSize = Height;
    if (Normal == FALSE)
    {
      if (Bold) tfh->tf_Style |= FSF_BOLD;
      if (Italic) tfh->tf_Style |= FSF_ITALIC;
      if (ULine) tfh->tf_Style |= FSF_UNDERLINED;
      if (Extended) tfh->tf_Style |= FSF_EXTENDED;
    }
    else tfh->tf_Style = FS_NORMAL;
    tfh->tf_Flags = FPF_DESIGNED|FPF_DISKFONT;
    if (Proportional) tfh->tf_Flags |= FPF_PROPORTIONAL;
    if (Reversed) tfh->tf_Flags |= FPF_REVPATH;
    switch (Aspect)
    {
      case 1:
	tfh->tf_Flags |= FPF_TALLDOT;
	break;
      case 2:
	tfh->tf_Flags |= FPF_WIDEDOT;
	break;
    }
    tfh->tf_XSize = Width;
    tfh->tf_Baseline = Baseline;
    tfh->tf_BoldSmear = Smear;
    tfh->tf_LoChar = FirstChar;
    tfh->tf_HiChar = LastChar;
    tfh->tf_CharData = (UBYTE *)((ULONG)fontdataptr-hunkstart);
    tfh->tf_Modulo = bitwidth/8;
    tfh->tf_CharLoc = (UBYTE *)((ULONG)fontlocptr-hunkstart);
    if (tables)
    {
      tfh->tf_CharSpace = (UBYTE *)((ULONG)fontkernptr-hunkstart);
      tfh->tf_CharKern =
	(UBYTE *)((ULONG)fontkernptr+(numchars*2)-hunkstart);
    }
    for (i = FirstChar, offbit = 0; i < LastChar+1; i++)
    {
      WriteCharData(fontlocptr,fontdataptr,i-FirstChar,i,&offbit,bitwidth/8);
      if (tables)
      {
	*(fontkernptr+(i-FirstChar)) = SpaceTable[i];
	*(fontkernptr+(i-FirstChar+numchars)) = KernTable[i];
      }
    }
    WriteCharData(fontlocptr,fontdataptr,numchars-1,256,&offbit,bitwidth/8);
    if (tables)
    {
      *(fontkernptr+(numchars-1)) = SpaceTable[256];
      *(fontkernptr+(numchars-1+numchars)) = KernTable[256];
    }

    *relocstart++ = 0x000003EC;		/* Reloc structure */
    *relocstart++ = 4 + (tables ? 2 : 0);
    *relocstart++ = 0x00000000;
    if (tables)
    {
      *relocstart++ = (ULONG)(&(tfh->tf_CharKern))-hunkstart;
      *relocstart++ = (ULONG)(&(tfh->tf_CharSpace))-hunkstart;
    }
    *relocstart++ = (ULONG)(&(tfh->tf_CharLoc))-hunkstart;
    *relocstart++ = (ULONG)(&(tfh->tf_CharData))-hunkstart;
    *relocstart++ = (ULONG)(&(tfh->tf_Message.mn_Node.ln_Name))-hunkstart;
    *relocstart++ = (ULONG)(&(dfh->dfh_DF.ln_Name))-hunkstart;
    *relocstart++ = 0x00000000;
    *relocstart++ = 0x000003F2;

    if (preview) return (buffer);

    WindowBusy(SaveWndObj);
    lock = Lock(fontpath,ACCESS_READ);
    WindowReady(SaveWndObj);
    if (lock == 0)
    {
      if (SaveShowReq(GetString(msgSaveNoDir),GetString(msgSaveNoDirGadgets),
	fontpath))
      {
        WindowBusy(SaveWndObj);
        lock = CreateDir(fontpath);
        WindowReady(SaveWndObj);
	if (lock == 0)
	{
	  SaveShowReq(GetString(msgSaveCreateError),GetString(msgCancel),
	    fontpath);
	  if (buffer) FreeVec(buffer);
	  return;
	}
	else UnLock(lock);
      }
      else
      {
	if (buffer) FreeVec(buffer);
	return;
      }
    }
    else UnLock(lock);

    WindowBusy(SaveWndObj);
    lock = Lock(filename,ACCESS_READ);
    WindowReady(SaveWndObj);
    if (lock)
    {
      UnLock(lock);
      if (!SaveShowReq(GetString(msgSaveWarnExists),
	GetString(msgSaveWarnExistsGadgets),filename))
      {
	if (buffer) FreeVec(buffer);
	return;
      }
    }

    WindowBusy(SaveWndObj);
    fontfile = Open(filename,MODE_NEWFILE);
    WindowReady(SaveWndObj);
    if (fontfile)
    {
      WindowBusy(SaveWndObj);
      Write(fontfile,buffer,filesize);
      Close(fontfile);
      DataChanged = FALSE;

      lock = Lock(SavePath,ACCESS_READ);
      WindowReady(SaveWndObj);
      if (lock != 0)
      {
	sprintf(filename,"%s.font",fontpath);
	WindowBusy(SaveWndObj);
	fch = NewFontContents(lock,FilePart(filename));
	WindowReady(SaveWndObj);
	if (fch != NULL)
	{
	  WindowBusy(SaveWndObj);
	  contfile = Open(filename,MODE_NEWFILE);
	  WindowReady(SaveWndObj);
	  if (contfile != 0)
	  {
	    WindowBusy(SaveWndObj);
	    Write(contfile,fch,sizeof(struct FontContentsHeader)+
	      (fch->fch_NumEntries*sizeof(struct FontContents)));
	    Close(contfile);
	    WindowReady(SaveWndObj);
	  }
	  else SaveShowReq(GetString(msgSaveWriteHeader),
	    GetString(msgCancel),filename);
	  DisposeFontContents(fch);
	}
	else ShowReq(GetString(msgSaveCreateHeader),GetString(msgCancel));
	UnLock(lock);
      }
    }
    else SaveShowReq(GetString(msgSaveWriteData),GetString(msgCancel),
      filename);
  }
  else SaveShowReq(GetString(msgSaveNoMemory),GetString(msgCancel));
  if (buffer) FreeVec(buffer);
  FlushAllFonts();
  return (NULL);
}

ULONG SaveShowReq(char *text,char *gadgets,...)
{
va_list va;
struct EasyStruct req =
  { sizeof(struct EasyStruct),0,NAME,NULL,NULL };
ULONG retcode;

  if (SaveWnd == NULL) return (0);
  WindowBusy(SaveWndObj);
  req.es_TextFormat = text;
  req.es_GadgetFormat = gadgets;
  va_start(va,gadgets);
  retcode = EasyRequestArgs(SaveWnd,&req,NULL,va);
  va_end(va);
  WindowReady(SaveWndObj);
  return (retcode);
}

void WriteCharData(struct charDef *cd, UBYTE *fontdataptr, ULONG dest,
  ULONG src, ULONG *off, ULONG mod)
{
struct Character *chr;
UBYTE *data;
ULONG i,j,width,widthi,modi,offset;

  chr = CharBuffer+src;
  data = (chr->chr_Data == NULL) ?
    (CharBuffer+256)->chr_Data : chr->chr_Data;
  width = chr->chr_Width;
  offset = *off;
  for (i = 0; i < chr->chr_Height; i++)
  {
    modi = mod*i;
    widthi = width*i;
    for (j = 0; j < width; j++)
    {
      if (*(data+widthi+j) == 1)
	*(fontdataptr+modi+((offset+j)>>3)) |= 128>>((offset+j)&7);
    }
  }
  (cd+dest)->charOffset = offset;
  (cd+dest)->charBitWidth = width;
  *off += width;
}

void OpenQueryWidthWnd(void)
{
Object *load, *info;
ULONG args[2];
extern char FontName[256];
extern ULONG Height;

  if (QueryWndObj == NULL)
  {
    QueryWndObj = WindowObject,
      WINDOW_Screen,Screen,
      WINDOW_SharedPort,WndMsgPort,
      WINDOW_Title,GetString(msgQueryWidthTitle),
      WINDOW_HelpFile,NAME".guide",
      WINDOW_HelpNode,"open",
      WINDOW_ScaleWidth,10,
      WINDOW_SmartRefresh,TRUE,
      WINDOW_SizeGadget,FALSE,
      WINDOW_CloseGadget,FALSE,
      WINDOW_RMBTrap,TRUE,
      WINDOW_MasterGroup,
	VGroupObject,
	  HOffset(SizeX(8)),VOffset(SizeY(4)),Spacing(SizeY(4)),
	  GROUP_BackFill,SHINE_RASTER,
	  StartMember,
	    VGroupObject,
	      HOffset(SizeX(8)),VOffset(SizeY(4)),Spacing(SizeY(2)),
	      ButtonFrame,
	      FRM_Recessed,TRUE,
	      StartMember,
		HGroupObject,
		  Spacing(SizeX(8)),
		  StartMember,
		    info = InfoObject,
		      ButtonFrame,
		      FRM_Flags,FRF_RECESSED,
		      Label(GetString(msgQueryFont)),
		      INFO_TextFormat,"%s/%ld",
		      INFO_Args,args,
		      INFO_MinLines,1,
		      INFO_HorizOffset,6,
		      INFO_VertOffset,3,
		      INFO_FixTextWidth,TRUE,
		    EndObject,
		  EndMember,
		  StartMember,
		    QueryWidthNum = StringObject,
		      RidgeFrame,
		      UScoreLabel(GetString(gadgQueryNewWidth),'_'),
		      STRINGA_LongVal,Width,
		      STRINGA_IntegerMin,0,
		      STRINGA_IntegerMax,65535,
		      STRINGA_MaxChars,5,
		      STRINGA_MinCharsVisible,4,
		      GA_ID,ID_QUERYWIDTHNUM,
		    EndObject,
		    Weight(40),
		  EndMember,
		EndObject,
	      EndMember,
	    EndObject,
	  EndMember,
	  StartMember,
	    load = KeyButton(GetString(gadgLoad),ID_ACCEPT),
	    FixMinHeight,
	  EndMember,
	EndObject,
      EndObject;
    if (QueryWndObj == NULL) ErrorCode(NEWWINDOW);
    SetLabelKey(QueryWndObj,QueryWidthNum,gadgQueryNewWidth);
    SetLabelKey(QueryWndObj,load,gadgLoad);
    SetAttrs(QueryWidthNum,STRINGA_BufferPos,1);
    if (Width > 10) SetAttrs(QueryWidthNum,STRINGA_BufferPos,2);
    if (Width > 100) SetAttrs(QueryWidthNum,STRINGA_BufferPos,3);
  }
  args[0] = (ULONG)FontName;
  args[1] = Height;
  if ((QueryWnd = WindowOpen(QueryWndObj)) == NULL) ErrorCode(OPENWINDOW);
  ActivateGadget((struct Gadget *)QueryWidthNum,QueryWnd,NULL);
}

void CloseQueryWidthWnd(void)
{
  ClrWindowClose(&QueryWndObj,&QueryWnd);
  ClrDisposeObject(&QueryWndObj);
}

BOOL LoadFont(struct TextAttr *font, ULONG width)
{
ULONG i;
char *endptr;
struct TTextAttr tagfont;
ULONG tags[3];

  strcpy(FontName,font->ta_Name);
  if (endptr = strstr(FontName,".font")) *endptr = 0;

  if (width > 0)
  {
    CopyMem(font,&tagfont,sizeof(struct TextAttr));
    tagfont.tta_Flags &= ~FPF_DESIGNED;
    tagfont.tta_Style |= FSF_TAGGED;
    tagfont.tta_Tags = (struct TagItem *)tags;
    tags[0] = TA_DeviceDPI;
    tags[1] = (width<<16)+tagfont.tta_YSize;
    tags[2] = TAG_DONE;
    NewFont = OpenDiskFont((struct TextAttr *)&tagfont);
  }
  else NewFont = OpenDiskFont(font);

  if (NewFont == NULL)
  {
    ShowReq(GetString(msgNoOpenFont),GetString(msgContinue),FontName,
      (ULONG)font->ta_YSize);
    return FALSE;
  }
  ClearCurrentFont();
  Height = NewFont->tf_YSize;
  Width = NewFont->tf_XSize;
  Baseline = NewFont->tf_Baseline;
  Smear = NewFont->tf_BoldSmear;
  FirstChar = NewFont->tf_LoChar;
  LastChar = NewFont->tf_HiChar;
  Proportional = ((NewFont->tf_Flags & FPF_PROPORTIONAL) != 0);
  Bold = ((NewFont->tf_Style & FSF_BOLD) != 0);
  Italic = ((NewFont->tf_Style & FSF_ITALIC) != 0);
  ULine = ((NewFont->tf_Style & FSF_UNDERLINED) != 0);
  Extended = ((NewFont->tf_Style & FSF_EXTENDED) != 0);
  Normal = ((Bold | Italic | ULine | Extended) == 0);
  Reversed = ((NewFont->tf_Flags & FPF_REVPATH) != 0);
  Aspect = 0;
  if (NewFont->tf_Flags & FPF_TALLDOT) Aspect = 1;
  if (NewFont->tf_Flags & FPF_WIDEDOT) Aspect = 2;

  for (i = 0; i < 257; i++)
  {
    (CharBuffer+i)->chr_Width = (((struct charDef *)(NewFont->tf_CharLoc))
      +LastChar-FirstChar+1)->charBitWidth;
    (CharBuffer+i)->chr_Height = NewFont->tf_YSize;
    SpaceTable[i] = NewFont->tf_XSize;
    KernTable[i] = 0;
    KernTables(i,LastChar-FirstChar+1);
  }
  for (i = 0; i < LastChar-FirstChar+1; i++)
  {
    if (!UnpackChar(CharBuffer+FirstChar+i,NewFont,i)) ErrorCode(ALLOCVEC);
    KernTables(FirstChar+i,i);
  }
  UnpackChar(CharBuffer+256,NewFont,LastChar-FirstChar+1);
  KernTables(256,LastChar-FirstChar+1);
  sprintf(WinTitle,"%s/%ld",FontName,(ULONG)font->ta_YSize);
  SetAttrs(FontWndObj,WINDOW_Title,WinTitle,TAG_DONE);
  CloseFont(NewFont); NewFont = NULL;
  DataChanged = FALSE;
  return TRUE;
}
