That's all there is pal, end of the line.

The above quote was from the film 2 minute warning and is fitting as it is the title of the last post to this blog.

To use another film quote from Dirty Harry, "A man has to know this limits" and unfortunately I need to know my limits. I had bought the minibook as a toy to muck about with and I have learned quite a lot about Linux but I also saw that it needed a lot of work on the software side, in particular a framebuffer desktop User interface due to its limited processor power. I was thinking of trying my hand at it but due to circumstances in my life, I have to be honest in saying that I would not be able commit myself to the time to do get this off the ground nor the motivation to be the sole owner of the project.

As to this blog, I am keeping it open just in case somebody finds the information useful.

Excel VBA

In my work, we use a lot of spreadsheets. To automate parts of the process, I have created Excel VBA code. One of them is to create a series on codes on a spreadsheet in the following form 999X. For example:

332A
333A
334A

The code to do this is as follows:

Sub temp2()

Dim cell_value As String

Range("a1").Select
Selection.End(xlDown).Select
cell_value = Selection.Value

For x = 0 To 10
ActiveCell.Select
Selection.Offset(1, 0).Select
cell_value = get_new_value(cell_value)
Selection.Value = cell_value
Next x
End Sub


Function get_new_value(cell_value)

Dim ipad_number As Integer
Dim ipad_char As Integer
Dim new_ipad_number As String

ipad_number = Val(Left(cell_value, 3))
ipad_char = Asc(Right(cell_value, 1))
ipad_number = ipad_number + 1

If (ipad_number > 999) Then
ipad_number = 0
ipad_char = ipad_char + 1
End If
new_ipad_number = conv_to_str(ipad_number)
get_new_value = new_ipad_number + Chr(ipad_char)
End Function

Function conv_to_str(num_part)

If (num_part < 10) Then
new_str = "00" + LTrim(Str(num_part))
ElseIf (num_part > 9) And (num_part < 100) Then
new_str = "0" + LTrim(Str(num_part))
Else
new_str = Str(num_part)
End If
conv_to_str = LTrim(new_str)
End Function

Installing Nano-X

The link to download the source code for Nano-X is here.

Once downloaded, extract all files usually to the microwindows-x.xx (where x.xx is version number, the version I used is 0.90).

Before the source code can be compiled, a few changes to the source code need to be made before it can be compiled.

First, at terminally, enter the following command:

cd micro-windows-0.90/src

Next the appropriate config file for compiling needs to be copied from the Configs folder. I used the one for Framebuffer. To do this enter:

cp ./Configs/config.fb config

To settings in the config file needs to be amended. To do this use your favourite editor to amend config. The following settings need to be set:


TTYKBD = N
SCANKBD = Y


Save file.

Two of the source files, need to be edited. Firstly, edit ./mwin/winevent.c

The abs macro, starting at line 16, needs to be commented out to look like this:

//#if !(DOS_TURBOC | DOS_QUICKC | _MINIX | VXWORKS)
//static int
//abs(int n)
//{
// return n >= 0? n: -n;
//}
//#endif


Save file.

Secondly, the file ./demos/nanowm/nanowm.h, needs to have line 173 commented out to look like this:

//extern win *windows;

Save file.

Once this is done, enter the following commands

make default
make
sudo make install


The source code should have successfully compiled.

The program gpm (cut and paste utility and mouse server for virtual consoles
) needs to be installed, if not already. If it is not, then enter the following command:

sudo apt-get install gpm

Switch to another virtual console by pressing ctrl+Alt+F2. Log in as normal. Move to microwindows-x.xx/src folder and enter the following command:

sudo ./mouse.sh

This will activate the mouse for use in the Nano-X demos.

There is a number of shell files in the microwindows/src folder that runs the demo. To run these enter

sudo ./shell-file.sh

where shell-file is name of shell file. For example.

sudo ./demo.sh

If everything went well, the demo should work.

When I had first got Nano-X, I had got the mouse working but now it isn't. I don't think this is to do with Nano-X but with the gpm program. I will need to investigate further

DirectFB - no ma cup o' tea

I've tried a few of the demo programs of DirectFB and still don't get it. It is slow and I can't figure out what is wrong when using the keyboard buffer. As the only output is sent to the framebuffer, it is hard to debug the program and find out what is going on.

I looked around for alternative solutions for a Framebuffer Desktop and found two, Nano-X (formally known as Microwindows) and Dinx. The link for Nano-X is here and the link for Dinx is here. The Dinx webpage is out of date but I found the webpage to download the source code, link is here.

I haven't had success trying to compile Dinx but I managed to get Nano-X compiled. First impression of Nano-X is favourable.

DirectFb - Colour and Text

Display text isn't really all that hard. The only thing you need is a truetype font. These fonts are usually supplied by your distro. In Ubuntu, they are stored in /usr/share/fonts/truetype. The C code to define the font is as follows:

dfb->CreateFont (dfb, "/usr/share/fonts/truetype/freefont/FreeSans.ttf", &font_dsc, &font

Where:
font_dsc is a DFBFontDescription variable that stores details about the font ie height
font is a IDirectFBFont variable which is used to specify the font in the program.

Colours are defined are RGBA color space. The wiki link about this is here. The colours are defined in Red, Green, Blue and Alpha. The values are defined in hexadecimal format, the wiki link for this is here, from 0x00 to 0xFF (0 to 255).

The following examples give details of the 3 primary colours:

red - primary->SetColor (primary, 0x80, 0x00, 0x0, 0xFF);
green - primary->SetColor (primary, 0x0, 0x80, 0x0, 0xFF);
blue - primary->SetColor (primary, 0x0, 0x00, 0x80, 0xFF);

To get other colours, the Red, Green and Blue values will need to be set. I found a webpage that has the hex codes of various colours, the link is here. The hex codes need to be broken up into it's Red, Green and Blue parts for use in DirectFB's SetColor. Examples are:

ghostwhite which has hex code #F8F8FF - primary->SetColor (primary, 0xF8,0xF8,0xFF, 0xFF);
navy which has hex code #000080 - primary->SetColor (primary, 0x00, 0x00, 0x80, 0xFF);
chocolate which has hex code #D2691E - primary->SetColor (primary, 0xD2, x069, 0x1E ,0xFF);

The following code gives an example of text and colour in action:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <directfb.h>

/*
* (Globals)
*/
static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static int screen_width = 0;
static int screen_height = 0;
#define DFBCHECK(x...) \
{ \
DFBResult err = x; \
\
if (err != DFB_OK) \
{ \
fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
DirectFBErrorFatal( #x, err ); \
} \
}


// The font we will use to draw the text.
static IDirectFBFont *font = NULL;


int main (int argc, char **argv)
{

//A structure describing font properties.
DFBFontDescription font_dsc;

DFBSurfaceDescription dsc;

DFBCHECK (DirectFBInit (&argc, &argv));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
dsc.flags = DSDESC_CAPS;
dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;
DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));
DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

/*
* First we need to create a font interface by passing a filename
* and a font description to specify the desired font size. DirectFB will
* find (or not) a suitable font loader.
*/
font_dsc.flags = DFDESC_HEIGHT;
font_dsc.height = 48;
DFBCHECK (dfb->CreateFont (dfb, "/usr/share/fonts/truetype/freefont/FreeSans.ttf", &font_dsc, &font));


//Set the font to the surface we want to draw to.

DFBCHECK (primary->SetFont (primary, font));


//Set the color that will be used to draw the text.
DFBCHECK (primary->SetColor (primary, 0x80, 0x00, 0x0, 0xFF));
DFBCHECK (primary->DrawString (primary, "This is red", -1, screen_width / 2, screen_height / 3, DSTF_LEFT));

DFBCHECK (primary->SetColor (primary, 0x0, 0x80, 0x0, 0xFF));
DFBCHECK (primary->DrawString (primary, "This is green", -1, screen_width / 2, screen_height / 2, DSTF_LEFT));

DFBCHECK (primary->SetColor (primary, 0x0, 0x00, 0x80, 0xFF));
DFBCHECK (primary->DrawString (primary, "This is Blue", -1, screen_width / 2, screen_height / 4, DSTF_LEFT));

DFBCHECK (primary->Flip (primary, NULL, DSFLIP_WAITFORSYNC));

sleep(1);

font->Release (font);
primary->Release (primary);
dfb->Release (dfb);

return 23;
}

Directfb - first impressions

DirectFB, located here is a library/C language API for the framebuffer.

I've had a look at the tutorial page (link here) and experimented with the first one ( link here)

On looking at the code, the following is required as a template to be used to get a functioning DirectFB program:

#include <stdio.h>
#include <unistd.h>
#include <directfb.h>

static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static int screen_width = 0;
static int screen_height = 0;

#define DFBCHECK(x...)
    {
       DFBResult err = x;

       if (err != DFB_OK)
       {
             fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ );
             DirectFBErrorFatal( #x, err );
       }
    }

int main (int argc, char **argv)
{
    DFBSurfaceDescription dsc;

    DFBCHECK (DirectFBInit (&argc, &argv));
    DFBCHECK (DirectFBCreate (&dfb));
    DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));

    dsc.flags = DSDESC_CAPS;
    dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;

    DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));
    DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));
    DFBCHECK (primary->SetColor (primary, 0x80, 0x80, 0xff, 0xff));

    // Code goes here

    DFBCHECK (primary->Flip (primary, NULL, 0));

    sleep (1);

    primary->Release( primary );
    dfb->Release( dfb );

    return 23;
}


In the above template, where the following appears:

// Code goes here

Enter the code which is required to do what you want to display on screen. I had experimented with drawing lines and rectangles. The code is obtained from the API reference ( link here). On my Ubuntu laptop, version 1.01 is installed, there are API's for new versions.

It has to be noted that the variables screen_width and screen_height are important to the code you put in as this gives the maximum height and width of the screen you use. This is obvious as you can't draw graphics that are bigger than your screen size. I assume that these sizes correlates to the screen resolution you have ie the higher the resolution the higher the variables.

It is not really necessary to understand the ins and outs of how the template works apart from it being the building blocks to get a DirectFB program working. This can be figured out when comfortable with the API.

To compile the program, enter the following command on the terminal (assuming you use Ubuntu which uses pkg-config for ease of compiling):

    gcc `pkg-config --cflags directfb` filename.c -o outputname `pkg-config --libs directfb`

Where filename.c is name of C file and outputname is the name of compiled program. For example:

    gcc `pkg-config --cflags directfb` test.c -o test `pkg-config --libs directfb`

It also to be noted that to run the compiled program you have to run it as root. The reason for this is that directFB needs root access to be able to communicate with the framebuffer, keyboard and mouse devices. According to the Readme file (link here) the permissions of these device can be amended so that the directFB program does not need to be run as root.

To run the program, assuming it is called test:

   sudo sudo ./test

Displaying text is not as straightforward as a font needs to be defined beforehand. I had some difficulty with this and will require some more investigation.

Frame-buffer - The first steps.

As I mentioned, I had thoughts about how to design a desktop User Interface that could be used on the LLL. The best way to do this on a resource-scarce machine like the LLL is using the framebuffer rather than X.

I've made the first start on this by setting up the framebuffer on my Ubuntu laptop. There is a few steps involved on this.

Firstly, the grub bootloader needs to be amended. To do this, amend the file /boot/grub/menu.lst with any editor. As this is a system file, it will have to be in root mode.

In menu.lst, scroll down to the bottom where the Grub Bootloader entries are located. These are always of in the format of

title ..
root ...
kernel ...
initrd


In the appropriate entry, edit the kernel line by removing the text splash and replace it with vga=792. An example would look like this

title Ubuntu 8.04.2, kernel 2.6.24-24-generic
root (hd0,4)
kernel /boot/vmlinuz-2.6.24-24-generic root=UUID=ec2c54a8-1fd7-4186-9d86-33e5e27659a8 ro quiet vga=792
initrd /boot/initrd.img-2.6.24-24-generic


To use different framebuffer resolution modes refer to the following webpage - link here

Secondly, /etc/X11/x.org needs to be amended to include the following text:

Section "Screen"
Driver "FBDev"
    Device "Primary Card"
    Monitor "Primary Monitor"
    SubSection "Display"
        Modes "default"
    EndSubSection
EndSection


Lastly, the vesafb modules needs to removed from the module blacklist. To do this edit /etc/modprode.d/blacklist-framebuffer and comment out the vesafb module by entering a # in front of it. The entry should look like:

#blacklist vesafb

Reboot the computer and if everything works ok then the Framebuffer and the X11 framebuffer should be set up. To test this enter the following command at the terminal:

   ls /dev/fb*

The following info should be displayed:

   /dev/fb0

Also enter the command on the terminal:

   /fbset

If successful, the framebuffer mode settings should be displayed.

Update data on Microsoft Access Form via VBA - Issue 2

I had applied the code to the Access database and unfortunately it did not work. An error message was thrown up. I think it may have to do with the fact that the form I applied code gets the data from a SQL select query that uses 2 tables and ME.Dirty does not like it.

I'll have to investigate this further in work-time as the best way to get the problem fixed is by using the real database rather than mock-ups at home.

Alternative Desktop - Update 2.

The past week or two I have been down with the flu (not the swine variant but who knows, the way it is mutating I could have caught the alcohol variant?). With the snorters and eyeballs nearly falling out of my head, I couldn't do anything but hold up in bed until it passed. When it did pass a little, I worked on the MS Access problem and had some more time to think about the alternative desktop I had mentioned.

I was thinking about how to display the application in context of the overall User Interface. As many different types of application with differing ways of displaying output are used, it will be a issue on how to implement it. I think the most crucial ones are:
  • The way the data is displayed ie text areas or cells

  • What parts are read only and what is read/write

  • The way the data is represented in terms of colour font etc to highlight data

  • Borders which may be required to reference data ie cell co-ordinates or ruler
Another big issue that needs to be overcome is how to implement specific functionality to each application like for instance, applying formatting to text, add a formula to spreadsheet cell or insert calendar note. The only way I can think of at moment is to a right click menu. As these are scaled down versions of the ones available on the desktop of a lot less features, this may work.

Update data on Microsoft Access Form via VBA - Issue

I had updated the code onto the MS Access database and test it with full success.

When I used the database I had no issues but when my colleagues used it, they sometimes got the error:

Update or CancelUpdate without AddNew or Edit

I had never got the error but with mucking about with the database, I finally managed to replicate it. It occurs when you manually amend the contents of the fields that will be updated by button (in my case the date and time fields), try and amend the other data fields and then click on the update button.

I also noticed that you manually amend the contents of the fields that will be updated by button and then click on the update button, nothing happens but when you try to exit form or goto to another field, a Record Upate query box appears.

I googled around and found the problem was caused Me.Dirty being set to True. On mucking about with the code, I finally managed to come up with the solution. It involves adding VB to the After Update event of every input field to see if Me.Dirty is true and if it is then set it to False.

The code is as follows:

Sub time_update_AfterUpdate()
  If Me.Dirty Then
     Me.Dirty = False
  End if
End Sub


Repeat for every input field.