/*
    NOTES.C

Written by DavidW
Started on 17/12/91

*/

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


LOCAL_D TEXT *cmds[]=
    {
    "aNew note",
    "jInsert note",
    "kCopy note",
    "dDelete note",
    "iInsert text",
    "cCopy text",
    "vEvaluate",
    "zSum",
    "rRecord",
    "uUndo",
    "tTitle window",
    "nNotes window",
    "fFind window",
    "oOptions",
    "sSearch forwards",
    "bSearch backwards",
    "qSearch first",
    "lSearch last",
    "+Set",
    "-Clear",
    "*Tag all",
    "/Clear all",
    "gGo to",
    "mMove to",
    "hShow symbols",
    "pPrint",
    "yPrint setup",
    "xExit",
    NULL
    };

#define NOTES_ITEMS     4
#define EDIT_ITEMS      6
#define WINDOW_ITEMS    3
#define SEARCH_ITEMS    5
#define TAG_ITEMS       4
#define SPECIAL_ITEMS   6

#define ITEMS_BEFORE_NOTES      0
#define ITEMS_BEFORE_EDIT       NOTES_ITEMS
#define ITEMS_BEFORE_WINDOW     (ITEMS_BEFORE_EDIT+EDIT_ITEMS)
#define ITEMS_BEFORE_SEARCH     (ITEMS_BEFORE_WINDOW+WINDOW_ITEMS)
#define ITEMS_BEFORE_TAG        (ITEMS_BEFORE_SEARCH+SEARCH_ITEMS)
#define ITEMS_BEFORE_SPECIAL    (ITEMS_BEFORE_TAG+TAG_ITEMS)

#define SYMBOLS_ITEM        ITEMS_BEFORE_SPECIAL+2

LOCAL_D H_MENU_DATA mdata[]=
    {
    "Notes",NOTES_ITEMS,
    "Edit",EDIT_ITEMS,
    "Windows",WINDOW_ITEMS,
    "Search",SEARCH_ITEMS,
    "Tag",TAG_ITEMS,
    "Special",SPECIAL_ITEMS,
    NULL
    };

GLDEF_D TEXT ** _cmds=(&cmds[0]);
GLDEF_D H_MENU_DATA * _mdata=(&mdata[0]);


LOCAL_D UINT MainWid;

typedef struct
    {
    UBYTE len;
    TEXT *buf;
    } LENBUF;

typedef struct
    {
    LENBUF title;
    LENBUF note;
    UWORD tagged;
    } NOTE;

LOCAL_D NOTE index[99];
LOCAL_D WORD count=1;
LOCAL_D WORD where;

LOCAL_D WORD changed=TRUE;

LOCAL_D VOID *edit[3];
LOCAL_D UWORD show_statwin=TRUE;
LOCAL_D UWORD ScreenWidth;
LOCAL_D INT emph=0;

LOCAL_D INT sumflag='=';
LOCAL_D INT sumndp=2;

LOCAL_D NOTE clip;

LOCAL_D UWORD PrintTagsOnly;
LOCAL_D UWORD PrintRec;
LOCAL_D UWORD PrintState;
LOCAL_D TEXT *PrintBuf;
LOCAL_D WORD PrintLen;
LOCAL_D UWORD PrintCount;
LOCAL_D UWORD PrintNewPage=1;

LOCAL_D UWORD casesens=1;
LOCAL_D UWORD findtype=1;
LOCAL_D TEXT *pattern;
LOCAL_D WORD pattlen;

LOCAL_D UWORD ShowSymbols=FALSE;

LOCAL_D TEXT FindStack[6][21];
LOCAL_D WORD FindSP=0;

LOCAL_D UWORD tly[]={0,17,65};
LOCAL_D UWORD bry[]={15,62,80};

LOCAL_C VOID DrawBorder(INT i)
    {
    P_RECT rect;

    rect.tl.x=(i? 0: 8);
    rect.br.x=ScreenWidth;
    if (i==2)
        rect.br.x-=30;
    rect.tl.y=tly[i];
    rect.br.y=bry[i];
    gBorderRect(&rect,
            W_BORD_CORNER_4|W_BORD_SHADOW_S|(i==emph? W_BORD_SHADOW_ON: 0));
    hEBEmphasise(edit[i],i==emph);
    }

LOCAL_C VOID RotateTo(INT newemph)
    {
    INT oldemph;

    if (newemph!=emph)
        {
        oldemph=emph;
        emph=newemph;
        DrawBorder(oldemph);
        DrawBorder(newemph);
        }
    }

LOCAL_C INT CheckEditing(VOID)
    {
    if (emph==1)
        return(0);
    wInfoMsg("Only available in notes window");
    return(-1);
    }

LOCAL_C INT RecordChange(VOID *ebH,LENBUF *lb)
    {
    TEXT *buf;
    INT len;
    TEXT *newbuf;

    if (!hEBSenseChanged(ebH))
        return(0);
    buf=hEBSenseText(ebH);
    len=p_slen(buf);
    newbuf=p_realloc(lb->buf,len);
    if (!newbuf)
        {
        wInfoMsg("No memory to store changes in note");
        return(-1);
        }
    lb->buf=newbuf;
    lb->len=len;
    p_bcpy(newbuf,buf,len);
    hEBClearChanged(ebH);
    return(0);
    }

LOCAL_C INT RecordChanges(VOID)
    {
    return(RecordChange(edit[0],&index[where].title)
                            || RecordChange(edit[1],&index[where].note));
    }

LOCAL_C VOID DrawWhereAndCount(VOID)
    {
    TEXT buf[10];
    P_RECT box;

    p_atos(&buf[0],"%d/%d",where+1,count);
    box.tl.x=ScreenWidth-30;
    box.br.x=ScreenWidth;
    box.tl.y=67;
    box.br.y=77;
    gPrintBoxText(&box,8,G_TEXT_ALIGN_CENTRE,0,&buf[0],p_slen(&buf[0]));
    }

LOCAL_C VOID DrawTagStatus(VOID)
    {
    P_RECT box;

    box.tl.y=2;
    box.br.y=12;
    box.tl.x=0;
    box.br.x=8;
    gPrintBoxText(&box,8,G_TEXT_ALIGN_LEFT,0,"\014",index[where].tagged);
    }

LOCAL_C INT LoadEditors(VOID)
    {
    if (hEBSetText(edit[0],index[where].title.buf,index[where].title.len))
        return(-1);
    hEBClearChanged(edit[0]);
    if (hEBSetText(edit[1],index[where].note.buf,index[where].note.len))
        return(-1);
    hEBClearChanged(edit[1]);
    DrawWhereAndCount();
    DrawTagStatus();
    return(0);
    }

LOCAL_C INT LocateNewWhere(VOID)
    {
    if (index[where].title.len || index[where].note.len)
        {
        if (count==99)
            {
            wInfoMsg("Maximum number of notes reached");
            return(-1);
            }
        where=count++;
        }
    return(0);
    }

LOCAL_C VOID StartNewNote(VOID)
    {
    if (RecordChanges())
        return;
    if (LocateNewWhere())
        return;
    if (LoadEditors())
        return;
    RotateTo(0);
    }

LOCAL_C INT CheckChanged(VOID)
    {
    if (!hEBSenseChanged(edit[0]) && !hEBSenseChanged(edit[1]))
        {
        wInfoMsg("Not changed");
        return(-1);
        }
    return(0);
    }

LOCAL_C VOID RecordNote(VOID)
    {
    if (CheckChanged())
        return;
    if (RecordChanges())
        return;
    wInfoMsg("Note recorded");
    }

LOCAL_C INT RunDialog(VOID)
    {
    INT ret;

    hEBEmphasise(edit[emph],FALSE);
    ret=uRunDialog();
    hEBEmphasise(edit[emph],TRUE);
    return(ret);
    }

LOCAL_C INT Confirm(TEXT *pb)
    {
    if (uOpenDialog(pb))
        return(-1);
    if (uAddButtonList("No",-'n',"Yes",'y',NULL))
        return(-1);
    return(RunDialog()!='y');
    }

LOCAL_C VOID UndoEditing(VOID)
    {
    if (CheckChanged())
        return;
    if (Confirm("Undo editing"))
        return;
    LoadEditors();
    }

LOCAL_C VOID GoToNote(VOID)
    {
    LONG newwhere;
    H_DI_NUMBER num;

    newwhere=where+1;
    if (uOpenDialog("Go to"))
        return;
    num.value=(&newwhere);
    num.low=1;
    num.high=count;
    if (uAddDialogItem(H_DIALOG_NUMBER,"Note number",&num))
        return;
    if (RunDialog()<=0)
        return;
    if (RecordChanges())
        return;
    where=(INT)newwhere-1;
    LoadEditors();
    }

LOCAL_C VOID MoveNote(VOID)
    {
    LONG newwhere;
    H_DI_NUMBER num;
    INT neww;
    INT tomove;
    NOTE moving;
    NOTE *targ;
    NOTE *src;

    newwhere=1;
    if (uOpenDialog("Move note"))
        return;
    num.value=(&newwhere);
    num.low=1;
    num.high=count;
    if (uAddDialogItem(H_DIALOG_NUMBER,"New note number",&num))
        return;
    if (RunDialog()<=0)
        return;
    neww=(INT)newwhere-1;
    tomove=(neww-where)*sizeof(NOTE);
    if (!tomove)
        return;
    moving=index[where];
    targ=(&index[where]);
    src=targ+1;
    if (tomove<0)
        {
        src=(&index[neww]);
        targ=src+1;
        tomove=(-tomove);
        }
    p_bcpy(targ,src,tomove);
    index[neww]=moving;
    where=neww;
    DrawWhereAndCount();
    }

LOCAL_C INT AddCentredTextItem(TEXT *pb)
    {
    H_DI_TEXT txt;
    TEXT buf[64];

    txt.type=H_DTEXT_ALIGN_CENTRE;
    txt.str=(&buf[0]);
    uZTStoBCS(&buf[0],pb);
    return(uAddDialogItem(H_DIALOG_TEXT,NULL,&txt));
    }

LOCAL_C VOID SumData(VOID)
    {
    TEXT flag[2];
    H_DI_EDIT ed;
    LONG newndp;
    H_DI_NUMBER num;
    WORD datacount;
    INT badcount;
    DOUBLE datasum;
    DOUBLE value;
    TEXT *pb;
    INT ind;
    TEXT buf[30];
    P_DTOB dtob;

    if (uOpenDialog("Sum data"))
        return;
    flag[0]=1;
    flag[1]=(BYTE)sumflag;
    ed.len=1;
    ed.str=(&flag[0]);
    if (uAddDialogItem(H_DIALOG_EDIT,"Sum values flagged by",&ed))
        return;
    newndp=sumndp;
    num.value=(&newndp);
    num.low=0;
    num.high=10;
    if (uAddDialogItem(H_DIALOG_NUMBER,"Number of dec places",&num))
        return;
    if (RunDialog()<=0)
        return;
    sumndp=(INT)newndp;
    if (flag[1])
        sumflag=flag[1];
    datacount=0;
    badcount=0;
    p_itof(&datasum,&datacount);
    pb=hEBSenseText(edit[1]);
    FOREVER
        {
        ind=p_sloc(pb,sumflag);
        if (ind<0)
            break;
        pb+=ind+1;
        if (p_stod(&pb,&value,'.'))
            badcount++;
        else
            {
            datacount++;
            p_fadd(&datasum,&value);
            }
        }
    if (badcount)
        {
        if (uOpenDialog("Warning"))
            return;
        p_atos(&buf[0],"%d bad flagged value(s)",badcount);
        if (AddCentredTextItem(&buf[0]))
            return;
        RunDialog();
        }
    p_atos(&buf[0],"Sum of %d values",datacount);
    if (uOpenDialog(&buf[0]))
        return;
    dtob.type=P_DTOB_FIXED;
    dtob.width=29;
    dtob.ndec=sumndp;
    dtob.point='.';
    dtob.trilen=0;
    buf[p_dtob(&buf[0],&datasum,&dtob)]=0;
    if (AddCentredTextItem(&buf[0]))
        return;
    if (AddCentredTextItem("(Sum will be copied into clipboard)"))
        return;
    if (RunDialog()<=0)
        return;
    hEBSetClipText(edit[1],&buf[0],p_slen(&buf[0]));
    }

LOCAL_C VOID PrintSetupDialog(VOID)
    {
    hEBEmphasise(edit[emph],FALSE);
    hPrintSetupDialog();
    hEBEmphasise(edit[emph],TRUE);
    }

LOCAL_C VOID ZeroLenbuf(LENBUF *lb)
    {
    p_free(lb->buf);
    lb->buf=NULL;
    lb->len=0;
    }

LOCAL_C VOID ZeroNote(NOTE *pn)
    {
    ZeroLenbuf(&pn->title);
    ZeroLenbuf(&pn->note);
    pn->tagged=FALSE;
    }

LOCAL_C VOID DeleteNote(VOID)
    {
    INT tomove;

    if (Confirm("Delete this note"))
        return;
    tomove=count-1-where;
    if (tomove>0)
        p_bcpy(&index[where],&index[where+1],tomove*sizeof(NOTE));
    else
        ZeroNote(&index[where]);
    if (count>1)
        count--;
    if (where==count)
        where=count-1;
    LoadEditors();
    }

LOCAL_C VOID ExitIfConfirmed(VOID)
    {
    if (uOpenDialog("Warning"))
        return;
    if (AddCentredTextItem("Exiting will delete all notes"))
        return;
    if (uAddButtonList("Cancel",W_KEY_ESCAPE,"Exit",W_KEY_RETURN,NULL))
        return;
    if (RunDialog()!=W_KEY_RETURN)
        return;
    p_exit(0);
    }

LOCAL_C INT TakeCopyLenbuf(LENBUF *targ,LENBUF *src)
    {
    targ->buf=p_alloc(src->len);
    if (!targ->buf)
        {
        uErrorValue(E_GEN_NOMEMORY);
        return(-1);
        }
    p_bcpy(targ->buf,src->buf,src->len);
    targ->len=src->len;
    return(0);
    }

LOCAL_C INT TakeCopy(NOTE *targ,NOTE *src)
    {
    if (TakeCopyLenbuf(&targ->title,&src->title))
        return(-1);
    if (TakeCopyLenbuf(&targ->note,&src->note))
        {
        p_free(targ->title.buf);
        targ->title.buf=0;
        return(-1);
        }
    targ->tagged=src->tagged;
    return(0);
    }

LOCAL_C VOID CopyNote(VOID)
    {
    NOTE new;

    if (RecordChanges())
        return;
    if (!index[where].title.len && !index[where].note.len)
        {
        wInfoMsg("No note to copy");
        return;
        }
    if (TakeCopy(&new,&index[where]))
        return;
    ZeroNote(&clip);
    clip=new;
    wInfoMsg("Note copied");
    }

LOCAL_C VOID InsertNote(VOID)
    {
    if (!clip.title.len && !clip.note.len)
        {
        wInfoMsg("No note to insert");
        return;
        }
    if (LocateNewWhere())
        return;
    TakeCopy(&index[where],&clip);
    LoadEditors();
    }

LOCAL_C INT TagCount(VOID)
    {
    INT i;
    INT tagcount;

    tagcount=0;
    for (i=0; i<count; i++)
        tagcount+=index[i].tagged;
    return(tagcount);
    }

LOCAL_C VOID CDECL InfoMsg(TEXT *fmt,...)
    {
    TEXT buf[64];

    buf[p_atob(&buf[0],fmt,&fmt+1)]=0;
    wInfoMsg(&buf[0]);
    }

LOCAL_C VOID GiveTagCount(VOID)
    {
    InfoMsg("Number of notes currently tagged: %d",TagCount());
    }

LOCAL_C VOID SetTag(INT flag)
    {
    index[where].tagged=flag;
    DrawTagStatus();
    GiveTagCount();
    }

LOCAL_C VOID TagAll(INT flag)
    {
    INT i;

    for (i=0; i<count; i++)
        index[i].tagged=flag;
    DrawTagStatus();
    GiveTagCount();
    }

LOCAL_C INT PrintLine(H_PRINT *pr)
    {
    INT ind;

    switch (PrintState++)
        {
    case 0:
        FOREVER
            {
            if (PrintRec==count)
                return(FALSE);
            if (!PrintTagsOnly || index[PrintRec].tagged)
                break;
            PrintRec++;
            }
        if (PrintCount)
            {
            pr->blen=0;
            if (PrintNewPage==2)
                pr->flags|=H_PRINT_PAGE;
            return(TRUE);
            }
        PrintState++;
    case 1:
        pr->style|=H_PRINT_STY_BOLD;
        pr->blen=index[PrintRec].title.len;
        pr->buf=index[PrintRec].title.buf;
        break;
    case 2:
        PrintBuf=index[PrintRec].note.buf;
        PrintLen=index[PrintRec].note.len;
    default:
        pr->buf=PrintBuf;
        ind=p_bloc(PrintBuf,PrintLen,'\n');
        if (ind>=0)
            {
            pr->blen=ind;
            PrintLen-=ind+1;
            PrintBuf+=ind+1;
            }
        else
            {
            pr->blen=PrintLen;
            PrintCount++;
            PrintState=0;
            PrintRec++;
            }
        }
    pr->flags|=H_PRINT_KEEP;
    return(TRUE);
    }

LOCAL_C VOID PrintNotes(VOID)
    {
    if (uOpenDialog("Print"))
        return;
    if (uAddChoiceList("New page for each note",&PrintNewPage,"No","Yes",0))
        return;
    if (uAddButtonList("Tagged notes",'t',"All notes",'a',NULL))
        return;
    PrintTagsOnly=FALSE;
    switch (RunDialog())
        {
    case 't':
        PrintTagsOnly=TRUE;
    case 'a':
        if (RecordChanges())
            return;
        PrintRec=0;
        PrintState=0;
        PrintCount=0;
        hPrint(PrintLine);
        InfoMsg("%d note(s) printed",PrintCount);
        }
    }

LOCAL_C VOID OptionsForSearch(VOID)
    {
    if (uOpenDialog("Options for search"))
        return;
    if (uAddChoiceList("Case sensitive",&casesens,"No","Yes",NULL))
        return;
    if (uAddChoiceList("Search",&findtype,"Just notes",
                                    "Just title","Title and notes",NULL))
        return;
    RunDialog();
    }

LOCAL_C INT Search(INT here,INT window)
    {
    LENBUF *lb;
    INT ind;

    lb=(&index[here].title)+window;
    if (casesens==1)
        ind=p_bsubi(lb->buf,lb->len,pattern,pattlen);
    else
        ind=p_bsub(lb->buf,lb->len,pattern,pattlen);
    if (ind<0)
        return(-1);
    if (here!=where)
        {
        where=here;
        if (LoadEditors())
            return(0);
        }
    if (pattlen)
        {
        if (window!=emph)
            {
            hEBEmphasise(edit[emph],FALSE);
            hEBSetCWidth(edit[window],0);
            hEBEmphasise(edit[window],TRUE);
            }
        hEBSetSelect(edit[window],ind,ind+pattlen);
        if (window!=emph)
            {
            wFlush();
            p_sleep(5L);
            hEBEmphasise(edit[window],FALSE);
            hEBSetCWidth(edit[window],2);
            hEBEmphasise(edit[emph],TRUE);
            }
        }
    return(0);
    }

LOCAL_C INT CheckSearchTitle(INT here)
    {
    if (!(findtype&0x02))
        return(-1);
    return(Search(here,0));
    }

LOCAL_C INT CheckSearchNote(INT here)
    {
    if (!(findtype&0x01))
        return(-1);
    return(Search(here,1));
    }

LOCAL_C VOID DoSearch(INT here,INT direction)
    {
    INT k;

    if (RecordChanges())
        return;
    pattern=hEBSenseText(edit[2]);
    pattlen=p_slen(pattern);
    hEBClearChanged(edit[2]);
    k=count;
    while (k--)
        {
        here+=direction;
        if (here<0)
            here=count-1;
        else if (here>=count)
            here=0;
        if (!CheckSearchTitle(here))
            return;
        if (!CheckSearchNote(here))
            return;
        }
    wInfoMsg("Not found");
    }

LOCAL_C VOID ToggleShowSymbols(VOID)
    {
    ShowSymbols^=TRUE;
    hEBShowSymbols(edit[1],ShowSymbols);
    cmds[SYMBOLS_ITEM]=(ShowSymbols? "hHide symbols": "hShow symbols");
    }

LOCAL_C VOID ManageCommand(INT index)
    {
    switch (index)
        {
    case ITEMS_BEFORE_NOTES:
        StartNewNote();
        break;
    case ITEMS_BEFORE_NOTES+1:
        InsertNote();
        break;
    case ITEMS_BEFORE_NOTES+2:
        CopyNote();
        break;
    case ITEMS_BEFORE_NOTES+3:
        DeleteNote();
        break;
    case ITEMS_BEFORE_EDIT:
        if (!CheckEditing())
            {
            if (hEBPaste(edit[1])>0)
                wInfoMsg("No text to insert");
            }
        break;
    case ITEMS_BEFORE_EDIT+1:
        if (!CheckEditing())
            {
            if (hEBCopy(edit[1])>0)
                wInfoMsg("No text to copy");
            else
                wInfoMsg("Text copied");
            }
        break;
    case ITEMS_BEFORE_EDIT+2:
        if (!CheckEditing())
            hEBEvaluate(edit[1]);
        break;
    case ITEMS_BEFORE_EDIT+3:
        if (!CheckEditing())
            SumData();
        break;
    case ITEMS_BEFORE_EDIT+4:
        RecordNote();
        break;
    case ITEMS_BEFORE_EDIT+5:
        UndoEditing();
        break;
    case ITEMS_BEFORE_WINDOW:
    case ITEMS_BEFORE_WINDOW+1:
    case ITEMS_BEFORE_WINDOW+2:
        RotateTo(index-ITEMS_BEFORE_WINDOW);
        break;
    case ITEMS_BEFORE_SEARCH:
        OptionsForSearch();
        break;
    case ITEMS_BEFORE_SEARCH+1:
        DoSearch(where, +1);
        break;
    case ITEMS_BEFORE_SEARCH+2:
        DoSearch(where, -1);
        break;
    case ITEMS_BEFORE_SEARCH+3:
        DoSearch(count,+1);
        break;
    case ITEMS_BEFORE_SEARCH+4:
        DoSearch(count,-1);
        break;
    case ITEMS_BEFORE_TAG:
    case ITEMS_BEFORE_TAG+1:
        SetTag(ITEMS_BEFORE_TAG+1-index);
        break;
    case ITEMS_BEFORE_TAG+2:
    case ITEMS_BEFORE_TAG+3:
        TagAll(ITEMS_BEFORE_TAG+3-index);
        break;
    case ITEMS_BEFORE_SPECIAL:
        GoToNote();
        break;
    case ITEMS_BEFORE_SPECIAL+1:
        MoveNote();
        break;
    case ITEMS_BEFORE_SPECIAL+2:
        ToggleShowSymbols();
        break;
    case ITEMS_BEFORE_SPECIAL+3:
        PrintNotes();
        break;
    case ITEMS_BEFORE_SPECIAL+4:
        PrintSetupDialog();
        break;
    case ITEMS_BEFORE_SPECIAL+5:
        ExitIfConfirmed();
        }
    }

LOCAL_C VOID TryExecuteCommand(INT keycode)
    {
    keycode=uLocateCommand(keycode);
    if (keycode>=0)
        ManageCommand(keycode);
    }

LOCAL_C INT ResizeWidth(UWORD width)
    {
    INT ret;
    W_WINDATA wd;

    wd.extent.tl.x=wd.extent.tl.y=0;
    wd.extent.width=width;
    wd.extent.height=80;
    wSetWindow(MainWid,W_WIN_EXTENT,&wd);
    ret=uErrorValue(wCheckPoint());
    if (!ret)
        ScreenWidth=width;
    return(ret);
    }

LOCAL_C VOID SetStyle(INT style)
    {
    G_GC gc;

    gc.style=style;
    gSetGC(0,G_GC_MASK_STYLE,&gc);
    }

LOCAL_C VOID DrawFindPrompt(VOID)
    {
    SetStyle(G_STY_ITALIC);
    gPrintText(5,67+8,"Find:",5);
    SetStyle(0);
    }

LOCAL_C VOID DrawBorders(VOID)
    {
    INT i;

    for (i=0; i<3; i++)
        DrawBorder(i);
    DrawFindPrompt();
    DrawWhereAndCount();
    }

LOCAL_C VOID ClearWholeWindow(VOID)
    {
    P_RECT whole;

    whole.tl.x=whole.tl.y=0;
    whole.br.x=240;
    whole.br.y=80;
    gClrRect(&whole,G_TRMODE_CLR);
    }

LOCAL_C VOID ToggleStatusWindow(VOID)
    {
    if (show_statwin)
        {
        if (ResizeWidth(240))
            return;
        wsDisable();
        }
    else
        {
        if (ResizeWidth(189))
            return;
        wsEnable();
        }
    show_statwin^=TRUE;
    ClearWholeWindow();
    DrawBorders();
    hEBChangeWidth(edit[0],ScreenWidth-12-8);
    hEBChangeWidth(edit[1],ScreenWidth-12);
    hEBChangeWidth(edit[2],ScreenWidth-12-32-30);
    }

LOCAL_C VOID RotateFocus(INT shifted)
    {
    INT newemph;

    newemph=emph;
    if (shifted)
        {
        if (!newemph--)
            newemph=2;
        }
    else if (++newemph==3)
        newemph=0;
    RotateTo(newemph);
    }

LOCAL_C VOID QuickSearch(INT dir)
    {
    INT here;

    here=(hEBSenseChanged(edit[2])? count: where);
    DoSearch(here,dir);
    }

LOCAL_C VOID ToFindStack(VOID)
    {
    TEXT *buf;
    INT len;

    if (!hEBSenseChanged(edit[2]))
        return;
    buf=hEBSenseText(edit[2]);
    len=p_slen(buf);
    FindStack[FindSP][0]=len;
    p_bcpy(&FindStack[FindSP][1],buf,len);
    }

LOCAL_C VOID ChangeFindSP(INT dir)
    {
    FindSP+=dir;
    if (FindSP<0)
        FindSP=5;
    else if (FindSP>5)
        FindSP=0;
    if (hEBSetText(edit[2],&FindStack[FindSP][1],FindStack[FindSP][0]))
        return;
    hEBSetSelect(edit[2],0,FindStack[FindSP][0]);
    }

LOCAL_C VOID MainLoop(VOID)
    {
    INT ret;
    WMSG_KEY key;

    FOREVER
        {
        uGetKey(&key);
        if (key.keycode&W_SPECIAL_KEY)
            TryExecuteCommand(key.keycode&(~W_SPECIAL_KEY));
        else
            {
            switch (key.keycode)
                {
            case W_KEY_MENU:
                if (key.modifiers&W_CTRL_MODIFIER)
                    ToggleStatusWindow();
                else
                    {
                    ret=uPresentMenus();
                    if (ret>0)
                        TryExecuteCommand(ret);
                    }
                break;
            case W_KEY_TAB:
                RotateFocus(key.modifiers&W_SHIFT_MODIFIER);
                break;
            case W_KEY_RETURN:
                if (!emph)
                    {
                    RotateTo(1);
                    break;
                    }
            default:
                if (emph==2)
                    {
                    if (key.keycode==W_KEY_RETURN)
                        {
                        ToFindStack();
                        QuickSearch(key.modifiers&W_SHIFT_MODIFIER? -1: +1);
                        break;
                        }
                    else if (key.keycode==W_KEY_UP)
                        {
                        ToFindStack();
                        ChangeFindSP(-1);
                        break;
                        }
                    else if (key.keycode==W_KEY_DOWN || key.keycode==W_KEY_ESCAPE)
                        {
                        ToFindStack();
                        ChangeFindSP(+1);
                        break;
                        }
                    }
                hEBHandleKey(edit[emph],key.keycode,key.modifiers);
                }    
            }
        }
    }

LOCAL_C VOID OpenEditors(VOID)
    {
    H_EDIT_BOX heb;

    heb.win=MainWid;
    heb.maxchars=40;
    heb.vulen=177-8;
    heb.pos.x=5+8;
    heb.pos.y=2;
    heb.font=0x4001;
    heb.style=0;
    edit[0]=hEBOpen(H_EDIT_BOX_FONT,&heb);
    heb.maxchars=256;
    heb.vulen=177;
    heb.vislines=4;
    heb.pos.x=5;
    heb.pos.y=19;
    edit[1]=hEBOpen(H_EDIT_BOX_VISLINES|
                        H_EDIT_BOX_LEFT_CURSOR|H_EDIT_BOX_CLIPBOARD,&heb);
    heb.maxchars=20;
    heb.vulen=177-32-30;
    heb.pos.x=5+32;
    heb.pos.y=67;
    edit[2]=hEBOpen(0,&heb);
    }

LOCAL_C VOID SmallScreen(VOID)
    {
    if (ResizeWidth(189))
        p_exit(0);
    }

LOCAL_C VOID CreateGC(VOID)
    {
    INT hgc;

    hgc=gCreateGC0(MainWid);
    if (hgc<0)
        p_exit(hgc);
    }

LOCAL_C VOID SpecificInit(VOID)
    {
    uEscape(FALSE);
    MainWid=uFindMainWid();
    CreateGC();
    hCrackCommandLine();
    SmallScreen();
    OpenEditors();
    DrawBorders();
    wsEnable();
    }

GLDEF_C VOID main(VOID)
    {
    uCommonInit();
    SpecificInit();
    MainLoop();
    }
