PC Plus HelpDesk - issue 272

Paul Grosse This month, Paul Grosse gives you more insight into some of the topics dealt with in HelpDesk.

From the pages of HelpDesk, I look at:

  • Preloading pings for quicker results;
  • Retrieve your asterisk - remove autoformatting;
  • Diamonds are your worst enemyFiles available - click on icon;
  • Extend your WiFi range;
  • Monitor Live IP StatusFiles available - click on icon;
  • Standardise your document program output;Files available - click on iconand,
  • Using a pipeFiles available - click on icon.

(Note: where you see a larger Files available - click on the larger icon on the left when you see iton the left, you can click on it to open a new browser window with the relevant files in it.)


Preloading pings for quicker results

Simple though it appears on the surface, ping is quite a powerful tool. Packets are sent out and returned and the round trip time is measured in microseconds.

By monitoring pings carefully, you can tell when things have changed on a network - even if it is someone changing a patch cord - this is more about the location of a patch lead in terms of which socket it goes in because signals travel at around 100,000,000m/s along copper so adding a 5 metre length will add around 100ns to the round trip. However, something that you will notice on external pings is that different routes will show up.

However, pinging at one per second takes time if you need to do more than one and there are ways of speeding things up.

If you use the '-l' switch (as in the screenshot), you can preload up to three packets, releasing them as fast as they will go - this is effectively the same as flood pinging only you are restricted to three packets. Of course, if you are root, there is no restriction.

Here, I have used the 'time' command to show how quickly the program runs and you can see that in real time it took just 4ms to do the job. If you are using this in an automated setting, you can also have a time-out so that it won't take the default time out or forever to finish.

In the screenshot, you can see that an interval of 6 microseconds occurred between packets 13 and 15.

If you are just sending out three packets to see if a machine is up, you don't have to be root and, you can get the result in a lot less than one second.

Retrieve your asterisk - remove autoformatting

Typing can be enough of a headache without people 'helping' you out.

If you have been using email for a decade or so, you will be able to remember it before html email came along. At the time, if you wanted to make something stand out, you would bracket the text with '*' to embolden it and '_' to imply an underscore. You typed them and that was how they stayed. Everybody knew what it meant.

Now, if you use and asterisk or an underscore, the word processor formats that text for you and you can see the symbols you wanted leaving alone disappearing in front of your eyes.

However, not all is lost.

In OpenOffice.org, click on 'Tools', 'Autocorrect...' and then, on the AutoCorrect form, the 'Options' tab.

There are two columns of checkboxes: '[M]' for the action to be undertaken when existing text is being modified and '[T]' for the same when you are typing.

The fourth line down is 'Automatic *bold* and _underline_' so now is your chance to rid yourself of this formatting 'aid' by unchecking those boxes.

You might also want to look at some of the others whilst you are there.

Files available - click hereDiamonds are your worst enemy

Transparent materials such as plastics and gems all produce rainbow-like effects at contrasty borders. This effect, called 'dispersion', is produced by the refractive index of the medium changing with the wavelength of light.

Light travels in a vacuum at so close to 300,000,000m/s that we will, purely for the sake of convenience, call it 300,000,000m/s rather than 299,792,458m/s. When it travels through a transparent medium other than a vacuum, it is slowed down (that is to say that the speed that the light in the medium travels at is slower, not the speed of light).

Note that it is possible for particles to travel faster than the speed that light travels at in a given (insulator) medium and when that happens, light of a uniform distribution of wavelengths (looks a washed-out pale blue) is given off in a cone, the angles of the sides of which are determined by the refractive index and the speed of the particle - this is called Cherenkov radiation and you are most likely to have seen it in pictures from nuclear power station water tanks

The ratio of the speed of light in a vacuum to the speed of the light in a medium is the refractive index so, for air, where it is slowed down to roughly 299,711,990m/s, it has an RI of 1.00027 and for a diamond, where light travels roughly at 127,009,800m/s, it has an RI of 2.41749.

Just in case you were wondering what these values could go up to, Titanium dioxide has a refractive index of 2.958 and, if you go away from room temperature, downwards, a long way, the refractive index of a Bose Einstein condensate (a state of matter that exists only very close to absolute zero) has been measured overall at roughly 674,351,977.5 (or a speed of 44.4cm/s that's 1.6kmph).

On the right, you can see that pulses of light (a mixture of monochromatic red, green and blue, as opposed to a continuous spectrum) travelling from left to right are slowed down by the medium. Different colours are slowed down by different amounts. It is usually the blue that is slowed down the most but not in all materials.

For the reason that light travels at different speeds for different wavelengths, the refractive index is always measured at a standard, easy to obtain wavelength, the Sodium D lines - these are a number of lines that are very close together and with sodium lights being ubiquitous, they are easy to get hold of and therefore cheap. These refractive indices are usually denoted 'nD'.

So, what do different refractive indices look like when we put them into a ray tracing program?

On the right, you can see a simple illustration of the perception of depth. We all now that water is deeper than it looks and with the three blocks on the right, I have given them RIs of 1.60, 2.00 and 2.40.

You can see how much the green bar beneath them has been displaced and also, the view of the numbers through the front face and the writing through the top face.

We know that we can change the RI in a medium on a ray traced model so how would we use that to create the effect of dispersion?

On the right, you can see Blender with an approximation to a simplified brilliant cut gem.
On the Mirror Transparency tab, we can change the Refractive Index (IOR) to whatever we want.

So, what do we want?

It is convenient to think of the three primary colours appearing as three wavebands so here are the values...
  Red Green Blue
Band 700-600nm 600-500nm 500-400nm
Centre 650nm 550nm 450nm

Here are the refractive indices of diamond and crown glass at those centre wavelengths...

  Refractive Index
Wavelength / nm 650 550 450
Crown Glass 1.512 1.516 1.525
Diamond 2.409 2.423 2.444

Now, we can use this data to get the refractive index of the medium to produce three different images.

Files available - click hereclick here to open up the file directory in a new browserHere are a number of images of the same brilliant(sort of) cut gem but all with a slightly different refractive index used.

Click on the image on the right to open up a new browser window with these files in it.

You can see that there are slight differences between the images but if you compare the internal reflections between dia-222.jpg and dia-224.jpg, you can see quite a difference. even at this scale.

The images are all 800x600 and as I've saved you the bother of having to create your own diamond model and render it, you can load them directly into your image editor.

First of all, create a new image that is 800x600 pixels (click on 'File', 'New' the choose a template that is 800x600 then click on 'OK'). You don't have to do this, it is just an easy (lazy) way of accomplishing the task. The advantage is that this gives you an image that hasn't got a name so you won't find yourself overwriting the original.

Next, drag the images you want to use (try the dia-240.jpg, dia-242.jpg and dia-244.jpg images (although you can use the dia-222.jpg, dia-232.jpg and dia-242.jpg images to see the effect exaggerated) and drop them on the new images as in the screenshot on the right.

You should be able to see the differences between the images as you drop them onto the image you are creating

Here, you can see the effect of exaggerated changes in refractive index with the value in the top left.

If you look carefully, you will see that the physical dimensions of the gem stay the same - it is the internal reflections that you see through the faces that change.

Next, in the Layers dialogue box, change the top two images' mode to 'Addition'.

Now, select the the curves tool and then for each layer, turn down the two colours that aren't wanted. So, for the lowest refractive index image, drag the top-right node in the curves graph down to the bottom right for the green and blue channels so that you are left with the red.

Repeat this for the other two layers so that you end up with a green and a blue image adding to the red - in the screenshot on the right, you can see the job almost complete with the mouse to release the node for the green layer.

Click here to see the 800x600 composite image in a new windowThis is the final image. If you click on it, the full-sized image will open up in a new window.
Here is a part of it blown up.

You can see that where there is a change in contrast, there are colour fringes.

The ones at the top are fairly realistic. However, the darker ones at the bottom show distinct bands - unlike reality.

This is why ...

When real light (continuous spectrum, such as tungsten or sunlight sources) is dispersed, you get a pattern like the one on the right.
However, we are using just three colours and the image will end up like so - as the image above shows.

If the dispersion isn't that great, you will get away with it. However, if it is too great, you will end up as blocks of posterised colour, ie
RED, YELLOW, GREEN, CYAN, BLUE or worst still, just
RED, GREEN, BLUE instead of a

The reason for this is that the computer only needs three colours to simulate most of the colour that we can see. The colours for the continuous spectrum text above are defined as RGB values as opposed to a wavelength. For most purposes, we get away with it but when it comes to continuous spectra, it falls apart because you are looking at spatial separation.

Ray tracers could allow you to define the dispersion of a material and it could work its way through the RI range, working out the colours and adding them to the pixel values but this takes a lot of computing.

Just when you though it couldn't get any worse, have you considered mercury vapour lamps?

They produce a spectrum like the one on the right. To look at an image produced by that (or, more appropriately, to take a photograph of a scene illuminated by mercury vapour emission spectra), you would need to process four channels and only one of them is anything like close to one of the colours we use.

To take a photograph, you would need filters for those wavelengths and then you would need imaging software that could turn it into RGB so that it could be displayed by our three colour monitors. And then, there are some people with a type of 'colour blindness' where they have a fourth colour receptor in addition to the RGB receptors. And then, there is not account of angle of polarisation - reflections with an incident angle of 45 degrees result in one angle of polarisation being reflected predominantly, whilst the other being refracted predominantly. And then, there are minerals that have two, uniaxial birefringent refractive indices - examples being Calcite, Rutile, Sodium Nitrate and Calomel.

Being able to see yellow light as its own colour means that three colour monitors would never look like the real thing because only 75% of the image they require is displayed. It would be a bit like mixing the red and green to make one yellow channel.

Penultimately (as opposed to finally), as this happens in all transparent media, including lenses, there are three solutions to the problem of chromatic aberrations in lenses. Essentially, you get chromatic aberrations when you use a convex lens with a medium that produces a higher RI with blue light. So, you can either:

  1. use an additional lens that has a concave surface using a material with a higher dispersion of the same polarity;
  2. use an additional lens that has a convex surface using a material with a dispersion of the opposite polarity; or,
  3. don't use any lens - use a concave mirror instead.

Solution 1 has the effect of lowering the power of the lens, 2 has the effect of increasing it and 3 reflects the light, reversing it which is all right if you are using a telescope or a camera.

And finally, how do your eyes correct for chromatic aberration? Well, they don't. You don't have any colour sensitivity in your peripheral vision where you would get chromatic aberrations. Your vision there is only monochrome. You perceive colour in your peripheral vision because your brain makes up what it doesn't know, either from having looked at it recently and assuming that it hasn't changed, or from guess work.

Extend your WiFi range

With a wireless router, you are all right as long as all of your nodes are effectively out of range by the perimeter of your property - this can either be because you property is so big or because your buildings cut down the range so that it stays effectively within your site.

There isn't actually a limit beyond where the waves won't travel. They will, go on forever. However, there is an effective limit, the limit of a usably high signal level. In the diagram on the left, both A and B are within each other's usable signal levels. You could increase this range so that your signal could be received over a larger range by increasing the power but whilst your signal could be received, you would need a more sensitive receiver in order to be able to receive other user's signals.

However, there is another way of doing this...

Several years ago, there was a demonstration just before the annual InfoSecurity exhibition in London (UK). They got a normal Bluetooth dongle (remember that one of the main security features of this is that it has a range of only 5 to 10m) and a wave guide (making it look like a Bazooka) and were able to transmit/receive signals of a ranged between half and one mile.

This is effectively what is happening in the diagram on the left. C's footprint has been changed by using a reflector/waveguide and whilst A and B were secure(ish) before C turned up, they can now be hacked.

Wireless routers are effectively increasing their coverage because of the use of wireless network range extenders. These are simple devices that once configured, extend the range of a network to several hundred yards and also fill in any dead spots you might have had.

They can also be used as wireless access points, allowing you (and possibly a number of other people) to benefit from the freedom of your network. In addition, some gadgets can increase the range of a network up to several miles. In the diagram on the left, you can see that even using one that has the same strength/sensitivity as the original network, there is now an effective area D that has coverage of anything that C can pick up and transmit to.

Many companies assumed that because their network used to have a range limited to their building, they didn't have to do anything about security other than use the default passwords. As a result, these companies are now becoming vulnerable.

So, how do we make it safer if we are going to stick with wireless? Passwords need to be changed and encryption used, even on guests. With a 802.11g WiFi router with a claimed line-of-sight range of up to five miles on the market so you can't make any assumptions any more.

So, Extend your WiFi range but remember that you could be extending other people's. WiFi has never been completely safe but now it needs security like it has never needed it before.

Files available - click hereMonitor Live IP Status

So, you want a network monitoring tool that just pings each machine and lets you know if everything seems all right.

Network monitoring tools either take some configuring or need to run even when you are not at your computer.

In addition, you can see that you have to have a screen dedicated to it. If you are an admin, looking after a network and that is all you do, it is a very useful tool that does a good job, alerting you onscreen or via email, SNMP or any other method you have the plug-ins for including SMS, but if you just run a small network, maybe over a few offices or a few rooms in a house and want to see in real time when a machine is on, it is a bit too much.

One alternative is nmap but you can't see what is going on quickly and it is not cross-platform. It's output is displayed in the screenshot on the right.

It scans the network that you've specified and tells you about anything that it's found. To see what's going on, you have to take the trouble to execute it - it's not automatic - and read it.

Where Nagios could have been too much, this is probably too little.

Further up the page (Preloading pings for quicker results), we saw how you can send and receive up to 3 pings in a few milliseconds without any additional privileges.

Round-trip times are printed out in milliseconds to three places (here, they all have three microseconds as the last place but that is just coincidence) so resolution is down to microsecond level (the clock on a 100mb/s Ethernet runs at 25MHz so 1 microsecond is well within its abilities).

If we sniff the network when this is done, you can see that the actual time between pings is in the order of six to thirty microseconds so it does the job fairly easily and with a useful resolution.
Files available - click hereSo, I've provided you with a little program I've written that displays a dialogue box showing you the status of any IP addresses you need to monitor so you can see what is going on at a glance.

Just click on any block to give you an immediate update or wait for the program to do it itself.

You can get it to display the name and/or the IP address of the machine along with its ping time in microseconds.

IP groups, intervals and warning thresholds are all defined in the configuration file making the addition of new machines simple.

You can make the warning limits different for each IP address so whilst a local machine might show red for a ping of 150 microseconds, one on a distant network could show green at 20,000 microseconds.

The program is written in Perl, is annotated and runs on Windows, Linux and the BSDs so it is easy to edit and being a flat text file, you can even edit it in Notepad.

Above-right is the program running on Linux and on the right, it is running on Windows Vista.

*Note that on Windows, the ping resolution is only in whole milliseconds so, for your LAN, where ping times are usually only a few hundred microseconds, they will show up as zero.

You can make the non-okay IPs stand out more by making the green colour only slightly different to the form's colour. I fact, you don't need to use green, yellow, orange and red at all if you don't want to - these are all fully configurable in the program.

On the left, you can see one configuration that I use - I'll leave it as an exercise for the reader to modify the program so that it produces the output on the left.

You can find the program and the configuration file by clicking here for Windows and here for Linux, *BSD and so on which will open up a new browser window. The OS is specified in the configuration file and if you want to add another (such as Solaris), just add it to the configuration file and the program - it is fairly obvious how to.

When you run the program, it checks through the configuration file and lets you know what is going on. When it exits, it leaves a code which is...
  • 0 for a clean exit;
  • 1 for configuration file not found (make sure that the file exists);
  • 2 for no IPs section at all (you need at least one IP address for it to monitor);
  • 3 for unrecognised OS or other globals section part specified (it tells you which and on which line);
  • 4 for empty IP section defined (just remark it out with a hash mark or add an IP address); and,
  • 5 for IP section not defined (make sure there is a header (such as; '[Accounts]') before the first IP address.

Files available - click hereStandardise your document program output

Writing a computer program is cool but writing a program that writes other programs is cooler still.

If you need to produce documents as program output, you will probably have thought of plain text files but formatting is out of your control and graphics are non-existent.

However, PostScript files produce standard output using specified fonts and graphics and will work across many different platforms.

Rather than a complex, proprietary binary, PostScript files are actually plain text. They are, in effect, programs for printers and plotters and apart from being able to produce them by hand with a text editor like NotePad or KWrite, it is quite easy to write a program to do it using any language.

If you are going to use it in a program, it is probably a good idea to get used to the basics of the language by doing some programming with a text editor to see how it works.

You can either write a file directly and view that or you can write and run a program that writes the PostScript file. It is probably easier to start off writing the file directly to get the feel of what is needed.

On the right, you can see that the basic text editor on KDE - 'KWrite' has a colouring system that allows you to view a post script document more easily. It automatically determines what sort of file it is by using the first line of the file - in this case %!PS-Adobe'.

All PostScript files start off like this - this technique is used so that if you pass a file to a shell, it can determine what sort of file it is and which program to run it with, in pretty much the same way as starting a file with '#!/bin/bash' or '#!/usr/bin/perl'.

If, you want to change the highlighting (for some reason or if it hasn't decided that it is a PS file (for instance, you haven't saved it yet), then just click on 'Tools', 'Highlighting', 'Markup', 'PostScript' to select the highlighting.

So, whilst all PostScript files start off with '%!PS-Adobe' on the first line, they don't have to on every system - the percent sign is used as a remark so it is ignored by the interpreter any way.

However, it is a good idea to use it if you want your files to be cross-platform.

First of all, start off your file so that it looks like this...

...and save it, for example, as 'myfile.ps'. The showpage command makes the interpreter display the page so it is fairly important to have it there. All of the other programming goes between these two lines. (Note that line endings are not important to the interpreter. There are no semicolons or commas, just white space. Use it to make your document legible.)

However, now that it is saved, you can open it with a viewer such as KGhostView.

If you have saved your file to the desktop, right-click on the file and select 'Open With', 'KGhostView'. The program will look like the screenshot on the right. To get the paper size right, click on 'View', 'Paper Size', 'A4'.

Each time you modify the page as you program it, can refresh the image of it by switching focus to KGhostView, pressing [F5] and then switching focus back - ie, pressing [Alt]-[Tab], [F5], [Alt]-[Tab], which is a bit laborious.

Instead, on KGhostView, select 'Settings', 'Watch File' and whenever you save your PS file, it will update the image of it automatically.

So, we have the first line and the last line, now we need to put something in between. Here are some of the basics...

First of all, the co-ordinate system works with 0,0 in the bottom left with 'y' increasing as you move up the paper (just like it does on graph paper, except that we all got used to it being 0,0 at the top left with 'y' increasing as you move down the paper when we all learned how to do graphics on the computer - just forget everything you know about computer graphics).

The distance units you will be using are an approximation to points. One of these points is 1/72nd of an inch or 28.34 units to the centimetre. For argument's sake we will acknowledge that they are not actually real points but go ahead and call them points any way.

Next, the commands are designed to work with a stack (a 'LIFO' buffer, the Last one you put In is the First one to take Out).
  • To put a number on the stack, you write it down;
  • To duplicate the top number, use dup;
  • To remove it, use pop - you will see later on why you would ever want to remove a number that you have taken the trouble to put on the stack; and,
  • To use it, you use a procedure or a function of some sort. Mostly, these take a number or more from the stack and do something with them and then optionally place a number back on the stack.

So if you want to multiply 31 by 15, you write ...

31 15 mul

... and it removes the 15 and 31 places 465 on the stack. Note that the height of the stack has gone down one. Also remember that in our .PS document there are no commas, just white space between the values.

If you want to move the pen from 20,20 and draw a 1.6 point wide line to 40,50, you write this...

1.6 setlinewidth
20 20 moveto
40 50 lineto

Highlight the text above and copy it [Ctrl][C]. In KWrite, Select all text [Ctrl][A] and paste the new text [Ctrl][V] and then save it [Ctrl][S]. You can do this with any of the text here that starts and finishes properly (ie with the adobe first line and showpage).

When you save the file, KGhostView updates its display and you can see what you have just done.

Note that if you wanted to move the line upwards so that instead of starting at 20,20, it started at 20,80 and wrote ...

80 20 moveto
40 50 lineto

... you would end up with a line that pointed downwards - you would have to change the y co-ordinate of the second line as well so that it read 40 110 lineto. Instead, you can make life easier by using relative co-ordinates. You do this by using rlineto and rmoveto instead. If your first lines look like this ...

20 20 moveto
20 30 rlineto

... then for your second pair of lines, you only need to change the absolute co-ordinates like so ...

80 20 moveto
20 30 rlineto

... which gives the same results. So, always start off with a pair of absolute co-ordinates.

So, let's start off with a Scotch Border. We'll bracket the contents of our page with two commands that preserve the rest of what is going on, on the printer - these are called gsave and grestore.

Additionally, we'll define the colour in terms of RGB and the line width in points. 'setrgbcolor' is spelled the Americanised English way so there is no 'U' in it and the other thing to look out for is that the RGB values have a value from 0 to 1 inclusive (you don't have to remember if it was (0..100) or (0..255) or whatever).

The value of the line width is in points and the line between the line's starting and ending points defines the line's centre-line.

This means that if you want to place things by the side of lines, you have to take this into account (but you'll be using a computer so that shouldn't be hard to do, you just have to remember to do it).

We'll also add the concept of a path - this allows you to define a starting point and when you want to close it, instead of having to work out just how you should get back (you might have been using different co-ordinate systems or something) all you have to do is close the path and it does it for you. It also has another effect. Try running the following program (The % at the beginning of each comment on the right, above, allows you to copy the text just by dragging it into a text editor - the % signs making the column on the right into comments which won't be interpreted so you don't need to be concerned about deleting it because you don't need to.)...

  20 setlinewidth
  % No path
  0 0 0 setrgbcolor % black
  50 700 moveto
  72 0 rlineto 0 72 rlineto
  -72 0 rlineto 0 -72 rlineto
  % For the reasons that the line is wide and that the box is not 'closed' by PostScript but by hand, the start and the finish are treated differently to the other corners.
  % Run as four separate Lines
  0 0 0 setrgbcolor % black
  50 600 moveto 72 0 rlineto stroke

  1 0 0 setrgbcolor % red
  122 600 moveto 0 72 rlineto stroke

  0 1 0 setrgbcolor % green
  122 672 moveto -72 0 rlineto stroke

  0 0 1 setrgbcolor % blue
  50 671 moveto 0 -72 rlineto stroke
  % You can see this more easily with this example ... displaying how the lines are drawn when they are drawn separately.
  % Use newpath/closepath instead
  0 0 0 setrgbcolor % black
    50 500 moveto 72 0 rlineto
    0 72 rlineto -72 0 rlineto
  % Now, you can see that we use the closepath procedure to make postscript treat the start and the finish the same as the other corners - in fact, we don't even need to define where the last part of the line is, because we did that when we defined where the path started in the moveto just after the 'newpath' statement.
  % Use newpath/closepath instead
  0 0 0 setrgbcolor % black
    50 400 moveto 72 0 rlineto
    0 72 rlineto -72 0 rlineto

  % Here, instead of drawing the outline to the box, we've used 'fill' instead. This just uses the path and ignores the line width. If you want to draw a line as well as fill it, either work out where the perimeter will be and just fill it (easy, knowing the line width and the corners if the only angles in it are right angles but not so easy for other shapes) or, easier if you are programming it (or using copy and paste on a text editor) just draw the path twice, one for the line, the other for the fill. The latter has the advantage that you can use different colours.

... and you should get the result above on the right. Each of the images is next to their subroutines so you can see what happens.

So this is what we have so far...

  % draw scotch border
  0 0 0 setrgbcolor 0.5 setlinewidth
    50 50 moveto 50 790 lineto
    550 790 lineto 550 50 lineto
  2 setlinewidth
    53 53 moveto 53 787 lineto
    547 787 lineto 547 53 lineto

Copy and paste this into a new document to see it work.

You can insert an additional rgb definition before the second line and make the two lines different shades of grey or any other colour if you want.

Another option is that instead of feeding the stack just the values it needs when they are needed (ie, for a moveto, you push two values onto the stack), you can push as many values as you like onto the stack and then execute them with a series of commands. Instead of having ...

50 50 moveto 50 790 lineto 550 790 lineto 550 50 lineto

... you have ...

550 50 550 790 50 790 50 50 moveto lineto lineto lineto

However, it is important that you remember the order that they are read off the stack. If we colour each set of values and instructions, the order they go in is this ...

550 50 550 790 50 790 50 50 moveto lineto lineto lineto

The commands remove numbers from the top of the stack so they take them off in the reverse (pair) order that you put them on (note that this is not all numbers in reversed order, just the pairs as they are used - if you used commands that took different numbers of values such as 'setrgbcolor' or 'setlinewidth', you would group those instead)

So, whilst that might look pretty, it is hard to read so what use it is? Well, you can define your own procedures (do this by putting a slash in front of the name, then open and close braces then 'def' and your procedure goes inside the braces like '/l {lineto} def' ). Note that these are case-dependent so 'p' is different to 'P'. If you do something more than once or twice (depending upon how long it is and how lazy a typist you are), you can turn it into a procedure. Instead of 'moveto lineto lineto lineto', you could just define a procedure. In fact, the other things we used to define a box don't even use parameters so we could end up with this...


/b {newpath moveto lineto lineto lineto closepath stroke} def

  % draw scotch border
  0 0 0 setrgbcolor 0.5 setlinewidth
  550 50 550 790 50 790 50 50 b
  2 setlinewidth
  547 53 547 787 53 787 53 53 b

... where the co-ordinates of the box are all pushed onto the stack in reverse-pair order and then 'b' is called which pops them all off again so our stack is clean. Note that your procedures don't have to be single line, they can call each other (be careful) and you can put comments in them so that you can maintain your program (if you make an original and comment that, when you write your program, you can leave the comments out of its output - you don't need them there).

Also, your procedures can have any names they want (within the usual limits) but remember that they are case-dependent though.

Let's put some text at the top. A font is just a PostScript file and you find it, scale it and then set it to be the current font. Like any drawing, you take a position and then start drawing. Like so ...

/Helvetica findfont 36 scalefont setfont
65 750 moveto
1 0 0 setrgbcolor (PC) show
0 0 0 setrgbcolor (Plus HelpDesk SuperDVD) show

... where the font is Helvetica, it will be 36 points high, positioned at x=65 points and y=750 points. Using a red colour (1,0,0), we print the letters 'PC'. The current position is now after the 'C' of 'PC' Next, we change the colour to black and print the rest of the text.

Just in case you were wondering, if you want a bold font, you ask for one. It doesn't convert a font that you haven't got a bold version of into a bold font but if you have one, it will use it. Try the following fragment ...

  /Helvetica findfont 36 scalefont setfont
  65 750 moveto
  1 0 0 setrgbcolor (PC) show
  0 0 0 setrgbcolor (Plus HelpDesk SuperDVD) show
  /Helvetica-bold findfont 36 scalefont setfont
  55 700 moveto
  1 0 0 setrgbcolor (PC) show
  0 0 0 setrgbcolor (Plus HelpDesk SuperDVD) show

Supposing you get your design all nice but decide that it could all move about an inch to the right and half an inch upwards. Instead of changing all of the absolute co-ordinates, all we need to do is introduce a vector function.

72 36 translate

This takes the current co-ordinate system and shifts it all along and upwards by the defined amounts. Note that this is relative so the next one you use adds to this so if you wanted to shift the next load of actions left by half an inch after using the command above, you would use ...

-36 0 translate

Another thing you can do is to write for-to-next loops. You define: the starting value; the increment; the value that, when exceeded, will cause the anonymous procedure to not run; the anonymous procedure; and, type the word 'for'. If you wrote ...

/Helvetica findfont 72 scalefont setfont
50 750 moveto % Put it at the top of the page
0 5 50 {
  dup       % Make a copy of the number on the stack
  0 rmoveto % Use that top copy and add a 0 to it to
            % get an increasing movement to the right
  50 div dup 0 exch setrgbcolor % Push a 50 onto the
            % stack and divide the number on the stack
            % by it so we have a number from 0 to 1.
            % Duplicate it, push a zero onto the stack,
            % swap the zero with the number under it (Okay,
            % this is totally unnecessary but it shows
            % you that it can be done, then use the three
            % values to set the rgb colour with '0' in
            % the middle so we get shades of magenta
  (I) show  % Print an 'I' which, in Helvetica is just
            % a vertical bar 
} for

... then we get a series of capital 'I's in 72 point Helvetica running from the top left of the page in black through to the right hand side with increasing spacing and increasing 'magentaness' like so.

The next snippet uses what we have already learned plus the rotate command which takes the value off the stack (in degrees) and rotates about the current location, everything you do after it. It is sensible to use gsave and grestore when doing this. Note that we also use an rmoveto with a negative Y value. The font height is 12 points should give you a clue as to why we do this. Try changing it and see what happens.
% upper arc of PC Plus
/Helvetica findfont 12 scalefont setfont
0 11.25 90 {
    0 100 moveto
    50 -6 rmoveto
    1 0 0 setrgbcolor (PC) show
    0 0 0 setrgbcolor (Plus ) show
    1 0 0 setrgbcolor (PC) show
    0 0 0 setrgbcolor (Plus) show
} for

Note that I have used indentation to make it easier for me to track what is going on - the machine doesn't have any trouble unless I make a mistake.

Finally, the colour blocks look like this ...
50 50 translate
0 20 100 {
  dup dup 0 moveto
  0 20 100 {
    exch 100 div exch 100 div 0 20 rmoveto
    1 setrgbcolor 20 setlinewidth
      0 20 rlineto stroke
  } for
} for

We've already used or commented on all of the commands here so see if you can work out how it works.

  • How does it make a filled in square (this isn't the only way of making a filled square but it is the laziest)?
  • how does it produce a 2D array of different colours in order?

The best way of doing this is to open up a text editor and pretend to be the stack

Here is another one for you to look at....
150 550 translate
% Graded border
10 setlinewidth
  1 1 8 {
    8 div dup 2 div 0.5 add
    exch dup 2 div setrgbcolor
    -10 -10 translate
      0 0 moveto dup 20 mul 0 rlineto
      dup 20 mul 0 exch rlineto
      dup -20 mul 0 rlineto
  } for
% Orange diamond
1 0.5 0 setrgbcolor
  -10 0 moveto 10 10 rlineto
  10 -10 rlineto -10 -10 rlineto
closepath fill

Again, pretend to be the stack to see what is going on.

There are programs that will produce PS or EPS output that you can look at such as Karbon14.

These are like any other vector drawing program (they will also produce other file types as well such as BMP, PNG GIMP Native Image Format, Windows Metafile and so on) and when outputting to EPS, you can open them up with a text editor like any other type of PS file. One thing you won't see is fonts defined as they are all converted to linetos.

Once you have learned the tricks you need to know, converting the file into the program you need to generate it is simple - you know what you want, you know what you need and you know how to do it.

Using one of your own programs to write these files is also very powerful - if you write your own Sudoku or Kakuro problem generating program for example.

Using a pipe

Files available - click hereSo, you have a device that can display digits or, a number of numbers and is connected via an RS232c serial cable. Some of these have alphanumeric displays, along with buffers and others are number-only like the Nixie tube web counters.

However, they all need something to process the data that the web counter passes on. Ideally, a number of different programs would talk to it and it would all be under a semi-intelligent control - sort-of.

You could have each program open up the RS232c link, talk to it and then close the port but supposing something went wrong - would your web counter (and therefore your webserver) gum up? Also, what if you wanted your webcounter value displayed for 2 seconds before anything else was shown (apart from another webcounter update of course)? This latter condition might be difficult to control using files to pass data onto a program that read them continuously - a lot of file reading going on there ...

Ideally, we want all of the programs to talk to a continuously running program, through a single point of entry, so that it can all be controlled intelligently. This is one way of doing it.

There are a number of different file types on a UNIX-like system and one of the more interesting and useful is the 'pipe'. A pipe is a FIFO buffer that has permissions in the same way as any other file does. A program sitting on the receiving end of it can process data when it comes in instead of having to read a file every second or so. This is far more efficient.

You have a choice of commands to create them (depending on your system), either mkpipe or mkfifo. To make a pipe in the current directory, type ...

mkfifo webctr

... which will create a pipe called 'webctr'. This has permissions which can be changed if you need to - you should need to write to it for a start. You might find that it is owned by root so if you chown it to yourself and then change the permissions to -rw--w--w- or 644 then you can design it so that anything can write to it but only you can read it (later on, you can make it so that the owner has little in the way of privileges and run it as that).

So, we need a program that can read from the pipe and any number of programs that can write to it. The best language to handle this is Perl - it is on all UNIX-like systems by default (the Internet runs on Perl) and it is designed for the job.

Files available - click hereI have written some example code for you which should demonstrate how it works and you can get to the directory by clicking here. Unfortunately, pipes can't be copied onto DVDs because they won't go into .ZIP or .TAR.GZ files so you will have to make your own in the directory that you copy these files into. These files just demonstrate how you can have several files talking to another program via a pipe and they can be filtered so that the appropriate information gets to the device. You can edit them to make them as simple or complicated as you like.

The important file is the 'cntiface' file which acts as the interface between your pipe and your display. You display should either be able to take digits or any character and there will be control characters as well. All you need to do is to make sure that the control characters are sent in the string with your information.

The output program works by sending its data to the console output so it is seen as a series of lines. The actual counter will be different, of course.

The variable $digitonly is set to 0 to get the verbose (LCD-type) display and,

set to 1 to get the digit only information on the right. You would set it to give a persistently positioned set of digits for days, hours minutes - DDD-HH-MM so that you could see it incrementing.

If you open a console, cd to your pipe directory and type ./cntiface nothing will happen until something is sent to the pipe. Let it run for the moment...

More on this program later.

Let's have a look at the inputting programs.

This snippet simulates what you would have in a web counter program - an SSI that is run when somebody accesses the page that is being counted and producing the text on the left.

As this program already has the number in it, you can just add the three lines that start with 'open' and finish with 'close'.

If you process your web counter value by, say, putting commas between groups of three digits (in the style of thousands, ie 1,234,567) then you can either make a copy of the counter value or take the processed value and remove the commas using the substitute string ( $c =~ s/,//g; ). At the end of the program, use the lines ...

open (PIPE, "+<webctr") or die $!;
  print PIPE "cn $c\n";
close PIPE;

as the last thing it does before the program exits. That way, if there was any problem with opening the pipe, it would not destroy the functionality of the rest of the counter cgi script and any error would show up in the server's error log.

Using '+<' in the open statement means that it will not hang up if the pipe has nothing listening to it so your web server won't time-out.

If nothing is there, nothing is heard but, like the tree falling in the woods, it carries on happening any way.

Open up another console, cd to your pipe directory and type ./inp1 and it will start sending a counter signal ('cn 128934' to start with) between every 2 to 5 seconds. Let it run. You should see the printer number appear in the other console.

The other program really just demonstrates that you can have more than one program writing to it at the same time and that the input from one program is processed to have priority over the input from the other.

This one, just for the sake of producing data, sends the uptime of the computer every second to the pipe.

In reality, if you wanted to use uptime, you would get the program that reads the pipe to look at it using an alarm interrupt.

Back to the program that listens to the pipe and talks to the display device.

Once you have started this program, it only runs when something is written to the pipe (unless you are using an alarm as well, such as in the uptime option).

You would normally start the program by opening the port to the display device and end the program by closing it. However, here, I'm not assuming that you have such a device so that is remarked out.

The next thing that happens is that the pipe is opened (again, this is closed at the end) and the piped monitored - this goes to $_ when it arrives. This has the carriage return chomped off and then it is split into two - the function and the value.

    $a =~ m/(..) (.+)/;
    $fn = $1;
    $val = $2;

We use a matching regular expression to get the first two characters, ignore the space and then get the rest of the string. If you look at the other two programs, they start their output with either a 'cn' or a 'ut'. Here, we use that information to determine what we should do. You don't have to do it this way - you could use just the numbers but here, we are making the program more flexible for future changes should they be needed.

The next few lines look to see if it is an uptime and if it is, then if the last information displayed was within 3 seconds, it does nothing. There is provision for an old function ($of) so that you could, if you wish, get it to compare that and if the last command was an uptime, print it out anyway.

Next, it looks to see if it is a counter value.

    } elsif ($fn eq "cn") {
      if ($digitonly == 0) {
        1 while ($val =~ s/(\d+)(\d\d\d)/$1,$2/);
        printit "Web Counter: $val";
      } else {
        printit "$val";

If it isn't digit only, the string is broken with commas at every third digit from the right and then the words 'Web Counter: ' is added so '1234567' would turn into 'Web Counter: 1,234,567'. If it is digit only, then it is left as just the number. In both cases, the value is sent to a routine called 'printit'.

Here it just outputs to the console screen - where you would add any control codes you need to use.

sub printit {
  $a = shift;
  # here we put our program for writing to the port
  # note that the port is already open so we don't
  # have to do that

  # until then, we'll write to the screen instead
  print "$a\n"

This is just a demonstration. You can add whatever functionality and connectivity you like.

Files available - click hereAlso in the files directory is a GUI version (for those of you who haven't got the Nixie or LCD hardware but want to have a counter on the screen) called 'cntGUI'. When it's running, put it on top and make it visible on all desktops.

For the reason that anybody can read the pipe, you don't need a privileged user to be able to. So, you can have this program in your ~/home/bin/perl/ directory if you want and run it from there. Just make sure that the path to the pipe is correct - use and absolute path. On the right is the real output from that particular program - adapt it how you want to.

In addition, this one sends a "\a" to STDOUT which is the standard VT100 bell so if you are running it from a console, you will get a beep each time someone looks at your main page. (Leave this on a line on its own so that it is easy to see and remark out because eventually, it will drive you around the bend.)

If you want to make more than one program look at the result of the counter increment, you could make your other program save its PID to a file in a known place and then program your pipe-monitoring program to read that and send the pid a signal (assuming that it is with the same user or is root - privileges making security in UNIX again) so that the program receiving the signal can read the new value in the counter number file.

Back to PC Plus Archive Index Page