MMMrkLst.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:16k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 01.07.98 - 16:42:02 $                                        =}
  24. {========================================================================}
  25. unit MMMrkLst;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.   Windows,
  31. {$ELSE}
  32.   WinProcs,
  33.   WinTypes,
  34. {$ENDIF}
  35.   SysUtils,
  36.   Classes,
  37.   MMObj,
  38.   MMMuldiv,
  39.   MMUtils;
  40. type
  41.   PMMMarker = ^TMMMarker;
  42.   TMMMarker = packed record
  43.     ID     : Longint;
  44.     NextID : Longint;
  45.     Offset : Longint;
  46.     Name   : string[80];
  47.     Comment: string[255];
  48.     Fixed  : Boolean;
  49.     Visible: Boolean;
  50.     Color  : Longint;
  51.     User   : Longint;
  52.     Flags  : Longint;
  53.   end;
  54. const
  55.   { Maximum List size }
  56.   {$IFDEF WIN32}
  57.   MaxMrkListSize = Maxint div (sizeOf(TMMMarker));
  58.   {$ELSE}
  59.   MaxMrkListSize = 65520 div sizeOf(TMMMarker);
  60.   {$ENDIF}
  61. type
  62.   PMMMarkerArray = ^TMMMarkerArray;
  63.   TMMMarkerArray = array[0..MaxMrkListSize-1] of TMMMarker;
  64.   TMMMarkerList = class(TMMObject)
  65.   private
  66.     FList       : PMMMarkerArray;
  67.     FCount      : Integer;
  68.     FCapacity   : Integer;
  69.   protected
  70.     procedure Error; virtual;
  71.     procedure Grow; virtual;
  72.     function  Add(Marker: TMMMarker): Integer;
  73.     function  Get(Index: Integer): PMMMarker;
  74.     procedure Put(Index: Integer; Marker: PMMMarker);
  75.     procedure SetCapacity(NewCapacity: Integer);
  76.     procedure SetCount(NewCount: Integer);
  77.   public
  78.     constructor Create; virtual;
  79.     destructor  Destroy; override;
  80.     procedure  Clear; virtual;
  81.     procedure  Assign(Source: TPersistent); override;
  82.     procedure  AddMarker(Marker: TMMMarker);
  83.     procedure  Insert(Index: Integer; Marker: TMMMarker);
  84.     procedure  Exchange(Index1, Index2: Integer);
  85.     procedure  Move(CurIndex, NewIndex: Integer);
  86.     function   Remove(Marker: PMMMarker): Integer;
  87.     procedure  Delete(Index: Integer);
  88.     function   IndexOf(Marker: PMMMarker): Integer;
  89.     function   FindFreeID: Longint;
  90.     function   LocateMarker(Offset: Longint): integer;
  91.     function   FindMarker(Offset: Longint): integer;
  92.     function   FindConnectedMarker(Index: integer): integer;
  93.     function   QueryMarker(Offset: Longint): Boolean;
  94.     procedure  Sort;
  95.     function   First: PMMMarker;
  96.     function   Last: PMMMarker;
  97.     function   Expand: TMMMarkerList;
  98.     procedure  SetOffset(Index: integer; Offset: Longint);
  99.     procedure  SetColor(Index: integer; Color: Longint);
  100.     property   OnChange;
  101.     property   OnChanging;
  102.     property   Capacity: Integer read FCapacity write SetCapacity;
  103.     property   Count: Integer read FCount write SetCount;
  104.     property   Markers[Index: Integer]: PMMMarker read Get write Put; default;
  105.     property   List: PMMMarkerArray read FList;
  106.   end;
  107. function  CompareMarkers(Marker1,Marker2: PMMMarker): Boolean;
  108. implementation
  109. uses
  110.     Consts
  111.     {$IFDEF DELPHI6}
  112.     ,RTLConsts
  113.     {$ENDIF}
  114.     ;
  115. {------------------------------------------------------------------------}
  116. function CompareMarkers(Marker1,Marker2: PMMMarker): Boolean;
  117. begin
  118.    Result := (Marker1^.Offset = Marker2^.Offset);
  119. end;
  120. {------------------------------------------------------------------------}
  121. {$IFDEF DELPHI3}
  122. procedure ListError(const Ident: string);
  123. begin
  124.    raise EListError.Create(Ident);
  125. end;
  126. {$ELSE}
  127. procedure ListError(Ident: Word);
  128. begin
  129.    raise EListError.CreateRes(Ident);
  130. end;
  131. {$ENDIF}
  132. {------------------------------------------------------------------------}
  133. procedure ListIndexError;
  134. begin
  135.    ListError(SListIndexError);
  136. end;
  137. {== TMMMarkerList ========================================================}
  138. constructor TMMMarkerList.Create;
  139. begin
  140.    inherited Create;
  141.    FList := nil;
  142. end;
  143. {-- TMMMarkerList --------------------------------------------------------}
  144. destructor TMMMarkerList.Destroy;
  145. begin
  146.    OnChange   := nil;
  147.    OnChanging := nil;
  148.    Clear;
  149.    inherited Destroy;
  150. end;
  151. {-- TMMMarkerList --------------------------------------------------------}
  152. procedure TMMMarkerList.Error;
  153. begin
  154.    ListIndexError;
  155. end;
  156. {-- TMMMarkerList --------------------------------------------------------}
  157. function TMMMarkerList.Add(Marker: TMMMarker): Integer;
  158. begin
  159.    Changing;
  160.    Result := FCount;
  161.    if Result = FCapacity then Grow;
  162.    FList^[Result] := Marker;
  163.    Inc(FCount);
  164.    Changed;
  165. end;
  166. {-- TMMMarkerList --------------------------------------------------------}
  167. { AddMarker f黦t einen Punkt in die Liste ein }
  168. procedure TMMMarkerList.AddMarker(Marker: TMMMarker);
  169. var
  170.   i: integer;
  171. begin
  172.    i := LocateMarker(Marker.Offset);
  173.    if (i < 0) or (i >= Count) then
  174.       Add(Marker)
  175.    else
  176.       Insert(i, Marker);
  177. end;
  178. {-- TMMMarkerList --------------------------------------------------------}
  179. procedure TMMMarkerList.Clear;
  180. begin
  181.    Changing;
  182.    SetCount(0);
  183.    SetCapacity(0);
  184.    Changed;
  185. end;
  186. {-- TMMMarkerList --------------------------------------------------------}
  187. procedure TMMMarkerList.Delete(Index: Integer);
  188. begin
  189.    if (Index < 0) or (Index >= FCount) then Error;
  190.    Changing;
  191.    Dec(FCount);
  192.    if Index < FCount then
  193.      System.Move(FList^[Index + 1], FList^[Index],
  194.                  (FCount - Index) * SizeOf(TMMMarker));
  195.    Changed;
  196. end;
  197. {-- TMMMarkerList --------------------------------------------------------}
  198. procedure TMMMarkerList.Exchange(Index1, Index2: Integer);
  199. var
  200.   Marker: TMMMarker;
  201. begin
  202.    if (Index1 < 0) or (Index1 >= FCount) then Error;
  203.    if (Index2 < 0) or (Index2 >= FCount) then Error;
  204.    Changing;
  205.    Marker := FList^[Index1];
  206.    FList^[Index1] := FList^[Index2];
  207.    FList^[Index2] := Marker;
  208.    Changed;
  209. end;
  210. {-- TMMMarkerList --------------------------------------------------------}
  211. function TMMMarkerList.Expand: TMMMarkerList;
  212. begin
  213.    if FCount = FCapacity then Grow;
  214.    Result := Self;
  215. end;
  216. {-- TMMMarkerList --------------------------------------------------------}
  217. function TMMMarkerList.First: PMMMarker;
  218. begin
  219.    Result := Get(0);
  220. end;
  221. {-- TMMMarkerList --------------------------------------------------------}
  222. function TMMMarkerList.Get(Index: Integer): PMMMarker;
  223. begin
  224.    if (Index < 0) or (Index >= FCount) then Error;
  225.    Result := @FList^[Index];
  226. end;
  227. {-- TMMMarkerList --------------------------------------------------------}
  228. procedure TMMMarkerList.Grow;
  229. var
  230.   Delta: Integer;
  231. begin
  232.    if FCapacity > 8 then
  233.       Delta := 16
  234.    else if FCapacity > 4 then
  235.       Delta := 8
  236.    else
  237.       Delta := 4;
  238.   SetCapacity(FCapacity + Delta);
  239. end;
  240. {-- TMMMarkerList --------------------------------------------------------}
  241. function TMMMarkerList.IndexOf(Marker: PMMMarker): Integer;
  242. begin
  243.    Result := 0;
  244.    while (Result < FCount) and not CompareMarkers(@FList^[Result],Marker) do Inc(Result);
  245.    if Result = FCount then Result := -1;
  246. end;
  247. {-- TMMMarkerList --------------------------------------------------------}
  248. procedure TMMMarkerList.Insert(Index: Integer; Marker: TMMMarker);
  249. begin
  250.    if (Index < 0) or (Index > FCount) then Error;
  251.    Changing;
  252.    if FCount = FCapacity then Grow;
  253.    if Index < FCount then
  254.       System.Move(FList^[Index], FList^[Index + 1],
  255.                  (FCount - Index) * SizeOf(TMMMarker));
  256.    FList^[Index] := Marker;
  257.    Inc(FCount);
  258.    Changed;
  259. end;
  260. {-- TMMMarkerList --------------------------------------------------------}
  261. function TMMMarkerList.Last: PMMMarker;
  262. begin
  263.    Result := Get(FCount-1);
  264. end;
  265. {-- TMMMarkerList --------------------------------------------------------}
  266. procedure TMMMarkerList.Move(CurIndex, NewIndex: Integer);
  267. var
  268.   Marker: TMMMarker;
  269. begin
  270.    if CurIndex <> NewIndex then
  271.    begin
  272.       if (NewIndex < 0) or (NewIndex >= FCount) then Error;
  273.       Marker := Get(CurIndex)^;
  274.       Delete(CurIndex);
  275.       Insert(NewIndex, Marker);
  276.    end;
  277. end;
  278. {-- TMMMarkerList --------------------------------------------------------}
  279. procedure TMMMarkerList.Put(Index: Integer; Marker: PMMMarker);
  280. begin
  281.    if (Index < 0) or (Index >= FCount) then Error;
  282.    Changing;
  283.    FList^[Index] := Marker^;
  284.    Changed;
  285. end;
  286. {-- TMMMarkerList --------------------------------------------------------}
  287. function TMMMarkerList.Remove(Marker: PMMMarker): Integer;
  288. begin
  289.    Result := IndexOf(Marker);
  290.    if Result <> -1 then Delete(Result);
  291. end;
  292. {-- TMMMarkerList --------------------------------------------------------}
  293. procedure TMMMarkerList.SetCapacity(NewCapacity: Integer);
  294. begin
  295.    if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then Error;
  296.    if NewCapacity <> FCapacity then
  297.    begin
  298.      {$IFDEF WIN32}
  299.      ReallocMem(FList, NewCapacity * SizeOf(TMMMarker));
  300.      {$ELSE}
  301.      if NewCapacity = 0 then
  302.      begin
  303.         GlobalFreeMem(FList);
  304.         FList := nil;
  305.      end
  306.      else
  307.      begin
  308.         if FCapacity = 0 then
  309.            FList := GlobalAllocPtr(HeapAllocFlags, NewCapacity*sizeOf(TMMMarker))
  310.         else
  311.            FList := GlobalReallocPtr(FList, NewCapacity*sizeOf(TMMMarker), HeapAllocFlags);
  312.         if FList = nil then
  313.            raise EStreamError.Create(LoadStr(SMemoryStreamError));
  314.      end;
  315.      {$ENDIF}
  316.      FCapacity := NewCapacity;
  317.    end;
  318. end;
  319. {-- TMMMarkerList --------------------------------------------------------}
  320. procedure TMMMarkerList.SetCount(NewCount: Integer);
  321. begin
  322.    if (NewCount < 0) or (NewCount > MaxListSize) then Error;
  323.    if NewCount > FCapacity then SetCapacity(NewCount);
  324.    if NewCount > FCount then
  325.       FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(TMMMarker), 0);
  326.    FCount := NewCount;
  327. end;
  328. {-- TMMMarkerList --------------------------------------------------------}
  329. procedure TMMMarkerList.SetOffset(Index: integer; Offset: Longint);
  330. begin
  331.    if (Index < 0) or (Index >= FCount) then Error;
  332.    BeginUpdate;
  333.    try
  334.       Markers[Index]^.Offset := Offset;
  335.       Sort;
  336.    finally
  337.       EndUpdate;
  338.    end;
  339. end;
  340. {-- TMMMarkerList --------------------------------------------------------}
  341. procedure TMMMarkerList.SetColor(Index: integer; Color: Longint);
  342. begin
  343.    if (Index < 0) or (Index >= FCount) then Error;
  344.    if (Color <> Markers[Index]^.Color) then
  345.    begin
  346.       Changing;
  347.       Markers[Index]^.Color := Color;
  348.       Changed;
  349.    end;
  350. end;
  351. {-- TMMMarkerList --------------------------------------------------------}
  352. procedure TMMMarkerList.Assign(Source: TPersistent);
  353. var
  354.    i: integer;
  355.    p: TMMMarker;
  356. begin
  357.    if (Source is TMMMarkerList) or (Source = nil) then
  358.    begin
  359.       if (Source <> Self) then
  360.       begin
  361.          BeginUpdate;
  362.          try
  363.             Clear;
  364.             if (Source <> nil) then
  365.             begin
  366.                for i := 0 to TMMMarkerList(Source).Count-1 do
  367.                begin
  368.                   p := TMMMarkerList(Source).Markers[i]^;
  369.                   Add(p);
  370.                end;
  371.                Sort;
  372.             end;
  373.          finally
  374.             EndUpdate;
  375.          end;
  376.       end;
  377.    end
  378.    else inherited assign(Source);
  379. end;
  380. {-- TMMMarkerList --------------------------------------------------------}
  381. function TMMMarkerList.FindFreeID: Longint;
  382. Label Again;
  383. var
  384.    i: integer;
  385. begin
  386.    Randomize;
  387. Again:
  388.    {$IFDEF WIN32}
  389.    Result := Random(MaxLongint);
  390.    {$ELSE}
  391.    Result := Random(65535);
  392.    {$ENDIF}
  393.    for i := 0 to Count-1 do
  394.    begin
  395.       if (Result <= 0) or (Markers[i]^.ID = Result) then
  396.          goto Again;
  397.    end;
  398. end;
  399. {-- TMMMarkerList --------------------------------------------------------}
  400. { LocatePoint gibt den Index des ersten Markers, der rechts von Offset liegt,
  401.   zurueck. Ist die Liste leer: -1 , gibt es kein rechtes Element mehr: Count(!) }
  402. function TMMMarkerList.LocateMarker(Offset: Longint): integer;
  403. var
  404.    L, H : integer;
  405. begin
  406.    if (Count = 0) then
  407.    begin
  408.       Result := -1;
  409.    end
  410.    else
  411.    begin
  412.       if Markers[Count-1]^.Offset <= Offset then
  413.       begin
  414.          Result := Count;
  415.       end
  416.       else
  417.       begin
  418.          L := 0;
  419.          H := Count-1;
  420.          Result := H shr 1;
  421.          while L < H do
  422.          begin
  423.             if (Markers[Result]^.Offset <= Offset) then
  424.                L := Result+1
  425.             else
  426.                H := Result;
  427.             Result := (L + H) shr 1;
  428.          end;
  429.       end;
  430.    end;
  431. end;
  432. {-- TMMMarkerList --------------------------------------------------------}
  433. { QueryPoint returns true if a new marker is allowed at "Offset"          }
  434. function TMMMarkerList.QueryMarker(Offset: Longint): Boolean;
  435. begin
  436.    Result := Findmarker(Offset) = -1;
  437. end;
  438. {-- TMMMarkerList --------------------------------------------------------}
  439. { FindMarker gibt genau den Index des Markers zurueck, oder -1 }
  440. function TMMMarkerList.FindMarker(Offset: Longint): integer;
  441. var
  442.   i : integer;
  443. begin
  444.    Result := -1;
  445.    i := LocateMarker(Offset);
  446.    if (i > 0) and (i <= Count) then
  447.    begin
  448.       if Offset = Markers[i-1]^.Offset then
  449.       begin
  450.          Result := i-1;
  451.       end;
  452.    end
  453.    else if (i = 0) and (Count > 0) then
  454.    begin
  455.       if Offset = Markers[i]^.Offset then
  456.       begin
  457.          Result := i;
  458.       end;
  459.    end;
  460. end;
  461. {-- TMMMarkerList --------------------------------------------------------}
  462. { FindConnectedMarker gibt den Index eines zugeh鰎igen  Markers zurueck }
  463. function TMMMarkerList.FindConnectedMarker(index: integer): integer;
  464. var
  465.   i : integer;
  466. begin
  467.    Result := -1;
  468.    if (Index < 0) or (Index >= FCount) then Error;
  469.    
  470.    if (Markers[Index]^.NextID > 0) then
  471.    begin
  472.       for i := 0 to Count-1 do
  473.       begin
  474.          if (Markers[i]^.ID = Markers[Index]^.NextID) then
  475.          begin
  476.             Result := i;
  477.             exit;
  478.          end;
  479.       end;
  480.    end;
  481. end;
  482. {-- TMMMarkerList --------------------------------------------------------}
  483. procedure TMMMarkerList.Sort;
  484. var
  485.    i,j,h: integer;
  486.    m: TMMMarker;
  487. begin          { Start Shell-Sort }
  488.    h := 1;
  489.    while h <= Count div 9 do h := h*3 + 1;
  490.    while h > 0 do
  491.    begin
  492.       for i := h to Count-1 do
  493.       begin
  494.          m := Markers[i]^;
  495.          j := i;
  496.          while (j >= h) and (Markers[j-h]^.Offset > m.Offset) do
  497.          begin
  498.             Markers[j]^ := Markers[j-h]^;
  499.             dec(j, h);
  500.          end;
  501.          Markers[j]^ := m;
  502.       end;
  503.       h := h div 3;
  504.    end;
  505. end;
  506. end.