OSDN Git Service

change version number
[bbk/bchanl.git] / src / main.c
1 /*
2  * main.c
3  *
4  * Copyright (c) 2009-2015 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include        <basic.h>
28 #include        <bstdlib.h>
29 #include        <bstdio.h>
30 #include        <bstring.h>
31 #include        <errcode.h>
32 #include        <tstring.h>
33 #include        <keycode.h>
34 #include        <tcode.h>
35 #include        <btron/btron.h>
36 #include        <btron/dp.h>
37 #include        <btron/hmi.h>
38 #include        <btron/vobj.h>
39 #include        <btron/libapp.h>
40 #include        <btron/bsocket.h>
41
42 #include        "window.h"
43 #include        "subjectretriever.h"
44 #include        "subjectcache.h"
45 #include        "subjectparser.h"
46 #include        "subjectlist.h"
47 #include        "subjectlayout.h"
48 #include    "bbsmenuretriever.h"
49 #include    "bbsmenucache.h"
50 #include    "bbsmenuparser.h"
51 #include        "bbsmenufilter.h"
52 #include    "bbsmenulayout.h"
53 #include    "extbbslist.h"
54 #include    "util.h"
55
56 #include    "bchanl_subject.h"
57 #include    "bchanl_hmi.h"
58 #include    "bchanl_menus.h"
59 #include    "bchanl_panels.h"
60
61 #include        <http/http_connector.h>
62
63 #ifdef BCHANL_CONFIG_DEBUG
64 # define DP(arg) printf arg
65 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
66 #else
67 # define DP(arg) /**/
68 # define DP_ER(msg, err) /**/
69 #endif
70
71 #define BCHANL_DBX_MENU_TEST 20
72 #define BCHANL_DBX_TEXT_MLIST0  21
73 #define BCHANL_DBX_TEXT_MLIST1  22
74 #define BCHANL_DBX_TEXT_MLIST2  23
75 #define BCHANL_DBX_VIEWER_FUSEN 24
76 #define BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU 25
77 #define BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT 26
78 #define BCHANL_DBX_TEXT_MSG_RETRBBSMENU 27
79 #define BCHANL_DBX_TEXT_MSG_RETRSUBJECT 28
80 #define BCHANL_DBX_TEXT_MSG_ERRRETR 29
81 #define BCHANL_DBX_TB_SBJTOPT_FLT 30
82 #define BCHANL_DBX_WS_SBJTOPT_ODR 31
83 #define BCHANL_DBX_WS_SBJTOPT_ODRBY     32
84 #define BCHANL_DBX_TEXT_CATE_EXTBBS 33
85
86 #define BCHANL_MENU_WINDOW 3
87
88 #define BCHANL_COMMONSTORAGE_EXTBBSLIST_RECTYPE 30
89 #define BCHANL_COMMONSTORAGE_EXTBBSLIST_SUBTYPE 1
90
91 LOCAL UB bchanl_httpheader_useragent[] = "Monazilla/1.00 (bchanl/0.300)";
92 LOCAL W bchanl_httpheader_useragent_len = sizeof(bchanl_httpheader_useragent) - 1;
93
94 typedef struct bchanl_hmistate_t_ bchanl_hmistate_t;
95 struct bchanl_hmistate_t_ {
96         PTRSTL ptr;
97
98         TC *msg_retr_bbsmenu;
99         TC *msg_retr_subject;
100         TC *msg_error_retr;
101 };
102
103 LOCAL VOID bchanl_hmistate_updateptrstyle(bchanl_hmistate_t *hmistate, PTRSTL ptr)
104 {
105         if (hmistate->ptr == ptr) {
106                 return;
107         }
108         hmistate->ptr = ptr;
109         gset_ptr(hmistate->ptr, NULL, -1, -1);
110 }
111
112 LOCAL VOID bchanl_hmistate_initialize(bchanl_hmistate_t *hmistate)
113 {
114         W err;
115
116         hmistate->ptr = PS_SELECT;
117
118         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRBBSMENU, (void**)&hmistate->msg_retr_bbsmenu);
119         if (err < 0) {
120                 DP_ER("dget_dtp: message retrieving error", err);
121                 hmistate->msg_retr_bbsmenu = NULL;
122         }
123         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRSUBJECT, (void**)&hmistate->msg_retr_subject);
124         if (err < 0) {
125                 DP_ER("dget_dtp: message not modified error", err);
126                 hmistate->msg_retr_subject = NULL;
127         }
128         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_ERRRETR, (void**)&hmistate->msg_error_retr);
129         if (err < 0) {
130                 DP_ER("dget_dtp: message retrieve error error", err);
131                 hmistate->msg_error_retr = NULL;
132         }
133 }
134
135 typedef struct bchanl_bbsmenu_t_ bchanl_bbsmenu_t;
136 struct bchanl_bbsmenu_t_ {
137         W gid;
138
139         bbsmnretriever_t *retriever;
140         bbsmncache_t *cache;
141         bbsmnparser_t *parser;
142         bbsmnfilter_t *filter;
143         bbsmnlayout_t *layout;
144         bbsmndraw_t *draw;
145
146         bchanl_subjecthash_t *subjecthash;
147         extbbslist_t *extbbslist;
148         extbbslist_editcontext_t *editctx;
149         TC *category_extbbs;
150 };
151
152 #define BCHANL_NETWORK_FLAG_WAITHTTPEVENT 0x00000001
153
154 struct bchanl_t_ {
155         W taskid;
156         W flgid; /* for reduce TMOUT message sending. */
157
158         bchanl_mainmenu_t mainmenu;
159         VID vid;
160         W exectype;
161
162         bchanl_hmistate_t hmistate;
163
164         http_connector_t *connector;
165
166         sbjtretriever_t *retriever;
167
168         bchanl_subjecthash_t *subjecthash;
169         bchanl_bbsmenu_t bbsmenu;
170         bchanl_subject_t *currentsubject;
171         bchanl_subject_t *nextsubject;
172         struct {
173                 Bool resnum;
174                 Bool since;
175                 Bool vigor;
176         } subjectdisplay;
177
178         bchanlhmi_t *hmi;
179         subjectwindow_t *subjectwindow;
180         bbsmenuwindow_t *bbsmenuwindow;
181         subjectoptionwindow_t *subjectoptionwindow;
182         registerexternalwindow_t *registerexternalwindow;
183         externalbbswindow_t *externalbbswindow;
184 };
185 typedef struct bchanl_t_ bchanl_t;
186
187 LOCAL VOID bchanl_swapresnumberdisplay(bchanl_t *bchanl)
188 {
189         if (bchanl->subjectdisplay.resnum != False) {
190                 bchanl->subjectdisplay.resnum = False;
191         } else {
192                 bchanl->subjectdisplay.resnum = True;
193         }
194 }
195
196 LOCAL VOID bchanl_swapsincedisplay(bchanl_t *bchanl)
197 {
198         if (bchanl->subjectdisplay.since != False) {
199                 bchanl->subjectdisplay.since = False;
200         } else {
201                 bchanl->subjectdisplay.since = True;
202         }
203 }
204
205 LOCAL VOID bchanl_swapvigordisplay(bchanl_t *bchanl)
206 {
207         if (bchanl->subjectdisplay.vigor != False) {
208                 bchanl->subjectdisplay.vigor = False;
209         } else {
210                 bchanl->subjectdisplay.vigor = True;
211         }
212 }
213
214 LOCAL VOID bchanl_killme(bchanl_t *bchanl);
215
216 LOCAL VOID bchanl_subjectwindow_draw(bchanl_t *bchanl)
217 {
218         sbjtdraw_t *draw;
219         RECT r;
220         if (bchanl->currentsubject == NULL) {
221                 do {
222                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
223                                 break;
224                         }
225                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
226                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
227         } else {
228                 draw = bchanl_subject_getdraw(bchanl->currentsubject);
229                 do {
230                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
231                                 break;
232                         }
233                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
234                         sbjtdraw_draw(draw, &r);
235                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
236         }
237 }
238
239 LOCAL VOID bchanl_subjectwindow_scroll(bchanl_t *bchanl, W dh, W dv)
240 {
241         sbjtdraw_t *draw;
242         if (bchanl->currentsubject == NULL) {
243                 return;
244         }
245         draw = bchanl_subject_getdraw(bchanl->currentsubject);
246         sbjtdraw_scrollviewrect(draw, dh, dv);
247         subjectwindow_scrollworkarea(bchanl->subjectwindow, -dh, -dv);
248         bchanl_subjectwindow_draw(bchanl);
249 }
250
251 LOCAL VOID bchanl_subjectwindow_resize(bchanl_t *bchanl, SIZE newsize)
252 {
253         W l,t,r,b;
254         sbjtdraw_t *draw;
255
256         if (bchanl->currentsubject == NULL) {
257                 return;
258         }
259         draw = bchanl_subject_getdraw(bchanl->currentsubject);
260
261         sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
262
263         r = l + newsize.h;
264         b = t + newsize.v;
265
266         sbjtdraw_setviewrect(draw, l, t, r, b);
267         subjectwindow_setworkrect(bchanl->subjectwindow, l, t, r, b);
268
269         bchanl_subjectwindow_draw(bchanl);
270 }
271
272 LOCAL VOID bchanl_subjectwindow_close(bchanl_t *bchanl)
273 {
274         bchanl_killme(bchanl);
275 }
276
277 LOCAL VOID bchanl_subjectwindow_press(bchanl_t *bchanl, PNT evpos)
278 {
279         sbjtlist_tuple_t *tuple;
280         sbjtdraw_t *draw;
281         WID wid_butup;
282         W event_type, size, err, fsn_len, dx, dy;
283         void *fsn;
284         GID gid;
285         PNT pos, p1, pos_butup;
286         TR_VOBJREC vrec;
287         TRAYREC tr_rec;
288         WEVENT paste_ev;
289         SEL_RGN sel;
290         RECT r0, vframe;
291
292         if (bchanl->currentsubject == NULL) {
293                 return;
294         }
295         draw = bchanl_subject_getdraw(bchanl->currentsubject);
296
297         err = sbjtdraw_findthread(draw, evpos, &tuple, &vframe);
298         if (err == 0) {
299                 return;
300         }
301
302         gid = subjectwindow_startdrag(bchanl->subjectwindow);
303         if (gid < 0) {
304                 DP_ER("wsta_drg error:", gid);
305                 return;
306         }
307
308         gget_fra(gid, &r0);
309         gset_vis(gid, r0);
310
311         dx = vframe.c.left - evpos.x;
312         dy = vframe.c.top - evpos.y;
313
314         p1 = evpos;
315         sel.sts = 0;
316         sel.rgn.r.c.left = vframe.c.left;
317         sel.rgn.r.c.top = vframe.c.top;
318         sel.rgn.r.c.right = vframe.c.right;
319         sel.rgn.r.c.bottom = vframe.c.bottom;
320         adsp_sel(gid, &sel, 1);
321
322         gset_ptr(PS_GRIP, NULL, -1, -1);
323         for (;;) {
324                 event_type = subjectwindow_getdrag(bchanl->subjectwindow, &pos, &wid_butup, &pos_butup);
325                 if (event_type == EV_BUTUP) {
326                         break;
327                 }
328                 if (event_type != EV_NULL) {
329                         continue;
330                 }
331                 if ((pos.x == p1.x)&&(pos.y == p1.y)) {
332                         continue;
333                 }
334                 adsp_sel(gid, &sel, 0);
335                 sel.rgn.r.c.left += pos.x - p1.x;
336                 sel.rgn.r.c.top += pos.y - p1.y;
337                 sel.rgn.r.c.right += pos.x - p1.x;
338                 sel.rgn.r.c.bottom += pos.y - p1.y;
339                 adsp_sel(gid, &sel, 1);
340                 p1 = pos;
341         }
342         gset_ptr(PS_SELECT, NULL, -1, -1);
343         adsp_sel(gid, &sel, 0);
344         subjectwindow_enddrag(bchanl->subjectwindow);
345
346         /* BUTUP on self window or no window or system message panel */
347         if ((wid_butup == subjectwindow_getWID(bchanl->subjectwindow))||(wid_butup == 0)||(wid_butup == -1)) {
348                 return;
349         }
350
351         err = oget_vob(-wid_butup, &vrec.vlnk, NULL, 0, &size);
352         if (err < 0) {
353                 return;
354         }
355
356         err = dget_dtp(64, BCHANL_DBX_VIEWER_FUSEN, (void**)&fsn);
357         if (err < 0) {
358                 DP_ER("dget_dtp: ", err);
359                 return;
360         }
361         fsn_len = dget_siz((B*)fsn);
362         err = bchanl_subject_createviewervobj(bchanl->currentsubject, tuple, fsn, fsn_len, &vrec.vseg, (LINK*)&vrec.vlnk);
363         if (err < 0) {
364                 DP_ER("bchanl_subject_createviewervobj error", err);
365                 return;
366         }
367         if (err == BCHANL_SUBJECT_CREATEVIEWERVOBJ_CANCELED) {
368                 DP(("canceled\n"));
369                 return;
370         }
371
372         tr_rec.id = TR_VOBJ;
373         tr_rec.len = sizeof(TR_VOBJREC);
374         tr_rec.dt = (B*)&vrec;
375         err = tset_dat(&tr_rec, 1);
376         if (err < 0) {
377                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
378                 if (err < 0) {
379                         DP_ER("error del_fil:", err);
380                 }
381                 return;
382         }
383
384         paste_ev.r.type = EV_REQUEST;
385         paste_ev.r.r.p.rightbot.x = pos_butup.x + dx;
386         paste_ev.r.r.p.rightbot.y = pos_butup.y + dy;
387         paste_ev.r.cmd = W_PASTE;
388         paste_ev.r.wid = wid_butup;
389         err = wsnd_evt(&paste_ev);
390         if (err < 0) {
391                 tset_dat(NULL, 0);
392                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
393                 if (err < 0) {
394                         DP_ER("error del_fil:", err);
395                 }
396                 return;
397         }
398         err = wwai_rsp(NULL, W_PASTE, 60000);
399         if (err != W_ACK) {
400                 tset_dat(NULL, 0);
401                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
402                 if (err < 0) {
403                         DP_ER("error del_fil:", err);
404                 }
405         }
406
407         wswi_wnd(wid_butup, NULL);
408 }
409
410 LOCAL VOID bchanl_subjectwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
411 {
412         switch (dck) {
413         case    W_CLICK:
414         case    W_DCLICK:
415         case    W_QPRESS:
416         default:
417                 return;
418         case    W_PRESS:
419                 bchanl_subjectwindow_press(bchanl, evpos);
420         }
421 }
422
423 LOCAL VOID bchanl_setcurrentsubject(bchanl_t *bchanl, bchanl_subject_t *sbjt)
424 {
425         bchanl->currentsubject = sbjt;
426         bchanl_subject_setresnumberdisplay(sbjt, bchanl->subjectdisplay.resnum);
427         bchanl_subject_setsincedisplay(sbjt, bchanl->subjectdisplay.since);
428         bchanl_subject_setvigordisplay(sbjt, bchanl->subjectdisplay.vigor);
429         subjectwindow_requestredisp(bchanl->subjectwindow);
430 }
431
432 LOCAL VOID bchanl_setnextsubject(bchanl_t *bchanl, bchanl_subject_t *sbjt)
433 {
434         bchanl->nextsubject = sbjt;
435 }
436
437 LOCAL VOID bchanl_bbsmenuwindow_draw(bchanl_t *bchanl)
438 {
439         RECT r;
440         do {
441                 if (bbsmenuwindow_startredisp(bchanl->bbsmenuwindow, &r) == 0) {
442                         break;
443                 }
444                 bbsmenuwindow_eraseworkarea(bchanl->bbsmenuwindow, &r);
445                 bbsmndraw_draw(bchanl->bbsmenu.draw, &r);
446         } while (bbsmenuwindow_endredisp(bchanl->bbsmenuwindow) > 0);
447 }
448
449 LOCAL VOID bchanl_bbsmenuwindow_scroll(bchanl_t *bchanl, W dh, W dv)
450 {
451         bbsmndraw_scrollviewrect(bchanl->bbsmenu.draw, dh, dv);
452         bbsmenuwindow_scrollworkarea(bchanl->bbsmenuwindow, -dh, -dv);
453         bchanl_bbsmenuwindow_draw(bchanl);
454 }
455
456 LOCAL VOID bchanl_bbsmenuwindow_resize(bchanl_t *bchanl, SIZE newsize)
457 {
458         W l,t,r,b;
459
460         bbsmndraw_getviewrect(bchanl->bbsmenu.draw, &l, &t, &r, &b);
461
462         r = l + newsize.h;
463         b = t + newsize.v;
464
465         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, l, t, r, b);
466         bbsmenuwindow_setworkrect(bchanl->bbsmenuwindow, l, t, r, b);
467
468         bchanl_bbsmenuwindow_draw(bchanl);
469 }
470
471 LOCAL VOID bchanl_bbsmenuwindow_close(bchanl_t *bchanl)
472 {
473         bchanl_killme(bchanl);
474 }
475
476 LOCAL VOID bchanl_updatesubjectorder(bchanl_t *bchanl, SUBJECTOPTIONWINDOW_ORDERVALUE_T order, SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby, TC *filterword, W filterword_len)
477 {
478         Bool descending;
479         W sbjt_orderby;
480
481         if (order == SUBJECTOPTIONWINDOW_ORDERVALUE_DESCENDING) {
482                 descending = True;
483         } else {
484                 descending = False;
485         }
486         switch (orderby) {
487         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_NUMBER:
488         default:
489                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_NUMBER;
490                 break;
491         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_RES:
492                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_RES;
493                 break;
494         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_SINCE:
495                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_SINCE;
496                 break;
497         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_VIGOR:
498                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_VIGOR;
499                 break;
500         }
501
502         bchanl_subject_reorder(bchanl->currentsubject, filterword, filterword_len, sbjt_orderby, descending);
503
504         subjectwindow_requestredisp(bchanl->subjectwindow);
505 }
506
507 LOCAL VOID bchanl_changesubjectorder(bchanl_t *bchanl, W neworder)
508 {
509         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby;
510         W len;
511         TC buf[512];
512
513         if (bchanl->currentsubject == NULL) {
514                 return;
515         }
516
517         subjectoptionwindow_getorderbyvalue(bchanl->subjectoptionwindow, &orderby);
518         len = subjectoptionwindow_getfiltertext(bchanl->subjectoptionwindow, buf, 512);
519
520         bchanl_updatesubjectorder(bchanl, neworder, orderby, buf, len);
521 }
522
523 LOCAL VOID bchanl_changesubjectorderby(bchanl_t *bchanl, W neworderby)
524 {
525         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T order;
526         W len;
527         TC buf[512];
528
529         if (bchanl->currentsubject == NULL) {
530                 return;
531         }
532
533         subjectoptionwindow_getordervalue(bchanl->subjectoptionwindow, &order);
534         len = subjectoptionwindow_getfiltertext(bchanl->subjectoptionwindow, buf, 512);
535
536         bchanl_updatesubjectorder(bchanl, order, neworderby, buf, len);
537 }
538
539 LOCAL VOID bchanl_changesubjectfilterword(bchanl_t *bchanl, TC *newstr, W newstr_len)
540 {
541         sbjtlayout_t *layout;
542         sbjtdraw_t *draw;
543         SUBJECTOPTIONWINDOW_ORDERVALUE_T order;
544         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby;
545         RECT w_work;
546         W l, t, r, b;
547
548         if (bchanl->currentsubject == NULL) {
549                 return;
550         }
551
552         subjectoptionwindow_getordervalue(bchanl->subjectoptionwindow, &order);
553         subjectoptionwindow_getorderbyvalue(bchanl->subjectoptionwindow, &orderby);
554
555         bchanl_updatesubjectorder(bchanl, order, orderby, newstr, newstr_len);
556
557         subjectwindow_getworkrect(bchanl->subjectwindow, &w_work);
558         draw = bchanl_subject_getdraw(bchanl->currentsubject);
559         sbjtdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
560         subjectwindow_setworkrect(bchanl->subjectwindow, 0, 0, w_work.c.right, w_work.c.bottom);
561
562         layout = bchanl_subject_getlayout(bchanl->currentsubject);
563         sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
564         subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
565 }
566
567 LOCAL VOID bchanl_changedisplayattribute(bchanl_t *bchanl)
568 {
569         sbjtlayout_t *layout;
570         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T order;
571         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby;
572         W len;
573         TC buf[512];
574         W l, t, r, b;
575
576         if (bchanl->currentsubject == NULL) {
577                 return;
578         }
579
580         subjectoptionwindow_getordervalue(bchanl->subjectoptionwindow, &order);
581         subjectoptionwindow_getorderbyvalue(bchanl->subjectoptionwindow, &orderby);
582         len = subjectoptionwindow_getfiltertext(bchanl->subjectoptionwindow, buf, 512);
583
584         bchanl_updatesubjectorder(bchanl, order, orderby, buf, len);
585
586         layout = bchanl_subject_getlayout(bchanl->currentsubject);
587         sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
588         subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
589 }
590
591 LOCAL VOID bchanl_sendsubjectrequest(bchanl_t *bchanl, bchanl_subject_t *subject)
592 {
593         sbjtcache_t *cache;
594         W err;
595
596         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
597         pdsp_msg(bchanl->hmistate.msg_retr_subject);
598
599         cache = bchanl_subject_getcache(subject);
600         err = sbjtretriever_sendrequest(bchanl->retriever, cache);
601         if (err < 0) {
602                 pdsp_msg(bchanl->hmistate.msg_error_retr);
603                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
604                 return;
605         }
606         bchanl_setnextsubject(bchanl, subject);
607         set_flg(bchanl->flgid, BCHANL_NETWORK_FLAG_WAITHTTPEVENT);
608 }
609
610 LOCAL VOID bchanl_bbsmenuwindow_click(bchanl_t *bchanl, PNT pos)
611 {
612         bbsmnparser_item_t *item;
613         bchanl_subject_t *subject;
614         W fnd;
615         UB *host, *board;
616         W host_len, board_len;
617         UH port;
618         TC *title;
619         W title_len;
620
621         fnd = bbsmndraw_findboard(bchanl->bbsmenu.draw, pos, &item);
622         if (fnd == 0) {
623                 DP(("not found\n"));
624                 return;
625         }
626         if (item->category != NULL) {
627                 return;
628         }
629         bbsmnparser_item_gethostboard(item, &host, &host_len, &port, &board, &board_len);
630         subject = bchanl_subjecthash_search(bchanl->subjecthash, host, host_len, port, board, board_len);
631         if (subject == NULL) {
632                 DP(("not found by subject hash"));
633                 return;
634         }
635         bchanl_subject_gettitle(subject, &title, &title_len);
636
637         bchanl_sendsubjectrequest(bchanl, subject);
638 }
639
640 LOCAL VOID bchanl_bbsmenuwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
641 {
642         switch (dck) {
643         case    W_DCLICK:
644         case    W_PRESS:
645         case    W_QPRESS:
646         default:
647                 return;
648         case    W_CLICK:
649                 bchanl_bbsmenuwindow_click(bchanl, evpos);
650         }
651 }
652
653 LOCAL W bchanl_bbsmenu_initialize(bchanl_bbsmenu_t *bchanl, GID gid, bchanl_subjecthash_t *subjecthash, LINK *storage, http_connector_t *connector)
654 {
655         bbsmnretriever_t *retriever;
656         bbsmncache_t *cache;
657         bbsmnparser_t *parser;
658         bbsmnfilter_t *filter;
659         bbsmnlayout_t *layout;
660         bbsmndraw_t *draw;
661         extbbslist_t *extbbslist;
662         TC *category_extbbs;
663         W err;
664
665         cache = bbsmncache_new();
666         if (cache == NULL) {
667                 goto error_cache;
668         }
669         retriever = bbsmnretriever_new(connector, bchanl_httpheader_useragent, bchanl_httpheader_useragent_len);
670         if (retriever == NULL) {
671                 goto error_retriever;
672         }
673         parser = bbsmnparser_new(cache);
674         if (parser == NULL) {
675                 goto error_parser;
676         }
677         filter = bbsmnfilter_new();
678         if (filter == NULL) {
679                 goto error_filter;
680         }
681         layout = bbsmnlayout_new(gid);
682         if (layout == NULL) {
683                 goto error_layout;
684         }
685         draw = bbsmndraw_new(layout);
686         if (draw == NULL) {
687                 goto error_draw;
688         }
689         extbbslist = extbbslist_new(storage, BCHANL_COMMONSTORAGE_EXTBBSLIST_RECTYPE, BCHANL_COMMONSTORAGE_EXTBBSLIST_SUBTYPE);
690         if (extbbslist == NULL) {
691                 DP_ER("extbbslist_new", 0);
692                 goto error_extbbslist;
693         }
694         err = extbbslist_readfile(extbbslist);
695         if (err < 0) {
696                 DP_ER("extbbslist_readfile", 0);
697                 goto error_extbbslist_readfile;
698         }
699         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_CATE_EXTBBS, (void**)&category_extbbs);
700
701         bchanl->gid = gid;
702         bchanl->retriever = retriever;
703         bchanl->cache = cache;
704         bchanl->parser = parser;
705         bchanl->filter = filter;
706         bchanl->layout = layout;
707         bchanl->draw = draw;
708         bchanl->subjecthash = subjecthash;
709         bchanl->extbbslist = extbbslist;
710         bchanl->editctx = NULL;
711         bchanl->category_extbbs = category_extbbs;
712
713         return 0;
714
715 error_extbbslist_readfile:
716         extbbslist_delete(extbbslist);
717 error_extbbslist:
718         bbsmndraw_delete(draw);
719 error_draw:
720         bbsmnlayout_delete(layout);
721 error_layout:
722         bbsmnfilter_delete(filter);
723 error_filter:
724         bbsmnparser_delete(parser);
725 error_parser:
726         bbsmnretriever_delete(retriever);
727 error_retriever:
728         bbsmncache_delete(cache);
729 error_cache:
730         return -1; /* TODO */
731 }
732
733 LOCAL W bchanl_bbsmenu_appenditemtohash(bchanl_bbsmenu_t *bchanl, bbsmnparser_item_t *item)
734 {
735         W err;
736         UB *host, *board;
737         W host_len, board_len;
738         UH port;
739
740         bbsmnparser_item_gethostboard(item, &host, &host_len, &port, &board, &board_len);
741         err = bchanl_subjecthash_append(bchanl->subjecthash, host, host_len, port, board, board_len, item->title, item->title_len);
742         return err;
743 }
744
745 LOCAL VOID bchanl_bbsmenu_registerexternalbbs(bchanl_bbsmenu_t *bchanl, TC *title, W title_len, TC *url, W url_len)
746 {
747         extbbslist_editcontext_append(bchanl->editctx, title, title_len, url, url_len);
748 }
749
750 LOCAL VOID bchanl_bbsmenu_relayoutcache(bchanl_bbsmenu_t *bchanl)
751 {
752         W err, ret;
753         bbsmnparser_t *parser = bchanl->parser;
754         bbsmnparser_item_t *item;
755         bbsmnfilter_t *filter = bchanl->filter;
756         bbsmnlayout_t *layout = bchanl->layout;
757
758         for (;;) {
759                 err = bbsmnparser_getnextitem(parser, &item);
760                 if (err != 1) {
761                         break;
762                 }
763                 bbsmnfilter_inputitem(filter, item);
764                 for (;;) {
765                         ret = bbsmnfilter_outputitem(filter, &item);
766                         if (item != NULL) {
767                                 if (item->category == NULL) {
768                                         err = bchanl_bbsmenu_appenditemtohash(bchanl, item);
769                                         if (err < 0) {
770                                                 return;
771                                         }
772                                 }
773                                 err = bbsmnlayout_appenditem(layout, item);
774                                 if (err < 0) {
775                                         return;
776                                 }
777                         }
778                         if (ret != BBSMNFILTER_OUTPUTITEM_CONTINUE) {
779                                 break;
780                         }
781                 }
782                 if (ret == BBSMNFILTER_OUTPUTITEM_END) {
783                         printf("D\n");
784                         break;
785                 }
786                 if (ret != BBSMNFILTER_OUTPUTITEM_WAITNEXT) {
787                         /* TODO: error */
788                         break;
789                 }
790 /*
791                 if (item == NULL) {
792                         printf("F\n");
793                         break;
794                 }
795 */
796         }
797 }
798
799 LOCAL VOID bchanl_bbsmenu_relayoutexternal(bchanl_bbsmenu_t *bchanl)
800 {
801         W err, ret, title_len, url_len;
802         Bool cont;
803         TC *title;
804         UB *url;
805         extbbslist_readcontext_t *ctx;
806         bbsmnparser_t *parser = bchanl->parser;
807         bbsmnparser_item_t *item;
808         bbsmnlayout_t *layout = bchanl->layout;
809         extbbslist_t *list = bchanl->extbbslist;
810
811         ret = extbbslist_number(bchanl->extbbslist);
812         if (ret <= 0) {
813                 return;
814         }
815
816         ctx = extbbslist_startread(list);
817         if (ctx == NULL) {
818                 return;
819         }
820         for (;;) {
821                 cont = extbbslist_readcontext_getnext(ctx, &title, &title_len, &url, &url_len);
822                 if (cont == False) {
823                         break;
824                 }
825
826                 item = bbsmnparser_newboarditem(parser, title, title_len, url, url_len);
827                 if (item == NULL) {
828                         break;
829                 }
830                 err = bchanl_bbsmenu_appenditemtohash(bchanl, item);
831                 if (err < 0) {
832                         break;
833                 }
834                 err = bbsmnlayout_appenditem(layout, item);
835                 if (err < 0) {
836                         break;
837                 }
838         }
839         extbbslist_endread(list, ctx);
840 }
841
842 LOCAL VOID bchanl_bbsmenu_relayout(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *window)
843 {
844         W l, t, r, b;
845
846         bbsmnlayout_clear(bchanl->layout);
847         bbsmnfilter_clear(bchanl->filter);
848         bbsmnparser_clear(bchanl->parser);
849
850         bchanl_bbsmenu_relayoutcache(bchanl);
851         bchanl_bbsmenu_relayoutexternal(bchanl);
852
853         bbsmnlayout_getdrawrect(bchanl->layout, &l, &t, &r, &b);
854         bbsmenuwindow_setdrawrect(window, l, t, r, b);
855
856         bbsmenuwindow_requestredisp(window);
857 }
858
859 LOCAL Bool bchanl_registerexternalbbs(bchanl_t *bchanl)
860 {
861         TC title[128];
862         TC url[256];
863         W title_len, url_len, l, t, r, b;
864         TCURL_CHECK_VALID_BBSURL ret;
865         GID gid;
866
867         title_len = registerexternalwindow_getboradnametext(bchanl->registerexternalwindow, title, 128);
868         if (title_len < 0) {
869                 DP_ER("registerexternalwindow_getboradnametext error", title_len);
870                 return True;
871         }
872         title[title_len] = TNULL;
873         url_len = registerexternalwindow_geturltext(bchanl->registerexternalwindow, url, 255);
874         if (url_len < 0) {
875                 DP_ER("registerexternalwindow_geturltext error", url_len);
876                 return True;
877         }
878         url[url_len] = TNULL;
879
880         ret = tcurl_check_valid_bbsurl(url, url_len);
881         switch (ret) {
882         case TCURL_CHECK_VALID_BBSURL_NO_LAST_SLSH:
883                 url[url_len] = TK_SLSH;
884                 url_len++;
885                 /* intentional */
886         case TCURL_CHECK_VALID_BBSURL_OK:
887                 break;
888         case TCURL_CHECK_VALID_BBSURL_INVALID_SCHEME:
889                 bchan_panels_urlerror_scheme();
890                 return False;
891         case TCURL_CHECK_VALID_BBSURL_INVALID_HOST:
892                 bchan_panels_urlerror_host();
893                 return False;
894         case TCURL_CHECK_VALID_BBSURL_INVALID_PATH:
895                 bchan_panels_urlerror_path();
896                 return False;
897         }
898
899         bchanl_bbsmenu_registerexternalbbs(&bchanl->bbsmenu, title, title_len, url, url_len);
900
901         registerexternalwindow_setboradnametext(bchanl->registerexternalwindow, NULL, 0);
902         registerexternalwindow_seturltext(bchanl->registerexternalwindow, NULL, 0);
903
904         gid = externalbbswindow_getGID(bchanl->externalbbswindow);
905         extbbslist_editcontext_getdrawrect(bchanl->bbsmenu.editctx, gid, &l, &t, &r, &b);
906         externalbbswindow_setdrawrect(bchanl->externalbbswindow, l, t, r, b);
907         externalbbswindow_requestredisp(bchanl->externalbbswindow);
908
909         return True;
910 }
911
912 LOCAL VOID bchanl_externalbbswindow_draw(bchanl_t *bchanl)
913 {
914         RECT r;
915
916         do {
917                 if (externalbbswindow_startredisp(bchanl->externalbbswindow, &r) == 0) {
918                         break;
919                 }
920                 externalbbswindow_eraseworkarea(bchanl->externalbbswindow, &r);
921                 extbbslist_editcontext_draw(bchanl->bbsmenu.editctx, externalbbswindow_getGID(bchanl->externalbbswindow), &r);
922         } while (externalbbswindow_endredisp(bchanl->externalbbswindow) > 0);
923 }
924
925 LOCAL VOID bchanl_externalbbswindow_resize(bchanl_t *bchanl, SIZE newsize)
926 {
927         W l,t,r,b;
928
929         extbbslist_editcontext_getviewrect(bchanl->bbsmenu.editctx, &l, &t, &r, &b);
930
931         r = l + newsize.h;
932         b = t + newsize.v;
933
934         extbbslist_editcontext_setviewrect(bchanl->bbsmenu.editctx, l, t, r, b);
935         externalbbswindow_setworkrect(bchanl->externalbbswindow, l, t, r, b);
936 }
937
938 LOCAL VOID bchanl_externalbbswindow_close(bchanl_t *bchanl)
939 {
940         Bool changed, save = False;
941         BCHAN_PANELS_SAVECONFIRM_RESULT confirm;
942
943         changed = extbbslist_editcontext_ischanged(bchanl->bbsmenu.editctx);
944         if (changed != False) {
945                 confirm = bchan_panels_saveconfirm();
946                 switch (confirm) {
947                 case BCHAN_PANELS_SAVECONFIRM_RESULT_CANCEL:
948                         return;
949                 case BCHAN_PANELS_SAVECONFIRM_RESULT_OK_NOSAVE:
950                         save = False;
951                         break;
952                 case BCHAN_PANELS_SAVECONFIRM_RESULT_OK_SAVE:
953                         save = True;
954                         break;
955                 default:
956                         break;
957                 }
958         }
959
960         extbbslist_endedit(bchanl->bbsmenu.extbbslist, bchanl->bbsmenu.editctx, save);
961         bchanl->bbsmenu.editctx = NULL;
962         externalbbswindow_close(bchanl->externalbbswindow);
963         if (save != False) {
964                 bchanl_bbsmenu_relayout(&bchanl->bbsmenu, bchanl->bbsmenuwindow);
965         }
966 }
967
968 LOCAL VOID bchanl_externalbbswindow_butdn(bchanl_t *bchanl, W type, PNT pos)
969 {
970         Bool found;
971         W sel;
972
973         if (type == W_CLICK) {
974                 found = extbbslist_editcontext_finditem(bchanl->bbsmenu.editctx, pos, &sel);
975                 if (found != False) {
976                         extbbslist_editcontext_setselect(bchanl->bbsmenu.editctx, sel);
977                 }
978                 externalbbswindow_requestredisp(bchanl->externalbbswindow);
979         }
980 }
981
982 LOCAL W bchanl_externalbbswindow_paste_readtray(bchanl_t *bchanl)
983 {
984         W err, name_len, url_len;
985         TC *name, *url;
986
987         err = tray_getextbbsinfo(NULL, &name_len, NULL, &url_len);
988         if (err < 0) {
989                 return 1;
990         }
991
992         name = malloc(sizeof(TC)*(name_len+1));
993         if (name == NULL) {
994                 return 1;
995         }
996         url = malloc(sizeof(TC)*url_len+1);
997         if (url == NULL) {
998                 free(name);
999                 return 1;
1000         }
1001
1002         err = tray_getextbbsinfo(name, &name_len, url, &url_len);
1003         if (err < 0) {
1004                 free(url);
1005                 free(name);
1006                 return 1;
1007         }
1008         name[name_len] = TNULL;
1009         url[url_len] = TNULL;
1010
1011         registerexternalwindow_setboradnametext(bchanl->registerexternalwindow, name, name_len);
1012         registerexternalwindow_seturltext(bchanl->registerexternalwindow, url, url_len);
1013         registerexternalwindow_open(bchanl->registerexternalwindow);
1014
1015         free(url);
1016         free(name);
1017
1018         return 0;
1019 }
1020
1021 LOCAL VOID bchanl_externalbbswindow_paste(bchanl_t *bchanl)
1022 {
1023         W nak;
1024         PNT p = {0x8000, 0x8000};
1025         nak = bchanl_externalbbswindow_paste_readtray(bchanl);
1026         externalbbswindow_responsepasterequest(bchanl->externalbbswindow, nak, &p);
1027 }
1028
1029 LOCAL VOID bchanl_externalbbswindow_scroll(bchanl_t *bchanl, W dh, W dv)
1030 {
1031         extbbslist_editcontext_scrollviewrect(bchanl->bbsmenu.editctx, dh, dv);
1032         externalbbswindow_scrollworkarea(bchanl->externalbbswindow, -dh, -dv);
1033 }
1034
1035 #define BCHANL_MESSAGE_RETRIEVER_RELAYOUT 1
1036 #define BCHANL_MESSAGE_RETRIEVER_ERROR -1
1037 #define BCHANL_MESSAGE_HTTP_EVENT 2
1038
1039 LOCAL Bool bchanl_bbsmenu_httpevent(bchanl_bbsmenu_t *bchanl, http_connector_event *hevent)
1040 {
1041         Bool ok;
1042         W err;
1043
1044         ok = bbsmnretriever_iswaitingendpoint(bchanl->retriever, hevent->endpoint);
1045         if (ok == False) {
1046                 return False;
1047         }
1048         err = bbsmnretriever_recievehttpevent(bchanl->retriever, bchanl->cache, hevent);
1049
1050         switch (err) {
1051         case BBSMNRETRIEVER_REQUEST_ALLRELOAD:
1052                 req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
1053                 break;
1054         case BBSMNRETRIEVER_REQUEST_WAITNEXT:
1055                 break;
1056         default:
1057                 req_tmg(0, BCHANL_MESSAGE_RETRIEVER_ERROR);
1058                 DP_ER("bbsmnretriever_recievehttpevent", err);
1059                 break;
1060         }
1061
1062         return True;
1063 }
1064
1065 LOCAL Bool bchanl_subject_httpevent(bchanl_t *bchanl, http_connector_event *hevent)
1066 {
1067         Bool ok;
1068         W err;
1069         sbjtcache_t *cache;
1070         sbjtlayout_t *layout;
1071         sbjtdraw_t *draw;
1072         TC *title;
1073         RECT w_work;
1074         W l, t, r, b, title_len;
1075
1076         if (bchanl->nextsubject == NULL) {
1077                 return False;
1078         }       
1079
1080         ok = sbjtretriever_iswaitingendpoint(bchanl->retriever, hevent->endpoint);
1081         if (ok == False) {
1082                 return False;
1083         }
1084         cache = bchanl_subject_getcache(bchanl->nextsubject);
1085         err = sbjtretriever_recievehttpevent(bchanl->retriever, cache, hevent);
1086
1087         switch (err) {
1088         case SBJTRETRIEVER_REQUEST_ALLRELOAD:
1089                 /* should asynchronous layout? */
1090
1091                 subjectoptionwindow_setfiltertext(bchanl->subjectoptionwindow, NULL, 0);
1092                 err = subjectoptionwindow_setordervalue(bchanl->subjectoptionwindow, SUBJECTOPTIONWINDOW_ORDERVALUE_ASCENDING);
1093                 subjectoptionwindow_setorderbyvalue(bchanl->subjectoptionwindow, SUBJECTOPTIONWINDOW_ORDERBYVALUE_NUMBER);
1094
1095                 bchanl_setcurrentsubject(bchanl, bchanl->nextsubject);
1096                 bchanl_setnextsubject(bchanl, NULL);
1097                 bchanl_subject_relayout(bchanl->currentsubject);
1098
1099                 subjectwindow_getworkrect(bchanl->subjectwindow, &w_work);
1100                 draw = bchanl_subject_getdraw(bchanl->currentsubject);
1101                 sbjtdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
1102                 subjectwindow_setworkrect(bchanl->subjectwindow, 0, 0, w_work.c.right, w_work.c.bottom);
1103
1104                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1105                 sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
1106                 subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
1107
1108                 bchanl_subject_gettitle(bchanl->currentsubject, &title, &title_len);
1109                 subjectwindow_settitle(bchanl->subjectwindow, title);
1110
1111                 pdsp_msg(NULL);
1112                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1113
1114                 break;
1115         case SBJTRETRIEVER_REQUEST_WAITNEXT:
1116                 break;
1117         default:
1118                 req_tmg(0, BCHANL_MESSAGE_RETRIEVER_ERROR);
1119                 DP_ER("sbjtretriever_recievehttpevent", err);
1120                 break;
1121         }
1122
1123         return True;
1124 }
1125
1126 LOCAL VOID bchanl_http_task(W arg)
1127 {
1128         bchanl_t *bchanl;
1129         http_connector_t *connector;
1130         bbsmnretriever_t *retr;
1131         bbsmncache_t *cache;
1132         W err;
1133
1134         bchanl = (bchanl_t*)arg;
1135         connector = bchanl->connector;
1136         retr = bchanl->bbsmenu.retriever;
1137         cache = bchanl->bbsmenu.cache;
1138
1139         for (;;) {
1140                 err = http_connector_waitconnection(connector, T_FOREVER);
1141                 if (err < 0) {
1142                         DP_ER("http_connector_waitconnection", err);
1143                         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_ERROR);
1144                         break;
1145                 }
1146
1147                 err = wai_flg(bchanl->flgid, BCHANL_NETWORK_FLAG_WAITHTTPEVENT, WF_AND, T_FOREVER);
1148                 if (err < 0) {
1149                         DP_ER("wai_flg", err);
1150                 }
1151                 req_tmg(0, BCHANL_MESSAGE_HTTP_EVENT);
1152         }
1153
1154         ext_tsk();
1155 }
1156
1157 LOCAL VOID bchanl_handle_httpevent(bchanl_t *bchanl)
1158 {
1159         W err;
1160         http_connector_event hevent;
1161         Bool rcv;
1162
1163         set_flg(bchanl->flgid, BCHANL_NETWORK_FLAG_WAITHTTPEVENT);
1164
1165         err = http_connector_getevent(bchanl->connector, &hevent);
1166         if (err < 0) {
1167                 return;
1168         }
1169
1170         rcv = bchanl_bbsmenu_httpevent(&bchanl->bbsmenu, &hevent);
1171         if (rcv != False) {
1172                 return;
1173         }
1174
1175         rcv = bchanl_subject_httpevent(bchanl, &hevent);
1176 }
1177
1178 LOCAL W bchanl_prepare_network(bchanl_t *bchanl)
1179 {
1180         if (bchanl->retriever == NULL) {
1181                 return 0;
1182         }
1183
1184         bchanl->taskid = cre_tsk(bchanl_http_task, -1, (W)bchanl);
1185         if (bchanl->taskid < 0) {
1186                 DP_ER("error cre_tsk:", bchanl->taskid);
1187                 return -1;
1188         }
1189         bchanl->flgid = cre_flg(0, DELEXIT);
1190         if (bchanl->flgid < 0) {
1191                 ter_tsk(bchanl->taskid);
1192                 bchanl->taskid = -1;
1193                 DP_ER("error cre_flg:", bchanl->flgid);
1194                 return -1;
1195         }
1196
1197         return 0;
1198 }
1199
1200 LOCAL W bchanl_networkrequest_bbsmenu(bchanl_t *bchanl)
1201 {
1202         W err;
1203         static UW lastrequest = 0;
1204         UW etime;
1205
1206         if (bchanl->flgid < 0) {
1207                 return 0;
1208         }
1209
1210         err = get_etm(&etime);
1211         if (err < 0) {
1212                 DP_ER("get_etm error:", err);
1213                 return err;
1214         }
1215         if (lastrequest + 10000 > etime) {
1216                 return 0;
1217         }
1218         lastrequest = etime;
1219
1220         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
1221         pdsp_msg(bchanl->hmistate.msg_retr_bbsmenu);
1222
1223         err = bbsmnretriever_sendrequest(bchanl->bbsmenu.retriever, bchanl->bbsmenu.cache);
1224         if (err < 0) {
1225                 DP_ER("bbsmnretriever_sendrequest error:", err);
1226                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1227                 return err;
1228         }
1229         set_flg(bchanl->flgid, BCHANL_NETWORK_FLAG_WAITHTTPEVENT);
1230
1231         return 0;
1232 }
1233
1234 LOCAL W bchanl_initialize(bchanl_t *bchanl, VID vid, W exectype, LINK *storage)
1235 {
1236         static  RECT    r0 = {{400, 100, 700+7, 200+30}};
1237         static  RECT    r1 = {{100, 100, 300+7, 300+30}};
1238         static  RECT    r2 = {{400, 300, 800+7, 400+30}};
1239         static  PAT     white = {{0, 16, 16, 0x10ffffff, 0, FILL100}};
1240         static  PAT     bgpat0;
1241         static  PAT *bgpat;
1242         TC *title0 = NULL, *title1 = NULL;
1243         W err;
1244         WID wid;
1245         GID gid;
1246         RECT w_work;
1247         PNT p0 = {450, 0};
1248         http_connector_t *connector;
1249         sbjtretriever_t *retriever;
1250         bchanlhmi_t *hmi;
1251         bchanl_subjecthash_t *subjecthash;
1252         subjectwindow_t *subjectwindow;
1253         bbsmenuwindow_t *bbsmenuwindow;
1254         subjectoptionwindow_t *subjectoptionwindow;
1255         registerexternalwindow_t *registerexternalwindow;
1256         externalbbswindow_t *externalbbswindow;
1257
1258         err = wget_inf(WI_PANELBACK, &bgpat0, sizeof(bgpat0));
1259         if (err != sizeof(bgpat0)) {
1260                 bgpat = &white;
1261         } else {
1262                 bgpat = &bgpat0;
1263         }
1264
1265         connector = http_connector_new();
1266         if (connector == NULL) {
1267                 DP_ER("http_connector_new error", 0);
1268                 goto error_http_connector;
1269         }
1270
1271         retriever = sbjtretriever_new(connector, bchanl_httpheader_useragent, bchanl_httpheader_useragent_len);
1272         if (retriever == NULL) {
1273                 DP_ER("sbjtretriever_new error", 0);
1274                 goto error_retriever;
1275         }
1276         hmi = bchanlhmi_new();
1277         if (hmi == NULL) {
1278                 DP_ER("bchanlhmi_new error", 0);
1279                 goto error_bchanlhmi;
1280         }
1281         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT, (void**)&title0);
1282         subjectwindow = bchanlhmi_newsubjectwindow(hmi, &r0, 0, title0, NULL);
1283         if (subjectwindow == NULL) {
1284                 DP_ER("bchanlhmi_newsubjectwindow error", 0);
1285                 goto error_subjectwindow;
1286         }
1287         gid = subjectwindow_getGID(subjectwindow);
1288         subjecthash = bchanl_subjecthash_new(gid, 100);
1289         if (subjecthash == NULL) {
1290                 DP_ER("bchanl_subjecthash_new error", 0);
1291                 goto error_subjecthash;
1292         }
1293         subjectoptionwindow = bchanlhmi_newsubjectoptionwindow(hmi, &p0, subjectwindow, NULL, bgpat, BCHANL_DBX_TB_SBJTOPT_FLT, BCHANL_DBX_WS_SBJTOPT_ODR, BCHANL_DBX_WS_SBJTOPT_ODRBY);
1294         if (subjectoptionwindow == NULL) {
1295                 DP_ER("bchanlhmi_newsubjectoptionwindow", 0);
1296                 goto error_subjectoptionwindow;
1297         }
1298         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU, (void**)&title1);
1299         bbsmenuwindow = bchanlhmi_newbbsmenuwindow(hmi, &r1, 0, title1, NULL);
1300         if (bbsmenuwindow == NULL) {
1301                 DP_ER("bchanlhmi_newbbsmenuwindow error", 0);
1302                 goto error_bbsmenuwindow;
1303         }
1304         gid = bbsmenuwindow_getGID(bbsmenuwindow);
1305         registerexternalwindow = bchanlhmi_newregisterexternalwindow(hmi, &p0, 0, NULL, bgpat);
1306         if (registerexternalwindow == NULL) {
1307                 DP_ER("bchanlhmi_newregisterexternalwindow error", 0);
1308                 goto error_registerexternalwindow;
1309         }
1310         externalbbswindow = bchanlhmi_newexternalbbswindow(hmi, &r2, 0, NULL, NULL);
1311         if (externalbbswindow == NULL) {
1312                 DP_ER("bchanlhmi_newexternalbbswindow", 0);
1313                 goto error_externalbbswindow;
1314         }
1315         err = bchanl_bbsmenu_initialize(&(bchanl->bbsmenu), gid, subjecthash, storage, connector);
1316         if (err < 0) {
1317                 DP_ER("bchanl_bbsmenu_initialize error", err);
1318                 goto error_bbsmenu;
1319         }
1320         err = bchanl_mainmenu_initialize(&(bchanl->mainmenu), BCHANL_DBX_MENU_TEST);
1321         if (err < 0) {
1322                 DP_ER("bchanl_mainmenu_initialize %d", err);
1323                 goto error_mainmenu;
1324         }
1325
1326         bchanl_hmistate_initialize(&bchanl->hmistate);
1327
1328         if (exectype == EXECREQ) {
1329                 wid = bbsmenuwindow_getWID(bbsmenuwindow);
1330                 osta_prc(vid, wid);
1331         }
1332
1333         bbsmenuwindow_getworkrect(bbsmenuwindow, &w_work);
1334         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, 0, 0, w_work.c.right, w_work.c.bottom);
1335         bbsmenuwindow_setworkrect(bbsmenuwindow, 0, 0, w_work.c.right, w_work.c.bottom);
1336
1337         bchanl->connector = connector;
1338         bchanl->retriever = retriever;
1339         bchanl->subjecthash = subjecthash;
1340
1341         bchanl->currentsubject = NULL;
1342         bchanl->nextsubject = NULL;
1343         bchanl->subjectdisplay.resnum = True;
1344         bchanl->subjectdisplay.since = False;
1345         bchanl->subjectdisplay.vigor = False;
1346
1347         bchanl->vid = vid;
1348         bchanl->exectype = exectype;
1349
1350         bchanl->hmi = hmi;
1351         bchanl->subjectwindow = subjectwindow;
1352         bchanl->bbsmenuwindow = bbsmenuwindow;
1353         bchanl->subjectoptionwindow = subjectoptionwindow;
1354         bchanl->registerexternalwindow = registerexternalwindow;
1355         bchanl->externalbbswindow = externalbbswindow;
1356
1357         return 0;
1358
1359 error_mainmenu:
1360         //bchanl_bbsmenu_finalize(&(bchanl->bbsmenu));
1361 error_bbsmenu:
1362         bchanlhmi_deleteexternalbbswindow(hmi, externalbbswindow);
1363 error_externalbbswindow:
1364         bchanlhmi_deleteregisterexternalwindow(hmi, registerexternalwindow);
1365 error_registerexternalwindow:
1366         bchanlhmi_deletebbsmenuwindow(hmi, bbsmenuwindow);
1367 error_bbsmenuwindow:
1368         bchanlhmi_deletesubjectoptionwindow(hmi, subjectoptionwindow);
1369 error_subjectoptionwindow:
1370         bchanl_subjecthash_delete(subjecthash);
1371 error_subjecthash:
1372         bchanlhmi_deletesubjectwindow(hmi, subjectwindow);
1373 error_subjectwindow:
1374         bchanlhmi_delete(hmi);
1375 error_bchanlhmi:
1376         sbjtretriever_delete(retriever);
1377 error_retriever:
1378         http_connector_delete(connector);
1379 error_http_connector:
1380         return -1; /* TODO */
1381 }
1382
1383 LOCAL VOID bchanl_killme(bchanl_t *bchanl)
1384 {
1385         gset_ptr(PS_BUSY, NULL, -1, -1);
1386         pdsp_msg(NULL);
1387
1388         extbbslist_writefile(bchanl->bbsmenu.extbbslist);
1389         if (bchanl->exectype == EXECREQ) {
1390                 oend_prc(bchanl->vid, NULL, 0);
1391         }
1392         bchanl_mainmenu_finalize(&bchanl->mainmenu);
1393         bchanlhmi_deleteexternalbbswindow(bchanl->hmi, bchanl->externalbbswindow);
1394         bchanlhmi_deleteregisterexternalwindow(bchanl->hmi, bchanl->registerexternalwindow);
1395         bchanlhmi_deletebbsmenuwindow(bchanl->hmi, bchanl->bbsmenuwindow);
1396         bchanlhmi_deletesubjectoptionwindow(bchanl->hmi, bchanl->subjectoptionwindow);
1397         bchanl_subjecthash_delete(bchanl->subjecthash);
1398         bchanlhmi_deletesubjectwindow(bchanl->hmi, bchanl->subjectwindow);
1399         bchanlhmi_delete(bchanl->hmi);
1400         sbjtretriever_delete(bchanl->retriever);
1401         http_connector_delete(bchanl->connector);
1402
1403         ext_prc(0);
1404 }
1405
1406 LOCAL VOID bchanl_readbbsmenutestdata(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *bchanl_window)
1407 {
1408         TC fname[] = {TK_b, TK_b, TK_s, TK_m, TK_e, TK_n, TK_u, TK_PROD, TK_h, TK_t, TK_m, TK_l, TNULL};
1409         LINK lnk;
1410         W fd, len, err;
1411         UB *bin;
1412         RECT w_work;
1413         bbsmncache_t *cache = bchanl->cache;
1414         bbsmndraw_t *draw = bchanl->draw;
1415
1416         err = get_lnk(fname, &lnk, F_NORM);
1417         if (err < 0) {
1418                 DP_ER("error get_lnk", err);
1419                 return;
1420         }
1421         fd = opn_fil(&lnk, F_READ, NULL);
1422         if (fd < 0) {
1423                 return;
1424         }
1425         err = rea_rec(fd, 0, NULL, 0, &len, NULL);
1426         if (err < 0) {
1427                 cls_fil(fd);
1428                 return;
1429         }
1430         bin = malloc(len);
1431         if (bin == NULL) {
1432                 cls_fil(fd);
1433                 return;
1434         }
1435         err = rea_rec(fd, 0, bin, len, 0, NULL);
1436         if (err < 0) {
1437                 free(bin);
1438                 cls_fil(fd);
1439                 return;
1440         }
1441         cls_fil(fd);
1442
1443         bbsmncache_appenddata(cache, bin, len);
1444         free(bin);
1445
1446         bbsmenuwindow_getworkrect(bchanl_window, &w_work);
1447         bbsmndraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
1448         bbsmenuwindow_setworkrect(bchanl_window, 0, 0, w_work.c.right, w_work.c.bottom);
1449 }
1450
1451 LOCAL VOID bchanl_subjectwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
1452 {
1453         W l,t,r,b,l1,t1,r1,b1,scr;
1454         sbjtlayout_t *layout;
1455         sbjtdraw_t *draw;
1456
1457         if (bchanl->currentsubject == NULL) {
1458                 return;
1459         }
1460         draw = bchanl_subject_getdraw(bchanl->currentsubject);
1461
1462         switch (ch) {
1463         case KC_CC_U:
1464                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1465                 if (t < 16) {
1466                         scr = -t;
1467                 } else {
1468                         scr = -16;
1469                 }
1470                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1471                 bchanl_subjectwindow_scroll(bchanl, 0, scr);
1472                 break;
1473         case KC_CC_D:
1474                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1475                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1476                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1477                 if (b + 16 > b1) {
1478                         scr = b1 - b;
1479                 } else {
1480                         scr = 16;
1481                 }
1482                 if (scr > 0) {
1483                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1484                         bchanl_subjectwindow_scroll(bchanl, 0, scr);
1485                 }
1486                 break;
1487         case KC_CC_R:
1488                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1489                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1490                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1491                 if (r + 16 > r1) {
1492                         scr = r1 - r;
1493                 } else {
1494                         scr = 16;
1495                 }
1496                 if (scr > 0) {
1497                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1498                         bchanl_subjectwindow_scroll(bchanl, scr, 0);
1499                 }
1500                 break;
1501         case KC_CC_L:
1502                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1503                 if (l < 16) {
1504                         scr = -l;
1505                 } else {
1506                         scr = -16;
1507                 }
1508                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1509                 bchanl_subjectwindow_scroll(bchanl, scr, 0);
1510                 break;
1511         case KC_PG_U:
1512                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1513                 if (t < (b - t)) {
1514                         scr = -t;
1515                 } else {
1516                         scr = - (b - t);
1517                 }
1518                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1519                 bchanl_subjectwindow_scroll(bchanl, 0, scr);
1520                 break;
1521         case KC_PG_D:
1522                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1523                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1524                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1525                 if (b + (b - t) > b1) {
1526                         scr = b1 - b;
1527                 } else {
1528                         scr = (b - t);
1529                 }
1530                 if (scr > 0) {
1531                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1532                         bchanl_subjectwindow_scroll(bchanl, 0, scr);
1533                 }
1534                 break;
1535         case KC_PG_R:
1536                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1537                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1538                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1539                 if (r + (r - l) > r1) {
1540                         scr = r1 - r;
1541                 } else {
1542                         scr = (r - l);
1543                 }
1544                 if (scr > 0) {
1545                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1546                         bchanl_subjectwindow_scroll(bchanl, scr, 0);
1547                 }
1548                 break;
1549         case KC_PG_L:
1550                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1551                 if (l < (r - l)) {
1552                         scr = -l;
1553                 } else {
1554                         scr = - (r - l);
1555                 }
1556                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1557                 bchanl_subjectwindow_scroll(bchanl, scr, 0);
1558                 break;
1559         case TK_E: /* temporary */
1560                 if (stat & ES_CMD) {
1561                         bchanl_killme(bchanl);
1562                 }
1563                 break;
1564         }
1565 }
1566
1567 LOCAL VOID bchanl_bbsmenuwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
1568 {
1569         W l,t,r,b,l1,t1,r1,b1,scr;
1570         bbsmndraw_t *draw = bchanl->bbsmenu.draw;
1571         bbsmnlayout_t *layout = bchanl->bbsmenu.layout;
1572
1573         switch (ch) {
1574         case KC_CC_U:
1575                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1576                 if (t < 16) {
1577                         scr = -t;
1578                 } else {
1579                         scr = -16;
1580                 }
1581                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1582                 bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1583                 break;
1584         case KC_CC_D:
1585                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1586                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1587                 if (b + 16 > b1) {
1588                         scr = b1 - b;
1589                 } else {
1590                         scr = 16;
1591                 }
1592                 if (scr > 0) {
1593                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1594                         bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1595                 }
1596                 break;
1597         case KC_CC_R:
1598         case KC_CC_L:
1599                 break;
1600         case KC_PG_U:
1601                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1602                 if (t < (b - t)) {
1603                         scr = -t;
1604                 } else {
1605                         scr = - (b - t);
1606                 }
1607                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1608                 bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1609                 break;
1610         case KC_PG_D:
1611                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1612                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1613                 if (b + (b - t) > b1) {
1614                         scr = b1 - b;
1615                 } else {
1616                         scr = (b - t);
1617                 }
1618                 if (scr > 0) {
1619                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1620                         bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1621                 }
1622                 break;
1623         case KC_PG_R:
1624         case KC_PG_L:
1625                 break;
1626         case KC_PF5:
1627                 //bchanl_networkrequest_bbsmenu(bchanl);
1628                 break;
1629         case TK_E: /* temporary */
1630                 if (stat & ES_CMD) {
1631                         bchanl_killme(bchanl);
1632                 }
1633                 break;
1634         }
1635 }
1636
1637
1638 LOCAL VOID bchanl_keydwn(bchanl_t *bchanl, UH keytop, TC ch, UW stat)
1639 {
1640         Bool act;
1641
1642         act = subjectwindow_isactive(bchanl->subjectwindow);
1643         if (act == True) {
1644                 bchanl_subjectwindow_keydwn(bchanl, keytop, ch, stat);
1645                 return;
1646         }
1647         act = bbsmenuwindow_isactive(bchanl->bbsmenuwindow);
1648         if (act == True) {
1649                 bchanl_bbsmenuwindow_keydwn(bchanl, keytop, ch, stat);
1650                 return;
1651         }
1652 }
1653
1654 enum BCHANL_TEXTBOX_MENU_TYPE_ {
1655         BCHANL_TEXTBOX_MENU_TYPE_NONE,
1656         BCHANL_TEXTBOX_MENU_TYPE_FILTER,
1657         BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE,
1658         BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL,
1659 };
1660 typedef enum BCHANL_TEXTBOX_MENU_TYPE_ BCHANL_TEXTBOX_MENU_TYPE;
1661
1662 LOCAL VOID bchanl_setupmenu(bchanl_t *bchanl, BCHANL_TEXTBOX_MENU_TYPE type)
1663 {
1664         Bool isactive, isopen, isopen_extbbs, selected = False, fromtray, totray, trayempty;
1665         W index, num;
1666
1667         isactive = subjectwindow_isactive(bchanl->subjectwindow);
1668         isopen = subjectoptionwindow_isopen(bchanl->subjectoptionwindow);
1669         isopen_extbbs = externalbbswindow_isopen(bchanl->externalbbswindow);
1670         if (isopen_extbbs != False) {
1671                 index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1672                 if (index >= 0) {
1673                         selected = True;
1674                 }
1675         }
1676         switch (type) {
1677         case BCHANL_TEXTBOX_MENU_TYPE_NONE:
1678         default:
1679                 fromtray = totray = False;
1680                 break;
1681         case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1682                 trayempty = tray_isempty();
1683                 if (trayempty == False) {
1684                         fromtray = True;
1685                 } else {
1686                         fromtray = False;
1687                 }
1688                 num = subjectoptionwindow_cutfiltertext(bchanl->subjectoptionwindow, NULL, 0, False);
1689                 if (num > 0) {
1690                         totray = True;
1691                 } else {
1692                         totray = False;
1693                 }
1694                 break;
1695         case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1696                 trayempty = tray_isempty();
1697                 if (trayempty == False) {
1698                         fromtray = True;
1699                 } else {
1700                         fromtray = False;
1701                 }
1702                 num = registerexternalwindow_cutboradnametext(bchanl->registerexternalwindow, NULL, 0, False);
1703                 if (num > 0) {
1704                         totray = True;
1705                 } else {
1706                         totray = False;
1707                 }
1708                 break;
1709         case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1710                 trayempty = tray_isempty();
1711                 if (trayempty == False) {
1712                         fromtray = True;
1713                 } else {
1714                         fromtray = False;
1715                 }
1716                 num = registerexternalwindow_cuturltext(bchanl->registerexternalwindow, NULL, 0, False);
1717                 if (num > 0) {
1718                         totray = True;
1719                 } else {
1720                         totray = False;
1721                 }
1722                 break;
1723         }
1724
1725         bchanl_mainmenu_setup(&bchanl->mainmenu, isactive, isopen, isopen_extbbs, selected, fromtray, totray, bchanl->subjectdisplay.resnum, bchanl->subjectdisplay.since, bchanl->subjectdisplay.vigor);
1726 }
1727
1728 LOCAL VOID bchanl_selectmenu(bchanl_t *bchanl, W sel, BCHANL_TEXTBOX_MENU_TYPE type)
1729 {
1730         Bool isopen;
1731         RECT work;
1732 #define BCHANL_SELECTMENU_STRBUF_LENGTH 256
1733         TC str[BCHANL_SELECTMENU_STRBUF_LENGTH];
1734         W index, len = 0, l, t, r, b;
1735         GID gid;
1736
1737         switch(sel) {
1738         case BCHANL_MAINMENU_SELECT_CLOSE: /* [½ªÎ»] */
1739                 bchanl_killme(bchanl);
1740                 break;
1741         case BCHANL_MAINMENU_SELECT_REDISPLAY: /* [ºÆɽ¼¨] */
1742                 subjectwindow_requestredisp(bchanl->subjectwindow);
1743                 bbsmenuwindow_requestredisp(bchanl->bbsmenuwindow);
1744                 break;
1745         case BCHANL_MAINMENU_SELECT_BBSMENUFETCH: /* [ÈÄ°ìÍ÷ºÆ¼èÆÀ] */
1746                 //bchanl_networkrequest_bbsmenu(bchanl);
1747                 break;
1748         case BCHANL_MAINMENU_SELECT_SUBJECTOPTION: /* [¥¹¥ì°ìÍ÷ÀßÄê] */
1749                 isopen = subjectoptionwindow_isopen(bchanl->subjectoptionwindow);
1750                 if (isopen == False) {
1751                         subjectoptionwindow_open(bchanl->subjectoptionwindow);
1752                 } else {
1753                         subjectoptionwindow_close(bchanl->subjectoptionwindow);
1754                 }
1755                 break;
1756         case BCHANL_MAINMENU_SELECT_EXTBBS_MANAGER: /* [³°ÉôÈĤÎÄɲÃ] */
1757                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1758                 if (isopen == False) {
1759
1760                         bchanl->bbsmenu.editctx = extbbslist_startedit(bchanl->bbsmenu.extbbslist);
1761                         if (bchanl->bbsmenu.editctx == NULL) {
1762                                 break;
1763                         }
1764                         externalbbswindow_open(bchanl->externalbbswindow);
1765                         externalbbswindow_getworkrect(bchanl->externalbbswindow, &work);
1766                         extbbslist_editcontext_setviewrect(bchanl->bbsmenu.editctx, 0, 0, work.c.right - work.c.left, work.c.bottom - work.c.top);
1767                         externalbbswindow_setworkrect(bchanl->externalbbswindow, 0, 0, work.c.right - work.c.left, work.c.bottom - work.c.top);
1768                         gid = externalbbswindow_getGID(bchanl->externalbbswindow);
1769                         extbbslist_editcontext_getdrawrect(bchanl->bbsmenu.editctx, gid, &l, &t, &r, &b);
1770                         externalbbswindow_setdrawrect(bchanl->externalbbswindow, l, t, r, b);
1771                 }
1772                 break;
1773         case BCHANL_MAINMENU_SELECT_EXTBBS_REGISTER:
1774                 isopen = registerexternalwindow_isopen(bchanl->registerexternalwindow);
1775                 if (isopen == False) {
1776                         registerexternalwindow_open(bchanl->registerexternalwindow);
1777                 }
1778                 break;
1779         case BCHANL_MAINMENU_SELECT_EXTBBS_UP:
1780                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1781                 if (isopen != False) {
1782                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1783                         if (index < 0) {
1784                                 break;
1785                         }
1786                         extbbslist_editcontext_swapitem(bchanl->bbsmenu.editctx, index-1, index);
1787                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1788                 }
1789                 break;
1790         case BCHANL_MAINMENU_SELECT_EXTBBS_DOWN:
1791                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1792                 if (isopen != False) {
1793                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1794                         if (index < 0) {
1795                                 break;
1796                         }
1797                         extbbslist_editcontext_swapitem(bchanl->bbsmenu.editctx, index, index+1);
1798                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1799                 }
1800                 break;
1801         case BCHANL_MAINMENU_SELECT_EXTBBS_DELETE:
1802                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1803                 if (isopen != False) {
1804                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1805                         if (index < 0) {
1806                                 break;
1807                         }
1808                         extbbslist_editcontext_deleteitem(bchanl->bbsmenu.editctx, index);
1809                         gid = externalbbswindow_getGID(bchanl->externalbbswindow);
1810                         extbbslist_editcontext_getdrawrect(bchanl->bbsmenu.editctx, gid, &l, &t, &r, &b);
1811                         externalbbswindow_setdrawrect(bchanl->externalbbswindow, l, t, r, b);
1812                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1813                 }
1814                 break;
1815         case BCHANL_MAINMENU_SELECT_EDIT_COPY_TO_TRAY:
1816                 switch (type) {
1817                 case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1818                         len = subjectoptionwindow_cutfiltertext(bchanl->subjectoptionwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, False);
1819                         break;
1820                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1821                         len = registerexternalwindow_cutboradnametext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, False);
1822                         break;
1823                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1824                         len = registerexternalwindow_cuturltext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, False);
1825                         break;
1826                 default:
1827                         break;
1828                 }
1829                 if (len > 0) {
1830                         tray_pushstring(str, len);
1831                 }
1832                 break;
1833         case BCHANL_MAINMENU_SELECT_EDIT_COPY_FROM_TRAY:
1834                 len = tray_popstring(str, BCHANL_SELECTMENU_STRBUF_LENGTH);
1835                 switch (type) {
1836                 case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1837                         subjectoptionwindow_insertfiltertext(bchanl->subjectoptionwindow, str, len);
1838                         break;
1839                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1840                         registerexternalwindow_insertboradnametext(bchanl->registerexternalwindow, str, len);
1841                         break;
1842                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1843                         registerexternalwindow_inserturltext(bchanl->registerexternalwindow, str, len);
1844                         break;
1845                 default:
1846                         break;
1847                 }
1848                 break;
1849         case BCHANL_MAINMENU_SELECT_EDIT_MOVE_TO_TRAY:
1850                 switch (type) {
1851                 case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1852                         len = subjectoptionwindow_cutfiltertext(bchanl->subjectoptionwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1853                         break;
1854                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1855                         len = registerexternalwindow_cutboradnametext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1856                         break;
1857                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1858                         len = registerexternalwindow_cuturltext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1859                         break;
1860                 default:
1861                         break;
1862                 }
1863                 if (len > 0) {
1864                         tray_pushstring(str, len);
1865                 }
1866                 break;
1867         case BCHANL_MAINMENU_SELECT_EDIT_MOVE_FROM_TRAY:
1868                 len = tray_popstring(str, BCHANL_SELECTMENU_STRBUF_LENGTH);
1869                 switch (type) {
1870                 case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1871                         subjectoptionwindow_insertfiltertext(bchanl->subjectoptionwindow, str, len);
1872                         break;
1873                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1874                         registerexternalwindow_insertboradnametext(bchanl->registerexternalwindow, str, len);
1875                         break;
1876                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1877                         registerexternalwindow_inserturltext(bchanl->registerexternalwindow, str, len);
1878                         break;
1879                 default:
1880                         break;
1881                 }
1882                 tray_deletedata();
1883                 break;
1884         case BCHANL_MAINMENU_SELECT_EDIT_DELETE:
1885                 switch (type) {
1886                 case BCHANL_TEXTBOX_MENU_TYPE_FILTER:
1887                         subjectoptionwindow_cutfiltertext(bchanl->subjectoptionwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1888                         break;
1889                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE:
1890                         registerexternalwindow_cutboradnametext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1891                         break;
1892                 case BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL:
1893                         registerexternalwindow_cuturltext(bchanl->registerexternalwindow, str, BCHANL_SELECTMENU_STRBUF_LENGTH, True);
1894                         break;
1895                 default:
1896                         break;
1897                 }
1898                 break;
1899         case BCHANL_MAINMENU_SELECT_DISPLAY_RESNUMBER:
1900                 bchanl_swapresnumberdisplay(bchanl);
1901                 if (bchanl->currentsubject != NULL) {
1902                         bchanl_subject_setresnumberdisplay(bchanl->currentsubject, bchanl->subjectdisplay.resnum);
1903                         bchanl_changedisplayattribute(bchanl);
1904                 }
1905                 break;
1906         case BCHANL_MAINMENU_SELECT_DISPLAY_SINCE:
1907                 bchanl_swapsincedisplay(bchanl);
1908                 if (bchanl->currentsubject != NULL) {
1909                         bchanl_subject_setsincedisplay(bchanl->currentsubject, bchanl->subjectdisplay.since);
1910                         bchanl_changedisplayattribute(bchanl);
1911                 }
1912                 break;
1913         case BCHANL_MAINMENU_SELECT_DISPLAY_VIGOR:
1914                 bchanl_swapvigordisplay(bchanl);
1915                 if (bchanl->currentsubject != NULL) {
1916                         bchanl_subject_setvigordisplay(bchanl->currentsubject, bchanl->subjectdisplay.vigor);
1917                         bchanl_changedisplayattribute(bchanl);
1918                 }
1919                 break;
1920         }
1921         return;
1922 }
1923
1924 LOCAL VOID bchanl_popupmenu(bchanl_t *bchanl, PNT pos, BCHANL_TEXTBOX_MENU_TYPE type)
1925 {
1926         W sel;
1927         bchanl_setupmenu(bchanl, type);
1928         gset_ptr(PS_SELECT, NULL, -1, -1);
1929         sel = bchanl_mainmenu_popup(&bchanl->mainmenu, pos);
1930         if (sel > 0) {
1931                 bchanl_selectmenu(bchanl, sel, type);
1932         }
1933 }
1934
1935 LOCAL W bchanl_keyselect(bchanl_t *bchanl, TC keycode, BCHANL_TEXTBOX_MENU_TYPE type)
1936 {
1937         W sel;
1938         bchanl_setupmenu(bchanl, type);
1939         sel = bchanl_mainmenu_keyselect(&bchanl->mainmenu, keycode);
1940         if (sel > 0) {
1941                 bchanl_selectmenu(bchanl, sel, type);
1942         }
1943         return 0;
1944 }
1945
1946 LOCAL VOID bchanl_handletimeout(bchanl_t *bchanl, W code)
1947 {
1948         switch (code) {
1949         case BCHANL_MESSAGE_RETRIEVER_RELAYOUT:
1950                 bchanl_bbsmenu_relayout(&bchanl->bbsmenu, bchanl->bbsmenuwindow);
1951                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1952                 pdsp_msg(NULL);
1953                 break;
1954         case BCHANL_MESSAGE_RETRIEVER_ERROR:
1955                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1956                 pdsp_msg(NULL);
1957                 break;
1958         case BCHANL_MESSAGE_HTTP_EVENT:
1959                 bchanl_handle_httpevent(bchanl);
1960                 break;
1961         }
1962 }
1963
1964 LOCAL VOID bchanl_eventdispatch(bchanl_t *bchanl)
1965 {
1966         bchanlhmievent_t *evt;
1967         W sel, err;
1968         Bool close;
1969
1970         err = bchanlhmi_getevent(bchanl->hmi, &evt);
1971         if (err < 0) {
1972                 return;
1973         }
1974
1975         switch (evt->type) {
1976         case BCHANLHMIEVENT_TYPE_COMMON_MOUSEMOVE:
1977                 break;
1978         case BCHANLHMIEVENT_TYPE_COMMON_KEYDOWN:
1979                 if (evt->data.common_keydown.stat & ES_CMD) {   /*Ì¿Îᥭ¡¼*/
1980                         bchanl_setupmenu(bchanl, BCHANL_TEXTBOX_MENU_TYPE_NONE);
1981                         sel = bchanl_keyselect(bchanl, evt->data.common_keydown.keycode, BCHANL_TEXTBOX_MENU_TYPE_NONE);
1982                         if (sel > 0) {
1983                                 bchanl_selectmenu(bchanl, sel, BCHANL_TEXTBOX_MENU_TYPE_NONE);
1984                                 break;
1985                         }
1986                 }
1987                 bchanl_keydwn(bchanl, evt->data.common_keydown.keytop, evt->data.common_keydown.keycode, evt->data.common_keydown.stat);
1988                 break;
1989         case BCHANLHMIEVENT_TYPE_COMMON_MENU:
1990                 bchanl_popupmenu(bchanl, evt->data.common_menu.pos, BCHANL_TEXTBOX_MENU_TYPE_NONE);
1991                 break;
1992         case BCHANLHMIEVENT_TYPE_COMMON_TIMEOUT:
1993                 bchanl_handletimeout(bchanl, evt->data.common_timeout.code);
1994                 break;
1995         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW:
1996                 bchanl_subjectwindow_draw(bchanl);
1997                 break;
1998         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_RESIZE:
1999                 bchanl_subjectwindow_resize(bchanl, evt->data.subjectwindow_resize.work_sz);
2000                 break;
2001         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_CLOSE:
2002                 bchanl_subjectwindow_close(bchanl);
2003                 break;
2004         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_BUTDN:
2005                 bchanl_subjectwindow_butdn(bchanl, evt->data.subjectwindow_butdn.type, evt->data.subjectwindow_butdn.pos);
2006                 break;
2007         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_PASTE:
2008                 subjectwindow_responsepasterequest(bchanl->subjectwindow, /* NACK */ 1, NULL);
2009                 break;
2010         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_MOUSEMOVE:
2011                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
2012                 break;
2013         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL:
2014                 bchanl_subjectwindow_scroll(bchanl, evt->data.subjectwindow_scroll.dh, evt->data.subjectwindow_scroll.dv);
2015                 break;
2016         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW:
2017                 bchanl_bbsmenuwindow_draw(bchanl);
2018                 break;
2019         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_RESIZE:
2020                 bchanl_bbsmenuwindow_resize(bchanl, evt->data.bbsmenuwindow_resize.work_sz);
2021                 break;
2022         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_CLOSE:
2023                 bchanl_bbsmenuwindow_close(bchanl);
2024                 break;
2025         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_BUTDN:
2026                 bchanl_bbsmenuwindow_butdn(bchanl, evt->data.bbsmenuwindow_butdn.type, evt->data.bbsmenuwindow_butdn.pos);
2027                 break;
2028         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_MOUSEMOVE:
2029                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
2030                 break;
2031         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL:
2032                 bchanl_bbsmenuwindow_scroll(bchanl, evt->data.bbsmenuwindow_scroll.dh, evt->data.bbsmenuwindow_scroll.dv);
2033                 break;
2034         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_DETERMINE:
2035                 bchanl_changesubjectfilterword(bchanl, evt->data.subjectoptionwindow_filter_determine.value, evt->data.subjectoptionwindow_filter_determine.len);
2036                 break;
2037         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_COPY:
2038                 break;
2039         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MOVE:
2040                 break;
2041         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MENU:
2042                 bchanl_popupmenu(bchanl, evt->data.subjectoptionwindow_filter_menu.pos, BCHANL_TEXTBOX_MENU_TYPE_FILTER);
2043                 break;
2044         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_KEYMENU:
2045                 bchanl_keyselect(bchanl, evt->data.subjectoptionwindow_filter_keymenu.keycode, BCHANL_TEXTBOX_MENU_TYPE_FILTER);
2046                 break;
2047         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDER_CHANGE:
2048                 bchanl_changesubjectorder(bchanl, evt->data.subjectoptionwindow_order_change.value);
2049                 break;
2050         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDERBY_CHANGE:
2051                 bchanl_changesubjectorderby(bchanl, evt->data.subjectoptionwindow_order_change.value);
2052                 break;
2053         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_DETERMINE:
2054                 break;
2055         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_COPY:
2056                 break;
2057         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MOVE:
2058                 break;
2059         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MENU:
2060                 bchanl_popupmenu(bchanl, evt->data.registerexternalwindow_boradname_menu.pos, BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE);
2061                 break;
2062         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_KEYMENU:
2063                 bchanl_keyselect(bchanl, evt->data.registerexternalwindow_boradname_keymenu.keycode, BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_TITLE);
2064                 break;
2065         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_DETERMINE:
2066                 break;
2067         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_COPY:
2068                 break;
2069         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MOVE:
2070                 break;
2071         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MENU:
2072                 bchanl_popupmenu(bchanl, evt->data.registerexternalwindow_url_menu.pos, BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL);
2073                 break;
2074         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_KEYMENU:
2075                 bchanl_keyselect(bchanl, evt->data.registerexternalwindow_url_keymenu.keycode, BCHANL_TEXTBOX_MENU_TYPE_EXTBBS_URL);
2076                 break;
2077         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_DETERMINE_PUSH:
2078                 close = bchanl_registerexternalbbs(bchanl);
2079                 if (close != False) {
2080                         registerexternalwindow_close(bchanl->registerexternalwindow);
2081                 }
2082                 break;
2083         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_CANCEL_PUSH:
2084                 registerexternalwindow_close(bchanl->registerexternalwindow);
2085                 break;
2086         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW:
2087                 bchanl_externalbbswindow_draw(bchanl);
2088                 break;
2089         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_RESIZE:
2090                 bchanl_externalbbswindow_resize(bchanl, evt->data.externalbbswindow_resize.work_sz);
2091                 break;
2092         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_CLOSE:
2093                 bchanl_externalbbswindow_close(bchanl);
2094                 break;
2095         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_BUTDN:
2096                 bchanl_externalbbswindow_butdn(bchanl, evt->data.externalbbswindow_butdn.type, evt->data.externalbbswindow_butdn.pos);
2097                 break;
2098         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_PASTE:
2099                 bchanl_externalbbswindow_paste(bchanl);
2100                 break;
2101         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL:
2102                 bchanl_externalbbswindow_scroll(bchanl, evt->data.externalbbswindow_scroll.dh, evt->data.externalbbswindow_scroll.dv);
2103                 break;
2104         case BCHANLHMIEVENT_TYPE_NONE:
2105         }
2106 }
2107
2108 LOCAL TC filename_dbg_databox[] = (TC[]){TK_b, TK_c, TK_h, TK_a, TK_n, TK_l, TK_PROD, TK_d, TK_b, TK_x, TNULL};
2109 LOCAL TC filename_dbg_storage[] = (TC[]){TK_c, TK_o, TK_m, TK_m, TK_o, TK_n, TK_s, TK_t, TK_o, TK_r, TK_a, TK_g, TK_e, TK_2, TNULL};
2110 LOCAL TC filename_storage[] = (TC[]){TK_c, TK_o, TK_m, TK_m, TK_o, TK_n, TK_s, TK_t, TK_o, TK_r, TK_a, TK_g, TK_e, TNULL};
2111
2112 LOCAL W main_CLI_args(VID *vid, LINK *storage)
2113 {
2114         W err;
2115         LINK dbx;
2116
2117         *vid = -1;
2118         err = get_lnk(filename_dbg_databox, &dbx, F_NORM);
2119         if (err < 0) {
2120                 DP_ER("get_lnk:test databox error", err);
2121                 return err;
2122         }
2123         err = dopn_dat(&dbx);
2124         if (err < 0) {
2125                 DP_ER("dopn_dat error", err);
2126                 return err;
2127         }
2128         err = get_lnk(filename_dbg_storage, storage, F_NORM);
2129         if (err < 0) {
2130                 DP_ER("get_lnk;commonstorage error", err);
2131                 return err;
2132         }
2133
2134         return 0;
2135 }
2136
2137 LOCAL W main_EXECREC_args(M_EXECREQ *msg, VID *vid, LINK *storage)
2138 {
2139         W err;
2140         LINK lnk;
2141
2142         err = dopn_dat(&msg->self);
2143         if (err < 0) {
2144                 DP_ER("dopn_dat", err);
2145                 return err;
2146         }
2147
2148         lnk = msg->self;
2149         err = get_lnk(filename_storage, &lnk, F_BASED);
2150         if (err < 0) {
2151                 DP_ER("get_lnk;commonstorage error", err);
2152                 return err;
2153         }
2154         *storage = lnk;
2155
2156         *vid = msg->vid;
2157
2158         return 0;
2159 }
2160
2161 typedef struct _arg {
2162         W ac;
2163         TC **argv;
2164 } CLI_arg;
2165
2166 LOCAL    CLI_arg   MESSAGEtoargv(const MESSAGE *src)
2167 {
2168         W len,i,ac;
2169         TC *str;
2170         TC **argv;
2171         CLI_arg ret;
2172
2173         len = src->msg_size / sizeof(TC);
2174         str = (TC*)(src->msg_body.ANYMSG.msg_str);
2175         ac = 0;
2176         for(i=0;i<len;i++){
2177                 if(str[i] == TK_KSP){
2178                         str[i] = TNULL;
2179                         continue;
2180                 }
2181                 ac++;
2182                 for(;i<len;i++){
2183                         if(str[i] == TK_KSP){
2184                                 i--;
2185                                 break;
2186                         }
2187                 }
2188         }
2189
2190         argv = (TC**)malloc(sizeof(TC*)*ac);
2191
2192         ac = 0;
2193         for(i=0;i<len;i++){
2194                 if(str[i] == TNULL){
2195                         str[i] = TNULL;
2196                         continue;
2197                 }
2198                 argv[ac++] = str+i;
2199                 for(;i<len;i++){
2200                         if(str[i] == TNULL){
2201                                 i--;
2202                                 break;
2203                         }
2204                 }
2205         }
2206
2207         ret.ac = ac;
2208         ret.argv = argv;
2209
2210         return ret;
2211 }
2212
2213 EXPORT  W       MAIN(MESSAGE *msg)
2214 {
2215         W err;
2216         VID vid = -1;
2217         LINK storage;
2218         CLI_arg arg;
2219         bchanl_t bchanl;
2220
2221         err = dopn_dat(NULL);
2222         if (err < 0) {
2223                 DP_ER("dopn_dat error:", err);
2224                 ext_prc(0);
2225         }
2226
2227         switch (msg->msg_type) {
2228         case 0: /* CLI */
2229                 arg = MESSAGEtoargv(msg);
2230                 err = main_CLI_args(&vid, &storage);
2231                 if (err < 0) {
2232                         ext_prc(0);
2233                 }
2234                 break;
2235         case DISPREQ:
2236                 oend_req(((M_DISPREQ*)msg)->vid, -1);
2237                 ext_prc(0);
2238                 break;
2239         case PASTEREQ:
2240                 oend_req(((M_PASTEREQ*)msg)->vid, -1);
2241                 ext_prc(0);
2242                 break;
2243         case EXECREQ:
2244                 if ((((M_EXECREQ*)msg)->mode & 2) == 0) {
2245                         ext_prc(0);
2246                 }
2247                 err = main_EXECREC_args((M_EXECREQ*)msg, &vid, &storage);
2248                 if (err < 0) {
2249                         ext_prc(0);
2250                 }
2251                 break;
2252         default:
2253                 ext_prc(0);
2254                 break;
2255         }
2256
2257         err = bchanl_initialize(&bchanl, vid, msg->msg_type, &storage);
2258         if (err < 0) {
2259                 DP_ER("bchanl_initialize error", err);
2260                 ext_prc(0);
2261         }
2262         err = bchanl_prepare_network(&bchanl);
2263         if (err < 0) {
2264                 DP_ER("bchanl_prepare_network error", err);
2265                 bchanl_killme(&bchanl);
2266                 return err;
2267         }
2268
2269         if (msg->msg_type == 0) {
2270                 bchanl_readbbsmenutestdata(&(bchanl.bbsmenu), bchanl.bbsmenuwindow);
2271         } else if (msg->msg_type == EXECREQ) {
2272                 //bchanl_networkrequest_bbsmenu(&bchanl);
2273         }
2274         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
2275
2276         subjectwindow_requestredisp(bchanl.subjectwindow);
2277         bbsmenuwindow_requestredisp(bchanl.bbsmenuwindow);
2278
2279         for (;;) {
2280                 bchanl_eventdispatch(&bchanl);
2281         }
2282
2283         return 0;
2284 }