/*-*-C-*-
 * Help request processing for shell
 */


#include "resed.h"
#include "main.h"

#include "swicall.h"
#include "wimp.h"
#include "resformat.h"
#include "newmsgs.h"

#include "menu.h"
#include "registry.h"

#include "class.h"
#include "document.h"
#include "help.h"



/*
 * Look up the help text 'token' in the messages file.
 *
 * If the token is found, its text is copied to 'buf' and the result is TRUE.
 * If not, the result is FALSE.
 *
 * At most 'n' characters are copied to buf, which is guaranteed always to
 *  have a null terminator.
 */

Bool help_lookup_token (char *token, char *buf, int len)
{
    char *text = message_lookup (&msgs, token);

    if (text == token)    /* token not found in messages file */
        return FALSE;

    strncpy (buf, text, len-1);
    buf[len-1] = 0;

    return TRUE;
}


/*
 * Generate help text string for an icon in a dialogue box.
 *
 * Tokens are looked up in the messages file in the following order; the
 *  first one found is returned as the help message:
 *
 *     Hlp.W<n>.<icon-name>
 *     Hlp.<icon-name>
 *     Hlp.W<n>
 *
 *  where <n> is the dbox's registered type, and <icon-name> is the !WinEdit
 *  name of the icon.
 *
 * If no text is found, the result is FALSE.
 */

static Bool help_text_for_dbox (
    RegistryType type,
    int w,
    int icon,
    char *reply
)
{
    char tag[50], token[50];

    wimp_read_icon_name (w, icon, tag);

    if (*tag != 0)   /* icon has a name */
    {
        sprintf (token, "Hlp.W%d.%s", type, tag);
        if (help_lookup_token (token, reply, MAX_HELP_TEXT))
            return TRUE;

        sprintf (token, "Hlp.%s", tag);
        if (help_lookup_token (token, reply, MAX_HELP_TEXT))
            return TRUE;
    }

    sprintf (token, "Hlp.W%d", type);
    return help_lookup_token (token, reply, MAX_HELP_TEXT);
}


/*
 * Generate help text for the current menu entry.
 *
 * This is done by looking up tokens in the following order; the first found
 *  is returned as the help text:
 *
 *    Hlp.M<n>.h1.h2.h3
 *    Hlp.M<n>.h1.h2
 *    Hlp.M<n>.h1
 *    Hlp.M<n>
 *
 *  where <n> is the registered MenuType, and h1.h2.h3... is the "hit list".
 *
 * Result is TRUE iff a string matching this token is found in the messages
 *  file.
 */

static Bool help_text_for_menu_entry (char *reply)
{
    int buf[10];
    int *p = buf;
    char *s = reply;
    char *text;
    int type;

    /* determine state of current menu (if any) */
    if (swi (Wimp_GetMenuState, R0, 0, R1, buf, END) != NULL || *buf == -1)
        return FALSE;

    /* lookup type of current menu */
    type = menu_lookup_type ();
    if (type == UNKNOWN_MENU)
        return FALSE;

    /* construct tag */
    sprintf (reply, "Hlp.M%d", type);
    s = reply + 3;   /* points to first separator */
    while (*p != -1)
    {
        s += strlen(s);
        sprintf(s, ".%d", *p);
        p++;
    }

    /* lookup message text */
    while (TRUE)
    {
        text = message_lookup (&msgs, reply);

        if (text != reply)
            break;

        /* remove final component and try again */
        *s = 0;
        while (s != reply && *s != '.')
            s--;

        if (s == reply)
            return FALSE;
    }

    strcpy (reply, text);
    return TRUE;
}


/*
 * Turn a help message around.
 */

error * help_message (MessageHelpRequestPtr req)
{
    MessageHelpReplyPtr reply = (MessageHelpReplyPtr) req;
    RegistryType type;
    int w = req->mouse.windowhandle;
    int icon = req->mouse.iconhandle;

    if (w == -2)  /* pointer on icon bar */
    {
        if (icon == iconhandle)  /* our application icon */
        {
            if (!help_lookup_token ("Hlp.Icon", reply->help, MAX_HELP_TEXT))
                return NULL;
        }
        else
            return NULL;
    }

    else
    if (w == -1)  /* it's not in a window */
        return NULL;

    else          /* it's in a window */
    {
        void *closure;

        /* find out which kind of window */
        type = registry_lookup_window (w, &closure);

        switch (type)
        {
        case Unknown:    /* probably in a menu */
            if (!help_text_for_menu_entry (reply->help))
                return NULL;
            break;

        case Document:   /* document window or palette */
            if (!document_help_text ((DocumentPtr)closure,
                                        &req->mouse.position, reply->help))
                return NULL;
            break;

        default:         /* dialogue boxes */
            if (!help_text_for_dbox (type, w, icon, reply->help))
                return NULL;
            break;
        }
    }

    /* construct and send reply */
    reply->header.yourref = req->header.myref;
    reply->header.messageid = MESSAGE_HELP_REPLY;
    reply->header.size = (sizeof(MessageHeaderRec) +
                               strlen(reply->help) + 4) & ~3;

    return swi (Wimp_SendMessage,  NONX,
                R0, EV_USER_MESSAGE,
                R1, reply,
                R2, req->header.taskhandle,  END);
}
