Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
150 user(s) are online (106 user(s) are browsing Forums)

Members: 0
Guests: 150

more...

Headlines

Forum Index


Board index » All Posts (kas1e)




Re: Block comments
Home away from home
Home away from home


@Raziel
I asked some years ago to block HKvalhe comments on os4depot, as while i have no problems when one have mental issues, i do have problems when one start to dirty feedbacks with ill / psycho comments which kind of broke motivation to answer in the comments after. But as it wasn't done, i assume the way how HKvalhe still spam the os4depot's comments is ok for admins.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: Do we have fast, accelerated, bug-free, supporting scaling SNES emulator ?
Home away from home
Home away from home


@Huno
Quote:

Yes you can change the buttons that are already recognized in the GUI

How ? I tried to click in the items to type my new ones, and can't.

Quote:

however on the command line it accepts .sfc/smc, do you want me to add the search for .sfc/smc in the graphical interface


IMHO it will be good if gui can searh not only for zips but also for .sfc/smc as well, and maybe just in one single "ROM" directory instead of 3 different ones (if possible)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: Do we have fast, accelerated, bug-free, supporting scaling SNES emulator ?
Home away from home
Home away from home


@Huno
Tested, speed indeed ok on x5000! At least with Donkey Kong for sure.

Few questions:

Is it expected that i can't change buttons for the amigainput from GUI ?

Also is it possible to choose my own screenmode for the fullscreen, so to be not 640x480, but 1920x1080 (just like i have when resize window when in window mode in fullsreen) ?

And is there possibility to not use .zips, but sfc/smc too ?

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: Do we have fast, accelerated, bug-free, supporting scaling SNES emulator ?
Home away from home
Home away from home


@Maijestro
On your video donkey kong didn't looks like 50-60 fps, more like 20-25 fps.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@balaton
Quote:

You're modifying nw-Title and not restoring it, this will likely break window title.


But then we modified there a null terminated title, which modified only if it DISK, which title we use in Filer only as the one we construct , and while it null-terminated it should be ok ?

All the other opening of the same window, will do another openwindowtaglist() and if it filer again : then it ok to modify it, and not, then it will not go till that part.

The only problem probably, is that OS's code later free things, and Title can be less of size as original which can cause issues if cleaning code not good enough.

Or i miss some more issues with modified title like this ?


Quote:

Why are you opening DOS.library separately in _start instead of calling init

As joerg says that for making IDOS->Printf works, because i can't IDOS->Printf if it wasn't opened, which will cause a crash if by some reasons it can't be opened.

Quote:

but that's not required anyway: all libraries opened in init() are kickstart libraries which can't fail to open. If any of them couldn't be opened loading the wb2filer executable wouldn't be possible either...


Just more error check IMHO never hurt …

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@All
New version:

Quote:

-- better parsing of the titles to handle spaces

-- better parsing of the Filer's path, which also may contain spaces

-- Added "static inline" in front of all functions (except _start and original functions) to reduce size of the binary even more.

Thanks joerg for all the points about!


There is: https://kas1e.mikendezign.com/aos4/wb2filer/WB2Filer_v10.lha

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@Joerg
Quote:

You are searching for the first instead of the last '%', try something like

Thanks, works well

Quote:

To reduce code size add "static inline" to all functions, except for _start().


Right, now it's 1kb less as well (through not only for _start() can't use static inline, but also for declaration of original functions to avoid warnings "warning: variable ‘Original_OpenWindowTagList’ declared ‘inline’", etc).

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@geennaam
Quote:

Wb2filer doesn't work correctly for Usb media with space in its name. For example, when I try to open a USB msd with "No name" as volume name then I get a popup asking me to insert volume "No:"


That happens when i made parsing of "title" instead of other methods (as it more easy and fits better into everything): i simple search in the title for the first space and just replace it on ":" + nulltermination :) So spaces in names didn't parsed properly indeed.

Instead it should be done as Joerg says before:

Quote:

Search for the last '%' (to make volume names with a '%' in it work, there might be file systems which allow such volume names) in the title. If none found, goto end:
From the position of the last '%' go back one by one char until you find a space. If there is none, goto end:
If the char before the found space is not an additional space, goto end:
Volume name = Fist chars until, but excluding, the 2nd space found + ':'.


So now i update it to be like Joerg says:

.
    for(
int a=0lena++) 
    {
        if(
icon_name[a] == '%')
            for(
int b=0ab++)
                if(
icon_name[a-b] == '\x20')
                    if(
icon_name[a-b-1] == '\x20') {
                        
icon_name[a-b-1] = ':';
                        
icon_name[a-b] = '\x00';
                        
a=len;
                    }
    }


It seems to work fine with spaces now, but i not sure maybe this can be coded a bit better/faster.. With some inverted logic maybe, etc.

Quote:

Maybe some can also answer me a question about filer itself. What is the purpose of the SOURCE and DESTINATION. How do you use it as source or destination?


It for copy/move purposes only, so you need 2 at minimum (but can be more 3,4, etc.) different filers running, and you navigate between them to chose from which to which doing copy/move when need it (like Dopus5 in other words)


Edited by kas1e on 2023/12/20 14:58:48
Edited by kas1e on 2023/12/20 15:06:37
Edited by kas1e on 2023/12/20 15:07:38
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@Primax
Quote:

In the description of the OS4Depot archive, you should mention, that Filer is required and provide a link. Since this is not part of AmigaOS 4.


Isn't the first phrase in the README self-explained ?:) :

Quote:

WB2Filer is a hack which patch Intuition's functions via SetMethod() to allow transparently run of the Filer binary pointing to the given partition on Workbench's
Desktop instead of original Workbench windows.


The ones who didn't know what Filer is it and where to get it, probably have no needs in this hack as well.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@All
New version:

Quote:

-- code cleaning based on Joergs suggestions, thanks!
-- first os4depot release


Grab it from os4depot's upload query.

Then next few things about which i think which probably can be good to implement is:

1). Qualifier key which, once held, will allow running the same original WB window even when dbl-click on icons. This one probably needs to be configurable (so anyone can set a key he wants).

2) tooltype's support (so to be real true amiga app)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.8
Home away from home
Home away from home


@Joerg
Thanks, fixed all, only keep current way of SNprintF (it's just easy to understand what it does by looking on more "self-explained" version). At least for me of course when i will look at later :)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.7
Home away from home
Home away from home


@all
New version!

Quote:

-- fixed NULL pointer crash when we deselect WB Backdrop from the Workbench's menu and select it back by adding null pointer check on the nw->Title (which are NULL for pure NewWindow->Title when we back from)

-- replaced usage of C lib malloc and I/O based functions, incl. functions like strdup(), asnprintf(), etc., in the patched functions to AmigaOS4 native ones. Because patched functions running in foreign tasks may not have called the required C library setup to be able to use such functions in a thread safe way. Thanks to Joerg for pointing out on !

-- get rid of -lauto and open/close all the libraries manually

-- ditched completely newlib's startup code, and going true Amiga way:_start() instead of main(),obtaining of exec manually, etc. For such a hack where size and bloat are matter, this is the way to go.

-- replaced every C function on the Amiga native ones from dos, utility, intuition, and exec libraries.

-- switched to Amiga way of parsing argv/argc via ReadArgs()

-- binary builds now without "ld", just "gcc -S" to build assembler output, and then by "as" to build from assembler a ready binary.

-- all the above points reduced the size of binary even more (now it's 6kb only)


Grab it here: https://kas1e.mikendezign.com/aos4/wb2filer/WB2Filer_08.lha

Hope this one can fit os4depot if no bugs will be found, and it will work good enough.

If someone can go through code and check for mistakes/bad code style/ crap code, feel free of course, thanks !

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.7
Home away from home
Home away from home


@joerg
Thanks ! Fixed all!

Quote:

You can use simple C library string functions like strlen(), str(i)cmp(), strstr(), etc., just not string function which allocate memory (strdup(), asnprintf(), etc.).


Just already replaced everything and to make it all looks "in one style" want to get rid of "strstr()" and in whole want to get rid of whole newlib , just to be OS4 native only.. Maybe worth just implement it internally ? Like:

char *strstrOS4(const char *str, const char *substring)
{
    const 
char *a;
    const 
char *b;

    
/* First scan quickly through the two strings looking for a
     * single-character match.  When it's found, then compare the
     * rest of the substring.
     */

    
substring;
    if (*
== 0) {
        return (
char *) str;
    }

    for ( ; *
str != 0str += 1) {
        if (*
str != *b) {
            continue;
        }

        
str;
        while (
1) {
            if (*
== 0) {
                return (
char *) str;
            }
            if (*
a++ != *b++) {
                break;
            }
        }
        
substring;
    }

    return 
NULL;
}


Also do you aware of the replacement of newlibs/clib2 exit(0) ? Something like return(RETURN_OK); ?


I also want to ditch completely C lib, and wrote it as pure amigaos4 binary without C startup code. Maybe you aware how properly do it so to not be hardcoded to value 4, and so on ? Currently i just doing it like this:

#define __NOLIBBASE__
#define __NOGLOBALIFACE__

#include <proto/exec.h>
#include <proto/dos.h>

struct ExecBase *SysBase NULL;
struct ExecIFace *IExec NULL;
      
struct Library        *DOSBase NULL;
struct DOSIFace      *IDOS NULL;

int _start()
{

    if(
SysBase = *(struct ExecBase **)4) {        
        
IExec = (struct ExecIFace *)SysBase->MainInterface;
    }

    
    if(
DOSBase  IExec->OpenLibrary("dos.library"37)) {
        
IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase"main"1NULL); 
    }
        
    
IDOS->Printf("YEAAAH\n");


    if(
DOSBase) {
        
IExec->DropInterface((struct Interface *)IDOS);
        
IExec->CloseLibrary((struct Library *)DOSBase);
        
DOSBase NULL;
    }

    if(
IExec) {
        
IExec->DropInterface((struct Interface *)IExec);
    }

}


And i also need to get rid of main() then in favor of _start(), so probabaly need to switch to native ReadArgs() way ?


Edited by kas1e on 2023/12/16 7:39:41
Edited by kas1e on 2023/12/16 7:42:37
Edited by kas1e on 2023/12/16 9:43:37
Edited by kas1e on 2023/12/16 10:14:55
Edited by kas1e on 2023/12/16 13:10:05
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.7
Home away from home
Home away from home


@ktadd
You seem to download very old version, like the first ones or so (probably 03 one as the name of your folder suggest so) ?:) Display beep were dealt with long ago and selection of icon were removed too in favor of better and easy way: The version to check is 07 one currently.

@joerg
Quote:

Remove usage of malloc and I/O based functions, incl. functions like strdup(), asnprintf(), etc., in the patched functions.


Ok so:
asnprintf -> IUtility->SNPrintf()
strlen -> IUtility->StrLen()
stricmp -> IUtility->Stricmp()
strcmp -> IUtility->Stricmp() again (on os4 we anyway have no issues regarding the case)

but what about strstr() ?

Quote:

IUtility->SNPrintf().


Should't %c for this works as for asnprinf ? Just tried simple:

char command_line_test[1024];
    
int ret_test IUtility->SNPrintf(command_line_test,1024,"%c"'A');


And it printf nothing on serial, but for %s strings printing works.

Also, this buffer_size for the second argument is unknown when we use dinamic strings with char *, will 1024 fits in ? As i read OS4's SNPrintF add \0 anyway after adding necessary bits to the buffer, so probably limit to 1024 should fits just fine for the path to the Filer + name of partition ?

Quote:

For allocating memory only use IExec->AllocVecTags()/FreeVec()


Can i do :
char command_line_test[1024];
SNPrintF ....;
FreeVec(command_line_test);


? Or i had to allocate in any case with AllocVecTags instead of pure "char command_line[xxxx]" ?


Edited by kas1e on 2023/12/16 4:00:49
Edited by kas1e on 2023/12/16 4:05:48
Edited by kas1e on 2023/12/16 4:09:54
Edited by kas1e on 2023/12/16 4:12:16
Edited by kas1e on 2023/12/16 4:21:03
Edited by kas1e on 2023/12/16 4:27:53
Edited by kas1e on 2023/12/16 4:28:54
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.7
Home away from home
Home away from home


@balaton
Thanks for your inputs again :)

Quote:

Now that selList is gone and you don't need to free it at the end and just call Original_OpenWindowTagList(Self, nw, tagList) on error, you could get rid of the ok flag as well and write out return Original_OpenWindowTagList(Self, nw, tagList); everywhere. If you want to keep the flag and goto in case some clean up will be necessary in the future then use it consistently so also here should be goto end then:
if (strcmp(Caller->tc_Node.ln_Name, node->ln_Name) != 0) {
return Original_OpenWindowTagList(Self, nw, tagList);
}


Yes, want to keep goto way, it looks nicer and "goto end" sound self-explained too.

But why we need at end check on Called/Node names as well ? Because if we at end, we already checked if we should return original window or null ?


Quote:

you're probably modifying the window title with this;


Oh right, strtok() messed up the string we feed to by adding \0 where separator find! Maybe then just that:

// Find in string first space separator, replace it with ":" instead, and add \0 to finalize the string
    
    
char *icon_name nw->Title;
    
int len strlen(icon_name);
    
    for(
int a=0lena++)
    {    
        if(
icon_name[a] == '\x20') {
            
icon_name[a] = ':';
            
icon_name[a+1] = '\x00';
            
a=len;
        }            
    
    }
        
    if (!
icon_name || !icon_name[0] || icon_name[strlen(icon_name)-1] != ':') goto end;
    
    
char *command_line NULL;
    
    
int ret asprintf(&command_line"%s%c%c%s%c"filer_binary' ''"'icon_name'"');
    if (
ret 0) goto end;


? Simple and easy, no additional functions calls (only strlen), etc.

Quote:

At the beginning, checks are mixed up again, should be:
if (!nw || !(nw->Flags & WFLG_WBENCHWINDOW)) goto end;
struct Task *Caller = (struct Task *)IExec->FindTask(NULL);
if (!Caller || stricmp(Caller->tc_Node.ln_Name, "Workbench") != 0) goto end;
(or you can write it all in one line if you don't care about avoiding a call to FindTask when not needed or if you need to check Caller before window attributes).


Yeah, i specially doing so, because there is a problem : the AsyncWB window is not WFLG_WBENCHWINDOW, and not Workbench name, and have no newWindow struct, but, do have a task and name of task. So i had to change the order to firstly find a task, check if the name is AsyncWB, and mark it that next window will be "original" one, and only then do other kind of checks.


But it's all looks ugly indeed. Maybe ditch this whole AsyncWB thing and let it be "Filer" when run WBRun from ?

Quote:

- The skip_AsyncWB may have same problem as suppressing next beep but unlike that it may cause problems here. What happens if you run multiple wbrun commands e.g. from a script at the same time or quickly one after the other? Is there a better way to identify call after AsyncWB?


Dunno, i just found that when you hit "amiga+e" we do have 2 openwindowcalls() , one to call "AsyncWB - textinput process", which have no NW, no "Workbench", and no WFLG_WBENCHWINDOW, and then our OpenWindowTagList() which we need to handle. But then it's still ugly and add unnecessary all-the-time checks when not need it..

@khayoz

Yeah, there were missing null pointer check, try this one in meantime: https://kas1e.mikendezign.com/aos4/wb2 ... WB2Filer_pre08_binary.zip


Edited by kas1e on 2023/12/15 2:33:39
Edited by kas1e on 2023/12/15 2:35:19
Edited by kas1e on 2023/12/15 2:57:37
Edited by kas1e on 2023/12/15 3:04:59
Edited by kas1e on 2023/12/15 3:19:39
Edited by kas1e on 2023/12/15 9:05:13
Edited by kas1e on 2023/12/15 9:06:22
Edited by kas1e on 2023/12/15 9:14:05
Edited by kas1e on 2023/12/15 10:56:42
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.7
Home away from home
Home away from home


@msteed
Quote:

Just noticed: When WB2Filer is running, switching the Workbench background from a backdrop window to a regular window and then back again causes a crash (a DSI in the OpenWindowTagList() patch). Perhaps because there's no window title?


Yeah exactly :) Already fixed just hold for next one (maybe Balaton will check if i introduce some crap code again:) )

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.6
Home away from home
Home away from home


@All
New version !

Quote:

v.07 (14.12.2023)

-- totaly rewrote logic of patch: now instead of WB's WorkbenchControl() and manual icon selection,we simply based on window title names. This simplify patch a lot and make it work much better in all situations (thanks Joerg)

-- get rid of WFLG_BACKDROP check as struct *NewWindow never had WFLG_BACKDROP (joerg)

-- code cleaning by Balaton's suggestions (simplify DISK icon check, remove some nested ifs and indentation for readability, vars renaming, simplification of code, etc.)

-- added check on ActiveWindow to distinguish between main desktop and other windows more when want to have original Workbench windows while run wbrun from shell or from Filer's "Open Workbench"

-- added check on "Amiga+e" window (AsynWB - texinput process) : so when we hit "Amiga+e" we are able to do "wbrun" from it to have Original WB window.

-- rewrote README and made another version in true amiga.guide format

-- cosmetic fixes for the icons (thanks msteed for note)



There is: https://kas1e.mikendezign.com/aos4/wb2filer/WB2Filer_07.lha


Edited by kas1e on 2023/12/14 5:46:41
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.6
Home away from home
Home away from home


@joerg
Quote:

You are checking the wrong one again
If NewWindow->Title


As always, you are right :) Yeah, now i have proper lines for:

Quote:

Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = RAM Disk 100% full, 0B free, 47.9KB in use
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = sfs2 63% full, 6,252.1MB free, 10.3GB in use
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = Work 38% full, 310.8GB free, 189.9GB in use
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = Public 1% full, 37.2GB free, 288.7MB in use
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = System 1% full, 198.3GB free, 2,237.3MB in use
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
nw->Title = morphos 0% full, 12.5GB free, 3,295KB in use


Now need to think about proper way to parse the disk names: as i see, there are 2 spaces between disk names and numbers, but then, there can be situation when a disk name by itself have many spaces in (2 or more), so to parse on just spaces is no way.

And can't those "titles" be changed by GUI/workbench prefs by the way ?


@All
The easy way i go now is just:

// check if title of window have 2 spaces , at least one "," and one "%", then this is DISK.
    
if (!strstr(nw->Title,"  ") && !strstr(nw->Title,",") && !strstr(nw->Title,"%")) {
        goto 
end;
    }

    
// split string by first space separator and add ":" at end
    
char *icon_name;
    
icon_name strtok(nw->Title" ");
    
strcat(icon_name,":");


So all works fine, but then, we can't handle names with spaces, so no RAM DISK, but at least RAM: works too :)

And question still are : what should we do in other 4 cases which is not dbl-clicks, i mean : when run wbrun from shell, when run wbrun from "amiga+e", and when call workbenchs "Open Volumes" and "Open".

Imho we can keep filler for: 1)dbl-click 2). "Open Volumes" 3). "Open". But for 3 others like "amiga+e / wbrun" , "shell/wbrun" and "filler's open wb folder" - original WB window.

What you think ?


Edited by kas1e on 2023/12/13 18:26:23
Edited by kas1e on 2023/12/13 18:31:02
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.6
Home away from home
Home away from home


@All
So, that what we have:

1. When we dbl-click desktop disks :

Quote:

Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
ActiveWindow->Title = (null)
ActiveWindow->node->ln_Name = Workbench
WFLG_BACKDROP!



2. When we multiselect 2 icons, let's say RAM: and SFS2: and then dbl-click them, then:

Quote:

Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
ActiveWindow->Title = (null)
ActiveWindow->node->ln_Name = Workbench
WFLG_BACKDROP!
Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
ActiveWindow->Title = RAM Disk 100% full, 0B free, 47.9KB in use
ActiveWindow->node->ln_Name = Workbench


So null for first openwindowtaglist(), and then as opened window start to be active by default, title of already opened (auto-active) one.


In other words, first icon = NULL for title (workbench's one), then second icon, title of the active window (which is one opened before). Dunno if we can use Title then somehow ?


PS. found a way how to differ between workbench and amiga+e : by checking on the task name which is "AsyncWB - textinput", and deselect icons from desktop. It works, but not sure if localizations take place there or not, hope not.

Also, we need to sort the things how it better to react, i mean what to do when:

1). when dbl-click on icon on desktop
2). when run "wbrun" from shell
3). when run "wbrun" from amiga+e
4). when do "open" for selected icon
5). when do "open volume"


I think it should be like:

1). when dbl-click on icon on desktop - Filer
2). when run "wbrun" from shell - original WB window
3). when run "wbrun" from amiga+e - original WB window
4). when do "open" for selected icon - Filer
5). when do "open volume" - ?


Just to sort it all how it should be, and then one by one, deal with.


Edited by kas1e on 2023/12/13 10:03:39
Edited by kas1e on 2023/12/13 10:04:17
Edited by kas1e on 2023/12/13 10:05:13
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top


Re: wb2filer v0.6
Home away from home
Home away from home


@joerg
Quote:

To check if something was called from the Workbench backdrop window you'd have to use (ActiveWindow->Flags & WFLG_BACKDROP) instead.


You were right as always, yeah, now i can see that WFLG_BACKDROP is set for Workbench.

Do you aware of any way, how i can dereference when icon on the workbench selected (so active window is workbench) and then i hit "amiga+e" , and type there "wbrun something:", and while icon is selected on workbench, it's "workbench", but i need to detect somehow that with this "amiga+e/wbrun" combo it's not usual "click on workbench's desktop icon".

Im not sure if it possible to trace a command from which OpenWindowTagList() were called ? Because when we do "amiga+e", all i have is :

Quote:

Task->tc_Node.ln_Name is AsyncWB - textinput process
NW is NULL


So far looks good, but then, when i type there "wbrun ram:", it then:

Quote:

Task->tc_Node.ln_Name is Workbench
It's WBENCHWINDOW
ActiveWindow->node->ln_Name = Workbench
WFLG_BACKDROP!

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top



TopTop
« 1 2 (3) 4 5 6 ... 422 »




Powered by XOOPS 2.0 © 2001-2023 The XOOPS Project