Delphi and C++ Builder IDE Syntax-Highlighting Extensions Editor
by John Kaster
The Delphi and C++ Builder IDEs for Windows use the Windows registry for a wide variety of
settings that can be configured by the user. Most of these options are configurable in
dialogs inside the IDE. The file extensions to associate with the editor's syntax highlighting
is not one of the dialogs available inside the IDE.
Just the Highlights
This simple utility uses the TRegistry component, a TListBox, and a TAction to provide
a (hopefully) convenient interface for adding file extensions to the IDE editor's
syntax highlighter.
What's your extension?
For the work I do with SQL, I currently use two different file extensions.
I use SQL for straight SQL commands like INSERT, UPDATE,
and DELETE. I use DDL as the file extension for Data Definition
Language, for statements like ALTER TABLE and CREATE PROCEDURE.
This helps me keep my projects organized, particularly when I need to transfer a project from
one machine to another. The additional file extension helps me to create a self-documenting file of
sorts, because the extensions are different. The problem is, the Delphi and C++ Builder IDEs don't
recognize DDL as one of the valid extensions for its SQL-based syntax highlighting, which I greatly
prefer to use if it's available.
If you customize your editor options by using Tools | Editor Options in the IDE,
a new registry key called Editor\Options will be written the appropriate registry section for that
IDE. For example, in Delphi 5, it's:
\Software\Borland\Delphi\5.0\Editor\Options
and in C++ Builder 5, it's:
\Software\Borland\C++Builder\5.0\Editor\Options
When this registry key is written, there are several values listed in the registry that can be
used to configure the IDE's syntax highlighting support. These values are:
| Value | C++ Builder Values | Delphi Values |
| C Syntax Extensions | cpp;c;cc;hpp;h;hh;cxx;hxx | cpp;c;hpp;h;hh;cxx;hxx |
| IDL Syntax Extensions | idl | idl |
| SQL Syntax Extensions | sql | sql |
| Syntax Extensions | pas;dpr;dpk;inc;dfm | pas;dpr;dpk;inc;dfm |
HighEdit
Rather than edit the registry manually, I wanted something that made modifying the extensions a
little safer and more convenient. HighEdit is a simple Delphi utility that reads in the
registry values listed above, and allows you to edit the extension values for each one with a (hopefully)
convenient interface.
Reading the registry values
Since there were multiple values to configure for the syntax extensions, I wanted a convenient format
for preserving the changes. Descendants of the TStrings class all have support for Name/Value pairs, where
the Name/Value pair looks like this:
Name=Value
The TStrings.Names property allows you to retrieve the Name portion of the string by number. The
TStrings.Values property supports retrieving the Value portion of the string by passing in the
Name to it.
The first thing I need to do is open the appropriate registry key to read the current values for syntax highlighting.
I dropped a RadioGroup called rgOptionson the form, and set
its Items property to:
Delphi
C++Builder
Then I created a function called OptionsKey to return the appropriate registry value, depending on
whether the Delphi or C++ Builder radio button was checked. Here's the relevant code:
const
SEditorOptionsKey = '\Software\Borland\%s\5.0\Editor\Options';
...
function TFormSynHigh.OptionsKey: string;
begin
Result := Format( SEditorOptionsKey, [ EditorOption ] );
end;
function TFormSynHigh.EditorOption: string;
begin
Result := rgOptions.Items[ rgOptions.ItemIndex ];
end;
For displaying the display and easy selection of the various values in the registry, I decided to use a
ListBox, called lbExtensions which has an Items property that is
a TStrings descendant, to store and display the registry values the utlity loads and saves.
Here's the code:
procedure TFormSynHigh.LoadExtensions;
var
Exts : TStringList;
Reg : TRegistry;
i : integer;
function Ext( Value : string; Sep : string = ',' ) : string;
const
SExt = 'Syntax Extensions';
var
Spc : string;
begin
if Value = '' then
Spc := ''
else
Spc := ' ';
Result := '"' + Value + Spc + SExt + '"' + Sep;
end;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if not Reg.OpenKey(OptionsKey,False) then
IDENotInstalled;
Exts := TStringList.Create;
try
Exts.CommaText := Ext('C') + Ext('IDL') + Ext( 'SQL' ) + Ext( '', '' );
lbExtensions.Items.Clear;
for i := 0 to Exts.Count - 1 do
lbExtensions.Items.Add( Exts[ i ] + '='
+ Reg.ReadString( Exts[ i ] ) );
lbExtensions.ItemIndex := 0;
lbExtensionsClick(nil);
finally
Exts.Free;
end;
finally
if Assigned( Reg ) then
Reg.CloseKey;
Reg.Free;
end; { Finally }
end;
Notice the embedded function Ext, which is a shorthand function for creating the
appropriate Registry entries. It simply saves some typing, some space in the executable, and abstracts the naming logic for
the registry keys somewhat. The space savings would be more significant if there were more registry keys to set.
If the registry key is not found (the call to Reg.OpenKey fails, then an exception is raised in the application,
stating that the editor properties have not been customized. The following code provides this service:
resourcestring
SDelphiNotInstalled = 'The %s 5 editor properties have not been customized';
...
procedure TFormSynHigh.IDENotInstalled;
begin
Raise Exception.CreateFmt( SDelphiNotInstalled, [ EditorOption ] );
end;
Editing the extensions
After the values are loaded into the ListBox, a TLabel called
lblExtension is used to indicate the name of the label currently being edited,
and a TEdit called eExt is used for editing the extensions.
The label and edit controls get their values set in the ListBox.OnClick event, shown
here:
procedure TFormSynHigh.lbExtensionsClick(Sender: TObject);
begin
lblExtension.Caption := lbExtensions.Items.Names[ lbExtensions.ItemIndex ];
eExt.Text := lbExtensions.Items.Values[ lblExtension.Caption ];
end;
Whatever changes the user makes to the extension value is immediately reflected in the selected
ListBox item by the Edit.OnChange event, as shown here:
procedure TFormSynHigh.eExtChange(Sender: TObject);
begin
lbExtensions.Items[ lbExtensions.ItemIndex ] := lblExtension.Caption + '='
+ eExt.Text;
end;
Saving the changes
Clicking the Save button will write the changes to the registry. This button is
only enabled when the values have been loaded into the ListBox from the registry. The
TAction.OnUpdate event called actSaveUpdateEvent is what enables
or disables the Save button.
The SaveExtensions procedure writes the values from the ListBox to the registry,
then clears the ListBox, which will disable the Save button until the values are loaded
again.
procedure TFormSynHigh.SaveExtensions;
var
Reg : TRegistry;
i : integer;
ExtName : string;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if not Reg.OpenKey(OptionsKey,False) then
IDENotInstalled;
for i := 0 to lbExtensions.Items.Count - 1 do
begin
ExtName := lbExtensions.Items.Names[ i ];
Reg.WriteString( ExtName, lbExtensions.Items.Values[ ExtName ] );
end;
lblExtension.Caption := 'Extension Type';
eExt.Text := '';
lbExtensions.Items.Clear;
finally
if Assigned( Reg ) then
Reg.CloseKey;
Reg.Free;
end; { Finally }
end;
Download and use it
You can download the complete Delphi source code for this project this from
CodeCentral.
If you make improvements to it, let me know by attaching a comment tho this article or to the
CodeCentral submission, and I'll implement the improvements in a future version.
Connect with Us