/*
    UHWIF.C

Started by DavidW, 8/11/91

Utility layer of hwif

*/

#include <p_std.h>
#include <p_gen.h>
#include <p_file.h>
#include <p_cons.h>
#include <wlib.h>
#include <hwif.h>

GLREF_D UWORD DatLocked;

GLREF_D WSERV_SPEC *wserv_channel;
GLREF_D VOID *winHandle;
GLREF_D UWORD _UseFullScreen;
GLDEF_D UWORD _S3UseFullScreen;

GLREF_D TEXT ** _cmds;
GLREF_D H_MENU_DATA * _mdata;

LOCAL_C VOID Check(INT val)
    {
    if (val)
        p_exit(val);
    }

GLDEF_C VOID uCommonInit(VOID)
    {
    INT val;
    UINT func;
    CONSOLE_INFO cinfo;
    W_WINDATA wd;

    p_linklib(0);
    if (winHandle)
        {
        val=FALSE;
        func=P_SCR_CURSOR;
        Check(p_iow4(winHandle,P_FSET,&func,&val));
        goto exit;
        }
    Check(p_open(&winHandle,"CON:",0));
    if (_UseFullScreen || _S3UseFullScreen)
        {
        if ((wserv_channel->conn.info.version_id&WS_VERSION_MASK)
                                                            <WS_VERSION_4)
            _UseFullScreen=FALSE;
        else
            {
            val=0;
            if (_S3UseFullScreen)
                val=W_CTBY_S3_SCR;
            func=P_SCR_COMPATIBILITY;
            Check(p_iow4(winHandle,P_FSET,&func,&val));
            }
        }
    p_iow3(winHandle,P_FINQ,&cinfo);
    wd.extent.tl.x=wd.extent.tl.y=0;
    wd.extent.width=(wserv_channel->conn.info.pixels.x+1)/cinfo.char_width;
    wd.extent.height=(wserv_channel->conn.info.pixels.y+1)/cinfo.line_height;
    func=P_SCR_WSET;
    Check(p_iow4(winHandle,P_FSET,&func,&wd.extent));
    wd.extent.width=wserv_channel->conn.info.pixels.x;
    wd.extent.height=wserv_channel->conn.info.pixels.y;
    wSetWindow(cinfo.window_handle,W_WIN_EXTENT,&wd);
    Check(wCheckPoint());
exit:
    hIFInit(winHandle);
    }

GLDEF_C VOID uEnableGrey(VOID)
    {
    UINT func;
    UINT flags;

    func=P_SCR_GREY;
    flags=TRUE;
    Check(p_iow4(winHandle,P_FSET,&func,&flags));
    }

GLDEF_C VOID uGetKey(WMSG_KEY *pkey)
    {
    p_iow3(winHandle,P_EVENT_READ,pkey);
    }

GLDEF_C VOID uGetKeyA(WORD *pstat,WMSG_KEY *pkey)
    {
    p_ioc4(winHandle,P_EVENT_READ,pstat,pkey);
    }

GLDEF_C VOID uCancelGetKeyA(VOID)
    {
    p_iow2(winHandle,P_FCANCEL);
    }

GLDEF_C INT uKeyPressOutstanding(VOID)
    {
    UWORD flag;

    p_iow3(winHandle,P_FTEST,&flag);
    return(flag);
    }

GLDEF_C VOID uEscape(UWORD flag)
    {
    UINT func;

    func=P_SCR_ESCAPE;
    p_iow4(winHandle,P_FSET,&func,&flag);
    }

GLDEF_C UINT uFindMainWid(VOID)
    {
    CONSOLE_INFO info;

    p_iow3(winHandle,P_FINQ,&info);
    return(info.window_handle);
    }

GLDEF_C VOID uForceToFront(VOID)
    {
    wClientPosition(0,0);
    wFlush();
    }

GLDEF_C VOID uErrorString(TEXT *message)
    {
    uForceToFront();
    DatLocked++;
    wsAlertW(WS_ALERT_CLIENT,0,message,0);
    DatLocked--;
    }

GLDEF_C INT uErrorValue(INT ret)
    {
    TEXT buf[64];

    if (ret)
        {
        p_errs(&buf[0],ret);
        uErrorString(&buf[0]);
        }
    return(ret);
    }

GLDEF_C VOID *uCheckHandle(VOID *hand)
    {
    if (!hand)
        uErrorValue(E_GEN_NOMEMORY);
    return(hand);
    }

GLDEF_C VOID uZTStoBCS(TEXT *bcs,TEXT *zts)
    {
    p_bcpy(bcs+1,zts,*bcs=p_slen(zts));
    }

GLDEF_C INT uOpenDialog(TEXT *title)
    {
    TEXT buf[64];

    if (title)
        {
        uZTStoBCS(&buf[0],title);
        title=(&buf[0]);
        }
    return(uErrorValue(hDlgOpen(title)));
    }

GLDEF_C INT uAddDialogItem(INT type,TEXT *prompt,VOID *data)
    {
    TEXT buf[64];

    if (prompt)
        {
        uZTStoBCS(&buf[0],prompt);
        prompt=(&buf[0]);
        }
    return(uErrorValue(hDlgAdd(type,prompt,data)));
    }

GLDEF_C INT uRunDialog(VOID)
    {
    INT ret;

    DatLocked++;
    ret=hDlgRun();
    DatLocked--;
    if (ret<0)
        uErrorValue(ret);
    return(ret);
    }

GLDEF_C INT CDECL uAddButtonList(TEXT *but,INT code,...)
    {
    TEXT buf[40];
    INT count;
    TEXT **pbut;
    INT *pcode;
    VOID *buts;

    buts=uCheckHandle(hButtonOpen());
    if (!buts)
        return(-1);
    count=1;
    pbut=(&but);
    pcode=(&code);
    while (*pbut)
        {
        uZTStoBCS(&buf[0],*pbut);
        if (uErrorValue(hButtonAdd(buts,count++,*pcode,&buf[0])))
            goto CleanUp;
        pcode+=2;
        pbut+=2;
        }
    if (!uAddDialogItem(H_DIALOG_BUTTONS,0,(VOID *)buts))
        return(0);
CleanUp:
    hButtonClose(buts);
    return(-1);
    }

GLDEF_C INT uBeginDCL(H_DI_CHOICE *pch)
    {
    pch->u.count=1;
    pch->menu=uCheckHandle(hChoiceOpen());
    return(!(INT)pch->menu);
    }

GLDEF_C INT uGrowDCL(H_DI_CHOICE *pch,TEXT *choice)
    {
    TEXT buf[64];

    uZTStoBCS(&buf[0],choice);
    if (!uErrorValue(hChoiceAdd(pch->menu,pch->u.count++,&buf[0])))
        return(0);
    hChoiceClose(pch->menu);
    return(-1);
    }

GLDEF_C INT uAddDCL(TEXT *prompt,UWORD *nsel,H_DI_CHOICE *pch)
    {
    pch->u.sel=nsel;
    if (!uAddDialogItem(H_DIALOG_CHOICE,prompt,pch))
        return(0);
    hChoiceClose(pch->menu);
    return(-1);
    }

GLDEF_C INT CDECL uAddChoiceList(TEXT *prompt,UWORD *nsel,TEXT *choice,...)
    {
    TEXT **pchoice;
    H_DI_CHOICE ch;

    if (uBeginDCL(&ch))
        return(-1);
    pchoice=(&choice);
    while (*pchoice)
        {
        if (uGrowDCL(&ch,*pchoice++))
            return(-1);
        }
    return(uAddDCL(prompt,nsel,&ch));
    }

GLDEF_C INT uLocateCommand(INT accel)
    {
    INT i;
    TEXT **pcmd;
    TEXT *cmd;

    i=0;
    pcmd=_cmds;
    while ((cmd=*pcmd++)!=0)
        {
        if (*cmd==accel)
            return(i);
        i++;
        }
    return(-1);
    }

GLDEF_C INT uPresentMenus(VOID)
    {
    INT ret;
    VOID *card[16];
    VOID *loc;
    INT cardindex;
    TEXT **pcmd;
    TEXT *cmd;
    H_MENU_DATA *mdata;
    INT pos;
    INT nitems;
    TEXT buf[64];

    if (uErrorValue(hMenuOpen()))
        return(0);
    mdata=_mdata;
    pcmd=_cmds;
    cardindex=0;
    while (mdata->title)
        {
        loc=uCheckHandle(hCardOpen());
        if (!loc)
            goto TidyUp;
        card[cardindex++]=loc;
        nitems=mdata->nlines;
        pos=1;
        while (nitems--)
            {
            cmd=(*pcmd++);
            uZTStoBCS(&buf[0],cmd+1);
            if (uErrorValue(hCardAdd(loc,pos++,*cmd,&buf[0])))
                goto TidyUp;
            }
        uZTStoBCS(&buf[0],mdata->title);
        if (uErrorValue(hMenuAdd(&buf[0],loc)))
            goto TidyUp;
        mdata++;
        }
    DatLocked++;
    ret=hMenuRun();
    DatLocked--;
    if (ret>=0)
        goto CleanUp;
    uErrorValue(ret);
TidyUp:
    hMenuClose();
    ret=0;
CleanUp:
    while (cardindex)
        hCardClose(card[--cardindex]);
    return(ret);
    }

GLDEF_C VOID uAddGreyUline(UBYTE accel,UWORD *plines)
    {
    *(plines+(accel/16))|=(1<<(accel%16));
    }

GLDEF_C INT CDECL uDialogMenu(TEXT *title,TEXT *pb,...)
    {
    TEXT **ppb;
    H_DI_TEXT txt;
    TEXT buf[64];

    if (uOpenDialog(title))
        return(0);
    txt.type=H_DTEXT_ALIGN_LEFT|H_DTEXT_SELECTABLE;
    txt.str=(&buf[0]);
    ppb=(&pb);
    while (*ppb)
        {
        uZTStoBCS(&buf[0],*ppb++);
        if (uAddDialogItem(H_DIALOG_TEXT," ",&txt))
            return(0);
        }
    return(uRunDialog());
    }

GLDEF_C VOID CDECL uDisplayText(TEXT *pb,...)
    {
    TEXT **ppb;
    H_DI_TEXT txt;
    TEXT buf[64];

    if (uOpenDialog(NULL))
        return;
    txt.type=H_DTEXT_ALIGN_LEFT;
    txt.str=(&buf[0]);
    ppb=(&pb);
    while (*ppb)
        {
        uZTStoBCS(&buf[0],*ppb++);
        if (uAddDialogItem(H_DIALOG_TEXT,NULL,&txt))
            return;
        }
    uRunDialog();
    }
