home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / t_power / tppick.pas < prev    next >
Pascal/Delphi Source File  |  1988-02-17  |  15KB  |  460 lines

  1. {
  2. Copyright (c) 1987 by TurboPower Software. May be freely used by and
  3. distributed to owners of Turbo Professional 4.0.
  4.  
  5. Modified by Dan T. Davis, January 1988.
  6.  
  7. See TPDir for an example of using the TPPick unit.
  8. }
  9.  
  10. {$R-,I-,S-,V-}
  11.  
  12. unit TpPick;
  13.   {-Manage scrolling pick windows}
  14.   {{}
  15. interface
  16.  
  17. uses
  18.   TPString,
  19.   TPCrt,
  20.   TPWindow;
  21.  
  22. const
  23.   PickAttr : Boolean = False; {If True, special color attributes used to pick item}
  24.   PickAttrN : Byte = $00;    {Special Color Attribute; normal color}
  25.   PickAttrH : Byte = $00;    {Special Color Attribute; highlight color}
  26.   HideCursor : Boolean = True; {False to leave hardware cursor on screen}
  27.   PickMinRows : Word = 0;    {We want at least this many rows in PickWindow}
  28.   PickMaxRows : Word = 9999; {We want at most this many rows in PickWindow}
  29.   PickMatrix : Byte = 1;     {Number of Horizontal Fields in window}
  30.   PickStick : Boolean = True; {Get "stuck" at top/bottom on SCROLLING PickWindows?}
  31.  
  32. type
  33.   CharSet = set of Char;
  34.  
  35. function PickWindow
  36.   (StringFunc : Pointer;     {Pointer to function to return each item string}
  37.    NumItems : Word;          {Number of items to pick from}
  38.    XLow, YLow : Byte;        {Window coordinates, including frame if any}
  39.    XHigh, YHigh : Byte;      {Window coordinates, including frame if any}
  40.    DrawFrame : Boolean;      {True to draw a frame around window}
  41.    WindowAttr : Byte;        {Video attribute for body of window}
  42.    FrameAttr : Byte;         {Video attribute for frame}
  43.    HeaderAttr : Byte;        {Video attribute for header}
  44.    SelectAttr : Byte;        {Video attribute for selected item}
  45.    Header : string;          {Title for window}
  46.    PickSet : CharSet;        {Selection characters}
  47.    var Choice : Word;        {The item selected, in the range 1..NumItems}
  48.    var PickChar : Char       {Character used to perform selection}
  49.    ) : Boolean;              {True if PickWindow was successful}
  50.   {-Display a window, let user scroll around in it, and return choice.
  51.     Choice returned is in the range 1..NumItems.
  52.     PickChar is an element of PickSet.}
  53.  
  54. procedure FillPickWindow
  55.   (W : WindowPtr;            {Which window to display pick list}
  56.    StringFunc : Pointer;     {Pointer to function to return each item string}
  57.    Choice : Word;            {Choice,row tell how the items should be drawn}
  58.    Row : Word;               {           in a manner consistent with PickBar}
  59.    NumItems : Word);         {Number of items in PickArray}
  60.   {-Display a window, fill it with choices, and return.
  61.     Choice specifies the initial item highlighted.}
  62.  
  63. procedure PickBar
  64.   (W : WindowPtr;            {The window to operate in}
  65.    StringFunc : Pointer;     {Pointer to function to return items}
  66.    var Choice : Word;        {The item selected, range 1..numitems}
  67.    var Row : Word;           {The row to draw the bar on}
  68.    NumItems : Word;          {The number of items to pick from}
  69.    SelectAttr : Byte;        {Video attribute for bars}
  70.    PickSet : CharSet;        {Selection Characters}
  71.    var PickChar : Char;      {Character used to perform selection}
  72.    EraseBar : Boolean);      {Should we recolor the bar when finished?}
  73.   {-Choose from a pick list already displayed on the screen}
  74.  
  75.   {=========================================================================}
  76.  
  77.   (*}*)
  78. implementation
  79.  
  80. var
  81.   XSize : Word;              {Active width of pick window (no frame)}
  82.   YSize : Word;              {Active height of pick window}
  83.   PickFunc : Pointer;        {Pointer to function that returns each string}
  84.  
  85.   Items : Word;              {Total Items being considered}
  86.   ItemWidth : Byte;          {Maximum width for an item}
  87.   ItemOffSet : Word;         {Offset Between Item Numbers in different Columns}
  88.   ItemWrap : Boolean;        {Wrap when hitting PickWindow periphery}
  89.  
  90.   procedure Lower(var Source : Word; MaxVal : Word);
  91.   begin
  92.     if Source > MaxVal then
  93.       Source := MaxVal;
  94.   end;
  95.  
  96.   function InitPickVars
  97.     (W : WindowPtr;
  98.      NumItems : Word;
  99.      StringFunc : Pointer) : Boolean;
  100.     {-Initialize variables we'll use for display}
  101.   begin
  102.     InitPickVars := True;
  103.  
  104.     {Make sure the window is on screen; if it is, ASSUME that}
  105.     {the user has made it the top window with SETTOPWINDOW or SELECTWINDOW}
  106.     {Otherwise, assume the user wants us to turn it on}
  107.     if DisplayWindow(W) then {we had to turn it on} ;
  108.  
  109.     if W <> nil then
  110.       with WindowP(W)^ do begin
  111.         XSize := Succ(XH-XL);
  112.         YSize := Succ(YH-YL);
  113.     end else ;
  114.     { you should have already set XSize and YSize }
  115.  
  116.     Items := NumItems;
  117.     ItemWidth := XSize div PickMatrix;
  118.  
  119.     Lower(YSize, Items);
  120.     Lower(YSize, PickMaxRows);
  121.  
  122.     ItemOffSet := (Items+Pred(PickMatrix)) div PickMatrix;
  123.     if ItemOffSet < PickMinRows then
  124.       ItemOffSet := PickMinRows;
  125.     Lower(ItemOffSet, Items);
  126.  
  127.     Lower(YSize, ItemOffSet);
  128.  
  129.     ItemWrap := (YSize = ItemOffSet) or not PickStick;
  130.  
  131.     PickFunc := StringFunc;
  132.  
  133.     {Validate item information}
  134.     if (YSize = 0) or (PickFunc = nil) then
  135.       InitPickVars := False;
  136.  
  137.     {Were we able to show the window?}
  138.     if (W <> nil) and not WindowP(W)^.Active then
  139.       InitPickVars := False;
  140.   end;
  141.  
  142.   procedure ReCalc(var Row : Word; var Choice : Word; var Top : Word);
  143.   var
  144.     I : Integer;
  145.   begin
  146.     {make sure that we are asking for a valid Choice/Row combination}
  147.     I := Succ(Pred(Choice) mod ItemOffSet);
  148.     Lower(Row, I);
  149.     Lower(Row, YSize);
  150.     I := YSize-(ItemOffSet-I);
  151.     if Row < I then
  152.       Row := I;
  153.     if Row < 1 then
  154.       Row := 1;
  155.     Top := Succ((Choice-Row) mod ItemOffSet);
  156.   end;
  157.  
  158.   {{}
  159.   function GetString(Item : Word) : string;
  160.     {-Return the name of each item}
  161.     inline($FF/$1E/>PickFunc); {CALL DWORD PTR [>PickFunc]}
  162.   (*}*)
  163.  
  164.   procedure DrawItem(ItemNum : Word; Row, Col, Attr : Byte; HiLi : Boolean);
  165.     {-Draw the specified item}
  166.   var
  167.     S : string;
  168.   begin
  169.     if ItemNum <= Items then
  170.       S := GetString(ItemNum)
  171.     else
  172.       S := '';
  173.     if Length(S) <= ItemWidth then
  174.       S := Pad(S, ItemWidth)
  175.     else
  176.       S[0] := Chr(ItemWidth);
  177.     if PickAttr then begin
  178.       if HiLi then
  179.         FastWriteWindow(S, Row, Col, PickAttrH)
  180.       else
  181.         FastWriteWindow(S, Row, Col, PickAttrN);
  182.       PickAttr := False;
  183.     end else
  184.       FastWriteWindow(S, Row, Col, Attr);
  185.   end;
  186.  
  187.   procedure DrawPage(Top : Word; Attr : Byte);
  188.     {-Draw a full page of items, with Choice shown on Row}
  189.   var
  190.     I, J, BeforeTop, AtCol : Word;
  191.   begin
  192.     for I := 0 to Pred(PickMatrix) do begin
  193.       AtCol := Succ(I*ItemWidth);
  194.       BeforeTop := Pred(Top+I*ItemOffSet);
  195.       for J := 1 to YSize do
  196.         DrawItem(J+BeforeTop, J, AtCol, Attr, False);
  197.     end;
  198.   end;
  199.  
  200.   procedure PickBar
  201.     (W : WindowPtr;          {The window to operate in}
  202.      StringFunc : Pointer;   {Pointer to function to return items}
  203.      var Choice : Word;      {The item selected, range 1..numitems}
  204.      var Row : Word;         {The row to draw the bar on}
  205.      NumItems : Word;        {The number of items to pick from}
  206.      SelectAttr : Byte;      {Video attribute for bars}
  207.      PickSet : CharSet;      {Selection Characters}
  208.      var PickChar : Char;    {Character used to perform selection}
  209.      EraseBar : Boolean);    {Should we recolor the bar when finished?}
  210.   var
  211.     SaveBreak : Boolean;
  212.     XY, CursorScanLines : Word;
  213.     Done : Boolean;
  214.     KW : Word;
  215.     Top, PrevTop, PrevChoice, PrevRow : Word;
  216.     Column : Word;
  217.     AtLoc : Word;
  218.     MoveMax : Word;
  219.  
  220.   begin
  221.     if not InitPickVars(W, NumItems, StringFunc) then
  222.       Exit;
  223.  
  224.     { Initialize PrevTop to make sure we draw page initially }
  225.     PrevTop := 0;
  226.  
  227.     with WindowP(W)^ do begin
  228.  
  229.       GetCursorState(XY, CursorScanLines);
  230.       if HideCursor then
  231.         HiddenCursor
  232.       else
  233.         NormalCursor;
  234.       SaveBreak := CheckBreak;
  235.       CheckBreak := False;
  236.  
  237.       {Loop getting characters}
  238.       Done := False;
  239.       repeat
  240.  
  241.         {Check to see if we need to redraw the page or erase the bar}
  242.         ReCalc(Row, Choice, Top);
  243.         if PrevTop <> Top then
  244.           DrawPage(Top, WAttr)
  245.         else if (PrevChoice <> Choice) or (PrevRow <> Row) then
  246.           DrawItem(PrevChoice, PrevRow, Column, WAttr, False);
  247.  
  248.         PrevTop := Top;
  249.         PrevChoice := Choice;
  250.         PrevRow := Row;
  251.         Column := Succ((Pred(Choice) div ItemOffSet)*ItemWidth);
  252.  
  253.         {Highlight the selected entry}
  254.         DrawItem(Choice, Row, Column, SelectAttr, True);
  255.  
  256.         GoToXY(Column, Row);
  257.  
  258.         {Find our relative Location in the PickList}
  259.         AtLoc := Succ(Pred(Choice) mod ItemOffSet);
  260.  
  261.         {Get a command}
  262.         KW := ReadKeyWord;
  263.  
  264.         {See if a pick character first}
  265.         PickChar := Char(lo(KW));
  266.         if PickChar = #0 then
  267.           PickChar := Char(hi(KW) or $80);
  268.         if PickChar in PickSet then
  269.           Done := True;
  270.  
  271.         if not Done then
  272.           case KW of
  273.             $4700 :          {Home}
  274.               Choice := 1;
  275.  
  276.             $4800 :          {Up arrow}
  277.               if AtLoc <> 1 then begin
  278.                 {Move to previous item}
  279.                 Dec(Choice);
  280.                 {Move selection bar}
  281.                 Dec(Row);
  282.               end else if ItemWrap then begin
  283.                 {Wrap to previous column, if any}
  284.                 if Choice > 1 then
  285.                   Dec(Choice)
  286.                 else
  287.                   Choice := Items;
  288.                 Row := YSize;
  289.               end;
  290.  
  291.             $4900 :          {PgUp}
  292.               begin
  293.                 MoveMax := Pred(AtLoc);
  294.                 Lower(MoveMax, YSize);
  295.                 if MoveMax > 0 then
  296.                   Dec(Choice, MoveMax)
  297.                 else if ItemWrap then begin
  298.                   {Wrap to previous column, if any}
  299.                   if Choice > 1 then
  300.                     Dec(Choice)
  301.                   else
  302.                     Choice := Items;
  303.                   Row := YSize;
  304.                 end;
  305.               end;
  306.  
  307.             $4B00 :          {Left Arrow}
  308.               begin
  309.                 if Choice > ItemOffSet then
  310.                   Dec(Choice, ItemOffSet)
  311.                 else if Choice > 1 then begin
  312.                   Choice := Pred(Choice)+Pred(PickMatrix)*ItemOffSet;
  313.                   Dec(Row);
  314.                 end else if ItemWrap then
  315.                   Choice := PickMatrix*ItemOffSet;
  316.                 if Choice > Items then
  317.                   repeat Dec(Choice, ItemOffSet) until Choice <= Items;
  318.               end;
  319.  
  320.             $4D00 :          {Right Arrow}
  321.               if Choice <= Items-ItemOffSet then
  322.                 Inc(Choice, ItemOffSet)
  323.               else if AtLoc <> ItemOffSet then begin
  324.                 Choice := Succ(AtLoc);
  325.                 Inc(Row);
  326.               end else if ItemWrap then
  327.                 Choice := 1;
  328.  
  329.             $4F00 :          {End}
  330.               begin
  331.                 Choice := Items;
  332.                 Row := 1;
  333.               end;
  334.  
  335.             $5000 :          {Down arrow}
  336.               if (AtLoc <> ItemOffSet) and (Choice < Items) then begin
  337.                 {Move to next item}
  338.                 Inc(Choice);
  339.                 {Move selection bar}
  340.                 Inc(Row);
  341.               end else if ItemWrap then begin
  342.                 {Wrap to next column, if any}
  343.                 if Choice < Items then
  344.                   Inc(Choice)
  345.                 else
  346.                   Choice := 1;
  347.                 Row := 1;
  348.               end else if (Choice = Items) then
  349.                 Dec(Row);
  350.  
  351.             $5100 :          {PgDn}
  352.               begin
  353.                 MoveMax := ItemOffSet-AtLoc;
  354.                 Lower(MoveMax, YSize);
  355.                 if (MoveMax > 0) and (Choice < Items) then begin
  356.                   Inc(Choice, MoveMax);
  357.                   if Choice > Items then begin
  358.                     Choice := Items;
  359.                     Row := 1;
  360.                   end;
  361.                 end else if ItemWrap then begin
  362.                   {Wrap to next column, if any}
  363.                   if Choice < Items then
  364.                     Inc(Choice)
  365.                   else
  366.                     Choice := 1;
  367.                   Row := 1;
  368.                 end;
  369.               end;
  370.           end;
  371.       until Done;
  372.       if EraseBar then
  373.         DrawItem(Choice, Row, Column, WAttr, False);
  374.       CheckBreak := SaveBreak;
  375.       RestoreCursorState(XY, CursorScanLines);
  376.     end;
  377.   end;
  378.  
  379.   function PickWindow
  380.     (StringFunc : Pointer;   {Pointer to function to return each item string}
  381.      NumItems : Word;        {Number of items in PickArray}
  382.      XLow, YLow : Byte;      {Window coordinates, including frame if any}
  383.      XHigh, YHigh : Byte;    {Window coordinates, including frame if any}
  384.      DrawFrame : Boolean;    {True to draw a frame around window}
  385.      WindowAttr : Byte;      {Video attribute for body of window}
  386.      FrameAttr : Byte;       {Video attribute for frame}
  387.      HeaderAttr : Byte;      {Video attribute for header}
  388.      SelectAttr : Byte;      {Video attribute for selected item}
  389.      Header : string;        {Title for window}
  390.      PickSet : CharSet;      {Selection characters}
  391.      var Choice : Word;      {The item selected, in the range 1..NumItems}
  392.      var PickChar : Char     {Character used to perform selection}
  393.      ) : Boolean;            {True if PickWindow was successful}
  394.   var
  395.     Correction : Integer;
  396.     Row : Word;
  397.     W : WindowPtr;
  398.  
  399.   begin
  400.  
  401.     {Assume failure}
  402.     PickWindow := False;
  403.  
  404.     {Get a Value for YHigh}
  405.     if DrawFrame then
  406.       Correction := -1
  407.     else
  408.       Correction := +1;
  409.     XSize := XHigh-XLow+Correction;
  410.     YSize := YHigh-YLow+Correction;
  411.     if not InitPickVars(nil, NumItems, StringFunc) then
  412.       Exit;
  413.     if YSize >= PickMinRows then
  414.       YHigh := YLow+YSize-Correction
  415.     else
  416.       YHigh := YLow+PickMinRows-Correction;
  417.  
  418.     {Initialize the window}
  419.     if not MakeWindow(W, XLow, YLow, XHigh, YHigh,
  420.                       DrawFrame, True, False,
  421.                       WindowAttr, FrameAttr, HeaderAttr,
  422.                       Header) then Exit;
  423.  
  424.     if not InitPickVars(W, NumItems, StringFunc) then
  425.       Exit;
  426.  
  427.     {Initial item is the one we say if legal}
  428.     if (Choice < 1) or (Choice > NumItems) then
  429.       Choice := 1;
  430.     Row := Choice;
  431.     PickBar(W, PickFunc, Choice, Row, Items,
  432.             SelectAttr, PickSet, PickChar, False);
  433.  
  434.     {Restore the screen and deallocate the window}
  435.     W := EraseTopWindow;
  436.     DisposeWindow(W);
  437.  
  438.     {If we get to here, all was well}
  439.     PickWindow := True;
  440.   end;
  441.  
  442.   procedure FillPickWindow
  443.     (W : WindowPtr;          {Which window to display pick list}
  444.      StringFunc : Pointer;   {Pointer to function to return each item string}
  445.      Choice : Word;          {Choice,row tell how the items should be drawn}
  446.      Row : Word;             {           in a manner consistent with PickBar}
  447.      NumItems : Word);       {Number of items in PickArray}
  448.   var
  449.     Top : Word;
  450.   begin
  451.     if not InitPickVars(W, NumItems, StringFunc) then
  452.       Exit;
  453.  
  454.     ReCalc(Row, Choice, Top);
  455.     DrawPage(Top, WindowP(W)^.WAttr);
  456.   end;
  457.  
  458. end.
  459.  
  460.