(*
    Tux Commander - UChmod - Change permissions dialog
    Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net>
    Check for updates on tuxcmd.sourceforge.net

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*)
unit UChmod;

interface

uses
  SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKMenus;

type
  TFChmod = class(TGTKDialog)
    HBox, HBox2, HBox3: TGTKHBox;
    VBox: TGTKVBox;
    PermissionFrame, FileFrame: TGTKFrame;
    RecursiveCheckButton, cbSUID, cbSGID, cbSticky, cbUSRRead, cbUSRWrite, cbUSRExec, cbGRPRead, cbGRPWrite, cbGRPExec,
    cbALLRead, cbALLWrite, cbALLExec: TGTKCheckButton;
    RecursiveOptionMenu: TGTKOptionMenu;
    miAllFiles, miDirectories, miFiles: TGTKMenuItem;
    FileLabel, OctalLabel, TextLabel: TGTKLabel;
    OctalEntry: TGTKEntry;
    procedure FormCreate(Sender: TObject); override;
    procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean);
    procedure RecursiveCheckButtonToggled(Sender: TObject);
    procedure PermissionsCheckBoxToggle(Sender: TObject);
    procedure OctalEntryChanged(Sender: TObject);
  private
    Busy: boolean;
  public
    LastMode: Cardinal;
    procedure AssignMode(const Mode: Cardinal; const FileName, User, Group: string);
  end;

var
  FChmod: TFChmod;

implementation

uses ULibc, ULocale, UCoreUtils;


procedure TFChmod.FormCreate(Sender: TObject);
begin
  SetDefaultSize(-1, -1);
  LastMode := 0;
  Busy := True;
  Caption := LANGFChmod_Caption;
  Buttons := [mbOK, mbCancel];
  HBox := TGTKHBox.Create(Self);
  HBox.Homogeneous := False;
  HBox.BorderWidth := 6;
  PermissionFrame := TGTKFrame.Create(Self);
  PermissionFrame.Caption := LANGFChmod_PermissionFrame;
  FileFrame := TGTKFrame.Create(Self);
  FileFrame.Caption := LANGFChmod_FileFrame;
  HBox.AddControlEx(PermissionFrame, True, True, 5);
  HBox.AddControlEx(FileFrame, True, True, 5);
  HBox2 := TGTKHBox.Create(Self);
  HBox2.Homogeneous := False;
  HBox2.BorderWidth := 5;
  RecursiveCheckButton := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_ApplyRecursivelyFor);
  RecursiveCheckButton.OnToggled := RecursiveCheckButtonToggled;
  RecursiveOptionMenu := TGTKOptionMenu.Create(Self);
  miAllFiles := TGTKMenuItem.Create(Self);
  miAllFiles.Caption := LANGFChmod_miAllFiles;
  RecursiveOptionMenu.Items.Add(miAllFiles);
  miDirectories := TGTKMenuItem.Create(Self);
  miDirectories.Caption := LANGFChmod_miDirectories;
  RecursiveOptionMenu.Items.Add(miDirectories);
  miFiles := TGTKMenuItem.Create(Self);
  miFiles.Caption := LANGmiFiles_Caption;
  RecursiveOptionMenu.Items.Add(miFiles);
  HBox2.AddControlEx(TGTKLabel.Create(Self), False, False, 10);
  HBox2.AddControlEx(RecursiveCheckButton, False, False, 5);
  HBox2.AddControlEx(RecursiveOptionMenu, False, False, 5);

  HBox3 := TGTKHBox.Create(Self);
  HBox3.Homogeneous := False;
  HBox3.BorderWidth := 5;
  OctalLabel := TGTKLabel.Create(Self);
  OctalLabel.Caption := LANGFChmod_OctalLabel;
  OctalEntry := TGTKEntry.Create(Self);
  OctalEntry.MaxLength := 4;
  OctalEntry.SetSizeRequest(50, -1);
  OctalLabel.FocusControl := OctalEntry;
  OctalLabel.UseUnderline := True;
  TextLabel := TGTKLabel.Create(Self);
  TextLabel.Caption := '<span weight="ultrabold">Text:</span>   rw-rw-r--';
  TextLabel.UseMarkup := True;
  HBox3.AddControlEx(TGTKLabel.Create(Self), False, False, 10);
  HBox3.AddControlEx(OctalLabel, False, False, 5);
  HBox3.AddControlEx(OctalEntry, False, False, 5);
  HBox3.AddControlEx(TGTKVSeparator.Create(Self), False, False, 10);
  HBox3.AddControlEx(TextLabel, False, False, 10);

  ClientArea.AddControlEx(HBox, True, True, 0);
  ClientArea.AddControlEx(TGTKHSeparator.Create(Self), False, False, 5);
  ClientArea.AddControlEx(HBox3, False, False, 0);
  ClientArea.AddControlEx(TGTKHSeparator.Create(Self), False, False, 5);
  ClientArea.AddControlEx(HBox2, False, False, 0);

  FileLabel := TGTKLabel.Create(Self);
  FileLabel.SetAlignment(0, 0);
  FileLabel.SetPadding(10, 5);
  FileLabel.Caption := '<span weight="ultrabold">File:</span> .adobe'#10'<span weight="ultrabold">Text:</span> rw-rw-rw'#10 +
                       '<span weight="ultrabold">Octal:</span> 666'#10'<span weight="ultrabold">Owner:</span> root'#10 +
                       '<span weight="ultrabold">Group:</span> root';
  FileLabel.UseMarkup := True;
  FileFrame.AddControl(FileLabel);

  VBox := TGTKVBox.Create(Self);
  VBox.BorderWidth := 5;
  cbSUID := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_SUID);
  VBox.AddControlEx(cbSUID, False, False, 0);     cbSUID.OnToggled := PermissionsCheckBoxToggle;
  cbSGID := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_SGID);
  VBox.AddControlEx(cbSGID, False, False, 0);     cbSGID.OnToggled := PermissionsCheckBoxToggle;
  cbSticky := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_Sticky);
  VBox.AddControlEx(cbSticky, False, False, 0);     cbSticky.OnToggled := PermissionsCheckBoxToggle;
  VBox.AddControlEx(TGTKHSeparator.Create(Self), False, False, 2);
  cbUSRRead := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_RUSR);
  VBox.AddControlEx(cbUSRRead, False, False, 0);     cbUSRRead.OnToggled := PermissionsCheckBoxToggle;
  cbUSRWrite := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_WUSR);
  VBox.AddControlEx(cbUSRWrite, False, False, 0);     cbUSRWrite.OnToggled := PermissionsCheckBoxToggle;
  cbUSRExec := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_XUSR);
  VBox.AddControlEx(cbUSRExec, False, False, 0);     cbUSRExec.OnToggled := PermissionsCheckBoxToggle;
  VBox.AddControlEx(TGTKHSeparator.Create(Self), False, False, 2);
  cbGRPRead := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_RGRP);
  VBox.AddControlEx(cbGRPRead, False, False, 0);     cbGRPRead.OnToggled := PermissionsCheckBoxToggle;
  cbGRPWrite := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_WGRP);
  VBox.AddControlEx(cbGRPWrite, False, False, 0);     cbGRPWrite.OnToggled := PermissionsCheckBoxToggle;
  cbGRPExec := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_XGRP);
  VBox.AddControlEx(cbGRPExec, False, False, 0);     cbGRPExec.OnToggled := PermissionsCheckBoxToggle;
  VBox.AddControlEx(TGTKHSeparator.Create(Self), False, False, 2);
  cbALLRead := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_ROTH);
  VBox.AddControlEx(cbALLRead, False, False, 0);     cbALLRead.OnToggled := PermissionsCheckBoxToggle;
  cbALLWrite := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_WOTH);
  VBox.AddControlEx(cbALLWrite, False, False, 0);     cbALLWrite.OnToggled := PermissionsCheckBoxToggle;
  cbALLExec := TGTKCheckButton.CreateWithLabel(Self, LANGFChmod_XOTH);
  VBox.AddControlEx(cbALLExec, False, False, 0);     cbALLExec.OnToggled := PermissionsCheckBoxToggle;
  PermissionFrame.AddControl(VBox);

  Busy := False;
  OnKeyDown := FormKeyDown;
  OctalEntry.OnChanged := OctalEntryChanged;
  RecursiveCheckButtonToggled(Self);
end;

procedure TFChmod.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean);
begin
  case Key of
    GDK_RETURN, GDK_KP_ENTER: ModalResult := mbOK;
    GDK_ESCAPE: ModalResult := mbCancel;
  end;
end;

procedure TFChmod.RecursiveCheckButtonToggled(Sender: TObject);
begin
  RecursiveOptionMenu.Enabled := RecursiveCheckButton.Checked;
end;

procedure TFChmod.PermissionsCheckBoxToggle(Sender: TObject);
var Mode: Cardinal;
begin
  if Busy then Exit;   Busy := True;
  Mode := 0;
  { $WARNINGS OFF}
  Mode := Mode or (Ord(cbSUID.Checked) * __S_ISUID);
  Mode := Mode or (Ord(cbSGID.Checked) * __S_ISGID);
  Mode := Mode or (Ord(cbSticky.Checked) * __S_ISVTX);
  Mode := Mode or (Ord(cbUSRRead.Checked) * S_IRUSR);
  Mode := Mode or (Ord(cbUSRWrite.Checked) * S_IWUSR);
  Mode := Mode or (Ord(cbUSRExec.Checked) * S_IXUSR);
  Mode := Mode or (Ord(cbGRPRead.Checked) * S_IRGRP);
  Mode := Mode or (Ord(cbGRPWrite.Checked) * S_IWGRP);
  Mode := Mode or (Ord(cbGRPExec.Checked) * S_IXGRP);
  Mode := Mode or (Ord(cbALLRead.Checked) * S_IROTH);
  Mode := Mode or (Ord(cbALLWrite.Checked) * S_IWOTH);
  Mode := Mode or (Ord(cbALLExec.Checked) * S_IXOTH);
  { $WARNINGS ON}
  LastMode := Mode;
  TextLabel.Caption := Format(LANGFChmod_TextLabel, [AttrToStr(Mode, False)]);;
  TextLabel.UseMarkup := True;
  OctalEntry.Text := Format('%.4d', [AttrToOctal(Mode)]);
  Busy := False;
end;

procedure TFChmod.OctalEntryChanged(Sender: TObject);
var Mode: Cardinal;
begin
  if Busy then Exit;    Busy := True;
  Mode := OctalToAttr(StrToIntDef(OctalEntry.Text, 0));
  LastMode := Mode;
  cbSUID.Checked := Mode and __S_ISUID = __S_ISUID;
  cbSGID.Checked := Mode and __S_ISGID = __S_ISGID;
  cbSticky.Checked := Mode and __S_ISVTX = __S_ISVTX;
  cbUSRRead.Checked := Mode and S_IRUSR = S_IRUSR;
  cbUSRWrite.Checked := Mode and S_IWUSR = S_IWUSR;
  cbUSRExec.Checked := Mode and S_IXUSR = S_IXUSR;
  cbGRPRead.Checked := Mode and S_IRGRP = S_IRGRP;
  cbGRPWrite.Checked := Mode and S_IWGRP = S_IWGRP;
  cbGRPExec.Checked := Mode and S_IXGRP = S_IXGRP;
  cbALLRead.Checked := Mode and S_IROTH = S_IROTH;
  cbALLWrite.Checked := Mode and S_IWOTH = S_IWOTH;
  cbALLExec.Checked := Mode and S_IXOTH = S_IXOTH;
  TextLabel.Caption := Format(LANGFChmod_TextLabel, [AttrToStr(Mode, False)]);;
  TextLabel.UseMarkup := True;
  Busy := False;
end;

procedure TFChmod.AssignMode(const Mode: Cardinal; const FileName, User, Group: string);
begin
  LastMode := Mode mod $1000;
  OctalEntry.Text := Format('%.4d', [AttrToOctal(LastMode)]);
  FileLabel.Caption := Format(LANGFChmod_FileLabel, [StrToUTF8(FileName), AttrToStr(Mode), AttrToOctal(Mode), User, Group]);
  FileLabel.UseMarkup := True;
  if Length(FileName) > 20 then FileLabel.SetSizeRequest(200, -1);
end;

end.

