#include <stdarg.h>
#include <string.h>
#include <clib/alib_protos.h>
#include <clib/asl_protos.h>
#include <clib/bgui_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <exec/exec.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <intuition/icclass.h>
#include <intuition/intuitionbase.h>
#include <libraries/bgui_macros.h>

#define PROJECT_MENU \
  Title("Project"), \
    Item("Open Font...","O",ID_OPEN), \
    Item("Save Font...","S",ID_SAVE), \
    Item("Change Dir...","D",ID_CHANGEDIR), \
    ItemBar, \
    Item("Edit Font...","E",ID_EDITFONT), \
    ItemBar, \
    Item("Preferences...","P",ID_PREFS), \
    Item("About...","?",ID_ABOUT), \
    ItemBar, \
    Item("Quit","Q",ID_QUIT)
#define CHARACTER_MENU \
  Title("Character"), \
    Item("Copy","C",ID_COPY), \
    Item("Paste","V",ID_PASTE), \
    ItemBar, \
    Item("Move Left",NULL,ID_MOVEL), \
    Item("Move Right",NULL,ID_MOVER), \
    Item("Move Up",NULL,ID_MOVEU), \
    Item("Move Down",NULL,ID_MOVED), \
    ItemBar, \
    Item("Change Width...","W",ID_WIDTHC), \
    Item("Kerning...","K",ID_KERNING)

#define NAME "Typeface"
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))

struct Character
{
  UWORD chr_Width,chr_Height;
  UBYTE *chr_Data;
};

struct Preferences
{
  UWORD Version;
  ULONG Flags, ScrModeID, ScrDepth;
  ULONG VecHeight, PixelX, PixelY;
  ULONG SaveTo;
};

#define PREFS_CUSTOMSCREEN	(1<<0)
#define PREFS_PIXELBORDER	(1<<1)

/* typeface.c */

enum id { ID_OPEN = 1,
	  ID_SAVE,
	  ID_CHANGEDIR,
	  ID_EDITFONT,
	  ID_PREFS,
	  ID_ABOUT,
	  ID_QUIT,
	  ID_CHARS,
	  ID_CHARSCROLL,
	  ID_EDIT,
	  ID_WIDTHL,
	  ID_WIDTHR,
	  ID_WIDTHC,
	  ID_MOVEL,
	  ID_MOVER,
	  ID_MOVEU,
	  ID_MOVED,
	  ID_KERNING,
	  ID_COPY,
	  ID_PASTE,
	  ID_ACCEPT,
	  ID_CANCEL,
	  ID_PROP,
	  ID_HEIGHT,
	  ID_WIDTH,
	  ID_BASELINE,
	  ID_SMEAR,
	  ID_NORMAL,
	  ID_BOLD,
	  ID_ITALIC,
	  ID_ULINE,
	  ID_EXTEND,
	  ID_REVERSE,
	  ID_ASPECT,
	  ID_VECHEIGHT,
	  ID_PIXELWIDTH,
	  ID_PIXELHEIGHT,
	  ID_PIXELBORDER,
	  ID_ASSIGNSTR,
	  ID_ASSIGNPATH,
	  ID_ASSIGN,
	  ID_ASSIGNADD,
	  ID_CHARWIDTH,
	  ID_WIDTHPOS,
	  ID_SPACE,
	  ID_KERN,
	  ID_CUSTOM,
	  ID_CHOOSE,
	  ID_SAVETO,
	  ID_USE,
	  ID_FONTNAME,
	  ID_GETSAVEDIR,
	  ID_FIRST,
	  ID_LAST,
	  ID_KERNTABLE,
	  ID_SAVEDIR,
	  ID_BLANK };

enum scroll { GADG_HORIZ,
	      GADG_VERT,
	      GADG_LEFT,
	      GADG_RIGHT,
	      GADG_UP,
	      GADG_DOWN,
	      GADG_NONE };

#define GETBIT(buffer,offset) \
  ((((*((UBYTE *)(buffer)+((offset)>>3)))&(128>>((offset)&7))) != 0) \
  ? 1 : 0)

struct charDef
{
  WORD charOffset,charBitWidth;
};

void Setup(void);
void SetupScreen(void);
void Quit(void);
void QuitScreen(void);
void MsgLoop(void);
ULONG CheckObjMsg(struct Window *wnd, Object *obj);
void CheckOpenCharWin(ULONG pressed);
void SharedMsgs(ULONG code,struct CharNode *node);
void Error(char *message);
void ShowReq(char *text,char *gadgets,...);
void ClrDisposeObject(Object **obj);
void ClrWindowClose(Object **obj,struct Window **wnd);
void SleepWindows(void);
void WakeWindows(void);
void LoadFont(struct TextAttr *font);
BOOL UnpackChar(struct Character *chr,struct TextFont *font,ULONG i);
void KernTables(ULONG to, ULONG from);
void ClearCurrentFont(void);
void OpenEditFontWnd(void);
void CloseEditFontWnd(BOOL obj);
void OpenPrefsWnd(void);
void ClosePrefsWnd(BOOL obj);
void OpenAssignWnd(void);
void CloseAssignWnd(BOOL obj);
void OpenWidthWnd(struct CharNode *node);
void CloseWidthWnd(BOOL obj);
void OpenKernWnd(struct CharNode *node);
void CloseKernWnd(BOOL obj);
void OpenSaveWnd(void);
void CloseSaveWnd(BOOL obj);
void PutPositive(struct Window *wnd,char *name,LONG value,LONG min,
  LONG *dest);
void NewHeights(void);
void NewWidths(void);
void ChangeCharWidth(struct Character *chr, ULONG width, ULONG newoffset,
  ULONG oldoffset);
void CheckWidthKern(struct Character *chr);
void SavePrefs(char *filename);
void LoadPrefs(void);
void CopyChar(struct CharNode *node);
void PasteChar(struct CharNode *node);
void SaveFont(BOOL tables);
ULONG SaveShowReq(char *text,char *gadgets,...);
void WriteCharData(struct charDef *cd, UBYTE *fontdataptr, ULONG dest,
  ULONG src, ULONG *off, ULONG mod);
void FlushAllFonts(void);

/* char.c */

#define DATA(i,j) *(chr->chr_Data+((j)*chr->chr_Width)+(i))

struct CharNode
{
  struct Node chln_Node;
  Object *chln_Object;
  struct Window *chln_Window;
  char *chln_Title;
  Object *chln_HorizGadg, *chln_VertGadg;
  Object *chln_LeftGadg, *chln_RightGadg;
  Object *chln_UpGadg, *chln_DownGadg;
  struct Hook *chln_Hook;
  Object *chln_EditGadg;
  struct Character *chln_Character;
  ULONG chln_Number;
  Object *chln_WidthLObj, *chln_WidthRObj, *chln_KernObj;
};

struct CharNode *OpenCharWin(ULONG charnum,struct IBox size);
void CloseCharWin(struct CharNode *node);
Object *CreateSysImage(ULONG which,struct DrawInfo *dri);
Object *CreatePropGadg(ULONG freedom,Tag tag1,...);
Object *CreateButtonGadg(Object *image,Tag tag1,...);
__geta4 void CharHook(__a0 struct Hook *hook, __a2 Object *o,
  __a1 struct IntuiMessage *msg);
void ForceResizeChar(struct CharNode *node);
void SetScrollers(struct CharNode *node);
void RedrawEdit(struct CharNode *node);
void MoveLeft(struct CharNode *node);
void MoveRight(struct CharNode *node);
void MoveUp(struct CharNode *node);
void MoveDown(struct CharNode *node);

/* node.c */

struct List *GetNewList(struct List **list);
struct Node *CreateNode(ULONG size,struct List *list);
void RemoveList(struct List **list,BOOL all,(*hook)());

/* gadget.c */

#define CG_TAGBASE	(TAG_USER+1000)
#define CG_Pos		(CG_TAGBASE+0)
#define CG_Pressed	(CG_TAGBASE+1)

Class *InitCharGadgClass(void);
BOOL FreeCharGadgClass(Class *cl);
ULONG GetCharGadgWidth(void);
ULONG GetCharGadgHeight(void);

#define EG_XOFFSET 4
#define EG_YOFFSET 2

#define EG_TAGBASE	(TAG_USER+1000)
#define EG_PixelX	(EG_TAGBASE+1)
#define EG_PixelY	(EG_TAGBASE+2)
#define EG_CharStruct	(EG_TAGBASE+3)
#define EG_Update	(EG_TAGBASE+4)
#define EG_Width	(EG_TAGBASE+5)
#define EG_Height	(EG_TAGBASE+6)
#define EG_XOffset	(EG_TAGBASE+7)
#define EG_YOffset	(EG_TAGBASE+8)
#define EG_CharNode	(EG_TAGBASE+9)
#define EG_PixelBorder	(EG_TAGBASE+10)

Class *InitEditGadgClass(void);
BOOL FreeEditGadgClass(Class *cl);

#define SCRL_TAGBASE	(TAG_USER+1000)
#define SCRL_Right	(SCRL_TAGBASE+1)

Class *InitSlideGadgClass(void);
BOOL FreeSlideGadgClass(Class *cl);
