home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vp21beta.zip / ATVSRC.RAR / COLORSEL.PAS < prev    next >
Pascal/Delphi Source File  |  2000-08-15  |  28KB  |  1,163 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {       Turbo Pascal Version 7.0                        }
  4. {       Turbo Vision Unit                               }
  5. {                                                       }
  6. {       Copyright (c) 1992 Borland International        }
  7. {                                                       }
  8. {       Virtual Pascal v2.1                             }
  9. {       Copyright (C) 1996-2000 vpascal.com             }
  10. {                                                       }
  11. {*******************************************************}
  12.  
  13.  
  14. unit ColorSel;
  15.  
  16. {$X+,I-,S-,Cdecl-,Use32+}
  17.  
  18. interface
  19.  
  20. uses Objects, Drivers, Views, Dialogs;
  21.  
  22. const
  23.   cmColorForegroundChanged = 71;
  24.   cmColorBackgroundChanged = 72;
  25.   cmColorSet               = 73;
  26.   cmNewColorItem           = 74;
  27.   cmNewColorIndex          = 75;
  28.   cmSaveColorIndex         = 76;
  29.  
  30.   cBackgroundBlink: Boolean = False;
  31.  
  32. { True: 8 available/selectable background colors}
  33. { False:16 available/selectable colors}
  34.  
  35. type
  36.  
  37.   { TColorItem }
  38.  
  39.   PColorItem = ^TColorItem;
  40.   TColorItem = record
  41.     Name: PString;
  42.     Index: Byte;
  43.     Next: PColorItem;
  44.   end;
  45.  
  46.   { TColorGroup }
  47.  
  48.   PColorGroup = ^TColorGroup;
  49.   TColorGroup = record
  50.     Name:  PString;
  51.     Index: Byte;
  52.     Items: PColorItem;
  53.     Next:  PColorGroup;
  54.   end;
  55.  
  56.   { TColorIndexes }
  57.  
  58.   PColorIndex = ^TColorIndex;
  59.   TColorIndex = record
  60.     GroupIndex: byte;
  61.     ColorSize: byte;
  62.     ColorIndex: array[0..255] of byte;
  63.   end;
  64.  
  65.   { TColorSelector }
  66.  
  67.   TColorSel = (csBackground, csForeground);
  68.  
  69.   PColorSelector = ^TColorSelector;
  70.   TColorSelector = object(TView)
  71.     Color: Byte;
  72.     SelType: TColorSel;
  73.     constructor Init(var Bounds: TRect; ASelType: TColorSel);
  74.     constructor Load(var S: TStream);
  75.     procedure Draw; virtual;
  76.     procedure HandleEvent(var Event: TEvent); virtual;
  77.     procedure Store(var S: TStream);
  78.   end;
  79.  
  80.   { TMonoSelector }
  81.  
  82.   PMonoSelector = ^TMonoSelector;
  83.   TMonoSelector = object(TCluster)
  84.     constructor Init(var Bounds: TRect);
  85.     procedure Draw; virtual;
  86.     procedure HandleEvent(var Event: TEvent); virtual;
  87.     function Mark(Item: Integer): Boolean; virtual;
  88.     procedure NewColor;
  89.     procedure Press(Item: Integer); virtual;
  90.     procedure MovedTo(Item: Integer); virtual;
  91.   end;
  92.  
  93.   { TColorDisplay }
  94.  
  95.   PColorDisplay = ^TColorDisplay;
  96.   TColorDisplay = object(TView)
  97.     Color: ^Byte;
  98.     Text: PString;
  99.     constructor Init(var Bounds: TRect; AText: PString);
  100.     constructor Load(var S: TStream);
  101.     destructor Done; virtual;
  102.     procedure Draw; virtual;
  103.     procedure HandleEvent(var Event: TEvent); virtual;
  104.     procedure SetColor(var AColor: Byte); virtual;
  105.     procedure Store(var S: TStream);
  106.   end;
  107.  
  108.   { TColorGroupList }
  109.  
  110.   PColorGroupList = ^TColorGroupList;
  111.   TColorGroupList = object(TListViewer)
  112.     Groups: PColorGroup;
  113.     constructor Init(var Bounds: TRect; AScrollBar: PScrollBar;
  114.       AGroups: PColorGroup);
  115.     constructor Load(var S: TStream);
  116.     destructor Done; virtual;
  117.     procedure FocusItem(Item: Integer); virtual;
  118.     function GetText(Item: Integer; MaxLen: Integer): String; virtual;
  119.     procedure HandleEvent(var Event: TEvent); virtual;
  120.     procedure Store(var S: TStream);
  121.     procedure SetGroupIndex(GroupNum, ItemNum: Byte);
  122.     function GetGroup(GroupNum: Byte): PColorGroup;
  123.     function GetGroupIndex(GroupNum: Byte): Byte;
  124.     function GetNumGroups: byte;
  125.   end;
  126.  
  127.   { TColorItemList }
  128.  
  129.   PColorItemList = ^TColorItemList;
  130.   TColorItemList = object(TListViewer)
  131.     Items: PColorItem;
  132.     constructor Init(var Bounds: TRect; AScrollBar: PScrollBar;
  133.       AItems: PColorItem);
  134.     procedure FocusItem(Item: Integer); virtual;
  135.     function GetText(Item: Integer; MaxLen: Integer): String; virtual;
  136.     procedure HandleEvent(var Event: TEvent); virtual;
  137.   end;
  138.  
  139.   { TColorDialog }
  140.  
  141.   PColorDialog = ^TColorDialog;
  142.   TColorDialog = object(TDialog)
  143.     GroupIndex: byte;
  144.     Display: PColorDisplay;
  145.     Groups: PColorGroupList;
  146.     ForLabel: PLabel;
  147.     ForSel: PColorSelector;
  148.     BakLabel: PLabel;
  149.     BakSel: PColorSelector;
  150.     MonoLabel: PLabel;
  151.     MonoSel: PMonoSelector;
  152.     Pal: TPalette;
  153.     constructor Init(APalette: TPalette; AGroups: PColorGroup);
  154.     constructor Load(var S: TStream);
  155.     function DataSize: Word; virtual;
  156.     procedure GetData(var Rec); virtual;
  157.     procedure HandleEvent(var Event: TEvent); virtual;
  158.     procedure SetData(var Rec); virtual;
  159.     procedure Store(var S: TStream);
  160.     procedure GetIndexes(var Colors: PColorIndex);
  161.     procedure SetIndexes(var Colors: PColorIndex);
  162.   end;
  163.  
  164. { Pointer to saved color list item indexes }
  165. const
  166.   ColorIndexes: PColorIndex = nil;
  167.  
  168. { Load and Store Palette routines }
  169.  
  170. procedure StoreIndexes(var S: TStream);
  171. procedure LoadIndexes(var S: TStream);
  172.  
  173. { Color list building routines }
  174.  
  175. function ColorItem(const Name: String; Index: Byte;
  176.   Next: PColorItem): PColorItem;
  177. function ColorGroup(const Name: String; Items: PColorItem;
  178.   Next: PColorGroup): PColorGroup;
  179.  
  180. { Standard color items functions }
  181.  
  182. function DesktopColorItems(const Next: PColorItem): PColorItem;
  183. function MenuColorItems(const Next: PColorItem): PColorItem;
  184. function DialogColorItems(Palette: Word; const Next: PColorItem): PColorItem;
  185. function WindowColorItems(Palette: Word; const Next: PColorItem): PColorItem;
  186.  
  187. { ColorSel registration procedure }
  188.  
  189. procedure RegisterColorSel;
  190.  
  191. { Stream registration records }
  192.  
  193. const
  194.   RColorSelector: TStreamRec = (
  195.      ObjType: 21;
  196.      VmtLink: Ofs(TypeOf(TColorSelector)^);
  197.      Load:    @TColorSelector.Load;
  198.      Store:   @TColorSelector.Store
  199.   );
  200.  
  201. const
  202.   RMonoSelector: TStreamRec = (
  203.      ObjType: 22;
  204.      VmtLink: Ofs(TypeOf(TMonoSelector)^);
  205.      Load:    @TMonoSelector.Load;
  206.      Store:   @TMonoSelector.Store
  207.   );
  208.  
  209. const
  210.   RColorDisplay: TStreamRec = (
  211.      ObjType: 23;
  212.      VmtLink: Ofs(TypeOf(TColorDisplay)^);
  213.      Load:    @TColorDisplay.Load;
  214.      Store:   @TColorDisplay.Store
  215.   );
  216.  
  217. const
  218.   RColorGroupList: TStreamRec = (
  219.      ObjType: 24;
  220.      VmtLink: Ofs(TypeOf(TColorGroupList)^);
  221.      Load:    @TColorGroupList.Load;
  222.      Store:   @TColorGroupList.Store
  223.   );
  224.  
  225. const
  226.   RColorItemList: TStreamRec = (
  227.      ObjType: 25;
  228.      VmtLink: Ofs(TypeOf(TColorItemList)^);
  229.      Load:    @TColorItemList.Load;
  230.      Store:   @TColorItemList.Store
  231.   );
  232.  
  233. const
  234.   RColorDialog: TStreamRec = (
  235.      ObjType: 26;
  236.      VmtLink: Ofs(TypeOf(TColorDialog)^);
  237.      Load:    @TColorDialog.Load;
  238.      Store:   @TColorDialog.Store
  239.   );
  240.  
  241. implementation
  242.  
  243. { TColorSelector }
  244.  
  245. constructor TColorSelector.Init(var Bounds: TRect; ASelType: TColorSel);
  246. begin
  247.   TView.Init(Bounds);
  248.   Options := Options or (ofSelectable + ofFirstClick + ofFramed);
  249.   EventMask := EventMask or evBroadcast;
  250.   SelType := ASelType;
  251.   Color := 0;
  252. end;
  253.  
  254. constructor TColorSelector.Load(var S: TStream);
  255. begin
  256.   TView.Load(S);
  257.   S.Read(Color, SizeOf(Byte) + SizeOf(TColorSel));
  258. end;
  259.  
  260. procedure TColorSelector.Draw;
  261. var
  262.   B: TDrawBuffer;
  263.   C, I, J: Integer;
  264. begin
  265.   MoveChar(B, ' ', $70, Size.X);
  266.   for I := 0 to Size.Y do
  267.   begin
  268.     if I < 4 then
  269.       for J := 0 to 3 do
  270.       begin
  271.         C := I * 4 + J;
  272.         MoveChar(B[ J*3 ], #219, C, 3);
  273.         if C = Byte(Color) then
  274.         begin
  275.           WordRec(B[ J*3+1 ]).Lo := 8;
  276.           if C = 0 then WordRec(B[ J*3+1 ]).Hi := $70;
  277.         end;
  278.       end;
  279.     WriteLine(0, I, Size.X, 1, B);
  280.   end;
  281. end;
  282.  
  283. procedure TColorSelector.HandleEvent(var Event: TEvent);
  284. const
  285.   Width = 4;
  286. var
  287.   MaxCol: Byte;
  288.   Mouse: TPoint;
  289.   OldColor: Byte;
  290.  
  291. procedure ColorChanged;
  292. var
  293.   Msg: Integer;
  294. begin
  295.   if SelType = csForeground then
  296.     Msg := cmColorForegroundChanged else
  297.     Msg := cmColorBackgroundChanged;
  298.   Message(Owner, evBroadcast, Msg, Pointer(Color));
  299. end;
  300.  
  301. begin
  302.   TView.HandleEvent(Event);
  303.   case Event.What of
  304.     evMouseDown:
  305.       begin
  306.         OldColor := Color;
  307.         repeat
  308.           if MouseInView(Event.Where) then
  309.           begin
  310.             MakeLocal(Event.Where, Mouse);
  311.             Color := Mouse.Y * 4 + Mouse.X div 3;
  312.           end
  313.           else
  314.             Color := OldColor;
  315.           ColorChanged;
  316.           DrawView;
  317.         until not MouseEvent(Event, evMouseMove);
  318.       end;
  319.     evKeyDown:
  320.       begin
  321.         if (SelType = csBackground) And cBackgroundBlink then
  322.           MaxCol := 7 else
  323.           MaxCol := 15;
  324.         case CtrlToArrow(Event.KeyCode) of
  325.           kbLeft:
  326.             if Color > 0 then
  327.               Dec(Color) else
  328.               Color := MaxCol;
  329.           kbRight:
  330.             if Color < MaxCol then
  331.               Inc(Color) else
  332.               Color := 0;
  333.           kbUp:
  334.             if Color > Width - 1 then
  335.               Dec(Color, Width) else
  336.               if Color = 0 then
  337.                 Color := MaxCol else
  338.                 Inc(Color, MaxCol - Width);
  339.           kbDown:
  340.             if Color < MaxCol - (Width - 1) then
  341.               Inc(Color, Width) else
  342.               if Color = MaxCol then
  343.                 Color := 0 else
  344.                 Dec(Color, MaxCol - Width);
  345.         else
  346.           Exit;
  347.         end;
  348.       end;
  349.     evBroadcast:
  350.       if Event.Command = cmColorSet then
  351.       begin
  352.         if SelType = csBackground then
  353.           Color := Event.InfoByte shr 4 else
  354.           Color := Event.InfoByte and $0F;
  355.         DrawView;
  356.         Exit;
  357.       end else Exit;
  358.   else
  359.     Exit;
  360.   end;
  361.   DrawView;
  362.   ColorChanged;
  363.   ClearEvent(Event);
  364. end;
  365.  
  366. procedure TColorSelector.Store(var S: TStream);
  367. begin
  368.   TView.Store(S);
  369.   S.Write(Color, SizeOf(Byte) + SizeOf(TColorSel));
  370. end;
  371.  
  372. { TMonoSelector }
  373.  
  374. const
  375.   MonoColors: array[0..4] of Byte = ($07, $0F, $01, $70, $09);
  376.  
  377. constructor TMonoSelector.Init(var Bounds: TRect);
  378. begin
  379.   TCluster.Init(Bounds,
  380.     NewSItem('Normal',
  381.     NewSItem('Highlight',
  382.     NewSItem('Underline',
  383.     NewSItem('Inverse', nil)))));
  384.   EventMask := EventMask or evBroadcast;
  385. end;
  386.  
  387. procedure TMonoSelector.Draw;
  388. const
  389.   Button = ' ( ) ';
  390. begin
  391.   DrawBox(Button, #7);
  392. end;
  393.  
  394. procedure TMonoSelector.HandleEvent(var Event: TEvent);
  395. begin
  396.   TCluster.HandleEvent(Event);
  397.   if (Event.What = evBroadcast) and (Event.Command = cmColorSet) then
  398.   begin
  399.     Value := Event.InfoByte;
  400.     DrawView;
  401.   end;
  402. end;
  403.  
  404. function TMonoSelector.Mark(Item: Integer): Boolean;
  405. begin
  406.   Mark := MonoColors[Item] = Value;
  407. end;
  408.  
  409. procedure TMonoSelector.NewColor;
  410. begin
  411.   Message(Owner, evBroadcast, cmColorForegroundChanged,
  412.     Pointer(Value and $0F));
  413.   Message(Owner, evBroadcast, cmColorBackgroundChanged,
  414.     Pointer((Value shr 4) and $0F));
  415. end;
  416.  
  417. procedure TMonoSelector.Press(Item: Integer);
  418. begin
  419.   Value := MonoColors[Item];
  420.   NewColor;
  421. end;
  422.  
  423. procedure TMonoSelector.MovedTo(Item: Integer);
  424. begin
  425.   Value := MonoColors[Item];
  426.   NewColor;
  427. end;
  428.  
  429. { TColorDisplay }
  430.  
  431. constructor TColorDisplay.Init(var Bounds: TRect; AText: PString);
  432. begin
  433.   TView.Init(Bounds);
  434.   EventMask := EventMask or evBroadcast;
  435.   Text := AText;
  436.   Color := nil;
  437. end;
  438.  
  439. constructor TColorDisplay.Load(var S: TStream);
  440. begin
  441.   TView.Load(S);
  442.   Text := S.ReadStr;
  443. end;
  444.  
  445. destructor TColorDisplay.Done;
  446. begin
  447.   DisposeStr(Text);
  448.   TView.Done;
  449. end;
  450.  
  451. procedure TColorDisplay.Draw;
  452. var
  453.   B: TDrawBuffer;
  454.   I: Integer;
  455.   C: Byte;
  456. begin
  457.   C := Color^;
  458.   if C = 0 then C := ErrorAttr;
  459.   for I := 0 to Size.X div Length(Text^) do
  460.     MoveStr(B[I*Length(Text^)], Text^, C);
  461.   WriteLine(0, 0, Size.X, Size.Y, B);
  462. end;
  463.  
  464. procedure TColorDisplay.HandleEvent(var Event: TEvent);
  465. begin
  466.   TView.HandleEvent(Event);
  467.   case Event.What of
  468.     evBroadcast:
  469.       case Event.Command of
  470.         cmColorBackgroundChanged:
  471.           begin
  472.             Color^ := (Color^ and $0F) or (Event.InfoByte shl 4 and $F0);
  473.             DrawView;
  474.           end;
  475.         cmColorForegroundChanged:
  476.           begin
  477.             Color^ := (Color^ and $F0) or (Event.InfoByte and $0F);
  478.             DrawView;
  479.           end;
  480.       end;
  481.   end;
  482. end;
  483.  
  484. procedure TColorDisplay.SetColor(var AColor: Byte);
  485. begin
  486.   Color := @AColor;
  487.   Message(Owner, evBroadcast, cmColorSet, Pointer(Color^));
  488.   DrawView;
  489. end;
  490.  
  491. procedure TColorDisplay.Store(var S: TStream);
  492. begin
  493.   TView.Store(S);
  494.   S.WriteStr(Text);
  495. end;
  496.  
  497. { TColorGroupList }
  498.  
  499. constructor TColorGroupList.Init(var Bounds: TRect; AScrollBar: PScrollBar;
  500.   AGroups: PColorGroup);
  501. var
  502.   I: Integer;
  503. begin
  504.   TListViewer.Init(Bounds, 1, nil, AScrollBar);
  505.   Groups := AGroups;
  506.   I := 0;
  507.   while AGroups <> nil do
  508.   begin
  509.     AGroups := AGroups^.Next;
  510.     Inc(I);
  511.   end;
  512.   SetRange(I);
  513. end;
  514.  
  515. constructor TColorGroupList.Load(var S: TStream);
  516.  
  517. function ReadItems: PColorItem;
  518. var
  519.   Itms:  PColorItem;
  520.   CurItm: ^PColorItem;
  521.   Count, I: Integer;
  522. begin
  523.   S.Read(Count, SizeOf(Integer));
  524.   Itms := nil;
  525.   CurItm := @Itms;
  526.   for I := 1 to Count do
  527.   begin
  528.     New(CurItm^);
  529.     with CurItm^^ do
  530.     begin
  531.       Name := S.ReadStr;
  532.       S.Read(Index, SizeOf(Byte));
  533.     end;
  534.     CurItm := @CurItm^^.Next;
  535.   end;
  536.   CurItm^ := nil;
  537.   ReadItems := Itms;
  538. end;
  539.  
  540. function ReadGroups: PColorGroup;
  541. var
  542.   Grps:  PColorGroup;
  543.   CurGrp: ^PColorGroup;
  544.   Count, I: Integer;
  545. begin
  546.   S.Read(Count, SizeOf(Integer));
  547.   Grps := nil;
  548.   CurGrp := @Grps;
  549.   for I := 1 to Count do
  550.   begin
  551.     New(CurGrp^);
  552.     with CurGrp^^ do
  553.     begin
  554.       Name := S.ReadStr;
  555.       Items := ReadItems;
  556.     end;
  557.     CurGrp := @CurGrp^^.Next;
  558.   end;
  559.   CurGrp^ := nil;
  560.   ReadGroups := Grps;
  561. end;
  562.  
  563. begin
  564.   TListViewer.Load(S);
  565.   Groups := ReadGroups;
  566. end;
  567.  
  568. destructor TColorGroupList.Done;
  569.  
  570. procedure FreeItems(CurITem: PColorItem);
  571. var
  572.   P: PColorItem;
  573. begin
  574.   while CurItem <> nil do
  575.   begin
  576.     P := CurItem;
  577.     DisposeStr(CurItem^.Name);
  578.     CurItem := CurItem^.Next;
  579.     Dispose(P);
  580.   end;
  581. end;
  582.  
  583. procedure FreeGroups(CurGroup: PColorGroup);
  584. var
  585.   P: PColorGroup;
  586. begin
  587.   while CurGroup <> nil do
  588.   begin
  589.     P := CurGroup;
  590.     FreeItems(CurGroup^.Items);
  591.     DisposeStr(CurGroup^.Name);
  592.     CurGroup := CurGroup^.Next;
  593.     Dispose(P);
  594.   end
  595. end;
  596.  
  597. begin
  598.   TListViewer.Done;
  599.   FreeGroups(Groups);
  600. end;
  601.  
  602. procedure TColorGroupList.FocusItem(Item: Integer);
  603. var
  604.   CurGroup: PColorGroup;
  605. begin
  606.   TListViewer.FocusItem(Item);
  607.   CurGroup := Groups;
  608.   while Item > 0 do
  609.   begin
  610.     CurGroup := CurGroup^.Next;
  611.     Dec(Item);
  612.   end;
  613.   Message(Owner, evBroadcast, cmNewColorItem, CurGroup);
  614. end;
  615.  
  616. function TColorGroupList.GetText(Item: Integer; MaxLen: Integer): String;
  617. var
  618.   CurGroup: PColorGroup;
  619.   I: Integer;
  620. begin
  621.   CurGroup := Groups;
  622.   while Item > 0 do
  623.   begin
  624.     CurGroup := CurGroup^.Next;
  625.     Dec(Item);
  626.   end;
  627.   GetText := CurGroup^.Name^;
  628. end;
  629.  
  630. procedure TColorGroupList.Store(var S: TStream);
  631.  
  632. procedure WriteItems(Items: PColorItem);
  633. var
  634.   CurItm: PColorItem;
  635.   Count: Integer;
  636. begin
  637.   Count := 0;
  638.   CurItm := Items;
  639.   while CurItm <> nil do
  640.   begin
  641.     CurItm := CurItm^.Next;
  642.     Inc(Count);
  643.   end;
  644.   S.Write(Count, SizeOf(Integer));
  645.   CurItm := Items;
  646.   while CurItm <> nil do
  647.   begin
  648.     with CurItm^ do
  649.     begin
  650.       S.WriteStr(Name);
  651.       S.Write(Index, SizeOf(Byte));
  652.     end;
  653.     CurItm := CurItm^.Next;
  654.   end;
  655. end;
  656.  
  657. procedure WriteGroups(Groups: PColorGroup);
  658. var
  659.   CurGrp: PColorGroup;
  660.   Count: Integer;
  661. begin
  662.   Count := 0;
  663.   CurGrp := Groups;
  664.   while CurGrp <> nil do
  665.   begin
  666.     CurGrp := CurGrp^.Next;
  667.     Inc(Count);
  668.   end;
  669.   S.Write(Count, SizeOf(Integer));
  670.   CurGrp := Groups;
  671.   while CurGrp <> nil do
  672.   begin
  673.     with CurGrp^ do
  674.     begin
  675.       S.WriteStr(Name);
  676.       WriteItems(Items);
  677.     end;
  678.     CurGrp := CurGrp^.Next;
  679.   end;
  680. end;
  681.  
  682. begin
  683.   TListViewer.Store(S);
  684.   WriteGroups(Groups);
  685. end;
  686.  
  687. procedure TColorGroupList.HandleEvent(var Event: TEvent);
  688. begin
  689.   TListViewer.HandleEvent(Event);
  690.   if Event.What = evBroadcast then
  691.     if Event.Command = cmSaveColorIndex then
  692.       SetGroupIndex(Focused, Event.InfoByte);
  693. end;
  694.  
  695. procedure TColorGroupList.SetGroupIndex(GroupNum, ItemNum: Byte);
  696. var
  697.   Group: PColorGroup;
  698. begin
  699.   Group := GetGroup(GroupNum);
  700.   if Group <> nil then
  701.     Group^.Index := ItemNum;
  702. end;
  703.  
  704. function TColorGroupList.GetGroupIndex(GroupNum: Byte): byte;
  705. var
  706.   Group: PColorGroup;
  707. begin
  708.   Group := GetGroup(GroupNum);
  709.   if Group <> nil then
  710.     GetGroupIndex := Group^.Index
  711.   else
  712.     GetGroupIndex := 0;
  713. end;
  714.  
  715. function TColorGroupList.GetGroup(GroupNum: Byte): PColorGroup;
  716. var
  717.   Group: PColorGroup;
  718. begin
  719.   Group := Groups;
  720.   while GroupNum > 0 do
  721.   begin
  722.     Group := Group^.Next;
  723.     Dec(GroupNum);
  724.   end;
  725.   GetGroup := Group;
  726. end;
  727.  
  728. function TColorGroupList.GetNumGroups: byte;
  729. var
  730.   Index: byte;
  731.   Group: PColorGroup;
  732. begin
  733.   Index := 0;
  734.   Group := Groups;
  735.   while Group <> nil do
  736.   begin
  737.     Inc(Index);
  738.     Group := Group^.Next;
  739.   end;
  740.   GetNumGroups := Index;
  741. end;
  742.  
  743. { TColorItemList }
  744.  
  745. constructor TColorItemList.Init(var Bounds: TRect; AScrollBar: PScrollBar;
  746.   AItems: PColorItem);
  747. var
  748.   I: Integer;
  749. begin
  750.   TListViewer.Init(Bounds, 1, nil, AScrollBar);
  751.   EventMask := EventMask or evBroadcast;
  752.   Items := AItems;
  753.   I := 0;
  754.   while AItems <> nil do
  755.   begin
  756.     AItems := AItems^.Next;
  757.     Inc(I);
  758.   end;
  759.   SetRange(I);
  760. end;
  761.  
  762. procedure TColorItemList.FocusItem(Item: Integer);
  763. var
  764.   CurItem: PColorItem;
  765. begin
  766.   TListViewer.FocusItem(Item);
  767.   Message(Owner, evBroadcast, cmSaveColorIndex, Pointer(Item));
  768.   CurItem := Items;
  769.   while Item > 0 do
  770.   begin
  771.     CurItem := CurItem^.Next;
  772.     Dec(Item);
  773.   end;
  774.   Message(Owner, evBroadcast, cmNewColorIndex, Pointer(CurItem^.Index));
  775. end;
  776.  
  777. function TColorItemList.GetText(Item: Integer; MaxLen: Integer): String;
  778. var
  779.   CurItem: PColorItem;
  780. begin
  781.   CurItem := Items;
  782.   while Item > 0 do
  783.   begin
  784.     CurItem := CurItem^.Next;
  785.     Dec(Item);
  786.   end;
  787.   GetText := CurItem^.Name^;
  788. end;
  789.  
  790. procedure TColorItemList.HandleEvent(var Event: TEvent);
  791. var
  792.   CurItem: PColorItem;
  793.   Group: PColorGroup;
  794.   I: Integer;
  795. begin
  796.   TListViewer.HandleEvent(Event);
  797.   if Event.What = evBroadcast then
  798.   case Event.Command of
  799.     cmNewColorItem:
  800.       begin
  801.         Group := Event.InfoPtr;
  802.         Items := Group^.Items;
  803.         CurItem := Items;
  804.         I := 0;
  805.         while CurItem <> nil do
  806.         begin
  807.           CurItem := CurItem^.Next;
  808.           Inc(I);
  809.         end;
  810.         SetRange(I);
  811.         FocusItem(Group^.Index);
  812.         DrawView;
  813.       end;
  814.   end;
  815. end;
  816.  
  817. { TColorDialog }
  818.  
  819. constructor TColorDialog.Init(APalette: TPalette; AGroups: PColorGroup);
  820. var
  821.   R: TRect;
  822.   P: PView;
  823. begin
  824.   R.Assign(0, 0, 61, 18);
  825.   TDialog.Init(R, 'Colors');
  826.   Options := Options or ofCentered;
  827.   Pal := APalette;
  828.  
  829.   R.Assign(18, 3, 19, 14);
  830.   P := New(PScrollBar, Init(R));
  831.   Insert(P);
  832.   R.Assign(3, 3, 18, 14);
  833.   Groups := New(PColorGroupList, Init(R, PScrollBar(P), AGroups));
  834.   Insert(Groups);
  835.   R.Assign(2, 2, 8, 3);
  836.   Insert(New(PLabel, Init(R, '~G~roup', Groups)));
  837.  
  838.   R.Assign(41, 3, 42, 14);
  839.   P := New(PScrollBar, Init(R));
  840.   Insert(P);
  841.   R.Assign(21, 3, 41, 14);
  842.   P := New(PColorItemList, Init(R, PScrollBar(P), AGroups^.Items));
  843.   Insert(P);
  844.   R.Assign(20, 2, 25, 3);
  845.   Insert(New(PLabel, Init(R, '~I~tem', P)));
  846.  
  847.   R.Assign(45, 3, 57, 7);
  848.   ForSel := New(PColorSelector, Init(R, csForeground));
  849.   Insert(ForSel);
  850.   Dec(R.A.Y); R.B.Y := R.A.Y+1;
  851.   ForLabel := New(PLabel, Init(R, '~F~oreground', ForSel));
  852.   Insert(ForLabel);
  853.  
  854.   Inc(R.A.Y, 7); Inc(R.B.Y,10);
  855.   If cBackgroundBlink Then Dec(R.B.Y,2);
  856.   BakSel := New(PColorSelector, Init(R, csBackground));
  857.   Insert(BakSel);
  858.   Dec(R.A.Y); R.B.Y := R.A.Y+1;
  859.   BakLabel := New(PLabel, Init(R, '~B~ackground', BakSel));
  860.   Insert(BakLabel);
  861.  
  862.   Dec(R.A.X); Inc(R.B.X); Inc(R.A.Y, 6); Inc(R.B.Y, 7);
  863.   If cBackgroundBlink Then Begin Dec(R.A.Y,2); Dec(R.B.Y,2); End;
  864.   Display := New(PColorDisplay, Init(R, NewStr('Text ')));
  865.   Insert(Display);
  866.  
  867.   R.Assign(44, 3, 59, 8);
  868.   MonoSel := New(PMonoSelector, Init(R));
  869.   MonoSel^.Hide;
  870.   Insert(MonoSel);
  871.   R.Assign(43, 2, 49, 3);
  872.   MonoLabel := New(PLabel, Init(R, '~C~olor', MonoSel));
  873.   MonoLabel^.Hide;
  874.   Insert(MonoLabel);
  875.  
  876.   if (AGroups <> nil) and (AGroups^.Items <> nil) then
  877.     Display^.SetColor(Byte(Pal[AGroups^.Items^.Index]));
  878.  
  879.   R.Assign(16, 15, 26, 17);
  880.   P := New(PButton, Init(R, 'O~K~', cmOk, bfDefault));
  881.   Insert(P);
  882.   R.Assign(28, 15, 38, 17);
  883.   P := New(PButton, Init(R, 'Cancel', cmCancel, bfNormal));
  884.   Insert(P);
  885.   SelectNext(False);
  886. end;
  887.  
  888. constructor TColorDialog.Load(var S: TStream);
  889. var
  890.   Len: Byte;
  891. begin
  892.   TDialog.Load(S);
  893.   GetSubViewPtr(S, Display);
  894.   GetSubViewPtr(S, Groups);
  895.   GetSubViewPtr(S, ForLabel);
  896.   GetSubViewPtr(S, ForSel);
  897.   GetSubViewPtr(S, BakLabel);
  898.   GetSubViewPtr(S, BakSel);
  899.   GetSubViewPtr(S, MonoLabel);
  900.   GetSubViewPtr(S, MonoSel);
  901.   S.Read(Len, SizeOf(Byte));
  902.   S.Read(Pal[1], Len);
  903.   Pal[0] := Char(Len);
  904. end;
  905.  
  906. procedure TColorDialog.HandleEvent(var Event: TEvent);
  907. var
  908.   C: Byte;
  909.   ItemList: PColorItemList;
  910. begin
  911.   if Event.What = evBroadcast then
  912.     if Event.Command = cmNewColorItem then
  913.       GroupIndex := Groups^.Focused;
  914.   TDialog.HandleEvent(Event);
  915.   if Event.What = evBroadcast then
  916.     if Event.Command = cmNewColorIndex then
  917.       Display^.SetColor(Byte(Pal[Event.InfoByte]));
  918. end;
  919.  
  920. procedure TColorDialog.Store(var S: TStream);
  921. begin
  922.   TDialog.Store(S);
  923.   PutSubViewPtr(S, Display);
  924.   PutSubViewPtr(S, Groups);
  925.   PutSubViewPtr(S, ForLabel);
  926.   PutSubViewPtr(S, ForSel);
  927.   PutSubViewPtr(S, BakLabel);
  928.   PutSubViewPtr(S, BakSel);
  929.   PutSubViewPtr(S, MonoLabel);
  930.   PutSubViewPtr(S, MonoSel);
  931.   S.Write(Pal, Length(Pal)+1);
  932. end;
  933.  
  934. function TColorDialog.DataSize: Word;
  935. begin
  936.   DataSize := SizeOf(TPalette);
  937. end;
  938.  
  939. procedure TColorDialog.GetData(var Rec);
  940. begin
  941.   GetIndexes(ColorIndexes);
  942.   String(Rec) := Pal;
  943. end;
  944.  
  945. procedure TColorDialog.SetData(var Rec);
  946. {var
  947.   Item: PColorItem;
  948.   Index: byte;}
  949. begin
  950.   Pal := String(Rec);
  951.   SetIndexes(ColorIndexes);
  952. {  Display^.SetColor(Byte(Pal[Groups^.GetGroupIndex(GroupIndex)]));}
  953.   Groups^.FocusItem(GroupIndex);
  954.   if ShowMarkers then
  955.   begin
  956.     ForLabel^.Hide;
  957.     ForSel^.Hide;
  958.     BakLabel^.Hide;
  959.     BakSel^.Hide;
  960.     MonoLabel^.Show;
  961.     MonoSel^.Show;
  962.   end;
  963.   Groups^.Select;
  964. end;
  965.  
  966. procedure TColorDialog.SetIndexes(var Colors: PColorIndex);
  967. var
  968.   NumGroups, Index: byte;
  969. begin
  970.   NumGroups := Groups^.GetNumGroups;
  971.   if (Colors <> nil) and (Colors^.ColorSize <> NumGroups) then
  972.   begin
  973.     FreeMem(Colors, 2 + Colors^.ColorSize);
  974.     Colors := nil;
  975.   end;
  976.   if Colors = nil then
  977.   begin
  978.     GetMem(Colors, 2 + NumGroups);
  979.     fillchar(Colors^, 2 + NumGroups, 0);
  980.     Colors^.ColorSize := NumGroups;
  981.   end;
  982.   for Index := 0 to NumGroups - 1 do
  983.     Groups^.SetGroupIndex(Index, Colors^.ColorIndex[Index]);
  984.   GroupIndex := Colors^.GroupIndex;
  985. end;
  986.  
  987. procedure TColorDialog.GetIndexes(var Colors: PColorIndex);
  988. var
  989.   NumGroups, Index: Byte;
  990. begin
  991.   NumGroups := Groups^.GetNumGroups;
  992.   if Colors = nil then
  993.   begin
  994.     GetMem(Colors, 2 + NumGroups);
  995.     fillchar(Colors^, 2 + NumGroups, 0);
  996.     Colors^.ColorSize := NumGroups;
  997.   end;
  998.   Colors^.GroupIndex := GroupIndex;
  999.   for Index := 0 to NumGroups - 1 do
  1000.     Colors^.ColorIndex[Index] := Groups^.GetGroupIndex(Index);
  1001. end;
  1002.  
  1003. { Load and Store Palette routines }
  1004.  
  1005. procedure LoadIndexes(var S: TStream);
  1006. var
  1007.   ColorSize: byte;
  1008. begin
  1009.   S.Read(ColorSize, sizeof(ColorSize));
  1010.   if ColorSize > 0 then
  1011.   begin
  1012.     if ColorIndexes <> nil then
  1013.       FreeMem(ColorIndexes, 2 + ColorIndexes^.ColorSize);
  1014.     getmem(ColorIndexes, ColorSize);
  1015.     S.Read(ColorIndexes^, ColorSize);
  1016.   end;
  1017. end;
  1018.  
  1019. procedure StoreIndexes(var S: TStream);
  1020. var
  1021.   ColorSize: byte;
  1022. begin
  1023.   if ColorIndexes <> nil then
  1024.     ColorSize := 2 + ColorIndexes^.ColorSize
  1025.   else
  1026.     ColorSize := 0;
  1027.   S.Write(ColorSize, sizeof(ColorSize));
  1028.   if ColorSize > 0 then
  1029.     S.Write(ColorIndexes^, ColorSize);
  1030. end;
  1031.  
  1032. { -- Color list building routines -- }
  1033.  
  1034. function ColorItem(const Name: String; Index: Byte;
  1035.   Next: PColorItem): PColorItem;
  1036. var
  1037.   Item: PColorItem;
  1038. begin
  1039.   New(Item);
  1040.   Item^.Name := NewStr(Name);
  1041.   Item^.Index := Index;
  1042.   Item^.Next := Next;
  1043.   ColorItem := Item;
  1044. end;
  1045.  
  1046. function ColorGroup(const Name: String; Items: PColorItem;
  1047.   Next: PColorGroup): PColorGroup;
  1048. var
  1049.   Group: PColorGroup;
  1050. begin
  1051.   New(Group);
  1052.   Group^.Name := NewStr(Name);
  1053.   Group^.Items := Items;
  1054.   Group^.Next := Next;
  1055.   ColorGroup := Group;
  1056. end;
  1057.  
  1058. { Standard color items functions }
  1059.  
  1060. function DesktopColorItems(const Next: PColorItem): PColorItem;
  1061. begin
  1062.   DesktopColorItems :=
  1063.     ColorItem('Color',             1,
  1064.     Next);
  1065. end;
  1066.  
  1067. function MenuColorItems(const Next: PColorItem): PColorItem;
  1068. begin
  1069.   MenuColorItems :=
  1070.     ColorItem('Normal',            2,
  1071.     ColorItem('Disabled',          3,
  1072.     ColorItem('Shortcut',          4,
  1073.     ColorItem('Selected',          5,
  1074.     ColorItem('Selected disabled', 6,
  1075.     ColorItem('Shortcut selected', 7,
  1076.     Next))))));
  1077. end;
  1078.  
  1079. function DialogColorItems(Palette: Word; const Next: PColorItem): PColorItem;
  1080. const
  1081.   COffset: array[dpBlueDialog..dpGrayDialog] of Byte =
  1082.     (64, 96, 32);
  1083.   var
  1084.     Offset: Byte;
  1085. begin
  1086.   Offset := COffset[Palette];
  1087.   DialogColorItems :=
  1088.     ColorItem('Frame/background',  Offset + 1,
  1089.     ColorItem('Frame icons',       Offset + 2,
  1090.     ColorItem('Scroll bar page',   Offset + 3,
  1091.     ColorItem('Scroll bar icons',  Offset + 4,
  1092.     ColorItem('Static text',       Offset + 5,
  1093.  
  1094.     ColorItem('Label normal',      Offset + 6,
  1095.     ColorItem('Label selected',    Offset + 7,
  1096.     ColorItem('Label shortcut',    Offset + 8,
  1097.  
  1098.     ColorItem('Button normal',     Offset + 9,
  1099.     ColorItem('Button default',    Offset + 10,
  1100.     ColorItem('Button selected',   Offset + 11,
  1101.     ColorItem('Button disabled',   Offset + 12,
  1102.     ColorItem('Button shortcut',   Offset + 13,
  1103.     ColorItem('Button shadow',     Offset + 14,
  1104.  
  1105.     ColorItem('Cluster normal',    Offset + 15,
  1106.     ColorItem('Cluster selected',  Offset + 16,
  1107.     ColorItem('Cluster shortcut',  Offset + 17,
  1108.  
  1109.     ColorItem('Input normal',      Offset + 18,
  1110.     ColorItem('Input selected',    Offset + 19,
  1111.     ColorItem('Input arrow',       Offset + 20,
  1112.  
  1113.     ColorItem('History button',    Offset + 21,
  1114.     ColorItem('History sides',     Offset + 22,
  1115.     ColorItem('History bar page',  Offset + 23,
  1116.     ColorItem('History bar icons', Offset + 24,
  1117.  
  1118.     ColorItem('List normal',       Offset + 25,
  1119.     ColorItem('List focused',      Offset + 26,
  1120.     ColorItem('List selected',     Offset + 27,
  1121.     ColorItem('List divider',      Offset + 28,
  1122.  
  1123.     ColorItem('Information pane',  Offset + 29,
  1124.     Next)))))))))))))))))))))))))))));
  1125. end;
  1126.  
  1127. function WindowColorItems(Palette: Word;
  1128.   const Next: PColorItem): PColorItem;
  1129. const
  1130.   COffset: array[wpBlueWindow..wpGrayWindow] of Byte =
  1131.     (8, 16, 24);
  1132. var
  1133.   Offset: Word;
  1134. begin
  1135.   Offset := COffset[Palette];
  1136.   WindowColorItems :=
  1137.     ColorItem('Frame passive',     Offset + 0,
  1138.     ColorItem('Frame active',      Offset + 1,
  1139.     ColorItem('Frame icons',       Offset + 2,
  1140.     ColorItem('Scroll bar page',   Offset + 3,
  1141.     ColorItem('Scroll bar icons',  Offset + 4,
  1142.     ColorItem('Normal text',       Offset + 5,
  1143.     Next))))));
  1144. end;
  1145.  
  1146. { ColorSel registration procedure }
  1147.  
  1148. procedure RegisterColorSel;
  1149. begin
  1150.   RegisterType(RColorSelector);
  1151.   RegisterType(RMonoSelector);
  1152.   RegisterType(RColorDisplay);
  1153.   RegisterType(RColorGroupList);
  1154.   RegisterType(RColorItemList);
  1155.   RegisterType(RColorDialog);
  1156. end;
  1157.  
  1158. initialization
  1159. finalization
  1160.   if assigned(ColorIndexes) then
  1161.     FreeMem(ColorIndexes);
  1162. end.
  1163.