home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / T-Pascal.70 / SOURCE.ZIP / COLORSEL.PAS < prev    next >
Pascal/Delphi Source File  |  1992-10-30  |  28KB  |  1,148 lines

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