// fontevw.cpp : implementation of the CFonteditView class
//

#include "stdafx.h"
#include "globals.h"
#include "fontedit.h"

#include "fontedoc.h"
#include "fontevw.h"
#include "acwidths.h"
#include "deltaspace.h"
#include "fontproperties.h"
#include "font.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFonteditView

IMPLEMENT_DYNCREATE(CFonteditView, CView)

BEGIN_MESSAGE_MAP(CFonteditView, CView)
	//{{AFX_MSG_MAP(CFonteditView)
	ON_COMMAND(ID_IMAGE_NEXT, OnImageNext)
	ON_COMMAND(ID_IMAGE_PREV, OnImagePrev)
	ON_COMMAND(ID_IMAGE_ZOOMIN, OnImageZoomin)
	ON_COMMAND(ID_IMAGE_ZOOMOUT, OnImageZoomout)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_IMAGE_UNDO, OnImageUndo)
	ON_WM_CHAR()
	ON_COMMAND(ID_OPTIONS_CLUBS, OnOptionsClubs)
	ON_COMMAND(ID_OPTIONS_ENGLISH, OnOptionsEnglish)
	ON_COMMAND(ID_OPTIONS_FOREIGN, OnOptionsForeign)
	ON_COMMAND(ID_IMAGE_CHANGEACWIDTHS, OnImageChangeacwidths)
	ON_COMMAND(ID_OPTIONS_MAC, OnOptionsMac)
	ON_COMMAND(ID_OPTIONS_ALL, OnOptionsAll)
	ON_COMMAND(IDM_GLOBALCHANGEAANDC, OnGlobalchangeaandc)
	ON_COMMAND(IDM_VIEW_PROPERTIES, OnViewProperties)
	ON_COMMAND(ID_OPTIONS_ALPHABETICCHARACTERSONLY, OnOptionsAlphabeticcharactersonly)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

#define MAPHEIGHT 25
#define EDIT_OFFSET_X 0
#define EDIT_OFFSET_Y 35
#define GAP 10
#define SWIDTH 32

/////////////////////////////////////////////////////////////////////////////
// CFonteditView construction/destruction

CFonteditView::CFonteditView()
{
	int n,m;
	view = this;
	nZoom = 5;
	bCurChar = 65;
	CurColor = 128;
	bDownInColor = 0;
	bDownInDraw = 0;
	pWorkspace=0;
	nWorkspaceSize = 0;
	nWorkspaceWidth = 0;
	nWorkspaceHeight = 0;
	lp = (LOGPALETTE *)malloc(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY)*256));
	lp->palVersion = 0x300;
	lp->palNumEntries = 256;
	for (n=0; n<256; n++)
	{
		lp->palPalEntry[n].peRed = (BYTE)n;
		lp->palPalEntry[n].peGreen = (BYTE)n;
		lp->palPalEntry[n].peBlue = (BYTE)n;
		lp->palPalEntry[n].peFlags = 0;
	}
	hPal = CreatePalette(lp);
	bmi.bmiH.biSize = sizeof(bmi.bmiH);
	bmi.bmiH.biPlanes = 1;
	bmi.bmiH.biBitCount = 8;
	bmi.bmiH.biCompression = BI_RGB;
	bmi.bmiH.biSizeImage = 0;
	bmi.bmiH.biClrUsed = 0;
	bmi.bmiH.biClrImportant = 0;
	for (n=0; n<256; n++)
	{
		bmi.colors.bmiC[n] = (WORD)n;
	}
	pScale = (BYTE *)malloc(MAPHEIGHT * 512);
	pCurColor = (BYTE *)malloc(SWIDTH * SWIDTH);
	memset(pCurColor,CurColor,SWIDTH*SWIDTH);
	DWORD b;
	for (n=0; n<256; n++)
	{
		b = n;
		if (b>255)
			b=255;
		for (m=0; m<MAPHEIGHT; m++)
		{
			pScale[m*512 + n*2] = (BYTE)b;
			pScale[m*512 + n*2 + 1] = (BYTE)b;
		}
	}
}

CFonteditView::~CFonteditView()
{
	free(lp);
	DeleteObject(hPal);
	if (pWorkspace)
		free(pWorkspace);
}

/////////////////////////////////////////////////////////////////////////////
// CFonteditView drawing


void CFonteditView::OnDraw(CDC* pDC)
{
	int nMainWidth;
	int nMainHeight;
	int nHeight;
	int nWidth;
	char szOut[256];

	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	if (!theFont)
		return;
	HPALETTE hOldPal = ::SelectPalette(pDC->m_hDC,hPal,FALSE);
	RealizePalette(pDC->m_hDC);

	// draw the grayscale gradient map of values to pick from
	bmi.bmiH.biHeight = MAPHEIGHT;
	bmi.bmiH.biWidth = 512;
	HBRUSH hRedBrush= ::CreateSolidBrush(0x0000FF);
	HBRUSH hOldBrush = (HBRUSH)::SelectObject(pDC->m_hDC,hRedBrush);
	::PatBlt(pDC->m_hDC,0,0,518,MAPHEIGHT + 6,PATCOPY);
	SetDIBitsToDevice(pDC->m_hDC,
										3,
										3,
										512,
										MAPHEIGHT,
										0,0,
										0,	
										MAPHEIGHT,
										pScale,
										(BITMAPINFO *)&bmi,
										DIB_PAL_COLORS);

	nWidth = nWorkspaceWidth;
	nHeight = nWorkspaceHeight;
	nMainWidth = theFont->GetCharWidth(bCurChar) * nZoom;
	nMainHeight = theFont->GetCharHeight(bCurChar) * nZoom;
	bmi.bmiH.biWidth = nWidth;
	bmi.bmiH.biHeight = nHeight;

	rCurChar.left = EDIT_OFFSET_X;
	rCurChar.top = EDIT_OFFSET_Y;
	rCurChar.right = rCurChar.left + theFont->GetCharWidth(bCurChar) * nZoom;
	rCurChar.bottom = rCurChar.top + theFont->GetCharHeight(bCurChar) * nZoom;
	if (!pWorkspace)
		GetCurImage();
	StretchDIBits(pDC->m_hDC,EDIT_OFFSET_X,EDIT_OFFSET_Y,
							theFont->GetCharWidth(bCurChar) * nZoom,
							theFont->GetCharHeight(bCurChar) * nZoom,
							0,0,
							theFont->GetCharWidth(bCurChar),
							theFont->GetCharHeight(bCurChar),
							pWorkspace,
							(BITMAPINFO *)&bmi,
							DIB_PAL_COLORS,
							SRCCOPY);
	
	rCurSmallChar.left = EDIT_OFFSET_X + nMainWidth + GAP;
	rCurSmallChar.top = EDIT_OFFSET_Y;
	rCurSmallChar.right = rCurSmallChar.left + theFont->GetCharWidth(bCurChar);
	rCurSmallChar.bottom = rCurSmallChar.top + theFont->GetCharHeight(bCurChar);

	SetDIBitsToDevice(pDC->m_hDC,
										EDIT_OFFSET_X + nMainWidth + GAP,
										EDIT_OFFSET_Y,
										theFont->GetCharWidth(bCurChar),
										theFont->GetCharHeight(bCurChar),
										0,0,
										0,	
										theFont->GetCharHeight(bCurChar),
										pWorkspace,
										(BITMAPINFO *)&bmi,
										DIB_PAL_COLORS);

	bmi.bmiH.biWidth = bmi.bmiH.biHeight = SWIDTH;

	rCurColor.top = EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) + GAP;
	rCurColor.left = EDIT_OFFSET_X + nMainWidth + GAP;
	rCurColor.right = rCurColor.left + SWIDTH + SWIDTH + SWIDTH;
	rCurColor.bottom = rCurColor.top + SWIDTH;
	::PatBlt(pDC->m_hDC,rCurColor.left - 3,rCurColor.top  - 3
												,SWIDTH+6,SWIDTH+6,PATCOPY);

	SetDIBitsToDevice(pDC->m_hDC,
										EDIT_OFFSET_X + nMainWidth + GAP,
										EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) + GAP,
										SWIDTH,
										SWIDTH,
										0,0,
										0,	
										SWIDTH,
										pCurColor,
										(BITMAPINFO *)&bmi,
										DIB_PAL_COLORS);
	wsprintf(szOut,"%d    ",((int)CurColor)>>ALIAS_SHIFT);
	pDC->TextOut(
					EDIT_OFFSET_X + nMainWidth + GAP + SWIDTH + GAP,
					EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) + GAP,
					szOut,lstrlen(szOut));
	wsprintf(szOut,"%c:%d           ",bCurChar,(int)bCurChar);
	pDC->TextOut(0,EDIT_OFFSET_Y + nMainHeight + GAP,szOut,lstrlen(szOut));
	::SelectPalette(pDC->m_hDC,hOldPal,FALSE);
	::SelectObject(pDC->m_hDC,hOldBrush);
	::DeleteObject(hRedBrush);

	int iTextureY = EDIT_OFFSET_Y + nMainHeight + GAP + 50;
	int iTextureCount = theFont->GetTextureCount();
	for (int i=0; i<iTextureCount; i++)
	{
		theFont->DrawTexture(pDC->m_hDC,i,i*260,iTextureY);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CFonteditView diagnostics

#ifdef _DEBUG
void CFonteditView::AssertValid() const
{
	CView::AssertValid();
}

void CFonteditView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CFonteditDoc* CFonteditView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFonteditDoc)));
	return (CFonteditDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFonteditView message handlers
void CFonteditView::NewFont(void)
{
	GetCurImage();	
}

void CFonteditView::UpdateFont(void)
{
	SetCurImage();
}

void CFonteditView::OnImageNext() 
{
	if (!theFont)
		return;
	SetCurImage();
	bCurChar++;
	GetCurImage();
	InvalidateRect(NULL,TRUE);	
}

void CFonteditView::OnImagePrev() 
{
	if (!theFont)
		return;
	SetCurImage();
	bCurChar--;	
	GetCurImage();
	InvalidateRect(NULL,TRUE);	
}

void CFonteditView::OnImageZoomin() 
{
	if (!theFont)
		return;
	if (nZoom <24)
		nZoom++;
	InvalidateRect(NULL,TRUE);	
}

void CFonteditView::OnImageZoomout() 
{
	if (!theFont)
		return;
	if (nZoom > 1)
		nZoom --;
	InvalidateRect(NULL,TRUE);		
}

void CFonteditView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (bDownInColor && point.y > 3 && point.y <= 3 + MAPHEIGHT &&
			point.x > 3 && point.x <= 515)
	{
		CurColor = (BYTE)((point.x - 3)/2);
		memset(pCurColor,CurColor,SWIDTH * SWIDTH);
		InvalidateRect(&rCurColor,FALSE);
	}
	if (bDownInDraw && point.y > EDIT_OFFSET_Y && 
			point.y < EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) * nZoom &&
			point.x > EDIT_OFFSET_X &&
			point.x < EDIT_OFFSET_X + theFont->GetCharWidth(bCurChar) * nZoom)
	{ // we're drawing on the bmp
		bDownInDraw = 1;
		point.y -= EDIT_OFFSET_Y;
		point.x -= EDIT_OFFSET_X;
		int x = point.x/nZoom;
		int y = point.y/nZoom;
		pWorkspace[(nWorkspaceHeight-1-y) * nWorkspaceWidth + x] = CurColor;
		InvalidateRect(&rCurChar,FALSE);
		InvalidateRect(&rCurSmallChar,FALSE);
		return;
	}
}

void CFonteditView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (!theFont)
		return;
	GetCapture();
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	if (point.y > 3 && point.y <= 3 + MAPHEIGHT &&
			point.x > 3 && point.x <= 515)
	{
		CurColor = (BYTE)((point.x - 3));
		memset(pCurColor,CurColor,SWIDTH * SWIDTH);
		InvalidateRect(&rCurColor,FALSE);
		bDownInColor = TRUE;
		return;
	}
	if (point.y > EDIT_OFFSET_Y && 
			point.y < EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) * nZoom &&
			point.x > EDIT_OFFSET_X &&
			point.x < EDIT_OFFSET_X + theFont->GetCharWidth(bCurChar) * nZoom)
	{ // we're drawing on the bmp
		bDownInDraw = 1;
		point.y -= EDIT_OFFSET_Y;
		point.x -= EDIT_OFFSET_X;
		int x = point.x/nZoom;
		int y = point.y/nZoom;
		pWorkspace[(nWorkspaceHeight-1-y) * nWorkspaceWidth + x] = CurColor;
		InvalidateRect(&rCurChar,FALSE);
		InvalidateRect(&rCurSmallChar,FALSE);
		pDoc->SetModifiedFlag(TRUE);
		return;
	}
}

void CFonteditView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	ReleaseCapture();
	bDownInColor = FALSE;
	bDownInDraw = FALSE;

}

void CFonteditView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (point.y > EDIT_OFFSET_Y && 
			point.y < EDIT_OFFSET_Y + theFont->GetCharHeight(bCurChar) * nZoom &&
			point.x > EDIT_OFFSET_X &&
			point.x < EDIT_OFFSET_X + theFont->GetCharWidth(bCurChar) * nZoom)
	{ // we're drawing on the bmp
		point.y -= EDIT_OFFSET_Y;
		point.x -= EDIT_OFFSET_X;
		int x = point.x/nZoom;
		int y = point.y/nZoom;
		CurColor = pWorkspace[(nWorkspaceHeight-1-y) * nWorkspaceWidth + x];
		memset(pCurColor,CurColor,SWIDTH * SWIDTH);
		InvalidateRect(&rCurColor,FALSE);
		return;
	}
}

void CFonteditView::GetCurImage(void)
{
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	int nHeight = theFont->GetCharHeight(bCurChar);
	int nWidth = theFont->GetCharWidth(bCurChar);
	int nInternalWidth = nWidth;
	if (nInternalWidth & 0x3)
		nInternalWidth += 4 - (nInternalWidth&0x03);
	if (!pWorkspace || nWorkspaceSize < nInternalWidth * nHeight)
	{
		if (pWorkspace)
		{
			free(pWorkspace);
		}
		nWorkspaceSize = nInternalWidth * nHeight;
		pWorkspace = (BYTE *)malloc(nWorkspaceSize);
	}
	memset(pWorkspace,0,nWorkspaceSize);
	nWorkspaceWidth = nInternalWidth;
	nWorkspaceHeight = nHeight;
	BYTE *pSource = theFont->GetCharMap(bCurChar);
	for (int n=0; n<nHeight; n++)
	{ // flip the image to display DIB
		memcpy(pWorkspace + (nHeight-1-n)*nInternalWidth,pSource + (n*nWidth),nWidth);
	}
	delete pSource;
}

void CFonteditView::SetCurImage(void)
{
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	int nHeight = theFont->GetCharHeight(bCurChar);
	int nWidth = theFont->GetCharWidth(bCurChar);
	if (!pWorkspace)
		return;
	BYTE *pDest = new BYTE[nHeight * nWidth];
	for (int n=0; n<nHeight; n++)
	{ // flip the image to set back to font
		memcpy(pDest + (n*nWidth),pWorkspace + (nHeight-1-n)*nWorkspaceWidth,nWidth);
	}
	theFont->SetCharMap(bCurChar,pDest);
	delete pDest;
}

void CFonteditView::OnImageUndo() 
{
	if (!theFont)
		return;
	GetCurImage();
	InvalidateRect(&rCurChar,FALSE);
	InvalidateRect(&rCurSmallChar,FALSE);
}

void CFonteditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	CView::OnChar(nChar, nRepCnt, nFlags);
	SetCurImage();
	bCurChar = nChar;
	GetCurImage();
	InvalidateRect(NULL,TRUE);	
}


void CFonteditView::OnOptionsClubs() 
{
	nLanguage = 1;
	HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
	HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);

	CheckMenuItem(hOptionsMenu,ID_OPTIONS_CLUBS,MF_BYCOMMAND|MF_CHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ENGLISH,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_FOREIGN,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_MAC,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALL,MF_BYCOMMAND|MF_UNCHECKED);
	
}

void CFonteditView::OnOptionsEnglish() 
{
	nLanguage = 0;
	HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
	HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_CLUBS,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ENGLISH,MF_BYCOMMAND|MF_CHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_FOREIGN,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_MAC,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALL,MF_BYCOMMAND|MF_UNCHECKED);
	
}

void CFonteditView::OnOptionsForeign() 
{
	nLanguage = 2;
	HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
	HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_CLUBS,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ENGLISH,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_FOREIGN,MF_BYCOMMAND|MF_CHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_MAC,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALL,MF_BYCOMMAND|MF_UNCHECKED);
	
}

void CFonteditView::OnImageChangeacwidths() 
{
	if (!theFont)
		return;
	ACWidths dlg;	
	CFonteditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	dlg.nAWidth = theFont->GetCharAWidth(bCurChar);
	dlg.nCWidth = theFont->GetCharCWidth(bCurChar);

	if (dlg.DoModal() != IDOK)
		return;

	theFont->SetCharAWidth(bCurChar,dlg.nAWidth);
	theFont->SetCharCWidth(bCurChar,dlg.nCWidth);
	
}

void CFonteditView::OnOptionsMac() 
{
	nLanguage = 3;
	HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
	HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_CLUBS,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ENGLISH,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_FOREIGN,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_MAC,MF_BYCOMMAND|MF_CHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALL,MF_BYCOMMAND|MF_UNCHECKED);
	
	
}

void CFonteditView::OnOptionsAll() 
{
	nLanguage = 4;
	HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
	HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_CLUBS,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ENGLISH,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_FOREIGN,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_MAC,MF_BYCOMMAND|MF_UNCHECKED);
	CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALL,MF_BYCOMMAND|MF_CHECKED);
	
}

void CFonteditView::OnGlobalchangeaandc() 
{
	if (!theFont)
		return;
	CDeltaSpace dlg;
	if (dlg.DoModal()!= IDOK)
		return;

	CFonteditDoc* pDoc = GetDocument();
	for (int n=0; n<256; n++)
	{
		int a = theFont->GetCharAWidth(n);
		int c = theFont->GetCharCWidth(n);

		
		theFont->SetCharAWidth(n,a + dlg.m_DeltaA);
		theFont->SetCharCWidth(n,c + dlg.m_DeltaC);

	}
	
}


void CFonteditView::OnViewProperties() 
{
	FontProperties	dlg;

	if (!theFont)
		return;
	
	dlg.DoModal();

}


void CFonteditView::OnOptionsAlphabeticcharactersonly() 
{
	if (nLanguage == 100)
	{
		nLanguage = 0;
		HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
		HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
		CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALPHABETICCHARACTERSONLY,MF_BYCOMMAND|MF_UNCHECKED);
	}
	else
	{
		nLanguage = 100;
		HMENU hMainMenu = ::GetMenu(AfxGetMainWnd()->m_hWnd);
		HMENU hOptionsMenu = ::GetSubMenu(hMainMenu,3);
		CheckMenuItem(hOptionsMenu,ID_OPTIONS_ALPHABETICCHARACTERSONLY,MF_BYCOMMAND|MF_CHECKED);
	}
}

