home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 March / Chip_1999-03_cd.bin / zkuste / delphi / INFO / DI9805RS.ZIP / SortLst.pas < prev    next >
Pascal/Delphi Source File  |  1998-03-05  |  6KB  |  236 lines

  1. unit SortLst;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Graphics, Controls,
  7.   Forms, Dialogs, Menus, StdCtrls, Classes;
  8.  
  9. type
  10.     // The linked list cells.
  11.     PCell = ^TCell;
  12.     TCell = record
  13.         Value    : String[20]; // The data.
  14.         NextCell : PCell;      // The next cell in the list.
  15.     end;
  16.  
  17.   TLinkedListForm = class(TForm)
  18.     ValueText: TEdit;
  19.     CmdInsert: TButton;
  20.     CmdRemoveAfter: TButton;
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure CmdInsertClick(Sender: TObject);
  23.     procedure CmdRemoveAfterClick(Sender: TObject);
  24.     procedure ValueTextChange(Sender: TObject);
  25.     procedure DrawList;
  26.     procedure FormPaint(Sender: TObject);
  27.     procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
  28.       Shift: TShiftState; X, Y: Integer);
  29.     procedure EnableButtons;
  30.     procedure FormDestroy(Sender: TObject);
  31.   private
  32.     { Private declarations }
  33.     top_sentinel    : TCell;
  34.     bottom_sentinel : TCell;
  35.     num_items       : Integer;
  36.     selected        : Integer; // Selected cell index. 0 = sentinel.
  37.   public
  38.     { Public declarations }
  39.   end;
  40.  
  41. var
  42.   LinkedListForm: TLinkedListForm;
  43.  
  44. implementation
  45.  
  46. {$R *.DFM}
  47.  
  48. const
  49.     HGT = 14;
  50.     GAP = 3;
  51.  
  52. // Initialize the empty linked list.
  53. procedure TLinkedListForm.FormCreate(Sender: TObject);
  54. begin
  55.     top_sentinel.NextCell := @bottom_sentinel;
  56.     top_sentinel.Value := '';
  57.     bottom_sentinel.NextCell := nil;
  58.     bottom_sentinel.Value := #255;
  59.     num_items := 0;
  60.  
  61.     // Start with no item selected.
  62.     selected := -1;
  63. end;
  64.  
  65. // Add a new cell after the selected cell.
  66. procedure TLinkedListForm.CmdInsertClick(Sender: TObject);
  67. var
  68.     after_me, next_cell, new_cell : PCell;
  69.     new_value                     : String;
  70. begin
  71.     // Find the insertion position.
  72.     new_value := ValueText.Text;
  73.     after_me := @top_sentinel;
  74.     repeat
  75.         next_cell := after_me^.NextCell;
  76.         if (next_cell^.Value >= new_value) then break;
  77.         after_me := next_cell;
  78.     until (False);
  79.  
  80.     // Create the new cell.
  81.     New(new_cell);
  82.     new_cell^.Value := ValueText.Text;
  83.  
  84.     // Insert the cell in the list.
  85.     new_cell^.NextCell := next_cell;
  86.     after_me^.NextCell := new_cell;
  87.     num_items := num_items + 1;
  88.  
  89.     // Redisplay the list.
  90.     selected := -1;
  91.     DrawList;
  92.     EnableButtons;
  93.  
  94.     ValueText.Text := '';
  95.     ValueText.SetFocus;
  96. end;
  97.  
  98. // Remove the cell after the selected cell.
  99. procedure TLinkedListForm.CmdRemoveAfterClick(Sender: TObject);
  100. var
  101.     after_me, target : PCell;
  102.     i                : Integer;
  103. begin
  104.     // Find the cell before the target cell.
  105.     after_me := @top_sentinel;
  106.     for i := 1 to selected do
  107.         after_me := after_me^.NextCell;
  108.  
  109.     // Remove the next cell from the list.
  110.     target := after_me^.NextCell;
  111.     after_me^.NextCell := target^.NextCell;
  112.  
  113.     // Free the target cell's memory.
  114.     Dispose(target);
  115.     num_items := num_items - 1;
  116.  
  117.     // Redisplay the list.
  118.     DrawList;
  119.     EnableButtons;
  120.     ValueText.SetFocus;
  121. end;
  122.  
  123. // Enable the appropriate buttons.
  124. procedure TLinkedListForm.ValueTextChange(Sender: TObject);
  125. begin
  126.     CmdInsert.Enabled := (ValueText.Text <> '');
  127. end;
  128.  
  129. // Display the list, highlighting the selected item.
  130. procedure TLinkedListForm.DrawList;
  131. var
  132.     cell_ptr : PCell;
  133.     i, x, y  : Integer;
  134.     rect     : TRect;
  135. begin
  136.     // Clear the form.
  137.     rect.Left := 0;
  138.     rect.Top := 0;
  139.     rect.Right := ClientWidth;
  140.     rect.Bottom := ClientHeight;
  141.     Canvas.Brush.Color := clLtGray;
  142.     Canvas.FillRect(rect);
  143.  
  144.     // Display the list items.
  145.     x := ValueText.Left + ValueText.Width + 5;
  146.     y := ValueText.Top;
  147.     rect.Left := x;
  148.     rect.Right := ClientWidth;
  149.     cell_ptr := @top_sentinel;
  150.     for i := 0 to num_items + 1 do
  151.     begin
  152.         if (i = selected) then
  153.         begin
  154.             Canvas.Brush.Color := clBlack;
  155.             Canvas.Font.Color := clLtGray;
  156.         end else begin
  157.             Canvas.Brush.Color := clLtGray;
  158.             Canvas.Font.Color := clBlack;
  159.         end;
  160.         // Fill in the item's background.
  161.         rect.Top := y;
  162.         rect.Bottom := y + HGT;
  163.         Canvas.FillRect(rect);
  164.  
  165.         // Display the text.
  166.         if (i = 0) then
  167.             Canvas.TextOut(x, y, '<top sentinel>')
  168.         else if (i > num_items) then
  169.             Canvas.TextOut(x, y, '<bottom sentinel>')
  170.         else
  171.             Canvas.TextOut(x, y, cell_ptr^.Value);
  172.         y := y + HGT + GAP;
  173.  
  174.         // Move to the next cell.
  175.         cell_ptr := cell_ptr^.NextCell;
  176.     end;
  177. end;
  178.  
  179. // Redraw the list.
  180. procedure TLinkedListForm.FormPaint(Sender: TObject);
  181. begin
  182.     DrawList;
  183. end;
  184.  
  185. // Select the item clicked.
  186. procedure TLinkedListForm.FormMouseUp(Sender: TObject;
  187.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  188. var
  189.     i : Longint;
  190. begin
  191.     // Do nothing if the mouse is too far left.
  192.     if ((X < ValueText.Left + ValueText.Width + 5) or
  193.         (Y < ValueText.Top))
  194.     then
  195.         selected := -1
  196.     else begin
  197.         // See which item number it is.
  198.         i := (y - ValueText.Top) div (HGT + GAP);
  199.         if ((i >= 0) and (i <= num_items)) then
  200.             selected := i
  201.         else
  202.             selected := -1;
  203.     end;
  204.  
  205.     // Redraw the list.
  206.     DrawList;
  207.  
  208.     // Enable the appropriate buttons.
  209.     EnableButtons;
  210. end;
  211.  
  212. procedure TLinkedListForm.EnableButtons;
  213. begin
  214.     CmdInsert.Enabled := (ValueText.Text <> '');
  215.     CmdRemoveAfter.Enabled := ((selected >= 0) and
  216.         (selected < num_items));
  217. end;
  218.  
  219. // Free all the linked list memory.
  220. // This doesn't matter for this example program. It would
  221. // be important if the program created and destroyed
  222. // many forms.
  223. procedure TLinkedListForm.FormDestroy(Sender: TObject);
  224. var
  225.     target : PCell;
  226. begin
  227.     while (top_sentinel.NextCell <> @bottom_sentinel) do
  228.     begin
  229.         target := top_sentinel.NextCell;
  230.         top_sentinel.NextCell := target^.NextCell;
  231.         Dispose(target);
  232.     end;
  233. end;
  234.  
  235. end.
  236.