/*
 *	Draw.c - Copyright © 1991 by S.R. & P.C.
 *
 *	Created:	16 Feb 1991  12:32:43
 *	Modified:	21 Jul 1991  16:46:08
 *
 *	Make>> make
 */

#include "Global.h"
#include "proto/Draw.h"


extern struct Process *MainProcess;
extern struct Screen *Screen;
extern struct MinList WindowList;
extern struct BrowserWindow *CurrentWin;
extern struct Config Config;
extern short SelectNum;
extern long SelectBytes, SelectBlocks;


void Print(struct BrowserWindow *Win, struct ScrollEntry *S, short x, short y)
{
	struct RastPort *rp;
	ULONG enable;

	rp = Win->bw_Window->RPort;
	Move(rp, x, y);
	SetAPen(rp, S->se_Pen);
	SetDrMd(rp, (S->se_State & STATE_SELECTED)?INVERSVID|JAM2:JAM2);
	enable = AskSoftStyle(rp);
	if (S->se_State & STATE_GHOSTED)
		SetBPen(rp, 2);
	else if (S->se_State & STATE_DELETED)
		enable = SetSoftStyle(rp, FSF_ITALIC, enable);
	if (S->se_FileInfo.fi_Type == DLX_UNMOUNTED)
		enable = SetSoftStyle(rp, FSF_BOLD, enable);
	Text(rp, S->se_Print, Win->bw_PrintLen);
	SetSoftStyle(rp, FS_NORMAL, enable);
	SetBPen(rp, 0);
}


void ScrollAndDraw(long firstlinenum, long firstliney, long dY, long numlines)
{
	struct RastPort *rp;
	short i,j,n,L;

	rp = CurrentWin->bw_Window->RPort;
	L = CurrentWin->bw_ScrollStruct.NumLines;
	ScrollRaster(rp, 0, dY, 4, 11, CurrentWin->bw_Window->Width-17, 11+9*L);
	for( i=0 ; i<numlines ; i++ ) {
		for( j=0 ; j<CurrentWin->bw_NumCol ; j++ ) {
			n = firstlinenum+i+j*L;
			if (n > CurrentWin->bw_ShownEntries-1) break;
			Print(CurrentWin, CurrentWin->bw_EntryArray[n], 4+j*CurrentWin->bw_ColWidth, 18+firstliney+9*i);
		}
	}
}


void RedrawEntries(struct BrowserWindow *Win)
{
	register struct Window *W;
	register struct RastPort *rp;
	short i, j, m, n, tmp;

	W = Win->bw_Window;
	rp = W->RPort;
	SetAPen(rp,0);
	RectFill(rp, 2, 10, W->Width-17, W->Height-10);
	SetAPen(rp,1);
	n = Win->bw_ScrollStruct.NumLines * Win->bw_NumCol;
	m = (n < Win->bw_ShownEntries - Win->bw_ScrollStruct.TopEntryNumber) ? n : Win->bw_ShownEntries - Win->bw_ScrollStruct.TopEntryNumber;
	
	for( i=0 ; i<Win->bw_NumCol ; i++ ) {
		tmp = i * Win->bw_ScrollStruct.NumLines + Win->bw_ScrollStruct.TopEntryNumber;
		for( j=0 ; j<Win->bw_ScrollStruct.NumLines && i*Win->bw_ScrollStruct.NumLines+j<m ; j++ ) {
			Print(Win, Win->bw_EntryArray[tmp+j], 4+i*Win->bw_ColWidth, 18+9*j);
		}
	}
}


void RedrawAll(void)
{
	RedrawEntries(CurrentWin);
}


/* Get the coordinates of a ScrollEntry. If not currently displayed, return FALSE */

BOOL GetSePosition(struct BrowserWindow *Win, struct ScrollEntry *S, struct Point *Position)
{
	short top, visible, i;
	
	top = Win->bw_ScrollStruct.TopEntryNumber;
	visible = MIN(Win->bw_ScrollStruct.NumLines * Win->bw_NumCol, Win->bw_ShownEntries);
	for( i=top ; i<top+visible ; i++ ) {
		if (S == Win->bw_EntryArray[i]) {
			Position->X = 4 + ((i-top)/Win->bw_ScrollStruct.NumLines) * Win->bw_ColWidth;
			Position->Y = 18 + ((i-top)%Win->bw_ScrollStruct.NumLines) * 9;
			return TRUE;
		}
	}
	return FALSE;
}


void RefreshBottomInfo(struct BrowserWindow *Win)
{
	struct Window *W;
	struct RastPort *rp;
	short l, cx;

	W = Win->bw_Window;
	rp = W->RPort;
	SetDrMd(rp, JAM2);
	l = strlen(Win->bw_BottomText)-1;	/* Visible length. Ignore leading space. */
	if (l<0)
		return;	/* No text */
	SetAPen(rp, 2);
	SetBPen(rp, 1);
	LockLayerInfo(&Screen->LayerInfo);	/* Prevent resizing window while printing text which may trash screen */
	Move(rp, -4, W->Height-2);
	Text(rp, Win->bw_BottomText, (MIN(Win->bw_BottomLen, l))+1);
	SetBPen(rp, 0);
	SetAPen(rp, 1);
	cx = rp->cp_x;
	Move(rp, cx, W->Height-9);
	Draw(rp, 0, W->Height-9);
	if (l < Win->bw_BottomLen)
		RectFill(rp, cx, W->Height-9, W->Width-17, W->Height-1);
	UnlockLayerInfo(&Screen->LayerInfo);
}


void MakeMainBottomInfoString(void)
{
	static struct InfoData *info = NULL;
	struct BrowserWindow *Main;
	long FreeBlocks, FreeBytes;
	char VolumeName[34];

	if (info || (info = ArpAlloc(sizeof(struct InfoData)))) {
		Main = (struct BrowserWindow *)WindowList.mlh_Head;
		if (CurrentWin->bw_Type == BW_MAIN)
			SPrintf(Main->bw_BottomText, " %ld Bytes  %ld Blocks  %d Entries selected",
										  SelectBytes, SelectBlocks, SelectNum);
		else {
			MainProcess->pr_WindowPtr = (APTR)-1L;
			PathName(CurrentWin->bw_RootLock, VolumeName, 32);
			if (Info(CurrentWin->bw_RootLock, info)) {
				FreeBlocks = info->id_NumBlocks - info->id_NumBlocksUsed;
				FreeBytes = FreeBlocks * info->id_BytesPerBlock;
				SPrintf(Main->bw_BottomText, " %s %ld KBytes  %ld Blocks Free", VolumeName, FreeBytes>>10, FreeBlocks);
			}
			else
				SPrintf(Main->bw_BottomText, " %s Volume not mounted", VolumeName);
			MainProcess->pr_WindowPtr = (APTR)Main->bw_Window;
		}
		RefreshBottomInfo(Main);
	}
}


void MakeBottomInfoString(struct BrowserWindow *Win)
{
	if (Win->bw_Type == BW_DIR) {
		if (Win->bw_SelectNum > 0) {
			SPrintf(Win->bw_BottomText, " %ld/%ld Bytes  %ld/%ld Blocks  %d/%d  Entries selected",
			Win->bw_SelectBytes, Win->bw_ShownBytes,
			Win->bw_SelectBlocks, Win->bw_ShownBlocks,
			Win->bw_SelectNum, Win->bw_ShownEntries);
		}
		else {
			SPrintf(Win->bw_BottomText,
					" %d/%d Files  %d/%d Dirs  %ld/%ld Bytes  %ld/%ld Blocks",
					Win->bw_ShownFiles, Win->bw_NumFiles,
					Win->bw_ShownDirs, Win->bw_NumDirs,
					Win->bw_ShownBytes, Win->bw_NumBytes,
					Win->bw_ShownBlocks, Win->bw_NumBlocks);
		}
	}
	MakeMainBottomInfoString();
}


void RefreshWindow(struct BrowserWindow *Win)
{
	struct BrowserWindow *OldCurrent;
	struct Window *W;
	struct RastPort *rp;

	W = Win->bw_Window;
	rp = W->RPort;
	SetDrMd(rp, JAM2);
	Win->bw_ScrollStruct.NumLines = (W->Height-21)/9;
	Win->bw_ColWidth = 8 * (Win->bw_PrintStringLen+1);
	Win->bw_NumCol = (W->Width-22)/Win->bw_ColWidth;
	Win->bw_BottomLen = (W->Width-22)/8;
	SetAPen(rp, 1);
	RectFill(rp, 0, W->Height-9, W->Width-17, W->Height-1);
	RefreshBottomInfo(Win);
	if (Win->bw_NumCol == 0) {
		Win->bw_NumCol = 1;
		Win->bw_PrintLen = Win->bw_BottomLen;
	}
	else {
		Win->bw_PrintLen = Win->bw_PrintStringLen;
	}
	if (Win->bw_ScrollStruct.NumLines * Win->bw_NumCol >= Win->bw_ShownEntries) {
		Win->bw_ScrollStruct.NumEntries = Win->bw_ScrollStruct.NumLines;
		Win->bw_ScrollStruct.TopEntryNumber = 0;
	}
	else {
		Win->bw_ScrollStruct.NumEntries = Win->bw_ShownEntries - Win->bw_ScrollStruct.NumLines * (Win->bw_NumCol-1);
	}
	/* This can happen after deleting entries in window */
	if (Win->bw_ScrollStruct.TopEntryNumber >= Win->bw_ShownEntries) {
		Win->bw_ScrollStruct.TopEntryNumber = Win->bw_ShownEntries - Win->bw_ScrollStruct.NumLines * Win->bw_NumCol;
		if (((long)Win->bw_ScrollStruct.TopEntryNumber) < 0)
			Win->bw_ScrollStruct.TopEntryNumber = 0;
	}
	Win->bw_Prop.Info.VertBody = SetSize(Win->bw_ShownEntries, Win->bw_ScrollStruct.NumLines*Win->bw_NumCol);
	RefreshGList(&Win->bw_Prop.Gadget, W, NULL, 1);
	RedrawEntries(Win);
	OldCurrent = CurrentWin;
	CurrentWin = Win;	/* RealTimeScroll() calls functions that need CurrentWin */
	RealTimeScroll(&Win->bw_ScrollStruct);
	CurrentWin = OldCurrent;
}


