This commit is contained in:
Basile Burg 2014-07-27 08:59:29 +02:00
parent 909c7e0b97
commit f48fc903c5
17 changed files with 1329 additions and 28 deletions

View File

@ -1,13 +1,20 @@
Revision log. Revision log.
(single changes can be tracked with the GH commit messages) (single changes can be tracked with the GH commit messages)
r25:
- ce_plugin: added a plug-in API. D example. final goal is to use it to wrap D Completion Daemon and other D libs.
- ce_libman: library manager: additional sources and -I are automatically added to the options.
- ce_project: added a field, General options, for the libman aliases. An entry acts as a selector in the libman.
- ce_libmaneditor: created a widget for the libman.
- ce_staticexplorer: all the libman entries are added when generating the infos, which increases the success chance.
r24: r24:
- ce_messages: messages related to a project were not cleared when the project was closed. - ce_messages: messages related to a project were not cleared when the project was closed.
- ce_messages: obj files could be automatically opened in case of errors in 'compile & run'. - ce_messages: obj files could be automatically opened in case of errors in 'compile & run'.
- ce_messages: fix position in source code broken. - ce_messages: fix position in source code broken.
- ce_dmdwrap: removed old project fields 'versionIdentifier' and 'debugIdentifier'. - ce_dmdwrap: removed old project fields 'versionIdentifier' and 'debugIdentifier'.
- ce_main: compile & run, compile, run: fixed some inaccuracies related to platform specific process options (poWaitOnExit under win). - ce_main: compile & run, compile, run: fixed some inaccuracies related to platform specific process options (poWaitOnExit under win).
- ce_main, option: possible startup crash fixed when invalid height or width. - ce_main: option, possible startup crash fixed when invalid height or width.
r23: r23:
- ce_messages: position in source code. - ce_messages: position in source code.

View File

@ -0,0 +1,140 @@
module CoeditPlugApi;
alias void* Host_t;
alias void* Plugin_t;
// API version
immutable uint CE_PLG_API_VER = 0;
/// When passed to the Coedit dispatcher, it shows a 'hello plugin' message.
immutable uint HELLO_PLUGIN = 0xFFFFFFFF;
// Denotes the emiter and the message kind -------------------------------------
/// Coedit sends an event.
immutable uint HOST_EVENT = 0x10000000;
/// Coedit sends some data.
immutable uint HOST_DATA = 0x20000000;
/// The plug-in sends an event.
immutable uint PLUG_EVENT = 0x30000000;
/// The plug-in sends some data.
immutable uint PLUG_DATA = 0x40000000;
// Denotes the message context -------------------------------------------------
/// the dispatcher call is related to the project(s)
immutable uint CTXT_PROJ = 0x01000000;
/// the dispatcher call is related to the document(s)
immutable uint CTXT_DOCS = 0x02000000;
/// the dispatcher call is related to the edition of a document.
immutable uint CTXT_EDIT = 0x03000000;
/// the dispatcher call is related to the Coedit 'Message Widget'.
immutable uint CTXT_MSGS = 0x04000000;
/// the dispatcher call is related to the Coedit dialogs.
immutable uint CTXT_DLGS = 0x05000000;
// The events kinds ------------------------------------------------------------
/// somethings's just changed.
immutable uint EV_CHANGED = 0x00000001;
/// something's just been selected.
immutable uint EV_FOCUSED = 0x00000002;
/// something's just been closed.
immutable uint EV_CLOSED = 0x00000003;
/// something's just been created.
immutable uint EV_NEW = 0x00000004;
/// something gonna be compiled.
immutable uint EV_COMPILE = 0x00000005;
/// something gonna be executed.
immutable uint EV_RUN = 0x00000006;
// The data kinds --------------------------------------------------------------
/// data1 is used to set/get a filename. data1 is a PChar. data0 represents an index.
immutable uint DT_FNAME = 0x00000001;
/// data0 represents a count.
immutable uint DT_COUNT = 0x00000002;
/// data1 is used to set a message. data1 is a PChar.
immutable uint DT_ERR = 0x00000001;
/// ditto
immutable uint DT_INF = 0x00000002;
/// ditto
immutable uint DT_WARN = 0x00000003;
// terminal opCodes (emiter + context + event/data kind) -----------------------
/// Coedit says that the project's just been modified.
immutable uint HOST_PROJ_CHANGED = HOST_EVENT + CTXT_PROJ + EV_CHANGED;
/// opCode for asking for a document filename. data0 must be the document index.
immutable uint PLUG_WANT_DOC_NAME = PLUG_EVENT + CTXT_DOCS + DT_FNAME;
/// opCode for getting a document filenmae. data1 is a PChar to the filename.
immutable uint HOST_GIVE_DOC_NAME = HOST_DATA + CTXT_DOCS + DT_FNAME;
/// opCodes for displaying a message in a dialog box.
immutable uint PLUG_DLGS_ERR = PLUG_DATA + CTXT_DLGS + DT_ERR;
/// ditto.
immutable uint PLUG_DLGS_WARN = PLUG_DATA + CTXT_DLGS + DT_WARN;
/// ditto.
immutable uint PLUG_DLGS_INF = PLUG_DATA + CTXT_DLGS + DT_INF;
/// opCodes for displaying a message in the 'Message Widget'.
immutable uint PLUG_MSGS_ERR = PLUG_DATA + CTXT_MSGS + DT_ERR;
/// ditto.
immutable uint PLUG_MSGS_WARN = PLUG_DATA + CTXT_MSGS + DT_WARN;
/// ditto.
immutable uint PLUG_MSGS_INF = PLUG_DATA + CTXT_MSGS + DT_INF;
// host-side prototypes --------------------------------------------------------
/**
* A plugin asks for some information or it passes data here.
* Data1 and data2 are some pointers to a particular variable type.
* In the plugin hostCreatePlugProc, a the location of COedit dispatcher is passed
* to the plugin.
*/
extern(C) alias plugDispatchToHostProc =
void function(Plugin_t aPlugin, uint opCode, uint data0, void* data1, void* data2);
// plugin-side prototypes-------------------------------------------------------
/**
* Coedit initializes a plugin, the result is passed during the runtime as "aTarget".
* In the plugin implementation, it must be named 'createPlug'.
* If the result is null then the Plugin is not used at all.
* If the plugin is not warped in a class than the result must be set on something
* that can be pointed to (e.g: a global variable).
*/
extern(C) alias hostCreatePlugProc =
Plugin_t function (plugDispatchToHostProc aHost);
/**
* Coedit closes and aTarget can be destroyed.
* In the plugin implementation, it must be named 'destroyPlug'.
*/
extern(C) alias hostDestroyPlugProc =
void function (Plugin_t aTarget);
/**
* Coedit events and data are passed here. data1 and data2 can be casted according to opCode.
* In the plugin implementation, it must be named 'dispatchToPlug'.
*/
extern(C) alias hostDispatchToPlugProc =
void function(Plugin_t aPlugin, uint opCode, uint data0, void* data1, void* data2);
// helpers ---------------------------------------------------------------------
uint getEmiter(in uint opCode){
return opCode & 0xF0000000;
}
uint getContext(in uint opCode){
return opCode & 0x0FF00000;
}
uint getCommand(in uint opCode){
return opCode & 0x000FFFFF;
}

View File

@ -0,0 +1,39 @@
object CurrentProject: TCEProject
OptionsCollection = <
item
name = 'toPlugDir'
outputOptions.binaryKind = sharedlib
outputOptions.noBoundsCheck = False
outputOptions.boundsCheck = onAlways
outputOptions.optimizations = True
outputOptions.release = True
pathsOptions.outputFilename = '..\..\plugins\CoeditPlug.dll'
preBuildProcess.options = []
preBuildProcess.showWindow = swoNone
postBuildProcess.options = []
postBuildProcess.showWindow = swoNone
runOptions.options = []
runOptions.showWindow = swoNone
end
item
name = 'abovePlugDir'
outputOptions.binaryKind = sharedlib
outputOptions.inlining = True
outputOptions.noBoundsCheck = False
outputOptions.boundsCheck = onAlways
outputOptions.optimizations = True
outputOptions.release = True
pathsOptions.outputFilename = '..\..\plugins\temp\CoeditPlug.dll'
preBuildProcess.options = []
preBuildProcess.showWindow = swoNone
postBuildProcess.options = []
postBuildProcess.showWindow = swoNone
runOptions.options = []
runOptions.showWindow = swoNone
end>
Sources.Strings = (
'..\CoeditPlugApi.d'
'CoeditPlug.d'
)
ConfigurationIndex = 1
end

View File

@ -0,0 +1,130 @@
module CoeditPlug;
/*
Under linux:
Build:
1:dmd -c CoeditPlug.d ../CoeditPlugApi.d pathtoIZ/types.d -fPIC
(or with a coedit project, select outputKind : object (which is actually -c))
2:dmd -ofCOeditPlug.so <the three .o> -shared -defaultlib=libphobos2.so
Note about IZ:
The GC will make the plugin crash if coeditPlug is not an izObject
because (?). However since izObjects have their own, G.C free, de/allocators
it just instanciates fine.
*/
import std.stdio, std.string, std.conv;
import CoeditPlugApi;
version(Posix)
{
}
else
{
import std.c.windows.windows;
import core.sys.windows.dll;
}
import iz.types;
pragma( lib, "iz");
coeditPlug plugin;
class coeditPlug :izObject
{
protected
{
plugDispatchToHostProc fDispatcher;
Plugin_t asPlugin_t(){return cast(Plugin_t)this;}
}
public
{
this(plugDispatchToHostProc aDispatcher)
{
assert(aDispatcher, "the Coedit dispatcher is missing");
fDispatcher = aDispatcher;
//fDispatcher(asPlugin_t, HELLO_PLUGIN, 0, null, null);
auto msg = "simple Coedit plugin is created".toStringz;
fDispatcher(asPlugin_t, PLUG_MSGS_INF, 0, cast(void*)msg, null);
}
void hostEvent(uint eventContext, uint eventKind)
{
auto msg = (to!string(eventContext) ~ " " ~ to!string(eventKind)).toStringz;
fDispatcher(asPlugin_t, PLUG_MSGS_INF, 0, cast(void*)msg, null);
}
void hostData(uint dataContext, uint dataKind, uint data0, void* data1, void* data2)
{
}
}
}
extern(C) export
Plugin_t createPlug(plugDispatchToHostProc aHost)
{
plugin = new coeditPlug(aHost);
return &plugin;
}
extern(C) export
void destroyPlug(Plugin_t aPlug)
{
delete plugin;
}
extern(C) export
void dispatchToPlug(Plugin_t aPlugin, uint opCode, uint data0, void* data1, void* data2)
{
assert(&plugin == aPlugin);
coeditPlug* plg = (cast(coeditPlug*) aPlugin);
auto emit = opCode.getEmiter;
auto ctxt = opCode.getContext;
auto comd = opCode.getCommand;
if (emit == HOST_EVENT)
plg.hostEvent(ctxt, comd);
else
plg.hostData(ctxt, comd, data0, data1, data2);
}
version(Posix)
{
}
else
{
__gshared HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
default: break;
}
return true;
}
}

View File

@ -134,7 +134,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item6> </Item6>
</RequiredPackages> </RequiredPackages>
<Units Count="18"> <Units Count="21">
<Unit0> <Unit0>
<Filename Value="coedit.lpr"/> <Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -252,6 +252,24 @@
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<UnitName Value="ce_miniexplorer"/> <UnitName Value="ce_miniexplorer"/>
</Unit17> </Unit17>
<Unit18>
<Filename Value="..\src\ce_plugin.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="ce_plugin"/>
</Unit18>
<Unit19>
<Filename Value="..\src\ce_libman.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="ce_libman"/>
</Unit19>
<Unit20>
<Filename Value="..\src\ce_libmaneditor.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="CELibManEditorWidget"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="ce_libmaneditor"/>
</Unit20>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -10,7 +10,8 @@ uses
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg,
ce_widget, ce_dmdwrap, ce_common, ce_synmemo, ce_main, ce_messages, ce_editor, ce_widget, ce_dmdwrap, ce_common, ce_synmemo, ce_main, ce_messages, ce_editor,
ce_projinspect, ce_projconf, jsonparser, ce_project, ce_widgettypes, ce_projinspect, ce_projconf, jsonparser, ce_project, ce_widgettypes,
ce_staticexplorer, ce_search, ce_dlang, ce_dlangutils, ce_miniexplorer; ce_staticexplorer, ce_search, ce_dlang, ce_dlangutils, ce_miniexplorer,
ce_plugin, ce_libman, ce_libmaneditor;
{$R *.res} {$R *.res}

View File

@ -455,6 +455,7 @@ const
{$ENDIF} {$ENDIF}
begin begin
{$IFDEF WINDOWS} {$IFDEF WINDOWS}
PIDL := nil;
SHGetSpecialFolderLocation(0, CSIDL_APPDATA, PIDL); SHGetSpecialFolderLocation(0, CSIDL_APPDATA, PIDL);
SHGetPathFromIDList(PIDL, Folder); SHGetPathFromIDList(PIDL, Folder);
result:=Folder; result:=Folder;

139
src/ce_libman.pas Normal file
View File

@ -0,0 +1,139 @@
unit ce_libman;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, ce_common;
type
(**
* Represents a D static library. In a project libAlias allows to
* resolve automatically the dependencies of a project.
*)
TLibraryItem = class(TCollectionItem)
private
fAlias: string;
fSourcePath: string;
fLibFile: string;
published
property libAlias: string read fAlias write fAlias;
property libSourcePath: string read fSourcePath write fSourcePath;
property libFile: string read fLibFile write fLibFile;
end;
(**
* Represents all the D library present on this system.
*)
TLibraryManager = class(TComponent)
private
fCol: TCollection;
procedure setCol(const aValue: TCollection);
procedure readerPropNoFound(Reader: TReader; Instance: TPersistent;
var PropName: string; IsPath: boolean; var Handled, Skip: Boolean);
procedure readerError(Reader: TReader; const Message: string;
var Handled: Boolean);
published
property libraries: TCollection read fCol write setCol;
public
constructor create(aOwner: TComponent); override;
destructor destroy; override;
//
procedure getAdditionalSources(const someAliases, aList: TStrings);
procedure getAdditionalImport(const someAliases, aList: TStrings);
//
procedure loadFromFile(const aFilename: string);
procedure saveToFile(const aFilename: string);
end;
implementation
constructor TLibraryManager.create(aOwner: TComponent);
begin
inherited;
fCol := TCollection.Create(TLibraryItem);
end;
destructor TLibraryManager.destroy;
begin
fCol.Free;
inherited;
end;
procedure TLibraryManager.setCol(const aValue: TCollection);
begin
fCol.assign(aValue);
end;
procedure TLibraryManager.getAdditionalSources(const someAliases, aList: TStrings);
var
itm: TCollectionItem;
itmt: TLibraryItem;
ext, src: string;
srcs: TStringList;
begin
for itm in fCol do
begin
itmt := TLibraryItem(itm);
if someAliases.IndexOf(itmt.libAlias) = -1 then continue;
//
srcs := TStringList.Create;
try
listFiles(srcs, itmt.libSourcePath, true);
for src in srcs do
begin
ext := extractFileExt(src);
if DExtList.IndexOf(ext) = -1 then continue;
if aList.IndexOf(src) <> -1 then continue;
aList.Add(src);
end;
finally
srcs.Free;
end;
end;
end;
procedure TLibraryManager.getAdditionalImport(const someAliases, aList: TStrings);
var
itm: TCollectionItem;
itmt: TLibraryItem;
begin
for itm in fCol do
begin
itmt := TLibraryItem(itm);
if someAliases.IndexOf(itmt.libAlias) = -1 then continue;
//
if aList.IndexOf(itmt.libFile) <> -1 then continue;
aList.Add('-I'+ itmt.libFile);
end;
end;
procedure TLibraryManager.readerPropNoFound(Reader: TReader; Instance: TPersistent;
var PropName: string; IsPath: boolean; var Handled, Skip: Boolean);
begin
Skip := true;
Handled := false;
end;
procedure TLibraryManager.readerError(Reader: TReader; const Message: string;
var Handled: Boolean);
begin
Handled := true;
end;
procedure TLibraryManager.loadFromFile(const aFilename: string);
begin
loadCompFromTxtFile(self, aFilename, @readerPropNoFound, @readerError);
end;
procedure TLibraryManager.saveToFile(const aFilename: string);
begin
saveCompToTxtFile(self, aFilename);
end;
initialization
registerClasses([TLibraryManager, TLibraryItem]);
end.

296
src/ce_libmaneditor.lfm Normal file
View File

@ -0,0 +1,296 @@
inherited CELibManEditorWidget: TCELibManEditorWidget
Left = 1355
Height = 349
Top = 210
Width = 466
Caption = 'Library manager'
ClientHeight = 349
ClientWidth = 466
inherited Back: TPanel
Height = 349
Width = 466
ClientHeight = 349
ClientWidth = 466
inherited Content: TPanel
Height = 349
Width = 466
ClientHeight = 349
ClientWidth = 466
object Panel1: TPanel[0]
Left = 4
Height = 28
Top = 4
Width = 458
Align = alTop
BorderSpacing.Around = 4
BevelOuter = bvNone
ClientHeight = 28
ClientWidth = 458
TabOrder = 0
object btnAddLib: TBitBtn
Left = 0
Height = 28
Hint = 'add library alias'
Top = 0
Width = 28
Align = alLeft
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000001E0000003300000033000000330000001E00000000000000240000
0033000000330000003300000033000000330000003300000033000000330000
0033008D56A9009E5FFF009D5DFF009E5EFF008C55AC0000001EAA783CC1B985
46FFB88546FFB88445FFB78445FFB78445FFB78445FFB98345FFC68244FF5293
54FF00A66BFF00BA86FF77DFC4FF00BA86FF00A66AFF008C55ACB88446FFEDB2
5AFFC79049FFEAB05DFFE8AB55FFE7AB55FFE7AB56FFEBAB55FFFCAB53FF009E
60FF00C08DFF00BB82FFFFFFFFFF00BB82FF00C08CFF009E5EFFB78445FFEBB2
60FFC48D48FFE9B364FFE4A853FFE4A854FFE4A854FFE7A854FFFAA852FF009C
5EFF73E5CCFFFFFFFFFFFFFFFFFFFFFFFFFF77E5CCFF009C5CFFB78345FFECB6
66FFC48C46FFEAB76EFFE3A752FFE3A854FFE3A854FFE6A854FFF8A852FF009C
5FFF00CC98FF00C88FFFFFFFFFFF00C88FFF00CC98FF009D5DFFB78344FFEDB8
6AFFC38C45FFEBBC77FFE3A751FFE3A853FFE3A854FFE5A854FFF1A852FF5BA1
59FF00AE73FF00D39EFF74EDD4FF00D49EFF00AE72FF009F6097B78344FFEEBD
72FFC38C45FFECC183FFE3A853FFE3A854FFE3A854FFE3A854FFE8A854FFF7A9
52FF5CA159FF009B5DFF009C5BFF009D5EFF009F609600A06200B78243FFF0C3
7EFFC38C45FFEFC98FFFE3AB56FFE2A952FFE2A850FFE2A74FFFE3A850FFE8A9
52FFF1AB55FFFFCB8FFFD47E3DFF00A3650000A2640000A16300B68242FFF2C8
89FFC38C47FFF1D09CFFE3AB57FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE6AC57FFF7D29EFFBF7F3FFFD283420000A5680000A46600B68141FFF3CE
93FFC38E48FFF2D7A8FFE3AF5BFFE1AA52FFE0A74CFFE0A74BFFE0A74CFFE1AA
52FFE3B05CFFF4D9AAFFB7803FFFC1854400CA854500CE844400B68140FFF4D4
9DFFC48E48FFF4DCB3FFE4B05EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE4B15EFFF6DEB5FFB67F3EFFBB854500BD874700BE874700B6813FFFF5D9
A7FFC38E49FFF7E1BEFFE5B564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE5B564FFF9E4C1FFB57F3DFFBA854500BB874700BB874700B6813FFFF7DF
B1FFC48F4BFFF8E9CBFFE5BA6EFFE4B86AFFE4B767FFE4B667FFE4B767FFE4B8
6AFFE6BA6EFFFAECCDFFB57F3CFFBA854500BB874700BB874700B88241FFFCE8
C0FFC69552FFFDF0D6FFFBEED3FFFBEDD2FFFBEDD2FFFBEDD2FFFBEDD2FFFBED
D2FFFCEED3FFFFF2D8FFB7813EFFBB864500BB874700BB874700B88241B2B882
41FFB78240FFB67F3DFFB57E3CFFB57E3BFFB57E3BFFB57E3BFFB57E3BFFB57E
3BFFB57E3CFFB7803EFFB88241B2BB874700BB874700BB874700
}
OnClick = btnAddLibClick
TabOrder = 0
end
object btnRemLib: TBitBtn
Left = 28
Height = 28
Hint = 'remove library alias'
Top = 0
Width = 28
Align = alLeft
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000001E0000003300000033000000330000001E00000000000000240000
0033000000330000003300000033000000330000003300000033000000330000
00332B42BAA9374DCDFF384DCBFF384DCCFF3145B4AC0000001EAA783CC1B985
46FFB88546FFB88445FFB78445FFB78445FFB78445FFB88444FFC2893BFF7066
91FF324FDDFF375DFAFF375DFAFF385DF9FF3852D7FF3044B4ACB88446FFEDB2
5AFFC79049FFEAB05DFFE8AB55FFE7AB55FFE7AB56FFE9AD54FFF6B349FF2141
DCFF3E63FFFF3B60FAFF3A5DF8FF3C60FAFF4165FBFF344BCCFFB78445FFEBB2
60FFC48D48FFE9B364FFE4A853FFE4A854FFE4A854FFE6AA52FFF4B147FF1F3F
D8FFA6B8FFFFFFFFFFFFFFFFFFFFFFFFFFFFA9BAFFFF3148CAFFB78345FFECB6
66FFC48C46FFEAB76EFFE3A752FFE3A854FFE3A854FFE5A952FFF2B048FF1C3E
DCFF5776FFFF5675FFFF5473FDFF5776FEFF5D79FFFF334ACBFFB78344FFEDB8
6AFFC38C45FFEBBC77FFE3A751FFE3A853FFE3A854FFE5A852FFEDAD4CFF7B70
9BFF3757E7FF6A86FFFF718BFFFF6F89FFFF465EDDFF354CCD97B78344FFEEBD
72FFC38C45FFECC183FFE3A853FFE3A854FFE3A854FFE3A954FFE6AA51FFF1B0
49FF7B719BFF1F3ED8FF2743D4FF2F48D0FF354CCE96374ECF00B78243FFF0C3
7EFFC38C45FFEFC98FFFE3AB56FFE2A952FFE2A850FFE2A74FFFE2A84FFFE6AB
4FFFEDB04FFFFFD385FFCB8A2CFF2647DF00314CD500354ED200B68242FFF2C8
89FFC38C47FFF1D09CFFE3AB57FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE5AC56FFF6D39CFFBC8339FFCB8D34002346E4002949DE00B68141FFF3CE
93FFC38E48FFF2D7A8FFE3AF5BFFE1AA52FFE0A74CFFE0A74BFFE0A74CFFE1AA
52FFE3B05CFFF4D9AAFFB7803EFFBF884100C68C3C00C88D3900B68140FFF4D4
9DFFC48E48FFF4DCB3FFE4B05EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE4B15EFFF6DEB5FFB67F3EFFBB864500BD884500BD884500B6813FFFF5D9
A7FFC38E49FFF7E1BEFFE5B564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFE5B564FFF9E4C1FFB57F3DFFBA854500BB874700BB874700B6813FFFF7DF
B1FFC48F4BFFF8E9CBFFE5BA6EFFE4B86AFFE4B767FFE4B667FFE4B767FFE4B8
6AFFE6BA6EFFFAECCDFFB57F3CFFBA854500BB874700BB874700B88241FFFCE8
C0FFC69552FFFDF0D6FFFBEED3FFFBEDD2FFFBEDD2FFFBEDD2FFFBEDD2FFFBED
D2FFFCEED3FFFFF2D8FFB7813EFFBB864500BB874700BB874700B88241B2B882
41FFB78240FFB67F3DFFB57E3CFFB57E3BFFB57E3BFFB57E3BFFB57E3BFFB57E
3BFFB57E3CFFB7803EFFB88241B2BB874700BB874700BB874700
}
OnClick = btnRemLibClick
TabOrder = 1
end
object btnSelFile: TBitBtn
Left = 402
Height = 28
Hint = 'select the library file'
Top = 0
Width = 28
Align = alRight
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000A0000
002A000000330000002A0000000A000000000000000000000000469AD300469A
D300469AD300449AD500399BE100CF9044000000001200000031674D2B59B586
4AD9C18F4FFFB6864AD9684D2B590000003100000012C2915200469AD3000000
000B0000000A0000000A00000008000000338C683879BC8B4CF8D5A263FFF7C0
82FFFFDDB3FFE6B77FFFC59356FFBC8B4BF88B683A7A000000330000002F2959
7A5F2655755C2553745A1C4C6F55CD8E42FFD8A262FFF4BE81FFF8C182FFF3BA
79FFFBE1C1FFFBCF9BFFFFD6A5FFF3C690FFD8AA6FFFBD8C4CFF4598D0F14398
D2FF4094D0FF3D92D1FF3395DDFFCA8B3FFFF4BD7DFFECB676FFE6B06FFFECBD
84FFFDF0DEFFFFC890FFF6C892FFF7CC99FFFFD4A2FFD9A76FFF4499D2FF3F94
D0FFABFBFFFF9AF4FFFF89F6FFFFC6863BFFE3AC6AFFE1B882FFEFE0C3FFDDD1
B8FFE0D3B6FFE4E7D7FFEED2AAFFF4C693FFF1C591FFD7A56BFF4397D1FF56AC
DDFF8EDAF5FFA1EFFFFF7BECFFFFC98D47FFEDDDBDFFDFD0B3FFE0B380FFF0CC
A5FFFFDDB8FFFFD3A4FFEDD1ABFFE8EDDCFFF0E8CEFFD9A469FF4296D1FF71C4
EAFF6CBCE6FFBBF3FFFF6FE3FFFFC0863EFFE4AF73FFFFECCFFFFFDBB0FFFFCA
92FFD5A76EFFFFE9CEFFFFD9AFFFFFCB92FFEDBB80FFE5A663FF4095D0FF90DD
F8FF44A0D8FFDCFDFFFFD8FCFFFFD4FFFFFFCED1BFFFC7A169FFE8B178FFFFEB
CEFFFFDBB1FFFFCB92FFE0A768FFCD9E61FF8FABADFF2470A6683E93CFFFB2F6
FFFF51ACDEFF358ACBFF348BCBFF338CCEFF328DD2FF52C2F6FF79C6D4FFCAA4
70FFE7AF70FFC79E65FF7BCBE0FF79E2FFFFA5E2FDFF378AC4C63D92CFFFB8F3
FFFF77DFFEFF7BE0FEFF7CE1FFFF7CE1FFFF7DE2FFFF50ACE0FF51BBEFFFD1FB
FFFFCCF2FDFFCDF9FFFFD0F8FFFFD3F8FFFFDAFDFFFF3E94D1FF3C92CFFFC0F3
FFFF70D9FBFF73DAFBFF74DAFBFF74DAFBFF74DBFBFF76DEFDFF4FAADDFF358C
CCFF338CCDFF328CCDFF328CCDFF3790CEFF3D94D0FF4398D2AE3B92CFFFCAF6
FFFF69D5F9FF6CD5F9FF6AD4F9FF69D4F9FF69D5F9FF6AD6FAFF6BD8FBFF6BD9
FCFF6BDAFDFF69DAFDFFDAFDFFFF3C93D0FF367BAA2F469AD3003B92CFFFD5F7
FFFF60D1F9FF61D0F8FFB4EBFDFFD9F6FFFFDAF8FFFFDAF8FFFFDAF9FFFFDBF9
FFFFDAF9FFFFDAFAFFFFDFFEFFFF3D94D0FF4599D335469AD3003D94D0FFDCFC
FFFFD8F7FFFFD8F7FFFFDBFAFFFF358ECDFF3991CEFF3A92CFFF3A92CFFF3A92
CFFF3A92CFFF3A92CFFF3D94D0FF4298D2EA469AD300469AD3004398D2EF3D94
D0FF3A92CFFF3A92CFFF3D94D0FF4197D1E44398D22B4498D2324498D2334498
D2334498D2334499D2334499D337459AD300469AD300469AD300
}
OnClick = btnSelFileClick
TabOrder = 2
end
object btnSelRoot: TBitBtn
Left = 430
Height = 28
Hint = 'select the sources root'
Top = 0
Width = 28
Align = alRight
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000001E0000003300000033000000330000001E00000000469AD300469A
D300469AD300469AD300469AD300469AD300469AD300479AD5004D99DF000000
001E008C53AC009E5EFF009D5DFF009E5EFF008C55AC0000001E469AD3000000
000B0000000A0000000A0000000A0000000A0000000A0000000A00000008008D
4BAA00A668FF00BA86FF77DFC4FF00BA86FF00A66AFF008C55AC0000002F2959
7A5F2655755C2655745C2655745C2655745C2655745C2653745A24486851009E
52FF00C08AFF00BB82FFFFFFFFFF00BB82FF00C08CFF009E5EFF4598D0F14398
D2FF4094D0FF3E92CFFF3E92CEFF3F92CEFF3F92CEFF4092D1FF4792DAFF009B
4EFF75E5CAFFFFFFFFFFFFFFFFFFFFFFFFFF77E5CCFF009C5CFF4499D2FF3F94
D0FFABFBFFFF9BF3FFFF92F1FFFF93F1FFFF93F1FFFF95F1FFFF9EF4FFFF0096
4AFF00CA93FF00C78EFFFFFFFFFF00C88FFF00CC97FF009D5CFF4397D1FF56AC
DDFF8EDAF5FFA2EDFFFF82E5FEFF84E5FEFF84E5FEFF86E6FFFF8DE9FFFF35BA
9EFF00A965FF00D299FF74ECD1FF00D29AFF00AE6CFF009F56924296D1FF71C4
EAFF6CBCE6FFBBF2FFFF75DEFDFF77DEFCFF78DEFCFF7CDFFDFF80E1FFFF89E4
FFFF32B89EFF009549FF00954AFF00974BFF1F9E91FF000000124095D0FF90DD
F8FF44A0D8FFDDFCFFFFDAFAFFFFDBF9FFFFDEFAFFFF74DCFCFF76DBFBFF78DB
FEFF7CDDFFFF7FDFFFFF7FDFFFFFADECFFFF82C1EEFF3575A7703E93CFFFB2F6
FFFF51ACDEFF358ACAFF358ACAFF358ACAFF368ACAFF5BBDE9FF6ED9FBFF6AD6
FAFF69D5FBFF69D5FBFF68D5FCFF84DEFEFFABE1F8FF3A8AC1C83D92CFFFB8F3
FFFF77DFFEFF7BE0FEFF7CE1FEFF7CE1FFFF7DE2FFFF52ABDDFF56B9E8FFDAF8
FFFFD6F6FFFFD6F6FFFFD5F6FFFFD5F7FFFFDBFCFFFF3E94D0FF3C92CFFFC0F3
FFFF70D9FBFF73DAFBFF74DAFBFF74DAFBFF74DBFBFF76DEFDFF4FA9DCFF368B
CAFF358BCBFF338BCBFF338CCCFF3790CEFF3D94D0FF4398D2AE3B92CFFFCAF6
FFFF69D5F9FF6CD5F9FF6AD4F9FF69D4F9FF69D5F9FF6AD6FAFF6BD8FBFF6BD9
FCFF6BDAFDFF69DAFDFFDAFDFFFF3C93D0FF367BAA2F469AD3003B92CFFFD5F7
FFFF60D1F9FF61D0F8FFB4EBFDFFD9F6FFFFDAF8FFFFDAF8FFFFDAF9FFFFDBF9
FFFFDAF9FFFFDAFAFFFFDFFEFFFF3D94D0FF4599D335469AD3003D94D0FFDCFC
FFFFD8F7FFFFD8F7FFFFDBFAFFFF358ECDFF3991CEFF3A92CFFF3A92CFFF3A92
CFFF3A92CFFF3A92CFFF3D94D0FF4298D2EA469AD300469AD3004398D2EF3D94
D0FF3A92CFFF3A92CFFF3D94D0FF4197D1E44398D22B4498D2324498D2334498
D2334498D2334499D2334499D337459AD300469AD300469AD300
}
OnClick = btnSelRootClick
TabOrder = 3
end
object btnEditAlias: TBitBtn
Left = 374
Height = 28
Hint = 'edit the library alias'
Top = 0
Width = 28
Align = alRight
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF009461
3E9C94603DFF93603CFF153E54FF2A5F86FF4A87BBFF55819CFF836048FF8F5B
37FF8F5A36FF8E5A35FF8E5935B1FFFFFF00FFFFFF00FFFFFF00FFFFFF009562
3FE1CCAB85FFD1AF89FF2E6683FF94C7F9FF91C9F9FF4185C9FF2467A8FFB09A
86FFCB9F77FFC79971FF93613EFF4E3421A1FFFFFF00FFFFFF00FFFFFF009663
40E1CAA985FFA37854FF4389AAFFE0F2FFFF549AD8FF1A7ABEFF4998C5FF4283
B6FFA8886BFFC99D75FF93623FFF553C28E1FFFFFF00FFFFFF00FFFFFF009664
41E1CBAC88FFA67E57FF868A80FF7AB6D5FF90B7D1FF55C9E4FF5BDFF5FF78D0
EDFF4C93CFFFB79E85FF946240FF573E2AFFFFFFFF00FFFFFF00FFFFFF009765
43E1CEB08EFFAA855BFFCBA475FF909887FF75B7D3FFC2F6FDFF63DFF7FF5DE2
F8FF79D3F0FF4896D8FF886854FF573E2AFFFFFFFF00FFFFFF00FFFFFF009866
44E1D0B492FFAF8B60FFCEA97CFFCCA677FF8F998BFF77CBE7FFC7F7FDFF5EDC
F5FF5AE1F7FF7BD4F1FF4693D4FF504E4EFFFFFFFF00FFFFFF00FFFFFF009967
45E1D2B796FFB49265FFD1AE83FFCFAB7FFFCDA87AFF9AA893FF79D3EEFFC7F7
FDFF5FDCF5FF5BE2F7FF7AD6F2FF4291CFFF448DCD30FFFFFF00FFFFFF009968
46E1D5BB9BFFB89A69FFD4B38AFFD2AF87FFD0AD82FFCFAA7DFF9DAB96FF7DD4
EDFFC4F6FDFF6CDDF6FF6DCAEDFF63A3D7FF5D9BD2EC5192CA26FFFFFF009A69
47E1D7BF9FFFBD9F6FFFD4B590FFCBAD88FFC7A881FFC6A57DFFC4A17AFF8FA8
9AFF80D4EBFFB2E3F9FF8BC0E7FFAED3F6FFC4E0FCFF669FD3F7FFFFFF009B6A
48E1D9C2A4FFC1A472FFD2B894FFF5EDE4FFF4ECE2FFF4ECE1FFF4EBE0FFF3EA
DFFF8FAEA2FF77BEE7FFB4D2F0FFE5F3FFFFACD2EFFF488CC7E8FFFFFF009B6A
49E1DBC5A6FFC6A776FFD9BF9BFFD1B793FFCBB08EFFCAAE8AFFC8AB87FFCBAB
83FFD1B087FFA2B7B1FF58A5D8FF85B1DBFF469DD0FF2B95D15EFFFFFF009C6B
4AE1DDC8A9FFD4BD95FFE6D4B9FFE6D1B6FFE4D0B5FFE3CEB3FFE2CBB0FFE0C9
ADFFDFC7A9FFDABFA0FF9A6B4AFF573E2AFFFFFFFF00FFFFFF00FFFFFF009C6C
4BE0D9C2A5FFB59170FFAB805FFFA97E5EFFA97E5EFFA87D5CFFA87C5BFFA77B
5AFFA67959FF9C6B49FF966441FF573E2AFFFFFFFF00FFFFFF00FFFFFF009D6D
4BCFBA9778FFD8C5B9FFE8DED7FFE7DDD6FFE6DCD6FFE4DBD4FFE3DAD3FFE2D8
D1FFE1D7D0FFEBE7E5FFEFEFEFFF573E2AFFFFFFFF00FFFFFF00FFFFFF009D6D
4C919D6D4BFEBB9778FFAC8262FFAC8161FFAB8060FFAB7F5FFFAA7F5EFFA87E
5DFFA87C5CFF9D6D4CFF976643FF885C3CFFFFFFFF00FFFFFF00FFFFFF009E6E
4D2B9D6D4CD69D6D4BC59D6C4BFF9C6C4AFF9C6B49FF9B6A49FF9B6A48FF9A69
47FF996846FF986745FF936443FF845D3EDEFFFFFF00FFFFFF00
}
OnClick = btnEditAliasClick
TabOrder = 4
end
end
object List: TListView[1]
Left = 4
Height = 309
Top = 36
Width = 458
Align = alClient
AutoWidthLastColumn = True
BorderSpacing.Around = 4
Columns = <
item
Caption = 'Alias'
Width = 100
end
item
Caption = 'Library file'
Width = 200
end
item
Caption = 'Sources root'
Width = 154
end>
GridLines = True
HideSelection = False
ReadOnly = True
RowSelect = True
TabOrder = 1
ViewStyle = vsReport
OnEdited = ListEdited
end
end
end
inherited contextMenu: TPopupMenu
left = 184
top = 8
end
end

166
src/ce_libmaneditor.pas Normal file
View File

@ -0,0 +1,166 @@
unit ce_libmaneditor;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Menus, ComCtrls, Buttons, ce_widget;
type
{ TCELibManEditorWidget }
TCELibManEditorWidget = class(TCEWidget)
btnSelFile: TBitBtn;
btnAddLib: TBitBtn;
btnRemLib: TBitBtn;
btnEditAlias: TBitBtn;
btnSelRoot: TBitBtn;
List: TListView;
Panel1: TPanel;
procedure btnAddLibClick(Sender: TObject);
procedure btnEditAliasClick(Sender: TObject);
procedure btnRemLibClick(Sender: TObject);
procedure btnSelFileClick(Sender: TObject);
procedure btnSelRootClick(Sender: TObject);
procedure ListEdited(Sender: TObject; Item: TListItem; var AValue: string);
private
procedure dataToGrid;
procedure gridToData;
protected
procedure DoShow; override;
end;
implementation
{$R *.lfm}
uses
ce_main, ce_libman;
procedure TCELibManEditorWidget.ListEdited(Sender: TObject; Item: TListItem;
var AValue: string);
begin
GridToData;
end;
procedure TCELibManEditorWidget.btnAddLibClick(Sender: TObject);
var
itm: TListItem;
const
notav: string = '< n/a >';
begin
itm := List.Items.Add;
itm.Caption := notav;
itm.SubItems.Add(notav);
itm.SubItems.Add(notav);
end;
procedure TCELibManEditorWidget.btnEditAliasClick(Sender: TObject);
var
al: string;
begin
if List.Selected = nil then exit;
al := List.Selected.Caption;
if inputQuery('library alias', '', al) then
List.Selected.Caption := al;
GridToData;
end;
procedure TCELibManEditorWidget.btnRemLibClick(Sender: TObject);
begin
if List.Selected = nil then exit;
List.Items.Delete( List.Selected.Index );
gridToData;
end;
procedure TCELibManEditorWidget.btnSelFileClick(Sender: TObject);
var
ini: string;
begin
if List.Selected = nil then exit;
if List.Selected.SubItems.Count > 0 then
ini := List.Selected.SubItems[0]
else
begin
ini := '';
List.Selected.SubItems.Add(ini);
end;
with TOpenDialog.Create(nil) do
try
filename := ini;
if execute then
List.Selected.SubItems[0] := filename;
finally
Free;
end;
GridToData;
end;
procedure TCELibManEditorWidget.btnSelRootClick(Sender: TObject);
var
dir, outdir: string;
begin
if List.Selected = nil then exit;
if List.Selected.SubItems.Count > 1 then
dir := List.Selected.SubItems[1]
else
begin
dir := '';
while List.Selected.SubItems.Count < 2 do
List.Selected.SubItems.Add(dir);
end;
if selectDirectory('sources root', dir, outdir, true, 0) then
List.Selected.SubItems[1] := outdir;
GridToData;
end;
procedure TCELibManEditorWidget.DoShow;
begin
inherited;
dataToGrid;
end;
procedure TCELibManEditorWidget.dataToGrid;
var
itm: TLibraryItem;
row: TListItem;
i: NativeInt;
begin
List.Clear;
with CEMainForm do
begin
if LibraryManager = nil then exit;
for i:= 0 to LibraryManager.libraries.Count-1 do
begin
itm := TLibraryItem( LibraryManager.libraries.Items[i]);
row := List.Items.Add;
row.Caption := itm.libAlias;
row.SubItems.Add(itm.libFile);
row.SubItems.Add(itm.libSourcePath);
end;
end;
end;
procedure TCELibManEditorWidget.gridToData;
var
itmt: TLibraryItem;
row: TListItem;
begin
with CEMainForm do
begin
if LibraryManager = nil then exit;
LibraryManager.libraries.Clear;
for row in List.Items do
begin
itmt := TLibraryItem(LibraryManager.libraries.Add);
itmt.libAlias := row.Caption;
itmt.libFile := row.SubItems.Strings[0];
itmt.libSourcePath := row.SubItems.Strings[1];
end;
end;
end;
end.

View File

@ -1,7 +1,7 @@
object CEMainForm: TCEMainForm object CEMainForm: TCEMainForm
Left = 1071 Left = 1064
Height = 49 Height = 49
Top = 187 Top = 186
Width = 745 Width = 745
AllowDropFiles = True AllowDropFiles = True
Caption = 'Coedit' Caption = 'Coedit'

View File

@ -8,13 +8,15 @@ uses
Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms, Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms,
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics, AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics,
Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls, Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls,
ce_common, ce_dmdwrap, ce_project, ce_synmemo, ce_widget, ce_messages, ce_common, ce_dmdwrap, ce_project, ce_plugin, ce_synmemo, ce_widget, ce_messages,
ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer, ce_search, ce_miniexplorer; ce_widgettypes, ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer, ce_search,
ce_miniexplorer, dynlibs, ce_libman, ce_libmaneditor;
type type
TCEMainForm = class; TCEMainForm = class;
//TODO-cfeature: switches -f<sourcefile.d>, -p<project.coedit>, -noplug
//TODO-cfeature: options //TODO-cfeature: options
//TODO-cwidget: options editor //TODO-cwidget: options editor
(** (**
@ -197,6 +199,7 @@ type
private private
fUpdateCount: NativeInt; fUpdateCount: NativeInt;
fProject: TCEProject; fProject: TCEProject;
fPlugList: TCEPlugDescriptorList;
fWidgList: TCEWidgetList; fWidgList: TCEWidgetList;
fMesgWidg: TCEMessagesWidget; fMesgWidg: TCEMessagesWidget;
fEditWidg: TCEEditorWidget; fEditWidg: TCEEditorWidget;
@ -205,16 +208,21 @@ type
fStExpWidg: TCEStaticExplorerWidget; fStExpWidg: TCEStaticExplorerWidget;
fFindWidg: TCESearchWidget; fFindWidg: TCESearchWidget;
fExplWidg: TCEMiniExplorerWidget; fExplWidg: TCEMiniExplorerWidget;
fLibMWidg: TCELibManEditorWidget;
fProjMru: TMruFileList; fProjMru: TMruFileList;
fFileMru: TMruFileList; fFileMru: TMruFileList;
fLibMan: TLibraryManager;
//Init - Fina //Init - Fina
procedure InitLibMan;
procedure InitMRUs; procedure InitMRUs;
procedure InitWidgets; procedure InitWidgets;
procedure InitPlugins;
procedure InitDocking; procedure InitDocking;
procedure InitSettings; procedure InitSettings;
procedure SaveSettings; procedure SaveSettings;
procedure SaveDocking; procedure SaveDocking;
procedure KillPlugs;
// widget interfaces subroutines // widget interfaces subroutines
procedure checkWidgetActions(const aWidget: TCEWidget); procedure checkWidgetActions(const aWidget: TCEWidget);
@ -263,8 +271,11 @@ type
property EditWidget: TCEEditorWidget read fEditWidg; property EditWidget: TCEEditorWidget read fEditWidg;
property ProjectWidget: TCEProjectInspectWidget read fProjWidg; property ProjectWidget: TCEProjectInspectWidget read fProjWidg;
property ProjectConfWidget: TCEProjectConfigurationWidget read fPrjCfWidg; property ProjectConfWidget: TCEProjectConfigurationWidget read fPrjCfWidg;
property LibraryManager: TLibraryManager read fLibMan;
end; end;
procedure PlugDispatchToHost(aPlugin: TCEPlugin; opCode: LongWord; data0: Integer; data1, data2: Pointer); cdecl;
var var
CEMainForm: TCEMainForm; CEMainForm: TCEMainForm;
@ -279,11 +290,23 @@ constructor TCEMainForm.create(aOwner: TComponent);
begin begin
inherited create(aOwner); inherited create(aOwner);
InitMRUs; InitMRUs;
InitLibMan;
InitWidgets; InitWidgets;
InitDocking; InitDocking;
InitSettings; InitSettings;
// //
newProj; newProj;
InitPlugins;
end;
procedure TCEMainForm.InitLibMan;
var
fname: string;
begin
fLibMan := TLibraryManager.create(self);
fname := getDocPath + 'libraryManager.txt';
if fileExists(fname) then
fLibMan.loadFromFile(fname);
end; end;
procedure TCEMainForm.InitMRUs; procedure TCEMainForm.InitMRUs;
@ -296,6 +319,49 @@ begin
fFileMru.OnChange := @mruChange; fFileMru.OnChange := @mruChange;
end; end;
procedure TCEMainForm.InitPlugins;
var
pth: string;
fname: string;
lst: TStringList;
hdl: TLibHandle;
plg: PPlugDescriptor;
begin
fPlugList := TCEPlugDescriptorList.Create;
pth := extractFilePath(application.ExeName) + 'plugins';
lst := TStringList.Create;
try
listFiles(lst, pth, false);
for fname in lst do
begin
if extractFileExt(fname) <> '.' + SharedSuffix then
continue;
hdl := LoadLibrary(fname);
if hdl = NilHandle then
continue;
plg := new(PPlugDescriptor);
plg^.Handle := hdl;
plg^.HostCreatePlug := THostCreatePlug(GetProcAddress(hdl, 'createPlug'));
plg^.HostDestroyPlug := THostDestroyPlug(GetProcAddress(hdl, 'destroyPlug'));
plg^.HostDispatchToPlug := THostDispatchToPlug(GetProcAddress(hdl, 'dispatchToPlug'));
if plg^.HostCreatePlug <> nil then
plg^.Plugin := plg^.HostCreatePlug(@PlugDispatchToHost);
if (plg^.HostCreatePlug = nil) or (plg^.HostDestroyPlug = nil) or
(plg^.HostDispatchToPlug = nil) then
begin
Dispose(plg);
//FreeLibrary(hdl);
continue;
end;
fPlugList.addPlugin(plg);
end;
finally
lst.Free;
end;
end;
procedure TCEMainForm.InitWidgets; procedure TCEMainForm.InitWidgets;
var var
widg: TCEWidget; widg: TCEWidget;
@ -310,6 +376,7 @@ begin
fStExpWidg:= TCEStaticExplorerWidget.create(self); fStExpWidg:= TCEStaticExplorerWidget.create(self);
fFindWidg := TCESearchWidget.create(self); fFindWidg := TCESearchWidget.create(self);
fExplWidg := TCEMiniExplorerWidget.create(self); fExplWidg := TCEMiniExplorerWidget.create(self);
fLibMWidg := TCELibManEditorWidget.create(self);
fWidgList.addWidget(@fMesgWidg); fWidgList.addWidget(@fMesgWidg);
fWidgList.addWidget(@fEditWidg); fWidgList.addWidget(@fEditWidg);
@ -318,6 +385,7 @@ begin
fWidgList.addWidget(@fStExpWidg); fWidgList.addWidget(@fStExpWidg);
fWidgList.addWidget(@fFindWidg); fWidgList.addWidget(@fFindWidg);
fWidgList.addWidget(@fExplWidg); fWidgList.addWidget(@fExplWidg);
fWidgList.addWidget(@fLibMWidg);
for widg in fWidgList do for widg in fWidgList do
begin begin
@ -368,6 +436,7 @@ begin
DockMaster.GetAnchorSite(fEditWidg).Header.HeaderPosition := adlhpTop; DockMaster.GetAnchorSite(fEditWidg).Header.HeaderPosition := adlhpTop;
DockMaster.GetAnchorSite(fExplWidg).Close; DockMaster.GetAnchorSite(fExplWidg).Close;
DockMaster.GetAnchorSite(fLibMWidg).Close;
end; end;
procedure TCEMainForm.InitSettings; procedure TCEMainForm.InitSettings;
@ -386,9 +455,9 @@ begin
if opts.hasLoaded then if opts.hasLoaded then
begin begin
if fileExists(fname2) then if fileExists(fname2) then
deleteFile(fname2); sysutils.deleteFile(fname2);
if not fileExists(fname2) then if not fileExists(fname2) then
copyFile(fname1, fname2, false); fileutil.copyFile(fname1, fname2, false);
end; end;
end; end;
finally finally
@ -403,6 +472,7 @@ begin
opts := TCEOptions.create(nil); opts := TCEOptions.create(nil);
try try
forceDirectory(getDocPath); forceDirectory(getDocPath);
fLibMan.saveToFile(getDocPath + 'libraryManager.txt');
opts.saveToFile(getDocPath + 'options.txt'); opts.saveToFile(getDocPath + 'options.txt');
finally finally
opts.Free; opts.Free;
@ -416,18 +486,40 @@ begin
xcfg := TXMLConfigStorage.Create(getDocPath + 'docking.xml',false); xcfg := TXMLConfigStorage.Create(getDocPath + 'docking.xml',false);
try try
// <Item1 Name="CEMainForm" Type="CustomSite" ChildCount="..."> is always missing // <Item1 Name="CEMainForm" Type="CustomSite" ChildCount="..."> is always missing
DockMaster.SaveLayoutToConfig(xcfg); //DockMaster.SaveLayoutToConfig(xcfg);
xcfg.WriteToDisk; //xcfg.WriteToDisk;
finally finally
xcfg.Free; xcfg.Free;
end; end;
end; end;
procedure TCEMainForm.KillPlugs;
var
descr: TPlugDescriptor;
begin
if fPlugList = nil then exit;
for descr in fPlugList do
begin
descr.HostDestroyPlug(descr.Plugin);
{$IFDEF WINDOWS}
//FreeLibrary(descr.Handle);
{$ENDIF}
end;
while fPlugList.Count <> 0 do
begin
Dispose(PPlugDescriptor(fPlugList.Items[fPlugList.Count-1]));
fPlugList.Delete(fPlugList.Count-1);
end;
fPlugList.Free;
end;
destructor TCEMainForm.destroy; destructor TCEMainForm.destroy;
begin begin
SaveSettings; SaveSettings;
SaveDocking; SaveDocking;
// //
KillPlugs;
//
fWidgList.Free; fWidgList.Free;
fProjMru.Free; fProjMru.Free;
fFileMru.Free; fFileMru.Free;
@ -1015,11 +1107,11 @@ begin
runproc.Execute; runproc.Execute;
repeat ProcessOutputToMsg(runproc, mcEditor) until not runproc.Running; repeat ProcessOutputToMsg(runproc, mcEditor) until not runproc.Running;
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
DeleteFile(fname + '.exe'); sysutils.DeleteFile(fname + '.exe');
DeleteFile(fname + '.obj'); sysutils.DeleteFile(fname + '.obj');
{$ELSE} {$ELSE}
DeleteFile(fname); sysutils.DeleteFile(fname);
DeleteFile(fname + '.o'); sysutils.DeleteFile(fname + '.o');
{$ENDIF} {$ENDIF}
end end
else begin else begin
@ -1031,7 +1123,7 @@ begin
dmdproc.Free; dmdproc.Free;
runproc.Free; runproc.Free;
if extractFilePath(editor.fileName) = GetTempDir(false) then if extractFilePath(editor.fileName) = GetTempDir(false) then
DeleteFile(editor.fileName); sysutils.DeleteFile(editor.fileName);
chDir(olddir); chDir(olddir);
end; end;
end; end;
@ -1051,7 +1143,7 @@ begin
if aProject.Sources.Count = 0 then if aProject.Sources.Count = 0 then
begin begin
fMesgWidg.addCeErr( aProject.fileName + ' has no source files', mcProject); fMesgWidg.addCeWarn('the project has no source files', mcProject);
exit; exit;
end; end;
@ -1295,6 +1387,7 @@ begin
fProject.Name := 'CurrentProject'; fProject.Name := 'CurrentProject';
for widg in WidgetList do widg.projNew(fProject); for widg in WidgetList do widg.projNew(fProject);
fProject.onChange := @projChange; fProject.onChange := @projChange;
fProject.libraryManager := fLibMan;
end; end;
procedure TCEMainForm.saveProj; procedure TCEMainForm.saveProj;
@ -1549,6 +1642,40 @@ begin
end; end;
{$ENDREGION} {$ENDREGION}
procedure PlugDispatchToHost(aPlugin: TCEPlugin; opCode: LongWord; data0: Integer; data1, data2: Pointer); cdecl;
var
ctxt: NativeUint;
oper: NativeUint;
begin
if opCode = HELLO_PLUGIN then begin
dlgOkInfo('Hello plugin');
exit;
end;
ctxt := opCode and $0F000000;
oper := opCode and $000FFFFF;
case ctxt of
CTXT_MSGS:
case oper of
DT_ERR: CEMainForm.MessageWidget.addCeErr(PChar(data1));
DT_INF: CEMainForm.MessageWidget.addCeInf(PChar(data1));
DT_WARN: CEMainForm.MessageWidget.addCeWarn(PChar(data1));
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end;
CTXT_DLGS:
case oper of
DT_ERR: dlgOkError(PChar(data1));
DT_INF: dlgOkInfo(PChar(data1));
DT_WARN: dlgOkInfo(PChar(data1));
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end;
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end;
end;
initialization initialization
RegisterClasses([TCEOptions]); RegisterClasses([TCEOptions]);
end. end.

View File

@ -1,7 +1,7 @@
inherited CEMiniExplorerWidget: TCEMiniExplorerWidget inherited CEMiniExplorerWidget: TCEMiniExplorerWidget
Left = 1539 Left = 1493
Height = 651 Height = 651
Top = 6 Top = 45
Caption = 'Mini explorer' Caption = 'Mini explorer'
ClientHeight = 651 ClientHeight = 651
inherited Back: TPanel inherited Back: TPanel

196
src/ce_plugin.pas Normal file
View File

@ -0,0 +1,196 @@
unit ce_plugin;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, dynlibs;
type
TCEHost = type Pointer;
TCEPlugin = type Pointer;
const
// API version
CE_PLG_API_VER = 0;
// opcodes constants -------------------------------------------------------------]
HELLO_PLUGIN = $FFFFFFFF; // hello world
// Denotes the emiter and the message kind -------------------------------------
/// Coedit sends an event.
HOST_EVENT = $10000000;
/// Coedit sends some data.
HOST_DATA = $20000000;
/// The plug-in sends an event.
PLUG_EVENT = $30000000;
/// The plug-in sends some data.
PLUG_DATA = $40000000;
// Denotes the message context -------------------------------------------------
/// the dispatcher call is related to the project(s)
CTXT_PROJ = $01000000;
/// the dispatcher call is related to the document(s)
CTXT_DOCS = $02000000;
/// the dispatcher call is related to the edition of a document.
CTXT_EDIT = $03000000;
/// the dispatcher call is related to the Coedit 'Message Widget'.
CTXT_MSGS = $04000000;
/// the dispatcher call is related to the Coedit dialogs.
CTXT_DLGS = $05000000;
// The events kinds ------------------------------------------------------------
/// somethings's just changed.
EV_CHANGED = $00000001;
/// something's just been selected.
EV_FOCUSED = $00000002;
/// something's just been closed.
EV_CLOSED = $00000003;
/// something's just been created.
EV_NEW = $00000004;
/// something gonna be compiled.
EV_COMPILE = $00000005;
/// something gonna be executed.
EV_RUN = $00000006;
// The data kinds --------------------------------------------------------------
/// data1 is used to set/get a filename. data1 is a PChar. data0 represents an index.
DT_FNAME = $00000001;
/// data0 represents a count.
DT_COUNT = $00000002;
/// data1 is used to set a message. data1 is a PChar.
DT_ERR = $00000001;
DT_INF = $00000002;
DT_WARN = $00000003;
DATA_FNAME = $00000001;
// terminal opCodes (emiter + context + event/data kind) -----------------------
/// Coedit says that the project's just been modified.
HOST_PROJ_CHANGED = HOST_EVENT + CTXT_PROJ + EV_CHANGED;
/// opCode for asking for a document filename. data0 must be the document index.
PLUG_WANT_DOC_NAME = PLUG_EVENT + CTXT_DOCS + DT_FNAME;
/// opCode for getting a document filenmae. data1 is a PChar to the filename.
HOST_GIVE_DOC_NAME = HOST_DATA + CTXT_DOCS + DT_FNAME;
/// opCodes for displaying a message in a dialog box.
PLUG_DLGS_ERR = PLUG_DATA + CTXT_DLGS + DT_ERR;
/// ditto.
PLUG_DLGS_WARN = PLUG_DATA + CTXT_DLGS + DT_WARN;
/// ditto.
PLUG_DLGS_INF = PLUG_DATA + CTXT_DLGS + DT_INF;
/// opCodes for displaying a message in the 'Message Widget'.
PLUG_MSGS_ERR = PLUG_DATA + CTXT_MSGS + DT_ERR;
/// ditto.
PLUG_MSGS_WARN = PLUG_DATA + CTXT_MSGS + DT_WARN;
/// ditto.
PLUG_MSGS_INF = PLUG_DATA + CTXT_MSGS + DT_INF;
// host-side prototypes --------------------------------------------------------
type
(**
* A plugin asks for some information or it passes data here.
* Data1 and data2 are some pointers to a particular variable type.
* In the plugin hostCreatePlugProc, a the location of COedit dispatcher is passed
* to the plugin.
*)
TPlugDispatchToHost = procedure(aPlugin: TCEPlugin; opCode: LongWord; data0: Integer; data1, data2: Pointer); cdecl;
// plugin-side prototypes ------------------------------------------------------
(**
* Coedit initializes a plugin, the result is passed during the runtime as "aTarget".
* In the plugin implementation, it must be named 'createPlug'.
* If the result is null then the Plugin is not used at all.
* If the plugin is not warped in a class than the result must be set on something
* that can be pointed to (e.g: a global variable).
*)
THostCreatePlug = function(aHost: TPlugDispatchToHost): TCEPlugin; cdecl;
(**
* Coedit closes and aTarget can be destroyed.
* In the plugin implementation, it must be named 'destroyPlug'.
*)
THostDestroyPlug = procedure(aTarget: TCEPlugin); cdecl;
(**
* Coedit events and data are passed here. data1 and data2 can be casted according to opCode.
* In the plugin implementation, it must be named 'dispatchToPlug'.
*)
THostDispatchToPlug = procedure(aTarget: TCEPlugin; data0: Integer; opCode: LongWord; data1, data2: Pointer); cdecl;
// internal --------------------------------------------------------------------
PPlugDescriptor = ^TPlugDescriptor;
TPlugDescriptor = record
Handle: TLibHandle;
Plugin: TCEPlugin;
HostCreatePlug: THostCreatePlug;
HostDestroyPlug: THostDestroyPlug;
HostDispatchToPlug: THostDispatchToPlug;
end;
TCEPlugDescriptorList = class(TList)
private
function getPlugin(index: integer): TPlugDescriptor;
public
procedure addPlugin(aValue: PPlugDescriptor);
property plugin[index: integer]: TPlugDescriptor read getPlugin;
end;
TPlugDescriptorEnumerator = class
fList: TCEPlugDescriptorList;
fIndex: Integer;
function getCurrent: TPlugDescriptor;
Function moveNext: boolean;
property current: TPlugDescriptor read getCurrent;
end;
operator enumerator(aPlugDescrList: TCEPlugDescriptorList): TPlugDescriptorEnumerator;
implementation
function TCEPlugDescriptorList.getPlugin(index: integer): TPlugDescriptor;
begin
result := TPlugDescriptor(Items[index]^);
end;
procedure TCEPlugDescriptorList.addPlugin(aValue: PPlugDescriptor);
begin
add(Pointer(aValue));
end;
function TPlugDescriptorEnumerator.getCurrent: TPlugDescriptor;
begin
result := fList.plugin[fIndex];
end;
function TPlugDescriptorEnumerator.moveNext: boolean;
begin
Inc(fIndex);
result := fIndex < fList.Count;
end;
operator enumerator(aPlugDescrList: TCEPlugDescriptorList): TPlugDescriptorEnumerator;
begin
result := TPlugDescriptorEnumerator.Create;
result.fList := aPlugDescrList;
result.fIndex := -1;
end;
end.

View File

@ -7,7 +7,7 @@ interface
// TODO: configuration templates // TODO: configuration templates
uses uses
Classes, SysUtils, ce_dmdwrap; Classes, SysUtils, ce_dmdwrap, ce_libman;
type type
@ -25,11 +25,14 @@ type
fModified: boolean; fModified: boolean;
fFilename: string; fFilename: string;
fBasePath: string; fBasePath: string;
fLibAliases: TStringList;
fOptsColl: TCollection; fOptsColl: TCollection;
fSrcs, fSrcsCop: TStringList; fSrcs, fSrcsCop: TStringList;
fConfIx: Integer; fConfIx: Integer;
fLibMan: TLibraryManager;
fChangedCount: NativeInt; fChangedCount: NativeInt;
procedure doChanged; procedure doChanged;
procedure setLibAliases(const aValue: TStringList);
procedure subMemberChanged(sender : TObject); procedure subMemberChanged(sender : TObject);
procedure setOptsColl(const aValue: TCollection); procedure setOptsColl(const aValue: TCollection);
procedure setFname(const aValue: string); procedure setFname(const aValue: string);
@ -45,6 +48,7 @@ type
property OptionsCollection: TCollection read fOptsColl write setOptsColl; property OptionsCollection: TCollection read fOptsColl write setOptsColl;
property Sources: TStringList read fSrcs write setSrcs; // 'read' should return a copy to avoid abs/rel errors property Sources: TStringList read fSrcs write setSrcs; // 'read' should return a copy to avoid abs/rel errors
property ConfigurationIndex: Integer read fConfIx write setConfIx; property ConfigurationIndex: Integer read fConfIx write setConfIx;
property LibraryAliases: TStringList read fLibAliases write setLibAliases;
public public
constructor create(aOwner: TComponent); override; constructor create(aOwner: TComponent); override;
destructor destroy; override; destructor destroy; override;
@ -59,6 +63,7 @@ type
procedure saveToFile(const aFilename: string); procedure saveToFile(const aFilename: string);
procedure loadFromFile(const aFilename: string); procedure loadFromFile(const aFilename: string);
// //
property libraryManager: TLibraryManager read fLibMan write fLibMan;
property configuration[ix: integer]: TCompilerConfiguration read getConfig; property configuration[ix: integer]: TCompilerConfiguration read getConfig;
property currentConfiguration: TCompilerConfiguration read getCurrConf; property currentConfiguration: TCompilerConfiguration read getCurrConf;
property fileName: string read fFilename write setFname; property fileName: string read fFilename write setFname;
@ -74,6 +79,7 @@ uses
constructor TCEProject.create(aOwner: TComponent); constructor TCEProject.create(aOwner: TComponent);
begin begin
inherited create(aOwner); inherited create(aOwner);
fLibAliases := TStringList.Create;
fSrcs := TStringList.Create; fSrcs := TStringList.Create;
fSrcs.OnChange := @subMemberChanged; fSrcs.OnChange := @subMemberChanged;
fSrcsCop := TStringList.Create; fSrcsCop := TStringList.Create;
@ -85,6 +91,7 @@ end;
destructor TCEProject.destroy; destructor TCEProject.destroy;
begin begin
fOnChange := nil; fOnChange := nil;
fLibAliases.Free;
fSrcs.free; fSrcs.free;
fSrcsCop.Free; fSrcsCop.Free;
fOptsColl.free; fOptsColl.free;
@ -141,6 +148,13 @@ begin
afterChanged; afterChanged;
end; end;
procedure TCEProject.setLibAliases(const aValue: TStringList);
begin
beforeChanged;
fLibAliases.Assign(aValue);
afterChanged;
end;
procedure TCEProject.setSrcs(const aValue: TStringList); procedure TCEProject.setSrcs(const aValue: TStringList);
begin begin
beforeChanged; beforeChanged;
@ -242,6 +256,13 @@ begin
abs := expandFilenameEx(fBasePath,rel); abs := expandFilenameEx(fBasePath,rel);
aList.Add(abs); // process.inc ln 249. double quotes are added if there's a space. aList.Add(abs); // process.inc ln 249. double quotes are added if there's a space.
end; end;
//
if fLibMan <> nil then
begin
fLibMan.getAdditionalSources(fLibAliases, aList);
fLibMan.getAdditionalImport(fLibAliases, aList);
end;
//
TCompilerConfiguration(fOptsColl.Items[fConfIx]).getOpts(aList); TCompilerConfiguration(fOptsColl.Items[fConfIx]).getOpts(aList);
end; end;
@ -274,9 +295,9 @@ end;
procedure TCEProject.readerPropNoFound(Reader: TReader; Instance: TPersistent; procedure TCEProject.readerPropNoFound(Reader: TReader; Instance: TPersistent;
var PropName: string; IsPath: boolean; var Handled, Skip: Boolean); var PropName: string; IsPath: boolean; var Handled, Skip: Boolean);
var //var
idt: string; //idt: string;
curr: TCompilerConfiguration; //curr: TCompilerConfiguration;
begin begin
// continue loading: this method ensures the project compat. in case of drastic changes. // continue loading: this method ensures the project compat. in case of drastic changes.

View File

@ -74,7 +74,7 @@ type
implementation implementation
{$R *.lfm} {$R *.lfm}
uses ce_main; uses ce_main, ce_libman;
{$REGION Standard Comp/Obj------------------------------------------------------} {$REGION Standard Comp/Obj------------------------------------------------------}
constructor TCEStaticExplorerWidget.create(aOwner: TComponent); constructor TCEStaticExplorerWidget.create(aOwner: TComponent);
@ -323,6 +323,9 @@ var
ln: PInt64; ln: PInt64;
nme, knd: string; nme, knd: string;
i: NativeInt; i: NativeInt;
itm: TCollectionItem;
itmt: TLibraryItem;
allALiases: TStringList;
// recursively display members, without master categories. // recursively display members, without master categories.
procedure digMembers(const srcDt: TJsonData; const srcNd: TTreeNode); procedure digMembers(const srcDt: TJsonData; const srcNd: TTreeNode);
@ -378,7 +381,7 @@ begin
// //
lines.Assign(fDoc.Lines); lines.Assign(fDoc.Lines);
lines.SaveToFile(scf); lines.SaveToFile(scf);
// // option to gen. the Json file.
dmdProc.ShowWindow := swoHIDE; dmdProc.ShowWindow := swoHIDE;
dmdproc.Options := []; dmdproc.Options := [];
dmdproc.Executable := 'dmd'; dmdproc.Executable := 'dmd';
@ -387,6 +390,7 @@ begin
dmdproc.Parameters.Add('-o-'); dmdproc.Parameters.Add('-o-');
dmdproc.Parameters.Add('-X'); dmdproc.Parameters.Add('-X');
dmdproc.Parameters.Add('-Xf' + jsf); dmdproc.Parameters.Add('-Xf' + jsf);
// projects add.sources and I.
if fProj <> nil then if fProj <> nil then
begin begin
dmdProc.CurrentDirectory := extractFilePath(fProj.fileName); dmdProc.CurrentDirectory := extractFilePath(fProj.fileName);
@ -395,6 +399,23 @@ begin
for nme in fProj.currentConfiguration.pathsOptions.Includes do for nme in fProj.currentConfiguration.pathsOptions.Includes do
dmdproc.Parameters.Add('-I' + nme); dmdproc.Parameters.Add('-I' + nme);
end; end;
// add. sources and I from libman.
with CEMainForm do
begin
allALiases := TstringList.Create;
try
for itm in Librarymanager.libraries do
begin
itmt := TLibraryItem(itm);
allALiases.Add(itmt.libAlias);
end;
Librarymanager.getAdditionalSources(allALiases,dmdproc.Parameters);
Librarymanager.getAdditionalImport(allALiases,dmdproc.Parameters);
finally
allALiases.Free;
end;
end;
//
dmdproc.Execute; dmdproc.Execute;
while dmdproc.Running do; while dmdproc.Running do;
finally finally

View File

@ -9,8 +9,6 @@ uses
type type
// TODO-cfeature: document content access/modification
(** (**
* An implementer can save and load some stuffs on application start/quit * An implementer can save and load some stuffs on application start/quit
*) *)
@ -69,5 +67,6 @@ type
end; end;
implementation implementation
end. end.