home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Utilities / amiCheck / Source / regGadget.c < prev    next >
C/C++ Source or Header  |  1998-06-11  |  36KB  |  1,601 lines

  1. /***************************************************************
  2. * regGadget.c 
  3. *
  4. * Creates and maintains the custom register display gadget
  5. *
  6. ***************************************************************/
  7.  
  8. #include <strings.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <libraries/guifront.h>
  12. #include <intuition/gadgetclass.h>
  13. #include <exec/memory.h>
  14. #include <clib/graphics_protos.h>
  15. #include <clib/exec_protos.h>
  16. #include <clib/diskfont_protos.h>
  17. #include <intuition/screens.h>
  18. #include <clib/intuition_protos.h>
  19. #include <graphics/gfxmacros.h> 
  20. #include <graphics/gfxbase.h>
  21.  
  22. #include "amiCheck.h"
  23. #include "mainPanel.h"
  24. #include "regGadget.h"
  25. #include "dataBase.h"
  26.  
  27. extern struct GfxBase *GfxBase;
  28.  
  29. #define WaitBlit();
  30.  
  31. #define RTEST(x)        {if ((x)==FALSE) return FALSE;}
  32.  
  33. #define AREA_SIZE       200
  34. #define NUMCOLS         7
  35. #define COLBUFFER       4       /* pixels on either side */
  36.  
  37. /*
  38.  * globals and typedefs
  39.  */
  40. BOOL editDisable = TRUE;
  41.  
  42. /* typedef for register row */
  43. typedef struct {
  44.         ULONG rpY;      /* start of row */
  45.         ULONG height;   /* height of row */ 
  46.         ULONG fontY;    /* distance from top for text */
  47. } regRowType;
  48.  
  49. /* typedef for register column */
  50. typedef struct {
  51.         ULONG rpX;      /* start of column */
  52.         ULONG width;    /* width of column */
  53.         ULONG fontX;    /* distance from start for text */
  54. } regColType;
  55.  
  56. /* typedef for register cell */
  57. typedef struct {
  58.         regRowType              *cellRow;
  59.         regColType              *cellCol;
  60. } regCellType;
  61.  
  62. /* tool to index regGrid */
  63. #define REGGRID(r,c)   regGrid[(r)*numCols + (c)]
  64.  
  65.  
  66. regColType  registerCols[NUMCOLS];
  67. regRowType  *registerRows = NULL;
  68. regCellType *regGrid = NULL;
  69. filterNode  *regTopNode = NULL;
  70.  
  71. char *regTypeArray[3] = {
  72.     "Check",
  73.     "Withdrawal",
  74.     "Deposit",
  75. };
  76. long regPrintChars[3];
  77. long regPrintFlags[3];
  78.  
  79. /* vars for our geometry */
  80. ULONG regWidth, regHeight;
  81. ULONG regTop, regLeft;
  82. ULONG numRows;               /* number of items that fit */
  83. ULONG numCols = NUMCOLS;
  84. ULONG entryHeight;           /* pixels of entry */
  85. ULONG depth;
  86.  
  87. extern GadgetSpec gadgetspecs[]; 
  88.  
  89. /* vars for our working RP */
  90. struct RastPort workRP, *activeRP = NULL;
  91. chip struct BitMap   workbuffer;
  92. chip struct AreaInfo workarea;
  93. chip struct TmpRas   worktmp;
  94. chip void *tmprp = NULL;
  95. chip UWORD areaBuffer[AREA_SIZE];
  96.  
  97. /* vars for our header RP */
  98. struct RastPort headerRP;
  99. chip struct BitMap   headerbuffer;
  100. chip struct AreaInfo headerarea;
  101. chip struct TmpRas   headertmp;
  102. chip void *headertmprp = NULL;
  103. chip UWORD headerareaBuffer[AREA_SIZE];
  104. ULONG hWidth,hHeight,hTop,hLeft;
  105.  
  106. /* vars for our FONT */
  107. struct TextFont *regFont = NULL;
  108.  
  109. /* misc control vars */
  110. ULONG selRow = -1;      /* selected row */
  111. ULONG regValidRows;        /* number of valid rows from top */
  112. ULONG regTopRow;
  113.  
  114. /* lets remember the register window! */
  115. struct Window *guiWindow = NULL;
  116.  
  117. /* special register config var */
  118. BOOL showMemo = FALSE;
  119.  
  120. /*
  121.  * Configurations!
  122.  */
  123.  
  124. /* headers for register */
  125. char *headers[] = {
  126.         "Type",
  127.         "Date",
  128.         "Description",
  129.         "V",
  130.         "C",
  131.     "T",
  132.         "$ Amount",
  133. };
  134.  
  135.  
  136. /* 
  137.  * local prototypes 
  138.  */
  139. BOOL RegRPInit(void);
  140. BOOL RegLayout(void);
  141. BOOL RegAllocHeader(void);
  142. void RegRenderGrid(void);
  143. void RegRenderHeader(void);
  144.  
  145. void RegDeselect(BOOL);
  146. void RegScrollSetup(ULONG,ULONG,ULONG);
  147. void RegFillRow(filterNode *, WORD);
  148. void RegScrollListUp(void);
  149. void RegLastPage(void);
  150.  
  151. /*
  152.  * routines
  153.  */
  154.  
  155. /*************************************************************
  156. * RegSwapMemo()
  157. *
  158. *    Swaps memo in register
  159. **************************************************************/
  160. void RegSwapMemo(void)
  161. {
  162.  long entries, lastselRow, lasttop;
  163.  
  164.  /* preserve some globals */
  165.  lasttop = regTopRow;
  166.  lastselRow = selRow;
  167.  entries = entryCount;
  168.  
  169.  AmiLock();
  170.   if (showMemo)
  171.     showMemo = FALSE;
  172.  else    showMemo = TRUE;
  173.  
  174.  /* free up arrays */
  175.  if (registerRows != NULL) {
  176.         FreeVec(registerRows);
  177.  }
  178.  
  179.  if (regGrid != NULL) {
  180.         FreeVec(regGrid);
  181.  }
  182.         
  183.  RegLayout();
  184.  
  185.  entryCount = entries;
  186.  if (entryCount > numRows)
  187.     regValidRows = numRows;
  188.  else    regValidRows = entryCount;
  189.  
  190.  RegClearGrid();
  191.  
  192.  selRow = lastselRow;
  193.  if (entryCount > numRows && entryCount-lasttop < regValidRows)
  194.     lasttop = entryCount - regValidRows;
  195.  
  196.  if (selRow != -1)
  197.     RegMoveToSel(&filtered);
  198.  else    RegMoveList(&filtered,lasttop);
  199.  
  200.  RegRefresh(FALSE);
  201.  RegScrollSetup(regTopRow,entryCount,regValidRows);
  202.  AmiUnlock();
  203. }
  204.  
  205. /**************************************************************
  206. * RegInit()
  207. *
  208. * Initialize the register gadget
  209. *
  210. **************************************************************/
  211. BOOL RegInit(void)
  212. {
  213. int x;
  214.  
  215.  /* build structures */       
  216.  RTEST(RegRPInit());
  217.  RTEST(RegLayout());
  218.  RTEST(RegAllocHeader());
  219.  
  220.  /* create default imagery */
  221.  RegRenderHeader();
  222.  RegClearGrid();
  223.  
  224.  /* set up scroller */
  225.  RegScrollSetup(0,0,0);
  226.  regTopRow = regValidRows = 0;
  227.  
  228.  RegRefresh(TRUE);
  229.  
  230.  for (x=0;x<3;x++) {
  231.     regPrintFlags[x] = regPrintChars[x] = -1;
  232.  }
  233.       
  234.  return (TRUE);    
  235.  
  236. /**************************************************************
  237. * RegAllocHeader()
  238. *
  239. *       Allocates RP and BitMap for header.  Must be done
  240. *       _after_ reglayout() has selected and opened the font.
  241. *
  242. ***************************************************************/
  243. BOOL RegAllocHeader(void)
  244. {
  245.  ULONG x;
  246.  
  247.  hTop = AC_MainSpecs[GID_REGHEADER]->gs_Gadget->TopEdge + 1;
  248.  hLeft = AC_MainSpecs[GID_REGHEADER]->gs_Gadget->LeftEdge + 2;
  249.  hWidth =  AC_MainSpecs[GID_REGHEADER]->gs_Gadget->Width - 4;
  250.  hHeight=  AC_MainSpecs[GID_REGHEADER]->gs_Gadget->Height - 2;
  251.  
  252.  /* create bitmap */
  253.  InitBitMap(&headerbuffer,depth, hWidth,hHeight);
  254.  
  255.  for (x=0;x<depth;x++) {
  256.         headerbuffer.Planes[x] = (PLANEPTR)AllocRaster(hWidth+1,hHeight+1);
  257.         if (headerbuffer.Planes[x] == NULL) return (FALSE);
  258.  }
  259.  
  260.  /* create area buffer */
  261.  for (x=0;x<AREA_SIZE;x++) headerareaBuffer[x] =0;
  262.  InitArea(&headerarea, headerareaBuffer, (AREA_SIZE*2)/5);
  263.  
  264.  /* create TmpRas */
  265.  headertmprp =  (void *)AllocVec((hWidth+1)*(hHeight+1), MEMF_CHIP);
  266.  if (headertmprp == NULL) return (FALSE);
  267.  
  268.  InitTmpRas(&headertmp,headertmprp,(hWidth+1)*(hHeight+1));
  269.  
  270.  /* link in to our work rastport */
  271.  InitRastPort(&headerRP);
  272.  headerRP.BitMap = &headerbuffer;
  273.  headerRP.AreaInfo = &headerarea;
  274.  headerRP.TmpRas = &headertmp;
  275.  headerRP.Layer = NULL;
  276.  
  277.  /* initialize our pen colors */
  278.  SetAPen(&headerRP,DETAILPEN);
  279.   
  280.  /* fill area with color */
  281.  SetRast(&headerRP,DETAILPEN);
  282. /*
  283.  RectFill(&headerRP,0,0,hWidth,hHeight);
  284. */
  285.  
  286.  SetFont(&headerRP,regFont);
  287.          
  288.  return (TRUE);
  289. }
  290.  
  291. /**************************************************************
  292. * RegRenderHeader()
  293. *
  294. *       Renders the header titles above the register
  295. *
  296. ***************************************************************/
  297. void RegRenderHeader(void)
  298. {
  299.  ULONG x, top;
  300.  
  301.  /* set pen color */
  302.  SetAPen(&headerRP,BLOCKPEN);
  303.  
  304.  top = regFont->tf_Baseline;
  305.    
  306.  if (regFont->tf_YSize <= hHeight) {
  307.      for (x=0;x<numCols;x++) {
  308.                Move(&headerRP,REGGRID(0,x).cellCol->rpX + COLBUFFER,top);
  309.         Text(&headerRP,headers[x],strlen(headers[x]));
  310.      }
  311.  }
  312.  
  313. }
  314.  
  315. /**************************************************************
  316. * RegRPInit()
  317. *
  318. * initialize our playground 
  319. *
  320. **************************************************************/
  321. BOOL RegRPInit()
  322. {
  323. UWORD x;
  324.  
  325.  /* define geometry (-2 accounts for shadowing border) */
  326.  regWidth =  AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Width - 4;
  327.  regHeight=  AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Height - 2;
  328.  regTop   =  AC_MainSpecs[GID_REGFIELD]->gs_Gadget->TopEdge + 1;
  329.  regLeft  =  AC_MainSpecs[GID_REGFIELD]->gs_Gadget->LeftEdge + 2;
  330.  
  331.  /* the one and only delicate hack of our program */
  332.  AC_MainSpecs[GID_REGFIELD]->gs_Gadget->Activation |= GACT_IMMEDIATE;
  333.  
  334.  /* 
  335.   * extract information about our main window 
  336.   */
  337.  
  338.    
  339.  GF_GetGUIAttr(gui, GUI_Window, &guiWindow, TAG_DONE);
  340.  
  341.  activeRP = guiWindow->RPort;
  342.  depth = activeRP->BitMap->Depth;  
  343.             
  344.  /* 
  345.   * create working rast port area 
  346.   */
  347.  
  348.  /* create bitmap */
  349.  InitBitMap(&workbuffer,depth, regWidth, regHeight);
  350.  
  351.  for (x=0;x<depth;x++) {
  352.         workbuffer.Planes[x] = (PLANEPTR)AllocRaster(regWidth+1, 
  353.                                         regHeight+1);
  354.         if (workbuffer.Planes[x] == NULL) return (FALSE);
  355.  }
  356.  
  357.  /* create area buffer */
  358.  for (x=0;x<AREA_SIZE;x++) areaBuffer[x] =0;
  359.  InitArea(&workarea, areaBuffer, (AREA_SIZE*2)/5);
  360.  
  361.  /* create TmpRas */
  362.  tmprp = (void *)AllocVec((regWidth+1)*(regHeight+1), MEMF_CHIP);
  363.  if (tmprp == NULL) return (FALSE);
  364.  
  365.  InitTmpRas(&worktmp,tmprp,(regWidth+1)*(regHeight+1));
  366.  
  367.  /* link in to our work rastport */
  368.  InitRastPort(&workRP);
  369.  workRP.BitMap = &workbuffer;
  370.  workRP.AreaInfo = &workarea;
  371.  workRP.TmpRas = &worktmp;
  372.  workRP.Layer = NULL;
  373.  
  374.  return (TRUE);
  375. }
  376.  
  377. /*************************************************************
  378. * RegLayout()
  379. *
  380. * calculates the number of possible entries, the starting
  381. * position of each item.
  382. *
  383. **************************************************************/
  384. BOOL RegLayout(void)
  385. {
  386. struct TextAttr regAttr;
  387. UWORD regFontHeight;
  388. #if 0
  389. char regFontName[50];
  390. BOOL regScreen;
  391. #endif
  392. ULONG height;
  393. int x,temp,desc;
  394. char *colFixes[NUMCOLS] = {
  395.         "Withdrawal",
  396.         "DEC000000", 
  397.         "",
  398.         "V",
  399.         "C",
  400.     "T",
  401.         "000000000.00",
  402. };
  403.  
  404.  
  405.  GF_GetGUIAttr(gui,
  406.         GUI_ActualFont,®Attr,
  407.         TAG_DONE);
  408.         
  409.  
  410. #if 0
  411.  /* grab information from guifront on fonts */
  412.  GF_GetPrefsAttr(gui,
  413.         PRF_GadgetScreenFont,®Attr,
  414.         TAG_DONE);
  415.         
  416.  /* are we using the screen font? */
  417.  if (regScreen)
  418.         regAttr = guiWindow->WScreen->Font;
  419.  else {
  420.         if ( GF_GetPrefsAttr(gui,
  421.                 PRF_GadgetFontYSize, ®FontHeight,
  422.                 PRF_GadgetFontName,  regFontName,
  423.                 TAG_DONE) != 2) {
  424.  
  425.         regAttr = guiWindow->WScreen->Font;
  426.     }
  427.     else  regAttr = guiWindow->WScreen->Font;
  428.  }
  429.  
  430. #endif
  431.  
  432.  /* at last, open the damn thing */
  433.  regFont = OpenDiskFont(®Attr);
  434.  if (regFont == NULL) return (FALSE);
  435.  
  436.  SetFont(&workRP,regFont);  
  437.  
  438.  /* calculate entry separators */
  439.  height = regFont->tf_YSize + regFont->tf_YSize/8 + 1;
  440.  /* * * * */  
  441.  if (showMemo) height *= 2;
  442.  
  443.  numRows = regHeight/height;
  444.  
  445.  /* tweek height to absorb excess space - numRows is same */
  446.  entryHeight = height + (regHeight%height)/numRows;
  447.  temp = regHeight%entryHeight;
  448.  
  449.  /* install rows */
  450.  registerRows =  (regRowType *)AllocVec(sizeof(regRowType)*numRows,
  451.                                         MEMF_ANY); 
  452.  if (registerRows == NULL) return (FALSE);
  453.  
  454.  height = (entryHeight / 2) - (regFont->tf_YSize/2) +
  455.            regFont->tf_Baseline;
  456.  
  457.  
  458. #if 0
  459.  registerRows[0].fontY = height + 1;
  460.  registerRows[0].rpY = 0; /*entryHeight + ((temp>0)?1:0);*/
  461.  registerRows[0].height = entryHeight + ((temp>0)?1:0);
  462.  
  463.  for (x=1;x<numRows;x++) {
  464.     
  465.            registerRows[x].fontY = height + 1;
  466.     registerRows[x].height = entryHeight + ((x<temp)?1:0);
  467.         registerRows[x].rpY = registerRows[x-1].rpY + registerRows[x-1].height;
  468.  }
  469.  
  470. #endif
  471.  registerRows[0].fontY = height + 1;
  472.  registerRows[0].rpY = 0;
  473.  registerRows[0].height = entryHeight; /* should never get extra line... cest la vi! */
  474.  
  475.  for (x=1;x<numRows;x++) {
  476.     
  477.            registerRows[x].fontY = height + 1;
  478.     registerRows[x].height = entryHeight + ( (x > numRows-temp )?1:0);
  479.         registerRows[x].rpY = registerRows[x-1].rpY + registerRows[x-1].height;
  480.  }
  481.  
  482.  /* install cols */
  483.  temp = desc = 0;
  484.  for (x=0;x<numCols;x++) {
  485.         registerCols[x].fontX = COLBUFFER;
  486.         if (x == 0) registerCols[x].rpX = 0;
  487.         else        registerCols[x].rpX = registerCols[x-1].rpX +
  488.                                           registerCols[x-1].width + 1;
  489.  
  490.         /* need to give description all extra space */
  491.         if (strlen(colFixes[x]) == 0) {
  492.         desc = x;
  493.         registerCols[x].width = 0;
  494.     }
  495.         else {
  496.                 registerCols[x].width = TextLength(&workRP,
  497.                                    colFixes[x],strlen(colFixes[x])) +
  498.                                 COLBUFFER*2 ;
  499.                                 
  500.                 temp += registerCols[x].width;
  501.         }                             
  502.  }  
  503.  
  504.  /* now fix for description list */
  505.  registerCols[desc].width = regWidth - temp;
  506.  for (x=desc+1;x<numCols;x++) {
  507.         registerCols[x].rpX += registerCols[desc].width; 
  508.  }
  509.  
  510.  /* now build the cell grid */
  511.  regGrid = (regCellType *)AllocVec(sizeof(regCellType)*numCols*numRows,
  512.                                MEMF_ANY);
  513.  if (regGrid == NULL) return (FALSE);
  514.  
  515.  for (x=0;x<numRows;x++) {
  516.         for (temp=0;temp<numCols;temp++) {
  517.                 REGGRID(x,temp).cellRow = ®isterRows[x];
  518.                 REGGRID(x,temp).cellCol = ®isterCols[temp];
  519.         }
  520.  }       
  521.  
  522.  return (TRUE);
  523. }
  524.  
  525. /*************************************************************
  526. * RegRenderCellFlush()
  527. *
  528. *    Flush the text (right justify)
  529. **************************************************************/
  530. void RegRenderCellFlush(ULONG row, ULONG col, char *str, char pen,
  531. long *printchars)
  532. {
  533.   ULONG x,y,b, width, length;
  534.   struct TextExtent resultExtent;
  535.   
  536.   /* set pen */
  537.   SetAPen(&workRP,pen);
  538.   
  539.   /* quick pull out some info on cell */
  540.   y = REGGRID(row,col).cellRow->rpY;
  541.   b = REGGRID(row,col).cellRow->fontY;
  542.   x = REGGRID(row,col).cellCol->rpX + REGGRID(row,col).cellCol->fontX;
  543.   width = REGGRID(row,col).cellCol->width - COLBUFFER;
  544.   
  545.   /* clip str to make fit... */
  546.   if (*printchars == -1)
  547.     *printchars = TextFit(&workRP,str,strlen(str),&resultExtent,NULL,1,
  548.         REGGRID(row,col).cellCol->width-(COLBUFFER*3) + 1,
  549.         REGGRID(row,col).cellRow->height );
  550.  
  551.   length = TextLength(&workRP,str,*printchars);
  552.   if (length < width-(COLBUFFER*3)+1)
  553.     x += (width-(COLBUFFER*3)+1) - length;
  554.  
  555.   /* stuf it in */
  556.   Move(&workRP,x,y+b);
  557.   Text(&workRP,str, *printchars);
  558.  
  559.   if (row == numRows-1) {
  560.     SetAPen(&workRP,TEXTPEN);
  561.     Move(&workRP,1,regHeight-1);
  562.     Draw(&workRP,regWidth-1,regHeight-1);
  563.   }
  564. }
  565.  
  566. /*************************************************************
  567. * RegRenderCell()
  568. *
  569. *       Renders string contents into a given cell. Does
  570. *       necessary clipping of the string.
  571. *
  572. ***************************************************************/
  573. void RegRenderCell(ULONG row, ULONG col, char *str, char pen, 
  574. long *printchars, BOOL memo)
  575. {
  576.   ULONG x,y,b, width;
  577.   struct TextExtent resultExtent;
  578.   
  579.   /* set pen */
  580.   SetAPen(&workRP,pen);
  581.  
  582.   /* quick pull out some info on cell */
  583.   y = REGGRID(row,col).cellRow->rpY;
  584.   b = REGGRID(row,col).cellRow->fontY;
  585.   x = REGGRID(row,col).cellCol->rpX + REGGRID(row,col).cellCol->fontX;
  586.   width = REGGRID(row,col).cellCol->width - COLBUFFER;
  587.  
  588.   /* clip str to make fit... */
  589.   if (*printchars == -1) {
  590.     *printchars = TextFit(&workRP,str,strlen(str),&resultExtent,NULL,1,
  591.         REGGRID(row,col).cellCol->width-(COLBUFFER*2) + 1,
  592.         REGGRID(row,col).cellRow->height );
  593.   }
  594.  
  595.   /* special case description/memo stuff */
  596.   if (showMemo == TRUE && col == 2 ) {
  597.     if (memo == FALSE) {
  598.  
  599.  b = (entryHeight / 4) - (regFont->tf_YSize/2) +
  600.            regFont->tf_Baseline;
  601.  
  602. /*        b -= (regFont->tf_YSize/2);*/
  603.     }
  604.     else {
  605.         if (*printchars > strlen(str))
  606.             *printchars = strlen(str);
  607.  
  608.  b = (entryHeight ) - (regFont->tf_YSize/2) + 1 /* -
  609.            regFont->tf_Baseline*/;
  610.  
  611. /*        b  += (regFont->tf_YSize/2);*/
  612.     }
  613.   }
  614.   
  615.   /* stuf it in */
  616.   Move(&workRP,x,y+b);
  617.   Text(&workRP,str,*printchars);
  618.  
  619.   if (row == numRows-1) {
  620.     SetAPen(&workRP,TEXTPEN);
  621.     Move(&workRP,1,regHeight-1);
  622.     Draw(&workRP,regWidth-1,regHeight-1);
  623.   }
  624.  
  625. }
  626.  
  627. /*************************************************************
  628. * RegRenderGrid()
  629. *
  630. * Renders the register grid.  Simple enough...
  631. *
  632. **************************************************************/
  633. void RegRenderGrid(void)
  634. {
  635.  int x;
  636.  
  637.  /* set our pens */
  638.  SetAPen(&workRP,BLOCKPEN);
  639.  
  640.  /* horizontals */ 
  641.  for (x=0;x<numRows;x++) {
  642.         Move(&workRP,0,registerRows[x].rpY);
  643.         Draw(&workRP,regWidth,registerRows[x].rpY);
  644.  
  645.      if (showMemo) {
  646.         SetDrPt(&workRP,0xAAAA);
  647.         Move(&workRP,registerCols[2].rpX,registerRows[x].rpY + entryHeight/2);
  648.             Draw(&workRP,registerCols[3].rpX,registerRows[x].rpY + entryHeight/2);
  649.         SetDrPt(&workRP,~0);
  650.  
  651.         if (x != 0 && x < numRows){
  652.                 Move(&workRP,0,registerRows[x].rpY-1);
  653.                 Draw(&workRP,regWidth,registerRows[x].rpY-1);
  654.         }
  655.  
  656.      }
  657.  }
  658.  
  659.  /* verticals */
  660.  for (x=0;x<numCols;x++) {
  661.         Move(&workRP,registerCols[x].rpX,0);
  662.         Draw(&workRP,registerCols[x].rpX,regHeight);
  663.  }
  664.  
  665.  /* set highlight pen */
  666.  SetAPen(&workRP,TEXTPEN);
  667.  
  668.  /* put depth into our register window */
  669.  Move(&workRP,1,regHeight-1);
  670.  Draw(&workRP,regWidth,regHeight-1);
  671.  Move(&workRP,regWidth-1,1);
  672.  Draw(&workRP,regWidth-1,regHeight);
  673. }
  674.  
  675. /*************************************************************
  676. * RegRefresh()
  677. *
  678. * Blits the work area into the window
  679. *
  680. **************************************************************/
  681. void RegRefresh(BOOL header)
  682. {
  683.  
  684. #if 0  
  685.  /* blit over the working register bitmap into window */
  686.  ClipBlit(&workRP,0,0,activeRP,regLeft,regTop,
  687.         regWidth,regHeight,(ULONG)0xc0);
  688. #endif
  689.  
  690.  
  691. /*
  692. BltBitMapRastPort(workRP.BitMap,0,0,activeRP,regLeft,regTop,
  693.         regWidth,regHeight,0xc0);
  694. WaitBlit();*/
  695.  
  696. ClipBlit(&workRP,0,0,activeRP,regLeft,regTop,regWidth,regHeight,(ULONG)0xc0);
  697.  
  698. if (header) {
  699.     /*
  700.     BltBitMapRastPort(headerRP.BitMap,0,0,activeRP,hLeft,hTop,
  701.             hWidth,hHeight,0xc0);
  702.     WaitBlit();*/
  703.  
  704.     ClipBlit(&headerRP,0,0,activeRP,hLeft,hTop,hWidth,hHeight,(ULONG)0xc0);
  705. }
  706. }
  707.  
  708. /*************************************************************
  709. * RegSelect()
  710. *
  711. *       marks a row as being selected.  
  712. *
  713. **************************************************************/
  714. void RegSelect(ULONG row, BOOL towin)
  715. {
  716. BYTE oldmode, oldmask;
  717. ULONG height, top;
  718.  
  719. /* is it currently selected? */
  720. if (selRow == regTopRow + row) return;
  721.  
  722. /* remove old one */
  723. RegDeselect(towin);
  724.  
  725. height = registerRows[row].height - 2;
  726. top = registerRows[row].rpY + 1;
  727.  
  728. /* render it to the actual window first (avoids flicker later) */ 
  729. if (towin) {
  730.     oldmode = activeRP->DrawMode;
  731.     oldmask = activeRP->Mask;
  732.     SetDrMd(activeRP,COMPLEMENT);
  733.     SafeSetWriteMask(activeRP,0x3);
  734.  
  735.     RectFill(activeRP,
  736.             1 + regLeft, top + regTop,
  737.             regWidth - 2 + regLeft,top + height + regTop );
  738.  
  739.     WaitBlit();
  740.  
  741.     SetDrMd(activeRP,oldmode);
  742.     SafeSetWriteMask(activeRP,oldmask);
  743. }
  744.  
  745. /* now render it "for real" so refreshes will see it */
  746. oldmode = workRP.DrawMode;
  747. oldmask = workRP.Mask;
  748. SetDrMd(&workRP,COMPLEMENT);
  749. SafeSetWriteMask(&workRP,0x3);
  750.  
  751. RectFill(&workRP,
  752.         1, top,
  753.         regWidth-2,top + height );
  754.  
  755. WaitBlit();
  756.  
  757. SetDrMd(&workRP,oldmode);
  758. SafeSetWriteMask(&workRP,oldmask);
  759.  
  760. /* remember this selection for later */
  761. selRow = regTopRow + row;
  762. }
  763.  
  764. /*************************************************************
  765. * RegDeselect()
  766. *
  767. *       clears selection of a row.
  768. *
  769. **************************************************************/
  770. void RegDeselect(BOOL towin)
  771. {
  772.  BYTE oldmode, oldmask;
  773.  ULONG height,top, row = selRow;
  774.  
  775.  if (selRow == -1) return;
  776.  selRow = -1;
  777.  
  778.  /* if not visible, skip graphical rendering */
  779.  if (row < regTopRow || row > regTopRow+numRows-1)
  780.         return; 
  781.  
  782.  /* make zero based */
  783.  row -= regTopRow; 
  784.  
  785.  height = registerRows[row].height - 2;
  786.  top = registerRows[row].rpY + 1;
  787.  
  788.  if (towin) {
  789.      oldmode = activeRP->DrawMode;
  790.      oldmask = activeRP->Mask;
  791.     SetDrMd(activeRP,COMPLEMENT);
  792.      SafeSetWriteMask(activeRP,0x3);
  793.  
  794.      RectFill(activeRP,
  795.             1+regLeft, top + regTop,
  796.             regWidth-2+regLeft,top + height + regTop );
  797.  
  798.      WaitBlit();
  799.  
  800.      SetDrMd(activeRP,oldmode);
  801.      SafeSetWriteMask(activeRP,oldmask);
  802.  }
  803.  
  804.  oldmode = workRP.DrawMode;
  805.  oldmask = workRP.Mask;
  806.  SetDrMd(&workRP,COMPLEMENT);
  807.  SafeSetWriteMask(&workRP,0x3);
  808.  
  809.  RectFill(&workRP,
  810.         1,  top,
  811.         regWidth-2,top + height );
  812.  
  813.  WaitBlit();
  814.  
  815.  SetDrMd(&workRP,oldmode);
  816.  SafeSetWriteMask(&workRP,oldmask);         
  817. }
  818.  
  819. /*************************************************************
  820. * RegFreeAll()
  821. *
  822. * Free up ALL register gadget resources (not linked lists).
  823. * A small attempt is done to do this safely (checks for NULL)
  824. *
  825. **************************************************************/
  826. void RegFreeAll(void)
  827. {
  828. int x;
  829.  
  830.  /* free up arrays */
  831.  if (registerRows != NULL) {
  832.         FreeVec(registerRows);
  833.  }
  834.         
  835.  if (regGrid != NULL) {
  836.         FreeVec(regGrid);
  837.  }
  838.         
  839.   
  840.  /*
  841.   * workRP stuff
  842.   */
  843.        
  844.  /* free up bitmap */
  845.  for (x=0;x<depth;x++)
  846.         if (workbuffer.Planes[x] != NULL) {
  847.                  FreeRaster(workbuffer.Planes[x],regWidth+1,regHeight+1);  
  848.         }
  849.         
  850.  /* free TmpRas */
  851.  if (tmprp != NULL) {
  852.         FreeVec(tmprp);
  853.  }
  854.  
  855.  /*
  856.   * headerRP stuff
  857.   */
  858.   
  859.  /* free up bitmap */
  860.  for (x=0;x<depth;x++)
  861.        if (headerbuffer.Planes[x] != NULL) { 
  862.                 FreeRaster(headerbuffer.Planes[x],hWidth+1,hHeight+1);  
  863.         }
  864.         
  865.  /* free TmpRas */
  866.  if (headertmprp != NULL) {
  867.           FreeVec(headertmprp);
  868.  }
  869.  
  870.  /*
  871.   * misc 
  872.   */
  873.   
  874.  /* free font */
  875.  if (regFont != NULL) {
  876.           CloseFont(regFont);
  877.  }
  878.  
  879. }
  880.  
  881. /****************************************************************
  882. * RegHitTest()
  883. *
  884. *       Takes a mouse hit and determines what to do.
  885. *
  886. ****************************************************************/
  887. BOOL RegHitTest(ULONG Micros, ULONG Seconds, ULONG x, ULONG y)
  888. {
  889.  ULONG t,row;
  890.  static LONG lastrow = -1;
  891.  BOOL retval = FALSE;
  892.  static ULONG micros = 0, secs = 0;
  893.  
  894.  
  895.  /* quick clip of register gadget */
  896.  if (x < regLeft || x > regWidth+regLeft ||
  897.      y < regTop  || y > regHeight+regTop)
  898.      
  899.      return (FALSE);
  900.  
  901.  /* calc row */
  902.  y -= regTop;
  903.  row = 0;
  904.  for (t=0;t<numRows-1;t++) {
  905.     if (y > registerRows[t].rpY +registerRows[t].height)
  906.         row++;
  907.  
  908.     else    break;
  909.  }
  910.  
  911.  /* ok, is it a valid row? */
  912.  if (row < regValidRows) {
  913.         RegSelect(row, TRUE);
  914.     RegEditDisable(FALSE);
  915.     
  916.     if (DoubleClick(secs,micros,Seconds,Micros) && lastrow == row)
  917.         retval = TRUE;
  918.  }
  919.  
  920.  micros = Micros;
  921.  secs = Seconds;
  922.  lastrow = row;
  923.  
  924.  AmiMoveSwap();
  925.  return (retval);
  926. }
  927.  
  928. /****************************************************************
  929. * RegClearGrid()
  930. *
  931. *       Clears the register and then draws the grid.
  932. *
  933. *****************************************************************/
  934. void RegClearGrid()
  935. {
  936.  /*SetAPen(&workRP,DETAILPEN);*/
  937.  
  938.  /* fill area with color */
  939. /*
  940.  RectFill(&workRP,0,0,regWidth,regHeight);
  941. */
  942.  SetRast(&workRP,DETAILPEN);
  943.  
  944.  /* draw register grid */        
  945.  RegRenderGrid();
  946. }
  947.  
  948. /**************************************************************
  949. * RegScrollSetup()
  950. *
  951. *    Sets the scroller correctly
  952. ***************************************************************/
  953. void RegScrollSetup(ULONG top,ULONG total,ULONG visible)
  954. {
  955.  GF_SetGadgetAttrs(gui,AC_MainSpecs[GID_REGVSCROL]->gs_Gadget,
  956.     GTSC_Top,top,
  957.     GTSC_Total, total,
  958.     GTSC_Visible,visible,
  959.     TAG_DONE);
  960. }
  961.  
  962. /************************************************************
  963. * RegInsertEntry()
  964. *
  965. *    Add entry to list
  966. *************************************************************/
  967. void RegInsertEntry(UWORD row, filterNode *en)
  968. {
  969.     entryCount++;
  970.  
  971.     if (regValidRows < numRows) {
  972.         if (regTopNode == NULL)
  973.             regTopNode = en;
  974.  
  975.         regValidRows++;
  976.     }
  977.     
  978.     if (row >= regTopRow && row < regTopRow+regValidRows) {
  979.         RegMoveList(&filtered,regTopRow);
  980.         RegRefresh(FALSE);
  981.     }
  982.  
  983.     RegScrollSetup(regTopRow,entryCount,regValidRows);
  984.     RegEditDisable(TRUE);
  985. }
  986.  
  987. /************************************************************
  988. * RegAddEntry()
  989. *
  990. *    Add entry to list
  991. *************************************************************/
  992. void RegAddEntry(filterNode *en)
  993. {
  994.     entryCount++;
  995.  
  996.     if (regValidRows < numRows) {
  997.         RegDeselect(TRUE);
  998.         if (regTopNode == NULL)
  999.             regTopNode = en;
  1000.  
  1001.         regValidRows++;
  1002.         RegFillRow(en,regValidRows-1);
  1003.     }
  1004.     else {
  1005.         /* remove curr selection */
  1006.         selRow = -1;
  1007.         RegMoveList(&filtered,entryCount-regValidRows);
  1008.         RegRefresh(FALSE);
  1009.     }
  1010.  
  1011.     RegScrollSetup(regTopRow,entryCount,regValidRows);
  1012.     RegRefresh(FALSE);
  1013.     RegEditDisable(TRUE);
  1014. }
  1015.  
  1016. /************************************************************
  1017. * RegKeyScroll()
  1018. *
  1019. *    scrolls selected item on keyboard commands
  1020. *************************************************************/
  1021. void RegKeyScroll(UWORD code)
  1022. {
  1023.  ULONG currRow;
  1024.  
  1025.  if (entryCount == 0)
  1026.     return;
  1027.  
  1028.   /* is the selected area off screen? */
  1029.  if (selRow != -1 && (selRow < regTopRow || selRow >= regTopRow+numRows) ) {
  1030.     RegMoveToSel(&filtered);
  1031.  }
  1032.  
  1033.  currRow = selRow;
  1034.  
  1035.  switch (code) {
  1036.     case UP:
  1037.         if (currRow == 0)
  1038.             return;
  1039.  
  1040.         /* are we not selected? */
  1041.         if (currRow == -1)
  1042.             currRow = regTopRow+1;
  1043.         
  1044.         if (currRow == regTopRow) {
  1045.             selRow = -1;
  1046.             RegScrollListDown();
  1047.             RegRefresh(FALSE);
  1048.         }
  1049.         else RegDeselect(TRUE);
  1050.     
  1051.         currRow--;        
  1052.         RegSelect(currRow-regTopRow, TRUE);
  1053.         break;
  1054.  
  1055.     case SHIFTUP:
  1056.         /* is there a current selection? */
  1057.         if (currRow == -1) {
  1058.             RegSelect(0,TRUE);
  1059.         }
  1060.  
  1061.         /* are we already near the top? */
  1062.         else if (regTopRow < regValidRows) {
  1063.             if (regTopRow == 0)
  1064.                 RegDeselect(TRUE);
  1065.             else    selRow = -1;
  1066.  
  1067.             RegMoveList(&filtered,0);
  1068.             RegRefresh(FALSE);
  1069.             RegSelect(0, TRUE);
  1070.         }
  1071.         
  1072.         /* then just scroll there */
  1073.         else {    
  1074.             selRow = -1;
  1075.             currRow -= regTopRow;
  1076.             RegMoveList(&filtered,regTopRow-regValidRows+1);
  1077.             RegRefresh(FALSE);
  1078.             RegSelect(currRow, TRUE);
  1079.         }
  1080.         break;
  1081.  
  1082.     case CTRLUP:
  1083.         if (currRow == 0) 
  1084.             return;
  1085.  
  1086.         /* remove current selection */
  1087.         if (regTopRow == 0)
  1088.             RegDeselect(TRUE);
  1089.         else {
  1090.             selRow = -1;
  1091.             RegMoveList(&filtered,0);
  1092.             RegRefresh(FALSE);
  1093.         }
  1094.  
  1095.         /* grab top */
  1096.         RegSelect(0, TRUE);
  1097.         break;
  1098.  
  1099.     case DOWN:
  1100.         if (currRow == entryCount-1) {
  1101.             return;
  1102.         }
  1103.  
  1104.         /* are we selected? */
  1105.         if (currRow == -1) {
  1106.             currRow = regTopRow-1;
  1107.         }
  1108.         
  1109.         /* scroll down or jump down */
  1110.         if (currRow == regTopRow + regValidRows - 1) {
  1111.             selRow = -1;
  1112.             RegScrollListUp();
  1113.             RegRefresh(FALSE);
  1114.         }
  1115.         else {
  1116.             RegDeselect(TRUE);
  1117.         }
  1118.  
  1119.         WaitBlit();
  1120.         currRow++;    
  1121.         RegSelect(currRow-regTopRow, TRUE);
  1122.         break;
  1123.  
  1124.     case SHIFTDOWN:
  1125.         /* is there a current selection? */
  1126.         if (currRow == -1) {
  1127.             RegSelect(0, TRUE);
  1128.         }
  1129.  
  1130.         /* are there not enough entries to page down? */
  1131.         else if (entryCount - (regTopRow + regValidRows-1) <= regValidRows) {
  1132.             if (regTopRow == entryCount-regValidRows)
  1133.                 RegDeselect(TRUE);
  1134.             else selRow = -1;
  1135.  
  1136.             RegMoveList(&filtered,entryCount-regValidRows);
  1137.             RegRefresh(FALSE);
  1138.             RegSelect(regValidRows-1, TRUE);
  1139.         }
  1140.  
  1141.         /* just scroll there */
  1142.         else {    
  1143.             selRow = -1;
  1144.             currRow -= regTopRow;
  1145.             RegMoveList(&filtered,regTopRow+regValidRows-1);
  1146.             RegRefresh(FALSE);
  1147.             RegSelect(currRow, TRUE);
  1148.         }
  1149.         break;
  1150.  
  1151.     case CTRLDOWN:
  1152.         if (selRow == entryCount-1)
  1153.             return;
  1154.  
  1155.         /* remove curr selection */
  1156.         if (regTopRow == entryCount - regValidRows) 
  1157.             RegDeselect(TRUE);
  1158.         else {
  1159.             selRow = -1;
  1160.             /*RegMoveList(&filtered,entryCount-regValidRows); */
  1161.             RegLastPage();
  1162.             RegRefresh(FALSE);
  1163.         }
  1164.  
  1165.  
  1166.         /* grab bottom */
  1167.         RegSelect(regValidRows-1, TRUE);
  1168.         break;
  1169.  }
  1170.  
  1171.  RegScrollSetup(regTopRow, entryCount, regValidRows);
  1172.  RegEditDisable(FALSE);
  1173. }
  1174.  
  1175. /************************************************************
  1176. * void RegEditDisable()
  1177. *
  1178. *    Enable/disable the edit gadget
  1179. *************************************************************/
  1180. void RegEditDisable(BOOL ok)
  1181. {
  1182.  /*
  1183.  if (editDisable != ok) 
  1184.     AmiDisableSel(ok);
  1185.       editDisable = ok;
  1186.  }
  1187.  */
  1188.  
  1189.  AmiDisableSel(ok);
  1190. }
  1191.  
  1192. /************************************************************
  1193. * RegRedrawRow()
  1194. *
  1195. *    Updates alternate row
  1196. *************************************************************/
  1197. void RegRedrawRow(filterNode *en)
  1198. {
  1199.  ULONG height,top,row;
  1200.  UBYTE oldmode, oldmask;
  1201.  
  1202.  row = DataFindNode((struct List *)&filtered,(struct Node *)en);
  1203.  if (row < regTopRow || row >= regTopRow + numRows)
  1204.     return;
  1205.  
  1206.  row -= regTopRow;
  1207.  height = registerRows[row].height - 2;
  1208.  top = registerRows[row].rpY + 1;
  1209.  
  1210.  SetAPen(&workRP,DETAILPEN);
  1211.  
  1212.  /* erase row */
  1213.  RectFill(&workRP,
  1214.         1,  top,
  1215.         regWidth-2,top + height );
  1216.  
  1217.  WaitBlit();
  1218.  
  1219.  /* fill in the row */
  1220.  RegFillRow(en,row);
  1221.  
  1222.  /* now redraw the grid */
  1223.  RegRenderGrid();
  1224.  
  1225.  /* now select locally */
  1226.  oldmode = workRP.DrawMode;
  1227.  oldmask = workRP.Mask;
  1228.  
  1229.  /* update display */
  1230.  RegRefresh(FALSE);
  1231. }
  1232.  
  1233. /************************************************************
  1234. * RegRedrawSel()
  1235. *
  1236. *    Updates the selected row
  1237. *************************************************************/
  1238. void RegRedrawSel(filterNode *fn)
  1239. {
  1240.  int x;
  1241.  ULONG height,top,row;
  1242.  UBYTE oldmode, oldmask;
  1243.  
  1244.  row = selRow-regTopRow;
  1245.  height = registerRows[row].height - 2;
  1246.  top = registerRows[row].rpY + 1;
  1247.  
  1248.  SetAPen(&workRP,DETAILPEN);
  1249.  
  1250.  /* erase row */
  1251.  RectFill(&workRP,
  1252.         1,  top,
  1253.         regWidth-2,top + height );
  1254.  
  1255.  WaitBlit();
  1256.  
  1257.  /* fill in the row */
  1258.  for (x=0;x<4;x++)
  1259.     fn->printChars[x]= -1;
  1260.  RegFillRow(fn,row);
  1261.  
  1262.  /* now redraw the grid */
  1263.  RegRenderGrid();
  1264.  
  1265.  /* now select locally */
  1266.  oldmode = workRP.DrawMode;
  1267.  oldmask = workRP.Mask;
  1268.  SetDrMd(&workRP,COMPLEMENT);
  1269.  SafeSetWriteMask(&workRP,0x3);
  1270.  
  1271.  RectFill(&workRP,
  1272.         1,  top,
  1273.         regWidth-2,top + height );
  1274.  
  1275.  SetDrMd(&workRP,oldmode);
  1276.  SafeSetWriteMask(&workRP,oldmask);
  1277.  
  1278.  /* update display */
  1279.  RegRefresh(FALSE);
  1280. }
  1281.  
  1282. /************************************************************
  1283. * RegMoveList()
  1284. *
  1285. *    Moves visible list area to new top
  1286. *************************************************************/
  1287. void RegMoveList(struct MinList *filters, UWORD top)
  1288. {
  1289.  ULONG x, row;
  1290.  filterNode *ft = (filterNode *)filters->mlh_Head;
  1291.  
  1292.  /* empty list? */
  1293.  if (filters->mlh_TailPred == filters) {
  1294.     RegClearGrid();
  1295.     RegRenderGrid();
  1296.     return;
  1297.  }
  1298.  
  1299. #if 0
  1300.  /* are we already there? */
  1301.  if (top == regTopRow) 
  1302.     return;
  1303. #endif
  1304.  
  1305.  if (top > entryCount - regValidRows) {
  1306.     /*printf("WHOA! top = %d\n",top);*/
  1307.     return;
  1308.  }
  1309.  
  1310.  /* deselect item */
  1311.  row = selRow;
  1312.  selRow = -1;
  1313.  
  1314.  /* obtain new top */
  1315.  for (x=0;x<top;x++) 
  1316.     ft = (filterNode *)ft->node.mln_Succ;
  1317.  
  1318.  regTopRow = top;
  1319.  regTopNode = ft;
  1320.  
  1321.  /* now render */
  1322.  RegClearGrid();
  1323.  for (x=0;x<regValidRows; x++) {
  1324.     RegFillRow(ft,x);
  1325.     ft = (filterNode *)ft->node.mln_Succ;
  1326.  }
  1327.  RegRenderGrid();
  1328.  
  1329.  /* select item again*/
  1330.  if (row >= regTopRow && row <= regTopRow + regValidRows-1) {
  1331.     /*printf("selecting!\n");*/
  1332.     RegSelect(row-regTopRow, FALSE);
  1333.   }
  1334.  else selRow = row;
  1335. }
  1336.  
  1337. /************************************************************
  1338. * RegScrollListUp()
  1339. *
  1340. *    quick move of register up by size of one row 
  1341. *************************************************************/
  1342. void RegScrollListUp(void)
  1343. {
  1344.  WORD x;
  1345.  filterNode *filt;
  1346.  
  1347.  regTopRow++;
  1348.  
  1349.  filt=regTopNode = (filterNode *)regTopNode->node.mln_Succ;
  1350.   
  1351.  RegClearGrid();
  1352.  for (x=0;x < regValidRows; x++) {
  1353.     RegFillRow(filt,x);
  1354.     WaitBlit();
  1355.     filt = (filterNode *)filt->node.mln_Succ;
  1356.  }
  1357.  RegRenderGrid();
  1358.  
  1359. }
  1360.  
  1361. /************************************************************
  1362. * RegScrollListDown()
  1363. *
  1364. *    Quick scrolling of window down one
  1365. *************************************************************/
  1366. void RegScrollListDown(void)
  1367. {
  1368.  WORD x;
  1369.  filterNode *filt;
  1370.  
  1371.  /* are we at the top? */
  1372.  if (regTopRow == 0)
  1373.     return; 
  1374.  
  1375.  regTopRow--;
  1376.  filt=regTopNode = (filterNode *)regTopNode->node.mln_Pred;
  1377.  
  1378.  /* render */
  1379.  RegClearGrid();
  1380.  for (x=0;x <regValidRows; x++) {
  1381.     RegFillRow(filt,x);
  1382.     filt = (filterNode *)filt->node.mln_Succ;
  1383.  }
  1384.  RegRenderGrid();
  1385.  
  1386. }
  1387.  
  1388. /************************************************************
  1389. * RegFillRow()
  1390. *
  1391. *    Fill row with node data
  1392. *************************************************************/
  1393. void RegFillRow(filterNode *fn, WORD row)
  1394. {
  1395.  entryNode *en = fn->entry;
  1396.  char checktype[CHECKSIZE];
  1397.  char datestr[DATESIZE];
  1398.  char amntstr[AMNTSIZE];
  1399.  char textpen;
  1400.  long tempprint = -1;;
  1401.  
  1402.  /* now assumes row is blank */
  1403.  if (en->flags & VOIDED)
  1404.     textpen = SHINEPEN;
  1405.  else textpen = BLOCKPEN;
  1406.  
  1407.  /* fill in type */
  1408.  if (en->type != CHECKTYPE)
  1409.      RegRenderCell(row,0,regTypeArray[en->type],textpen,®PrintChars[en->type],FALSE);
  1410.  else {
  1411.     sprintf(checktype,"%06d",en->check);
  1412.     RegRenderCell(row,0,checktype,textpen, &fn->printChars[0],FALSE);
  1413.  }
  1414.  
  1415.  /* fill in date */
  1416.  DataBuildRegDate(&en->date,datestr);
  1417.  RegRenderCell(row,1,datestr,textpen, &fn->printChars[1],FALSE);
  1418.  
  1419.  /* fill in name */
  1420.  RegRenderCell(row,2,en->name,textpen, &fn->printChars[2],FALSE);
  1421.  
  1422.  /* memo? */
  1423.  if (showMemo)
  1424.     RegRenderCell(row,2,en->memo,textpen,&tempprint,TRUE);
  1425.     
  1426.  /* voided? */
  1427.  if (en->flags & VOIDED)
  1428.      RegRenderCell(row,3,"V", textpen, ®PrintFlags[0],FALSE);
  1429.  
  1430.  /* Cleared/tax deductible?? */
  1431.  if (en->flags & CLEARED)
  1432.     RegRenderCell(row,4,"C",textpen, ®PrintFlags[1],FALSE);
  1433.  
  1434.  if (en->flags & TAXDEDUCT)
  1435.     RegRenderCell(row,5,"T",textpen, ®PrintFlags[2],FALSE);
  1436.  
  1437.  /* amount? */
  1438.  DataBuildAmnt(TRUE, &en->amount,amntstr);
  1439.  
  1440.  if (en->type == DEPOSITTYPE && !(en->flags & VOIDED) )
  1441.     textpen=TEXTPEN;
  1442.  
  1443.  /* right justify this val */
  1444.  RegRenderCellFlush(row,6,amntstr,textpen, &fn->printChars[3]);
  1445.  WaitBlit();
  1446. }
  1447.  
  1448. /********************************************************
  1449. * RegLastPage()
  1450. *
  1451. *    Shows last page of register
  1452. *********************************************************/
  1453. void RegLastPage(void)
  1454. {
  1455.  WORD x;
  1456.  filterNode *filt;
  1457.  
  1458. #if 0
  1459.  /* test to see if we have too few entries */
  1460.  if (entryCount <= regValidRows) {
  1461.     RegMoveList(&filtered,0);
  1462.     return;
  1463.  }
  1464. #endif
  1465.  
  1466.  /* clear display */
  1467.  RegClearGrid();
  1468.  
  1469.  /* work from bottom */
  1470.  if (filtered.mlh_TailPred != &filtered) {
  1471.      filt = (filterNode *)filtered.mlh_TailPred;
  1472.     for (x=regValidRows;x > 0; x--) {
  1473.         RegFillRow(filt,x-1);
  1474.         regTopNode = filt;
  1475.         filt = (filterNode *)filt->node.mln_Pred;
  1476.      }
  1477.  
  1478.       regTopRow = entryCount - regValidRows;
  1479.  }
  1480.  
  1481.  RegRenderGrid();
  1482. }
  1483.  
  1484. /********************************************************
  1485. * RegRemoveSel()
  1486. *
  1487. *    Remove the filter entry of selected row,
  1488. *    redraw register
  1489. *********************************************************/
  1490. void RegRemoveSel(void)
  1491. {
  1492.  /*entryCount--;*/
  1493.  if (entryCount < regValidRows) {
  1494.     regValidRows--;
  1495.     selRow = -1;
  1496.     RegLastPage();
  1497.  }
  1498.  else {
  1499.     /* should we not move up? */
  1500.     if (regTopRow + regValidRows > entryCount)
  1501.         regTopRow--;
  1502.  
  1503.      selRow = -1;
  1504.      RegMoveList(&filtered,regTopRow);
  1505.  }
  1506.  
  1507.  RegRefresh(FALSE);
  1508.  RegScrollSetup(regTopRow, entryCount, regValidRows);
  1509.  RegEditDisable(TRUE);
  1510. }
  1511.  
  1512. /********************************************************
  1513. * RegNewFilter()
  1514. *
  1515. *     Resets the filter in the register
  1516. *********************************************************/
  1517. void RegNewFilter(void)
  1518. {
  1519.  selRow = -1;
  1520.  regTopRow = 0;
  1521.  if (entryCount < numRows)
  1522.     regValidRows = entryCount;
  1523.  else regValidRows = numRows;
  1524.  
  1525.  RegLastPage();
  1526.  RegRefresh(FALSE);
  1527.  RegEditDisable(TRUE);
  1528.  RegScrollSetup(regTopRow, entryCount, regValidRows);
  1529. }
  1530.  
  1531. /*********************************************************
  1532. * RegResetOffsets()
  1533. *
  1534. *    Reset the printlength offsets
  1535. **********************************************************/
  1536. void RegResetOffsets(int type)
  1537. {
  1538.  filterNode *filt = NULL;
  1539.  
  1540.  while ( (filt = (filterNode *)DataGetNext((struct List *)&filtered,
  1541.     (struct Node *)filt)) != NULL) {
  1542.         filt->printChars[type] = -1;
  1543.  }
  1544. }
  1545.  
  1546. /*********************************************************
  1547. * RegRedrawFilter()
  1548. *
  1549. *    Resets filter, but maintains selected state if needed
  1550. **********************************************************/
  1551. void RegRedrawFilter(ULONG filtentries)
  1552. {
  1553.  /* handle any unexpected new entries too */
  1554.  if (filtentries > 0) {
  1555.     entryCount += filtentries;
  1556.     if (regValidRows < numRows) {
  1557.         if (numRows-regValidRows <= filtentries)
  1558.             regValidRows = numRows;
  1559.         else    regValidRows += filtentries;
  1560.     }
  1561.  }
  1562.  
  1563.  if (selRow != -1)
  1564.     RegMoveToSel(&filtered);
  1565.  else     RegNewFilter();
  1566. }
  1567.  
  1568. /************************************************************
  1569. * RegMoveToSel()
  1570. *
  1571. *    Moves visible list area to show selected item in center
  1572. *************************************************************/
  1573. void RegMoveToSel(struct MinList *filters)
  1574. {
  1575.  ULONG top;
  1576.  
  1577.  /* empty list? */
  1578.  if (filters->mlh_TailPred == filters) {
  1579.     RegClearGrid();
  1580.     RegRenderGrid();
  1581.     return;
  1582.  }
  1583.  
  1584.  if (selRow == -1)
  1585.     return;
  1586.  
  1587.  /* calculate new top */
  1588.  if (selRow < numRows)
  1589.     top = 0;             /* on first page */
  1590.  else if (selRow > entryCount - numRows)
  1591.     top = entryCount - numRows;    /* on last page */
  1592.  else if (selRow >= regTopRow && selRow < regTopRow+numRows)
  1593.     top = regTopRow;
  1594.  else top = selRow - numRows/2;        /* put sel in middle */
  1595.  
  1596.  RegMoveList(filters,top);
  1597.  RegScrollSetup(regTopRow, entryCount, regValidRows);
  1598.  RegRefresh(FALSE);
  1599. }
  1600.