GtkBasic 003e - small Basic interpreter/IDE - 3300 functions

Stuff that has yet to be sorted into a category.
Message
Author
User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

GtkBasic 003e - small Basic interpreter/IDE - 3300 functions

#1 Post by MU »

Download (560 kb, august 31, 2008, for Puppy 2, 3 and 4)
(can be installed in addition to, or without version 002):
http://dotpups.de/puppy3/dotpups/Progra ... ic003e.pet
mirror:
http://puppyfiles.ca/dotpupsde/puppy3/d ... ic003e.pet

You also need Puppybasic 2.6, as it includes an important function-library:
http://murga-linux.com/puppy/viewtopic.php?t=11090

I do not bundle both, as Puppybasic uses less memory, so it should be used for small scripts instead of Gtkbasic.



Screenshot of IDE and examples:

Image

Full size:
http://dotpups.de/puppy3/dotpups/Progra ... -0.0.3.jpg


Screenshot of the new translation tool of the IDE:

Image

Full size:
http://dotpups.de/puppy3/dotpups/Progra ... locale.jpg


Release notes:

------------------------------------------------
Overview
------------------------------------------------
Gtkbasic is based on Puppybasic, a very small Basic-Interpreter, that is shipped as system-utility with Puppylinux.


It allows to handle Windows created with the mouse using simple Basic-code.
It is pretty small, less than 500 kb uncompressed, 95 kb compressed.

Due to its original purpose, it has functions that give extended access to a Linux-based System, so you can for example remotely move any window on your desktop using the internal functions to access Xlib.
Or use resultlist = xwin_system( "cat thefile | sed -e 's/word/replacement/' | some_weired_shell_options" ) to access Unix-tools that cover more advanced functions like regular expressions.
As Puppybasic was a pure comandline-interpreter, it also included a function-library for simplified access to external grafical tools like Xdialog or Gtkdialog.

But those dialog-tools had several limitations, that finally lead to the direct integration of libglade and the Gtk+ Api.
The first testversion was called "ginsbasic", as it only had wrappers to a utility originally written for shell-scripts.
The gins-library allows to load a XML-file generated with the grafical designer "Glade" using libglade.
So you do not code windows by hand, but instead use the grafical designer Glade.
Like this you can create very custom programs, e.g. combine lists with as many buttons as you like.
Gins has a few set of commands to read or modify those elements at runtime, but you quickly reached limits.

So I started writing wrappers to directly execute Gtk+ functions.
They allow to set far more options, or to create objects not supported by gins.

Meanwhile more than 700 Gtk+ functions are "automatically" wrapped, hence I now call it "Gtkbasic".
Not every function might work though, as the wrappers are created by a script, and it might not have detected all required conversions.
The Gtk+ C-API supports some objects not available in Basic, and those cannot be accessed directly like in C.
So I added some custom functions, that internally convert objects, or add them to an internal reference-table.

One example are Clists, that now are much easier to use than using standard-calls.
They include support for drag'n'drop and pictures.
Who ever tried to write a program using Clists in C, knows how difficult they are to handle.
But with the Gtkbasic functions, it becomes pretty easy.

------------------------------------------------
Changes from 002 to 003:
------------------------------------------------
The API changed slightly in 2 concerns.

1.) Objectnames
To adapt old programs:
remove the ":" from your objects.

- Old code:
gtk_create_object("mylist1")
gtk_do_something("window1", ":mylist1" , ...)

- New code:
gtk_create_object("mylist1")
gtk_do_something("window1", "mylist1" , ...)

The partially required ":" were confusing and slowed down execution, and were just used because it helped me to understand some mechanisms.

2.) Use the standard wrappers
The "handcoded" function "gtk_create_object" now only supports objects, that cannot be created with standard Gtk-functions in Gtkbasic.
For example because they depend on "Enums" not yet implemented.
Like Windows and Fileselectors.
I removed buttons and boxes from this function, as they can be built with the standard-functions.

So use standard-calls now, to keep your code easily portable.

- Old code:
gtk_create_object("label1" , "test" , 0 , 0)

- New code:
gtk("gtk_create_label_with_text" , "test" , 0 ,0 , 0 , 0 , 0 )
gtk_setobjectname("label1")

Whenever you create a new Gtk-object, you afterwards must assign the name for it, as Basic can not receive the objects directly.
In C, it would look like this:
GtkWidget *label1 = gtk_create_label_with_text( "test" );

Note, that the automatically generated Gtk-funtions gtk("gtk_whatever" ... ) always expect 6 argument after the functionname.
Unused arguments must be set to 0.
------------------------------------------------
Concerning object-creation, I however added a special feature to V003:
Objects created by reference calls now can get the names directly.
But that is extremely seldom, e.g. used to generate Gdk pixmaps and masks.

Such a function looks like this in C:
Widget *firstnewwidget;
firstnewwidget = new_widgettype(options);
Widget *secondnewwidget;
secondnewwidget = new_widgettype(options);
gtk_create_gdk_stuff(Widget *source , Widget &firstnewwidget , Widget &secondnewwidget)

In Gtkbasic003, this simply looks so:
gtk("gtk_create_gdk_stuff" , "sourcewidget" , "firstnewwidget" , "secondnewwidget" ,0 , 0 , 0)

Gtkbasic knows by the functionname, what type of new object is needed, and uses internally already reseved objects.
So you create them by simply assigning a new name.


------------------------------------------------
Pictures:
New since 003.
Gtk supports several different objects like images, pixmaps, bitmaps.
Very confusing, especially as there are in addition those types of the underlying "Gdk" library.

So I created a handwritten function to load Gtk-pixmaps, and convert them to gdk-objects.
Those are required by some older functions, that do not accept the new, easy to use "Gtk-image".
Look at the Demos to see, how you can display and clone pictures, or how to add them to other widgets.
------------------------------------------------
Project structure:
The easiest way to start, is to run the IDE from the demos.
Create a new project in it.
Version 002 created a file "start-project".
Version 003 now creates "project", a shellscript.
And "project.gtb" , the Basic-program.
In the shellscript, you could add any stuff you want to run before the Basic-program.
It already includes a simple mechanism for localization, and example locale-files for english and german.
------------------------------------------------
IDE:
If you execute a project, it now is run from a yellow rxvt, so you can see everything the program prints.
Needed to see events or analyze crashes.
------------------------------------------------
Lists:
They can use pictures now.
They use a different selection-method now.
Drag'n'drop was only partially supported in 002.
Now it has a "sensefull" fixed defined behaviour, and you can analyze the "drops" in detail from Basic.
See the example in the demos.

------------------------------------------------
Other fixes:
Fixed bug with missing ":" in Textviews, so now they are really usable.

If you load text from files, they should be saved as Unicode (UTF-8).
If you want to display files in different encodings, use first before attaching it to a textbuffer or widget:
thetext = g_locale_to_utf8( thetext )

Fixed severe memory-leaks (required memory was contiously increasing at runtime)

Radiobuttons no longer crash Glade in Puppy 3.
So I now added a demo how to use them.



Note: how to use sqlite with GtkBasic:
http://murga-linux.com/puppy/viewtopic. ... 542#160542


Time to sleep ;)

Good night, Mark
Last edited by MU on Sun 31 Aug 2008, 05:59, edited 7 times in total.

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#2 Post by Lobster »

Time to sleep
m m m . . . I thought they had good coffee in Germany? :D
Many thanks Mark. Great News for Basic programmers (I am still baffled by the turtle in Logo - I tried to make him into a soup) . . .
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
BarryK
Puppy Master
Posts: 9392
Joined: Mon 09 May 2005, 09:23
Location: Perth, Western Australia
Contact:

#3 Post by BarryK »

Mark, does gtkbasic require puppybasic to be installed? In other words, is it a dependency?

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#4 Post by MU »

not directly.

But several of my GtkBasic examples also use
/usr/lib/wxbasicscript/basefunctions.inc
So this file must be kept.
Less important is
/usr/lib/wxbasicscript/basefunctions2.inc

That uses a stricter syntax (uses strict mode, where every variable must be explicitly declared), but I think nobody has used it yet.

An important dependency beside the standard Gtk libraries is libglade, but this is in Puppy anyway.


I removed some days ago on my system
/usr/bin/wxbasicscript

Instead, I added a symlink:
cd /usr/bin
ln -s gtkbasic003 wxbasicscript

Until now I encountered no problems :)

Even complex programs like PSI work as expected.
Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#5 Post by MU »

I added another example, XFE-to-dotpupwizard.

It is only a very short example of Drag'n'drop.

I use a list where I can drop folders on from XFileExplorer.
The first folder will be passed to a shellscript (the dotpupwizard).

This step is required, as I cannot drop files directly from XFE to a Rox-Icon, as XFE uses a different protocoll for DND.

So this simple example shows, how you can "convert" Drag'n'Drop protocols.

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#6 Post by MU »

update:

in older versions of JWM there were problems with Buttons, so I had patched the Button events.
I now removed this patch, as it hindered checkboxes from working correct.

In JWM in Puppy3, it works ok now.

Older versions of JWM might/will have the erratic behaviour.

As checkbuttons are very important, and new versions of JWM work, I think it is acceptable to use the correct functions now, even if this means, that you cannot use Gtkbasic 003 in Puppy 2.

I also uploaded the current source to
http://noforum.de/files/wxbasic/gtkbasic/

It can be compiled with:
./___build_quick

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#7 Post by MU »

this one is not finished yet, but I must sleep now.
At least I'm so far that it basically works.
I must do internal restructuring (save settings in $HOME/.screensaver) and also not all options work yet.

Screenshot:

Image

If you want to try it, extract it in
/usr/local/Gtkbasic-003/Demos/
http://dotpups.de/diverse-tgz/Screensaver.tar.gz

Then start the GtkBasic demos again to see it.

It includes 2 older Xscreensavermodules that require OpenGL.
Antinspect (3DCC users know that), and the beautifull atlantis with whales and sharks.
They will open fullscreen on a second display.
The design is modular, so any program could be added in the modules folder.
Always 2 files are needed, a startscript and an executable file.

One thing I am not sure of how to solve, is how to deactivate the CTRL keys, so that you cannot switch the display or exit X when the password protection is activated (at moment password protection is always active).
I also must encrypt the password.

This screenshot shows atlantis, note that the password-login is mostly covered by Gimp, as that display has no windowmanager. So I cannot hide Gimp when I start the screenshot.

Image

Mark
Last edited by MU on Mon 08 Dec 2008, 01:20, edited 1 time in total.

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#8 Post by MU »

I uploaded a new source-archive.
It includes a new binary gtkbasic003.
This is intended for tests, not to replace the dotpups.
I will make a new dotpup in some days.

http://noforum.de/files/wxbasic/gtkbasi ... -05.tar.gz
mirror:
http://puppyfiles.org/stuff/wxbasic/Gtk ... -05.tar.gz

The interpreter is 260 kb compressed, or 1.3 MB uncompressed.
It now wraps all Gdk and Gtk functions (except several older, depreciated, and Cairo) - 3300 functioncalls.

So the size represents the "final size", it will not become much huger in future.

I did not test them, maybe several simply will crash your application.
It will take some days playing around, until I see what my completely rewritten build-script still does not manage.

I'm very impressed however, how easy it finally was to let it generate all the wrappers.
I had to add almost no more manual entries in the code to correct the automatic conversion.
That was very different before :)

----------------------------------------
In one of the last versions I added the ability to use functions, that have pointers to other widgets.
You also can access pointers to floating point numbers now.
Example:

Code: Select all

gtk("gtk_button_set_alignment" , "button1" ,"1","1",0,0,0)
gtk("gtk_button_get_alignment" , "button1" ,0,0,0,0,0)
a = gtk_returnpointervalue("1")
print "alignment:" & a
a = gtk_returnpointervalue("2")
print "alignment:" & a
The corresponding C-function:

Code: Select all

void gtk_button_get_alignment  (GtkButton *button,  gfloat *xalign, gfloat *yalign);
What currently not works, is to use integers or char that are pointers.
Such functions might simply crash. But those are not used very often.
It should not be so difficult to add this, too, so I will do it this year.

--------------------------------------------------

Here is an example to use enums:

Code: Select all

gtk("gtk_window_new" , "1",0,0,0,0,0)
gtk_setobjectname("mywin")
gtk("gtk_widget_show" , "mywin" , 0 ,0,0,0,0)
C-function:

Code: Select all

GtkWidget*  gtk_window_new (GtkWindowType type);
In the C-documentation you find:

Code: Select all

typedef enum
{
  GTK_WINDOW_TOPLEVEL,
  GTK_WINDOW_POPUP
} GtkWindowType;
So GtkWindowType can have the value 0 or 1.
If I remember well, those values progress, if you have more:

Code: Select all

typedef enum
{
  value1,
  value2,
  value3,
  value4,
  value5
} WHATEVER;
To use an enum, you would pass the corresponding number:
0
1
2
4
8

If you combine these values, you could activate 2 values, if the function supports it.
so gtk("gtk_teststuff_set_shadow_on_some_borders" , "testobject" , "3",0,0,0,0) could set a shadow on the top and left border of a testobject.
Just a fictive example, that does not work of course.

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#9 Post by MU »

the dotpup will of course contain new demos.
Until then some code-snippets to play with.
In the IDE, create a new project.
Copy a test.png to the subfolder /resource of your project with your filemanager.

Then add some lines after where the window is positioned after clicking on "edit" in the IDE.

Code: Select all

//-- manipulate a widget, e.g. move the window
gins_set("window1" , "10" , "10" , "<uposition>")


//-- load a picture and display it
gtk_createobject("PixmapwidFromFile" , "pixmap1", "test.png" , 0)
gtk("gtk_pixmap_get" , "pixmap1" , "gdkpixmap1" ,"gdkmask1",0,0,0)
gtk_destroyobject("pixmap1") // free memory
gtk("gtk_image_new_from_pixmap" ,  "gdkpixmap1" , "gdkmask1" ,0, 0 , 0 , 0)
gtk_setobjectname("image1")


//-- attach the image to the window
gtk("gtk_widget_show" , "image1" , 0 ,0,0,0,0)
gtk("gtk_box_pack_start" , "vbox1" , "image1" , "0","0","0",0)

//-- create a GDK grafics context
gtk("gdk_gc_new" , "gdkpixmap1"  , 0 ,0,0,0,0)
gtk_setobjectname("gc1")

//-- draw a black line
gtk("gdk_draw_line" , "gdkpixmap1"  , "gc1" , "0" , "0" , "40" , "40")

//-- load a font and draw a text
gtk("gdk_font_load" , "-*-helvetica-bold-r-normal--*-180-*-*-*-*-iso8859-1"  , 0 ,0,0,0,0)
gtk_setobjectname("font1")
gtk("gdk_draw_string" , "gdkpixmap1"  ,"font1" , "gc1" , "20" , "20" , "test" )
Like this you could plot diagrams for example.

Unfortunately, some drawing-functions like rectangulars, need more than 6 arguments.
So you cannot use them.
I must add a new gtk_long() , that gives access to functions with up to 10 arguments.

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#10 Post by MU »

update:
http://noforum.de/files/wxbasic/gtkbasic/

now has gtk_long(), it supports functions with up to 13 arguments.
Integers that are pointers now can be used like the pointer-floats mentioned above.
GdkColor now is referenced, they had the same syntax as for other objects, so my script did not recognize that.
Added a manual entry for GdkColor now.

I include an example using all this, in the subfolder testprojects.

It shows an icon with transparent, shadowed text beneath it.
Almost like in Rox, just the text is not centered.
It can be dragged around, a click on it starts leafpad. Right-click exits.
So far the theorie.
In practice, I encountered timing problems.
I wanted to make it like in Rox, with the left button you can click or drag around.
This behaves sluggish at moment.
Strange though that it works perfect, if I declare the window as "popup" in Gade.
Popups are not managed by the windowmanager, so there should be a way to achive the same behaviour with toplevel windows.
The disadvantage of the popup is, that it is always on top of all other windows.
I must try again after I got some sleep.

Mark
Last edited by MU on Sun 09 Dec 2007, 20:45, edited 1 time in total.

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#11 Post by MU »

uploaded new source, and updated also the dotpup.

Changes:
- now includes gdk-pixbuf.
- Removed memory-leaks.
- Reduced size from 1.4 MB to to 929 kb (200 kb compressed) by Code-optimization.
- The interpreter now can load includefiles "dynamically", by defining an environment-variable before running it (this is set by the IDE automatically in new projects to load the locale-files without copying them to /tmp/ first as before)
Details about that:
http://wxbasic.sourceforge.net/phpBB2/v ... php?t=1066

- Added an analogclock to show how to use the GDK library.
- added a prototype of an Icewm configurationtool. This will be completely rewritten by a more generic approach soon.

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#12 Post by MU »

here is a snapshot of what I'm working on.
It is not of any use yet, as it cannot save any values yet.
I'm just happy that I could get the subcategories working, if you click on a categorie, the subcategories under it open.
If you click on another one, they close, and the subcategories of the new one open.

Darn, that was difficult, also to get transparent icons displayed for the subcategories.
Unfortunately transparency has no nice borders with rounded icons.

It will take some more days until it becomes usable.

**edit** snapshot removed, prototype now is included as demo in GtkBasic.

Mark
Attachments
GtkBasic-ConfigCenter.jpg
(27.98 KiB) Downloaded 4860 times
Last edited by MU on Sun 16 Dec 2007, 21:12, edited 1 time in total.

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#13 Post by MU »

I updated the dotpup.

Fixed a bug with GdkColor.
Added support for Trayicons including a demo.

http://dotpups.de/puppy3/dotpups/Progra ... ic-003.pup

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#14 Post by MU »

updated the dotpup.

Changes:
the "translate locale" utility of the IDE now can use variables, that are elements in a list/table (comparable to Perls "Hashes").
I discussed this issue with David Cuny, core developer of wxBasic, that is used as the base for GtkBasic:
http://wxbasic.sourceforge.net/phpBB2/v ... php?t=1068

So you now can add variables like:
l["welcome"]

Attention: if you do that, you MUST define a table, before the .mo files are included, like this:

Code: Select all

l={}
includeenv "MOEN"
includeenv "MO"
The line "l={}" is new.

I need this feature for the Config-Center.
It reads in a configfile, and if it finds words that begin with a "_", it will look up in a table containing the translations.

This configcenter now is part of the demos, though it is not "finished" yet.
But it already can save the values.
There are however some enhancements required, until it can be used as a standalone-program to configure icewm or so.

Mark

mcewanw
Posts: 3169
Joined: Thu 16 Aug 2007, 10:48
Contact:

Re: GtkBasic 003 - small Basic interpreter/IDE - 3300 functi

#15 Post by mcewanw »

MU wrote: Gtkbasic is based on Puppybasic, a very small Basic-Interpreter, that is shipped as system-utility with Puppylinux.
This looks interesting, I'll give it a spin sometime when I have a freer moment.

It would be good if Gtkbasic or similar came preinstalled in Puppy Linux. Something like this, permanently in there, would improve utility/apps development immensely for little cost in terms of size it seems. I've been using gtkdialog for some frontend GUIs; it is nice and simple for some things, but limiting.

Does Gtkbasic support drag and drop? And, though I realise Gtkbasic is an interpreter, I wonder how it compares in size to gcc (and any required libraries etc)?

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#16 Post by MU »

GtkBasic currently supports Drag'n'Drop for Clists (lists that can display pictures and texts).
I have written some custom functions to simplify this, there is a demo included.
I did not try the drag'n'drop functionality of the native Gtk-functions that GtkBasic supports now.
So I cannot tell, if they are wrapped correctly or not.
However with the Clists you can build very comfortable Drag'n'Drop programs.

GtkBasic will not be in Puppy until we program utilities that make it a "must" ;)
Barry has pointed out, that he wants to keep Dingo (Puppy4) as small as possible, and so just leaves in GtkDialog and Xdialog.

So GtkBasic must be installed in addition, but it certainly soon will be bundled with addons like ezpup.

The size is reasonable: 200 k compressed with upx, or 930 k uncompressed.
Plus some kb for examples or utilities like the file-selection dialog, that is written in GtkBasic.
It just depends on X, Gtk2, and libglade.
Those are usually already in Puppy.

Mark

magerlab
Posts: 739
Joined: Sun 08 Jul 2007, 20:08

#17 Post by magerlab »

is it possible to use gtkbasic witthout Ezpup?
i failed to open dotpups .de with wideband limit error
what does it mean?

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#18 Post by MU »

yes, GtkBasic is a standalone-program.
Dotpups.de is down today, here is a mirror:
http://www.puppyfiles.ca/dotpupsde/pupp ... kBasic003/

Mark

User avatar
MU
Posts: 13649
Joined: Wed 24 Aug 2005, 16:52
Location: Karlsruhe, Germany
Contact:

#19 Post by MU »

I updated the Dotpup for Puppy 3 (which was reported to work in Puppy2, too).
And uploaded the sourcecode, too.

New:
Objectdestruction
In the past, the function gtk_destroyobject() did not work.
I now rewrote the internal reference-handling of the objects.

GtkBasic allows to handle 1000 Gtk-widgets at once.
If you need more, you first must destroy older ones, or you application crashes.

I could add support for more, but that increases memory-usage.
Tell me, when you need more.

:!: IMPORTANT: :!:
If you have an old application, that crashes now, please tell me.
I then will repackage it.
It will be sufficient, to remove lines using
gtk_destroyobject()
I had added that for tests in the past, but it had no function.
Now this could crash your app, if those objects still are needed.


For debugging I added:
gtk_dumpobjects()

This shows a list of all objects you created, and the length of the internal reference-list.
So you can see, if you properly destroyed objects.



I also added some new functions to handle mouseclicks better.

gtk_createobject("singleclickbutton","buttontest",0,0)
or:
gtk_createobject("singleclickbutton_with_label","buttontest","Hello",0)
or
gtk_createobject("singleclickeventbox","buttontest",0,0)

This creates a button, where signalhandling is not added to libglade.
You can assign a new signaldetection like this:
gtk_singleclick("buttontest" )

When this button now is clicked, you can detect this in the mainloop.
To be able to avoid confusion with the standard (libglade) eventmessages, this function returns the widgetname modifed.
The returnvalue for the widget now has a leading "single-".

So to detect it, you would write:
if widget = "single-buttontest" then

This application makes use of it:
http://murga-linux.com/puppy/viewtopic. ... 389#174389


Mark
[url=http://murga-linux.com/puppy/viewtopic.php?p=173456#173456]my recommended links[/url]

mrkcee
Posts: 19
Joined: Wed 23 Jan 2008, 01:12

#20 Post by mrkcee »

Whenever I run the pup file, I always says that I don't have enough disk space for it. But I have 200MB+ free space. Any ideas?
[i]Currently using:[/i] Puppy Linux 3.00 + Fluxbox

Post Reply