home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / OPSPRD.ZIP / TSPREAD2.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-01-16  |  11.2 KB  |  411 lines

  1. {$R-,S-,I-}
  2. {$I OPDEFINE.INC}
  3.  
  4. {$IFDEF UseMouse}
  5.   {$IFDEF UseDrag}
  6.     {$DEFINE UsingDrag}
  7.   {$ELSE}
  8.     {$DEFINE UseDragAnyway} {<--- define this to force use of OPDRAG}
  9.     {$IFDEF UseDragAnyway}
  10.       {$DEFINE UsingDrag}
  11.     {$ENDIF}
  12.   {$ENDIF}
  13. {$ENDIF}
  14.  
  15. program TSpread2;
  16.   {-Implement a simple SpreadSheet object using the SpreadList}
  17. uses
  18.   OpCrt,
  19.   OpString,
  20.   OpRoot,
  21.   OpCmd,
  22.   {$IFDEF UseMouse}
  23.   OpMouse,
  24.   {$ENDIF}
  25.   {$IFDEF UsingDrag}
  26.   OpDrag,
  27.   {$ENDIF}
  28.   OpFrame,
  29.   OpWindow,
  30.   OpPick,
  31.   OpSpread;
  32.  
  33. const
  34.   SpreadSize = 50;    {Elements on a side of this spreadsheet}
  35.   ItemWidth = 8;      {Each item uses ItemWidth screen columns}
  36.   DataWidth = ItemWidth-2; {Two characters are used for padding and dividers}
  37.   BackChar = #177;    {Character used to fill background}
  38.  
  39. type
  40.   ItemArray = array[1..SpreadSize, 1..SpreadSize] of String[DataWidth];
  41.  
  42.   SpreadSheet =
  43.     object(SpreadList)
  44.       TLRow : Word;      {Last known Row and col in top left of sheet}
  45.       TLCol : Word;
  46.       SSWid : Byte;      {Last known Width and Height of window}
  47.       SSHgt : Byte;
  48.       Items : ItemArray; {Data for the spreadsheet}
  49.  
  50.       constructor Init;
  51.         {-Constructor specific to this spread sheet}
  52.  
  53.       {---- PickList virtual methods we override ----}
  54.       procedure UpdateContents; virtual;
  55.         {-Used to force scrolling header updates}
  56.       procedure ProcessSelf; virtual;
  57.         {-Add a few commands to the default ProcessSelf handling}
  58.       procedure ItemString(Item : Word; Mode : pkMode; var IType : pkItemType;
  59.                            var IString : String); virtual;
  60.         {-Our item string function for the pick list}
  61.       procedure PreMove; virtual;
  62.         {-Used to draw scrolling row and column headers}
  63.       function ItemSearch : Boolean; virtual;
  64.         {-Used to force Process to exit whenever an alphanumeric character
  65.           is entered}
  66.       function OKToChangeChoice : Boolean; virtual;
  67.         {-Routine that validates cells before leaving them}
  68.       procedure PositionCursor(Item : Word; ACol, ARow : Byte); virtual;
  69.         {-Routine that positions hardware cursor within cell}
  70.  
  71.       {---- Routines added by SpreadSheet object ----}
  72.       procedure WarnInvalidItem(Item : Word); virtual;
  73.         {-Display a warning when specified item is invalid}
  74.       function ValidItem(Item : Word) : Boolean; virtual;
  75.         {-Determine whether specified item is valid}
  76.       procedure AddChar;
  77.         {-Add new character to the contents of current cell}
  78.       procedure DelChar;
  79.         {-Delete last character in current cell}
  80.     end;
  81.  
  82. var
  83.   SL : SpreadSheet;
  84.   {$IFDEF UseDragAnyway}
  85.   PickCommands : DragProcessor;
  86.   {$ENDIF}
  87.   {$IFDEF UsingDrag}
  88.   ZoomHeaderNum : byte;
  89.   HotCode : byte;
  90.   {$ENDIF}
  91.  
  92. procedure Warn(Msg : String);
  93. var
  94.   KW : Word;
  95.   Attr : Byte;
  96. begin
  97.   {Put up a message}
  98.   Attr := ColorMono(DefaultColorSet.HighlightColor, DefaultColorSet.HighlightMono);
  99.   FastWrite(Pad(Msg+'. Press a key...', ScreenWidth), ScreenHeight, 1, Attr);
  100.   RingBell;
  101.  
  102.   {Clear keyboard and wait for a keypress}
  103.   {$IFDEF UseMouse}
  104.   while KeyOrButtonPressed do
  105.     KW := ReadKeyOrButton;
  106.   KW := ReadKeyOrButton;
  107.   {$ELSE}
  108.   while KeyPressed do
  109.     KW := ReadKeyWord;
  110.   KW := ReadKeyWord;
  111.   {$ENDIF}
  112.   {$IFDEF UsingDrag}
  113.   {Get rid of any mouse}
  114.   ClearMouseEvents;
  115.   {$ENDIF}
  116.  
  117.   {Restore the screen}
  118.   FastWrite(CharStr(BackChar, ScreenWidth), ScreenHeight, 1, NormalAttr);
  119. end;
  120.  
  121. constructor SpreadSheet.Init;
  122. var
  123.   Row : Word;
  124.   Col : Word;
  125. begin
  126.   {Initialize the SpreadList}
  127.   if not SpreadList.InitAbstractDeluxe(19, 5, 50, 20,
  128.                                        DefaultColorSet,
  129.                                        DefWindowOptions or wBordered,
  130.                                        ItemWidth, SpreadSize, SpreadSize,
  131.                                        SingleChoice,
  132.                                        DefPickOptions) then
  133.     Fail;
  134.  
  135. {$IFDEF UseDragAnyway}
  136.   {Attach the DragProcessor to the PickList}
  137.   SetCommandProcessor(PickCommands);
  138. {$ENDIF}
  139.  
  140.   {Use vertical dividers}
  141.   EnableDividers(NoFrameChar, #179, NoFrameChar);
  142.   ResizeWindow(-1, 0);
  143.  
  144.   {Adjust the frame to allow room for row and col headers}
  145.   AdjustFrameCoords(15, 3, 50, 21);
  146.  
  147.   {Add horizontal and vertical scroll bars}
  148.   wFrame.AddScrollBar(frBB, 0, 0, DefaultColorSet);
  149.   wFrame.AddScrollBar(frRR, 0, 0, DefaultColorSet);
  150.  
  151.   {Add a title}
  152.   wFrame.AddHeader(' SpreadSheet Demo ', heTC);
  153.  
  154. {$IFDEF UsingDrag}
  155.   {Add hot spot for zoom}
  156.   wFrame.AddCustomHeader(#24, frtr, -1, 0,
  157.                          DefaultColorSet.HeaderColor,
  158.                          DefaultColorSet.HeaderMono);
  159.   wFrame.AddHotRegion(frTR, ZoomHotCode, -1, 0, 1, 1);
  160.   ZoomHeaderNum := wFrame.GetLastHeaderIndex;
  161.  
  162.   {Add hot spots for mouse dragging}
  163.   wFrame.AddHotBar(frTT, MoveHotCode);
  164.   wFrame.AddCustomHeader(#240, frbr, 0, 0,
  165.                          DefaultColorSet.FrameColor,
  166.                          DefaultColorSet.FrameMono);
  167.   wFrame.AddHotRegion(frBR, ResizeHotCode, 0, 0, 1, 1);
  168. {$ELSE}
  169.   {Scrolling by line is too slow without dragging}
  170.   pkOptionsOn(pkMousePage);
  171. {$ENDIF}
  172.  
  173.   {Limit the sizeability for demo purposes}
  174.   SetSizeLimits(23, 4, ScreenWidth, ScreenHeight);
  175.   SetPosLimits(1, 1, ScreenWidth, ScreenHeight-1);
  176.  
  177.   {Make the cursor visible within the spreadsheet}
  178.   SetCursor(cuNormal);
  179.  
  180.   {Add a little cosmetic padding}
  181.   SetPadSize(1, 0);
  182.  
  183.   {Initialize the data associated with the list}
  184.   for Row := 1 to SpreadSize do
  185.     for Col := 1 to SpreadSize do
  186.       Items[Row, Col] := Long2Str(Row*Col);
  187.  
  188.   {This will force the headers to be written the first time}
  189.   TLRow := 0;
  190.   TLCol := 0;
  191.   SSWid := 0;
  192.   SSHgt := 0;
  193. end;
  194.  
  195. procedure SpreadSheet.UpdateContents;
  196. begin
  197.   {Call ancestor's UpdateContents first}
  198.   SpreadList.UpdateContents;
  199.  
  200.   {Update scrolling headers}
  201.   PreMove;
  202. end;
  203.  
  204. procedure SpreadSheet.ProcessSelf;
  205. var
  206.   Cmd : Word;
  207. begin
  208.   {Handle a few more commands than the default ProcessSelf}
  209.   repeat
  210.     SpreadList.ProcessSelf;
  211.     Cmd := GetLastCommand;
  212.     case Cmd of
  213.       {$IFDEF UsingDrag}
  214.       ccMouseDown : if HandleMousePress(SL) = ZoomHotCode then
  215.                       if SL.IsZoomed then
  216.                         SL.ChangeHeader(ZoomHeaderNum, #18)
  217.                       else
  218.                         SL.ChangeHeader(ZoomHeaderNum, #24);
  219.       {$ENDIF}
  220.       ccChar :   {Add a character to the current cell}
  221.         AddChar;
  222.       ccUser0 :  {Delete last character in current cell}
  223.         DelChar;
  224.       ccQuit, ccUser1..255 :
  225.         {Validate cell before exiting}
  226.         if not ValidItem(GetLastChoice) then begin
  227.           WarnInvalidItem(GetLastChoice);
  228.           {Don't exit loop}
  229.           Cmd := ccNone;
  230.         end;
  231.     end;
  232.     {We don't exit on ccSelect here}
  233.   until Cmd in [ccQuit, ccError, ccUser1..255];
  234. end;
  235.  
  236. procedure SpreadSheet.ItemString(Item : Word; Mode : pkMode;
  237.                                   var IType : pkItemType;
  238.                                   var IString : String);
  239. begin
  240.   {Just return the item from the data array}
  241.   IString := Items[GetItemRow(Item), GetItemCol(Item)];
  242. end;
  243.  
  244. procedure SpreadSheet.PreMove;
  245. var
  246.   Row : Word;
  247.   Col : Word;
  248.   Wid : Byte;
  249.   Hgt : Byte;
  250.   Attr : Byte;
  251.   S : String;
  252. begin
  253.   {Call ancestor's PreMove first just in case}
  254.   SpreadList.PreMove;
  255.  
  256.   {Determine whether scrolling headers need updating}
  257.   TopLeftRowCol(Row, Col);
  258.   Wid := Width;
  259.   Hgt := Height;
  260.  
  261.   if (Row <> TLRow) or (Hgt <> SSHgt) then begin
  262.     {Need a new set of row headers}
  263.     TLRow := Row;
  264.     SSHgt := Hgt;
  265.     Attr := ColorMono(DefaultColorSet.FrameColor, DefaultColorSet.FrameMono);
  266.     for Row := 1 to Hgt do begin
  267.       S := Long2Str(Row+TLRow-1);
  268.       fFastWrite(LeftPad(S, 2)+' ', Row+1, 1, Attr);
  269.     end;
  270.   end;
  271.  
  272.   if (Col <> TLCol) or (Wid <> SSWid) then begin
  273.     {Need a new set of column headers}
  274.     TLCol := Col;
  275.     SSWid := Wid;
  276.     Attr := ColorMono(DefaultColorSet.FrameColor, DefaultColorSet.FrameMono);
  277.     S := '';
  278.     for Col := 1 to GetItemCols do begin
  279.       S := S+Pad(' '+Long2Str(TLCol+Col-1), ItemWidth-1);
  280.       {Add a divider bar}
  281.       if Col <> GetItemCols then
  282.         S := S+#179;
  283.     end;
  284.     S := Pad(S, Wid);
  285.     fFastWrite(S, 1, 4, Attr);
  286.   end;
  287. end;
  288.  
  289. function SpreadSheet.ItemSearch : Boolean;
  290. begin
  291.   {Exit Process if last key entered is not a control character}
  292.   ItemSearch := (Char(GetLastKey) >= ' ');
  293. end;
  294.  
  295. procedure SpreadSheet.WarnInvalidItem(Item : Word);
  296. begin
  297.   Warn('Empty cells are not acceptable');
  298. end;
  299.  
  300. function SpreadSheet.ValidItem(Item : Word) : Boolean;
  301. begin
  302.   {Don't accept an empty cell}
  303.   ValidItem := (Length(GetItemString(Item)) > 0);
  304. end;
  305.  
  306. function SpreadSheet.OKToChangeChoice : Boolean;
  307. var
  308.   Cmd : Word;
  309.   NextChoice : Word;
  310.   NextFirst : Word;
  311. begin
  312.   {Assume it's ok to change choice}
  313.   OKToChangeChoice := True;
  314.  
  315.   {Determine whether the current choice will actually be changed}
  316.   Cmd := GetLastCommand;
  317.   EvaluateCmd(Cmd, NextChoice, NextFirst);
  318.   if NextChoice = GetLastChoice then
  319.     Exit;
  320.  
  321.   {Validate item and display a warning if needed}
  322.   if ValidItem(GetLastChoice) then
  323.     OKToChangeChoice := True
  324.   else begin
  325.     WarnInvalidItem(GetLastChoice);
  326.     OKToChangeChoice := False;
  327.   end;
  328. end;
  329.  
  330. procedure SpreadSheet.PositionCursor(Item : Word; ACol, ARow : Byte);
  331. begin
  332.   {Position the cursor after the last character of the cell's string}
  333.   GotoXYAbs(ACol+Length(Items[GetItemRow(Item), GetItemCol(Item)])+1, ARow);
  334.   {The +1 is because we added 1 column of left padding via SetPadSize}
  335. end;
  336.  
  337. procedure SpreadSheet.AddChar;
  338. var
  339.   Row : Word;
  340.   Col : Word;
  341.   Ch : Char;
  342. begin
  343.   Ch := Char(Byte(GetLastKey));
  344.   if (Ch < '0') or (Ch > '9') then
  345.     {Accept only numbers}
  346.     Warn('Only numbers are acceptable')
  347.   else begin
  348.     Row := GetItemRow(GetLastChoice);
  349.     Col := GetItemCol(GetLastChoice);
  350.     if Length(Items[Row, Col]) < DataWidth then
  351.       Items[Row, Col] := Items[Row, Col]+Ch;
  352.   end;
  353. end;
  354.  
  355. procedure SpreadSheet.DelChar;
  356. var
  357.   Row : Word;
  358.   Col : Word;
  359. begin
  360.   Row := GetItemRow(GetLastChoice);
  361.   Col := GetItemCol(GetLastChoice);
  362.   if Length(Items[Row, Col]) > 0 then
  363.     dec(Items[Row, Col][0]);
  364. end;
  365.  
  366. procedure InitCommands;
  367. begin
  368. {$IFDEF UseMouse}
  369.   if MouseInstalled then begin
  370.     {$IFDEF UsingDrag}
  371.       {$IFDEF UseDragAnyway}
  372.       {Initialize the new DragProcessor}
  373.       if not PickCommands.Init(@PickKeySet, PickKeyMax) then
  374.         Halt;
  375.       {$ENDIF}
  376.       {See-through mouse cursor}
  377.       PickCommands.SetScreenMask($FFFF);
  378.       PickCommands.SetMouseCursor($7700, $7700, $7700);
  379.     {$ELSE}
  380.       {Enable the mouse with a see-through cursor}
  381.       PickCommands.cpOptionsOn(cpEnableMouse);
  382.       SoftMouseCursor($FFFF, $7700);
  383.     {$ENDIF}
  384.   end;
  385. {$ENDIF}
  386.  
  387.   {Add backspace as an exit command}
  388.   PickCommands.AddCommand(ccUser0, 1, Byte(^H), 0);
  389. end;
  390.  
  391. begin
  392.   {Initialize the screen}
  393.   TextChar := BackChar;
  394.   ClrScr;
  395.  
  396.   {Customize the PickList command processor}
  397.   InitCommands;
  398.  
  399.   {Initialize the SpreadSheet object}
  400.   SL.Init;
  401.   if InitStatus <> 0 then begin
  402.     WriteLn('Error initializing SpreadSheet');
  403.     Halt;
  404.   end;
  405.  
  406.   {Process it}
  407.   SL.Process;
  408.   SL.Erase;
  409.   SL.Done;
  410. end.
  411.