OSDN Git Service

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