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.
(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:
- 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: fix position in source code broken.
- 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, option: possible startup crash fixed when invalid height or width.
- ce_main: option, possible startup crash fixed when invalid height or width.
r23:
- 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"/>
</Item6>
</RequiredPackages>
<Units Count="18">
<Units Count="21">
<Unit0>
<Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/>
@ -252,6 +252,24 @@
<ResourceBaseClass Value="Form"/>
<UnitName Value="ce_miniexplorer"/>
</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>
</ProjectOptions>
<CompilerOptions>

View File

@ -10,7 +10,8 @@ uses
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg,
ce_widget, ce_dmdwrap, ce_common, ce_synmemo, ce_main, ce_messages, ce_editor,
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}

View File

@ -455,6 +455,7 @@ const
{$ENDIF}
begin
{$IFDEF WINDOWS}
PIDL := nil;
SHGetSpecialFolderLocation(0, CSIDL_APPDATA, PIDL);
SHGetPathFromIDList(PIDL, 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
Left = 1071
Left = 1064
Height = 49
Top = 187
Top = 186
Width = 745
AllowDropFiles = True
Caption = 'Coedit'

View File

@ -8,13 +8,15 @@ uses
Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms,
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics,
Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls,
ce_common, ce_dmdwrap, ce_project, ce_synmemo, ce_widget, ce_messages,
ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer, ce_search, ce_miniexplorer;
ce_common, ce_dmdwrap, ce_project, ce_plugin, ce_synmemo, ce_widget, ce_messages,
ce_widgettypes, ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer, ce_search,
ce_miniexplorer, dynlibs, ce_libman, ce_libmaneditor;
type
TCEMainForm = class;
//TODO-cfeature: switches -f<sourcefile.d>, -p<project.coedit>, -noplug
//TODO-cfeature: options
//TODO-cwidget: options editor
(**
@ -197,6 +199,7 @@ type
private
fUpdateCount: NativeInt;
fProject: TCEProject;
fPlugList: TCEPlugDescriptorList;
fWidgList: TCEWidgetList;
fMesgWidg: TCEMessagesWidget;
fEditWidg: TCEEditorWidget;
@ -205,16 +208,21 @@ type
fStExpWidg: TCEStaticExplorerWidget;
fFindWidg: TCESearchWidget;
fExplWidg: TCEMiniExplorerWidget;
fLibMWidg: TCELibManEditorWidget;
fProjMru: TMruFileList;
fFileMru: TMruFileList;
fLibMan: TLibraryManager;
//Init - Fina
procedure InitLibMan;
procedure InitMRUs;
procedure InitWidgets;
procedure InitPlugins;
procedure InitDocking;
procedure InitSettings;
procedure SaveSettings;
procedure SaveDocking;
procedure KillPlugs;
// widget interfaces subroutines
procedure checkWidgetActions(const aWidget: TCEWidget);
@ -263,8 +271,11 @@ type
property EditWidget: TCEEditorWidget read fEditWidg;
property ProjectWidget: TCEProjectInspectWidget read fProjWidg;
property ProjectConfWidget: TCEProjectConfigurationWidget read fPrjCfWidg;
property LibraryManager: TLibraryManager read fLibMan;
end;
procedure PlugDispatchToHost(aPlugin: TCEPlugin; opCode: LongWord; data0: Integer; data1, data2: Pointer); cdecl;
var
CEMainForm: TCEMainForm;
@ -279,11 +290,23 @@ constructor TCEMainForm.create(aOwner: TComponent);
begin
inherited create(aOwner);
InitMRUs;
InitLibMan;
InitWidgets;
InitDocking;
InitSettings;
//
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;
procedure TCEMainForm.InitMRUs;
@ -296,6 +319,49 @@ begin
fFileMru.OnChange := @mruChange;
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;
var
widg: TCEWidget;
@ -310,6 +376,7 @@ begin
fStExpWidg:= TCEStaticExplorerWidget.create(self);
fFindWidg := TCESearchWidget.create(self);
fExplWidg := TCEMiniExplorerWidget.create(self);
fLibMWidg := TCELibManEditorWidget.create(self);
fWidgList.addWidget(@fMesgWidg);
fWidgList.addWidget(@fEditWidg);
@ -318,6 +385,7 @@ begin
fWidgList.addWidget(@fStExpWidg);
fWidgList.addWidget(@fFindWidg);
fWidgList.addWidget(@fExplWidg);
fWidgList.addWidget(@fLibMWidg);
for widg in fWidgList do
begin
@ -350,7 +418,7 @@ begin
end;
Height := 0;
for i := 0 to fWidgList.Count-1 do
for i := 0 to fWidgList.Count-1 do
begin
DockMaster.MakeDockable(fWidgList.widget[i],true);
DockMaster.GetAnchorSite(fWidgList.widget[i]).Header.HeaderPosition := adlhpTop;
@ -368,6 +436,7 @@ begin
DockMaster.GetAnchorSite(fEditWidg).Header.HeaderPosition := adlhpTop;
DockMaster.GetAnchorSite(fExplWidg).Close;
DockMaster.GetAnchorSite(fLibMWidg).Close;
end;
procedure TCEMainForm.InitSettings;
@ -386,9 +455,9 @@ begin
if opts.hasLoaded then
begin
if fileExists(fname2) then
deleteFile(fname2);
sysutils.deleteFile(fname2);
if not fileExists(fname2) then
copyFile(fname1, fname2, false);
fileutil.copyFile(fname1, fname2, false);
end;
end;
finally
@ -403,6 +472,7 @@ begin
opts := TCEOptions.create(nil);
try
forceDirectory(getDocPath);
fLibMan.saveToFile(getDocPath + 'libraryManager.txt');
opts.saveToFile(getDocPath + 'options.txt');
finally
opts.Free;
@ -416,18 +486,40 @@ begin
xcfg := TXMLConfigStorage.Create(getDocPath + 'docking.xml',false);
try
// <Item1 Name="CEMainForm" Type="CustomSite" ChildCount="..."> is always missing
DockMaster.SaveLayoutToConfig(xcfg);
xcfg.WriteToDisk;
//DockMaster.SaveLayoutToConfig(xcfg);
//xcfg.WriteToDisk;
finally
xcfg.Free;
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;
begin
SaveSettings;
SaveDocking;
//
KillPlugs;
//
fWidgList.Free;
fProjMru.Free;
fFileMru.Free;
@ -1015,11 +1107,11 @@ begin
runproc.Execute;
repeat ProcessOutputToMsg(runproc, mcEditor) until not runproc.Running;
{$IFDEF MSWINDOWS}
DeleteFile(fname + '.exe');
DeleteFile(fname + '.obj');
sysutils.DeleteFile(fname + '.exe');
sysutils.DeleteFile(fname + '.obj');
{$ELSE}
DeleteFile(fname);
DeleteFile(fname + '.o');
sysutils.DeleteFile(fname);
sysutils.DeleteFile(fname + '.o');
{$ENDIF}
end
else begin
@ -1031,7 +1123,7 @@ begin
dmdproc.Free;
runproc.Free;
if extractFilePath(editor.fileName) = GetTempDir(false) then
DeleteFile(editor.fileName);
sysutils.DeleteFile(editor.fileName);
chDir(olddir);
end;
end;
@ -1051,7 +1143,7 @@ begin
if aProject.Sources.Count = 0 then
begin
fMesgWidg.addCeErr( aProject.fileName + ' has no source files', mcProject);
fMesgWidg.addCeWarn('the project has no source files', mcProject);
exit;
end;
@ -1295,6 +1387,7 @@ begin
fProject.Name := 'CurrentProject';
for widg in WidgetList do widg.projNew(fProject);
fProject.onChange := @projChange;
fProject.libraryManager := fLibMan;
end;
procedure TCEMainForm.saveProj;
@ -1549,6 +1642,40 @@ begin
end;
{$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
RegisterClasses([TCEOptions]);
end.

View File

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

View File

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

View File

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