Tuesday, December 29, 2009

The latest bright idea

Today I was leafing through Alan Cooper's "About Face - the essentials of user interface design". I bought this book years ago - the cover bears the proud sticker "Covers Windows 95" - and I try to read it every few years. I see that the book is now in its third edition, but the ideas presented in the original edition are just as valid now as they were 14 years ago.

Cooper pours much criticism on the overuse of modal dialog boxes, especially those which report on some error. What really annoys him is when a dialog box pops up to inform the user, and the user has to press OK! Here is the paragraph (page 131 in my edition, from chapter 11) which caught my imagination today:

When the program has information or feedback for the user, it has several ways to present it. The most common method is to pop up a dialog box on the screen. This technique is modal: it puts the program into a mode that must be dealt with before it can return to its normal state, and before the user can continue with his task. A better way to inform the user is with modeless feedback.

In the management program which I have just completed (for the time being), there are several dialog boxes which the user fills in. This is a justifiable use of the modal dialog box. When the user presses the 'ok' button, telling the dialog that the data can be entered into the database, a few checks are made, ensuring that key fields have values in them (for instance, a field holding a therapist's name should not be left blank). The check itself is very easy, but should the field be empty, a modal dialog box pops up, telling the user that the field is indeed empty. This is exactly what Cooper was writing about.

How can the program provide modeless feedback? The solution is actually very simple: add a statusbar to the dialog; the statusbar will normally not contain any text and its colour will be neutral.  When the 'ok' button is pressed and an empty text field is found, the error message is displayed on the statusbar, whose colour has now been changed to red. At the same time, the focus returns to the empty edit box. As soon as the user presses a key while the focus in on the edit box, the statusbar reverts to its original state. This solution requires a variable declared global to the form, which I've called 'errflag'; initially its value is false. Here is the specific code:

procedure TEditTherapist.OKBtnClick(Sender: TObject);
 if dbedit1.Text = '' then
   with sb do
     simpletext:= 'You must enter a value for this field';
     color:= clRed;
     errflag:= true;
   modalresult:= 0;

procedure TEditTherapist.DBEdit1KeyPress(Sender: TObject; var Key: Char);
 if errflag then
  with sb do
    simpletext:= '';
    color:= clSkyBlue;
    errflag:= false

Monday, December 28, 2009

What is the connection between King Crimson and Organisational Behaviour

The other night, we learnt about the Expectancy Theory of Vroom. Maybe Robert Fripp and his merry men were thinking of this when they released the "Vroom"  mini cd?

A new Word automation technique

Often in my Word automation code, I need to create a table in which to display data. To the best of my knowledge until now, there have been two ways to create and populate a table; in the first method, one declares a table (wrdTable:= WrdDoc.Tables.Add (wrdapp.selection.Range, 10, 5, 1, 2)), which is then populated by accessing specific cells in the table. The other method is to create a huge string in which the cells are separated by a specific character (for example, ^); after the huge string is created, the ConvertToTable method is called which converts the long string into a table.

Both methods have their problems: the first requires that the number of rows be known before the table is declared, whereas the second does not always work (maybe one day I should investigate this further, although I should point out that one time the code worked perfectly on my computer, but not on my client's computer, despite the fact that we have the same operating system and same version of Word).

Today I had to write Word code to populate a table, not knowing in advance how many rows would be in the table. Which horn of the dilemma should I choose? At first, I tried the ConvertToTable method, and as usual, it didn't work. So I used the first method. In the past, I have used a query inside the Delphi program to calculate how many rows would be returned from the real query, but this doesn't seem to be the optimal approach. Remembering that if one creates a table in Word, one can always add rows to it using the 'Add row' command. So I ran a quick macro check in Word, and discovered that there is a 'InsertRowsBelow' method belonging to the current selection.

So my code became (in pseudocode):
create a table of size one row and how ever many columns
insert the row headers into the first row
for every tuple returned from my query,
 add a row to the word table
 insert into this row the various fields of the tuple
until there are no more tuples
Voila! A perfectly sized table. Here is the Delphi code to do the above:      
         wrdTable:= WrdDoc.Tables.Add (wrdapp.selection.Range, 1, 5, 1, 2);
         wrdSel.paragraphformat.alignment:= wdAlignParagraphRight;
         wrdTable.cell (1, 1).range.text:= 'column 1';
         wrdTable.cell (1, 2).range.text:= '
column 2';
         wrdTable.cell (1, 3).range.text:= '
column 3';
         wrdTable.cell (1, 4).range.text:= '
column 4';
         wrdTable.cell (1, 5).range.text:= '
column 5
         row:= 1;
         while not eof do
           inc (row);
           wrdSel.InsertRowsBelow (1);  // add new row
           wrdTable.cell (row, 1).range.text:= qYomanTaarich.asstring;
           wrdTable.cell (row, 2).range.text:= qYomanForename.asstring;
           wrdTable.cell (row, 3).range.text:= qYomanSurname.asstring;
           wrdTable.cell (row, 4).range.text:= qYomanName.asstring;
           wrdTable.cell (row, 5).range.text:= qYomanTherPrice.AsString;

         wrdTable.borders.insidelinestyle:= true;
         wrdTable.borders.outsidelinestyle:= true;
         wrdTable.AutoFitBehavior (wdAutoFitContent);
         wrdTable.cell (row, 1).select;
         wrdSel.MoveDown (wdLine, 3); // Get out of the table
I suppose that the next step is to go over all my 'legacy' code and update those tables in which I don't know in advance how many rows there will be. This type of coding could be referred to as 'overhead' or 'excise', and a case could be made that my client should not have to pay for this. Fortunately, I think that there only two or three cases, so it shouldn't take very long to correct them. I often discover a new technique and then retrofit it into existing programs. It makes my maintenance easier, and generally improves the programs' performance.

Sunday, December 27, 2009

Dollhouse 2

Despite writing previously that I wouldn't watch the program again, I was drawn to it like a moth to a light. True, the first few episodes weren't very good, but around the fifth episode things started to get better, and indeed there has been a continual improvement ever since (except for the current episode, the 10th, which was a return to the opening episodes).

Most television programmes could be described as moderately good ideas executed well; occasionally there is the really good idea executed well, in which case the result is excellent. Unfortunately, "Dollhouse" seems to be a good idea executed poorly.

I think that the programme can't decide what it's supposed to be. Is it a run of the mill adventure series centered on "programmed people" ("actives")? Is it a thriller about an FBI agent trying to find the Dollhouse? Is it a philosophical programme about the morality of "programming" people, taking away their identity and establishing new albeit temporary ones?

When the programme is an adventure series, then it is dull and uninteresting. When it's a thriller, it's more interesting (especially when the agent's girlfriend suddenly turned out to be an active herself, a possibility which occurred to me long before it occurred to the FBI agent, and just before it was shown to be true), but it's at its best when it's working on the philosophical level. Unfortunately the proportions of screen time seem to be about 60%, 30% and 10% (an unscientific observation, more of a guess).

Only three more episodes until the end of the series ... I wonder whether there will be any form of resolution. Apparently there is a second series, after which the show was cancelled.

Saturday, December 26, 2009

Neat tricks in the 'management' program

I wrote about two weeks ago about a management program which I am developing for my weekend job. This program incorporates many techniques which I've never used before, and I want to talk about two of them here. The use of the ttabcontrol is such a first, as was the use of the tdbnavigator, although that has now been retired and has been replaced with a tdbgrid.The navigator control was causing more problems in terms of ease of use than it was solving, and doing away with it enabled me to remove three dialogs from the program, making it simpler and smaller.

The first technique which I want to share here is the solution to a problem which has plagued me since I started working with the dbExpress components and the Firebird database. In order to develop the program, the data module contains an TSQLConnection component which holds data regarding the location of the database. This component has to be left open during development time, but I aways had to remember to remove the database location from the component before installing the program on my client's computer. I found the other day a better discussion of the problem, and the article cited also purports to give a solution.

I have learnt a great deal about Delphi programming from Zarko Gajic's 'About Delphi' site, but I have to say that in this case, he is wrong - or at least, his solution does not work. There was enough information given which enabled me to find a working solution, which is what I present here.

The source problem is that the sqlconnection gets opened almost immediately on program invocation, even before code in the project file (dpr) executes. Thus any attempt at correcting or changing the connections' properties post facto are doomed to failure. What Gajic gets right is that the sqlconnection component's "BeforeConnect" event has to be hooked into. This is code which - as its name suggests - gets called before the connection to the database is opened. Gajic's solution involves creating a new constructor and various boolean fields, but seems to be lacking a line or two, without which the component does not know that it has to change its properties. A much simper solution follows, which does not involve private constructors nor any fol-de-rol. One simply has to write an event handler for the 'BeforeConnect' event as shown below:
procedure TDM.SQLConnection1BeforeConnect(Sender: TObject);
 dir: string;

 with TRegIniFile.create (regpath) do
   dir:= ReadString ('firebird', progname, '');

 with sqlconnection1 do
   params.values['database']:= dir;
   loginprompt:= false;
I keep the database locations in an .INI file; this is what is being retrieved in the first half of the code (with TRegIniFile.create ...). The second half (with sqlconnection1 do ...) is where the action happens; the first statement closes the connection, which presumably was left open at design time. The second statement inserts the new location of the database, and the third statement is optional - sometimes I forget to set the loginprompt property. This simple code solves the problem! After this event fires, Delphi will open the connection, and as now the database location is correct, the database will open correctly. 

I hate to think how much time I have wasted because of this problem. Several times I have installed my firebird programs with the sqlconnection open and pointing to the wrong location, causing embarrassment and lost time when I have tried to demonstrate the programs. This is one technique which will soon be migrating to other programs!

The second technique is to do with non-modal dialogs. Until now, I have never used such dialogs, preferring instead to use their modal siblings. Whilst I was aware that maybe the modal dialog is not the correct solution to every problem, it seemed much easier (from a user's point of view). The management program is the first program that I have written that uses non-modal dialogs seriously. There are several tables containing data which could be classed as 'secondary' - customers, therapists, types of activity and so on. These tables are accessed rarely after the data have been defined, but they still have to be accessible. I chose to define a non-modal dialog which allows data entry for all of these tables; one (non-modal) dialog displays all the names of the various records for all the tables, and then specific (modal) dialogs allow editing of all the chosen record's fields. 

I was asked how one could display two such dialogs at the same time. No problem, I replied, as I swiftly displayed one dialog, clicked on the main dialog, then displayed a second dialog. But wait a minute: where had the first dialog gone? I knew that I hadn't closed it, but I couldn't see it anywhere. It turns out that it had "hidden itself" behind the main dialog and thus to all intents and purposes had disappeared. After thinking about it, I realised that I had to write an event handler for an 'OnDeactivate' event (if such an event existing), minimising the dialog. I assumed that if there were an 'OnActivate' event (one which used to be ubiquitous with me, but now I don't use it, preferring 'OnShow' instead as this gets called only once in a program's lifetime), then there should be an 'OnDeactivate' event. Indeed there is, and the implementation is simple. 

procedure TDoTables.FormDeactivate(Sender: TObject);
 showwindow (handle, sw_minimize)

Although I promised only to write about two techniques, here is a third which I have started to use. Frequently, my programs' main dialog would be defined as a modal dialog box; such a form cannot be resized which is what I wanted. Unfortunately, this also meant that such dialogs cannot be minimised; I developed a technique of defining the F1 key as a 'minimise key', trapping this keypress and minimising the dialog. A much better solution is to define the form's borderstyle as 'bsSingle' and to set the bordericons property as [biSystemMenu, biMinimize]. 

I know that these are techniques which I should have absorbed ten years ago, but at the time there was so much material to assimilate that these little points got missed. Programs got written, they worked and they even solved problems, so what is basic Windows behaviour was ignored. Better late than never.....

Friday, December 25, 2009

Tim Hart, RIP

Christmas Day in the workhouse.

I heard today about the death of Tim Hart, who played guitar and sang in most of the lineups of Steeleye Span. Tim died at the age of 61 after a long battle with cancer. No doubt there are other tributes about him scattered elsewhere around the Web , but this is going to be a more personal memoir.

As one recalls, Steeleye was the band formed by Ashley Hutchings after he left Fairport Convention at the the end of 1969. A first lineup, including Tim Hart, made the 'Hark the village wait!' record, but this lineup split before the record was released. A second lineup, which added Martin Carthy and Peter Knight, was more long-lived, and it was this group that I saw in Bristol's Assembly Rooms in early 1971. All that I remember about this is Hutchings' blue Fender Mustang bass and Carthy playing a Telecaster. 

I knew quite well the two records released by this lineup, "Please to see the King" and "Ten man mop", although I never purchased them (a mistake rectified 35 years later when I bought a two cd compilation of their first three albums titled "The Early Years"). There was something about their sound which both attracted and repelled me. I used to call it "severe", but by chance I heard this morning a similar sounding adjective which seems more suitable - "austere". Maybe it was the lack of drums, maybe the lack of a distinguished instrumentalist (pace Richard Thompson), maybe it was a surmised lack of humour or fun. It wasn't too clear what Hart's instrumental function was, apart from the occasional turn on the electric dulcimer (the chilling "When I was on horseback").

My second meeting with the band was at the Lacock Festival, held in a small village "the other side" of Bath in May 1972. I went with my school friend Jonathan along with someone else whose name I can't recall (actually, I don't remember who the third person was at all, let alone his name). Maybe my mother or maybe one of Jonathan's parents took us to the village on the Friday afternoon, and I remember that we returned by bus. Steeleye were 'topping the bill', but arrived early at the village and hung out for a day before their show - it was an informal festival. There were singing and dancing workshops - I remember appearing at one of the open mic shows with my ratty acoustic guitar and spotting to my mortification Maddy Prior (lead singer with Steeleye) sitting in the front row. 

At some stage Jonathan and I approached the group and informed them that we had appointed ourselves as their official groupies (lackeys would be a better term) for the duration of the festival. I don't recall now what this function consisted of besides buying them the occasional drink. We were too cool to take mutual photographs or even ask for autographs, so all that is left is my failing memory. By this time, Bob Johnson and Rick Kemp had replaced Martin Carthy and Ashley Hutchings, and Johnson certainly brought a more fun approach to the group's music. 

This was when I first learnt how to Morris dance. At the time, I was fairly well versed (so I thought) in Israeli folk dancing, and had become aware of the fact that there was a vocabulary of dance moves; later on, dancing became a test of memory in which one had to recall the specific sequence of moves (I call them 'phonemes' for the moment, in imitation of spoken language) instead of letting the body react automatically. Anyway, I was sufficiently aware of the possibility of assigning a 'grammar' to the dance that I was able to distinguish the 'phonemes' of the Morris dance and catch on quite quickly. Let us not forget that this was maybe six or seven months after Ashley Hutchings' (again!) groundbreaking "Morris On" record, which taught polite public schoolboys like myself that there was a whole branch of English music out there of which we had never heard.

At the time I considered myself to be a folkie, what with the occasional visit to the Bristol Troubadour (mentioned elsewhere on this blog) and my connections to the Village Thing label. I vowed to find a Morris Dancing team in Bristol on my return; I did in fact find out where they met but never went. I did buy a concertina, though, and even learnt after a fashion how to play it, although tunes escaped me.

I saw Steeleye for the third and final time in 1973 at the Colston Hall; I have somewhere a cassette tape of this performance. This was the time between "Below the Salt" and "Parcel of rogues"; the music was much less austere than it was before - but still I didn't buy the records. 

When I came back to Britain in 1974 and went to live in London as a student, I bought Steeleye's "Now we are six" album as a raffle prize for an unsuccessful folk club which I was helping to run. I listened to it, probably taped it, and forgot about it. Maybe my tastes had changed (I certainly didn't consider myself an English folkie after spending a year in Israel!); whatever the reasons, Steeleye and I parted company.

It's interesting to note how much the repertoire of the early Steeleye stayed with me, and for that I have to thank Tim, Maddy, Ashley, Martin and Peter. When I came to record my 'Folktronics' disc a few years ago, I was surprised how many Steeleye tunes came to mind, even though at the time I hadn't heard the records for years (I should point out that all the tunes were traditional; I should have written "how many traditional tunes that Steeleye had brought to my attention").

Saturday, December 12, 2009

Displaying tabs on the right of a TTabControl

I started a new MBA course in 'Organisational Behaviour' yesterday; I should be more excited than I am about it at the moment. I hope that I will become more enthusiastic about it as time passes.

At the moment I'm more excited about a program which I am writing for my occupational psychologist. This program is supposed to be one which manages all non-primary information about the examinees: who everybody is, where they come from, which tests they did, who interviewed them, etc. One of the outputs of the program will be a calculation for each psychologist how many clients they interviewed during the month, and what their fee should be. The program is very much open ended at the moment, so I've configned myself to doing basic design, including a few input screens.

The program's main data structure/table is the docket, to which are connected people, to which are connected treatments (exams), to which are connected pyschologists. I made a nice ERD before I started coding, and so far I've completed everything in that design. But there'll be a lot more to come.

I went through several options before I came upon what is at the moment the final design for the main screen. Instead of displaying a dbgrid with docket numbers and dates, and possibly the names of the people connected to those dockets (utilising a left join, because there can be a docket with no people connected), I decided to take a different approach, utilising a component which I have never used before, the dbNavigator. This component allows one to page back and forth between different dockets, and I've connected a few dbText controls to display the data in the current docket tuple (a docket is never entered manually, as it only has two fields: number and date, both of which are inserted automatically).

For each docket there is a wealth of information to be displayed, although at the moment I only have two screens' worth: the people connected to the docket and the exams that those people did. After considering various options, I decided to use (for the first time) the TTabControl. There is a similar TPageControl, which allows different pages containing different controls; I tried this briefly, but didn't like it. As the the container control will hold a grid and a few buttons, it makes more sense to use the TTabControl (which uses the same child controls for all the 'pages', forcing the programmer to switch the data) as opposed to the TPageControl.

Here is a screen shot of the TTabControl in its naked form:

The TTabControl has two tabs, 'One' and 'Two', along with a grid. This would be ok if the program were working outside of Israel, but we need right to left controls. Although the TTabControl does have a BiDiMode (bidirectional) property, this controls how text appears and not the layout of the tabs. Obviously the solution is draw the tabs on the right hand side of the top of the TTabControl. Easier said than done.

I found a magic invocation which I have used before to get controls to draw themselves from right to left. Here is the result of using a little magic

Whilst the tabs are now drawn as I wanted, on the right, the grid seems to have disappeared. Thus the 'magic option' has very limited uses in the real world (such as none).

There is a property called TabAlign, which can display the tabs on the top (as I originally did), at the bottom, on the left or on the right. Is this the answer? Not really.

But we're nearly there.... All I need to do is to have the tabs draw their text horizontally, and then at least I will have a reasonable solution to what I want. The way to do this is to mark the TTabControl as owner drawn and to handle the tab drawing code by myself.

The sharp of sight will notice two things: the grid is now displayed right to left (by setting its BiDiMode property), and more importantly, the text of the tabs is wider than the tab. So the tab width has to be set manually? Not quite. If one remembers that the tabs have effectively been rotated by 90 degrees, then increasing their width effectively increases their height (at least, as how we see it). So to get the effect that I want, I have to increase their height, which will increase the onscreen width (who said that programming was easy?).

If I'm already owner drawing the tabs, why not add colour to the selected tab? Here is a screen shot of the final dialog, complete with a little data.

In case it isn't clear, there are two tabs on the right of the TTabControl: the selected tab has red text on a light blue background, whereas the tab below it has blue text on the common green background.

I have to say that I much prefer to concentrate on a program's logic, to get it to do what it's supposed to do with the minimum of effort from the user, instead of focusing on what seems to be arcane minutiae of the user interface. But sometimes there's no escaping this, especially if one works in a right to left environment. Looking back, I'm quite pleased with what I accomplished, even if it isn't exactly what I originally wanted. I hope that the client will also be pleased.....

Wednesday, December 09, 2009

After the accounting exam

Well, my accountancy exam has been and gone. It was much easier than I expected, for which I am truly grateful. The exam consisted of two sections: one part multiple choice, and one part containing two scenarios which have to be dealt with in depth. The 30 multiple choice questions covered most of the syllabus, and some were harder than I expected, but none of them were really hard. Theoretically, an hour and a half should be devoted to this section; I finished after an hour, and that included checking the answers.

The two in depth questions were much easier than I expected - or putting it another way, they were in areas which I know very well. I had been expecting a question about cash flow statements, which is a subject which I haven't grasped very well and so I have devoted a fair amount of time over the past week to solving questions in this area. My hopes were dashed - darn! - when it turned out that the first questions was simple accounting: create a balance sheet from opening balances and a series of transactions, some of which were given and some had to be deduced. Once the transactions had been recorded, one had to make a profit and loss account from them, as well as a trial balance. Solid work, but straightforward. After that, one had to comment on the financial state of the balance sheet - not very good; the company's current liabilities outweigh their assets.

The second question was even easier, if that's possible: a group of people want to put on a theatrical show which runs for a week. The theatre costs so much, the programmes cost, the theatre staff cost, etc. If the theatre seats 800 people and they expect 50% capacity on two days, 60% on another two days and 100% for the remaining performances, what is their financial status if a ticket costs 12 pounds? If a ticket costs 16 pounds? How many tickets do they need to sell to break even? I solved a very similar question to this a few months ago and the memory stayed in my mind; as it happened, one of the practice questions which I solved yesterday was a simpler version of this question (a group of students want to hold an end of term party).

Unfortunately, I won't get the results for another two months, but I am very optimistic about my chances. Actually, there are only passes and fails; a pass is 50%, and theoretically there is no difference between a pass at 51% and a pass at 90%. Maybe a future employer will want to look at the actual marks attained, but in my case, that would seem to be purely theoretical. Still, one wants to do as well as possible.

I remarked the other day about the 'fight' between the amygdalae and the cortex in the brain. Their fight was very pronounced today, with the amygdalae saying "check, check the answers", and the cortex saying that I've checked and that it's ok.

I forgot to try out a learning technique which I had read about. One of the few things which I had to memorise was the five advantages and five disadvantages of maintaining a budget, as I was convinced that there would be an in-depth question about budgets, and knowing the above ten words would give me ten marks. The technique states to place a little perfume on the back of one's hand when learning the material, and to place the same perfume on the hand when sitting the exam. It is well known that smells are a key to memories (the smell of eucalyptus trees in the damp always brings to mind Army basic training), so this perfume smell is supposed to unlock the memory of the learnt material. As I say, I forgot to try the technique, and anyway we only had a few multiple choice questions about budgets, which was really variance analysis.

Sunday, December 06, 2009

Accounting exam

The first semester of my MBA course is drawing to a close and the concluding exam is on Wednesday morning. I have been a witness for the past week to an ongoing battle between different parts of my brain: the mid-brain (probably the amygdala) keeps on saying that there is an important exam in a few days and one has to revise, revise, revise, whereas the top brain (the cortex) is calming the amygdalae down, saying that yes, there is an exam, but this is accountancy after all, a subject which I have been practising for years, and judging by my performance on the test exams, I'm going to get 75% without even trying very hard.

In the previous week (not the one just finished but the one before that), we had a guest lecturer from the home university come and give us three lessons. This is apparently a rare occurrence, which happens once every three-four years, so my fellow students and I should consider ourselves lucky. For reasons unknown to me (although I can guess), only about a third of the class attended these lectures. I think that this is a shame, because the lecturer went over test exams, taking a more tactical approach to that taken by our normal lecturer, and I found  this approach complimentary to what we had already learnt. In other words, those lectures will help me get a higher mark. The lecturer is the man who actually writes the exam questions so of course he has insight on how to solve them. He was careful not to give away which subjects will appear in the exam paper, claiming that he writes the questions two years in advance (as they have to be checked and translated) and so does not remember what will be in any specific exam. I think that there was a certain amount of truth in his statement, but felt that he probably did know what was in the paper.

I am going to take the middle course: devote an hour or two each evening to the areas in which I don't feel confident and which haven't been examined in the past four courses (the lecturer left us a list of which subjects have appeared in which exams). In my opinion, most of the areas are straight forward, and one only needs common sense aligned with mathematical sense to answer the questions. Of course, 'mathematical sense' is not shared equally between all students; for me, accountancy is easy because it aligns with my skills. It is considered one of the 'harder' subjects in the MBA constellation, both in the sense of 'hard' (as opposed to 'soft') and 'hard' (as opposed to 'easy'). Next semester I am taking the course in organisational behaviour, which is supposed to be both soft and easy. I suspect that the exam will be harder for me than the accountancy exam.

'Next semester' starts this Friday; the winter semester is short and compact. Our timetable reads as follows: Friday 4 Dec – last accountancy lecture; Wednesday 9 Dec – accountancy exam; Friday 11 Dec – first lecture in winter semester; Sunday 13 Dec – second lecture in winter semester.

Thursday, December 03, 2009

Swedish Fly Girls

Sorry about disappearing for what seems to have been all of November. I had two very busy weeks which didn't leave me any time for blogging (work and MBA), and anyway the system administrator at work has removed access to all blogspot sites, meaning that I couldn't read many of my favourite blogs at work, let alone add to my own. Although the pressure eased up this week, I managed to catch a bad cold, so I wasn't able to focus much. But now I'm back.

One of the rarer items in the Sandy Denny discography is the handful of songs which she sang for a forgotten film from 1970 called 'Swedish fly girls'. This was shown on tv last night and I had the presence of mind to record it ... only I needn't have bothered. The film has not aged well, and probably wouldn't have been well thought of even when it was released. Then it would have been considered somewhat risque, as the eponymous air stewardess (only one, and she's Danish) spent about a third of the film naked. But let's say that the nudity was non-sexual; this certainly wasn't a precursor to 'Emmanuelle'.

Sandy sings maybe ten lines in the film, although apparently the soundtrack featured four songs with her singing. Digging through the old letters from the Sandy mailing list, I found this gem from Moses Henry (grammar slightly corrected by me):

I was in London for 12 weeks the spring and summer of 1970. Manfred Mann and I co-produced the music for "Christa". The rhythm section was the band who did the London Production of 'Hair" and we used London Philharmonic strings and brass. At times a 30 piece rock orchestra for the film. I wrote all of the music, Dereck Wadsworth arranged it [and] Manfred [was the] # 1 Producer. I was associate producer without credits. I sang "I Need You" with Sandy. Sandy was ill and after she saw the lead sheets of the music she came to the studio to record it anyway, She told me 'What Will I Do With Tomorrow' was the most beautiful song she had ever heard. In my book she sang it like an angel. When she sang the final take for that recording the entire studio was lifted to another place and time words cannot describe. The recording said it well enough.

I also sang lead vocals on 'Make it to the Land that I Know', 'She is Free', and 'Love is All I Need'.

The film opened in New York in Three Theaters; I got to go to one in a Limo and I asked the owner of a theater [in] uptown New York why he had booked the film. He (not knowing I had written and sung the music) said the music touched his heart. The film titled 'Christa' did
not make enough money as that title so it was re-titled 'Swedish Fly Girls'. I know that more people saw Christa because of the new title and that is good. It will always be 'Christa' to me. I have 54 pages of lists of countries from BMI (Broadcast Music Inc.) of all the countries the film played in, some for over six years. The film played all over the earth for 18 years.

Almost every movie since then has been modeled on 'Christa'. It was the first film edited to the beat of the music and other film makers are using a lot more music in their soundtracks. We were the first to edit to the beat of the music with 'Christa'.

A wonderous project. I am still doing concerts: read 'The Miracle Concert' on my website and 'The Last Breath' film treatment. It is my true story; I,  however,  did not want the hassle of the publicity for that film project.

Let's keep touch; perhaps I will be doing a concert in your area some day. and we could put together a video salute for Sandy. She truly has the voice of an angel.

One Heart