Category Archives: General

danielk officially co-maintainer of gtkmm

I made danielk officially co-maintainer
of gtkmm. And then people responded by giving
us twice as much stuff to process. But that’s good.

We’ve finished processing Michael’s Forte patches, thanks
to danielk‘s iterator/traits hacking, so
I’ll soon be making a gtkmm release that works
on Sun’s GNOME2/Solaris platform.

I’m using GNOME2 as my desktop now. It was <a
href=”http://lists.gnome.org/archives/garnome-list/2002-April/msg00021.html”>easier
than I expected to set up. Nautilus is now fast enough for
us to start thinking about perfecting it. I’ve been trying
to make the keyboard navigation more Mac-like. I think I’ve
solved the complicated key-modifier conflicts, but while I
can get some things working in the List or Icon views I
can’t get everything working in both.

I made some patches to libglade so that it’s more useful
for C++, so libglademm2 should be useable soon. I’m adding
it to the gnomemm umbrella project.
nzkoz is helping out with that.

Those patches, and some libbonoboui changes for C++ had
to go through the API-change approval process, which is very
slow and inflexible. I then had to chase approval for
patches to the dependent packages. The resultant mess of
multiple pending overlapping patches and conditional
approvals got a little out of
hand and annoyed a few people as I tried to get them finally
checked in.

I figured out a sensible structure for the various
bonobomm parts, and I’ll release new tarballs soon. I think
the examples will be much clearer than the C, particularly
to those who already use CORBA with C++.

gtkmm2 on Solaris

Michael v. Szombathely sent me a wonderfully detailed email with lots of patches to make gtkmm2 build
on Solaris with Sun’s Forte compiler. Assuming that we get
Cedric Gustin’s patches soon, the next release should be
usable on Solaris and Windows, and of course Linux. This is
happening much sooner
than I expected.

Martin Schulze has also been doing lots of work that I
suggested. I just love getting patches.

I’ve been encouraging danielk to manage
some of
these contributions. I expect to officially make him
co-maintainer soon. As long as you have the same vision, I
think all projects should have 2 maintainers.

C++ wrappers for libgda

I started C++ wrappers for libgda (The database API underneath GNOME-DB), and
rodrigo seems eager to help out with it.
But there’s a lot of CORBA BonoboObject-based servers in
there, so it’ll have to go on hold while we figure out how
to auto-generate C++ wrappers for them.

I’m working on that
in bonobomm, and at the moment it looks like we’ll have to
just make our C++ server delegate to the C server through a
client reference. It’ll be simple code, but it might not be
very efficient.

I made some patches to make libbonoboui’s _new()
functions language-binding-friendly, but I’m having a hard
time getting them through the API-change approval process,
even though they are zero impact.

I also started libglademm2, and posted a libglade patch
to make it create full widget instances for gtkmm. I’m
trying to persuade jamesh that it’s a good
idea.

gtkmm and gnomemm are using GNOME‘s bugzilla
now, instead of sourceforge’s trackers. I thought people
would find it too complex but it seems to be a success. I’m
having fun reassigning bugs and marking them as dependent on
each other.

Together with Dennis Cranston, I patched the GNOME logout
dialog to replace the No|Yes buttons with Cancel|Logout.
However,
I’m still in the process of getting my system to use my
GNOME2 from cvs, so I couldn’t test it myself. I hear that
it’s broken now.

Back from GUADEC3.

Back from GUADEC3. I spent a little more time walking around Madrid than planned, as I got caught in gridlock
traffic and missed the flight. I don’t see what the big deal
is about Madrid – it’s big but not that special.

GUADEC was an incremental improvement personally, but it
was a mess overall. While I thank the organisers for what
they did do, I think that they let us down by not doing the
job properly. If GUADEC4 is in Munich next year, as some
have suggested then at least I’ll be able to tell people
what they are doing wrong.

Communication was a real difficulty. The Spanish must be
the only people who make the Brits look good when it
comes to foreign languages. I did eventually
recall some cowboy spanish gleaned from Cormac McCarthy
books, but “Give me my horse” will only go so far towards a
Cafe con leche, and “You killed my brother” won’t get you a
cab to the airport.

It was great to meet a few more people who were
previously just email addresses and irc nicks. It’s nice to
know that so many of the developers are such good people.
However, there were a lot of folk to meet, and the combined
effects of sleep deprivation, starvation, and indoor
windchill had left me a little frazzled. At one point I was
talking to somebody about himself as if he wasn’t there.
That’s fine in a David Lynch movie, but it won’t fly in
reality.

Although we still had the usual politics, it seems to
have become rather dull and passe now, so nobody bothered to
squabble properly. This is a good thing.

The gtkmm talk on Saturday
morning went
reasonably well,
though most people in the audience had never used gtkmm or
C++, and I’m not sure that they all understood my english.
Maybe the Ximian party should be on the last day next time –
apparently it ended at 5am. I’m told that there weren’t many
people in the main hall either. Because of that, and various
organisational difficulties, it was a bit of a shambles. For
those who didn’t make it, the slides and notes are online <a
href=”https://www.murrayc.com/murray/talks/2002/GUADEC3/”>here.
It was worth it to see Owen Taylor raise his hand when I
asked the audience whether they had done any GTK+
programming.

I noticed that we have a lot of young hackers who have
lots of enthusiam, intelligence, and time, but who aren’t
really involved as much as they’d like. We need to
make it easier for these people. Every subproject should
have a list of simple tasks that they can begin to help
with. Experienced developers forget that it’s difficult for
youngsters to know where to start, and difficult to maintain
focus without some coaxing. At the moment they are a vast
untapped resource which shouldn’t be wasted while other
hackers are complaining about having too much work.

I’m experiencing the strange urge to manage development
rather than just design and code. Is this some biological
change that accompanies the greying of the hair? Only my
dislike of C now prevents me from getting bossy on the GNOME
lists.

First libbonobouimm tarball

I posted a first libbonobouimm tarball to the gtkmm and bonbomm lists. I’ll put it in cvs
after everyone agrees on the directory structure. It has a
working example that’s far clearer than the C original. I
was suprised to find that libbonoboui actually implements
GTK-like widgets that don’t have much to do with CORBA
interfaces. But that does at least mean bonobomm
applications can continue to use the same architectures and
memory management techniques currently used for gnomemm
applications, without needing to dynamically allocate
everything via CORBA.

I posted to the Inti list, requesting that
hp just give up and endorse gtkmm
already. We’ll see.

I’ve been slowly porting Glom to GNOME2 now
that Bakery is mostly ported. My pleasure at
removing Gtk::Sheet is slighty lessened by my disappointment
with Gtk::TreeView – it seems there’s no way to get
notification of a particular cell value change, only a
non-specific row change. Luckily I had already wrapped
Gtk::Sheet in an abstraction layer, so hopefully with some
hacking I can reimplement it with Gtk::TreeView.

Tomorrow I fly to Madrid then onto GUADEC in Seville,
staying in the docpi-organised apartment. I expect it to be
quieter than last year, but at least this time I’ll have
more idea of who people are, and I won’t be dragging a leg
cast behind me.

libbonoboui(mm)

I had to spend a few days reverting the ORBit2 cpp branch a bit until it could compile Bonobo.idl again, but now I’m
back on track with my C++ version of the bonoboui_hello
sample.

I am becoming increasingly enraged at the
libbonoboui C API. There is such a confusion between
IDL-generated types and wrapper code, and the wrapper code
totally obscures the separation between client and server
objects. The C++ version is already looking a lot clearer,
and hopefully it will show people just what all their
obscure Bonobo code actually does. And hopefully more people
will then realise that the C wrappers need to be seriously
reorganised. Then people could understand it and use it
instead of just hoping for the best.

It’s now clear that BonoboUI can’t be used just as a
client API – people have to implement their own servers to
dispatch callbacks because CORBA doesn’t seem to have a real
signalling mechanism. And of course every such server has to
implement even tedious methods such as ref() and
queryInterface(), so we probably will need some bonobomm
short-cut code to help people out. I think that’s OK as long
as it’s clearly distinct from the generated stubs/skels. I
see a precedent for this in ATL, MFC, and VB – without one
of these frameworks it’s very hard to use or implement COM
interfaces
using COM alone.

cactus seems to be
making good progress
in his own orbit-cpp-cactus branch, working on more
fundamental aspects of the C++ mapping. I feel like I should
help him more , but I’m better at solving problems when they
are an obstacle.

The trend of other people doing work that I’d rather
avoid continues with Daniel Elstner. In the past week he has
fearlessly solved most of the remaining hard problems in
gtkmm, fixing the signal proxies, the boxed types (a crowd
pleaser), and enums. He should join Advogato so that we can
all rate him as Master.

Another couple of long-term TODO items seem to have been
knocked off the list: <a
href=”http://www.advogato.org/person/kenelson/”>kenelson fixed a
linker problem when building libsigc++ with Sun’s compiler,
as found by sander, so we are
halfway to
gtkmm on Solaris/Forte. And Cedric Gustin
successfully compiled the latest gtkmm2 on Windows.

There are a few faint glimmerings of paying work but it’s
still bleak. It seems like everybody is leaving Munich and
that I’ll have to also.

Writing FileMaker Plug-ins

I put this on my website a long time ago, maybe around 2002, as an HTML page. This is it moved to my blog.

Contents

Introduction

A FileMaker plug-in allows programmers to create new external functions to perform

calculations or other processing. These plug-ins must be written in C or C++. The following explanation assumes that you are using C++. There is very little difference when using C, though your code will be less easy to read.

The plug-in is a dynamically linked library, which integrates with FileMaker by means of some custom functions and data structures. The FileMaker Developer CD contains source code examples and a template which take care of most of the interaction with FileMaker – leaving you to write the external function code.

I would like to include full source code with this text. Unfortunately, large parts of the source code (in particular, the header files which are necessary to build plug-ins) are copyright protected by FileMaker Inc, who have decided that only people who have bought the Developer Edition should be allowed to write plug-ins. If you do not have access to the FileMaker Developer Edition then I suggest you contact one of the many FileMaker consultancy companies who will have it but will probably not have the C/C++ skills necessary to write Plug-ins.

How FileMaker interacts with the plug-in

FileMaker calls the FMExternCallProc() function (or FMExternCarbonCallProc() on the Mac) in the plug-in, passing it a pointer to a FMExternCallStruct data structure. The FMExternCallProc() function examines this struct to choose between one of the following operations:

  • Init: Allows the plug-in to do any special setup which it requires.
  • Idle: Allows the plug-in to make use of idle time.
  • External: Calculates an external function.
  • Shutdown: Allows the plug-in to do any special shutdown which it requires.
  • DoAppPreferences: Allows the user to set any plug-in options.

The Plug-in template project contains appropriately named functions to deal with each of these operations. You can modify these functions, but in most cases you will only need to change the Do_External() function.

The Do_External function is passed a function ID (see External Function Names), a Handle to a parameter, and a Handle to the result. A switch block in the Do_External function calls the appropriate function with the parameter and result Handles.

Handles

A Handle is a pointer to a pointer. The use of a Handle allows the actual data to move in memory as long as the pointer changes. We can still access the data as long as we do a fresh double dereference.

The following functions should be used to manage Handles:

  • FMX_NewHandle(size): Return Handle to new data allocation.
  • FMX_SetHandleSize(h, size):Set size of allocated data at the Handle.
  • FMX_GetHandleSize(h): Returns size of allocated data at the Handle.
  • FMX_DisposeHandle(h): Frees the data at the Handle.
  • FMX_LockHandle(h): Prevents the allocated data from moving in memory.
  • FMX_UnlockHandle(h): Allows the allocated data to move in memory.
  • FMX_MemoryError(): Checks for errors resulting from the use of these functions.

There are other memory management functions listed in FMExtern.h but their use is not demonstrated in the example source files and they are not documented.

Changing the Plug-in template to C++

I advise that you use C++ rather than C. Even if you do not understand the more advanced features of C++, the simpler improvements will make your code much easier to read.

To do so, you will need to change the template project from C to C++. For instance, with Visual C++ 5 simply change the file extensions of .c file to .cpp, and replace these files in the File tab of the project workspace. At this stage you may wish to rename the FMTemplate files to better reflect the name of your plug-in.

Mac

To use C++, you will need to add the following libraries to your Carbon target:

  • MSL_All_Carbon.Shlib
  • MSL_ShLibRuntime_PPC.lib

And you will need to specify the UseDLLPrefix.h prefix file in the
Language Settings / C/C++ Language part of the target’s settings.

And add these libraries to your PPC target:

  • MSL_All_PPC.Shlib
  • MSL_ShLibRuntime_PPC.lib

And you will need to specify the UseCarbonDLLPrefix.h prefix file in the
Language Settings / C/C++ Language part of the target’s settings.

Version String

In the FMTemplate.c (or, for instance, FMAbstractions.cpp) file you will find need to
change the #define statements which tell the plug-in what text to return from the Version
external function.

For instance, in the FMAbstractions.cpp I have used:

#define kVersionLength    24
#define kVersionString    "Abstractions Plug-in 1.1"

Note that you must count the number of characters manually.

The resource file

The example project contains these files, in the “Resources”
folder::

  • FMResource.h: constants used by the resources and the source code.
  • FMExample.r: A Macintosh resource file.
  • FMExample.rc: A Windows resource file.

The resources file must contain the following text resources:

  • 128: Plug-in Name (Note that the Plug-in Name must not begin with F)
  • 129: Description shown in Application Preferences
  • 130: Empty String
  • 131: Feature String (see below)
  • 145: External Function 0 Name
  • 146: External Function 1 Name
  • 147: etc

These resources are already present in the template project. You simply need to change them from their default entries.

Remember to modify the resource files in a text editor rather than your IDE (such as Visual C++’s resource editor), because the IDE may corrupt the file. FileMaker say this is because the resource file is intended to be “cross-platform”, but it’s not clear what they mean by that because they supply separate resource files for Macintosh and Windows. However, the IDE should compile the resource file without problems.

Feature String

The feature string gives FileMaker information about the plug-in and is made up as follows:

  • <4 char creator>: Registered Creator Code
  • <always 1>
  • <app prefs>: ‘Y’ if there are preferences, ‘n’ if not.
  • <externals>:  ‘Y’ if there are any external function, ‘n’ if not. Usually Y of course.
  • <always Y>
  • <idle> : ‘Y’ if you wish the plug-in to get FMXT_Idle messages, ‘n’ if not.
  • <always n>
  • <Win32s>: ‘Y’ if the plug-in only uses the Win32s API subset, ‘n’ if not.

For instance, the Abstractions Plug-in has “MurF1nYYnnY”:

External Function Names

The resources file should contain the names of your external functions, starting at
resource number 144. FileMaker will display these names to the user.When FileMaker calls
an external function it sends the function’s position in this list, starting at 0 for
resource number 144, then 1 for 145, 2 for 146, etc.

The function names should be prefixed with a Function Name Prefix. This prefix must be
4 or 5 characters and must not begin with FM.

For instance, the first 2 function names in the Abstractions Plug-in are:

144 "Abstr-Version"
145 "Abstr-RemoveMultipleReturns"

Adding an External Function

Add the function name

Add the function name to the resource file. e.g. 145  “Abstr-RemoveMultipleReturns” Add a case statement to the switch block in the Do_External() function so that it catches requests for the new function. e.g

/* Second function (RemoveMultipleReturns) */
case 1:
  RemoveMultipleReturns(parameter, result);
  break;

Add the function body

Enter the body of the function as static and void, in the FMTemplate.c (or, for example, FMAbstractions.cpp) file. e.g.

static void RemoveMultipleReturns(FHandle parameter, FHandle result) {

}

If you enter the body before the Do_External() function then you will not need to add a declaration prototype.

Get parameter size

Use FMX_GetHandleSize(parameter) to get the number of characters in the parameter. If
this equals 0 then there is no need to continue. e.g.

long lInSize = FMX_GetHandleSize(parameter);
if (lInSize > 0) {
  ...
}

Lock the parameter Handle

You should lock the parameter Handle to prevent the data moving during the lifetime of your function. e.g.

FMX_LockHandle(parameter);

Alternatively you could double-dereference this Handle every time you look at any piece of its data, but that would be tedious and inefficient.

Be sure to call FMX_UnlockHandle(parameter) at the end of the function.

Dereference the parameter Handle

You must use the * operator to dereference the Handle to get a pointer to the parameter
data. e.g.

unsigned char* pucIn = *parameter;

Note that I have used a puc prefix to remind myself that I am dealing with a pointer to an unsigned character.

Examine the parameter data

You may examine the data using array notation. e.g.

unsigned char ucTest = pucIn[4];

Or you could use the * operator to dereference:

unsigned char ucTest = *(pucIn + 4);

These two statements are equivalent.

You will probably use a loop to examine each character in turn. Make sure you do not go past the end of the parameter text. Remember that the data is not null-terminated, so many utility functions will not work.

Note that all parameter data is sent in text form, so you may need to convert text to a number. Be very careful when dealing with dates because the user must use the DateToText() function whose behaviour is not constant across different locales and which currently is not year-2000 compliant.

Set the result data

As soon as you know how many characters will be in the result data, you can use FMX_SetHandleSize() to allocate space for the result data.You should then check that the
call succeeded. e.g.

FMX_SetHandleSize(result, lOutLength);
if (FMX_MemoryError() == 0) {
  * pucOut = *result;
  ...

You should not dereference the result Handle to a pointer until just before you use it,
because the data may move between the time you get the pointer and the time you use it.
Alternatively you could use FMX_LockHandle().

You might set the result data as you examine the parameter data. e.g.

pucOut[x] = pucIn[y];

However you are more likely to copy the data into the result from an intermediate location. e.g.

lstrcpy((LPSTR)*result, (const char*)pucTemp);

You should have an appropriate #ifdef block for Mac code because the Mac deals with strings differently.

Be sure to delete (or free) any data which you have previously allocated dynamically using new (or malloc), to prevent memory leaks.

Accepting multiple parameters

Unfortunately a FileMaker external function can only be sent one text parameter. In order to receive more than one piece of data you must demand that the user separates the data with a special character.

It is becoming commonplace to use the ‘|’ (pipe) character as the dividing character with external functions. For instance, with the Abstractions Plug-in, a user would enter:

External(Abstr-KeyTriggeredBy, KeyField & "|" & TriggerField).

Of course this significantly complicates your external function because you must separate the parameters within your code.

Registering your plug-in

You must register your 4 character Creator Name with Apple at http://developer.apple.com/dev/cftype/ even if you are not creating a Mac plug-in.

You must then register your plug-in details at www.filemaker.com. They will then send you a registration code. You must email FileMaker Inc a copy of your plug-in, quoting the registration code.

Debugging with Visual C++

To step through your code with the Visual C++ debugger you must build your plugin, place a copy in the FileMaker System folder, then edit the Debug tab of the Project Settings. Choose ‘Additional DLLs’ from the Category drop-down, click on a new line under Local Name, then click the ‘…’ button to browse for the plugin in the FileMaker system folder.

Of course, be sure to choose Debug in Choose Active Configuration under the Build menu.

Developing on MacOS

CodeWarrior only

Although Apple provides development tools with MacOS X, including Project Builder, these can only be used to build Mach-O format executables, which run only under MacOS X. But at the moment FileMaker is not fully MacOS X native so it’s in the old PEF format (also known as CFM) and requires PEF format plug-ins. It seems that only CodeWarrior can build PEF executables on MacOS X, so you must buy it to develop plug-ins for FileMaker on MacOS X. In the future, FileMaker might change to Mach-O format.

CodeWarrior is also the best choice for C/C++ development on previous versions of MacOS, and there is a version which runs on both Mac and Windows platforms, making it easier to build cross-platform plug-ins.

MacOS X Target

You’ll need to use the “Carbon” target on Mac OS X, or the FAT target, which includes that target. See the next section, about MacOS Classic.

MacOS Classic Target

For “Classic” MacOS 8 or 9, you need to use the “FAT” target, which includes the PPC target. FAT was used in the past to contain both 68k and PowerPC executables, but in this case both executables seem to be the same apart from some “Version Info” settings in the Linker/PPC PEF part of the target’s settings.

You will need to remove the 68k target from the FAT target, because recent versions of CodeWarrior (for instance, 8 and 9) can not build 68k executables.

Note that FileMaker does not seem to be Carbonised on MacOS Classic, so you will not be able to link to CarbonLib (use InterfaceLib, AppearanceLib, UrlAccessLib, etc instead) or use any of the Carbon-only functions such as CEPreferencesSetAppValue(). Yes, this is very annoying.

Updating the CodeWarrior 6 example to CodeWarrior 8

In Edit| <target> Settings:
  • In Target/Access Paths/System Paths: Add (Compiler)MSL to avoid the “extras.h not found” error.
  • In Target/PPC Target: Change the Type to FMXT.
Re-add the resource file

Select the Project|Add Files menu item, then choose the FMExample.r file. It should now appear in the “Link Order” project tab.

Further Reading

ORBit2 cpp branch

After a lot of gratuitous hacking, the ORBit2 cpp branch can now support a simple helloworld client/server
example. I’m very pleased about that. I’ve been dismayed at
the lack of help from more expert CORBA C++ coders, but I
guess it’s
like gtkmm – people only get involved after
it’s obvious that the project is viable. And people are
really getting involved in gtkmm.

Now that ORBit2 cpp is on track, I’ll get started next on
the Bonobo interfaces. My “GNOME2 with C++” talk has been
scheduled for day 1 of
GUADEC 3, with an extra
hour that I might be able to use for Bonobomm if it’s ready.

I also solved a major problem with
gtkmm‘s signal wrappers. Our signals now
definitely, absolutely, use C++ types, so there’s now almost
no need whatsoever to access the underlying C objects.

I wrapped the Drag and Drop parts of GTK+, and that
has turned out to be a good example of how
gtkmm is able to make seemingly obscure and
fragmented interfaces more obvious. I added a chapter about
it to our “Programming with gtkmm2” book, part of our whole
gtkmm2
documentation
.

Daniel has added a wonderfully simple wrapper mechanism
for GError which maps them to C++ exceptions, making gtkmm
seem even more like the perfect modern C++ GUI toolkit. He’s
also been wrapping the glib text conversions and
cross-platform threading APIs. We’re thinking that glibmm
might be useful outside of gtkmm.

That’s a few major things removed from TODO list. Thing
are looking good.

Xerces-c++ sane includes

Incredibly, after about 6 months of hassling, my Xerces-C++ sane_includes patch has finally been applied.
One small step of many on the way to proper
packaging. I’m not a fan of the Apache-style
project
management scheme. There’s no real maintainers, so it’s like
a crowd of people standing around a victim, everybody
wondering when somebody else will do something. And in
practice Xercesc-C++ is actually governed by a few assigned
IBM employees, who didn’t get their positions based on
community activity. I’ve brought the weak leadership issue
up on the list before, but it doesn’t seem like it can be
fixed within the current system.

Tyler, who was on the dive boat in the Similan Islands
took some excellent underwater <a
href=”http://www.arrell.ca/pics/oz/sim1.html”>pictures.
I prefer these to the false-light scuba pictures that
you normally see. And here’s <a
href=”http://www.arrell.ca/pics/oz/set6/DSC00080.JPG”>me
hanging around during a safety stop. I think <a
href=”http://www.arrell.ca/pics/oz/set6/dsc00022.jpg”>this
is me too.

Back from Thailand

I’m back from Thailand, which I didn’t enjoy that
much. It’s very hard to break away from the normal tourist
trail due to the massive communication difficulties.
However, I did spend 4 days on a dive boat in the Similan
islands, and that was special.

While I was away, cactus ported
gconfmm to GNOME2 so we can add it to
gnomemm, and Paulo Pinto put a nice face
on gtkmm by creating this overview
page.

Now back to my TODO list: Fix the ORBit2 cpp branch,
Finish the gtkmm tutorial, and Merge the GTK+ C docs into
the gtkmm docs.