dexed/src/ce_common.pas

287 lines
6.2 KiB
Plaintext

unit ce_common;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, ActnList, dialogs, forms, controls;
const
DdiagFilter = 'D source|*.d|D interface|*.di|All files|*.*';
type
(**
* MRU list for strings
*)
TMRUList = class(TStringList)
private
fMaxCount: Integer;
fObj: TObject;
protected
fChecking: boolean;
procedure clearOutOfRange;
procedure setMaxCount(aValue: Integer);
function checkItem(const S: string): boolean; virtual;
procedure Put(Index: Integer; const S: string); override;
published
property maxCount: Integer read fMaxCount write setMaxCount;
public
constructor Create;
procedure Insert(Index: Integer; const S: string); override;
property objectTag: TObject read fObj write fObj;
end;
(**
* MRU list for filenames
*)
TMRUFileList = class(TMRUList)
protected
function checkItem(const S: string): boolean; override;
end;
(**
* Save a component with a readable aspect.
*)
procedure saveCompToTxtFile(const aComp: TComponent; const aFilename: string);
(**
* Load a component.
*)
procedure loadCompFromTxtFile(const aComp: TComponent; const aFilename: string);
(**
* Converts a relative path to an absolute path.
*)
function expandFilenameEx(const aBasePath, aFilename: string): string;
(**
* Patches the directory separators from a string.
* This is used to ensure that a project saved on a platform can be loaded
* on another one.
*)
function patchPlateformPath(const aPath: string): string;
procedure patchPlateformPaths(const sPaths: TStrings);
(**
* Ok/Cancel modal dialog
*)
function dlgOkCancel(const aMsg: string): TModalResult;
(**
* Info dialog
*)
function dlgOkInfo(const aMsg: string): TModalResult;
(**
* Returns an unique object identifier, based on its heap address.
*)
function uniqueObjStr(const aObject: Tobject): string;
(**
* Reduce a filename if its length is over the threshold defined by charThresh.
* Even if the result is not usable anymore, it avoids any "visually-overloaded" MRU menus.
*)
function displayShortFilename(const aPath: string; charThresh: Word = 80): string;
implementation
constructor TMRUList.Create;
begin
fMaxCount := 10;
end;
procedure TMRUList.clearOutOfRange;
begin
while Count > fMaxCount do delete(Count-1);
end;
procedure TMRUList.setMaxCount(aValue: Integer);
begin
if aValue < 0 then aValue := 0;
if fMaxCount = aValue then exit;
clearOutOfRange;
end;
function TMRUList.checkItem(const S: string): boolean;
var
i: NativeInt;
begin
i := indexOf(S);
if i = -1 then exit(true);
if i = 0 then exit(false);
if Count < 2 then exit(false);
exchange(i, i-1);
exit( false);
end;
procedure TMRUList.Put(Index: Integer; const S: string);
begin
if not (checkItem(S)) then exit;
inherited;
clearOutOfRange;
end;
procedure TMRUList.Insert(Index: Integer; const S: string);
begin
if not (checkItem(S)) then exit;
inherited;
clearOutOfRange;
end;
function TMRUFileList.checkItem(const S: string): boolean;
begin
exit( inherited checkItem(S) and fileExists(S));
end;
procedure saveCompToTxtFile(const aComp: TComponent; const aFilename: string);
var
str1, str2: TMemoryStream;
begin
str1 := TMemoryStream.Create;
str2 := TMemoryStream.Create;
try
str1.WriteComponent(aComp);
str1.Position := 0;
ObjectBinaryToText(str1,str2);
str2.SaveToFile(aFilename);
finally
str1.Free;
str2.Free;
end;
end;
procedure loadCompFromTxtFile(const aComp: TComponent; const aFilename: string);
var
str1, str2: TMemoryStream;
begin
str1 := TMemoryStream.Create;
str2 := TMemoryStream.Create;
try
str1.LoadFromFile(aFilename);
str1.Position := 0;
ObjectTextToBinary(str1,str2);
str2.Position := 0;
try
str2.ReadComponent(aComp);
except
end;
finally
str1.Free;
str2.Free;
end;
end;
function expandFilenameEx(const aBasePath, aFilename: string): string;
var
curr: string;
begin
curr := '';
getDir(0, curr);
try
if curr <> aBasePath then
chDir(aBasePath);
result := expandFileName(aFilename);
finally
chDir(curr);
end;
end;
function patchPlateformPath(const aPath: string): string;
function patchProc(const src: string; const invalid: char): string;
var
i: Integer;
dir: string;
begin
dir := ExtractFileDrive(src);
if length(dir) > 0 then
result := src[length(dir)+1..length(src)]
else
result := src;
i := pos(invalid, result);
if i <> 0 then
begin
repeat
result[i] := directorySeparator;
i := pos(invalid,result);
until
i = 0;
end;
result := dir + result;
end;
begin
result := aPath;
{$IFDEF MSWINDOWS}
result := patchProc(result, '/');
result := patchProc(result, ':');
{$ENDIF}
{$IFDEF LINUX}
result := patchProc(result, '\');
result := patchProc(result, ':');
{$ENDIF}
{$IFDEF MACOS}
result := patchProc(result, '\');
result := patchProc(result, '/');
{$ENDIF}
end;
procedure patchPlateformPaths(const sPaths: TStrings);
var
i: Integer;
str: string;
begin
for i:= 0 to sPaths.Count-1 do
begin
str := sPaths.Strings[i];
sPaths.Strings[i] := patchPlateformPath(str);
end;
end;
function dlgOkCancel(const aMsg: string): TModalResult;
const
Btns = [mbOK,mbCancel];
begin
exit( MessageDlg('Coedit', aMsg, mtConfirmation, Btns, ''));
end;
function dlgOkInfo(const aMsg: string): TModalResult;
const
Btns = [mbOK];
begin
exit( MessageDlg('Coedit', aMsg, mtInformation, Btns, ''));
end;
function uniqueObjStr(const aObject: Tobject): string;
begin
{$HINTS OFF}{$WARNINGS OFF}
exit( format('%.8X',[NativeUint(@aObject)]));
{$HINTS ON}{$WARNINGS ON}
end;
function displayShortFilename(const aPath: string; charThresh: Word = 80): string;
var
i: NativeInt;
sepCnt: NativeInt;
drv: string;
pth1: string;
begin
sepCnt := 0;
if length(aPath) <= charThresh then
exit(aPath);
drv := extractFileDrive(aPath);
i := length(aPath);
while(i <> length(drv)+1) do
begin
Inc(sepCnt, Byte(aPath[i] = directorySeparator));
if sepCnt = 2 then break;
Dec(i);
end;
pth1 := aPath[i..length(aPath)];
exit( format('%s%s...%s',[drv,directorySeparator,pth1]) );
end;
end.