OSDN Git Service

uniting external bbs manager HMI to extbbslist_t.
[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
55 #include    "bchanl_subject.h"
56 #include    "bchanl_hmi.h"
57 #include    "bchanl_menus.h"
58
59 #ifdef BCHANL_CONFIG_DEBUG
60 # define DP(arg) printf arg
61 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
62 #else
63 # define DP(arg) /**/
64 # define DP_ER(msg, err) /**/
65 #endif
66
67 #define BCHANL_DBX_MENU_TEST 20
68 #define BCHANL_DBX_TEXT_MLIST0  21
69 #define BCHANL_DBX_TEXT_MLIST1  22
70 #define BCHANL_DBX_TEXT_MLIST2  23
71 #define BCHANL_DBX_VIEWER_FUSEN 24
72 #define BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU 25
73 #define BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT 26
74 #define BCHANL_DBX_TEXT_MSG_RETRBBSMENU 27
75 #define BCHANL_DBX_TEXT_MSG_RETRSUBJECT 28
76 #define BCHANL_DBX_TEXT_MSG_ERRRETR 29
77 #define BCHANL_DBX_TB_SBJTOPT_FLT 30
78 #define BCHANL_DBX_WS_SBJTOPT_ODR 31
79 #define BCHANL_DBX_WS_SBJTOPT_ODRBY     32
80 #define BCHANL_DBX_TEXT_CATE_EXTBBS 33
81
82 #define BCHANL_MENU_WINDOW 3
83
84 #define BCHANL_COMMONSTORAGE_EXTBBSLIST_RECTYPE 30
85 #define BCHANL_COMMONSTORAGE_EXTBBSLIST_SUBTYPE 1
86
87 typedef struct bchanl_hmistate_t_ bchanl_hmistate_t;
88 struct bchanl_hmistate_t_ {
89         PTRSTL ptr;
90
91         TC *msg_retr_bbsmenu;
92         TC *msg_retr_subject;
93         TC *msg_error_retr;
94 };
95
96 LOCAL VOID bchanl_hmistate_updateptrstyle(bchanl_hmistate_t *hmistate, PTRSTL ptr)
97 {
98         if (hmistate->ptr == ptr) {
99                 return;
100         }
101         hmistate->ptr = ptr;
102         gset_ptr(hmistate->ptr, NULL, -1, -1);
103 }
104
105 LOCAL VOID bchanl_hmistate_initialize(bchanl_hmistate_t *hmistate)
106 {
107         W err;
108
109         hmistate->ptr = PS_SELECT;
110
111         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRBBSMENU, (void**)&hmistate->msg_retr_bbsmenu);
112         if (err < 0) {
113                 DP_ER("dget_dtp: message retrieving error", err);
114                 hmistate->msg_retr_bbsmenu = NULL;
115         }
116         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRSUBJECT, (void**)&hmistate->msg_retr_subject);
117         if (err < 0) {
118                 DP_ER("dget_dtp: message not modified error", err);
119                 hmistate->msg_retr_subject = NULL;
120         }
121         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_ERRRETR, (void**)&hmistate->msg_error_retr);
122         if (err < 0) {
123                 DP_ER("dget_dtp: message retrieve error error", err);
124                 hmistate->msg_error_retr = NULL;
125         }
126 }
127
128 typedef struct bchanl_bbsmenu_t_ bchanl_bbsmenu_t;
129 struct bchanl_bbsmenu_t_ {
130         W gid;
131
132         bbsmnretriever_t *retriever;
133         bbsmncache_t *cache;
134         bbsmnparser_t *parser;
135         bbsmnfilter_t *filter;
136         bbsmnlayout_t *layout;
137         bbsmndraw_t *draw;
138
139         bchanl_subjecthash_t *subjecthash;
140         extbbslist_t *extbbslist;
141         extbbslist_editcontext_t *editctx;
142         TC *category_extbbs;
143 };
144
145 struct bchanl_t_ {
146         W taskid;
147         W mbfid;
148
149         bchanl_mainmenu_t mainmenu;
150         VID vid;
151         W exectype;
152
153         bchanl_hmistate_t hmistate;
154
155         sbjtretriever_t *retriever;
156
157         bchanl_subjecthash_t *subjecthash;
158         bchanl_bbsmenu_t bbsmenu;
159         bchanl_subject_t *currentsubject;
160
161         bchanlhmi_t *hmi;
162         subjectwindow_t *subjectwindow;
163         bbsmenuwindow_t *bbsmenuwindow;
164         subjectoptionwindow_t *subjectoptionwindow;
165         registerexternalwindow_t *registerexternalwindow;
166         externalbbswindow_t *externalbbswindow;
167 };
168 typedef struct bchanl_t_ bchanl_t;
169
170 LOCAL VOID bchanl_killme(bchanl_t *bchanl);
171
172 LOCAL VOID bchanl_subjectwindow_draw(bchanl_t *bchanl)
173 {
174         sbjtdraw_t *draw;
175         RECT r;
176         if (bchanl->currentsubject == NULL) {
177                 do {
178                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
179                                 break;
180                         }
181                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
182                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
183         } else {
184                 draw = bchanl_subject_getdraw(bchanl->currentsubject);
185                 do {
186                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
187                                 break;
188                         }
189                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
190                         sbjtdraw_draw(draw, &r);
191                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
192         }
193 }
194
195 LOCAL VOID bchanl_subjectwindow_scroll(bchanl_t *bchanl, W dh, W dv)
196 {
197         sbjtdraw_t *draw;
198         if (bchanl->currentsubject == NULL) {
199                 return;
200         }
201         draw = bchanl_subject_getdraw(bchanl->currentsubject);
202         sbjtdraw_scrollviewrect(draw, dh, dv);
203         subjectwindow_scrollworkarea(bchanl->subjectwindow, -dh, -dv);
204         bchanl_subjectwindow_draw(bchanl);
205 }
206
207 LOCAL VOID bchanl_subjectwindow_resize(bchanl_t *bchanl, SIZE newsize)
208 {
209         W l,t,r,b;
210         sbjtdraw_t *draw;
211
212         if (bchanl->currentsubject == NULL) {
213                 return;
214         }
215         draw = bchanl_subject_getdraw(bchanl->currentsubject);
216
217         sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
218
219         r = l + newsize.h;
220         b = t + newsize.v;
221
222         sbjtdraw_setviewrect(draw, l, t, r, b);
223         subjectwindow_setworkrect(bchanl->subjectwindow, l, t, r, b);
224
225         bchanl_subjectwindow_draw(bchanl);
226 }
227
228 LOCAL VOID bchanl_subjectwindow_close(bchanl_t *bchanl)
229 {
230         bchanl_killme(bchanl);
231 }
232
233 LOCAL VOID bchanl_subjectwindow_press(bchanl_t *bchanl, PNT evpos)
234 {
235         sbjtlist_tuple_t *tuple;
236         sbjtdraw_t *draw;
237         WID wid_butup;
238         W event_type, size, err, fsn_len, dx, dy;
239         void *fsn;
240         GID gid;
241         PNT pos, p1, pos_butup;
242         TR_VOBJREC vrec;
243         TRAYREC tr_rec;
244         WEVENT paste_ev;
245         SEL_RGN sel;
246         RECT r0, vframe;
247
248         if (bchanl->currentsubject == NULL) {
249                 return;
250         }
251         draw = bchanl_subject_getdraw(bchanl->currentsubject);
252
253         err = sbjtdraw_findthread(draw, evpos, &tuple, &vframe);
254         if (err == 0) {
255                 return;
256         }
257
258         gid = subjectwindow_startdrag(bchanl->subjectwindow);
259         if (gid < 0) {
260                 DP_ER("wsta_drg error:", gid);
261                 return;
262         }
263
264         gget_fra(gid, &r0);
265         gset_vis(gid, r0);
266
267         dx = vframe.c.left - evpos.x;
268         dy = vframe.c.top - evpos.y;
269
270         p1 = evpos;
271         sel.sts = 0;
272         sel.rgn.r.c.left = vframe.c.left;
273         sel.rgn.r.c.top = vframe.c.top;
274         sel.rgn.r.c.right = vframe.c.right;
275         sel.rgn.r.c.bottom = vframe.c.bottom;
276         adsp_sel(gid, &sel, 1);
277
278         gset_ptr(PS_GRIP, NULL, -1, -1);
279         for (;;) {
280                 event_type = subjectwindow_getdrag(bchanl->subjectwindow, &pos, &wid_butup, &pos_butup);
281                 if (event_type == EV_BUTUP) {
282                         break;
283                 }
284                 if (event_type != EV_NULL) {
285                         continue;
286                 }
287                 if ((pos.x == p1.x)&&(pos.y == p1.y)) {
288                         continue;
289                 }
290                 adsp_sel(gid, &sel, 0);
291                 sel.rgn.r.c.left += pos.x - p1.x;
292                 sel.rgn.r.c.top += pos.y - p1.y;
293                 sel.rgn.r.c.right += pos.x - p1.x;
294                 sel.rgn.r.c.bottom += pos.y - p1.y;
295                 adsp_sel(gid, &sel, 1);
296                 p1 = pos;
297         }
298         gset_ptr(PS_SELECT, NULL, -1, -1);
299         adsp_sel(gid, &sel, 0);
300         subjectwindow_enddrag(bchanl->subjectwindow);
301
302         /* BUTUP on self window or no window or system message panel */
303         if ((wid_butup == subjectwindow_getWID(bchanl->subjectwindow))||(wid_butup == 0)||(wid_butup == -1)) {
304                 return;
305         }
306
307         err = oget_vob(-wid_butup, &vrec.vlnk, NULL, 0, &size);
308         if (err < 0) {
309                 return;
310         }
311
312         err = dget_dtp(64, BCHANL_DBX_VIEWER_FUSEN, (void**)&fsn);
313         if (err < 0) {
314                 DP_ER("dget_dtp: ", err);
315                 return;
316         }
317         fsn_len = dget_siz((B*)fsn);
318         err = bchanl_subject_createviewervobj(bchanl->currentsubject, tuple, fsn, fsn_len, &vrec.vseg, (LINK*)&vrec.vlnk);
319         if (err < 0) {
320                 DP_ER("bchanl_subject_createviewervobj error", err);
321                 return;
322         }
323         if (err == BCHANL_SUBJECT_CREATEVIEWERVOBJ_CANCELED) {
324                 DP(("canceled\n"));
325                 return;
326         }
327
328         tr_rec.id = TR_VOBJ;
329         tr_rec.len = sizeof(TR_VOBJREC);
330         tr_rec.dt = (B*)&vrec;
331         err = tset_dat(&tr_rec, 1);
332         if (err < 0) {
333                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
334                 if (err < 0) {
335                         DP_ER("error del_fil:", err);
336                 }
337                 return;
338         }
339
340         paste_ev.r.type = EV_REQUEST;
341         paste_ev.r.r.p.rightbot.x = pos_butup.x + dx;
342         paste_ev.r.r.p.rightbot.y = pos_butup.y + dy;
343         paste_ev.r.cmd = W_PASTE;
344         paste_ev.r.wid = wid_butup;
345         err = wsnd_evt(&paste_ev);
346         if (err < 0) {
347                 tset_dat(NULL, 0);
348                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
349                 if (err < 0) {
350                         DP_ER("error del_fil:", err);
351                 }
352                 return;
353         }
354         err = wwai_rsp(NULL, W_PASTE, 60000);
355         if (err != W_ACK) {
356                 tset_dat(NULL, 0);
357                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
358                 if (err < 0) {
359                         DP_ER("error del_fil:", err);
360                 }
361         }
362
363         wswi_wnd(wid_butup, NULL);
364 }
365
366 LOCAL VOID bchanl_subjectwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
367 {
368         switch (dck) {
369         case    W_CLICK:
370         case    W_DCLICK:
371         case    W_QPRESS:
372         default:
373                 return;
374         case    W_PRESS:
375                 bchanl_subjectwindow_press(bchanl, evpos);
376         }
377 }
378
379 LOCAL VOID bchanl_setcurrentsubject(bchanl_t *bchanl, bchanl_subject_t *sbjt)
380 {
381         bchanl->currentsubject = sbjt;
382         subjectwindow_requestredisp(bchanl->subjectwindow);
383 }
384
385 LOCAL VOID bchanl_bbsmenuwindow_draw(bchanl_t *bchanl)
386 {
387         RECT r;
388         do {
389                 if (bbsmenuwindow_startredisp(bchanl->bbsmenuwindow, &r) == 0) {
390                         break;
391                 }
392                 bbsmenuwindow_eraseworkarea(bchanl->bbsmenuwindow, &r);
393                 bbsmndraw_draw(bchanl->bbsmenu.draw, &r);
394         } while (bbsmenuwindow_endredisp(bchanl->bbsmenuwindow) > 0);
395 }
396
397 LOCAL VOID bchanl_bbsmenuwindow_scroll(bchanl_t *bchanl, W dh, W dv)
398 {
399         bbsmndraw_scrollviewrect(bchanl->bbsmenu.draw, dh, dv);
400         bbsmenuwindow_scrollworkarea(bchanl->bbsmenuwindow, -dh, -dv);
401         bchanl_bbsmenuwindow_draw(bchanl);
402 }
403
404 LOCAL VOID bchanl_bbsmenuwindow_resize(bchanl_t *bchanl, SIZE newsize)
405 {
406         W l,t,r,b;
407
408         bbsmndraw_getviewrect(bchanl->bbsmenu.draw, &l, &t, &r, &b);
409
410         r = l + newsize.h;
411         b = t + newsize.v;
412
413         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, l, t, r, b);
414         bbsmenuwindow_setworkrect(bchanl->bbsmenuwindow, l, t, r, b);
415
416         bchanl_bbsmenuwindow_draw(bchanl);
417 }
418
419 LOCAL VOID bchanl_bbsmenuwindow_close(bchanl_t *bchanl)
420 {
421         bchanl_killme(bchanl);
422 }
423
424 LOCAL VOID bchanl_updatesubjectorder(bchanl_t *bchanl, SUBJECTOPTIONWINDOW_ORDERVALUE_T order, SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby, TC *filterword, W filterword_len)
425 {
426         Bool descending;
427         W sbjt_orderby;
428
429         if (order == SUBJECTOPTIONWINDOW_ORDERVALUE_DESCENDING) {
430                 descending = True;
431         } else {
432                 descending = False;
433         }
434         switch (orderby) {
435         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_NUMBER:
436         default:
437                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_NUMBER;
438                 break;
439         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_RES:
440                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_RES;
441                 break;
442         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_SINCE:
443                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_SINCE;
444                 break;
445         case SUBJECTOPTIONWINDOW_ORDERBYVALUE_VIGOR:
446                 sbjt_orderby = BCHANL_SUBJECT_SORTBY_VIGOR;
447                 break;
448         }
449
450         bchanl_subject_reorder(bchanl->currentsubject, filterword, filterword_len, sbjt_orderby, descending);
451
452         subjectwindow_requestredisp(bchanl->subjectwindow);
453 }
454
455 LOCAL VOID bchanl_changesubjectorder(bchanl_t *bchanl, W neworder)
456 {
457         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby;
458         W len;
459         TC buf[512];
460
461         if (bchanl->currentsubject == NULL) {
462                 return;
463         }
464
465         subjectoptionwindow_getorderbyvalue(bchanl->subjectoptionwindow, &orderby);
466         len = subjectoptionwindow_getfiltertext(bchanl->subjectoptionwindow, buf, 512);
467
468         bchanl_updatesubjectorder(bchanl, neworder, orderby, buf, len);
469 }
470
471 LOCAL VOID bchanl_changesubjectorderby(bchanl_t *bchanl, W neworderby)
472 {
473         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T order;
474         W len;
475         TC buf[512];
476
477         if (bchanl->currentsubject == NULL) {
478                 return;
479         }
480
481         subjectoptionwindow_getordervalue(bchanl->subjectoptionwindow, &order);
482         len = subjectoptionwindow_getfiltertext(bchanl->subjectoptionwindow, buf, 512);
483
484         bchanl_updatesubjectorder(bchanl, order, neworderby, buf, len);
485 }
486
487 LOCAL VOID bchanl_changesubjectfilterword(bchanl_t *bchanl, TC *newstr, W newstr_len)
488 {
489         sbjtlayout_t *layout;
490         sbjtdraw_t *draw;
491         SUBJECTOPTIONWINDOW_ORDERVALUE_T order;
492         SUBJECTOPTIONWINDOW_ORDERBYVALUE_T orderby;
493         RECT w_work;
494         W l, t, r, b;
495
496         if (bchanl->currentsubject == NULL) {
497                 return;
498         }
499
500         subjectoptionwindow_getordervalue(bchanl->subjectoptionwindow, &order);
501         subjectoptionwindow_getorderbyvalue(bchanl->subjectoptionwindow, &orderby);
502
503         bchanl_updatesubjectorder(bchanl, order, orderby, newstr, newstr_len);
504
505         subjectwindow_getworkrect(bchanl->subjectwindow, &w_work);
506         draw = bchanl_subject_getdraw(bchanl->currentsubject);
507         sbjtdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
508         subjectwindow_setworkrect(bchanl->subjectwindow, 0, 0, w_work.c.right, w_work.c.bottom);
509
510         layout = bchanl_subject_getlayout(bchanl->currentsubject);
511         sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
512         subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
513 }
514
515 LOCAL VOID bchanl_sendsubjectrequest(bchanl_t *bchanl, bchanl_subject_t *subject)
516 {
517         sbjtcache_t *cache;
518         sbjtlayout_t *layout;
519         sbjtdraw_t *draw;
520         TC *title;
521         RECT w_work;
522         W l, t, r, b, title_len, err;
523
524         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
525         pdsp_msg(bchanl->hmistate.msg_retr_subject);
526
527         cache = bchanl_subject_getcache(subject);
528         err = sbjtretriever_sendrequest(bchanl->retriever, cache);
529         if (err < 0) {
530                 pdsp_msg(bchanl->hmistate.msg_error_retr);
531                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
532                 return;
533         }
534
535         pdsp_msg(NULL);
536         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
537
538         subjectoptionwindow_setfiltertext(bchanl->subjectoptionwindow, NULL, 0);
539         err = subjectoptionwindow_setordervalue(bchanl->subjectoptionwindow, SUBJECTOPTIONWINDOW_ORDERVALUE_ASCENDING);
540         subjectoptionwindow_setorderbyvalue(bchanl->subjectoptionwindow, SUBJECTOPTIONWINDOW_ORDERBYVALUE_NUMBER);
541
542         bchanl_subject_relayout(subject);
543
544         bchanl_setcurrentsubject(bchanl, subject);
545
546         subjectwindow_getworkrect(bchanl->subjectwindow, &w_work);
547         draw = bchanl_subject_getdraw(subject);
548         sbjtdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
549         subjectwindow_setworkrect(bchanl->subjectwindow, 0, 0, w_work.c.right, w_work.c.bottom);
550
551         layout = bchanl_subject_getlayout(subject);
552         sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
553         subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
554
555         bchanl_subject_gettitle(subject, &title, &title_len);
556         subjectwindow_settitle(bchanl->subjectwindow, title);
557 }
558
559 LOCAL VOID bchanl_bbsmenuwindow_click(bchanl_t *bchanl, PNT pos)
560 {
561         bbsmnparser_item_t *item;
562         bchanl_subject_t *subject;
563         W fnd;
564         UB *host, *board;
565         W host_len, board_len;
566         TC *title;
567         W title_len;
568
569         fnd = bbsmndraw_findboard(bchanl->bbsmenu.draw, pos, &item);
570         if (fnd == 0) {
571                 DP(("not found\n"));
572                 return;
573         }
574         if (item->category != NULL) {
575                 return;
576         }
577         bbsmnparser_item_gethostboard(item, &host, &host_len, &board, &board_len);
578         subject = bchanl_subjecthash_search(bchanl->subjecthash, host, host_len, board, board_len);
579         if (subject == NULL) {
580                 DP(("not found by subject hash"));
581                 return;
582         }
583         bchanl_subject_gettitle(subject, &title, &title_len);
584
585         bchanl_sendsubjectrequest(bchanl, subject);
586 }
587
588 LOCAL VOID bchanl_bbsmenuwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
589 {
590         switch (dck) {
591         case    W_DCLICK:
592         case    W_PRESS:
593         case    W_QPRESS:
594         default:
595                 return;
596         case    W_CLICK:
597                 bchanl_bbsmenuwindow_click(bchanl, evpos);
598         }
599 }
600
601 LOCAL W bchanl_bbsmenu_initialize(bchanl_bbsmenu_t *bchanl, GID gid, bchanl_subjecthash_t *subjecthash, LINK *storage)
602 {
603         bbsmnretriever_t *retriever;
604         bbsmncache_t *cache;
605         bbsmnparser_t *parser;
606         bbsmnfilter_t *filter;
607         bbsmnlayout_t *layout;
608         bbsmndraw_t *draw;
609         extbbslist_t *extbbslist;
610         TC *category_extbbs;
611
612         cache = bbsmncache_new();
613         if (cache == NULL) {
614                 goto error_cache;
615         }
616         retriever = bbsmnretriever_new();
617         if (retriever == NULL) {
618                 goto error_retriever;
619         }
620         parser = bbsmnparser_new(cache);
621         if (parser == NULL) {
622                 goto error_parser;
623         }
624         filter = bbsmnfilter_new();
625         if (filter == NULL) {
626                 goto error_filter;
627         }
628         layout = bbsmnlayout_new(gid);
629         if (layout == NULL) {
630                 goto error_layout;
631         }
632         draw = bbsmndraw_new(layout);
633         if (draw == NULL) {
634                 goto error_draw;
635         }
636         extbbslist = extbbslist_new(storage, BCHANL_COMMONSTORAGE_EXTBBSLIST_RECTYPE, BCHANL_COMMONSTORAGE_EXTBBSLIST_SUBTYPE);
637         if (extbbslist == NULL) {
638                 DP_ER("extbbslist_new", 0);
639                 goto error_extbbslist;
640         }
641         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_CATE_EXTBBS, (void**)&category_extbbs);
642
643         bchanl->gid = gid;
644         bchanl->retriever = retriever;
645         bchanl->cache = cache;
646         bchanl->parser = parser;
647         bchanl->filter = filter;
648         bchanl->layout = layout;
649         bchanl->draw = draw;
650         bchanl->subjecthash = subjecthash;
651         bchanl->extbbslist = extbbslist;
652         bchanl->editctx = NULL;
653         bchanl->category_extbbs = category_extbbs;
654
655         return 0;
656
657 error_extbbslist:
658         bbsmndraw_delete(draw);
659 error_draw:
660         bbsmnlayout_delete(layout);
661 error_layout:
662         bbsmnfilter_delete(filter);
663 error_filter:
664         bbsmnparser_delete(parser);
665 error_parser:
666         bbsmnretriever_delete(retriever);
667 error_retriever:
668         bbsmncache_delete(cache);
669 error_cache:
670         return -1; /* TODO */
671 }
672
673 LOCAL W bchanl_bbsmenu_appenditemtohash(bchanl_bbsmenu_t *bchanl, bbsmnparser_item_t *item)
674 {
675         W err;
676         UB *host, *board;
677         W host_len, board_len;
678
679         bbsmnparser_item_gethostboard(item, &host, &host_len, &board, &board_len);
680         err = bchanl_subjecthash_append(bchanl->subjecthash, host, host_len, board, board_len, item->title, item->title_len);
681         return err;
682 }
683
684 LOCAL VOID bchanl_bbsmenu_registerexternalbbs(bchanl_bbsmenu_t *bchanl, TC *title, W title_len, TC *url, W url_len)
685 {
686         extbbslist_editcontext_append(bchanl->editctx, title, title_len, url, url_len);
687 }
688
689 LOCAL VOID bchanl_bbsmenu_relayoutcache(bchanl_bbsmenu_t *bchanl)
690 {
691         W err, ret;
692         bbsmnparser_t *parser = bchanl->parser;
693         bbsmnparser_item_t *item;
694         bbsmnfilter_t *filter = bchanl->filter;
695         bbsmnlayout_t *layout = bchanl->layout;
696
697         for (;;) {
698                 err = bbsmnparser_getnextitem(parser, &item);
699                 if (err != 1) {
700                         break;
701                 }
702                 bbsmnfilter_inputitem(filter, item);
703                 for (;;) {
704                         ret = bbsmnfilter_outputitem(filter, &item);
705                         if (item != NULL) {
706                                 if (item->category == NULL) {
707                                         err = bchanl_bbsmenu_appenditemtohash(bchanl, item);
708                                         if (err < 0) {
709                                                 return;
710                                         }
711                                 }
712                                 err = bbsmnlayout_appenditem(layout, item);
713                                 if (err < 0) {
714                                         return;
715                                 }
716                         }
717                         if (ret != BBSMNFILTER_OUTPUTITEM_CONTINUE) {
718                                 break;
719                         }
720                 }
721                 if (ret == BBSMNFILTER_OUTPUTITEM_END) {
722                         printf("D\n");
723                         break;
724                 }
725                 if (ret != BBSMNFILTER_OUTPUTITEM_WAITNEXT) {
726                         /* TODO: error */
727                         break;
728                 }
729 /*
730                 if (item == NULL) {
731                         printf("F\n");
732                         break;
733                 }
734 */
735         }
736 }
737
738 LOCAL VOID bchanl_bbsmenu_relayoutexternal(bchanl_bbsmenu_t *bchanl)
739 {
740         W err, ret, category_len, title_len, url_len;
741         Bool cont;
742         TC *category, *title;
743         UB *url;
744         extbbslist_readcontext_t *ctx;
745         bbsmnparser_t *parser = bchanl->parser;
746         bbsmnparser_item_t *item;
747         bbsmnlayout_t *layout = bchanl->layout;
748         extbbslist_t *list = bchanl->extbbslist;
749
750         ret = extbbslist_number(bchanl->extbbslist);
751         if (ret <= 0) {
752                 return;
753         }
754
755         category = bchanl->category_extbbs;
756         category_len = tc_strlen(category);
757         item = bbsmnparser_newcategoryitem(parser, category, category_len);
758         if (item == NULL) {
759                 return;
760         }
761         err = bbsmnlayout_appenditem(layout, item);
762         if (err < 0) {
763                 return;
764         }
765
766         ctx = extbbslist_startread(list);
767         if (ctx == NULL) {
768                 return;
769         }
770         for (;;) {
771                 cont = extbbslist_readcontext_getnext(ctx, &title, &title_len, &url, &url_len);
772                 if (cont == False) {
773                         break;
774                 }
775
776                 item = bbsmnparser_newboarditem(parser, title, title_len, url, url_len);
777                 if (item == NULL) {
778                         break;
779                 }
780                 err = bchanl_bbsmenu_appenditemtohash(bchanl, item);
781                 if (err < 0) {
782                         break;
783                 }
784                 err = bbsmnlayout_appenditem(layout, item);
785                 if (err < 0) {
786                         break;
787                 }
788         }
789         extbbslist_endread(list, ctx);
790 }
791
792 LOCAL VOID bchanl_bbsmenu_relayout(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *window)
793 {
794         W l, t, r, b;
795
796         bbsmnlayout_clear(bchanl->layout);
797         bbsmnfilter_clear(bchanl->filter);
798         bbsmnparser_clear(bchanl->parser);
799
800         bchanl_bbsmenu_relayoutcache(bchanl);
801         bchanl_bbsmenu_relayoutexternal(bchanl);
802
803         bbsmnlayout_getdrawrect(bchanl->layout, &l, &t, &r, &b);
804         bbsmenuwindow_setdrawrect(window, l, t, r, b);
805
806         bbsmenuwindow_requestredisp(window);
807 }
808
809 LOCAL VOID bchanl_registerexternalbbs(bchanl_t *bchanl)
810 {
811         TC title[128];
812         TC url[256];
813         W title_len, url_len;
814
815         title_len = registerexternalwindow_getboradnametext(bchanl->registerexternalwindow, title, 128);
816         if (title_len < 0) {
817                 DP_ER("registerexternalwindow_getboradnametext error", title_len);
818                 return;
819         }
820         title[title_len] = TNULL;
821         url_len = registerexternalwindow_geturltext(bchanl->registerexternalwindow, url, 256);
822         if (url_len < 0) {
823                 DP_ER("registerexternalwindow_geturltext error", url_len);
824                 return;
825         }
826         url[url_len] = TNULL;
827
828         bchanl_bbsmenu_registerexternalbbs(&bchanl->bbsmenu, title, title_len, url, url_len);
829
830         registerexternalwindow_setboradnametext(bchanl->registerexternalwindow, NULL, 0);
831         registerexternalwindow_seturltext(bchanl->registerexternalwindow, NULL, 0);
832
833         externalbbswindow_requestredisp(bchanl->externalbbswindow);
834 }
835
836 LOCAL VOID bchanl_externalbbswindow_draw(bchanl_t *bchanl)
837 {
838         RECT r;
839
840         do {
841                 if (externalbbswindow_startredisp(bchanl->externalbbswindow, &r) == 0) {
842                         break;
843                 }
844                 externalbbswindow_eraseworkarea(bchanl->externalbbswindow, &r);
845                 extbbslist_editcontext_draw(bchanl->bbsmenu.editctx, externalbbswindow_getGID(bchanl->externalbbswindow), &r);
846         } while (externalbbswindow_endredisp(bchanl->externalbbswindow) > 0);
847 }
848
849 LOCAL VOID bchanl_externalbbswindow_resize(bchanl_t *bchanl, SIZE newsize)
850 {
851         W l,t,r,b;
852
853         extbbslist_editcontext_getviewrect(bchanl->bbsmenu.editctx, &l, &t, &r, &b);
854
855         r = l + newsize.h;
856         b = t + newsize.v;
857
858         extbbslist_editcontext_setviewrect(bchanl->bbsmenu.editctx, l, t, r, b);
859         externalbbswindow_setworkrect(bchanl->externalbbswindow, l, t, r, b);
860 }
861
862 LOCAL VOID bchanl_externalbbswindow_close(bchanl_t *bchanl)
863 {
864         extbbslist_endedit(bchanl->bbsmenu.extbbslist, bchanl->bbsmenu.editctx, True);
865         bchanl->bbsmenu.editctx = NULL;
866         externalbbswindow_close(bchanl->externalbbswindow);
867         bchanl_bbsmenu_relayout(&bchanl->bbsmenu, bchanl->bbsmenuwindow);
868 }
869
870 LOCAL VOID bchanl_externalbbswindow_butdn(bchanl_t *bchanl, W type, PNT pos)
871 {
872         Bool found;
873         W sel;
874
875         if (type == W_CLICK) {
876                 found = extbbslist_editcontext_finditem(bchanl->bbsmenu.editctx, pos, &sel);
877                 if (found != False) {
878                         extbbslist_editcontext_setselect(bchanl->bbsmenu.editctx, sel);
879                 }
880                 externalbbswindow_requestredisp(bchanl->externalbbswindow);
881         }
882 }
883
884 LOCAL VOID bchanl_externalbbswindow_paste(bchanl_t *bchanl)
885 {
886         externalbbswindow_responsepasterequest(bchanl->externalbbswindow, /* NACK */ 1, NULL);
887 }
888
889 LOCAL VOID bchanl_externalbbswindow_scroll(bchanl_t *bchanl, W dh, W dv)
890 {
891         extbbslist_editcontext_scrollviewrect(bchanl->bbsmenu.editctx, dh, dv);
892         externalbbswindow_scrollworkarea(bchanl->externalbbswindow, -dh, -dv);
893 }
894
895 #define BCHANL_MESSAGE_RETRIEVER_RELAYOUT 1
896 #define BCHANL_MESSAGE_RETRIEVER_ERROR -1
897
898 LOCAL VOID bchanl_retriever_task(W arg)
899 {
900         bchanl_t *bchanl;
901         bbsmnretriever_t *retr;
902         bbsmncache_t *cache;
903         W msg,err;
904
905         bchanl = (bchanl_t*)arg;
906         retr = bchanl->bbsmenu.retriever;
907         cache = bchanl->bbsmenu.cache;
908
909         for (;;) {
910                 DP(("before rcv_mbf %d\n", bchanl->mbfid));
911                 err = rcv_mbf(bchanl->mbfid, (VP)&msg, T_FOREVER);
912                 DP_ER("rcv_mbf error:",err);
913                 if (err != 4) {
914                         continue;
915                 }
916
917                 err = bbsmnretriever_sendrequest(retr, cache);
918
919                 switch (err) {
920                 case BBSMNRETRIEVER_REQUEST_ALLRELOAD:
921                         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
922                         break;
923                 default:
924                         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_ERROR);
925                         DP_ER("bbsmnretreiver_request error",err);
926                         break;
927                 }
928         }
929
930         ext_tsk();
931 }
932
933 LOCAL W bchanl_prepare_network(bchanl_t *bchanl)
934 {
935         if (bchanl->retriever == NULL) {
936                 return 0;
937         }
938
939         bchanl->mbfid = cre_mbf(sizeof(W), sizeof(W), DELEXIT);
940         if (bchanl->mbfid < 0) {
941                 DP_ER("error cre_mbf:", bchanl->mbfid);
942                 return -1;
943         }
944         bchanl->taskid = cre_tsk(bchanl_retriever_task, -1, (W)bchanl);
945         if (bchanl->taskid < 0) {
946                 del_mbf(bchanl->mbfid);
947                 bchanl->mbfid = -1;
948                 DP_ER("error cre_tsk:", bchanl->taskid);
949                 return -1;
950         }
951
952         return 0;
953 }
954
955 LOCAL W bchanl_networkrequest_bbsmenu(bchanl_t *bchanl)
956 {
957         W msg = 1, err;
958         static UW lastrequest = 0;
959         UW etime;
960
961         if (bchanl->mbfid < 0) {
962                 return 0;
963         }
964
965         err = get_etm(&etime);
966         if (err < 0) {
967                 DP_ER("get_etm error:", err);
968                 return err;
969         }
970         if (lastrequest + 10000 > etime) {
971                 return 0;
972         }
973         lastrequest = etime;
974
975         err = snd_mbf(bchanl->mbfid, &msg, sizeof(W), T_FOREVER);
976         if (err < 0) {
977                 DP_ER("snd_mbf error:", err);
978                 return err;
979         }
980
981         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
982         pdsp_msg(bchanl->hmistate.msg_retr_bbsmenu);
983
984         return 0;
985 }
986
987 LOCAL W bchanl_initialize(bchanl_t *bchanl, VID vid, W exectype, LINK *storage)
988 {
989         static  RECT    r0 = {{400, 100, 700+7, 200+30}};
990         static  RECT    r1 = {{100, 100, 300+7, 300+30}};
991         static  RECT    r2 = {{400, 300, 800+7, 400+30}};
992         TC *title0 = NULL, *title1 = NULL;
993         W err;
994         WID wid;
995         GID gid;
996         RECT w_work;
997         PNT p0 = {450, 0};
998         sbjtretriever_t *retriever;
999         bchanlhmi_t *hmi;
1000         bchanl_subjecthash_t *subjecthash;
1001         subjectwindow_t *subjectwindow;
1002         bbsmenuwindow_t *bbsmenuwindow;
1003         subjectoptionwindow_t *subjectoptionwindow;
1004         registerexternalwindow_t *registerexternalwindow;
1005         externalbbswindow_t *externalbbswindow;
1006
1007         retriever = sbjtretriever_new();
1008         if (retriever == NULL) {
1009                 DP_ER("sbjtretriever_new error", 0);
1010                 goto error_retriever;
1011         }
1012         hmi = bchanlhmi_new();
1013         if (hmi == NULL) {
1014                 DP_ER("bchanlhmi_new error", 0);
1015                 goto error_bchanlhmi;
1016         }
1017         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT, (void**)&title0);
1018         subjectwindow = bchanlhmi_newsubjectwindow(hmi, &r0, 0, title0, NULL);
1019         if (subjectwindow == NULL) {
1020                 DP_ER("bchanlhmi_newsubjectwindow error", 0);
1021                 goto error_subjectwindow;
1022         }
1023         gid = subjectwindow_getGID(subjectwindow);
1024         subjecthash = bchanl_subjecthash_new(gid, 100);
1025         if (subjecthash == NULL) {
1026                 DP_ER("bchanl_subjecthash_new error", 0);
1027                 goto error_subjecthash;
1028         }
1029         subjectoptionwindow = bchanlhmi_newsubjectoptionwindow(hmi, &p0, subjectwindow, NULL, NULL, BCHANL_DBX_TB_SBJTOPT_FLT, BCHANL_DBX_WS_SBJTOPT_ODR, BCHANL_DBX_WS_SBJTOPT_ODRBY);
1030         if (subjectoptionwindow == NULL) {
1031                 DP_ER("bchanlhmi_newsubjectoptionwindow", 0);
1032                 goto error_subjectoptionwindow;
1033         }
1034         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU, (void**)&title1);
1035         bbsmenuwindow = bchanlhmi_newbbsmenuwindow(hmi, &r1, 0, title1, NULL);
1036         if (bbsmenuwindow == NULL) {
1037                 DP_ER("bchanlhmi_newbbsmenuwindow error", 0);
1038                 goto error_bbsmenuwindow;
1039         }
1040         gid = bbsmenuwindow_getGID(bbsmenuwindow);
1041         registerexternalwindow = bchanlhmi_newregisterexternalwindow(hmi, &p0, 0, NULL, NULL);
1042         if (registerexternalwindow == NULL) {
1043                 DP_ER("bchanlhmi_newregisterexternalwindow error", 0);
1044                 goto error_registerexternalwindow;
1045         }
1046         externalbbswindow = bchanlhmi_newexternalbbswindow(hmi, &r2, 0, NULL, NULL);
1047         if (externalbbswindow == NULL) {
1048                 DP_ER("bchanlhmi_newexternalbbswindow", 0);
1049                 goto error_externalbbswindow;
1050         }
1051         err = bchanl_bbsmenu_initialize(&(bchanl->bbsmenu), gid, subjecthash, storage);
1052         if (err < 0) {
1053                 DP_ER("bchanl_bbsmenu_initialize error", err);
1054                 goto error_bbsmenu;
1055         }
1056         err = bchanl_mainmenu_initialize(&(bchanl->mainmenu), BCHANL_DBX_MENU_TEST);
1057         if (err < 0) {
1058                 DP_ER("bchanl_mainmenu_initialize %d", err);
1059                 goto error_mainmenu;
1060         }
1061
1062         bchanl_hmistate_initialize(&bchanl->hmistate);
1063
1064         if (exectype == EXECREQ) {
1065                 wid = bbsmenuwindow_getWID(bbsmenuwindow);
1066                 osta_prc(vid, wid);
1067         }
1068
1069         bbsmenuwindow_getworkrect(bbsmenuwindow, &w_work);
1070         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, 0, 0, w_work.c.right, w_work.c.bottom);
1071         bbsmenuwindow_setworkrect(bbsmenuwindow, 0, 0, w_work.c.right, w_work.c.bottom);
1072
1073         bchanl->retriever = retriever;
1074         bchanl->subjecthash = subjecthash;
1075
1076         bchanl->currentsubject = NULL;
1077
1078         bchanl->vid = vid;
1079         bchanl->exectype = exectype;
1080
1081         bchanl->hmi = hmi;
1082         bchanl->subjectwindow = subjectwindow;
1083         bchanl->bbsmenuwindow = bbsmenuwindow;
1084         bchanl->subjectoptionwindow = subjectoptionwindow;
1085         bchanl->registerexternalwindow = registerexternalwindow;
1086         bchanl->externalbbswindow = externalbbswindow;
1087
1088         return 0;
1089
1090 error_mainmenu:
1091         //bchanl_bbsmenu_finalize(&(bchanl->bbsmenu));
1092 error_bbsmenu:
1093         bchanlhmi_deleteexternalbbswindow(hmi, externalbbswindow);
1094 error_externalbbswindow:
1095         bchanlhmi_deleteregisterexternalwindow(hmi, registerexternalwindow);
1096 error_registerexternalwindow:
1097         bchanlhmi_deletebbsmenuwindow(hmi, bbsmenuwindow);
1098 error_bbsmenuwindow:
1099         bchanlhmi_deletesubjectoptionwindow(hmi, subjectoptionwindow);
1100 error_subjectoptionwindow:
1101         bchanl_subjecthash_delete(subjecthash);
1102 error_subjecthash:
1103         bchanlhmi_deletesubjectwindow(hmi, subjectwindow);
1104 error_subjectwindow:
1105         bchanlhmi_delete(hmi);
1106 error_bchanlhmi:
1107         sbjtretriever_delete(retriever);
1108 error_retriever:
1109         return -1; /* TODO */
1110 }
1111
1112 LOCAL VOID bchanl_killme(bchanl_t *bchanl)
1113 {
1114         gset_ptr(PS_BUSY, NULL, -1, -1);
1115         pdsp_msg(NULL);
1116
1117         if (bchanl->exectype == EXECREQ) {
1118                 oend_prc(bchanl->vid, NULL, 0);
1119         }
1120         bchanl_mainmenu_finalize(&bchanl->mainmenu);
1121         bchanlhmi_deleteexternalbbswindow(bchanl->hmi, bchanl->externalbbswindow);
1122         bchanlhmi_deleteregisterexternalwindow(bchanl->hmi, bchanl->registerexternalwindow);
1123         bchanlhmi_deletebbsmenuwindow(bchanl->hmi, bchanl->bbsmenuwindow);
1124         bchanlhmi_deletesubjectoptionwindow(bchanl->hmi, bchanl->subjectoptionwindow);
1125         bchanl_subjecthash_delete(bchanl->subjecthash);
1126         bchanlhmi_deletesubjectwindow(bchanl->hmi, bchanl->subjectwindow);
1127         bchanlhmi_delete(bchanl->hmi);
1128         sbjtretriever_delete(bchanl->retriever);
1129
1130         ext_prc(0);
1131 }
1132
1133 LOCAL VOID bchanl_readbbsmenutestdata(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *bchanl_window)
1134 {
1135         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};
1136         LINK lnk;
1137         W fd, len, err;
1138         UB *bin;
1139         RECT w_work;
1140         bbsmncache_t *cache = bchanl->cache;
1141         bbsmndraw_t *draw = bchanl->draw;
1142
1143         err = get_lnk(fname, &lnk, F_NORM);
1144         if (err < 0) {
1145                 DP_ER("error get_lnk", err);
1146                 return;
1147         }
1148         fd = opn_fil(&lnk, F_READ, NULL);
1149         if (fd < 0) {
1150                 return;
1151         }
1152         err = rea_rec(fd, 0, NULL, 0, &len, NULL);
1153         if (err < 0) {
1154                 cls_fil(fd);
1155                 return;
1156         }
1157         bin = malloc(len);
1158         if (bin == NULL) {
1159                 cls_fil(fd);
1160                 return;
1161         }
1162         err = rea_rec(fd, 0, bin, len, 0, NULL);
1163         if (err < 0) {
1164                 free(bin);
1165                 cls_fil(fd);
1166                 return;
1167         }
1168         cls_fil(fd);
1169
1170         bbsmncache_appenddata(cache, bin, len);
1171         free(bin);
1172
1173         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
1174
1175         bbsmenuwindow_getworkrect(bchanl_window, &w_work);
1176         bbsmndraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
1177         bbsmenuwindow_setworkrect(bchanl_window, 0, 0, w_work.c.right, w_work.c.bottom);
1178 }
1179
1180 LOCAL VOID bchanl_subjectwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
1181 {
1182         W l,t,r,b,l1,t1,r1,b1,scr;
1183         sbjtlayout_t *layout;
1184         sbjtdraw_t *draw;
1185
1186         if (bchanl->currentsubject == NULL) {
1187                 return;
1188         }
1189         draw = bchanl_subject_getdraw(bchanl->currentsubject);
1190
1191         switch (ch) {
1192         case KC_CC_U:
1193                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1194                 if (t < 16) {
1195                         scr = -t;
1196                 } else {
1197                         scr = -16;
1198                 }
1199                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1200                 bchanl_subjectwindow_scroll(bchanl, 0, scr);
1201                 break;
1202         case KC_CC_D:
1203                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1204                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1205                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1206                 if (b + 16 > b1) {
1207                         scr = b1 - b;
1208                 } else {
1209                         scr = 16;
1210                 }
1211                 if (scr > 0) {
1212                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1213                         bchanl_subjectwindow_scroll(bchanl, 0, scr);
1214                 }
1215                 break;
1216         case KC_CC_R:
1217                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1218                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1219                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1220                 if (r + 16 > r1) {
1221                         scr = r1 - r;
1222                 } else {
1223                         scr = 16;
1224                 }
1225                 if (scr > 0) {
1226                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1227                         bchanl_subjectwindow_scroll(bchanl, scr, 0);
1228                 }
1229                 break;
1230         case KC_CC_L:
1231                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1232                 if (l < 16) {
1233                         scr = -l;
1234                 } else {
1235                         scr = -16;
1236                 }
1237                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1238                 bchanl_subjectwindow_scroll(bchanl, scr, 0);
1239                 break;
1240         case KC_PG_U:
1241                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1242                 if (t < (b - t)) {
1243                         scr = -t;
1244                 } else {
1245                         scr = - (b - t);
1246                 }
1247                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1248                 bchanl_subjectwindow_scroll(bchanl, 0, scr);
1249                 break;
1250         case KC_PG_D:
1251                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1252                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1253                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1254                 if (b + (b - t) > b1) {
1255                         scr = b1 - b;
1256                 } else {
1257                         scr = (b - t);
1258                 }
1259                 if (scr > 0) {
1260                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
1261                         bchanl_subjectwindow_scroll(bchanl, 0, scr);
1262                 }
1263                 break;
1264         case KC_PG_R:
1265                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1266                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
1267                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1268                 if (r + (r - l) > r1) {
1269                         scr = r1 - r;
1270                 } else {
1271                         scr = (r - l);
1272                 }
1273                 if (scr > 0) {
1274                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1275                         bchanl_subjectwindow_scroll(bchanl, scr, 0);
1276                 }
1277                 break;
1278         case KC_PG_L:
1279                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
1280                 if (l < (r - l)) {
1281                         scr = -l;
1282                 } else {
1283                         scr = - (r - l);
1284                 }
1285                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
1286                 bchanl_subjectwindow_scroll(bchanl, scr, 0);
1287                 break;
1288         case TK_E: /* temporary */
1289                 if (stat & ES_CMD) {
1290                         bchanl_killme(bchanl);
1291                 }
1292                 break;
1293         }
1294 }
1295
1296 LOCAL VOID bchanl_bbsmenuwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
1297 {
1298         W l,t,r,b,l1,t1,r1,b1,scr;
1299         bbsmndraw_t *draw = bchanl->bbsmenu.draw;
1300         bbsmnlayout_t *layout = bchanl->bbsmenu.layout;
1301
1302         switch (ch) {
1303         case KC_CC_U:
1304                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1305                 if (t < 16) {
1306                         scr = -t;
1307                 } else {
1308                         scr = -16;
1309                 }
1310                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1311                 bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1312                 break;
1313         case KC_CC_D:
1314                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1315                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1316                 if (b + 16 > b1) {
1317                         scr = b1 - b;
1318                 } else {
1319                         scr = 16;
1320                 }
1321                 if (scr > 0) {
1322                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1323                         bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1324                 }
1325                 break;
1326         case KC_CC_R:
1327         case KC_CC_L:
1328                 break;
1329         case KC_PG_U:
1330                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1331                 if (t < (b - t)) {
1332                         scr = -t;
1333                 } else {
1334                         scr = - (b - t);
1335                 }
1336                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1337                 bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1338                 break;
1339         case KC_PG_D:
1340                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1341                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1342                 if (b + (b - t) > b1) {
1343                         scr = b1 - b;
1344                 } else {
1345                         scr = (b - t);
1346                 }
1347                 if (scr > 0) {
1348                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1349                         bchanl_bbsmenuwindow_scroll(bchanl, 0, scr);
1350                 }
1351                 break;
1352         case KC_PG_R:
1353         case KC_PG_L:
1354                 break;
1355         case KC_PF5:
1356                 bchanl_networkrequest_bbsmenu(bchanl);
1357                 break;
1358         case TK_E: /* temporary */
1359                 if (stat & ES_CMD) {
1360                         bchanl_killme(bchanl);
1361                 }
1362                 break;
1363         }
1364 }
1365
1366
1367 LOCAL VOID bchanl_keydwn(bchanl_t *bchanl, UH keytop, TC ch, UW stat)
1368 {
1369         Bool act;
1370
1371         act = subjectwindow_isactive(bchanl->subjectwindow);
1372         if (act == True) {
1373                 bchanl_subjectwindow_keydwn(bchanl, keytop, ch, stat);
1374                 return;
1375         }
1376         act = bbsmenuwindow_isactive(bchanl->bbsmenuwindow);
1377         if (act == True) {
1378                 bchanl_bbsmenuwindow_keydwn(bchanl, keytop, ch, stat);
1379                 return;
1380         }
1381 }
1382
1383 LOCAL VOID bchanl_setupmenu(bchanl_t *bchanl)
1384 {
1385         Bool isopen, isopen_extbbs, selected = False;
1386         W index;
1387
1388         isopen = subjectoptionwindow_isopen(bchanl->subjectoptionwindow);
1389         isopen_extbbs = externalbbswindow_isopen(bchanl->externalbbswindow);
1390         if (isopen_extbbs != False) {
1391                 index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1392                 if (index >= 0) {
1393                         selected = True;
1394                 }
1395         }
1396
1397         bchanl_mainmenu_setup(&bchanl->mainmenu, isopen, isopen_extbbs, selected);
1398 }
1399
1400 LOCAL VOID bchanl_selectmenu(bchanl_t *bchanl, W sel)
1401 {
1402         Bool isopen;
1403         RECT work;
1404         W index;
1405
1406         switch(sel) {
1407         case BCHANL_MAINMENU_SELECT_CLOSE: /* [½ªÎ»] */
1408                 bchanl_killme(bchanl);
1409                 break;
1410         case BCHANL_MAINMENU_SELECT_REDISPLAY: /* [ºÆɽ¼¨] */
1411                 subjectwindow_requestredisp(bchanl->subjectwindow);
1412                 bbsmenuwindow_requestredisp(bchanl->bbsmenuwindow);
1413                 break;
1414         case BCHANL_MAINMENU_SELECT_BBSMENUFETCH: /* [ÈÄ°ìÍ÷ºÆ¼èÆÀ] */
1415                 bchanl_networkrequest_bbsmenu(bchanl);
1416                 break;
1417         case BCHANL_MAINMENU_SELECT_SUBJECTOPTION: /* [¥¹¥ì°ìÍ÷ÀßÄê] */
1418                 isopen = subjectoptionwindow_isopen(bchanl->subjectoptionwindow);
1419                 if (isopen == False) {
1420                         subjectoptionwindow_open(bchanl->subjectoptionwindow);
1421                 } else {
1422                         subjectoptionwindow_close(bchanl->subjectoptionwindow);
1423                 }
1424                 break;
1425         case BCHANL_MAINMENU_SELECT_EXTBBS_MANAGER: /* [³°ÉôÈĤÎÄɲÃ] */
1426                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1427                 if (isopen == False) {
1428
1429                         bchanl->bbsmenu.editctx = extbbslist_startedit(bchanl->bbsmenu.extbbslist);
1430                         if (bchanl->bbsmenu.editctx == NULL) {
1431                                 break;
1432                         }
1433                         externalbbswindow_open(bchanl->externalbbswindow);
1434                         externalbbswindow_getworkrect(bchanl->externalbbswindow, &work);
1435                         extbbslist_editcontext_setviewrect(bchanl->bbsmenu.editctx, 0, 0, work.c.right - work.c.left, work.c.bottom - work.c.top);
1436                         externalbbswindow_setworkrect(bchanl->externalbbswindow, 0, 0, work.c.right - work.c.left, work.c.bottom - work.c.top);
1437                 }
1438                 break;
1439         case BCHANL_MAINMENU_SELECT_EXTBBS_REGISTER:
1440                 isopen = registerexternalwindow_isopen(bchanl->registerexternalwindow);
1441                 if (isopen == False) {
1442                         registerexternalwindow_open(bchanl->registerexternalwindow);
1443                 }
1444                 break;
1445         case BCHANL_MAINMENU_SELECT_EXTBBS_UP:
1446                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1447                 if (isopen != False) {
1448                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1449                         if (index < 0) {
1450                                 break;
1451                         }
1452                         extbbslist_editcontext_swapitem(bchanl->bbsmenu.editctx, index-1, index);
1453                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1454                 }
1455                 break;
1456         case BCHANL_MAINMENU_SELECT_EXTBBS_DOWN:
1457                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1458                 if (isopen != False) {
1459                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1460                         if (index < 0) {
1461                                 break;
1462                         }
1463                         extbbslist_editcontext_swapitem(bchanl->bbsmenu.editctx, index, index+1);
1464                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1465                 }
1466                 break;
1467         case BCHANL_MAINMENU_SELECT_EXTBBS_DELETE:
1468                 isopen = externalbbswindow_isopen(bchanl->externalbbswindow);
1469                 if (isopen != False) {
1470                         index = extbbslist_editcontext_getselect(bchanl->bbsmenu.editctx);
1471                         if (index < 0) {
1472                                 break;
1473                         }
1474                         extbbslist_editcontext_deleteitem(bchanl->bbsmenu.editctx, index);
1475                         externalbbswindow_requestredisp(bchanl->externalbbswindow);
1476                 }
1477                 break;
1478         }
1479         return;
1480 }
1481
1482 LOCAL VOID bchanl_popupmenu(bchanl_t *bchanl, PNT pos)
1483 {
1484         W sel;
1485         bchanl_setupmenu(bchanl);
1486         gset_ptr(PS_SELECT, NULL, -1, -1);
1487         sel = bchanl_mainmenu_popup(&bchanl->mainmenu, pos);
1488         if (sel > 0) {
1489                 bchanl_selectmenu(bchanl, sel);
1490         }
1491 }
1492
1493 LOCAL W bchanl_keyselect(bchanl_t *bchanl, TC keycode)
1494 {
1495         W sel;
1496         bchanl_setupmenu(bchanl);
1497         sel = bchanl_mainmenu_keyselect(&bchanl->mainmenu, keycode);
1498         if (sel > 0) {
1499                 bchanl_selectmenu(bchanl, sel);
1500         }
1501         return 0;
1502 }
1503
1504 LOCAL VOID bchanl_handletimeout(bchanl_t *bchanl, W code)
1505 {
1506         switch (code) {
1507         case BCHANL_MESSAGE_RETRIEVER_RELAYOUT:
1508                 bchanl_bbsmenu_relayout(&bchanl->bbsmenu, bchanl->bbsmenuwindow);
1509                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1510                 pdsp_msg(NULL);
1511                 break;
1512         case BCHANL_MESSAGE_RETRIEVER_ERROR:
1513                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1514                 pdsp_msg(NULL);
1515                 break;
1516         }
1517 }
1518
1519 LOCAL VOID bchanl_eventdispatch(bchanl_t *bchanl)
1520 {
1521         bchanlhmievent_t *evt;
1522         W sel, err;
1523
1524         err = bchanlhmi_getevent(bchanl->hmi, &evt);
1525         if (err < 0) {
1526                 return;
1527         }
1528
1529         switch (evt->type) {
1530         case BCHANLHMIEVENT_TYPE_COMMON_MOUSEMOVE:
1531                 break;
1532         case BCHANLHMIEVENT_TYPE_COMMON_KEYDOWN:
1533                 if (evt->data.common_keydown.stat & ES_CMD) {   /*Ì¿Îᥭ¡¼*/
1534                         bchanl_setupmenu(bchanl);
1535                         sel = bchanl_keyselect(bchanl, evt->data.common_keydown.keycode);
1536                         if (sel > 0) {
1537                                 bchanl_selectmenu(bchanl, sel);
1538                                 break;
1539                         }
1540                 }
1541                 bchanl_keydwn(bchanl, evt->data.common_keydown.keytop, evt->data.common_keydown.keycode, evt->data.common_keydown.stat);
1542                 break;
1543         case BCHANLHMIEVENT_TYPE_COMMON_MENU:
1544                 bchanl_popupmenu(bchanl, evt->data.common_menu.pos);
1545                 break;
1546         case BCHANLHMIEVENT_TYPE_COMMON_TIMEOUT:
1547                 bchanl_handletimeout(bchanl, evt->data.common_timeout.code);
1548                 break;
1549         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_DRAW:
1550                 bchanl_subjectwindow_draw(bchanl);
1551                 break;
1552         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_RESIZE:
1553                 bchanl_subjectwindow_resize(bchanl, evt->data.subjectwindow_resize.work_sz);
1554                 break;
1555         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_CLOSE:
1556                 bchanl_subjectwindow_close(bchanl);
1557                 break;
1558         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_BUTDN:
1559                 bchanl_subjectwindow_butdn(bchanl, evt->data.subjectwindow_butdn.type, evt->data.subjectwindow_butdn.pos);
1560                 break;
1561         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_PASTE:
1562                 subjectwindow_responsepasterequest(bchanl->subjectwindow, /* NACK */ 1, NULL);
1563                 break;
1564         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_MOUSEMOVE:
1565                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
1566                 break;
1567         case BCHANLHMIEVENT_TYPE_SUBJECTWINDOW_SCROLL:
1568                 bchanl_subjectwindow_scroll(bchanl, evt->data.subjectwindow_scroll.dh, evt->data.subjectwindow_scroll.dv);
1569                 break;
1570         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_DRAW:
1571                 bchanl_bbsmenuwindow_draw(bchanl);
1572                 break;
1573         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_RESIZE:
1574                 bchanl_bbsmenuwindow_resize(bchanl, evt->data.bbsmenuwindow_resize.work_sz);
1575                 break;
1576         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_CLOSE:
1577                 bchanl_bbsmenuwindow_close(bchanl);
1578                 break;
1579         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_BUTDN:
1580                 bchanl_bbsmenuwindow_butdn(bchanl, evt->data.bbsmenuwindow_butdn.type, evt->data.bbsmenuwindow_butdn.pos);
1581                 break;
1582         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_MOUSEMOVE:
1583                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
1584                 break;
1585         case BCHANLHMIEVENT_TYPE_BBSMENUWINDOW_SCROLL:
1586                 bchanl_bbsmenuwindow_scroll(bchanl, evt->data.bbsmenuwindow_scroll.dh, evt->data.bbsmenuwindow_scroll.dv);
1587                 break;
1588         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_DETERMINE:
1589                 bchanl_changesubjectfilterword(bchanl, evt->data.subjectoptionwindow_filter_determine.value, evt->data.subjectoptionwindow_filter_determine.len);
1590                 break;
1591         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_COPY:
1592                 break;
1593         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MOVE:
1594                 break;
1595         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_MENU:
1596                 break;
1597         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_FILTER_KEYMENU:
1598                 break;
1599         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDER_CHANGE:
1600                 bchanl_changesubjectorder(bchanl, evt->data.subjectoptionwindow_order_change.value);
1601                 break;
1602         case BCHANLHMIEVENT_TYPE_SUBJECTOPTIONWINDOW_PARTS_ORDERBY_CHANGE:
1603                 bchanl_changesubjectorderby(bchanl, evt->data.subjectoptionwindow_order_change.value);
1604                 break;
1605         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_DETERMINE:
1606                 break;
1607         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_COPY:
1608                 break;
1609         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MOVE:
1610                 break;
1611         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_MENU:
1612                 break;
1613         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_BORADNAME_KEYMENU:
1614                 break;
1615         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_DETERMINE:
1616                 break;
1617         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_COPY:
1618                 break;
1619         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MOVE:
1620                 break;
1621         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_MENU:
1622                 break;
1623         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_URL_KEYMENU:
1624                 break;
1625         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_DETERMINE_PUSH:
1626                 bchanl_registerexternalbbs(bchanl);
1627                 registerexternalwindow_close(bchanl->registerexternalwindow);
1628                 break;
1629         case BCHANLHMIEVENT_TYPE_REGISTEREXTERNALWINDOW_PARTS_CANCEL_PUSH:
1630                 registerexternalwindow_close(bchanl->registerexternalwindow);
1631                 break;
1632         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_DRAW:
1633                 bchanl_externalbbswindow_draw(bchanl);
1634                 break;
1635         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_RESIZE:
1636                 break;
1637                 bchanl_externalbbswindow_resize(bchanl, evt->data.externalbbswindow_resize.work_sz);
1638         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_CLOSE:
1639                 bchanl_externalbbswindow_close(bchanl);
1640                 break;
1641         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_BUTDN:
1642                 bchanl_externalbbswindow_butdn(bchanl, evt->data.externalbbswindow_butdn.type, evt->data.externalbbswindow_butdn.pos);
1643                 break;
1644         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_PASTE:
1645                 bchanl_externalbbswindow_paste(bchanl);
1646                 break;
1647         case BCHANLHMIEVENT_TYPE_EXTERNALBBSWINDOW_SCROLL:
1648                 bchanl_externalbbswindow_scroll(bchanl, evt->data.externalbbswindow_scroll.dh, evt->data.externalbbswindow_scroll.dv);
1649                 break;
1650         case BCHANLHMIEVENT_TYPE_NONE:
1651         }
1652 }
1653
1654 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};
1655 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};
1656 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};
1657
1658 LOCAL W main_CLI_args(VID *vid, LINK *storage)
1659 {
1660         W err;
1661         LINK dbx;
1662
1663         *vid = -1;
1664         err = get_lnk(filename_dbg_databox, &dbx, F_NORM);
1665         if (err < 0) {
1666                 DP_ER("get_lnk:test databox error", err);
1667                 return err;
1668         }
1669         err = dopn_dat(&dbx);
1670         if (err < 0) {
1671                 DP_ER("dopn_dat error", err);
1672                 return err;
1673         }
1674         err = get_lnk(filename_dbg_storage, storage, F_NORM);
1675         if (err < 0) {
1676                 DP_ER("get_lnk;commonstorage error", err);
1677                 return err;
1678         }
1679
1680         return 0;
1681 }
1682
1683 LOCAL W main_EXECREC_args(M_EXECREQ *msg, VID *vid, LINK *storage)
1684 {
1685         W err;
1686         LINK lnk;
1687
1688         err = dopn_dat(&msg->self);
1689         if (err < 0) {
1690                 DP_ER("dopn_dat", err);
1691                 return err;
1692         }
1693
1694         lnk = msg->self;
1695         err = get_lnk(filename_storage, &lnk, F_BASED);
1696         if (err < 0) {
1697                 DP_ER("get_lnk;commonstorage error", err);
1698                 return err;
1699         }
1700         *storage = lnk;
1701
1702         *vid = msg->vid;
1703
1704         return 0;
1705 }
1706
1707 typedef struct _arg {
1708         W ac;
1709         TC **argv;
1710 } CLI_arg;
1711
1712 LOCAL    CLI_arg   MESSAGEtoargv(const MESSAGE *src)
1713 {
1714         W len,i,ac;
1715         TC *str;
1716         TC **argv;
1717         CLI_arg ret;
1718
1719         len = src->msg_size / sizeof(TC);
1720         str = (TC*)(src->msg_body.ANYMSG.msg_str);
1721         ac = 0;
1722         for(i=0;i<len;i++){
1723                 if(str[i] == TK_KSP){
1724                         str[i] = TNULL;
1725                         continue;
1726                 }
1727                 ac++;
1728                 for(;i<len;i++){
1729                         if(str[i] == TK_KSP){
1730                                 i--;
1731                                 break;
1732                         }
1733                 }
1734         }
1735
1736         argv = (TC**)malloc(sizeof(TC*)*ac);
1737
1738         ac = 0;
1739         for(i=0;i<len;i++){
1740                 if(str[i] == TNULL){
1741                         str[i] = TNULL;
1742                         continue;
1743                 }
1744                 argv[ac++] = str+i;
1745                 for(;i<len;i++){
1746                         if(str[i] == TNULL){
1747                                 i--;
1748                                 break;
1749                         }
1750                 }
1751         }
1752
1753         ret.ac = ac;
1754         ret.argv = argv;
1755
1756         return ret;
1757 }
1758
1759 EXPORT  W       MAIN(MESSAGE *msg)
1760 {
1761         W err;
1762         VID vid = -1;
1763         LINK storage;
1764         CLI_arg arg;
1765         bchanl_t bchanl;
1766
1767         err = dopn_dat(NULL);
1768         if (err < 0) {
1769                 DP_ER("dopn_dat error:", err);
1770                 ext_prc(0);
1771         }
1772
1773         switch (msg->msg_type) {
1774         case 0: /* CLI */
1775                 arg = MESSAGEtoargv(msg);
1776                 err = main_CLI_args(&vid, &storage);
1777                 if (err < 0) {
1778                         ext_prc(0);
1779                 }
1780                 break;
1781         case DISPREQ:
1782                 oend_req(((M_DISPREQ*)msg)->vid, -1);
1783                 ext_prc(0);
1784                 break;
1785         case PASTEREQ:
1786                 oend_req(((M_PASTEREQ*)msg)->vid, -1);
1787                 ext_prc(0);
1788                 break;
1789         case EXECREQ:
1790                 if ((((M_EXECREQ*)msg)->mode & 2) == 0) {
1791                         ext_prc(0);
1792                 }
1793                 err = main_EXECREC_args((M_EXECREQ*)msg, &vid, &storage);
1794                 if (err < 0) {
1795                         ext_prc(0);
1796                 }
1797                 break;
1798         default:
1799                 ext_prc(0);
1800                 break;
1801         }
1802
1803         err = bchanl_initialize(&bchanl, vid, msg->msg_type, &storage);
1804         if (err < 0) {
1805                 DP_ER("bchanl_initialize error", err);
1806                 ext_prc(0);
1807         }
1808         err = bchanl_prepare_network(&bchanl);
1809         if (err < 0) {
1810                 DP_ER("bchanl_prepare_network error", err);
1811                 bchanl_killme(&bchanl);
1812                 return err;
1813         }
1814
1815         if (msg->msg_type == 0) {
1816                 bchanl_readbbsmenutestdata(&(bchanl.bbsmenu), bchanl.bbsmenuwindow);
1817         } else if (msg->msg_type == EXECREQ) {
1818                 bchanl_networkrequest_bbsmenu(&bchanl);
1819         }
1820
1821         subjectwindow_requestredisp(bchanl.subjectwindow);
1822         bbsmenuwindow_requestredisp(bchanl.bbsmenuwindow);
1823
1824         for (;;) {
1825                 bchanl_eventdispatch(&bchanl);
1826         }
1827
1828         return 0;
1829 }