OSDN Git Service

change version number
[bbk/bchanl.git] / src / bchanl_hmi.c
index b84141e..902d4b7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * bchanl_hmi.c
  *
- * Copyright (c) 2011 project bchan
+ * Copyright (c) 2012 project bchan
  *
  * This software is provided 'as-is', without any express or implied
  * warranty. In no event will the authors be held liable for any damages
  *
  */
 
+/* This file is automatically generated. */
+
 #include    "bchanl_hmi.h"
-#include    "hmi_wscr.h"
+#include    "hmi/hmi_windowscroll.h"
 
 #include       <bstdio.h>
 #include       <bstdlib.h>
@@ -35,7 +37,7 @@
 #include       <btron/hmi.h>
 #include       <btron/vobj.h>
 
-#ifdef BCHANL_CONFIG_DEBUG
+#if 1
 # define DP(arg) printf arg
 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
 #else
 #endif
 
 struct subjectwindow_t_ {
+       UW flag;
        WID wid;
        GID gid;
-       subjectwindow_scrollcalback scroll_callback;
-       windowscroll_t wscr;
-       VP arg;
+       WID parent;
+       RECT r;
+       PAT bgpat;
+       hmi_windowscroll_t wscr;
        WEVENT savedwev;
 };
 
 struct bbsmenuwindow_t_ {
+       UW flag;
        WID wid;
        GID gid;
-       bbsmenuwindow_scrollcalback scroll_callback;
-       windowscroll_t wscr;
-       VP arg;
+       WID parent;
+       RECT r;
+       PAT bgpat;
+       hmi_windowscroll_t wscr;
        WEVENT savedwev;
 };
 
-#define SUBJECTOPTIONWINDOW_STRBUF_LEN 512
 struct subjectoptionwindow_t_ {
+       UW flag;
+       WID wid;
+       GID gid;
+       subjectwindow_t *parent;
+       RECT r;
+       PAT bgpat;
+       TC title[256+1];
+       WEVENT savedwev;
+       struct {
+               PAID id;
+               W dnum;
+               TC buf[1000+7+1];
+               W buf_written;
+               Bool appended;
+               Bool nextaction;
+       } filter;
+       struct {
+               PAID id;
+               W dnum;
+               SUBJECTOPTIONWINDOW_ORDERVALUE_T value;
+       } order;
+       struct {
+               PAID id;
+               W dnum;
+               SUBJECTOPTIONWINDOW_ORDERBYVALUE_T value;
+       } orderby;
+};
+
+struct registerexternalwindow_t_ {
+       UW flag;
+       WID wid;
+       GID gid;
+       WID parent;
+       RECT r;
+       PAT bgpat;
+       TC title[256+1];
+       WEVENT savedwev;
+       struct {
+               PAID id;
+               
+               TC buf[1000+7+1];
+               W buf_written;
+               Bool appended;
+               Bool nextaction;
+       } boradname;
+       struct {
+               PAID id;
+               
+               TC buf[1000+7+1];
+               W buf_written;
+               Bool appended;
+               Bool nextaction;
+       } url;
+       struct {
+               PAID id;
+               
+       } determine;
+       struct {
+               PAID id;
+               
+       } cancel;
+};
+
+struct externalbbswindow_t_ {
+       UW flag;
        WID wid;
        GID gid;
        WID parent;
        RECT r;
        PAT bgpat;
-       W dnum_filter;
-       W dnum_order;
-       W dnum_orderby;
-       PAID tb_filter_id;
-       PAID ws_order_id;
-       PAID ws_orderby_id;
+       hmi_windowscroll_t wscr;
+       TC title[256+1];
        WEVENT savedwev;
-       W order;
-       W orderby;
-       TC strbuf[SUBJECTOPTIONWINDOW_STRBUF_LEN];
-       W strbuf_written;
-       Bool tb_appended;
 };
 
 #define BCHANLHMI_FLAG_SWITCHBUTDN 0x00000001
@@ -91,31 +152,73 @@ struct bchanlhmi_t_ {
        subjectwindow_t *subjectwindow;
        bbsmenuwindow_t *bbsmenuwindow;
        subjectoptionwindow_t *subjectoptionwindow;
+       registerexternalwindow_t *registerexternalwindow;
+       externalbbswindow_t *externalbbswindow;
 };
 
-EXPORT W subjectwindow_startredisp(subjectwindow_t *window, RECT *r)
+#define SUBJECTWINDOW_FLAG_DRAWREQUEST 0x00000001
+#define SUBJECTWINDOW_FLAG_RSCROLLING 0x00000002
+#define SUBJECTWINDOW_FLAG_BSCROLLING 0x00000004
+
+#define subjectwindow_setflag(window, flagx) (window)->flag = (window)->flag | (flagx)
+#define subjectwindow_clearflag(window, flagx) (window)->flag = (window)->flag & ~(flagx)
+#define subjectwindow_issetflag(window, flagx) (((window)->flag & (flagx)) == 0 ? False : True)
+
+EXPORT VOID subjectwindow_scrollbyvalue(subjectwindow_t *window, W dh, W dv)
 {
-       return wsta_dsp(window->wid, r, NULL);
+       hmi_windowscroll_scrollworkrect(&window->wscr, dh, dv);
 }
 
-EXPORT W subjectwindow_endredisp(subjectwindow_t *window)
+EXPORT W subjectwindow_setdrawrect(subjectwindow_t *window, W l, W t, W r, W b)
 {
-       return wend_dsp(window->wid);
+       return hmi_windowscroll_setdrawrect(&window->wscr, l, t, r, b);
 }
 
-EXPORT W subjectwindow_eraseworkarea(subjectwindow_t *window, RECT *r)
+EXPORT W subjectwindow_setworkrect(subjectwindow_t *window, W l, W t, W r, W b)
 {
-       return wera_wnd(window->wid, r);
+       return hmi_windowscroll_setworkrect(&window->wscr, l, t, r, b);
 }
 
 EXPORT W subjectwindow_scrollworkarea(subjectwindow_t *window, W dh, W dv)
 {
-       return wscr_wnd(window->wid, NULL, dh, dv, W_MOVE|W_RDSET);
+       W err;
+       err = wscr_wnd(window->wid, NULL, dh, dv, W_MOVE|W_RDSET);
+       if (err < 0) {
+               return err;
+       }
+       if ((err & W_RDSET) != 0) {
+               subjectwindow_setflag(window, SUBJECTWINDOW_FLAG_DRAWREQUEST);
+       }
+       return 0;
 }
 
-EXPORT VOID subjectwindow_scrollbyvalue(subjectwindow_t *window, W dh, W dv)
+EXPORT W subjectwindow_getworkrect(subjectwindow_t *window, RECT *r)
+{
+       return wget_wrk(window->wid, r);
+}
+
+EXPORT VOID subjectwindow_responsepasterequest(subjectwindow_t *window, W nak, PNT *pos)
+{
+       if (pos != NULL) {
+               window->savedwev.r.r.p.rightbot.x = pos->x;
+               window->savedwev.r.r.p.rightbot.y = pos->y;
+       }
+       wrsp_evt(&window->savedwev, nak);
+}
+
+EXPORT W subjectwindow_startredisp(subjectwindow_t *window, RECT *r)
+{
+       return wsta_dsp(window->wid, r, NULL);
+}
+
+EXPORT W subjectwindow_endredisp(subjectwindow_t *window)
 {
-       windowscroll_scrollbyvalue(&window->wscr, dh, dv);
+       return wend_dsp(window->wid);
+}
+
+EXPORT W subjectwindow_eraseworkarea(subjectwindow_t *window, RECT *r)
+{
+       return wera_wnd(window->wid, r);
 }
 
 EXPORT W subjectwindow_requestredisp(subjectwindow_t *window)
@@ -146,20 +249,6 @@ EXPORT VOID subjectwindow_enddrag(subjectwindow_t *window)
        wend_drg();
 }
 
-EXPORT VOID subjectwindow_responsepasterequest(subjectwindow_t *window, W nak, PNT *pos)
-{
-       if (pos != NULL) {
-               window->savedwev.r.r.p.rightbot.x = pos->x;
-               window->savedwev.r.r.p.rightbot.y = pos->y;
-       }
-       wrsp_evt(&window->savedwev, nak);
-}
-
-EXPORT W subjectwindow_getworkrect(subjectwindow_t *window, RECT *r)
-{
-       return wget_wrk(window->wid, r);
-}
-
 EXPORT GID subjectwindow_getGID(subjectwindow_t *window)
 {
        return wget_gid(window->wid);
@@ -185,39 +274,117 @@ EXPORT Bool subjectwindow_isactive(subjectwindow_t *window)
        return False;
 }
 
-EXPORT W subjectwindow_setdrawrect(subjectwindow_t *window, W l, W t, W r, W b)
+LOCAL VOID subjectwindow_butdnwork(subjectwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
 {
-       return windowscroll_setdrawrect(&window->wscr, l, t, r, b);
+       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_BUTDN;
+       evt->data.subjectwindow_butdn.type = wchk_dck(wev->s.time);
+       evt->data.subjectwindow_butdn.pos = wev->s.pos;
+       memcpy(&window->savedwev, wev, sizeof(WEVENT));
 }
 
-EXPORT W subjectwindow_setworkrect(subjectwindow_t *window, W l, W t, W r, W b)
+LOCAL VOID subjectwindow_resize(subjectwindow_t *window, SIZE *sz)
 {
-       return windowscroll_setworkrect(&window->wscr, l, t, r, b);
+       RECT work;
+       Bool workchange = False;
+
+       wget_wrk(window->wid, &work);
+       if (work.c.left != 0) {
+               work.c.left = 0;
+               workchange = True;
+       }
+       if (work.c.top != 0) {
+               work.c.top = 0;
+               workchange = True;
+       }
+       wset_wrk(window->wid, &work);
+       gset_vis(window->gid, work);
+
+       if (workchange == True) {
+               wera_wnd(window->wid, NULL);
+               wreq_dsp(window->wid);
+       }
+
+       sz->v = work.c.bottom - work.c.top;
+       sz->h = work.c.right - work.c.left;
 }
 
-EXPORT W bbsmenuwindow_startredisp(bbsmenuwindow_t *window, RECT *r)
+LOCAL W subjectwindow_open(subjectwindow_t *window, TC *title)
 {
-       return wsta_dsp(window->wid, r, NULL);
+       WID wid;
+
+       if (window->wid > 0) {
+               return 0;
+       }
+
+       wid = wopn_wnd(WA_STD|WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, window->parent, &(window->r), NULL, 2, title, &window->bgpat, NULL);
+       if (wid < 0) {
+               DP_ER("wopn_wnd: subjectoption error", wid);
+               return wid;
+       }
+       window->wid = wid;
+       window->gid = wget_gid(wid);
+       hmi_windowscroll_settarget(&window->wscr, wid);
+
+
+       wreq_dsp(wid);
+
+       return 0;
 }
 
-EXPORT W bbsmenuwindow_endredisp(bbsmenuwindow_t *window)
+#define BBSMENUWINDOW_FLAG_DRAWREQUEST 0x00000001
+#define BBSMENUWINDOW_FLAG_RSCROLLING 0x00000002
+#define BBSMENUWINDOW_FLAG_BSCROLLING 0x00000004
+
+#define bbsmenuwindow_setflag(window, flagx) (window)->flag = (window)->flag | (flagx)
+#define bbsmenuwindow_clearflag(window, flagx) (window)->flag = (window)->flag & ~(flagx)
+#define bbsmenuwindow_issetflag(window, flagx) (((window)->flag & (flagx)) == 0 ? False : True)
+
+EXPORT VOID bbsmenuwindow_scrollbyvalue(bbsmenuwindow_t *window, W dh, W dv)
 {
-       return wend_dsp(window->wid);
+       hmi_windowscroll_scrollworkrect(&window->wscr, dh, dv);
 }
 
-EXPORT W bbsmenuwindow_eraseworkarea(bbsmenuwindow_t *window, RECT *r)
+EXPORT W bbsmenuwindow_setdrawrect(bbsmenuwindow_t *window, W l, W t, W r, W b)
 {
-       return wera_wnd(window->wid, r);
+       return hmi_windowscroll_setdrawrect(&window->wscr, l, t, r, b);
+}
+
+EXPORT W bbsmenuwindow_setworkrect(bbsmenuwindow_t *window, W l, W t, W r, W b)
+{
+       return hmi_windowscroll_setworkrect(&window->wscr, l, t, r, b);
 }
 
 EXPORT W bbsmenuwindow_scrollworkarea(bbsmenuwindow_t *window, W dh, W dv)
 {
-       return wscr_wnd(window->wid, NULL, dh, dv, W_MOVE|W_RDSET);
+       W err;
+       err = wscr_wnd(window->wid, NULL, dh, dv, W_MOVE|W_RDSET);
+       if (err < 0) {
+               return err;
+       }
+       if ((err & W_RDSET) != 0) {
+               bbsmenuwindow_setflag(window, BBSMENUWINDOW_FLAG_DRAWREQUEST);
+       }
+       return 0;
+}
+
+EXPORT W bbsmenuwindow_getworkrect(bbsmenuwindow_t *window, RECT *r)
+{
+       return wget_wrk(window->wid, r);
 }
 
-EXPORT VOID bbsmenuwindow_scrollbyvalue(bbsmenuwindow_t *window, W dh, W dv)
+EXPORT W bbsmenuwindow_startredisp(bbsmenuwindow_t *window, RECT *r)
+{
+       return wsta_dsp(window->wid, r, NULL);
+}
+
+EXPORT W bbsmenuwindow_endredisp(bbsmenuwindow_t *window)
+{
+       return wend_dsp(window->wid);
+}
+
+EXPORT W bbsmenuwindow_eraseworkarea(bbsmenuwindow_t *window, RECT *r)
 {
-       windowscroll_scrollbyvalue(&window->wscr, dh, dv);
+       return wera_wnd(window->wid, r);
 }
 
 EXPORT W bbsmenuwindow_requestredisp(bbsmenuwindow_t *window)
@@ -248,20 +415,6 @@ EXPORT VOID bbsmenuwindow_enddrag(bbsmenuwindow_t *window)
        wend_drg();
 }
 
-EXPORT VOID bbsmenuwindow_responsepasterequest(bbsmenuwindow_t *window, W nak, PNT *pos)
-{
-       if (pos != NULL) {
-               window->savedwev.r.r.p.rightbot.x = pos->x;
-               window->savedwev.r.r.p.rightbot.y = pos->y;
-       }
-       wrsp_evt(&window->savedwev, nak);
-}
-
-EXPORT W bbsmenuwindow_getworkrect(bbsmenuwindow_t *window, RECT *r)
-{
-       return wget_wrk(window->wid, r);
-}
-
 EXPORT GID bbsmenuwindow_getGID(bbsmenuwindow_t *window)
 {
        return wget_gid(window->wid);
@@ -287,17 +440,41 @@ EXPORT Bool bbsmenuwindow_isactive(bbsmenuwindow_t *window)
        return False;
 }
 
-EXPORT W bbsmenuwindow_setdrawrect(bbsmenuwindow_t *window, W l, W t, W r, W b)
+LOCAL VOID bbsmenuwindow_butdnwork(bbsmenuwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
 {
-       return windowscroll_setdrawrect(&window->wscr, l, t, r, b);
+       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_BUTDN;
+       evt->data.bbsmenuwindow_butdn.type = wchk_dck(wev->s.time);
+       evt->data.bbsmenuwindow_butdn.pos = wev->s.pos;
+       memcpy(&window->savedwev, wev, sizeof(WEVENT));
 }
 
-EXPORT W bbsmenuwindow_setworkrect(bbsmenuwindow_t *window, W l, W t, W r, W b)
+LOCAL VOID bbsmenuwindow_resize(bbsmenuwindow_t *window, SIZE *sz)
 {
-       return windowscroll_setworkrect(&window->wscr, l, t, r, b);
+       RECT work;
+       Bool workchange = False;
+
+       wget_wrk(window->wid, &work);
+       if (work.c.left != 0) {
+               work.c.left = 0;
+               workchange = True;
+       }
+       if (work.c.top != 0) {
+               work.c.top = 0;
+               workchange = True;
+       }
+       wset_wrk(window->wid, &work);
+       gset_vis(window->gid, work);
+
+       if (workchange == True) {
+               wera_wnd(window->wid, NULL);
+               wreq_dsp(window->wid);
+       }
+
+       sz->v = work.c.bottom - work.c.top;
+       sz->h = work.c.right - work.c.left;
 }
 
-EXPORT W subjectoptionwindow_open(subjectoptionwindow_t *window)
+LOCAL W bbsmenuwindow_open(bbsmenuwindow_t *window, TC *title)
 {
        WID wid;
 
@@ -305,219 +482,1053 @@ EXPORT W subjectoptionwindow_open(subjectoptionwindow_t *window)
                return 0;
        }
 
-       wid = wopn_wnd(WA_SUBW|WA_TITL|WA_HHDL, window->parent, &(window->r), NULL, 2, NULL, &window->bgpat, NULL);
+       wid = wopn_wnd(WA_STD|WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, window->parent, &(window->r), NULL, 2, title, &window->bgpat, NULL);
        if (wid < 0) {
                DP_ER("wopn_wnd: subjectoption error", wid);
                return wid;
        }
        window->wid = wid;
        window->gid = wget_gid(wid);
+       hmi_windowscroll_settarget(&window->wscr, wid);
 
-       window->tb_filter_id = copn_par(wid, window->dnum_filter, NULL);
-       if (window->tb_filter_id < 0) {
-               DP_ER("copn_par list error:", window->tb_filter_id);
-       }
-       window->ws_order_id = copn_par(wid, window->dnum_order, NULL);
-       if (window->ws_order_id < 0) {
-               DP_ER("copn_par delete error:", window->ws_order_id);
-       }
-       window->ws_orderby_id = copn_par(wid, window->dnum_orderby, NULL);
-       if (window->ws_orderby_id < 0) {
-               DP_ER("copn_par input error:", window->ws_orderby_id);
-       }
 
        wreq_dsp(wid);
 
        return 0;
 }
 
-EXPORT VOID subjectoptionwindow_close(subjectoptionwindow_t *window)
-{
-       WDSTAT stat;
-       W err;
-
-       if (window->wid < 0) {
-               return;
-       }
-
-       stat.attr = WA_STD;
-       err = wget_sts(window->wid, &stat, NULL);
-       if (err >= 0) {
-               window->r = stat.r;
-       }
-       cdel_pwd(window->wid, NOCLR);
-       wcls_wnd(window->wid, CLR);
-       window->wid = -1;
-       window->gid = -1;
-}
-
-EXPORT Bool subjectoptionwindow_isopen(subjectoptionwindow_t *window)
-{
-       if (window->wid < 0) {
-               return False;
-       }
-       return True;
-}
-
-EXPORT W subjectoptionwindow_setorder(subjectoptionwindow_t *window, W order)
-{
-       if ((order != SUBJECTOPTIONWINDOW_ORDER_ASCENDING)
-               &&(order != SUBJECTOPTIONWINDOW_ORDER_DESCENDING)) {
-               return -1; /* TODO */
-       }
-       window->order = order;
-       if (window->wid < 0) {
-               return 0;
-       }
-       return cset_val(window->ws_order_id, 1, (W*)&order);
-}
+#define SUBJECTOPTIONWINDOW_FLAG_DRAWREQUEST 0x00000001
+#define SUBJECTOPTIONWINDOW_FLAG_PARTS_OTHEREVENT 0x0000000f
+#define SUBJECTOPTIONWINDOW_FLAG_PARTS_NEXTACTION 0x00000010
 
-EXPORT W subjectoptionwindow_setorderby(subjectoptionwindow_t *window, W orderby)
-{
-       if ((orderby != SUBJECTOPTIONWINDOW_ORDERBY_NUMBER)
-               &&(orderby != SUBJECTOPTIONWINDOW_ORDERBY_RES)
-               &&(orderby != SUBJECTOPTIONWINDOW_ORDERBY_SINCE)
-               &&(orderby != SUBJECTOPTIONWINDOW_ORDERBY_VIGOR)) {
-               return -1; /* TODO */
-       }
-       window->orderby = orderby;
-       if (window->wid < 0) {
-               return 0;
-       }
-       return cset_val(window->ws_orderby_id, 1, (W*)&orderby);
-}
+#define subjectoptionwindow_setflag(window, flagx) (window)->flag = (window)->flag | (flagx)
+#define subjectoptionwindow_clearflag(window, flagx) (window)->flag = (window)->flag & ~(flagx)
+#define subjectoptionwindow_issetflag(window, flagx) (((window)->flag & (flagx)) == 0 ? False : True)
 
-EXPORT W subjectoptionwindow_settext(subjectoptionwindow_t *window, TC *str, W len)
+EXPORT W subjectoptionwindow_setfiltertext(subjectoptionwindow_t *window, TC *str, W len)
 {
        W cp_len;
 
-       if (len < SUBJECTOPTIONWINDOW_STRBUF_LEN) {
+       if (len < 1000) {
                cp_len = len;
        } else {
-               cp_len = SUBJECTOPTIONWINDOW_STRBUF_LEN;
+               cp_len = 1000;
        }
-       memcpy(window->strbuf, str, cp_len * sizeof(TC));
-       window->strbuf_written = cp_len;
+       memcpy(window->filter.buf+7, str, cp_len * sizeof(TC));
+       window->filter.buf[7 + cp_len] = TNULL;
+       window->filter.buf_written = cp_len;
        if (window->wid < 0) {
                return 0;
        }
 
-       return cset_val(window->tb_filter_id, cp_len, (W*)window->strbuf);
-}
-
-EXPORT W subjectoptionwindow_getorder(subjectoptionwindow_t *window)
-{
-       return window->order;
+       return cset_val(window->filter.id, cp_len, (W*)(window->filter.buf+7));
 }
 
-EXPORT W subjectoptionwindow_getorderby(subjectoptionwindow_t *window)
+EXPORT W subjectoptionwindow_getfiltertext(subjectoptionwindow_t *window, TC *str, W len)
 {
-       return window->orderby;
-}
+       W err, cp_len;
 
-EXPORT W subjectoptionwindow_gettext(subjectoptionwindow_t *window, TC *str, W len)
-{
-       W cp_len;
+       if (window->wid > 0) {
+               err = cget_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->filter.buf_written = err;
+       }
 
-       if (len < window->strbuf_written) {
+       if (len < window->filter.buf_written) {
                cp_len = len;
        } else {
-               cp_len = window->strbuf_written;
+               cp_len = window->filter.buf_written;
        }
-       memcpy(str, window->strbuf, cp_len * sizeof(TC));
+       memcpy(str, window->filter.buf + 7, cp_len * sizeof(TC));
 
        return cp_len;
 }
 
-EXPORT W subjectoptionwindow_starttextboxaction(subjectoptionwindow_t *window)
+EXPORT W subjectoptionwindow_cutfiltertext(subjectoptionwindow_t *window, TC *str, W len, Bool cut)
 {
-       window->tb_appended = False;
-       return 0;
-}
+       W err, len0;
 
-EXPORT W subjectoptionwindow_gettextboxaction(subjectoptionwindow_t *window, TC *key, TC **val, W *len)
+       len0 = ccut_txt(window->filter.id, len, str, cut == False ? 0 : 1);
+       if (len0 < 0) {
+               return len0;
+       }
+
+       if (cut != False) {
+               err = cget_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->filter.buf_written = err;
+               return len0;
+       }
+
+       return len0;
+}
+
+EXPORT W subjectoptionwindow_insertfiltertext(subjectoptionwindow_t *window, TC *str, W len)
+{
+       W err;
+
+       err = cins_txt(window->filter.id, (PNT){0x8000, 0x8000}, str);
+       if (err < 0) {
+               return err;
+       }
+
+       err = cget_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+       if (err < 0) {
+               return err;
+       }
+       window->filter.buf_written = err;
+
+       return err;
+}
+
+LOCAL VOID subjectoptionwindow_actionfilter(subjectoptionwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       W i, len;
+
+       i = cact_par(window->filter.id, wev);
+       if (i & 0x2000) {
+               window->filter.nextaction = True;
+               switch (i) {
+               case    P_MENU:
+                       if ((wev->s.type == EV_KEYDWN)&&(wev->s.stat & ES_CMD)) {
+                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_KEYMENU;
+                               evt->data.subjectoptionwindow_filter_keymenu.keycode = wev->e.data.key.code;
+                       } else {
+                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MENU;
+                               evt->data.subjectoptionwindow_filter_menu.pos = wev->s.pos;
+                       }
+                       subjectoptionwindow_setflag(window, SUBJECTOPTIONWINDOW_FLAG_PARTS_NEXTACTION);
+                       break;
+               default:
+                       wugt_evt(wev);
+                       subjectoptionwindow_setflag(window, SUBJECTOPTIONWINDOW_FLAG_PARTS_OTHEREVENT);
+                       break;
+               }
+               return;
+       }
+       window->filter.nextaction = False;
+       if (i & 0x1000) {
+               len = cget_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+               if (len > 0) {
+                       window->filter.buf_written = len;
+               }
+       }
+       switch (i & 7) {
+       case    P_BUT:
+               cchg_par(window->filter.id, P_INACT);
+               cchg_par(window->filter.id, P_ACT);
+               wugt_evt(wev);
+               break;
+       case    P_TAB:
+               break;
+       case    P_NL:
+       case    P_END:
+               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_DETERMINE;
+               evt->data.subjectoptionwindow_filter_determine.value = window->filter.buf+7;
+               evt->data.subjectoptionwindow_filter_determine.len = window->filter.buf_written;
+               break;
+       case    P_MOVE:
+               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MOVE;
+               evt->data.subjectoptionwindow_filter_move.rel_wid = wev->s.wid;
+               evt->data.subjectoptionwindow_filter_move.pos = wev->s.pos;
+               break;
+       case    P_COPY:
+               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_COPY;
+               evt->data.subjectoptionwindow_filter_copy.rel_wid = wev->s.wid;
+               evt->data.subjectoptionwindow_filter_copy.pos = wev->s.pos;
+               break;
+       }
+}
+
+EXPORT W subjectoptionwindow_setordervalue(subjectoptionwindow_t *window, SUBJECTOPTIONWINDOW_ORDERVALUE_T value)
+{
+       W val;
+
+       val = window->order.value = value;
+       if (window->wid < 0) {
+               return 0;
+       }
+
+       return cset_val(window->order.id, 1, (W*)(&val));
+}
+
+EXPORT W subjectoptionwindow_getordervalue(subjectoptionwindow_t *window, SUBJECTOPTIONWINDOW_ORDERVALUE_T *value)
+{
+       W val,err;
+
+       if (window->wid > 0) {
+               err = cget_val(window->order.id, 1, (W*)(&val));
+               if (err < 0) {
+                       return err;
+               }
+       }
+       *value = window->order.value = val;
+
+       return 0;
+}
+
+LOCAL VOID subjectoptionwindow_actionorder(subjectoptionwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       W i;
+
+       i = cact_par(window->order.id, wev);
+       if ((i & 0x5000) != 0x5000) {
+               return;
+       }
+       window->order.value = i & 0xfff;
+       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDER_CHANGE;
+       evt->data.subjectoptionwindow_order_change.value = window->order.value;
+}
+
+EXPORT W subjectoptionwindow_setorderbyvalue(subjectoptionwindow_t *window, SUBJECTOPTIONWINDOW_ORDERBYVALUE_T value)
+{
+       W val;
+
+       val = window->orderby.value = value;
+       if (window->wid < 0) {
+               return 0;
+       }
+
+       return cset_val(window->orderby.id, 1, (W*)(&val));
+}
+
+EXPORT W subjectoptionwindow_getorderbyvalue(subjectoptionwindow_t *window, SUBJECTOPTIONWINDOW_ORDERBYVALUE_T *value)
+{
+       W val,err;
+
+       if (window->wid > 0) {
+               err = cget_val(window->orderby.id, 1, (W*)(&val));
+               if (err < 0) {
+                       return err;
+               }
+       }
+       *value = window->orderby.value = val;
+
+       return 0;
+}
+
+LOCAL VOID subjectoptionwindow_actionorderby(subjectoptionwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       W i;
+
+       i = cact_par(window->orderby.id, wev);
+       if ((i & 0x5000) != 0x5000) {
+               return;
+       }
+       window->orderby.value = i & 0xfff;
+       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDERBY_CHANGE;
+       evt->data.subjectoptionwindow_orderby_change.value = window->orderby.value;
+}
+
+EXPORT Bool subjectoptionwindow_isopen(subjectoptionwindow_t *window)
+{
+       if (window->wid < 0) {
+               return False;
+       }
+       return True;
+}
+
+LOCAL VOID subjectoptionwindow_draw(subjectoptionwindow_t *window, RECT *r)
+{
+       cdsp_pwd(window->wid, r, P_RDISP);
+       gset_chc(window->gid, 0x10000000, -1);
+       gdra_stp(window->gid, 8, 26, (TC[]){0x2555, 0x2523, 0x256b, 0x253f, 0x2127, TNULL}, 5, G_STORE);
+       gset_chc(window->gid, 0x10000000, -1);
+       gdra_stp(window->gid, 8, 58, (TC[]){0x4a42, 0x2459, 0x3d67, 0x2127, TNULL}, 4, G_STORE);
+}
+
+LOCAL VOID subjectoptionwindow_redisp(subjectoptionwindow_t *window)
+{
+       RECT r;
+       do {
+               if (wsta_dsp(window->wid, &r, NULL) == 0) {
+                       break;
+               }
+               wera_wnd(window->wid, &r);
+               subjectoptionwindow_draw(window, &r);
+       } while (wend_dsp(window->wid) > 0);
+}
+
+EXPORT W subjectoptionwindow_requestredisp(subjectoptionwindow_t *window)
+{
+       return wreq_dsp(window->wid);
+}
+
+EXPORT GID subjectoptionwindow_getGID(subjectoptionwindow_t *window)
+{
+       return wget_gid(window->wid);
+}
+
+EXPORT WID subjectoptionwindow_getWID(subjectoptionwindow_t *window)
+{
+       return window->wid;
+}
+
+EXPORT W subjectoptionwindow_settitle(subjectoptionwindow_t *window, TC *title)
+{
+       tc_strncpy(window->title, title, 256);
+       window->title[256] = TNULL;
+       return wset_tit(window->wid, -1, window->title, 0);
+}
+
+EXPORT Bool subjectoptionwindow_isactive(subjectoptionwindow_t *window)
+{
+       WID wid;
+       wid = wget_act(NULL);
+       if (window->wid == wid) {
+               return True;
+       }
+       return False;
+}
+
+LOCAL VOID subjectoptionwindow_butdnwork(subjectoptionwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       PAID id;
+       W ret;
+
+       ret = cfnd_par(window->wid, wev->s.pos, &id);
+       if (ret <= 0) {
+               return;
+       }
+       if (id == window->filter.id) {
+               memcpy(&window->savedwev, wev, sizeof(WEVENT));
+               subjectoptionwindow_actionfilter(window, wev, evt);
+               return;
+       }
+       if (id == window->order.id) {
+               subjectoptionwindow_actionorder(window, wev, evt);
+               return;
+       }
+       if (id == window->orderby.id) {
+               subjectoptionwindow_actionorderby(window, wev, evt);
+               return;
+       }
+}
+
+EXPORT W subjectoptionwindow_open(subjectoptionwindow_t *window)
+{
+       WID wid;
+
+       if (window->wid > 0) {
+               return 0;
+       }
+
+       wid = wopn_wnd(WA_STD|WA_SUBW, window->parent->wid, &(window->r), NULL, 2, window->title, &window->bgpat, NULL);
+       if (wid < 0) {
+               DP_ER("wopn_wnd: subjectoption error", wid);
+               return wid;
+       }
+       window->wid = wid;
+       window->gid = wget_gid(wid);
+
+       window->filter.id = copn_par(wid, window->filter.dnum, NULL);
+       if (window->filter.id < 0) {
+               DP_ER("ccre_xxx filter error:", window->filter.id);
+       }
+       cset_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+       window->order.id = copn_par(wid, window->order.dnum, NULL);
+       if (window->order.id < 0) {
+               DP_ER("ccre_xxx order error:", window->order.id);
+       }
+       cset_val(window->order.id, 1, (W*)(&window->order.value));
+       window->orderby.id = copn_par(wid, window->orderby.dnum, NULL);
+       if (window->orderby.id < 0) {
+               DP_ER("ccre_xxx orderby error:", window->orderby.id);
+       }
+       cset_val(window->orderby.id, 1, (W*)(&window->orderby.value));
+
+       wreq_dsp(wid);
+
+       return 0;
+}
+
+EXPORT VOID subjectoptionwindow_close(subjectoptionwindow_t *window)
+{
+       WDSTAT stat;
+       W err;
+
+       if (window->wid < 0) {
+               return;
+       }
+
+       stat.attr = WA_STD;
+       err = wget_sts(window->wid, &stat, NULL);
+       if (err >= 0) {
+               window->r = stat.r;
+       }
+       err = cget_val(window->orderby.id, 1, (W*)(&window->orderby.value));
+       err = cget_val(window->order.id, 1, (W*)(&window->order.value));
+       err = cget_val(window->filter.id, 1000, (W*)(window->filter.buf+7));
+       if (err >= 0) {
+               window->filter.buf_written = err;
+       }
+       cdel_pwd(window->wid, NOCLR);
+       wcls_wnd(window->wid, CLR);
+       window->wid = -1;
+       window->gid = -1;
+}
+
+#define REGISTEREXTERNALWINDOW_FLAG_DRAWREQUEST 0x00000001
+#define REGISTEREXTERNALWINDOW_FLAG_PARTS_OTHEREVENT 0x0000000f
+#define REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION 0x00000010
+
+#define registerexternalwindow_setflag(window, flagx) (window)->flag = (window)->flag | (flagx)
+#define registerexternalwindow_clearflag(window, flagx) (window)->flag = (window)->flag & ~(flagx)
+#define registerexternalwindow_issetflag(window, flagx) (((window)->flag & (flagx)) == 0 ? False : True)
+
+EXPORT W registerexternalwindow_setboradnametext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W cp_len;
+
+       if (len < 1000) {
+               cp_len = len;
+       } else {
+               cp_len = 1000;
+       }
+       memcpy(window->boradname.buf+7, str, cp_len * sizeof(TC));
+       window->boradname.buf[7 + cp_len] = TNULL;
+       window->boradname.buf_written = cp_len;
+       if (window->wid < 0) {
+               return 0;
+       }
+
+       return cset_val(window->boradname.id, cp_len, (W*)(window->boradname.buf+7));
+}
+
+EXPORT W registerexternalwindow_getboradnametext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W err, cp_len;
+
+       if (window->wid > 0) {
+               err = cget_val(window->boradname.id, 1000, (W*)(window->boradname.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->boradname.buf_written = err;
+       }
+
+       if (len < window->boradname.buf_written) {
+               cp_len = len;
+       } else {
+               cp_len = window->boradname.buf_written;
+       }
+       memcpy(str, window->boradname.buf + 7, cp_len * sizeof(TC));
+
+       return cp_len;
+}
+
+EXPORT W registerexternalwindow_cutboradnametext(registerexternalwindow_t *window, TC *str, W len, Bool cut)
+{
+       W err, len0;
+
+       len0 = ccut_txt(window->boradname.id, len, str, cut == False ? 0 : 1);
+       if (len0 < 0) {
+               return len0;
+       }
+
+       if (cut != False) {
+               err = cget_val(window->boradname.id, 1000, (W*)(window->boradname.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->boradname.buf_written = err;
+               return len0;
+       }
+
+       return len0;
+}
+
+EXPORT W registerexternalwindow_insertboradnametext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W err;
+
+       err = cins_txt(window->boradname.id, (PNT){0x8000, 0x8000}, str);
+       if (err < 0) {
+               return err;
+       }
+
+       err = cget_val(window->boradname.id, 1000, (W*)(window->boradname.buf+7));
+       if (err < 0) {
+               return err;
+       }
+       window->boradname.buf_written = err;
+
+       return err;
+}
+
+LOCAL VOID registerexternalwindow_actionboradname(registerexternalwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       W i, len;
+
+       i = cact_par(window->boradname.id, wev);
+       if (i & 0x2000) {
+               window->boradname.nextaction = True;
+               switch (i) {
+               case    P_MENU:
+                       if ((wev->s.type == EV_KEYDWN)&&(wev->s.stat & ES_CMD)) {
+                               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_KEYMENU;
+                               evt->data.registerexternalwindow_boradname_keymenu.keycode = wev->e.data.key.code;
+                       } else {
+                               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MENU;
+                               evt->data.registerexternalwindow_boradname_menu.pos = wev->s.pos;
+                       }
+                       registerexternalwindow_setflag(window, REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION);
+                       break;
+               default:
+                       wugt_evt(wev);
+                       registerexternalwindow_setflag(window, REGISTEREXTERNALWINDOW_FLAG_PARTS_OTHEREVENT);
+                       break;
+               }
+               return;
+       }
+       window->boradname.nextaction = False;
+       if (i & 0x1000) {
+               len = cget_val(window->boradname.id, 1000, (W*)(window->boradname.buf+7));
+               if (len > 0) {
+                       window->boradname.buf_written = len;
+               }
+       }
+       switch (i & 7) {
+       case    P_BUT:
+               cchg_par(window->boradname.id, P_INACT);
+               cchg_par(window->boradname.id, P_ACT);
+               wugt_evt(wev);
+               break;
+       case    P_TAB:
+               break;
+       case    P_NL:
+       case    P_END:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_DETERMINE;
+               evt->data.registerexternalwindow_boradname_determine.value = window->boradname.buf+7;
+               evt->data.registerexternalwindow_boradname_determine.len = window->boradname.buf_written;
+               break;
+       case    P_MOVE:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MOVE;
+               evt->data.registerexternalwindow_boradname_move.rel_wid = wev->s.wid;
+               evt->data.registerexternalwindow_boradname_move.pos = wev->s.pos;
+               break;
+       case    P_COPY:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_COPY;
+               evt->data.registerexternalwindow_boradname_copy.rel_wid = wev->s.wid;
+               evt->data.registerexternalwindow_boradname_copy.pos = wev->s.pos;
+               break;
+       }
+}
+
+EXPORT W registerexternalwindow_seturltext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W cp_len;
+
+       if (len < 1000) {
+               cp_len = len;
+       } else {
+               cp_len = 1000;
+       }
+       memcpy(window->url.buf+7, str, cp_len * sizeof(TC));
+       window->url.buf[7 + cp_len] = TNULL;
+       window->url.buf_written = cp_len;
+       if (window->wid < 0) {
+               return 0;
+       }
+
+       return cset_val(window->url.id, cp_len, (W*)(window->url.buf+7));
+}
+
+EXPORT W registerexternalwindow_geturltext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W err, cp_len;
+
+       if (window->wid > 0) {
+               err = cget_val(window->url.id, 1000, (W*)(window->url.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->url.buf_written = err;
+       }
+
+       if (len < window->url.buf_written) {
+               cp_len = len;
+       } else {
+               cp_len = window->url.buf_written;
+       }
+       memcpy(str, window->url.buf + 7, cp_len * sizeof(TC));
+
+       return cp_len;
+}
+
+EXPORT W registerexternalwindow_cuturltext(registerexternalwindow_t *window, TC *str, W len, Bool cut)
+{
+       W err, len0;
+
+       len0 = ccut_txt(window->url.id, len, str, cut == False ? 0 : 1);
+       if (len0 < 0) {
+               return len0;
+       }
+
+       if (cut != False) {
+               err = cget_val(window->url.id, 1000, (W*)(window->url.buf+7));
+               if (err < 0) {
+                       return err;
+               }
+               window->url.buf_written = err;
+               return len0;
+       }
+
+       return len0;
+}
+
+EXPORT W registerexternalwindow_inserturltext(registerexternalwindow_t *window, TC *str, W len)
+{
+       W err;
+
+       err = cins_txt(window->url.id, (PNT){0x8000, 0x8000}, str);
+       if (err < 0) {
+               return err;
+       }
+
+       err = cget_val(window->url.id, 1000, (W*)(window->url.buf+7));
+       if (err < 0) {
+               return err;
+       }
+       window->url.buf_written = err;
+
+       return err;
+}
+
+LOCAL VOID registerexternalwindow_actionurl(registerexternalwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       W i, len;
+
+       i = cact_par(window->url.id, wev);
+       if (i & 0x2000) {
+               window->url.nextaction = True;
+               switch (i) {
+               case    P_MENU:
+                       if ((wev->s.type == EV_KEYDWN)&&(wev->s.stat & ES_CMD)) {
+                               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_KEYMENU;
+                               evt->data.registerexternalwindow_url_keymenu.keycode = wev->e.data.key.code;
+                       } else {
+                               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MENU;
+                               evt->data.registerexternalwindow_url_menu.pos = wev->s.pos;
+                       }
+                       registerexternalwindow_setflag(window, REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION);
+                       break;
+               default:
+                       wugt_evt(wev);
+                       registerexternalwindow_setflag(window, REGISTEREXTERNALWINDOW_FLAG_PARTS_OTHEREVENT);
+                       break;
+               }
+               return;
+       }
+       window->url.nextaction = False;
+       if (i & 0x1000) {
+               len = cget_val(window->url.id, 1000, (W*)(window->url.buf+7));
+               if (len > 0) {
+                       window->url.buf_written = len;
+               }
+       }
+       switch (i & 7) {
+       case    P_BUT:
+               cchg_par(window->url.id, P_INACT);
+               cchg_par(window->url.id, P_ACT);
+               wugt_evt(wev);
+               break;
+       case    P_TAB:
+               break;
+       case    P_NL:
+       case    P_END:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_DETERMINE;
+               evt->data.registerexternalwindow_url_determine.value = window->url.buf+7;
+               evt->data.registerexternalwindow_url_determine.len = window->url.buf_written;
+               break;
+       case    P_MOVE:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MOVE;
+               evt->data.registerexternalwindow_url_move.rel_wid = wev->s.wid;
+               evt->data.registerexternalwindow_url_move.pos = wev->s.pos;
+               break;
+       case    P_COPY:
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_COPY;
+               evt->data.registerexternalwindow_url_copy.rel_wid = wev->s.wid;
+               evt->data.registerexternalwindow_url_copy.pos = wev->s.pos;
+               break;
+       }
+}
+
+EXPORT Bool registerexternalwindow_isopen(registerexternalwindow_t *window)
+{
+       if (window->wid < 0) {
+               return False;
+       }
+       return True;
+}
+
+LOCAL VOID registerexternalwindow_draw(registerexternalwindow_t *window, RECT *r)
+{
+       cdsp_pwd(window->wid, r, P_RDISP);
+       gset_chc(window->gid, 0x10000000, -1);
+       gdra_stp(window->gid, 8, 26, (TC[]){0x4844, 0x4c3e, 0x2127, TNULL}, 3, G_STORE);
+       gset_chc(window->gid, 0x10000000, -1);
+       gdra_stp(window->gid, 8, 58, (TC[]){0x2355, 0x2352, 0x234c, 0x2127, TNULL}, 4, G_STORE);
+}
+
+LOCAL VOID registerexternalwindow_redisp(registerexternalwindow_t *window)
+{
+       RECT r;
+       do {
+               if (wsta_dsp(window->wid, &r, NULL) == 0) {
+                       break;
+               }
+               wera_wnd(window->wid, &r);
+               registerexternalwindow_draw(window, &r);
+       } while (wend_dsp(window->wid) > 0);
+}
+
+EXPORT W registerexternalwindow_requestredisp(registerexternalwindow_t *window)
+{
+       return wreq_dsp(window->wid);
+}
+
+EXPORT GID registerexternalwindow_getGID(registerexternalwindow_t *window)
+{
+       return wget_gid(window->wid);
+}
+
+EXPORT WID registerexternalwindow_getWID(registerexternalwindow_t *window)
+{
+       return window->wid;
+}
+
+EXPORT W registerexternalwindow_settitle(registerexternalwindow_t *window, TC *title)
+{
+       tc_strncpy(window->title, title, 256);
+       window->title[256] = TNULL;
+       return wset_tit(window->wid, -1, window->title, 0);
+}
+
+EXPORT Bool registerexternalwindow_isactive(registerexternalwindow_t *window)
+{
+       WID wid;
+       wid = wget_act(NULL);
+       if (window->wid == wid) {
+               return True;
+       }
+       return False;
+}
+
+LOCAL VOID registerexternalwindow_butdnwork(registerexternalwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       PAID id;
+       W ret;
+
+       ret = cfnd_par(window->wid, wev->s.pos, &id);
+       if (ret <= 0) {
+               return;
+       }
+       if (id == window->boradname.id) {
+               memcpy(&window->savedwev, wev, sizeof(WEVENT));
+               registerexternalwindow_actionboradname(window, wev, evt);
+               return;
+       }
+       if (id == window->url.id) {
+               memcpy(&window->savedwev, wev, sizeof(WEVENT));
+               registerexternalwindow_actionurl(window, wev, evt);
+               return;
+       }
+       if (id == window->determine.id) {
+               ret = cact_par(window->determine.id, wev);
+               if ((ret & 0x5000) != 0x5000) {
+                       return;
+               }
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_DETERMINE_PUSH;
+               return;
+       }
+       if (id == window->cancel.id) {
+               ret = cact_par(window->cancel.id, wev);
+               if ((ret & 0x5000) != 0x5000) {
+                       return;
+               }
+               evt->type = BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_CANCEL_PUSH;
+               return;
+       }
+}
+
+EXPORT W registerexternalwindow_open(registerexternalwindow_t *window)
+{
+       WID wid;
+       RECT r;
+
+       if (window->wid > 0) {
+               return 0;
+       }
+
+       wid = wopn_wnd(WA_STD, window->parent, &(window->r), NULL, 2, window->title, &window->bgpat, NULL);
+       if (wid < 0) {
+               DP_ER("wopn_wnd: subjectoption error", wid);
+               return wid;
+       }
+       window->wid = wid;
+       window->gid = wget_gid(wid);
+
+       r = (RECT){{80, 8, 368, 34}};
+       window->boradname.id = ccre_tbx(wid, TB_PARTS|P_DISP, &r, 1000, window->boradname.buf, NULL);
+       if (window->boradname.id < 0) {
+               DP_ER("ccre_xxx boradname error:", window->boradname.id);
+       }
+       r = (RECT){{80, 38, 368, 64}};
+       window->url.id = ccre_tbx(wid, TB_PARTS|P_DISP, &r, 1000, window->url.buf, NULL);
+       if (window->url.id < 0) {
+               DP_ER("ccre_xxx url error:", window->url.id);
+       }
+       r = (RECT){{226, 72, 368, 98}};
+       window->determine.id = ccre_msw(wid, MS_PARTS|P_DISP, &r, (TC[]){MC_STR, 0x4449, 0x3243, TNULL}, NULL);
+       if (window->determine.id < 0) {
+               DP_ER("ccre_xxx determine error:", window->determine.id);
+       }
+       r = (RECT){{8, 72, 150, 98}};
+       window->cancel.id = ccre_msw(wid, MS_PARTS|P_DISP, &r, (TC[]){MC_STR, 0x3c68, 0x246a, 0x3e43, 0x2437, TNULL}, NULL);
+       if (window->cancel.id < 0) {
+               DP_ER("ccre_xxx cancel error:", window->cancel.id);
+       }
+
+       wreq_dsp(wid);
+
+       return 0;
+}
+
+EXPORT VOID registerexternalwindow_close(registerexternalwindow_t *window)
+{
+       WDSTAT stat;
+       W err;
+
+       if (window->wid < 0) {
+               return;
+       }
+
+       stat.attr = WA_STD;
+       err = wget_sts(window->wid, &stat, NULL);
+       if (err >= 0) {
+               window->r = stat.r;
+       }
+       err = cget_val(window->url.id, 1000, (W*)(window->url.buf+7));
+       if (err >= 0) {
+               window->url.buf_written = err;
+       }
+       err = cget_val(window->boradname.id, 1000, (W*)(window->boradname.buf+7));
+       if (err >= 0) {
+               window->boradname.buf_written = err;
+       }
+       cdel_pwd(window->wid, NOCLR);
+       wcls_wnd(window->wid, CLR);
+       window->wid = -1;
+       window->gid = -1;
+}
+
+#define EXTERNALBBSWINDOW_FLAG_DRAWREQUEST 0x00000001
+#define EXTERNALBBSWINDOW_FLAG_RSCROLLING 0x00000002
+#define EXTERNALBBSWINDOW_FLAG_BSCROLLING 0x00000004
+
+#define externalbbswindow_setflag(window, flagx) (window)->flag = (window)->flag | (flagx)
+#define externalbbswindow_clearflag(window, flagx) (window)->flag = (window)->flag & ~(flagx)
+#define externalbbswindow_issetflag(window, flagx) (((window)->flag & (flagx)) == 0 ? False : True)
+
+EXPORT VOID externalbbswindow_scrollbyvalue(externalbbswindow_t *window, W dh, W dv)
+{
+       hmi_windowscroll_scrollworkrect(&window->wscr, dh, dv);
+}
+
+EXPORT W externalbbswindow_setdrawrect(externalbbswindow_t *window, W l, W t, W r, W b)
+{
+       return hmi_windowscroll_setdrawrect(&window->wscr, l, t, r, b);
+}
+
+EXPORT W externalbbswindow_setworkrect(externalbbswindow_t *window, W l, W t, W r, W b)
+{
+       return hmi_windowscroll_setworkrect(&window->wscr, l, t, r, b);
+}
+
+EXPORT W externalbbswindow_scrollworkarea(externalbbswindow_t *window, W dh, W dv)
+{
+       W err;
+       err = wscr_wnd(window->wid, NULL, dh, dv, W_MOVE|W_RDSET);
+       if (err < 0) {
+               return err;
+       }
+       if ((err & W_RDSET) != 0) {
+               externalbbswindow_setflag(window, EXTERNALBBSWINDOW_FLAG_DRAWREQUEST);
+       }
+       return 0;
+}
+
+EXPORT W externalbbswindow_getworkrect(externalbbswindow_t *window, RECT *r)
+{
+       return wget_wrk(window->wid, r);
+}
+
+EXPORT Bool externalbbswindow_isopen(externalbbswindow_t *window)
+{
+       if (window->wid < 0) {
+               return False;
+       }
+       return True;
+}
+
+EXPORT VOID externalbbswindow_responsepasterequest(externalbbswindow_t *window, W nak, PNT *pos)
+{
+       if (pos != NULL) {
+               window->savedwev.r.r.p.rightbot.x = pos->x;
+               window->savedwev.r.r.p.rightbot.y = pos->y;
+       }
+       wrsp_evt(&window->savedwev, nak);
+}
+
+EXPORT W externalbbswindow_startredisp(externalbbswindow_t *window, RECT *r)
+{
+       return wsta_dsp(window->wid, r, NULL);
+}
+
+EXPORT W externalbbswindow_endredisp(externalbbswindow_t *window)
+{
+       return wend_dsp(window->wid);
+}
+
+EXPORT W externalbbswindow_eraseworkarea(externalbbswindow_t *window, RECT *r)
+{
+       return wera_wnd(window->wid, r);
+}
+
+EXPORT W externalbbswindow_requestredisp(externalbbswindow_t *window)
+{
+       return wreq_dsp(window->wid);
+}
+
+EXPORT GID externalbbswindow_startdrag(externalbbswindow_t *window)
+{
+       return wsta_drg(window->wid, 0);
+}
+
+EXPORT W externalbbswindow_getdrag(externalbbswindow_t *window, PNT *pos, WID *wid, PNT *pos_butup)
+{
+       W etype;
+
+       etype = wget_drg(pos, &window->savedwev);
+       *wid = window->savedwev.s.wid;
+       if (etype == EV_BUTUP) {
+               *pos_butup = window->savedwev.s.pos;
+       }
+
+       return etype;
+}
+
+EXPORT VOID externalbbswindow_enddrag(externalbbswindow_t *window)
+{
+       wend_drg();
+}
+
+EXPORT GID externalbbswindow_getGID(externalbbswindow_t *window)
+{
+       return wget_gid(window->wid);
+}
+
+EXPORT WID externalbbswindow_getWID(externalbbswindow_t *window)
+{
+       return window->wid;
+}
+
+EXPORT W externalbbswindow_settitle(externalbbswindow_t *window, TC *title)
+{
+       tc_strncpy(window->title, title, 256);
+       window->title[256] = TNULL;
+       return wset_tit(window->wid, -1, window->title, 0);
+}
+
+EXPORT Bool externalbbswindow_isactive(externalbbswindow_t *window)
+{
+       WID wid;
+       wid = wget_act(NULL);
+       if (window->wid == wid) {
+               return True;
+       }
+       return False;
+}
+
+LOCAL VOID externalbbswindow_butdnwork(externalbbswindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_BUTDN;
+       evt->data.externalbbswindow_butdn.type = wchk_dck(wev->s.time);
+       evt->data.externalbbswindow_butdn.pos = wev->s.pos;
+       memcpy(&window->savedwev, wev, sizeof(WEVENT));
+}
+
+LOCAL VOID externalbbswindow_resize(externalbbswindow_t *window, SIZE *sz)
 {
-       W ret, len0;
-       WEVENT *wev;
+       RECT work;
+       Bool workchange = False;
 
-       if (window->tb_appended == True) {
-               return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
+       wget_wrk(window->wid, &work);
+       if (work.c.left != 0) {
+               work.c.left = 0;
+               workchange = True;
        }
+       if (work.c.top != 0) {
+               work.c.top = 0;
+               workchange = True;
+       }
+       wset_wrk(window->wid, &work);
+       gset_vis(window->gid, work);
 
-       wev = &window->savedwev;
-
-       for (;;) {
-               ret = cact_par(window->tb_filter_id, wev);
-               if (ret < 0) {
-                       DP_ER("cact_par tb_filter_id error:", ret);
-                       return ret;
-               }
-               switch (ret & 0xefff) {
-               case P_EVENT:
-                       switch (wev->s.type) {
-                       case EV_INACT:
-                       case EV_REQUEST:
-                               wugt_evt(wev);
-                               return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
-                       case EV_DEVICE:
-                               oprc_dev(&wev->e, NULL, 0);
-                               break;
-                       }
-                       wev->s.type = EV_NULL;
-                       continue;
-               case P_MENU:
-                       wev->s.type = EV_NULL;
-                       if ((wev->s.type == EV_KEYDWN)&&(wev->s.stat & ES_CMD)) {
-                               *key = wev->e.data.key.code;
-                               return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_KEYMENU;
-                       }
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_MENU;
-               case (0x4000|P_MOVE):
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_MOVE;
-               case (0x4000|P_COPY):
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_COPY;
-               case (0x4000|P_NL):
-                       len0 = cget_val(window->tb_filter_id, 128, (W*)window->strbuf);
-                       if (len0 <= 0) {
-                               return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
-                       }
-                       *val = window->strbuf;
-                       *len = len0;
-                       window->tb_appended = True;
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_APPEND;
-               case (0x4000|P_TAB):
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
-               case (0x4000|P_BUT):
-                       wugt_evt(wev);
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
-               default:
-                       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
-               }
+       if (workchange == True) {
+               wera_wnd(window->wid, NULL);
+               wreq_dsp(window->wid);
        }
 
-       return SUBJECTOPTIONWINDOW_GETTEXTBOXACTION_FINISH;
+       sz->v = work.c.bottom - work.c.top;
+       sz->h = work.c.right - work.c.left;
 }
 
-EXPORT W subjectoptionwindow_endtextboxaction(subjectoptionwindow_t *window)
+EXPORT W externalbbswindow_open(externalbbswindow_t *window)
 {
+       WID wid;
+
+       if (window->wid > 0) {
+               return 0;
+       }
+
+       wid = wopn_wnd(WA_STD|WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, window->parent, &(window->r), NULL, 2, window->title, &window->bgpat, NULL);
+       if (wid < 0) {
+               DP_ER("wopn_wnd: subjectoption error", wid);
+               return wid;
+       }
+       window->wid = wid;
+       window->gid = wget_gid(wid);
+       hmi_windowscroll_settarget(&window->wscr, wid);
+
+
+       wreq_dsp(wid);
+
        return 0;
 }
 
-LOCAL VOID subjectoptionwindow_draw(subjectoptionwindow_t *window, RECT *r)
+EXPORT VOID externalbbswindow_close(externalbbswindow_t *window)
 {
-       cdsp_pwd(window->wid, r, P_RDISP);
-}
+       WDSTAT stat;
+       W err;
 
-LOCAL VOID subjectoptionwindow_redisp(subjectoptionwindow_t *window)
-{
-       RECT r;
-       do {
-               if (wsta_dsp(window->wid, &r, NULL) == 0) {
-                       break;
-               }
-               wera_wnd(window->wid, &r);
-               subjectoptionwindow_draw(window, &r);
-       } while (wend_dsp(window->wid) > 0);
+       if (window->wid < 0) {
+               return;
+       }
+
+       stat.attr = WA_STD;
+       err = wget_sts(window->wid, &stat, NULL);
+       if (err >= 0) {
+               window->r = stat.r;
+       }
+       wcls_wnd(window->wid, CLR);
+       window->wid = -1;
+       window->gid = -1;
 }
 
 LOCAL VOID bchanlhmi_setswitchbutdnflag(bchanlhmi_t *hmi)
@@ -538,195 +1549,206 @@ LOCAL Bool bchanlhmi_issetswitchbutdnflag(bchanlhmi_t *hmi)
        return True;
 }
 
-LOCAL WID bchanlhmi_getsubjectWID(bchanlhmi_t *hmi)
+LOCAL Bool bchanlhmi_issubjectwindowWID(bchanlhmi_t *hmi, WID wid)
 {
-       if (hmi->subjectwindow == NULL) {
-               return -1;
+       if (hmi->subjectwindow->wid == wid) {
+               return True;
        }
-       return hmi->subjectwindow->wid;
+       return False;
 }
 
-LOCAL WID bchanlhmi_getbbsmenuWID(bchanlhmi_t *hmi)
+LOCAL Bool bchanlhmi_isbbsmenuwindowWID(bchanlhmi_t *hmi, WID wid)
 {
-       if (hmi->bbsmenuwindow == NULL) {
-               return -1;
+       if (hmi->bbsmenuwindow->wid == wid) {
+               return True;
        }
-       return hmi->bbsmenuwindow->wid;
+       return False;
 }
 
-LOCAL WID bchanlhmi_getsubjectoptionWID(bchanlhmi_t *hmi)
+LOCAL Bool bchanlhmi_issubjectoptionwindowWID(bchanlhmi_t *hmi, WID wid)
 {
-       if (hmi->subjectoptionwindow == NULL) {
-               return -1;
+       if (hmi->subjectoptionwindow->wid == wid) {
+               return True;
        }
-       return hmi->subjectoptionwindow->wid;
+       return False;
 }
 
-LOCAL VOID bchanlhmi_weventrequest(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
+LOCAL Bool bchanlhmi_isregisterexternalwindowWID(bchanlhmi_t *hmi, WID wid)
+{
+       if (hmi->registerexternalwindow->wid == wid) {
+               return True;
+       }
+       return False;
+}
+
+LOCAL Bool bchanlhmi_isexternalbbswindowWID(bchanlhmi_t *hmi, WID wid)
 {
-       WID subject_wid, bbsmenu_wid, subjectoption_wid;
+       if (hmi->externalbbswindow->wid == wid) {
+               return True;
+       }
+       return False;
+}
 
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       bbsmenu_wid = bchanlhmi_getbbsmenuWID(hmi);
-       subjectoption_wid = bchanlhmi_getsubjectoptionWID(hmi);
+LOCAL VOID bchanlhmi_weventnull(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
+{
+       cidl_par(wev->s.wid, &wev->s.pos);
+       if (wev->s.cmd != W_WORK)
+               return;         /*ºî¶ÈÎΰ賰*/
+       if (wev->s.stat & ES_CMD)
+               return; /*Ì¿Îᥭ¡¼¤¬²¡¤µ¤ì¤Æ¤¤¤ë*/
+       if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_MOUSEMOVE;
+               hmi->evt.data.subjectwindow_mousemove.pos = wev->s.pos;
+               hmi->evt.data.subjectwindow_mousemove.stat = wev->s.stat;
+               return;
+       }
+       if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_MOUSEMOVE;
+               hmi->evt.data.bbsmenuwindow_mousemove.pos = wev->s.pos;
+               hmi->evt.data.bbsmenuwindow_mousemove.stat = wev->s.stat;
+               return;
+       }
+       if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->s.wid) == True) {
+               cidl_par(wev->s.wid, &wev->s.pos);
+               return;
+       }
+       if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->s.wid) == True) {
+               cidl_par(wev->s.wid, &wev->s.pos);
+               return;
+       }
+       if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+               gset_ptr(PS_SELECT, NULL, -1, -1);
+               return;
+       }
+       /*¥¦¥£¥ó¥É¥¦³°*/
+       hmi->evt.type = BCHANLHMIEVENT_TYPE_COMMON_MOUSEMOVE;
+       hmi->evt.data.common_mousemove.pos = wev->s.pos;
+}
 
+LOCAL VOID bchanlhmi_weventrequest(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
+{
        switch (wev->g.cmd) {
        case    W_REDISP:       /*ºÆɽ¼¨Í×µá*/
-               if (wev->g.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_DRAW;
-               } else if (wev->g.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_DRAW;
-               } else if (wev->g.wid == subjectoption_wid) {
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW;
+                       break;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW;
+                       break;
+               }
+               if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->g.wid) == True) {
                        subjectoptionwindow_redisp(hmi->subjectoptionwindow);
+                       break;
+               }
+               if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->g.wid) == True) {
+                       registerexternalwindow_redisp(hmi->registerexternalwindow);
+                       break;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW;
+                       break;
                }
                break;
        case    W_PASTE:        /*Ž¹þ¤ßÍ×µá*/
-               if (wev->g.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_PASTE;
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_PASTE;
                        memcpy(&hmi->subjectwindow->savedwev, wev, sizeof(WEVENT));
-               } else if (wev->g.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_PASTE;
-                       memcpy(&hmi->bbsmenuwindow->savedwev, wev, sizeof(WEVENT));
-               } else {
-                       wrsp_evt(wev, 1); /*NACK*/
+                       break;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_PASTE;
+                       memcpy(&hmi->externalbbswindow->savedwev, wev, sizeof(WEVENT));
+                       break;
                }
+               wrsp_evt(wev, 1); /*NACK*/
                break;
        case    W_DELETE:       /*Êݸ½ªÎ»*/
                wrsp_evt(wev, 0);       /*ACK*/
-               if (wev->g.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_CLOSE;
-                       evt->data.subject_close.save = True;
-               } else if (wev->g.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_CLOSE;
-                       evt->data.bbsmenu_close.save = True;
-               } else if (wev->g.wid == subjectoption_wid) {
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_CLOSE;
+                       evt->data.subjectwindow_close.save = True;
+                       break;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_CLOSE;
+                       evt->data.bbsmenuwindow_close.save = True;
+                       break;
+               }
+               if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->g.wid) == True) {
                        subjectoptionwindow_close(hmi->subjectoptionwindow);
+                       break;
+               }
+               if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->g.wid) == True) {
+                       registerexternalwindow_close(hmi->registerexternalwindow);
+                       break;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_CLOSE;
+                       evt->data.externalbbswindow_close.save = True;
+                       break;
                }
                break;
        case    W_FINISH:       /*ÇÑ´þ½ªÎ»*/
                wrsp_evt(wev, 0);       /*ACK*/
-               if (wev->g.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_CLOSE;
-                       evt->data.subject_close.save = False;
-               } else if (wev->g.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_CLOSE;
-                       evt->data.bbsmenu_close.save = False;
-               } else if (wev->g.wid == subjectoption_wid) {
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_CLOSE;
+                       evt->data.subjectwindow_close.save = False;
+                       break;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_CLOSE;
+                       evt->data.bbsmenuwindow_close.save = False;
+                       break;
+               }
+               if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->g.wid) == True) {
                        subjectoptionwindow_close(hmi->subjectoptionwindow);
+                       break;
                }
-               break;
-       }
-}
-
-LOCAL VOID subjectwindow_resize(subjectwindow_t *window, SIZE *sz)
-{
-       RECT work;
-       Bool workchange = False;
-
-       wget_wrk(window->wid, &work);
-       if (work.c.left != 0) {
-               work.c.left = 0;
-               workchange = True;
-       }
-       if (work.c.top != 0) {
-               work.c.top = 0;
-               workchange = True;
-       }
-       wset_wrk(window->wid, &work);
-       gset_vis(window->gid, work);
-
-       if (workchange == True) {
-               wera_wnd(window->wid, NULL);
-               wreq_dsp(window->wid);
-       }
-
-       sz->v = work.c.bottom - work.c.top;
-       sz->h = work.c.right - work.c.left;
-}
-
-LOCAL VOID bbsmenuwindow_resize(bbsmenuwindow_t *window, SIZE *sz)
-{
-       RECT work;
-       Bool workchange = False;
-
-       wget_wrk(window->wid, &work);
-       if (work.c.left != 0) {
-               work.c.left = 0;
-               workchange = True;
-       }
-       if (work.c.top != 0) {
-               work.c.top = 0;
-               workchange = True;
-       }
-       wset_wrk(window->wid, &work);
-       gset_vis(window->gid, work);
-
-       if (workchange == True) {
-               wera_wnd(window->wid, NULL);
-               wreq_dsp(window->wid);
-       }
-
-       sz->v = work.c.bottom - work.c.top;
-       sz->h = work.c.right - work.c.left;
-}
-
-LOCAL VOID subjectoptionwindow_butdnwork(subjectoptionwindow_t *window, WEVENT *wev, bchanlhmievent_t *evt)
-{
-       PAID id;
-       W ret;
-
-       ret = cfnd_par(window->wid, wev->s.pos, &id);
-       if (ret <= 0) {
-               return;
-       }
-       if (id == window->tb_filter_id) {
-               memcpy(&window->savedwev, wev, sizeof(WEVENT));
-               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTION_TEXTBOX;
-               return;
-       }
-       if (id == window->ws_order_id) {
-               ret = cact_par(window->ws_order_id, wev);
-               if ((ret & 0x5000) != 0x5000) {
-                       return;
+               if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->g.wid) == True) {
+                       registerexternalwindow_close(hmi->registerexternalwindow);
+                       break;
                }
-               window->order = ret & 0xfff;
-               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTION_CHANGEORDER;
-               evt->data.subjectoption_changeorder.order = window->order;
-               return;
-       }
-       if (id == window->ws_orderby_id) {
-               ret = cact_par(window->ws_orderby_id, wev);
-               if ((ret & 0x5000) != 0x5000) {
-                       return;
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->g.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_CLOSE;
+                       evt->data.externalbbswindow_close.save = False;
+                       break;
                }
-               window->orderby = ret & 0xfff;
-               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTOPTION_CHANGEORDERBY;
-               evt->data.subjectoption_changeorderby.orderby = window->orderby;
-               return;
+               break;
        }
 }
 
 LOCAL VOID bchanlhmi_weventbutdn(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
 {
-       W i;
-       WID subject_wid, bbsmenu_wid, subjectoption_wid;
-
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       bbsmenu_wid = bchanlhmi_getbbsmenuWID(hmi);
-       subjectoption_wid = bchanlhmi_getsubjectoptionWID(hmi);
+       W i, err;
+       W dh, dv; /* TODO: add check for exist scrollable window */
 
        switch  (wev->s.cmd) {
        case    W_PICT:
                switch (wchk_dck(wev->s.time)) {
                case    W_DCLICK:
-                       if (wev->s.wid == subject_wid) {
-                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_CLOSE;
-                               evt->data.subject_close.save = True; /* TODO: tmp value. */
-                       } else if (wev->s.wid == bbsmenu_wid) {
-                               evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_CLOSE;
-                               evt->data.bbsmenu_close.save = True; /* TODO: tmp value. */
-                       } else if (wev->s.wid == subjectoption_wid) {
+                       if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_CLOSE;
+                               evt->data.subjectwindow_close.save = True; /* TODO: tmp value */
+                               return;
+                       }
+                       if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_CLOSE;
+                               evt->data.bbsmenuwindow_close.save = True; /* TODO: tmp value */
+                               return;
+                       }
+                       if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->s.wid) == True) {
                                subjectoptionwindow_close(hmi->subjectoptionwindow);
+                               return;
+                       }
+                       if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->s.wid) == True) {
+                               registerexternalwindow_close(hmi->registerexternalwindow);
+                               return;
+                       }
+                       if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_CLOSE;
+                               evt->data.externalbbswindow_close.save = True; /* TODO: tmp value */
+                               return;
                        }
                        return;
                case    W_PRESS:
@@ -737,12 +1759,25 @@ LOCAL VOID bchanlhmi_weventbutdn(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t
        case    W_FRAM:
        case    W_TITL:
                if (wmov_drg(wev, NULL) > 0) {
-                       if (wev->s.wid == subject_wid) {
-                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_DRAW;
-                       } else if (wev->s.wid == bbsmenu_wid) {
-                               evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_DRAW;
-                       } else if (wev->s.wid == subjectoption_wid) {
+                       if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW;
+                               return;
+                       }
+                       if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW;
+                               return;
+                       }
+                       if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->s.wid) == True) {
                                subjectoptionwindow_redisp(hmi->subjectoptionwindow);
+                               return;
+                       }
+                       if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->s.wid) == True) {
+                               registerexternalwindow_redisp(hmi->registerexternalwindow);
+                               return;
+                       }
+                       if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                               evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW;
+                               return;
                        }
                }
                return;
@@ -761,60 +1796,148 @@ LOCAL VOID bchanlhmi_weventbutdn(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t
                        return;
                }
 
-               if (wev->s.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_RESIZE;
-                       subjectwindow_resize(hmi->subjectwindow, &evt->data.subject_resize.work_sz);
-                       windowscroll_updatebar(&hmi->subjectwindow->wscr);
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_RESIZE;
+                       subjectwindow_resize(hmi->subjectwindow, &evt->data.subjectwindow_resize.work_sz);
+                       hmi_windowscroll_updatebar(&hmi->subjectwindow->wscr);
                        if (i > 0) {
-                               //evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_DRAW;
-                               /* TODO: queueing */
-                               evt->data.subject_resize.needdraw = True;
-                       } else {
-                               evt->data.subject_resize.needdraw = False;
+                               subjectwindow_setflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_DRAWREQUEST);
                        }
-               } else if (wev->s.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_RESIZE;
-                       bbsmenuwindow_resize(hmi->bbsmenuwindow, &evt->data.bbsmenu_resize.work_sz);
-                       windowscroll_updatebar(&hmi->bbsmenuwindow->wscr);
+                       return;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_RESIZE;
+                       bbsmenuwindow_resize(hmi->bbsmenuwindow, &evt->data.bbsmenuwindow_resize.work_sz);
+                       hmi_windowscroll_updatebar(&hmi->bbsmenuwindow->wscr);
+                       if (i > 0) {
+                               bbsmenuwindow_setflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_DRAWREQUEST);
+                       }
+                       return;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_RESIZE;
+                       externalbbswindow_resize(hmi->externalbbswindow, &evt->data.externalbbswindow_resize.work_sz);
+                       hmi_windowscroll_updatebar(&hmi->externalbbswindow->wscr);
                        if (i > 0) {
-                               //evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_DRAW;
-                               /* TODO: queueing */
-                               evt->data.bbsmenu_resize.needdraw = True;
+                               externalbbswindow_setflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_DRAWREQUEST);
+                       }
+                       return;
+               }
+               return;
+       case    W_RBAR:
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventrbar(&hmi->subjectwindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING);
+                       } else {
+                               subjectwindow_setflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING);
+                       }
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL;
+                       evt->data.subjectwindow_scroll.dh = dh;
+                       evt->data.subjectwindow_scroll.dv = dv;
+                       return;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventrbar(&hmi->bbsmenuwindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING);
+                       } else {
+                               bbsmenuwindow_setflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING);
+                       }
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL;
+                       evt->data.bbsmenuwindow_scroll.dh = dh;
+                       evt->data.bbsmenuwindow_scroll.dv = dv;
+                       return;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventrbar(&hmi->externalbbswindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING);
+                       } else {
+                               externalbbswindow_setflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING);
+                       }
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL;
+                       evt->data.externalbbswindow_scroll.dh = dh;
+                       evt->data.externalbbswindow_scroll.dv = dv;
+                       return;
+               }
+               return;
+       case    W_BBAR:
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventbbar(&hmi->subjectwindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING);
+                       } else {
+                               subjectwindow_setflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING);
+                       }
+                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL;
+                       evt->data.subjectwindow_scroll.dh = dh;
+                       evt->data.subjectwindow_scroll.dv = dv;
+                       return;
+               }
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventbbar(&hmi->bbsmenuwindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING);
+                       } else {
+                               bbsmenuwindow_setflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING);
+                       }
+                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL;
+                       evt->data.bbsmenuwindow_scroll.dh = dh;
+                       evt->data.bbsmenuwindow_scroll.dv = dv;
+                       return;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                       err = hmi_windowscroll_weventbbar(&hmi->externalbbswindow->wscr, wev, &dh, &dv);
+                       if (err < 0) {
+                               return;
+                       }
+                       if (err == 0) {
+                               externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING);
                        } else {
-                               evt->data.bbsmenu_resize.needdraw = False;
+                               externalbbswindow_setflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING);
                        }
+                       evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL;
+                       evt->data.externalbbswindow_scroll.dh = dh;
+                       evt->data.externalbbswindow_scroll.dv = dv;
+                       return;
                }
-               /* subject option window need not do nothing. */
                return;
-       case    W_RBAR:
-               if (wev->s.wid == subject_wid) {
-                       windowscroll_weventrbar(&hmi->subjectwindow->wscr, wev);
-               } else if (wev->s.wid == bbsmenu_wid) {
-                       windowscroll_weventrbar(&hmi->bbsmenuwindow->wscr, wev);
+       case    W_WORK:
+               if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+                       subjectwindow_butdnwork(hmi->subjectwindow, wev, evt);
+                       return;
                }
-               /* subject option window need not do nothing. */
-               return;
-       case    W_BBAR:
-               if (wev->s.wid == subject_wid) {
-                       windowscroll_weventbbar(&hmi->subjectwindow->wscr, wev);
-               } else if (wev->s.wid == bbsmenu_wid) {
-                       windowscroll_weventbbar(&hmi->bbsmenuwindow->wscr, wev);
+               if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+                       bbsmenuwindow_butdnwork(hmi->bbsmenuwindow, wev, evt);
+                       return;
                }
-               /* subject option window need not do nothing. */
-               return;
-       case    W_WORK:
-               if (wev->s.wid == subject_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_BUTDN;
-                       evt->data.subject_butdn.type = wchk_dck(wev->s.time);
-                       evt->data.subject_butdn.pos = wev->s.pos;
-                       memcpy(&hmi->subjectwindow->savedwev, wev, sizeof(WEVENT));
-               } else if (wev->s.wid == bbsmenu_wid) {
-                       evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_BUTDN;
-                       evt->data.bbsmenu_butdn.type = wchk_dck(wev->s.time);
-                       evt->data.bbsmenu_butdn.pos = wev->s.pos;
-                       memcpy(&hmi->bbsmenuwindow->savedwev, wev, sizeof(WEVENT));
-               } else if (wev->s.wid == subjectoption_wid) {
+               if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->s.wid) == True) {
                        subjectoptionwindow_butdnwork(hmi->subjectoptionwindow, wev, evt);
+                       return;
+               }
+               if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->s.wid) == True) {
+                       registerexternalwindow_butdnwork(hmi->registerexternalwindow, wev, evt);
+                       return;
+               }
+               if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+                       externalbbswindow_butdnwork(hmi->externalbbswindow, wev, evt);
+                       return;
                }
                return;
        }
@@ -824,39 +1947,29 @@ LOCAL VOID bchanlhmi_weventbutdn(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t
 
 LOCAL VOID bchanlhmi_weventswitch(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
 {
-       WID subject_wid, bbsmenu_wid;
-
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       bbsmenu_wid = bchanlhmi_getbbsmenuWID(hmi);
-
-       if (wev->s.wid == subject_wid) {
-               evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_SWITCH;
-               evt->data.subject_switch.needdraw = False;
-       } else if (wev->s.wid == bbsmenu_wid) {
-               evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_SWITCH;
-               evt->data.bbsmenu_switch.needdraw = False;
-       }
        bchanlhmi_setswitchbutdnflag(hmi);
 }
 
 LOCAL VOID bchanlhmi_weventreswitch(bchanlhmi_t *hmi, WEVENT *wev, bchanlhmievent_t *evt)
 {
-       WID subject_wid, bbsmenu_wid, subjectoption_wid;
-
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       bbsmenu_wid = bchanlhmi_getbbsmenuWID(hmi);
-       subjectoption_wid = bchanlhmi_getsubjectoptionWID(hmi);
-
-       if (wev->s.wid == subject_wid) {
-               evt->type = BCHANLHMIEVENT_TYPE_SUBJECT_SWITCH;
-               evt->data.subject_switch.needdraw = True;
-       } else if (wev->s.wid == bbsmenu_wid) {
-               evt->type = BCHANLHMIEVENT_TYPE_BBSMENU_SWITCH;
-               evt->data.bbsmenu_switch.needdraw = True;
-       } else if (wev->s.wid == subjectoption_wid) {
+       bchanlhmi_setswitchbutdnflag(hmi);
+       if (bchanlhmi_issubjectwindowWID(hmi, wev->s.wid) == True) {
+               evt->type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW;
+       }
+       if (bchanlhmi_isbbsmenuwindowWID(hmi, wev->s.wid) == True) {
+               evt->type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW;
+       }
+       if (bchanlhmi_issubjectoptionwindowWID(hmi, wev->s.wid) == True) {
                subjectoptionwindow_redisp(hmi->subjectoptionwindow);
+               return;
+       }
+       if (bchanlhmi_isregisterexternalwindowWID(hmi, wev->s.wid) == True) {
+               registerexternalwindow_redisp(hmi->registerexternalwindow);
+               return;
+       }
+       if (bchanlhmi_isexternalbbswindowWID(hmi, wev->s.wid) == True) {
+               evt->type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW;
        }
-       bchanlhmi_setswitchbutdnflag(hmi);
 }
 
 LOCAL VOID bchanlhmi_receivemessage(bchanlhmi_t *hmi, bchanlhmievent_t *evt)
@@ -864,7 +1977,7 @@ LOCAL VOID bchanlhmi_receivemessage(bchanlhmi_t *hmi, bchanlhmievent_t *evt)
        MESSAGE msg;
        W err;
 
-    err = rcv_msg(MM_ALL, &msg, sizeof(MESSAGE), WAIT|NOCLR);
+       err = rcv_msg(MM_ALL, &msg, sizeof(MESSAGE), WAIT|NOCLR);
        if (err >= 0) {
                if (msg.msg_type == MS_TMOUT) { /* should be use other type? */
                        evt->type = BCHANLHMIEVENT_TYPE_COMMON_TIMEOUT;
@@ -874,17 +1987,146 @@ LOCAL VOID bchanlhmi_receivemessage(bchanlhmi_t *hmi, bchanlhmievent_t *evt)
        clr_msg(MM_ALL, MM_ALL);
 }
 
+LOCAL Bool bchanlhmi_checkflag(bchanlhmi_t *hmi, bchanlhmievent_t **evt)
+{
+       W err, dh, dv;
+
+       if (subjectwindow_issetflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING) == True) {
+               err = hmi_windowscroll_weventrbar(&hmi->subjectwindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING);
+               } else {
+                       subjectwindow_setflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_RSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL;
+               hmi->evt.data.subjectwindow_scroll.dh = dh;
+               hmi->evt.data.subjectwindow_scroll.dv = dv;
+               return True;
+       }
+       if (subjectwindow_issetflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING) == True) {
+               err = hmi_windowscroll_weventbbar(&hmi->subjectwindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING);
+               } else {
+                       subjectwindow_setflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_BSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL;
+               hmi->evt.data.subjectwindow_scroll.dh = dh;
+               hmi->evt.data.subjectwindow_scroll.dv = dv;
+               return True;
+       }
+       if (bbsmenuwindow_issetflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING) == True) {
+               err = hmi_windowscroll_weventrbar(&hmi->bbsmenuwindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING);
+               } else {
+                       bbsmenuwindow_setflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_RSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL;
+               hmi->evt.data.bbsmenuwindow_scroll.dh = dh;
+               hmi->evt.data.bbsmenuwindow_scroll.dv = dv;
+               return True;
+       }
+       if (bbsmenuwindow_issetflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING) == True) {
+               err = hmi_windowscroll_weventbbar(&hmi->bbsmenuwindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING);
+               } else {
+                       bbsmenuwindow_setflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_BSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL;
+               hmi->evt.data.bbsmenuwindow_scroll.dh = dh;
+               hmi->evt.data.bbsmenuwindow_scroll.dv = dv;
+               return True;
+       }
+       if (externalbbswindow_issetflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING) == True) {
+               err = hmi_windowscroll_weventrbar(&hmi->externalbbswindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING);
+               } else {
+                       externalbbswindow_setflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_RSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL;
+               hmi->evt.data.externalbbswindow_scroll.dh = dh;
+               hmi->evt.data.externalbbswindow_scroll.dv = dv;
+               return True;
+       }
+       if (externalbbswindow_issetflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING) == True) {
+               err = hmi_windowscroll_weventbbar(&hmi->externalbbswindow->wscr, &hmi->wev, &dh, &dv);
+               if (err < 0) {
+                       externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING);
+                       return False;
+               }
+               if (err == 0) {
+                       externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING);
+               } else {
+                       externalbbswindow_setflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_BSCROLLING);
+               }
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL;
+               hmi->evt.data.externalbbswindow_scroll.dh = dh;
+               hmi->evt.data.externalbbswindow_scroll.dv = dv;
+               return True;
+       }
+       if (subjectoptionwindow_issetflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_PARTS_OTHEREVENT) == True) {
+               subjectoptionwindow_clearflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_PARTS_OTHEREVENT);
+               subjectoptionwindow_setflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_PARTS_NEXTACTION);
+               return False;
+       } else if (subjectoptionwindow_issetflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_PARTS_NEXTACTION) == True) {
+               subjectoptionwindow_clearflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_PARTS_NEXTACTION);
+               if (hmi->subjectoptionwindow->filter.nextaction == True) {
+                       hmi->wev.s.type = EV_NULL;
+                       subjectoptionwindow_actionfilter(hmi->subjectoptionwindow, &hmi->wev, &hmi->evt);
+                       return True;
+               }
+       }
+       if (registerexternalwindow_issetflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_PARTS_OTHEREVENT) == True) {
+               registerexternalwindow_clearflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_PARTS_OTHEREVENT);
+               registerexternalwindow_setflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION);
+               return False;
+       } else if (registerexternalwindow_issetflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION) == True) {
+               registerexternalwindow_clearflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_PARTS_NEXTACTION);
+               if (hmi->registerexternalwindow->boradname.nextaction == True) {
+                       hmi->wev.s.type = EV_NULL;
+                       registerexternalwindow_actionboradname(hmi->registerexternalwindow, &hmi->wev, &hmi->evt);
+                       return True;
+               }
+               if (hmi->registerexternalwindow->url.nextaction == True) {
+                       hmi->wev.s.type = EV_NULL;
+                       registerexternalwindow_actionurl(hmi->registerexternalwindow, &hmi->wev, &hmi->evt);
+                       return True;
+               }
+       }
+
+       return False;
+}
+
 EXPORT W bchanlhmi_getevent(bchanlhmi_t *hmi, bchanlhmievent_t **evt)
 {
        WEVENT  *wev0;
-       WID subject_wid, bbsmenu_wid, subjectoption_wid;
        Bool ok;
 
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       bbsmenu_wid = bchanlhmi_getbbsmenuWID(hmi);
-       subjectoption_wid = bchanlhmi_getsubjectoptionWID(hmi);
-
        hmi->evt.type = BCHANLHMIEVENT_TYPE_NONE;
+       *evt = &hmi->evt;
        wev0 = &hmi->wev;
 
        ok = bchanlhmi_issetswitchbutdnflag(hmi);
@@ -894,35 +2136,41 @@ EXPORT W bchanlhmi_getevent(bchanlhmi_t *hmi, bchanlhmievent_t **evt)
                return 0;
        }
 
+       if (subjectwindow_issetflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_DRAWREQUEST) == True) {
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW;
+               subjectwindow_clearflag(hmi->subjectwindow, SUBJECTWINDOW_FLAG_DRAWREQUEST);
+               return 0;
+       }
+       if (bbsmenuwindow_issetflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_DRAWREQUEST) == True) {
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW;
+               bbsmenuwindow_clearflag(hmi->bbsmenuwindow, BBSMENUWINDOW_FLAG_DRAWREQUEST);
+               return 0;
+       }
+       if (subjectoptionwindow_issetflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_DRAWREQUEST) == True) {
+               subjectoptionwindow_redisp(hmi->subjectoptionwindow);
+               subjectoptionwindow_clearflag(hmi->subjectoptionwindow, SUBJECTOPTIONWINDOW_FLAG_DRAWREQUEST);
+               return 0;
+       }
+       if (registerexternalwindow_issetflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_DRAWREQUEST) == True) {
+               registerexternalwindow_redisp(hmi->registerexternalwindow);
+               registerexternalwindow_clearflag(hmi->registerexternalwindow, REGISTEREXTERNALWINDOW_FLAG_DRAWREQUEST);
+               return 0;
+       }
+       if (externalbbswindow_issetflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_DRAWREQUEST) == True) {
+               hmi->evt.type = BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW;
+               externalbbswindow_clearflag(hmi->externalbbswindow, EXTERNALBBSWINDOW_FLAG_DRAWREQUEST);
+               return 0;
+       }
+
+       ok = bchanlhmi_checkflag(hmi, evt);
+       if (ok == True) {
+               return 0;
+       }
+
        wget_evt(wev0, WAIT);
        switch (wev0->s.type) {
        case    EV_NULL:
-               cidl_par(wev0->s.wid, &wev0->s.pos);
-               if ((wev0->s.wid != subject_wid)&&(wev0->s.wid != bbsmenu_wid)) {
-                       hmi->evt.type = BCHANLHMIEVENT_TYPE_COMMON_MOUSEMOVE;
-                       hmi->evt.data.common_mousemove.pos = wev0->s.pos;
-                       break;          /*¥¦¥£¥ó¥É¥¦³°*/
-               }
-               if (wev0->s.cmd != W_WORK)
-                       break;          /*ºî¶ÈÎΰ賰*/
-               if (wev0->s.stat & ES_CMD)
-                       break;  /*Ì¿Îᥭ¡¼¤¬²¡¤µ¤ì¤Æ¤¤¤ë*/
-               if (wev0->s.wid == subject_wid) {
-                       hmi->evt.type = BCHANLHMIEVENT_TYPE_SUBJECT_MOUSEMOVE;
-                       hmi->evt.data.subject_mousemove.pos = wev0->s.pos;
-                       hmi->evt.data.subject_mousemove.stat = wev0->s.stat;
-                       break;
-               }
-               if (wev0->s.wid == bbsmenu_wid) {
-                       hmi->evt.type = BCHANLHMIEVENT_TYPE_BBSMENU_MOUSEMOVE;
-                       hmi->evt.data.bbsmenu_mousemove.pos = wev0->s.pos;
-                       hmi->evt.data.bbsmenu_mousemove.stat = wev0->s.stat;
-                       break;
-               }
-               if (wev0->s.wid == subjectoption_wid) {
-                       cidl_par(wev0->s.wid, &wev0->s.pos);
-                       break;
-               }
+               bchanlhmi_weventnull(hmi, wev0, &hmi->evt);
                break;
        case    EV_REQUEST:
                bchanlhmi_weventrequest(hmi, wev0, &hmi->evt);
@@ -958,158 +2206,218 @@ EXPORT W bchanlhmi_getevent(bchanlhmi_t *hmi, bchanlhmievent_t **evt)
                break;
        }
 
-       *evt = &hmi->evt;
-
        return 0;
 }
 
-LOCAL VOID subjectwindow_scroll(VP arg, W dh, W dv)
+EXPORT subjectwindow_t* subjectwindow_new(RECT *r, WID parent, TC *title, PAT *bgpat)
 {
-       subjectwindow_t *window = (subjectwindow_t*)arg;
-       (*window->scroll_callback)(window->arg, dh, dv);
-}
-
-LOCAL subjectwindow_t* subjectwindow_new(RECT *r, TC *title, PAT *bgpat, subjectwindow_scrollcalback scrollcallback, VP arg)
-{
-       subjectwindow_t* window;
+       subjectwindow_t *window;
        W err;
 
-       window = malloc(sizeof(subjectwindow_t));
+       window = (subjectwindow_t*)malloc(sizeof(subjectwindow_t));
        if (window == NULL) {
                return NULL;
        }
-
-       window->wid = wopn_wnd(WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, 0, r, NULL, 1, title, bgpat, NULL);
-       if (window->wid < 0) {
+       window->flag = 0;
+       window->wid = -1;
+       window->gid = -1;
+       window->parent = parent;
+       window->r = *r;
+       if (bgpat != NULL) {
+               window->bgpat = *bgpat;
+       } else {
+               window->bgpat = (PAT){{0, 16, 16, 0x10ffffff, 0, FILL100}};
+       }
+       err = hmi_windowscroll_initialize(&window->wscr, window->wid);
+       if (err < 0) {
                free(window);
                return NULL;
        }
-       err = windowscroll_initialize(&window->wscr, window->wid, subjectwindow_scroll, (VP)window);
+
+       err = subjectwindow_open(window, title);
        if (err < 0) {
-               wcls_wnd(window->wid, CLR);
+               hmi_windowscroll_finalize(&window->wscr);
                free(window);
                return NULL;
        }
-       window->gid = wget_gid(window->wid);
-       window->scroll_callback = scrollcallback;
-       window->arg = arg;
 
        return window;
 }
 
 LOCAL VOID subjectwindow_delete(subjectwindow_t *window)
 {
-       wcls_wnd(window->wid, CLR);
-       windowscroll_finalize(&window->wscr);
+       if (window->wid > 0) {
+               wcls_wnd(window->wid, CLR);
+       }
+       hmi_windowscroll_finalize(&window->wscr);
        free(window);
 }
 
-EXPORT subjectwindow_t* bchanlhmi_newsubjectwindow(bchanlhmi_t *hmi, RECT *r, TC *title, PAT *bgpat, subjectwindow_scrollcalback scrollcallback, VP arg)
-{
-       hmi->subjectwindow = subjectwindow_new(r, title, bgpat, scrollcallback, arg);
-       return hmi->subjectwindow;
-}
-
-EXPORT VOID bchanlhmi_deletesubjectwindow(bchanlhmi_t *hmi, subjectwindow_t *window)
-{
-       subjectwindow_delete(window);
-       hmi->subjectwindow = NULL;
-}
-
-LOCAL VOID bbsmenuwindow_scroll(VP arg, W dh, W dv)
-{
-       bbsmenuwindow_t *window = (bbsmenuwindow_t*)arg;
-       (*window->scroll_callback)(window->arg, dh, dv);
-}
-
-LOCAL bbsmenuwindow_t* bbsmenuwindow_new(RECT *r, TC *title, PAT *bgpat, bbsmenuwindow_scrollcalback scrollcallback, VP arg)
+EXPORT bbsmenuwindow_t* bbsmenuwindow_new(RECT *r, WID parent, TC *title, PAT *bgpat)
 {
-       bbsmenuwindow_twindow;
+       bbsmenuwindow_t *window;
        W err;
 
-       window = malloc(sizeof(bbsmenuwindow_t));
+       window = (bbsmenuwindow_t*)malloc(sizeof(bbsmenuwindow_t));
        if (window == NULL) {
                return NULL;
        }
-
-       window->wid = wopn_wnd(WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, 0, r, NULL, 1, title, bgpat, NULL);
-       if (window->wid < 0) {
+       window->flag = 0;
+       window->wid = -1;
+       window->gid = -1;
+       window->parent = parent;
+       window->r = *r;
+       if (bgpat != NULL) {
+               window->bgpat = *bgpat;
+       } else {
+               window->bgpat = (PAT){{0, 16, 16, 0x10ffffff, 0, FILL100}};
+       }
+       err = hmi_windowscroll_initialize(&window->wscr, window->wid);
+       if (err < 0) {
                free(window);
                return NULL;
        }
-       err = windowscroll_initialize(&window->wscr, window->wid, bbsmenuwindow_scroll, (VP)window);
+
+       err = bbsmenuwindow_open(window, title);
        if (err < 0) {
-               wcls_wnd(window->wid, CLR);
+               hmi_windowscroll_finalize(&window->wscr);
                free(window);
                return NULL;
        }
-       window->gid = wget_gid(window->wid);
-       window->scroll_callback = scrollcallback;
-       window->arg = arg;
 
        return window;
 }
 
 LOCAL VOID bbsmenuwindow_delete(bbsmenuwindow_t *window)
 {
-       wcls_wnd(window->wid, CLR);
-       windowscroll_finalize(&window->wscr);
+       if (window->wid > 0) {
+               wcls_wnd(window->wid, CLR);
+       }
+       hmi_windowscroll_finalize(&window->wscr);
        free(window);
 }
 
-EXPORT bbsmenuwindow_t* bchanlhmi_newbbsmenuwindow(bchanlhmi_t *hmi, RECT *r, TC *title, PAT *bgpat, bbsmenuwindow_scrollcalback scrollcallback, VP arg)
+EXPORT subjectoptionwindow_t* subjectoptionwindow_new(PNT *p, subjectwindow_t *parent, TC *title, PAT *bgpat, W dnum_filter, W dnum_order, W dnum_orderby)
 {
-       hmi->bbsmenuwindow = bbsmenuwindow_new(r, title, bgpat, scrollcallback, arg);
-       return hmi->bbsmenuwindow;
+       subjectoptionwindow_t *window;
+
+       window = (subjectoptionwindow_t*)malloc(sizeof(subjectoptionwindow_t));
+       if (window == NULL) {
+               return NULL;
+       }
+       window->wid = -1;
+       window->gid = -1;
+       window->parent = parent;
+       window->r.c.left = p->x;
+       window->r.c.top = p->y;
+       window->r.c.right = p->x + 384;
+       window->r.c.bottom = p->y + 160;
+       if (bgpat != NULL) {
+               window->bgpat = *bgpat;
+       } else {
+               window->bgpat = (PAT){{0, 16, 16, 0x10ffffff, 0, FILL100}};
+       }
+       tc_strset(window->title, TNULL, 256+1);
+       if (title != 0) {
+               tc_strncpy(window->title, title, 256);
+       } else {
+               window->title[0] = 0x2539;
+               window->title[1] = 0x256c;
+               window->title[2] = 0x306c;
+               window->title[3] = 0x4d77;
+               window->title[4] = 0x405f;
+               window->title[5] = 0x446a;
+       }
+       window->filter.id = -1;
+       window->filter.dnum = dnum_filter;
+       memset(window->filter.buf, 0, sizeof(TC)*1000);
+       window->filter.buf[0] = MC_ATTR;
+       *(COLOR*)(window->filter.buf + 1) = -1;
+       window->filter.buf[3] = -1;
+       window->filter.buf[4] = 0;
+       window->filter.buf[5] = 16;
+       window->filter.buf[6] = 16;
+       window->filter.buf[7] = TNULL;
+       window->filter.nextaction = False;
+       window->order.id = -1;
+       window->order.dnum = dnum_order;
+       window->order.value = 0;
+       window->orderby.id = -1;
+       window->orderby.dnum = dnum_orderby;
+       window->orderby.value = 0;
+
+
+       return window;
 }
 
-EXPORT VOID bchanlhmi_deletebbsmenuwindow(bchanlhmi_t *hmi, bbsmenuwindow_t *window)
+LOCAL VOID subjectoptionwindow_delete(subjectoptionwindow_t *window)
 {
-       bbsmenuwindow_delete(window);
-       hmi->bbsmenuwindow = NULL;
+       if (window->wid > 0) {
+               cdel_pwd(window->wid, NOCLR);
+               wcls_wnd(window->wid, CLR);
+       }
+       free(window);
 }
 
-LOCAL subjectoptionwindow_t* subjectoptionwindow_new(PNT *p, WID parent, W dnum_filter, W dnum_order, W dnum_orderby)
+EXPORT registerexternalwindow_t* registerexternalwindow_new(PNT *p, WID parent, TC *title, PAT *bgpat)
 {
-       subjectoptionwindow_t *window;
-       W err;
+       registerexternalwindow_t *window;
 
-       window = (subjectoptionwindow_t*)malloc(sizeof(subjectoptionwindow_t));
+       window = (registerexternalwindow_t*)malloc(sizeof(registerexternalwindow_t));
        if (window == NULL) {
-               DP_ER("malloc error:", 0);
                return NULL;
        }
        window->wid = -1;
        window->gid = -1;
        window->parent = parent;
-       window->r.p.lefttop = *p;
-       window->r.p.rightbot.x = p->x + 8+360+8+80+8 + 7;
-       window->r.p.rightbot.y = p->y + 8+24+16+70+8 + 7;
-       err = wget_inf(WI_PANELBACK, &window->bgpat, sizeof(PAT));
-       if (err != sizeof(PAT)) {
-               DP_ER("wget_inf error:", err);
-               window->bgpat.spat.kind = 0;
-               window->bgpat.spat.hsize = 16;
-               window->bgpat.spat.vsize = 16;
-               window->bgpat.spat.fgcol = 0x10ffffff;
-               window->bgpat.spat.bgcol = 0;
-               window->bgpat.spat.mask = FILL100;
-       }
-       window->dnum_filter = dnum_filter;
-       window->dnum_order = dnum_order;
-       window->dnum_orderby = dnum_orderby;
-       window->tb_filter_id = -1;
-       window->ws_order_id = -1;
-       window->ws_orderby_id = -1;
-       window->order = SUBJECTOPTIONWINDOW_ORDER_ASCENDING;
-       window->orderby = SUBJECTOPTIONWINDOW_ORDERBY_NUMBER;
-       memset(window->strbuf, 0, sizeof(TC)*SUBJECTOPTIONWINDOW_STRBUF_LEN);
-       window->strbuf_written = 0;
+       window->r.c.left = p->x;
+       window->r.c.top = p->y;
+       window->r.c.right = p->x + 384;
+       window->r.c.bottom = p->y + 138;
+       if (bgpat != NULL) {
+               window->bgpat = *bgpat;
+       } else {
+               window->bgpat = (PAT){{0, 16, 16, 0x10ffffff, 0, FILL100}};
+       }
+       tc_strset(window->title, TNULL, 256+1);
+       if (title != 0) {
+               tc_strncpy(window->title, title, 256);
+       } else {
+               window->title[0] = 0x3330;
+               window->title[1] = 0x4974;
+               window->title[2] = 0x4844;
+               window->title[3] = 0x244e;
+               window->title[4] = 0x4449;
+               window->title[5] = 0x3243;
+       }
+       window->boradname.id = -1;
+       memset(window->boradname.buf, 0, sizeof(TC)*1000);
+       window->boradname.buf[0] = MC_ATTR;
+       *(COLOR*)(window->boradname.buf + 1) = -1;
+       window->boradname.buf[3] = -1;
+       window->boradname.buf[4] = 0;
+       window->boradname.buf[5] = 16;
+       window->boradname.buf[6] = 16;
+       window->boradname.buf[7] = TNULL;
+       window->boradname.nextaction = False;
+       window->url.id = -1;
+       memset(window->url.buf, 0, sizeof(TC)*1000);
+       window->url.buf[0] = MC_ATTR;
+       *(COLOR*)(window->url.buf + 1) = -1;
+       window->url.buf[3] = -1;
+       window->url.buf[4] = 0;
+       window->url.buf[5] = 8;
+       window->url.buf[6] = 16;
+       window->url.buf[7] = TNULL;
+       window->url.nextaction = False;
+       window->determine.id = -1;
+       window->cancel.id = -1;
+
 
        return window;
 }
 
-LOCAL VOID subjectoptionwindow_delete(subjectoptionwindow_t *window)
+LOCAL VOID registerexternalwindow_delete(registerexternalwindow_t *window)
 {
        if (window->wid > 0) {
                cdel_pwd(window->wid, NOCLR);
@@ -1118,24 +2426,131 @@ LOCAL VOID subjectoptionwindow_delete(subjectoptionwindow_t *window)
        free(window);
 }
 
-EXPORT subjectoptionwindow_t *bchanlhmi_newsubjectoptionwindow(bchanlhmi_t *hmi, PNT *p, W dnum_filter, W dnum_order, W dnum_orderby)
+EXPORT externalbbswindow_t* externalbbswindow_new(RECT *r, WID parent, TC *title, PAT *bgpat)
+{
+       externalbbswindow_t *window;
+       W err;
+
+       window = (externalbbswindow_t*)malloc(sizeof(externalbbswindow_t));
+       if (window == NULL) {
+               return NULL;
+       }
+       window->flag = 0;
+       window->wid = -1;
+       window->gid = -1;
+       window->parent = parent;
+       window->r = *r;
+       if (bgpat != NULL) {
+               window->bgpat = *bgpat;
+       } else {
+               window->bgpat = (PAT){{0, 16, 16, 0x10ffffff, 0, FILL100}};
+       }
+       err = hmi_windowscroll_initialize(&window->wscr, window->wid);
+       if (err < 0) {
+               free(window);
+               return NULL;
+       }
+       tc_strset(window->title, TNULL, 256+1);
+       if (title != 0) {
+               tc_strncpy(window->title, title, 256);
+       } else {
+               window->title[0] = 0x3330;
+               window->title[1] = 0x4974;
+               window->title[2] = 0x4844;
+       }
+
+
+       return window;
+}
+
+LOCAL VOID externalbbswindow_delete(externalbbswindow_t *window)
+{
+       if (window->wid > 0) {
+               wcls_wnd(window->wid, CLR);
+       }
+       hmi_windowscroll_finalize(&window->wscr);
+       free(window);
+}
+
+EXPORT subjectwindow_t* bchanlhmi_newsubjectwindow(bchanlhmi_t *hmi, RECT *r, WID parent, TC *title, PAT *bgpat)
+{
+       if (hmi->subjectwindow != NULL) {
+               return NULL;
+       }
+       hmi->subjectwindow = subjectwindow_new(r, parent, title, bgpat);
+       return hmi->subjectwindow;
+}
+
+EXPORT VOID bchanlhmi_deletesubjectwindow(bchanlhmi_t *hmi, subjectwindow_t *window)
+{
+       subjectwindow_delete(hmi->subjectwindow);
+       hmi->subjectwindow = NULL;
+}
+
+EXPORT bbsmenuwindow_t* bchanlhmi_newbbsmenuwindow(bchanlhmi_t *hmi, RECT *r, WID parent, TC *title, PAT *bgpat)
+{
+       if (hmi->bbsmenuwindow != NULL) {
+               return NULL;
+       }
+       hmi->bbsmenuwindow = bbsmenuwindow_new(r, parent, title, bgpat);
+       return hmi->bbsmenuwindow;
+}
+
+EXPORT VOID bchanlhmi_deletebbsmenuwindow(bchanlhmi_t *hmi, bbsmenuwindow_t *window)
+{
+       bbsmenuwindow_delete(hmi->bbsmenuwindow);
+       hmi->bbsmenuwindow = NULL;
+}
+
+EXPORT subjectoptionwindow_t* bchanlhmi_newsubjectoptionwindow(bchanlhmi_t *hmi, PNT *p, subjectwindow_t *parent, TC *title, PAT *bgpat, W dnum_filter, W dnum_order, W dnum_orderby)
 {
-       W subject_wid;
-       subject_wid = bchanlhmi_getsubjectWID(hmi);
-       if (subject_wid < 0) {
-               DP_ER("subject window not exist", 0);
+       if (parent == NULL) {
+               return NULL;
+       }
+       if (hmi->subjectoptionwindow != NULL) {
                return NULL;
        }
-       hmi->subjectoptionwindow = subjectoptionwindow_new(p, subject_wid, dnum_filter, dnum_order, dnum_orderby);
+       hmi->subjectoptionwindow = subjectoptionwindow_new(p, parent, title, bgpat, dnum_filter, dnum_order, dnum_orderby);
        return hmi->subjectoptionwindow;
 }
 
 EXPORT VOID bchanlhmi_deletesubjectoptionwindow(bchanlhmi_t *hmi, subjectoptionwindow_t *window)
 {
-       subjectoptionwindow_delete(window);
+       subjectoptionwindow_delete(hmi->subjectoptionwindow);
        hmi->subjectoptionwindow = NULL;
 }
 
+EXPORT registerexternalwindow_t* bchanlhmi_newregisterexternalwindow(bchanlhmi_t *hmi, PNT *p, WID parent, TC *title, PAT *bgpat)
+{
+       if (hmi->registerexternalwindow != NULL) {
+               return NULL;
+       }
+       hmi->registerexternalwindow = registerexternalwindow_new(p, parent, title, bgpat);
+       return hmi->registerexternalwindow;
+}
+
+EXPORT VOID bchanlhmi_deleteregisterexternalwindow(bchanlhmi_t *hmi, registerexternalwindow_t *window)
+{
+       registerexternalwindow_delete(hmi->registerexternalwindow);
+       hmi->registerexternalwindow = NULL;
+}
+
+EXPORT externalbbswindow_t* bchanlhmi_newexternalbbswindow(bchanlhmi_t *hmi, RECT *r, WID parent, TC *title, PAT *bgpat)
+{
+       if (hmi->externalbbswindow != NULL) {
+               return NULL;
+       }
+       hmi->externalbbswindow = externalbbswindow_new(r, parent, title, bgpat);
+       return hmi->externalbbswindow;
+}
+
+EXPORT VOID bchanlhmi_deleteexternalbbswindow(bchanlhmi_t *hmi, externalbbswindow_t *window)
+{
+       externalbbswindow_delete(hmi->externalbbswindow);
+       hmi->externalbbswindow = NULL;
+}
+
+
 EXPORT bchanlhmi_t* bchanlhmi_new()
 {
        bchanlhmi_t *hmi;
@@ -1144,23 +2559,32 @@ EXPORT bchanlhmi_t* bchanlhmi_new()
        if (hmi == NULL) {
                return NULL;
        }
+       hmi->flag = 0;
        hmi->subjectwindow = NULL;
        hmi->bbsmenuwindow = NULL;
        hmi->subjectoptionwindow = NULL;
+       hmi->registerexternalwindow = NULL;
+       hmi->externalbbswindow = NULL;
 
        return hmi;
 }
 
 EXPORT VOID bchanlhmi_delete(bchanlhmi_t *hmi)
 {
-       if (hmi->subjectoptionwindow != NULL) {
-               subjectoptionwindow_delete(hmi->subjectoptionwindow);
+       if (hmi->subjectwindow != NULL) {
+               subjectwindow_delete(hmi->subjectwindow);
        }
        if (hmi->bbsmenuwindow != NULL) {
                bbsmenuwindow_delete(hmi->bbsmenuwindow);
        }
-       if (hmi->subjectwindow != NULL) {
-               subjectwindow_delete(hmi->subjectwindow);
+       if (hmi->subjectoptionwindow != NULL) {
+               subjectoptionwindow_delete(hmi->subjectoptionwindow);
+       }
+       if (hmi->registerexternalwindow != NULL) {
+               registerexternalwindow_delete(hmi->registerexternalwindow);
+       }
+       if (hmi->externalbbswindow != NULL) {
+               externalbbswindow_delete(hmi->externalbbswindow);
        }
        free(hmi);
 }