home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 6
/
AACD06.ISO
/
AACD
/
Utilities
/
amiCheck
/
Source
/
regGadget.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-11
|
36KB
|
1,601 lines
/***************************************************************
* regGadget.c
*
* Creates and maintains the custom register display gadget
*
***************************************************************/
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <libraries/guifront.h>
#include <intuition/gadgetclass.h>
#include <exec/memory.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/diskfont_protos.h>
#include <intuition/screens.h>
#include <clib/intuition_protos.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfxbase.h>
#include "amiCheck.h"
#include "mainPanel.h"
#include "regGadget.h"
#include "dataBase.h"
extern struct GfxBase *GfxBase;
#define WaitBlit();
#define RTEST(x) {if ((x)==FALSE) return FALSE;}
#define AREA_SIZE 200
#define NUMCOLS 7
#define COLBUFFER 4 /* pixels on either side */
/*
* globals and typedefs
*/
BOOL editDisable = TRUE;
/* typedef for register row */
typedef struct {
ULONG rpY; /* start of row */
ULONG height; /* height of row */
ULONG fontY; /* distance from top for text */
} regRowType;
/* typedef for register column */
typedef struct {
ULONG rpX; /* start of column */
ULONG width; /* width of column */
ULONG fontX; /* distance from start for text */
} regColType;
/* typedef for register cell */
typedef struct {
regRowType *cellRow;
regColType *cellCol;
} regCellType;
/* tool to index regGrid */
#define REGGRID(r,c) regGrid[(r)*numCols + (c)]
regColType registerCols[NUMCOLS];
regRowType *registerRows = NULL;
regCellType *regGrid = NULL;
filterNode *regTopNode = NULL;
char *regTypeArray[3] = {
"Check",
"Withdrawal",
"Deposit",
};
long regPrintChars[3];
long regPrintFlags[3];
/* vars for our geometry */
ULONG regWidth, regHeight;
ULONG regTop, regLeft;
ULONG numRows; /* number of items that fit */
ULONG numCols = NUMCOLS;
ULONG entryHeight; /* pixels of entry */
ULONG depth;
extern GadgetSpec gadgetspecs[];
/* vars for our working RP */
struct RastPort workRP, *activeRP = NULL;
chip struct BitMap workbuffer;
chip struct AreaInfo workarea;
chip struct TmpRas worktmp;
chip void *tmprp = NULL;
chip UWORD areaBuffer[AREA_SIZE];
/* vars for our header RP */
struct RastPort headerRP;
chip struct BitMap headerbuffer;
chip struct AreaInfo headerarea;
chip struct TmpRas headertmp;
chip void *headertmprp = NULL;
chip UWORD headerareaBuffer[AREA_SIZE];
ULONG hWidth,hHeight,hTop,hLeft;
/* vars for our FONT */
struct TextFont *regFont = NULL;
/* misc control vars */
ULONG selRow = -1; /* selected row */
ULONG regValidRows; /* number of valid rows from top */
ULONG regTopRow;
/* lets remember the register window! */
struct Window *guiWindow = NULL;
/* special register config var */
BOOL showMemo = FALSE;
/*
* Configurations!
*/
/* headers for register */
char *headers[] = {
"Type",
"Date",
"Description",
"V",
"C",
"T",
"$ Amount",
};
/*
* local prototypes
*/
BOOL RegRPInit(void);
BOOL RegLayout(void);
BOOL RegAllocHeader(void);
void RegRenderGrid(void);
void RegRenderHeader(void);
void RegDeselect(BOOL);
void RegScrollSetup(ULONG,ULONG,ULONG);
void RegFillRow(filterNode *, WORD);
void RegScrollListUp(void);
void RegLastPage(void);
/*
* routines
*/
/*************************************************************
* RegSwapMemo()
*
* Swaps memo in register
**************************************************************/
void RegSwapMemo(void)
{
long entries, lastselRow, lasttop;
/* preserve some globals */
lasttop = regTopRow;
lastselRow = selRow;
entries = entryCount;
AmiLock();
if (showMemo)
showMemo = FALSE;
else showMemo = TRUE;
/* free up arrays */
if (registerRows != NULL) {
FreeVec(registerRows);
}
if (regGrid != NULL) {
FreeVec(regGrid);
}
RegLayout();
entryCount = entries;
if (entryCount > numRows)
regValidRows = numRows;
else regValidRows = entryCount;
RegClearGrid();
selRow = lastselRow;
if (entryCount > numRows && entryCount-lasttop < regValidRows)
lasttop = entryCount - regValidRows;
if (selRow != -1)
RegMoveToSel(&filtered);
else RegMoveList(&filtered,lasttop);
RegRefresh(FALSE);
RegScrollSetup(regTopRow,entryCount,regValidRows);
AmiUnlock();
}
/**************************************************************
* RegInit()
*
* Initialize the register gadget
*
**************************************************************/
BOOL RegInit(void)
{
int x;
/* build structures */
RTEST(RegRPInit());
RTEST(RegLayout());
RTEST(RegAllocHeader());
/* create default imagery */
RegRenderHeader();
RegClearGrid();
/* set up scroller */
RegScrollSetup(0,0,0);
regTopRow = regValidRows = 0;
RegRefresh(TRUE);
for (x=0;x<3;x++) {
regPrintFlags[x] = regPrintChars[x] = -1;
}
return (TRUE);
}
/**************************************************************
* RegAllocHeader()
*
* Allocates RP and BitMap for header. Must be done
* _after_ reglayout() has selected and opened the font.
*
***************************************************************/
BOOL RegAllocHeader(void)
{
ULONG x;
hTop = AC_MainSpecs[GID_REGHEADER]->gs_Gadget->TopEdge + 1;
hLeft = AC_MainSpecs[GID_REGHEADER]->gs_Gadget->LeftEdge + 2;
hWidth = AC_MainSpecs[GID_REGHEADER]->gs_Gadget->Width - 4;
hHeight= AC_MainSpecs[GID_REGHEADER]->gs_Gadget->Height - 2;
/* create bitmap */
InitBitMap(&headerbuffer,depth, hWidth,hHeight);
for (x=0;x<depth;x++) {
headerbuffer.Planes[x] = (PLANEPTR)AllocRaster(hWidth+1,hHeight+1);
if (headerbuffer.Planes[x] == NULL) return (FALSE);
}
/* create area buffer */
for (x=0;x<AREA_SIZE;x++) headerareaBuffer[x] =0;
InitArea(&headerarea, headerareaBuffer, (AREA_SIZE*2)/5);
/* create TmpRas */
headertmprp = (void *)AllocVec((hWidth+1)*(hHeight+1), MEMF_CHIP);
if (headertmprp == NULL) return (FALSE);
InitTmpRas(&headertmp,headertmprp,(hWidth+1)*(hHeight+1));
/* link in to our work rastport */
InitRastPort(&headerRP);
headerRP.BitMap = &headerbuffer;
headerRP.AreaInfo = &headerarea;
headerRP.TmpRas = &headertmp;
headerRP.Layer = NULL;
/* initialize our pen colors */
SetAPen(&headerRP,DETAILPEN);
/* fill area with color */
SetRast(&headerRP,DETAILPEN);
/*
RectFill(&headerRP,0,0,hWidth,hHeight);
*/
SetFont(&headerRP,regFont);
return (TRUE);
}
/**************************************************************
* RegRenderHeader()
*
* Renders the header titles above the register
*
***************************************************************/
void RegRenderHeader(void)
{
ULONG x, top;
/* set pen color */
SetAPen(&headerRP,BLOCKPEN);
top = regFont->tf_Baseline;
if (regFont->tf_YSize <= hHeight) {
for (x=0;x<numCols;x++) {
Move(&headerRP,REGGRID(0,x).cellCol->rpX + COLBUFFER,top);
Text(&headerRP,headers[x],strlen(headers[x]));
}
}
}
/**************************************************************
* RegRPInit()
*
* initialize our playground
*
**************************************************************/
BOOL RegRPInit()
{
UWORD x;
/* define geometry (-2 accounts for shadowing border) */
regWidth = AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Width - 4;
regHeight= AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Height - 2;
regTop = AC_MainSpecs[GID_REGFIELD]->gs_Gadget->TopEdge + 1;
regLeft = AC_MainSpecs[GID_REGFIELD]->gs_Gadget->LeftEdge + 2;
/* the one and only delicate hack of our program */
AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Activation |= GACT_IMMEDIATE;
/*
* extract information about our main window
*/
GF_GetGUIAttr(gui, GUI_Window, &guiWindow, TAG_DONE);
activeRP = guiWindow->RPort;
depth = activeRP->BitMap->Depth;
/*
* create working rast port area
*/
/* create bitmap */
InitBitMap(&workbuffer,depth, regWidth, regHeight);
for (x=0;x<depth;x++) {
workbuffer.Planes[x] = (PLANEPTR)AllocRaster(regWidth+1,
regHeight+1);
if (workbuffer.Planes[x] == NULL) return (FALSE);
}
/* create area buffer */
for (x=0;x<AREA_SIZE;x++) areaBuffer[x] =0;
InitArea(&workarea, areaBuffer, (AREA_SIZE*2)/5);
/* create TmpRas */
tmprp = (void *)AllocVec((regWidth+1)*(regHeight+1), MEMF_CHIP);
if (tmprp == NULL) return (FALSE);
InitTmpRas(&worktmp,tmprp,(regWidth+1)*(regHeight+1));
/* link in to our work rastport */
InitRastPort(&workRP);
workRP.BitMap = &workbuffer;
workRP.AreaInfo = &workarea;
workRP.TmpRas = &worktmp;
workRP.Layer = NULL;
return (TRUE);
}
/*************************************************************
* RegLayout()
*
* calculates the number of possible entries, the starting
* position of each item.
*
**************************************************************/
BOOL RegLayout(void)
{
struct TextAttr regAttr;
UWORD regFontHeight;
#if 0
char regFontName[50];
BOOL regScreen;
#endif
ULONG height;
int x,temp,desc;
char *colFixes[NUMCOLS] = {
"Withdrawal",
"DEC000000",
"",
"V",
"C",
"T",
"000000000.00",
};
GF_GetGUIAttr(gui,
GUI_ActualFont,®Attr,
TAG_DONE);
#if 0
/* grab information from guifront on fonts */
GF_GetPrefsAttr(gui,
PRF_GadgetScreenFont,®Attr,
TAG_DONE);
/* are we using the screen font? */
if (regScreen)
regAttr = guiWindow->WScreen->Font;
else {
if ( GF_GetPrefsAttr(gui,
PRF_GadgetFontYSize, ®FontHeight,
PRF_GadgetFontName, regFontName,
TAG_DONE) != 2) {
regAttr = guiWindow->WScreen->Font;
}
else regAttr = guiWindow->WScreen->Font;
}
#endif
/* at last, open the damn thing */
regFont = OpenDiskFont(®Attr);
if (regFont == NULL) return (FALSE);
SetFont(&workRP,regFont);
/* calculate entry separators */
height = regFont->tf_YSize + regFont->tf_YSize/8 + 1;
/* * * * */
if (showMemo) height *= 2;
numRows = regHeight/height;
/* tweek height to absorb excess space - numRows is same */
entryHeight = height + (regHeight%height)/numRows;
temp = regHeight%entryHeight;
/* install rows */
registerRows = (regRowType *)AllocVec(sizeof(regRowType)*numRows,
MEMF_ANY);
if (registerRows == NULL) return (FALSE);
height = (entryHeight / 2) - (regFont->tf_YSize/2) +
regFont->tf_Baseline;
#if 0
registerRows[0].fontY = height + 1;
registerRows[0].rpY = 0; /*entryHeight + ((temp>0)?1:0);*/
registerRows[0].height = entryHeight + ((temp>0)?1:0);
for (x=1;x<numRows;x++) {
registerRows[x].fontY = height + 1;
registerRows[x].height = entryHeight + ((x<temp)?1:0);
registerRows[x].rpY = registerRows[x-1].rpY + registerRows[x-1].height;
}
#endif
registerRows[0].fontY = height + 1;
registerRows[0].rpY = 0;
registerRows[0].height = entryHeight; /* should never get extra line... cest la vi! */
for (x=1;x<numRows;x++) {
registerRows[x].fontY = height + 1;
registerRows[x].height = entryHeight + ( (x > numRows-temp )?1:0);
registerRows[x].rpY = registerRows[x-1].rpY + registerRows[x-1].height;
}
/* install cols */
temp = desc = 0;
for (x=0;x<numCols;x++) {
registerCols[x].fontX = COLBUFFER;
if (x == 0) registerCols[x].rpX = 0;
else registerCols[x].rpX = registerCols[x-1].rpX +
registerCols[x-1].width + 1;
/* need to give description all extra space */
if (strlen(colFixes[x]) == 0) {
desc = x;
registerCols[x].width = 0;
}
else {
registerCols[x].width = TextLength(&workRP,
colFixes[x],strlen(colFixes[x])) +
COLBUFFER*2 ;
temp += registerCols[x].width;
}
}
/* now fix for description list */
registerCols[desc].width = regWidth - temp;
for (x=desc+1;x<numCols;x++) {
registerCols[x].rpX += registerCols[desc].width;
}
/* now build the cell grid */
regGrid = (regCellType *)AllocVec(sizeof(regCellType)*numCols*numRows,
MEMF_ANY);
if (regGrid == NULL) return (FALSE);
for (x=0;x<numRows;x++) {
for (temp=0;temp<numCols;temp++) {
REGGRID(x,temp).cellRow = ®isterRows[x];
REGGRID(x,temp).cellCol = ®isterCols[temp];
}
}
return (TRUE);
}
/*************************************************************
* RegRenderCellFlush()
*
* Flush the text (right justify)
**************************************************************/
void RegRenderCellFlush(ULONG row, ULONG col, char *str, char pen,
long *printchars)
{
ULONG x,y,b, width, length;
struct TextExtent resultExtent;
/* set pen */
SetAPen(&workRP,pen);
/* quick pull out some info on cell */
y = REGGRID(row,col).cellRow->rpY;
b = REGGRID(row,col).cellRow->fontY;
x = REGGRID(row,col).cellCol->rpX + REGGRID(row,col).cellCol->fontX;
width = REGGRID(row,col).cellCol->width - COLBUFFER;
/* clip str to make fit... */
if (*printchars == -1)
*printchars = TextFit(&workRP,str,strlen(str),&resultExtent,NULL,1,
REGGRID(row,col).cellCol->width-(COLBUFFER*3) + 1,
REGGRID(row,col).cellRow->height );
length = TextLength(&workRP,str,*printchars);
if (length < width-(COLBUFFER*3)+1)
x += (width-(COLBUFFER*3)+1) - length;
/* stuf it in */
Move(&workRP,x,y+b);
Text(&workRP,str, *printchars);
if (row == numRows-1) {
SetAPen(&workRP,TEXTPEN);
Move(&workRP,1,regHeight-1);
Draw(&workRP,regWidth-1,regHeight-1);
}
}
/*************************************************************
* RegRenderCell()
*
* Renders string contents into a given cell. Does
* necessary clipping of the string.
*
***************************************************************/
void RegRenderCell(ULONG row, ULONG col, char *str, char pen,
long *printchars, BOOL memo)
{
ULONG x,y,b, width;
struct TextExtent resultExtent;
/* set pen */
SetAPen(&workRP,pen);
/* quick pull out some info on cell */
y = REGGRID(row,col).cellRow->rpY;
b = REGGRID(row,col).cellRow->fontY;
x = REGGRID(row,col).cellCol->rpX + REGGRID(row,col).cellCol->fontX;
width = REGGRID(row,col).cellCol->width - COLBUFFER;
/* clip str to make fit... */
if (*printchars == -1) {
*printchars = TextFit(&workRP,str,strlen(str),&resultExtent,NULL,1,
REGGRID(row,col).cellCol->width-(COLBUFFER*2) + 1,
REGGRID(row,col).cellRow->height );
}
/* special case description/memo stuff */
if (showMemo == TRUE && col == 2 ) {
if (memo == FALSE) {
b = (entryHeight / 4) - (regFont->tf_YSize/2) +
regFont->tf_Baseline;
/* b -= (regFont->tf_YSize/2);*/
}
else {
if (*printchars > strlen(str))
*printchars = strlen(str);
b = (entryHeight ) - (regFont->tf_YSize/2) + 1 /* -
regFont->tf_Baseline*/;
/* b += (regFont->tf_YSize/2);*/
}
}
/* stuf it in */
Move(&workRP,x,y+b);
Text(&workRP,str,*printchars);
if (row == numRows-1) {
SetAPen(&workRP,TEXTPEN);
Move(&workRP,1,regHeight-1);
Draw(&workRP,regWidth-1,regHeight-1);
}
}
/*************************************************************
* RegRenderGrid()
*
* Renders the register grid. Simple enough...
*
**************************************************************/
void RegRenderGrid(void)
{
int x;
/* set our pens */
SetAPen(&workRP,BLOCKPEN);
/* horizontals */
for (x=0;x<numRows;x++) {
Move(&workRP,0,registerRows[x].rpY);
Draw(&workRP,regWidth,registerRows[x].rpY);
if (showMemo) {
SetDrPt(&workRP,0xAAAA);
Move(&workRP,registerCols[2].rpX,registerRows[x].rpY + entryHeight/2);
Draw(&workRP,registerCols[3].rpX,registerRows[x].rpY + entryHeight/2);
SetDrPt(&workRP,~0);
if (x != 0 && x < numRows){
Move(&workRP,0,registerRows[x].rpY-1);
Draw(&workRP,regWidth,registerRows[x].rpY-1);
}
}
}
/* verticals */
for (x=0;x<numCols;x++) {
Move(&workRP,registerCols[x].rpX,0);
Draw(&workRP,registerCols[x].rpX,regHeight);
}
/* set highlight pen */
SetAPen(&workRP,TEXTPEN);
/* put depth into our register window */
Move(&workRP,1,regHeight-1);
Draw(&workRP,regWidth,regHeight-1);
Move(&workRP,regWidth-1,1);
Draw(&workRP,regWidth-1,regHeight);
}
/*************************************************************
* RegRefresh()
*
* Blits the work area into the window
*
**************************************************************/
void RegRefresh(BOOL header)
{
#if 0
/* blit over the working register bitmap into window */
ClipBlit(&workRP,0,0,activeRP,regLeft,regTop,
regWidth,regHeight,(ULONG)0xc0);
#endif
/*
BltBitMapRastPort(workRP.BitMap,0,0,activeRP,regLeft,regTop,
regWidth,regHeight,0xc0);
WaitBlit();*/
ClipBlit(&workRP,0,0,activeRP,regLeft,regTop,regWidth,regHeight,(ULONG)0xc0);
if (header) {
/*
BltBitMapRastPort(headerRP.BitMap,0,0,activeRP,hLeft,hTop,
hWidth,hHeight,0xc0);
WaitBlit();*/
ClipBlit(&headerRP,0,0,activeRP,hLeft,hTop,hWidth,hHeight,(ULONG)0xc0);
}
}
/*************************************************************
* RegSelect()
*
* marks a row as being selected.
*
**************************************************************/
void RegSelect(ULONG row, BOOL towin)
{
BYTE oldmode, oldmask;
ULONG height, top;
/* is it currently selected? */
if (selRow == regTopRow + row) return;
/* remove old one */
RegDeselect(towin);
height = registerRows[row].height - 2;
top = registerRows[row].rpY + 1;
/* render it to the actual window first (avoids flicker later) */
if (towin) {
oldmode = activeRP->DrawMode;
oldmask = activeRP->Mask;
SetDrMd(activeRP,COMPLEMENT);
SafeSetWriteMask(activeRP,0x3);
RectFill(activeRP,
1 + regLeft, top + regTop,
regWidth - 2 + regLeft,top + height + regTop );
WaitBlit();
SetDrMd(activeRP,oldmode);
SafeSetWriteMask(activeRP,oldmask);
}
/* now render it "for real" so refreshes will see it */
oldmode = workRP.DrawMode;
oldmask = workRP.Mask;
SetDrMd(&workRP,COMPLEMENT);
SafeSetWriteMask(&workRP,0x3);
RectFill(&workRP,
1, top,
regWidth-2,top + height );
WaitBlit();
SetDrMd(&workRP,oldmode);
SafeSetWriteMask(&workRP,oldmask);
/* remember this selection for later */
selRow = regTopRow + row;
}
/*************************************************************
* RegDeselect()
*
* clears selection of a row.
*
**************************************************************/
void RegDeselect(BOOL towin)
{
BYTE oldmode, oldmask;
ULONG height,top, row = selRow;
if (selRow == -1) return;
selRow = -1;
/* if not visible, skip graphical rendering */
if (row < regTopRow || row > regTopRow+numRows-1)
return;
/* make zero based */
row -= regTopRow;
height = registerRows[row].height - 2;
top = registerRows[row].rpY + 1;
if (towin) {
oldmode = activeRP->DrawMode;
oldmask = activeRP->Mask;
SetDrMd(activeRP,COMPLEMENT);
SafeSetWriteMask(activeRP,0x3);
RectFill(activeRP,
1+regLeft, top + regTop,
regWidth-2+regLeft,top + height + regTop );
WaitBlit();
SetDrMd(activeRP,oldmode);
SafeSetWriteMask(activeRP,oldmask);
}
oldmode = workRP.DrawMode;
oldmask = workRP.Mask;
SetDrMd(&workRP,COMPLEMENT);
SafeSetWriteMask(&workRP,0x3);
RectFill(&workRP,
1, top,
regWidth-2,top + height );
WaitBlit();
SetDrMd(&workRP,oldmode);
SafeSetWriteMask(&workRP,oldmask);
}
/*************************************************************
* RegFreeAll()
*
* Free up ALL register gadget resources (not linked lists).
* A small attempt is done to do this safely (checks for NULL)
*
**************************************************************/
void RegFreeAll(void)
{
int x;
/* free up arrays */
if (registerRows != NULL) {
FreeVec(registerRows);
}
if (regGrid != NULL) {
FreeVec(regGrid);
}
/*
* workRP stuff
*/
/* free up bitmap */
for (x=0;x<depth;x++)
if (workbuffer.Planes[x] != NULL) {
FreeRaster(workbuffer.Planes[x],regWidth+1,regHeight+1);
}
/* free TmpRas */
if (tmprp != NULL) {
FreeVec(tmprp);
}
/*
* headerRP stuff
*/
/* free up bitmap */
for (x=0;x<depth;x++)
if (headerbuffer.Planes[x] != NULL) {
FreeRaster(headerbuffer.Planes[x],hWidth+1,hHeight+1);
}
/* free TmpRas */
if (headertmprp != NULL) {
FreeVec(headertmprp);
}
/*
* misc
*/
/* free font */
if (regFont != NULL) {
CloseFont(regFont);
}
}
/****************************************************************
* RegHitTest()
*
* Takes a mouse hit and determines what to do.
*
****************************************************************/
BOOL RegHitTest(ULONG Micros, ULONG Seconds, ULONG x, ULONG y)
{
ULONG t,row;
static LONG lastrow = -1;
BOOL retval = FALSE;
static ULONG micros = 0, secs = 0;
/* quick clip of register gadget */
if (x < regLeft || x > regWidth+regLeft ||
y < regTop || y > regHeight+regTop)
return (FALSE);
/* calc row */
y -= regTop;
row = 0;
for (t=0;t<numRows-1;t++) {
if (y > registerRows[t].rpY +registerRows[t].height)
row++;
else break;
}
/* ok, is it a valid row? */
if (row < regValidRows) {
RegSelect(row, TRUE);
RegEditDisable(FALSE);
if (DoubleClick(secs,micros,Seconds,Micros) && lastrow == row)
retval = TRUE;
}
micros = Micros;
secs = Seconds;
lastrow = row;
AmiMoveSwap();
return (retval);
}
/****************************************************************
* RegClearGrid()
*
* Clears the register and then draws the grid.
*
*****************************************************************/
void RegClearGrid()
{
/*SetAPen(&workRP,DETAILPEN);*/
/* fill area with color */
/*
RectFill(&workRP,0,0,regWidth,regHeight);
*/
SetRast(&workRP,DETAILPEN);
/* draw register grid */
RegRenderGrid();
}
/**************************************************************
* RegScrollSetup()
*
* Sets the scroller correctly
***************************************************************/
void RegScrollSetup(ULONG top,ULONG total,ULONG visible)
{
GF_SetGadgetAttrs(gui,AC_MainSpecs[GID_REGVSCROL]->gs_Gadget,
GTSC_Top,top,
GTSC_Total, total,
GTSC_Visible,visible,
TAG_DONE);
}
/************************************************************
* RegInsertEntry()
*
* Add entry to list
*************************************************************/
void RegInsertEntry(UWORD row, filterNode *en)
{
entryCount++;
if (regValidRows < numRows) {
if (regTopNode == NULL)
regTopNode = en;
regValidRows++;
}
if (row >= regTopRow && row < regTopRow+regValidRows) {
RegMoveList(&filtered,regTopRow);
RegRefresh(FALSE);
}
RegScrollSetup(regTopRow,entryCount,regValidRows);
RegEditDisable(TRUE);
}
/************************************************************
* RegAddEntry()
*
* Add entry to list
*************************************************************/
void RegAddEntry(filterNode *en)
{
entryCount++;
if (regValidRows < numRows) {
RegDeselect(TRUE);
if (regTopNode == NULL)
regTopNode = en;
regValidRows++;
RegFillRow(en,regValidRows-1);
}
else {
/* remove curr selection */
selRow = -1;
RegMoveList(&filtered,entryCount-regValidRows);
RegRefresh(FALSE);
}
RegScrollSetup(regTopRow,entryCount,regValidRows);
RegRefresh(FALSE);
RegEditDisable(TRUE);
}
/************************************************************
* RegKeyScroll()
*
* scrolls selected item on keyboard commands
*************************************************************/
void RegKeyScroll(UWORD code)
{
ULONG currRow;
if (entryCount == 0)
return;
/* is the selected area off screen? */
if (selRow != -1 && (selRow < regTopRow || selRow >= regTopRow+numRows) ) {
RegMoveToSel(&filtered);
}
currRow = selRow;
switch (code) {
case UP:
if (currRow == 0)
return;
/* are we not selected? */
if (currRow == -1)
currRow = regTopRow+1;
if (currRow == regTopRow) {
selRow = -1;
RegScrollListDown();
RegRefresh(FALSE);
}
else RegDeselect(TRUE);
currRow--;
RegSelect(currRow-regTopRow, TRUE);
break;
case SHIFTUP:
/* is there a current selection? */
if (currRow == -1) {
RegSelect(0,TRUE);
}
/* are we already near the top? */
else if (regTopRow < regValidRows) {
if (regTopRow == 0)
RegDeselect(TRUE);
else selRow = -1;
RegMoveList(&filtered,0);
RegRefresh(FALSE);
RegSelect(0, TRUE);
}
/* then just scroll there */
else {
selRow = -1;
currRow -= regTopRow;
RegMoveList(&filtered,regTopRow-regValidRows+1);
RegRefresh(FALSE);
RegSelect(currRow, TRUE);
}
break;
case CTRLUP:
if (currRow == 0)
return;
/* remove current selection */
if (regTopRow == 0)
RegDeselect(TRUE);
else {
selRow = -1;
RegMoveList(&filtered,0);
RegRefresh(FALSE);
}
/* grab top */
RegSelect(0, TRUE);
break;
case DOWN:
if (currRow == entryCount-1) {
return;
}
/* are we selected? */
if (currRow == -1) {
currRow = regTopRow-1;
}
/* scroll down or jump down */
if (currRow == regTopRow + regValidRows - 1) {
selRow = -1;
RegScrollListUp();
RegRefresh(FALSE);
}
else {
RegDeselect(TRUE);
}
WaitBlit();
currRow++;
RegSelect(currRow-regTopRow, TRUE);
break;
case SHIFTDOWN:
/* is there a current selection? */
if (currRow == -1) {
RegSelect(0, TRUE);
}
/* are there not enough entries to page down? */
else if (entryCount - (regTopRow + regValidRows-1) <= regValidRows) {
if (regTopRow == entryCount-regValidRows)
RegDeselect(TRUE);
else selRow = -1;
RegMoveList(&filtered,entryCount-regValidRows);
RegRefresh(FALSE);
RegSelect(regValidRows-1, TRUE);
}
/* just scroll there */
else {
selRow = -1;
currRow -= regTopRow;
RegMoveList(&filtered,regTopRow+regValidRows-1);
RegRefresh(FALSE);
RegSelect(currRow, TRUE);
}
break;
case CTRLDOWN:
if (selRow == entryCount-1)
return;
/* remove curr selection */
if (regTopRow == entryCount - regValidRows)
RegDeselect(TRUE);
else {
selRow = -1;
/*RegMoveList(&filtered,entryCount-regValidRows); */
RegLastPage();
RegRefresh(FALSE);
}
/* grab bottom */
RegSelect(regValidRows-1, TRUE);
break;
}
RegScrollSetup(regTopRow, entryCount, regValidRows);
RegEditDisable(FALSE);
}
/************************************************************
* void RegEditDisable()
*
* Enable/disable the edit gadget
*************************************************************/
void RegEditDisable(BOOL ok)
{
/*
if (editDisable != ok)
AmiDisableSel(ok);
editDisable = ok;
}
*/
AmiDisableSel(ok);
}
/************************************************************
* RegRedrawRow()
*
* Updates alternate row
*************************************************************/
void RegRedrawRow(filterNode *en)
{
ULONG height,top,row;
UBYTE oldmode, oldmask;
row = DataFindNode((struct List *)&filtered,(struct Node *)en);
if (row < regTopRow || row >= regTopRow + numRows)
return;
row -= regTopRow;
height = registerRows[row].height - 2;
top = registerRows[row].rpY + 1;
SetAPen(&workRP,DETAILPEN);
/* erase row */
RectFill(&workRP,
1, top,
regWidth-2,top + height );
WaitBlit();
/* fill in the row */
RegFillRow(en,row);
/* now redraw the grid */
RegRenderGrid();
/* now select locally */
oldmode = workRP.DrawMode;
oldmask = workRP.Mask;
/* update display */
RegRefresh(FALSE);
}
/************************************************************
* RegRedrawSel()
*
* Updates the selected row
*************************************************************/
void RegRedrawSel(filterNode *fn)
{
int x;
ULONG height,top,row;
UBYTE oldmode, oldmask;
row = selRow-regTopRow;
height = registerRows[row].height - 2;
top = registerRows[row].rpY + 1;
SetAPen(&workRP,DETAILPEN);
/* erase row */
RectFill(&workRP,
1, top,
regWidth-2,top + height );
WaitBlit();
/* fill in the row */
for (x=0;x<4;x++)
fn->printChars[x]= -1;
RegFillRow(fn,row);
/* now redraw the grid */
RegRenderGrid();
/* now select locally */
oldmode = workRP.DrawMode;
oldmask = workRP.Mask;
SetDrMd(&workRP,COMPLEMENT);
SafeSetWriteMask(&workRP,0x3);
RectFill(&workRP,
1, top,
regWidth-2,top + height );
SetDrMd(&workRP,oldmode);
SafeSetWriteMask(&workRP,oldmask);
/* update display */
RegRefresh(FALSE);
}
/************************************************************
* RegMoveList()
*
* Moves visible list area to new top
*************************************************************/
void RegMoveList(struct MinList *filters, UWORD top)
{
ULONG x, row;
filterNode *ft = (filterNode *)filters->mlh_Head;
/* empty list? */
if (filters->mlh_TailPred == filters) {
RegClearGrid();
RegRenderGrid();
return;
}
#if 0
/* are we already there? */
if (top == regTopRow)
return;
#endif
if (top > entryCount - regValidRows) {
/*printf("WHOA! top = %d\n",top);*/
return;
}
/* deselect item */
row = selRow;
selRow = -1;
/* obtain new top */
for (x=0;x<top;x++)
ft = (filterNode *)ft->node.mln_Succ;
regTopRow = top;
regTopNode = ft;
/* now render */
RegClearGrid();
for (x=0;x<regValidRows; x++) {
RegFillRow(ft,x);
ft = (filterNode *)ft->node.mln_Succ;
}
RegRenderGrid();
/* select item again*/
if (row >= regTopRow && row <= regTopRow + regValidRows-1) {
/*printf("selecting!\n");*/
RegSelect(row-regTopRow, FALSE);
}
else selRow = row;
}
/************************************************************
* RegScrollListUp()
*
* quick move of register up by size of one row
*************************************************************/
void RegScrollListUp(void)
{
WORD x;
filterNode *filt;
regTopRow++;
filt=regTopNode = (filterNode *)regTopNode->node.mln_Succ;
RegClearGrid();
for (x=0;x < regValidRows; x++) {
RegFillRow(filt,x);
WaitBlit();
filt = (filterNode *)filt->node.mln_Succ;
}
RegRenderGrid();
}
/************************************************************
* RegScrollListDown()
*
* Quick scrolling of window down one
*************************************************************/
void RegScrollListDown(void)
{
WORD x;
filterNode *filt;
/* are we at the top? */
if (regTopRow == 0)
return;
regTopRow--;
filt=regTopNode = (filterNode *)regTopNode->node.mln_Pred;
/* render */
RegClearGrid();
for (x=0;x <regValidRows; x++) {
RegFillRow(filt,x);
filt = (filterNode *)filt->node.mln_Succ;
}
RegRenderGrid();
}
/************************************************************
* RegFillRow()
*
* Fill row with node data
*************************************************************/
void RegFillRow(filterNode *fn, WORD row)
{
entryNode *en = fn->entry;
char checktype[CHECKSIZE];
char datestr[DATESIZE];
char amntstr[AMNTSIZE];
char textpen;
long tempprint = -1;;
/* now assumes row is blank */
if (en->flags & VOIDED)
textpen = SHINEPEN;
else textpen = BLOCKPEN;
/* fill in type */
if (en->type != CHECKTYPE)
RegRenderCell(row,0,regTypeArray[en->type],textpen,®PrintChars[en->type],FALSE);
else {
sprintf(checktype,"%06d",en->check);
RegRenderCell(row,0,checktype,textpen, &fn->printChars[0],FALSE);
}
/* fill in date */
DataBuildRegDate(&en->date,datestr);
RegRenderCell(row,1,datestr,textpen, &fn->printChars[1],FALSE);
/* fill in name */
RegRenderCell(row,2,en->name,textpen, &fn->printChars[2],FALSE);
/* memo? */
if (showMemo)
RegRenderCell(row,2,en->memo,textpen,&tempprint,TRUE);
/* voided? */
if (en->flags & VOIDED)
RegRenderCell(row,3,"V", textpen, ®PrintFlags[0],FALSE);
/* Cleared/tax deductible?? */
if (en->flags & CLEARED)
RegRenderCell(row,4,"C",textpen, ®PrintFlags[1],FALSE);
if (en->flags & TAXDEDUCT)
RegRenderCell(row,5,"T",textpen, ®PrintFlags[2],FALSE);
/* amount? */
DataBuildAmnt(TRUE, &en->amount,amntstr);
if (en->type == DEPOSITTYPE && !(en->flags & VOIDED) )
textpen=TEXTPEN;
/* right justify this val */
RegRenderCellFlush(row,6,amntstr,textpen, &fn->printChars[3]);
WaitBlit();
}
/********************************************************
* RegLastPage()
*
* Shows last page of register
*********************************************************/
void RegLastPage(void)
{
WORD x;
filterNode *filt;
#if 0
/* test to see if we have too few entries */
if (entryCount <= regValidRows) {
RegMoveList(&filtered,0);
return;
}
#endif
/* clear display */
RegClearGrid();
/* work from bottom */
if (filtered.mlh_TailPred != &filtered) {
filt = (filterNode *)filtered.mlh_TailPred;
for (x=regValidRows;x > 0; x--) {
RegFillRow(filt,x-1);
regTopNode = filt;
filt = (filterNode *)filt->node.mln_Pred;
}
regTopRow = entryCount - regValidRows;
}
RegRenderGrid();
}
/********************************************************
* RegRemoveSel()
*
* Remove the filter entry of selected row,
* redraw register
*********************************************************/
void RegRemoveSel(void)
{
/*entryCount--;*/
if (entryCount < regValidRows) {
regValidRows--;
selRow = -1;
RegLastPage();
}
else {
/* should we not move up? */
if (regTopRow + regValidRows > entryCount)
regTopRow--;
selRow = -1;
RegMoveList(&filtered,regTopRow);
}
RegRefresh(FALSE);
RegScrollSetup(regTopRow, entryCount, regValidRows);
RegEditDisable(TRUE);
}
/********************************************************
* RegNewFilter()
*
* Resets the filter in the register
*********************************************************/
void RegNewFilter(void)
{
selRow = -1;
regTopRow = 0;
if (entryCount < numRows)
regValidRows = entryCount;
else regValidRows = numRows;
RegLastPage();
RegRefresh(FALSE);
RegEditDisable(TRUE);
RegScrollSetup(regTopRow, entryCount, regValidRows);
}
/*********************************************************
* RegResetOffsets()
*
* Reset the printlength offsets
**********************************************************/
void RegResetOffsets(int type)
{
filterNode *filt = NULL;
while ( (filt = (filterNode *)DataGetNext((struct List *)&filtered,
(struct Node *)filt)) != NULL) {
filt->printChars[type] = -1;
}
}
/*********************************************************
* RegRedrawFilter()
*
* Resets filter, but maintains selected state if needed
**********************************************************/
void RegRedrawFilter(ULONG filtentries)
{
/* handle any unexpected new entries too */
if (filtentries > 0) {
entryCount += filtentries;
if (regValidRows < numRows) {
if (numRows-regValidRows <= filtentries)
regValidRows = numRows;
else regValidRows += filtentries;
}
}
if (selRow != -1)
RegMoveToSel(&filtered);
else RegNewFilter();
}
/************************************************************
* RegMoveToSel()
*
* Moves visible list area to show selected item in center
*************************************************************/
void RegMoveToSel(struct MinList *filters)
{
ULONG top;
/* empty list? */
if (filters->mlh_TailPred == filters) {
RegClearGrid();
RegRenderGrid();
return;
}
if (selRow == -1)
return;
/* calculate new top */
if (selRow < numRows)
top = 0; /* on first page */
else if (selRow > entryCount - numRows)
top = entryCount - numRows; /* on last page */
else if (selRow >= regTopRow && selRow < regTopRow+numRows)
top = regTopRow;
else top = selRow - numRows/2; /* put sel in middle */
RegMoveList(filters,top);
RegScrollSetup(regTopRow, entryCount, regValidRows);
RegRefresh(FALSE);
}