//---------------------------------------------------------------------------

#include <vcl.h>
#include <math.h>
#pragma hdrstop
                 
#include "picedit.h"
#include "explorer.h"
#include "main.h"
#include "colourselect.h"
#include "piccommand.h"
#include "wait.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "MenuBar"
#pragma resource "*.dfm"
TWndPicEdit *WndPicEdit; 
//---------------------------------------------------------------------------
typedef struct {
	int index;
    char *name;
} tsCSRRES;
tsCSRRES picCsrRes[] = {
	{-1,				NULL},
	{PTOOL_LINE,		"LINECURSOR"},
	{PTOOL_SHORTLINE,	"LINECURSOR"},
	{PTOOL_TINYLINE,	"LINECURSOR"},
	{PTOOL_ABSPEN,		"PENCURSOR"},
	{PTOOL_NEARPEN,	 	"PENCURSOR"},
	{PTOOL_CLSPEN,	 	"PENCURSOR"},
	{PTOOL_FILL,		"FILLCURSOR"},
	{PTOOL_ZOOM,		"ZOOMCURSOR"}
};
PAINTSTRUCT ps = {
	NULL,
	FALSE,
	NULL
};
int priPoints[14] = {42, 53, 64, 74, 85, 96, 106, 117, 127, 138, 149, 159, 170, 180};
AnsiString picCmdNames[] = {
	"Visual Set",
	"Visual Off",
	"Priority Set",
	"Priority Off",
	"Short Pen",
	"Short Line",
	"Line",
	"Tiny Line",
    "Fill",
    "Change Pattern",
    "Abs Pen",
	"Control Set",
	"Control Off",
    "Short Pen",
    "Change Palette",
    "End of Pic"
};

U8 defPic[] = {0xFF};

U8 onCodes[3]  = {0xF0,0xF2,0xFB};
U8 offCodes[3] = {0xF1,0xF3,0xFC};

#define GETPIX(x,y,s)\
	pic->bitmaps[s][(sPIC_MAXY-y)*sPIC_WIDTH+x]
//---------------------------------------------------------------------------
__fastcall TWndPicEdit::TWndPicEdit(TComponent* Owner)
	: TForm(Owner)
{
	pic = NULL;
    PicBitmapBits = NULL;
}
//---------------------------------------------------------------------------
void piEditorClose(EDITORTAG *edtTag)
{
}
//---------------------------------------------------------------------------
void piSaveRes(EDITORTAG *edtTag)
{
	//((TWndTextEdit*)edtTag->Form)->Save1Click(edtTag->Form);
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::InitEditor(EDTWND *_edtWnd, U8 *resBuf)
{
    edTag.EditorClose = piEditorClose;
    edTag.SaveRes = piSaveRes;
    edTag.edtWnd = _edtWnd;
    edTag.DefCaption = Caption;
    edTag.Form = this;
	Tag = (int)&edTag;

    PICBMP=FALSE;

	pal = &palEGAU;


   binfo = (BITMAPINFO *)malloc( sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD));

   binfoh.biSize          = sizeof(BITMAPINFOHEADER);
   binfoh.biWidth         = 320;
   binfoh.biHeight        = 190;
   binfoh.biPlanes        = 1;
   binfoh.biBitCount      = 8;
   binfoh.biCompression   = BI_RGB;
   binfoh.biSizeImage     = 0;
   binfoh.biXPelsPerMeter = 0;
   binfoh.biYPelsPerMeter = 0;
   binfoh.biClrUsed       = 0;
   binfoh.biClrImportant  = 0;

   binfo->bmiHeader = binfoh;

   memcpy(binfo->bmiColors,pal->lPal->palPalEntry, 256*sizeof(RGBQUAD));

   HDC ahDC = GetDC( Handle );
   PicBitmap = CreateDIBitmap(
      ahDC,
      &binfo->bmiHeader,
      CBM_INIT,
      PicBitmapBits,
      binfo,
      DIB_RGB_COLORS
   );

   ReleaseDC( Handle, ahDC );

   bmih.biSize          = sizeof(BITMAPINFOHEADER);
   bmih.biWidth         = 320;
   bmih.biHeight        = 190;
   bmih.biPlanes        = 1;
   bmih.biBitCount      = 32;
   bmih.biCompression   = BI_RGB;
   bmih.biSizeImage     = 0;
   bmih.biXPelsPerMeter = 0;
   bmih.biYPelsPerMeter = 0;
   bmih.biClrUsed       = 0;
   bmih.biClrImportant  = 0;

   binfo->bmiHeader = bmih;

   ahDC = GetDC( Handle );
   BackBitmap = CreateDIBitmap(
      ahDC,
      &bmih,
      CBM_INIT,
      BackBitmapBits,
      binfo,
      DIB_RGB_COLORS
   );

   ReleaseDC( Handle, ahDC );


    BACK_LOADED = FALSE;
	PIC_8BIT = TRUE;

    activeScreen = asVISUAL;
    activePalette = 0;

    drawingCursor = winNum+10; // unique tag

    ZoomClick(NormalViewing1);

    tbCurTool = NULL;
    ToolClick(sbOff);

    if(!WndExplorer)
    	SaveToGame1->Visible = FALSE;
    if(edTag.edtWnd->resInfo&&resBuf) {
		LoadPic(resBuf, edTag.edtWnd->resInfo->size);
		UPDATE_CAPTION();
    } else {  
    	NewPic();
    }   

    PICBMP=TRUE;
    UpdatePic();


	switch(activePalette) {
     	case 0:
    		PaletteClick(tbPal0);
        	break;
     	case 1:
    		PaletteClick(tbPal1);
        	break;
     	case 2:
    		PaletteClick(tbPal2);
        	break;
     	case 3:
    		PaletteClick(tbPal3);
        	break;
    }

    drawingTool = -1;

	return TRUE;
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::SavePic()
{
	U8 *buf;
    U16 len;

    if((!CHECK_EXPLORERED())&&(edTag.edtWnd->fileName[0]=='\0')) {
        SaveAs1Click(this);
        return TRUE;
    }

    buf = pic->data;
    len = pic->length;

    if(CHECK_EXPLORERED()) {
        RESINFO *newRI = edTag.edtWnd->resInfo = WndExplorer->SaveResToGame(buf, len, rsPIC, 0);
     	if(!newRI) {
    		return FALSE;
        } else edTag.edtWnd->resInfo = newRI;
    } else {
        FILE *fFile;
        if((fFile=ssOpenFile(ssFIO_ROOT|ssFIO_MESSAGE,edTag.edtWnd->fileName,"wb"))==NULL)
            return FALSE;
        ssFPutW((0x80|rsPIC),fFile);
        ssFWrite(buf,len,fFile);
        ssCloseFile(fFile);
    }

    CLEAR_RESCHANGED();
    UPDATE_CAPTION();

    return TRUE;
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::LoadPic(U8 *buf, U16 len)
{
	U8 *newB;
    sciPIC   *p;
	if(buf==NULL||len==0) {
		OpenDialog->Filter = resTypes[rsPIC].filter;
    	if(!OpenDialog->Execute()) FALSE;
   		if((newB=ssLoadFile(ssFIO_ROOT|ssFIO_MESSAGE, OpenDialog->FileName.c_str(), &len))==NULL)
    		return FALSE;
    	if(CheckSCIFileHeader(newB)!=rsPIC) {
			ssMessage(ssERROR,"The file your are trying to open, %s, is not a valid SCI %s resource, or does not contain a valid header",OpenDialog->FileName.c_str(),resTypes[rsPIC].name);
        	ssFree(newB);
        	return FALSE;
    	}             
    	strcpy(edTag.edtWnd->fileName,OpenDialog->FileName.c_str());
    	buf = newB+2;
        len-=2;
    }

	ClosePic();

	if((p = PicLoad(buf,len,plEDITOR,activePalette))==NULL) return FALSE;
    pic = p;

    ssFree(buf);

	UpdatePic();

    return TRUE;
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::UpdatePic()
{
	if(!pic) return FALSE;

    oldPicLen = -1;   

    UpdateDataEdit();

	switch(activeScreen) {
     	case asVISUAL:
    		ScreenClick(tbVisual);
        	break;
     	case asPRIORITY:
    		ScreenClick(tbPriority);
        	break;
     	case asCONTROL:
    		ScreenClick(tbControl);
        	break;
    }
	switch(activePalette) {
     	case 0:
    		PaletteClick(tbPal0);
        	break;
     	case 1:
    		PaletteClick(tbPal1);
        	break;
     	case 2:
    		PaletteClick(tbPal2);
        	break;
     	case 3:
    		PaletteClick(tbPal3);
        	break;
    }

    for(int i=0;i<3;i++)
		DrawColour(i);

    sbSquare->Down  =  (pic->patCode&PATTERN_FLAG_RECTANGLE  );
    sbCircle->Down  = !(pic->patCode&PATTERN_FLAG_RECTANGLE  );
    sbPattern->Down =  (pic->patCode&PATTERN_FLAG_USE_PATTERN);
    sbSolid->Down   = !(pic->patCode&PATTERN_FLAG_USE_PATTERN);

    PenSizeE->Caption = IntToStr(pic->patCode&7);
    UpDown1->Position = (pic->patCode&7);

    DrawActiveScreen(TRUE);

    return TRUE;
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::ClosePic()
{
    return TRUE;
}
//---------------------------------------------------------------------------
BOOL TWndPicEdit::NewPic()
{
	if((pic = PicLoad(defPic,sizeof(defPic),plEDITOR,activePalette))==NULL) return FALSE;

	UpdatePic();
	
    return TRUE;
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::New1Click(TObject *Sender)
{
	NewPic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::Open1Click(TObject *Sender)
{
	LoadPic(NULL,0);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::Save1Click(TObject *Sender)
{
	SavePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SaveAs1Click(TObject *Sender)
{
	if(edTag.edtWnd->fileName[0])
    	SaveDialog->FileName=AnsiString(edTag.edtWnd->fileName);
    else if(CHECK_EXPLORERED()&&edTag.edtWnd->resInfo)
    	SaveDialog->FileName = AnsiStringFmtRes(edTag.edtWnd->resInfo->type,edTag.edtWnd->resInfo->number);
	SaveDialog->Filter=resTypes[rsPIC].filter;
	if(SaveDialog->Execute()) {
    	CLEAR_EXPLORERED();
        strcpy(edTag.edtWnd->fileName,SaveDialog->FileName.c_str());
    	Save1Click(Sender);
    }
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SaveToGame1Click(TObject *Sender)
{
	SET_EXPLORERED();
    Save1Click(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::Close1Click(TObject *Sender)
{
	Close();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::CommandHistory1Click(TObject *Sender)
{
///
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::Copy1Click(TObject *Sender)
{
//	
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::PasteTracingImage1Click(TObject *Sender)
{
//	
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::AssignBack(Graphics::TBitmap *TempBit)
{
	long c;
    int w =  TempBit->Width, h = TempBit->Height;
    Graphics::TBitmap *newBit=new Graphics::TBitmap;
	newBit->Width  = sPIC_WIDTH;
	newBit->Height = sPIC_HEIGHT;
    if((w!=sPIC_WIDTH||h!=sPIC_HEIGHT)
    	&& Application->MessageBox(
        	"The bitmap's dimensions do not match the picture's (320x200). Would it to be scaled?",
            "Scale The Picture?",
            MB_YESNO)==IDYES) {
                newBit->Canvas->StretchDraw(
                	Rect(0,0,sPIC_WIDTH,sPIC_HEIGHT),
                    TempBit
                );
            	w = sPIC_WIDTH;
            	h = sPIC_HEIGHT;
    } else newBit->Canvas->Draw(
                	0,0,
                    TempBit
                );

    DlgWait = new TDlgWait(this);
    DlgWait->ProgressBar->Max = sPIC_HEIGHT;
    DlgWait->ProgressBar->Position = 0;
    DlgWait->Show();
    if(w>sPIC_WIDTH) w = sPIC_WIDTH;
    if(h>sPIC_HEIGHT) h = sPIC_HEIGHT;
    long *foo=(long*)BackBitmapBits;
    for(int y=0;y<h;y++) {
        for(int x=0;x<w;x++) {
        	c = (long)newBit->Canvas->Pixels[x][y];
            foo[((189-y)*sPIC_WIDTH)+x] =
                ((c>>16)&0xFF)|((c<<16)&0xFF0000)|(c&0xFF00);
        }  
        DlgWait->ProgressBar->Position++;
    }
	delete newBit;
    delete DlgWait;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::LoadTracingImage1Click(TObject *Sender)
{
    if(!BGOpenDialog->Execute()) return;
    Graphics::TBitmap *BGBitmap = new Graphics::TBitmap;
    BGBitmap->LoadFromFile(BGOpenDialog->FileName);
    AssignBack(BGBitmap);
    delete BGBitmap;
    BACK_LOADED = TRUE;            
    ShowTracingImage1->Checked 		 = FALSE;
    ShowTracingImage1->ImageIndex 	|= 1;
    tbTracingBitmap->ImageIndex  	|= 1;
	PIC_8BIT 						 = FALSE;
    DrawActiveScreen(TRUE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ShowTracingImage1Click(TObject *Sender)
{
    if(!BACK_LOADED) LoadTracingImage1Click(this);
    if(!BACK_LOADED) return;
	PIC_8BIT = ShowTracingImage1->Checked;
    ShowTracingImage1->Checked 		 = !ShowTracingImage1->Checked;
    ShowTracingImage1->ImageIndex 	^= 1;
    tbTracingBitmap->ImageIndex  	^= 1;
    DrawActiveScreen(FALSE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ShowPriorityBars1Click(TObject *Sender)
{
    ShowPriorityBars1->Checked 	     = !ShowPriorityBars1->Checked;
    ShowPriorityBars1->ImageIndex 	^= 1;
    tbPriLines->ImageIndex 			^= 1;
    DrawActiveScreen(FALSE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ZoomClick(TObject *Sender)
{
	zoomLevel = ((TMenuItem*)Sender)->Tag;
	pbSurfacePaint(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ZoomIn1Click(TObject *Sender)
{
	if(zoomLevel<16) zoomLevel++;
	pbSurfacePaint(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ZoomOut1Click(TObject *Sender)
{
	if(zoomLevel>1) zoomLevel--;
	pbSurfacePaint(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ShapeSelectClick(TObject *Sender)
{
	switch( ((TToolButton*)Sender)->Tag ) {
		case 0: // circle
        	pic->patCode &= 0xEF; break;
		case 1: // square
        	pic->patCode |= 0x10; break;
		case 2: // random
        	pic->patCode |= 0x20; break;
		case 3: // solid
        	pic->patCode &= 0xDF; break;
    }     
    WritePattern();  
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::UpDown1Click(TObject *Sender,
      TUDBtnType Button)
{
    PenSizeE->Caption = IntToStr(UpDown1->Position);
    pic->patCode = (pic->patCode & 0xF8) | (StrToInt(UpDown1->Position) & 7);

    WritePattern();
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton2Click(TObject *Sender)
{
	DeleteCode(pic->offset);
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton1Click(TObject *Sender)
{
	CropCode(pic->offset);
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton11Click(TObject *Sender)
{
    pic->offset = 0;  
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton10Click(TObject *Sender)
{
    if(!pic->offset) return;
    pic->offset = PicSkipTo(pic,psBACKWARD);
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton9Click(TObject *Sender)
{
    if(pic->offset>=pic->length-1) return;
    pic->offset = PicSkipTo(pic,psFORWARD);
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton8Click(TObject *Sender)
{
	pic->offset = pic->length-1;
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::SpeedButton3Click(TObject *Sender)
{
	long oldPixLen=pic->length;

	TDlgPicCommand *CmdWin = new TDlgPicCommand(this);

    FillListView(CmdWin->ListBox,pic->offset);
	CmdWin->offset = pic->offset;
    CmdWin->ShowModal();
    pic->offset = CmdWin->offset;
	if(pic->offset>=pic->length&&oldPixLen!=pic->length) pic->offset = pic->length;
	delete CmdWin;
    UpdatePic();
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ToolClick(TObject *Sender)
{
	int i,newTool;     
	lastTool = curTool;
	if(tbCurTool)
    	tbCurTool->Down = FALSE;
    tbCurTool = ((TToolButton*)Sender);
	newTool = tbCurTool->Tag;
    tbCurTool->Down = TRUE;
    for(i=0;i<TOTAL_PIC_TOOLS;i++)
    	if(picCsrRes[i].index==newTool) {
    		Screen->Cursors[drawingCursor] = LoadCursor(HInstance, picCsrRes[i].name);
    		pbSurface->Cursor = (TCursor) drawingCursor;
            break;
        }
    if(i==TOTAL_PIC_TOOLS) {
		Screen->Cursors[drawingCursor] = (HICON)crArrow;
		pbSurface->Cursor = (TCursor)drawingCursor;
    }
    curTool = newTool;
    drawingTool = -1;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ToolButton1Click(TObject *Sender)
{
//
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::ScreenClick(TObject *Sender)
{
	((TToolButton*)Sender)->Down = TRUE;
	activeScreen = ((TToolButton*)Sender)->Tag;
    DrawActiveScreen(FALSE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::PaletteClick(TObject *Sender)
{
	((TToolButton*)Sender)->Down = TRUE;
	activePalette = ((TToolButton*)Sender)->Tag;
    pic->visPal = activePalette;
    DrawActiveScreen(TRUE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::pbSurfaceMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
	float hPcnt,vPcnt,wPcnt,uPcnt;
	dnX = X/zoomLevel;
	dnY = Y/zoomLevel;
    DoAngleThing(&dnX,&dnY,Shift.Contains(ssShift));
                       
    if(curTool==PTOOL_ZOOM) {
    	if(Shift.Contains(ssLeft))
        	ZoomIn1Click(this);
        else
        	ZoomOut1Click(this);
        hPcnt = (float)dnX/(float)sPIC_WIDTH;
        vPcnt = (float)dnY/(float)sPIC_HEIGHT;
        ScrollBox1->HorzScrollBar->Position = (((float)((float)ScrollBox1->HorzScrollBar->Range-ScrollBox1->Width)*hPcnt));
        ScrollBox1->VertScrollBar->Position = (((float)((float)ScrollBox1->VertScrollBar->Range-ScrollBox1->Height)*vPcnt));
     	return;
	}
    if(Shift.Contains(ssRight)) {
     	drawingTool = -1;
		UpdatePic();
        return;
    }
    if(!Shift.Contains(ssLeft)) return;

    if(drawingTool!=curTool) paramCount=0;

    switch(curTool) {
        case PTOOL_LINE:
        	if(paramCount) {
        		if(paramCount==1) {
            		AddCode(0xF6);
        			AddCoords(lastPoint.x,lastPoint.y);
            	}
                if(paramCount>=1)
        			AddCoords(dnX,dnY);
            }
            UpdatePic();
            break;
        case PTOOL_SHORTLINE:
        	if(paramCount) {
        		if(paramCount==1) {
            		AddCode(0xF5);
        			AddCoords(lastPoint.x,lastPoint.y);
            	}
                if(paramCount>=1) {
            		FixCoords8Bit(&dnX,&dnY);
        			AddRel8Coords(lastPoint.x,lastPoint.y,dnX,dnY);
            	}
            }
            UpdatePic();
            break;
        case PTOOL_TINYLINE:
        	if(paramCount) {
        		if(paramCount==1) {
            		AddCode(0xF7);
        			AddCoords(lastPoint.x,lastPoint.y);
            	} 
                if(paramCount>=1) {
            		FixCoords4Bit(&dnX,&dnY);
        			AddRel4Coords(lastPoint.x,lastPoint.y,dnX,dnY);
            	}
            }
            UpdatePic();
            break;
        case PTOOL_FILL:
        	if(drawingTool!=PTOOL_FILL)
            	AddCode(0xF8);
        	AddCoords(dnX,dnY);
            UpdatePic();
            break;
        case PTOOL_ABSPEN:
        	if(drawingTool!=PTOOL_ABSPEN)
            	AddCode(0xFA);
            if(pic->patCode & 0x20) AddCode(pic->patNum<<1);
        	AddCoords(dnX,dnY);
            UpdatePic();
            break;
        case PTOOL_NEARPEN:
        	if(drawingTool!=PTOOL_NEARPEN) {
            	AddCode(0xFD);
            	if(pic->patCode & 0x20) AddCode(pic->patNum<<1);
        		AddCoords(dnX,dnY);
            } else {
            	FixCoords8Bit(&dnX,&dnY);  
            	if(pic->patCode & 0x20) AddCode(pic->patNum<<1);
        		AddRel8Coords(lastPoint.x,lastPoint.y,dnX,dnY);
            }
            UpdatePic();
            break;
        case PTOOL_CLSPEN:
        	if(drawingTool!=PTOOL_CLSPEN) {
            	AddCode(0xF4);       
            	if(pic->patCode & 0x20) AddCode(pic->patNum<<1);
        		AddCoords(dnX,dnY);
            } else {
            	FixCoords4Bit(&dnX,&dnY); 
            	if(pic->patCode & 0x20) AddCode(pic->patNum<<1);
        		AddRel4Coords(lastPoint.x,lastPoint.y,dnX,dnY);
            }
            UpdatePic();
            break;
    }
    lastPoint.x = dnX;
    lastPoint.y = dnY;
	mvX = dnX;
	mvY = dnY;
    drawingTool = curTool;
    paramCount++;

	pbSurfacePaint(Sender);
}
//---------------------------------------------------------------------------
#include <time.h>
void __fastcall TWndPicEdit::pbSurfaceMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
//	clock_t s = clock();
//    int a,b,c,d;
	mvX = X/zoomLevel;
	mvY = Y/zoomLevel;
//a = clock()-s;
    DoAngleThing(&mvX,&mvY,Shift.Contains(ssShift));
//b = clock()-s;

    switch(curTool) {
        case PTOOL_NEARPEN:   
        case PTOOL_SHORTLINE:
        	FixCoords8Bit(&mvX,&mvY);
            break;
        case PTOOL_CLSPEN:   
        case PTOOL_TINYLINE:
        	FixCoords4Bit(&mvX,&mvY);
            break;
    }         
//c = clock()-s;

	pbSurfacePaint(Sender);
//d = clock()-s;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::pbSurfaceMouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
	upX = X/zoomLevel;
	upY = Y/zoomLevel;

	//pbSurfacePaint(Sender);
}
//---------------------------------------------------------------------------
void TWndPicEdit::FixUpSurface()
{
    pbSurface->Width = sPIC_WIDTH*zoomLevel;
    pbSurface->Height = sPIC_HEIGHT*zoomLevel;

    FromTop = ScrollBox1->VertScrollBar->Position==0?0:
        ScrollBox1->VertScrollBar->Position/zoomLevel;
    FromLeft = ScrollBox1->HorzScrollBar->Position==0?0:
        ScrollBox1->HorzScrollBar->Position/zoomLevel;

    ps.rcPaint.left = FromLeft;
    ps.rcPaint.top = 0;
    ps.rcPaint.right = sPIC_WIDTH-FromLeft;
    ps.rcPaint.bottom = sPIC_HEIGHT-FromTop;

	nDestWidth  = pbSurface->Width-ScrollBox1->HorzScrollBar->Position;
	nDestHeight = pbSurface->Height-ScrollBox1->VertScrollBar->Position;
    nSrcWidth = sPIC_WIDTH-FromLeft;
    nSrcHeight = sPIC_HEIGHT-FromTop;
}
//---------------------------------------------------------------------------
#define BitPix(x,y,b,c)\
			b[y*sPIC_WIDTH+x] = c

#define LINEMACROX(startx, starty, deltalinear, deltanonlinear, linearvar, nonlinearvar, \
                  linearend, nonlinearstart, linearmod, nonlinearmod) \
   x = (startx); y = (starty); \
   incrNE = ((deltalinear) > 0)? (deltalinear) : -(deltalinear); \
   incrNE <<= 1; \
   deltanonlinear <<= 1; \
   incrE = ((deltanonlinear) > 0) ? -(deltanonlinear) : (deltanonlinear);  \
   d = nonlinearstart-1;  \
   while (linearvar != (linearend)) { \
     BitPix(x,y,b,c); \
     linearvar += linearmod; \
     if ((d+=incrE) < 0) { \
       d += incrNE; \
       nonlinearvar += nonlinearmod; \
     }; \
   }; \
   BitPix(x,y,b,c);

void BitsLine(int x1, int y1, int x2, int y2, U8 *b, U8 c)
{
	int dx, dy, incrE, incrNE, d, finalx, finaly;
	int x = x1;
	int y = y1;
	dx = x2-x1;
	dy = y2-y1;
	finalx = x2;
	finaly = y2;

	dx = abs(dx);
	dy = abs(dy);

	if (dx > dy) {
		if (finalx < x) {
			if (finaly < y) { /* llu == left-left-up */
				LINEMACROX(x, y, dx, dy, x, y, finalx, dx, -1, -1);
			} else {         /* lld */
				LINEMACROX(x, y, dx, dy, x, y, finalx, dx, -1, 1);
			}
		} else { /* x1 >= x */
			if (finaly < y) { /* rru */
				LINEMACROX(x, y, dx, dy, x, y, finalx, dx, 1, -1);
			} else {         /* rrd */
				LINEMACROX(x, y, dx, dy, x, y, finalx, dx, 1, 1);
			}
		}
	} else { /* dx <= dy */
		if (finaly < y) {
			if (finalx < x) { /* luu */
				LINEMACROX(x, y, dy, dx, y, x, finaly, dy, -1, -1);
			} else {         /* ruu */
				LINEMACROX(x, y, dy, dx, y, x, finaly, dy, -1, 1);
			}
		} else { /* y1 >= y */
			if (finalx < x) { /* ldd */
				LINEMACROX(x, y, dy, dx, y, x, finaly, dy, 1, -1);
			} else {         /* rdd */
				LINEMACROX(x, y, dy, dx, y, x, finaly, dy, 1, 1);
			}
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::pbSurfacePaint(TObject *Sender)
{
	if(!PicBitmapBits) return;
	pbSurface->OnPaint = NULL;

    pbSurface->Width = sPIC_WIDTH*zoomLevel;
    pbSurface->Height = sPIC_HEIGHT*zoomLevel;


    int FromTop = ScrollBox1->VertScrollBar->Position==0?0:
        ScrollBox1->VertScrollBar->Position/zoomLevel;
    int FromLeft = ScrollBox1->HorzScrollBar->Position==0?0:
        ScrollBox1->HorzScrollBar->Position/zoomLevel;
    HDC ahDC = GetDC( ScrollBox1->Handle );
    
    ps.hdc = ahDC;
    ps.rcPaint.left = FromLeft;
    ps.rcPaint.top = 0;
    ps.rcPaint.right = sPIC_WIDTH-FromLeft;
    ps.rcPaint.bottom = sPIC_HEIGHT-FromTop;
	BeginPaint(ScrollBox1->Handle,&ps);

    memcpy(TempBitmapBits,PicBitmapBits,sizeof(PicBitmapBits));
    if(ShowPriorityBars1->Checked)
        for(int i=0;i<14;i++)
        	BitsLine(0,priPoints[i],sPIC_WIDTH,priPoints[i],PicBitmapBits,i);
             /*
    if(ShowPriorityBars1->Checked) {
        for(int i=0;i<14;i++) {
        	SelectObject(ahDC, CreatePen(PS_SOLID,zoomLevel,pal->cols[i+1]));
        	MoveToEx(ahDC, 0,(priPoints[i]-FromTop)*zoomLevel,NULL);
        	LineTo(ahDC, (sPIC_WIDTH-FromLeft)*zoomLevel-1,(priPoints[i]-FromTop)*zoomLevel);
		}
    }
    if(drawingTool == PTOOL_CLSPEN || drawingTool == PTOOL_NEARPEN) {
    	RECT r = {(lastPoint.x-FromLeft)*zoomLevel,(lastPoint.y-FromTop)*zoomLevel,(mvX-FromLeft)*zoomLevel,(mvY-FromTop)*zoomLevel};
        SelectObject(ps.hdc, CreatePen(PS_DOT,1,clBlack));
        MoveToEx(ps.hdc, r.left, r.top,NULL);
        LineTo(ps.hdc, r.right, r.bottom);
    } else if(drawingTool == PTOOL_LINE || drawingTool == PTOOL_SHORTLINE || drawingTool == PTOOL_TINYLINE) {
    	RECT r = {(lastPoint.x-FromLeft)*zoomLevel,(lastPoint.y-FromTop)*zoomLevel,(mvX-FromLeft)*zoomLevel,(mvY-FromTop)*zoomLevel};
        SelectObject(ps.hdc, CreatePen(PS_SOLID,zoomLevel,clBlack));
        MoveToEx(ps.hdc, r.left, r.top,NULL);
        LineTo(ps.hdc, r.right, r.bottom);
    }            */

    StretchDIBits(
        ahDC,
        0,
		0,
		pbSurface->Width-ScrollBox1->HorzScrollBar->Position,
		pbSurface->Height-ScrollBox1->VertScrollBar->Position,
		FromLeft,
        0,
		sPIC_WIDTH-FromLeft,
		sPIC_HEIGHT-FromTop,
		PicBitmapBits,
		binfo,
		DIB_RGB_COLORS,
		SRCCOPY
    );        
    memcpy(PicBitmapBits,TempBitmapBits,sizeof(PicBitmapBits));
	EndPaint(ScrollBox1->Handle,&ps);
    ReleaseDC( ScrollBox1->Handle, ahDC );
        pbSurface->OnPaint = pbSurfacePaint;
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::DrawActiveScreen(BOOL FULL)
{
    if(!PICBMP) return;
    if(FULL) DrawPic(FALSE, activePalette, pic);

    if(ShowTracingImage1->Checked) {
        memcpy(TempBitmapBits2, BackBitmapBits, sizeof(TempBitmapBits));
        PicBitmapBits = TempBitmapBits2;
        binfo->bmiHeader = bmih;
        U8 *c = pic->bitmaps[activeScreen];
        U8 d = activeScreen==asVISUAL?0xF:0;
    	long *foo=(long*)PicBitmapBits;
        for(int y=0;y<sPIC_SIZE;y++) {
            if(*c!=d) {
                foo[y]=
                    palEGAU.cols[*c];
            }
            c++;
        }
    } else {
        PicBitmapBits = pic->bitmaps[activeScreen];
        binfo->bmiHeader = binfoh;
    }

    pbSurfacePaint(this);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::FormShow(TObject *Sender)
{
    DrawActiveScreen(FALSE);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::AddCode(U8 code)
{/*
	if(pic->offset >= rsMAX_SIZE) {
     	ssMessage(ssERROR,"Somehow you've managed to create a picture larger than SCI is capable of using! The picture is too large!");
        return;
    }*/
    for(int i=pic->length;i>pic->offset;i--)
    	pic->data[i] = pic->data[i-1];
	pic->data[pic->offset] = code;
    pic->offset++;
    pic->length++;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::AddCoords(S16 x, S16 y)
{
	AddCode((x&0x100)>>4);
	AddCode(x&0xFF);
	AddCode(y&0xFF);
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::AddRel8Coords(S16 x1, S16 y1, S16 x2, S16 y2)
{
	AddCode((char) (y2 < y1)? (char)(((y1-y2) & 0x7F) | 0x80):(char)((y2-y1) & 0x7F));
	AddCode((char) (x2 - x1));
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::AddRel4Coords(S16 x1, S16 y1, S16 x2, S16 y2)
{
	U8 w = ((abs(x2-x1) << 4) & 0x70) | (abs(y2-y1) & 7);
	if(x2<x1) w |= 0x80;
	if(y2<y1) w |= 0x08;
	AddCode(w);
}                
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::FixCoords8Bit(int *x, int *y)
{
	if(*x > lastPoint.x + 0x6F) *x = lastPoint.x + 0x6F;
	if(*x < lastPoint.x - 0x6F) *x = lastPoint.x - 0x6F;
	if(*y > lastPoint.y + 0x6F) *y = lastPoint.y + 0x6F;
	if(*y < lastPoint.y - 0x6F) *y = lastPoint.y - 0x6F;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::FixCoords4Bit(int *x, int *y)
{
	if(*x > lastPoint.x + 6) *x = lastPoint.x + 6;
	if(*x < lastPoint.x - 6) *x = lastPoint.x - 6;
	if(*y > lastPoint.y + 7) *y = lastPoint.y + 7;
	if(*y < lastPoint.y - 7) *y = lastPoint.y - 7;
}

//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::WritePattern()
{
	ToolClick(sbOff);
	if(PicGetLastCode(pic)==0xF9)
    	pic->data[pic->offset-1] = (pic->patCode);
    else {
    	AddCode(0xF9);
    	AddCode(pic->patCode);
    }
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::DeleteCode(U16 position)
{
	pic->offset = position;
	U16 oldOffset = pic->offset;
    U16 endOffset = PicGetNextCmdOffset(pic);
    U16 copyLen = endOffset-oldOffset;

    for(int i=0;i<copyLen;i++)
    	pic->data[oldOffset+i] = pic->data[endOffset+i];
    pic->length -= copyLen;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::CropCode(U16 position)
{
	pic->length				= position+1;
    pic->offset				= position;
    pic->data[pic->offset]	= 0xFF;
}
//---------------------------------------------------------------------------  
#define PI 3.14159265358979F
float __fastcall TWndPicEdit::PointsToAngle(float xOne, float yOne, float X, float Y)
{
    float nRatio, nASin;

    if(xOne == X && Y == yOne) return 0;

    X -= xOne;
    Y -= yOne;

    nRatio = X / sqrt(Y*Y + X*X);
    
    if(abs(nRatio) == 1)
        nASin = 90 * nRatio;
	else
        nASin = atan(nRatio / sqrt(-nRatio * nRatio + 1)) * (180 / PI);

	if(Y < 0)
        nASin = 90 - nASin + 90;
	else
    	if(X < 0)
        	nASin = nASin + 360;

    if(nASin<180) nASin += 180;
    else nASin-=180;

    nASin=abs(nASin-360);

	return nASin;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::DoAngleThing(int *_x, int *_y, BOOL LOCK)
{
	int x=*_x,y=*_y;
	if((curTool==PTOOL_LINE||curTool==PTOOL_SHORTLINE||curTool==PTOOL_TINYLINE||curTool==PTOOL_NEARPEN||curTool==PTOOL_CLSPEN)&&curTool==drawingTool) {
    	Angle = PointsToAngle(lastPoint.x,lastPoint.y,x,y);
		if(LOCK) {
        	if(Angle<23) {Angle=0; x = lastPoint.x;}
        	else if(Angle<68) {Angle=45; int d=sqrt(pow(x-lastPoint.x,2)+pow(y-lastPoint.x,2))*0.75; x = lastPoint.x+d; y = lastPoint.x-d; }
        	else if(Angle<113) {Angle=90; y = lastPoint.x;}
        	else if(Angle<158) {Angle=135; int d=sqrt(pow(x-lastPoint.x,2)+pow(y-lastPoint.x,2))*0.75; x = lastPoint.x+d; y = lastPoint.x+d; }
        	else if(Angle<203) {Angle=180; x = lastPoint.x;}
        	else if(Angle<248) {Angle=225; int d=sqrt(pow(x-lastPoint.x,2)+pow(y-lastPoint.x,2))*0.75; x = lastPoint.x-d; y = lastPoint.x+d; }
        	else if(Angle<293) {Angle=270; y = lastPoint.x;}
        	else if(Angle<338) {Angle=315; int d=sqrt(pow(x-lastPoint.x,2)+pow(y-lastPoint.x,2))*0.75; x = lastPoint.x-d; y = lastPoint.x-d; }
        	else {Angle=0; x = lastPoint.x;}
        }
    } else Angle = 0;
    AngleLabel->Caption = "Angle: "+IntToStr((__int64)Angle);
    XLabel->Caption = "X: "+IntToStr(x);
    YLabel->Caption = "Y: "+IntToStr(y);
    PriLabel->Caption = IntToStr(VIEW_PRIORITY(y));
    ColLabel->Caption = IntToHex(GETPIX(x,y,activeScreen),1);
    shPri->Brush->Color = palEGA.cols[VIEW_PRIORITY(y)];
    shCol->Brush->Color = palEGA.cols[GETPIX(x,y,activeScreen)];
    *_x = x;
    *_y = y;
}
//---------------------------------------------------------------------------
void __fastcall TWndPicEdit::FillListView(TListBox *lb, WORD o)
{
	int i=0,l,ii=-1,j,oi;
	lb->Items->Clear();
    U16 oldOffset = pic->offset;
    pic->offset=0;
    BOOL FIRST=TRUE;
	while(i<pic->length-1) {
    	oi = PicPrintCode(pic,FIRST);
        FIRST = FALSE;
        j=lb->Items->Add(IntToHex(i,4)+": "+picCmdNames[pic->data[i]&0xF]+" "+codeStr);
        if(i==o) ii=j;
        i = oi;
    }
    lb->ItemIndex=ii==-1?lb->Items->Count-1:ii;
    pic->offset = oldOffset;
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::UpdateDataEdit()
{
    if(!PICBMP) return;

    if(oldPicLen!=pic->length) SET_RESCHANGED();
    oldPicLen = pic->length;

    Graphics::TBitmap *b=new Graphics::TBitmap;
    b->Width  = ImgData->Width;
    b->Height = ImgData->Height;
    b->Canvas->Brush->Color = clBtnFace;
    b->Canvas->Brush->Style = bsSolid;
    b->Canvas->FillRect(Rect(0,0,b->Width,b->Height));
	AnsiString NewText;
    NewText= IntToHex((__int64)pic->offset,4)+":";
	int X = 0;

    	b->Canvas->Font->Name = "Tahoma";
    	b->Canvas->Font->Color = clBtnText;
    	b->Canvas->Font->Style = TFontStyles() << fsBold;
    	b->Canvas->Brush->Color = clBtnFace;
    	b->Canvas->Pen->Color = clWindowFrame;
    	b->Canvas->Pen->Width = 2;
        int tw=b->Canvas->TextWidth(NewText)+8;
        int th=b->Canvas->TextHeight(NewText)+8;
    	b->Canvas->Rectangle(Rect(X+1,(b->Height-th)/2+1,X+tw,((b->Height-th)/2)+th));
		b->Canvas->TextOut(X+4, (b->Height-th)/2+4, NewText);
        X += tw+4;
        b->Canvas->Font->Style=TFontStyles();
    	b->Canvas->Pen->Width = 1;
    int xo=pic->offset;
    BOOL FIRST=TRUE;
    while(xo<pic->length&&X<b->Width) {
        int tw= b->Canvas->TextWidth(picCmdNames[pic->data[xo]&0xF])+6;
        int th= b->Canvas->TextHeight(picCmdNames[pic->data[xo]&0xF])+6;
    	b->Canvas->Brush->Color = cl3DDkShadow;
    	b->Canvas->FillRect(Rect(X,(b->Height-th)/2,X+tw,((b->Height-th)/2)+th));
    	b->Canvas->Font->Color = cl3DLight;
		b->Canvas->TextOut(X+3, (b->Height-th)/2+3, picCmdNames[pic->data[xo]&0xF]);
        X += tw;
    	xo = PicPrintCode(pic,FIRST);
        FIRST = FALSE;
    	if(codeStr!="") {
    		b->Canvas->Font->Color = clBtnText;
    		b->Canvas->Brush->Color = clBtnFace;
        	int tw=b->Canvas->TextWidth(codeStr)+6;
        	int th=b->Canvas->TextHeight(codeStr)+6;
    		b->Canvas->Rectangle(Rect(X,(b->Height-th)/2,X+tw,((b->Height-th)/2)+th));
			b->Canvas->TextOut(X+3, (b->Height-th)/2+3, codeStr);
        	X += tw+4;
		} else X+=4;
    }
    ImgData->Picture->Bitmap->Assign(b);
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::GetColour(int scr, sciPIC *pic)
{
	TDlgColourSelect *ColWin = new TDlgColourSelect(this);
    ColWin->Setup(scr,this);
	ColWin->ShowModal();
    if(ColWin->ResPal==-2) return; // cancel

    memcpy(pic->palette, ColWin->Palette, sizeof(ColWin->Palette));

    if(ColWin->COLOUR_CHANGED) {
		if(ColWin->rbNewColours) {
    		AddCode(0xFE);
    		AddCode(0x00);
            for(int p=0;p<4;p++)
            	for(int c=0;c<40;c++) {
    				AddCode(SET_PALENT(p,c));
    				AddCode(pic->palette[p][c]);
                }
        } else {
    		AddCode(0xFE);
    		AddCode(0x01);   
			AddCode(ColWin->ResPal);
            for(int c=0;c<40;c++)
                AddCode(pic->palette[ColWin->ResPal][c]);
        }
    }

    if(ColWin->ResPal==-1) {// turn off
    	AddCode(offCodes[scr]);
    } else {
    	AddCode(onCodes[scr]);
    	AddCode(
        	(scr==asVISUAL)?
            SET_PALENT(ColWin->ResPal,ColWin->ResCol):
            ColWin->ResCol
        );
    }

	DrawColour(scr);

	delete ColWin;

    UpdatePic();
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::DrawColour(int scr)
{
	TColor c1,c2;
    TImage *im;
    switch(scr) {
     	case asVISUAL:
        	im=imVisCol;
            break;
     	case asPRIORITY:
        	im=imPriCol;
            break;
     	case asCONTROL:
        	im=imCtlCol;
            break;
        default:
        	return;
    }
    U8 p,c;
	im->Visible = FALSE;
	p = GET_PALDEX(pic->col[scr]);
	c = GET_PALCOL(pic->col[scr]);
    if(pic->drawenable&(1<<scr)) {// turn on
        if(scr==asVISUAL) {
         	c1 = palEGA.cols[(pic->palette[p][c]>>4)&0xF];
         	c2 = palEGA.cols[pic->palette[p][c]&0xF];
        } else {
         	c1 = c2 = palEGA.cols[c&0xF];
        }                          
        im->Canvas->Pen->Color		= clWindowFrame;
        im->Canvas->Brush->Style	= bsClear;
        im->Canvas->Rectangle(0,0,im->Width,im->Height);
        for(int y=im->Height-2;y>=1;y--)
        	for(int x=im->Width-2;x>=1;x--)
        		im->Canvas->Pixels[x][y] = ((x^y)&1)?c1:c2;
    } else { // turn off
        im->Canvas->Brush->Color	= clBtnFace;
        im->Canvas->Pen->Color		= clBtnFace;
        im->Canvas->Rectangle(0,0,im->Width,im->Height);
        im->Canvas->Pen->Color		= clBtnHighlight;
        im->Canvas->MoveTo(1, 0 );
        im->Canvas->LineTo(14,13);
        im->Canvas->MoveTo(1, 13);
        im->Canvas->LineTo(14,0);
        im->Canvas->Pen->Color		= clBtnShadow;
        im->Canvas->MoveTo(0, 0 );
        im->Canvas->LineTo(13,13);
        im->Canvas->MoveTo(0, 13);
        im->Canvas->LineTo(13,0);
        im->Canvas->Brush->Style	= bsClear;
        im->Canvas->Rectangle(0,0,im->Width,im->Height);
    }    
	im->Visible = TRUE;
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::sbVisClick(TObject *Sender)
{
	GetColour(asVISUAL,pic);
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::sbPriClick(TObject *Sender)
{
	GetColour(asPRIORITY,pic);
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::sbCtlClick(TObject *Sender)
{
	GetColour(asCONTROL,pic);
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::ScrollBox1Resize(TObject *Sender)
{
    //FixUpSurface();
}
//---------------------------------------------------------------------------

void __fastcall TWndPicEdit::Panel1Resize(TObject *Sender)
{
	UpdatePic();
}
//---------------------------------------------------------------------------
