[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <devices/keymap.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/dos_pragmas.h>

#include "loadkeymap.h"


/*****************************************************************************/


extern struct Library *SysBase;
extern struct Library *UtilityBase;
extern struct Library *DOSBase;


/*****************************************************************************/


/* Case-insensitive version of FindName() */
static struct Node *FindNameNC(struct List *list, STRPTR name)
{
struct Node *node;
WORD         result;

    node = list->lh_Head;
    while (node->ln_Succ)
    {
        result = Stricmp(name,node->ln_Name);
        if (result == 0)
            return(node);

        node = node->ln_Succ;
    }

    return(NULL);
}


/*****************************************************************************/


struct KeyMap *LoadKeyMap(STRPTR name)
{
BPTR                   segment;
struct KeyMapResource *kr;
struct KeyMapNode     *kn;
STRPTR                 base;

    kn      = NULL;
    segment = NULL;

    /* open the keymap resource, in order to gain access to the keymap list */
    if (kr = (struct KeyMapResource *)OpenResource("keymap.resource"))
    {
        segment = NULL;
        base = FilePart(name);

        /* must access the list under Forbid() */
        Forbid();

        /* is the keymap we want already on the keymap list? */
        if (!(kn = (struct KeyMapNode *)FindNameNC(&kr->kr_List,base)))
        {
            /* if not on the keymap list, try loading it */
            if (segment = LoadSeg(name))
            {
                /* see if someone added it to the keymap list while we were
                 * doing a LoadSeg() (which broke Forbid() )
                 */
                if (!(kn = (struct KeyMapNode *)FindNameNC(&kr->kr_List,base)))
                {
                    kn = (struct KeyMapNode *)((segment << 2) + sizeof(BPTR));

                    /* we've loaded a keymap file. Do a few sanity checks
                     * to make sure it is a keymap, and not some bogus
                     * load file
                     */
                    if (TypeOfMem(kn->kn_Node.ln_Name)
                    &&  Stricmp(name,kn->kn_Node.ln_Name))
                    {
                        /* add to the system's keymap list */
                        AddHead(&(kr->kr_List),(struct Node *)kn);
                    }
                    else
                    {
                        /* bogus load file! Get rid of it and fail */
                        UnLoadSeg(segment);
                        kn = NULL;
                    }
                }
                else
                {
                    /* the keymap was added to the list behind our back!
                     * Free what was loaded and return happily
                     */
                    UnLoadSeg(segment);
                }
            }
        }

        /* get out of forbidden state */
        Permit();
    }

    if (kn)
        return(&kn->kn_KeyMap);

    return(NULL);
}