OSDN Git Service

remove unused function.
[bbk/bchanl.git] / src / main.c
1 /*
2  * main.c
3  *
4  * Copyright (c) 2009-2011 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        "subjectlayout.h"
47 #include    "bbsmenuretriever.h"
48 #include    "bbsmenucache.h"
49 #include    "bbsmenuparser.h"
50 #include        "bbsmenufilter.h"
51 #include    "bbsmenulayout.h"
52
53 #include    "bchanl_subject.h"
54 #include    "bchanl_hmi.h"
55 #include    "bchanl_menus.h"
56
57 #ifdef BCHANL_CONFIG_DEBUG
58 # define DP(arg) printf arg
59 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
60 #else
61 # define DP(arg) /**/
62 # define DP_ER(msg, err) /**/
63 #endif
64
65 #define BCHANL_DBX_MENU_TEST 20
66 #define BCHANL_DBX_TEXT_MLIST0  21
67 #define BCHANL_DBX_TEXT_MLIST1  22
68 #define BCHANL_DBX_TEXT_MLIST2  23
69 #define BCHANL_DBX_VIEWER_FUSEN 24
70 #define BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU 25
71 #define BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT 26
72 #define BCHANL_DBX_TEXT_MSG_RETRBBSMENU 27
73 #define BCHANL_DBX_TEXT_MSG_RETRSUBJECT 28
74 #define BCHANL_DBX_TEXT_MSG_ERRRETR 29
75
76 #define BCHANL_MENU_WINDOW 3
77
78 typedef struct bchanl_hmistate_t_ bchanl_hmistate_t;
79 struct bchanl_hmistate_t_ {
80         PTRSTL ptr;
81
82         TC *msg_retr_bbsmenu;
83         TC *msg_retr_subject;
84         TC *msg_error_retr;
85 };
86
87 LOCAL VOID bchanl_hmistate_updateptrstyle(bchanl_hmistate_t *hmistate, PTRSTL ptr)
88 {
89         if (hmistate->ptr == ptr) {
90                 return;
91         }
92         hmistate->ptr = ptr;
93         gset_ptr(hmistate->ptr, NULL, -1, -1);
94 }
95
96 LOCAL VOID bchanl_hmistate_initialize(bchanl_hmistate_t *hmistate)
97 {
98         W err;
99
100         hmistate->ptr = PS_SELECT;
101
102         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRBBSMENU, (void**)&hmistate->msg_retr_bbsmenu);
103         if (err < 0) {
104                 DP_ER("dget_dtp: message retrieving error", err);
105                 hmistate->msg_retr_bbsmenu = NULL;
106         }
107         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_RETRSUBJECT, (void**)&hmistate->msg_retr_subject);
108         if (err < 0) {
109                 DP_ER("dget_dtp: message not modified error", err);
110                 hmistate->msg_retr_subject = NULL;
111         }
112         err = dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_MSG_ERRRETR, (void**)&hmistate->msg_error_retr);
113         if (err < 0) {
114                 DP_ER("dget_dtp: message retrieve error error", err);
115                 hmistate->msg_error_retr = NULL;
116         }
117 }
118
119 typedef struct bchanl_bbsmenu_t_ bchanl_bbsmenu_t;
120 struct bchanl_bbsmenu_t_ {
121         W gid;
122
123         bbsmnretriever_t *retriever;
124         bbsmncache_t *cache;
125         bbsmnparser_t *parser;
126         bbsmnfilter_t *filter;
127         bbsmnlayout_t *layout;
128         bbsmndraw_t *draw;
129
130         bchanl_subjecthash_t *subjecthash;
131 };
132
133 struct bchanl_t_ {
134         W taskid;
135         W mbfid;
136
137         bchanl_mainmenu_t mainmenu;
138         VID vid;
139         W exectype;
140
141         bchanl_hmistate_t hmistate;
142
143         sbjtretriever_t *retriever;
144
145         bchanl_subjecthash_t *subjecthash;
146         bchanl_bbsmenu_t bbsmenu;
147         bchanl_subject_t *currentsubject;
148
149         bchanlhmi_t *hmi;
150         subjectwindow_t *subjectwindow;
151         bbsmenuwindow_t *bbsmenuwindow;
152 };
153 typedef struct bchanl_t_ bchanl_t;
154
155 LOCAL VOID bchanl_killme(bchanl_t *bchanl);
156
157 LOCAL VOID bchanl_subjectwindow_draw(bchanl_t *bchanl)
158 {
159         sbjtdraw_t *draw;
160         RECT r;
161         if (bchanl->currentsubject == NULL) {
162                 do {
163                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
164                                 break;
165                         }
166                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
167                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
168         } else {
169                 draw = bchanl_subject_getdraw(bchanl->currentsubject);
170                 do {
171                         if (subjectwindow_startredisp(bchanl->subjectwindow, &r) == 0) {
172                                 break;
173                         }
174                         subjectwindow_eraseworkarea(bchanl->subjectwindow, &r);
175                         sbjtdraw_draw(draw, &r);
176                 } while (subjectwindow_endredisp(bchanl->subjectwindow) > 0);
177         }
178 }
179
180 LOCAL VOID bchanl_subjectwindow_scroll(VP arg, W dh, W dv)
181 {
182         bchanl_t *bchanl = (bchanl_t*)arg;
183         sbjtdraw_t *draw;
184         if (bchanl->currentsubject == NULL) {
185                 return;
186         }
187         draw = bchanl_subject_getdraw(bchanl->currentsubject);
188         sbjtdraw_scrollviewrect(draw, dh, dv);
189         subjectwindow_scrollworkarea(bchanl->subjectwindow, -dh, -dv);
190         bchanl_subjectwindow_draw(bchanl);
191 }
192
193 LOCAL VOID bchanl_subjectwindow_resize(bchanl_t *bchanl, SIZE newsize)
194 {
195         W l,t,r,b;
196         sbjtdraw_t *draw;
197
198         if (bchanl->currentsubject == NULL) {
199                 return;
200         }
201         draw = bchanl_subject_getdraw(bchanl->currentsubject);
202
203         sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
204
205         r = l + newsize.h;
206         b = t + newsize.v;
207
208         sbjtdraw_setviewrect(draw, l, t, r, b);
209         subjectwindow_setworkrect(bchanl->subjectwindow, l, t, r, b);
210
211         bchanl_subjectwindow_draw(bchanl);
212 }
213
214 LOCAL VOID bchanl_subjectwindow_close(bchanl_t *bchanl)
215 {
216         bchanl_killme(bchanl);
217 }
218
219 LOCAL VOID bchanl_subjectwindow_press(bchanl_t *bchanl, PNT evpos)
220 {
221         sbjtparser_thread_t *thread;
222         sbjtdraw_t *draw;
223         WID wid_butup;
224         W event_type, size, err, fsn_len, dx, dy;
225         void *fsn;
226         GID gid;
227         PNT pos, p1, pos_butup;
228         TR_VOBJREC vrec;
229         TRAYREC tr_rec;
230         WEVENT paste_ev;
231         SEL_RGN sel;
232         RECT r0, vframe;
233
234         if (bchanl->currentsubject == NULL) {
235                 return;
236         }
237         draw = bchanl_subject_getdraw(bchanl->currentsubject);
238
239         err = sbjtdraw_findthread(draw, evpos, &thread, &vframe);
240         if (err == 0) {
241                 return;
242         }
243
244         gid = subjectwindow_startdrag(bchanl->subjectwindow);
245         if (gid < 0) {
246                 DP_ER("wsta_drg error:", gid);
247                 return;
248         }
249
250         gget_fra(gid, &r0);
251         gset_vis(gid, r0);
252
253         dx = vframe.c.left - evpos.x;
254         dy = vframe.c.top - evpos.y;
255
256         p1 = evpos;
257         sel.sts = 0;
258         sel.rgn.r.c.left = vframe.c.left;
259         sel.rgn.r.c.top = vframe.c.top;
260         sel.rgn.r.c.right = vframe.c.right;
261         sel.rgn.r.c.bottom = vframe.c.bottom;
262         adsp_sel(gid, &sel, 1);
263
264         gset_ptr(PS_GRIP, NULL, -1, -1);
265         for (;;) {
266                 event_type = subjectwindow_getdrag(bchanl->subjectwindow, &pos, &wid_butup, &pos_butup);
267                 if (event_type == EV_BUTUP) {
268                         break;
269                 }
270                 if (event_type != EV_NULL) {
271                         continue;
272                 }
273                 if ((pos.x == p1.x)&&(pos.y == p1.y)) {
274                         continue;
275                 }
276                 adsp_sel(gid, &sel, 0);
277                 sel.rgn.r.c.left += pos.x - p1.x;
278                 sel.rgn.r.c.top += pos.y - p1.y;
279                 sel.rgn.r.c.right += pos.x - p1.x;
280                 sel.rgn.r.c.bottom += pos.y - p1.y;
281                 adsp_sel(gid, &sel, 1);
282                 p1 = pos;
283         }
284         gset_ptr(PS_SELECT, NULL, -1, -1);
285         adsp_sel(gid, &sel, 0);
286         subjectwindow_enddrag(bchanl->subjectwindow);
287
288         /* BUTUP on self window or no window or system message panel */
289         if ((wid_butup == subjectwindow_getWID(bchanl->subjectwindow))||(wid_butup == 0)||(wid_butup == -1)) {
290                 return;
291         }
292
293         err = oget_vob(-wid_butup, &vrec.vlnk, NULL, 0, &size);
294         if (err < 0) {
295                 return;
296         }
297
298         err = dget_dtp(64, BCHANL_DBX_VIEWER_FUSEN, (void**)&fsn);
299         if (err < 0) {
300                 DP_ER("dget_dtp: ", err);
301                 return;
302         }
303         fsn_len = dget_siz((B*)fsn);
304         err = bchanl_subject_createviewervobj(bchanl->currentsubject, thread, fsn, fsn_len, &vrec.vseg, (LINK*)&vrec.vlnk);
305         if (err < 0) {
306                 DP_ER("bchanl_subject_createviewervobj error", err);
307                 return;
308         }
309         if (err == BCHANL_SUBJECT_CREATEVIEWERVOBJ_CANCELED) {
310                 DP(("canceled\n"));
311                 return;
312         }
313
314         tr_rec.id = TR_VOBJ;
315         tr_rec.len = sizeof(TR_VOBJREC);
316         tr_rec.dt = (B*)&vrec;
317         err = tset_dat(&tr_rec, 1);
318         if (err < 0) {
319                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
320                 if (err < 0) {
321                         DP_ER("error del_fil:", err);
322                 }
323                 return;
324         }
325
326         paste_ev.r.type = EV_REQUEST;
327         paste_ev.r.r.p.rightbot.x = pos_butup.x + dx;
328         paste_ev.r.r.p.rightbot.y = pos_butup.y + dy;
329         paste_ev.r.cmd = W_PASTE;
330         paste_ev.r.wid = wid_butup;
331         err = wsnd_evt(&paste_ev);
332         if (err < 0) {
333                 tset_dat(NULL, 0);
334                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
335                 if (err < 0) {
336                         DP_ER("error del_fil:", err);
337                 }
338                 return;
339         }
340         err = wwai_rsp(NULL, W_PASTE, 60000);
341         if (err != W_ACK) {
342                 tset_dat(NULL, 0);
343                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
344                 if (err < 0) {
345                         DP_ER("error del_fil:", err);
346                 }
347         }
348
349         wswi_wnd(wid_butup, NULL);
350 }
351
352 LOCAL VOID bchanl_subjectwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
353 {
354         switch (dck) {
355         case    W_CLICK:
356         case    W_DCLICK:
357         case    W_QPRESS:
358         default:
359                 return;
360         case    W_PRESS:
361                 bchanl_subjectwindow_press(bchanl, evpos);
362         }
363 }
364
365 LOCAL VOID bchanl_setcurrentsubject(bchanl_t *bchanl, bchanl_subject_t *sbjt)
366 {
367         bchanl->currentsubject = sbjt;
368         subjectwindow_requestredisp(bchanl->subjectwindow);
369 }
370
371 LOCAL VOID bchanl_bbsmenuwindow_draw(bchanl_t *bchanl)
372 {
373         RECT r;
374         do {
375                 if (bbsmenuwindow_startredisp(bchanl->bbsmenuwindow, &r) == 0) {
376                         break;
377                 }
378                 bbsmenuwindow_eraseworkarea(bchanl->bbsmenuwindow, &r);
379                 bbsmndraw_draw(bchanl->bbsmenu.draw, &r);
380         } while (bbsmenuwindow_endredisp(bchanl->bbsmenuwindow) > 0);
381 }
382
383 LOCAL VOID bchanl_bbsmenuwindow_scroll(VP arg, W dh, W dv)
384 {
385         bchanl_t *bchanl = (bchanl_t*)arg;
386         bbsmndraw_scrollviewrect(bchanl->bbsmenu.draw, dh, dv);
387         bbsmenuwindow_scrollworkarea(bchanl->bbsmenuwindow, -dh, -dv);
388         bchanl_bbsmenuwindow_draw(bchanl);
389 }
390
391 LOCAL VOID bchanl_bbsmenuwindow_resize(bchanl_t *bchanl, SIZE newsize)
392 {
393         W l,t,r,b;
394
395         bbsmndraw_getviewrect(bchanl->bbsmenu.draw, &l, &t, &r, &b);
396
397         r = l + newsize.h;
398         b = t + newsize.v;
399
400         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, l, t, r, b);
401         bbsmenuwindow_setworkrect(bchanl->bbsmenuwindow, l, t, r, b);
402
403         bchanl_bbsmenuwindow_draw(bchanl);
404 }
405
406 LOCAL VOID bchanl_bbsmenuwindow_close(bchanl_t *bchanl)
407 {
408         bchanl_killme(bchanl);
409 }
410
411 LOCAL VOID bchanl_sendsubjectrequest(bchanl_t *bchanl, bchanl_subject_t *subject)
412 {
413         sbjtcache_t *cache;
414         sbjtlayout_t *layout;
415         sbjtdraw_t *draw;
416         TC *title;
417         RECT w_work;
418         W l, t, r, b, title_len, err;
419
420         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
421         pdsp_msg(bchanl->hmistate.msg_retr_subject);
422
423         cache = bchanl_subject_getcache(subject);
424         err = sbjtretriever_sendrequest(bchanl->retriever, cache);
425         if (err < 0) {
426                 pdsp_msg(bchanl->hmistate.msg_error_retr);
427                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
428                 return;
429         }
430
431         pdsp_msg(NULL);
432         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
433
434         bchanl_subject_relayout(subject);
435
436         bchanl_setcurrentsubject(bchanl, subject);
437
438         subjectwindow_getworkrect(bchanl->subjectwindow, &w_work);
439         draw = bchanl_subject_getdraw(subject);
440         sbjtdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
441         subjectwindow_setworkrect(bchanl->subjectwindow, 0, 0, w_work.c.right, w_work.c.bottom);
442
443         layout = bchanl_subject_getlayout(subject);
444         sbjtlayout_getdrawrect(layout, &l, &t, &r, &b);
445         subjectwindow_setdrawrect(bchanl->subjectwindow, l, t, r, b);
446
447         bchanl_subject_gettitle(subject, &title, &title_len);
448         subjectwindow_settitle(bchanl->subjectwindow, title);
449 }
450
451 LOCAL VOID bchanl_bbsmenuwindow_click(bchanl_t *bchanl, PNT pos)
452 {
453         bbsmnparser_item_t *item;
454         bchanl_subject_t *subject;
455         W fnd;
456         UB *host, *board;
457         W host_len, board_len;
458         TC *title;
459         W title_len;
460
461         fnd = bbsmndraw_findboard(bchanl->bbsmenu.draw, pos, &item);
462         if (fnd == 0) {
463                 DP(("not found\n"));
464                 return;
465         }
466         if (item->category != NULL) {
467                 return;
468         }
469         bbsmnparser_item_gethostboard(item, &host, &host_len, &board, &board_len);
470         subject = bchanl_subjecthash_search(bchanl->subjecthash, host, host_len, board, board_len);
471         if (subject == NULL) {
472                 DP(("not found by subject hash"));
473                 return;
474         }
475         bchanl_subject_gettitle(subject, &title, &title_len);
476
477         bchanl_sendsubjectrequest(bchanl, subject);
478 }
479
480 LOCAL VOID bchanl_bbsmenuwindow_butdn(bchanl_t *bchanl, W dck, PNT evpos)
481 {
482         switch (dck) {
483         case    W_DCLICK:
484         case    W_PRESS:
485         case    W_QPRESS:
486         default:
487                 return;
488         case    W_CLICK:
489                 bchanl_bbsmenuwindow_click(bchanl, evpos);
490         }
491 }
492
493 LOCAL W bchanl_bbsmenu_initialize(bchanl_bbsmenu_t *bchanl, GID gid, bchanl_subjecthash_t *subjecthash)
494 {
495         bbsmnretriever_t *retriever;
496         bbsmncache_t *cache;
497         bbsmnparser_t *parser;
498         bbsmnfilter_t *filter;
499         bbsmnlayout_t *layout;
500         bbsmndraw_t *draw;
501
502         cache = bbsmncache_new();
503         if (cache == NULL) {
504                 goto error_cache;
505         }
506         retriever = bbsmnretriever_new();
507         if (retriever == NULL) {
508                 goto error_retriever;
509         }
510         parser = bbsmnparser_new(cache);
511         if (parser == NULL) {
512                 goto error_parser;
513         }
514         filter = bbsmnfilter_new();
515         if (filter == NULL) {
516                 goto error_filter;
517         }
518         layout = bbsmnlayout_new(gid);
519         if (layout == NULL) {
520                 goto error_layout;
521         }
522         draw = bbsmndraw_new(layout);
523         if (draw == NULL) {
524                 goto error_draw;
525         }
526
527         bchanl->gid = gid;
528         bchanl->retriever = retriever;
529         bchanl->cache = cache;
530         bchanl->parser = parser;
531         bchanl->filter = filter;
532         bchanl->layout = layout;
533         bchanl->draw = draw;
534         bchanl->subjecthash = subjecthash;
535
536         return 0;
537
538 error_draw:
539         bbsmnlayout_delete(layout);
540 error_layout:
541         bbsmnfilter_delete(filter);
542 error_filter:
543         bbsmnparser_delete(parser);
544 error_parser:
545         bbsmnretriever_delete(retriever);
546 error_retriever:
547         bbsmncache_delete(cache);
548 error_cache:
549         return -1; /* TODO */
550 }
551
552 LOCAL W bchanl_bbsmenu_appenditemtohash(bchanl_bbsmenu_t *bchanl, bbsmnparser_item_t *item)
553 {
554         W err;
555         UB *host, *board;
556         W host_len, board_len;
557
558         bbsmnparser_item_gethostboard(item, &host, &host_len, &board, &board_len);
559         err = bchanl_subjecthash_append(bchanl->subjecthash, host, host_len, board, board_len, item->title, item->title_len);
560         return err;
561 }
562
563 LOCAL VOID bchanl_bbsmenu_relayout(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *window)
564 {
565         W err, l, t, r, b, ret;
566         bbsmnparser_t *parser = bchanl->parser;
567         bbsmnparser_item_t *item;
568         bbsmnfilter_t *filter = bchanl->filter;
569         bbsmnlayout_t *layout = bchanl->layout;
570
571         bbsmnlayout_clear(layout);
572         bbsmnfilter_clear(filter);
573         bbsmnparser_clear(parser);
574
575         for (;;) {
576                 err = bbsmnparser_getnextitem(parser, &item);
577                 if (err != 1) {
578                         break;
579                 }
580                 bbsmnfilter_inputitem(filter, item);
581                 for (;;) {
582                         ret = bbsmnfilter_outputitem(filter, &item);
583                         if (item != NULL) {
584                                 if (item->category == NULL) {
585                                         err = bchanl_bbsmenu_appenditemtohash(bchanl, item);
586                                         if (err < 0) {
587                                                 return;
588                                         }
589                                 }
590                                 err = bbsmnlayout_appenditem(layout, item);
591                                 if (err < 0) {
592                                         return;
593                                 }
594                         }
595                         if (ret != BBSMNFILTER_OUTPUTITEM_CONTINUE) {
596                                 break;
597                         }
598                 }
599                 if (ret == BBSMNFILTER_OUTPUTITEM_END) {
600                         printf("D\n");
601                         break;
602                 }
603                 if (ret != BBSMNFILTER_OUTPUTITEM_WAITNEXT) {
604                         /* TODO: error */
605                         break;
606                 }
607 /*
608                 if (item == NULL) {
609                         printf("F\n");
610                         break;
611                 }
612 */
613         }
614
615         bbsmnlayout_getdrawrect(bchanl->layout, &l, &t, &r, &b);
616         bbsmenuwindow_setdrawrect(window, l, t, r, b);
617
618         bbsmenuwindow_requestredisp(window);
619 }
620
621 #define BCHANL_MESSAGE_RETRIEVER_RELAYOUT 1
622 #define BCHANL_MESSAGE_RETRIEVER_ERROR -1
623
624 LOCAL VOID bchanl_retriever_task(W arg)
625 {
626         bchanl_t *bchanl;
627         bbsmnretriever_t *retr;
628         bbsmncache_t *cache;
629         W msg,err;
630
631         bchanl = (bchanl_t*)arg;
632         retr = bchanl->bbsmenu.retriever;
633         cache = bchanl->bbsmenu.cache;
634
635         for (;;) {
636                 DP(("before rcv_mbf %d\n", bchanl->mbfid));
637                 err = rcv_mbf(bchanl->mbfid, (VP)&msg, T_FOREVER);
638                 DP_ER("rcv_mbf error:",err);
639                 if (err != 4) {
640                         continue;
641                 }
642
643                 err = bbsmnretriever_sendrequest(retr, cache);
644
645                 switch (err) {
646                 case BBSMNRETRIEVER_REQUEST_ALLRELOAD:
647                         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
648                         break;
649                 default:
650                         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_ERROR);
651                         DP_ER("bbsmnretreiver_request error",err);
652                         break;
653                 }
654         }
655
656         ext_tsk();
657 }
658
659 LOCAL W bchanl_prepare_network(bchanl_t *bchanl)
660 {
661         if (bchanl->retriever == NULL) {
662                 return 0;
663         }
664
665         bchanl->mbfid = cre_mbf(sizeof(W), sizeof(W), DELEXIT);
666         if (bchanl->mbfid < 0) {
667                 DP_ER("error cre_mbf:", bchanl->mbfid);
668                 return -1;
669         }
670         bchanl->taskid = cre_tsk(bchanl_retriever_task, -1, (W)bchanl);
671         if (bchanl->taskid < 0) {
672                 del_mbf(bchanl->mbfid);
673                 bchanl->mbfid = -1;
674                 DP_ER("error cre_tsk:", bchanl->taskid);
675                 return -1;
676         }
677
678         return 0;
679 }
680
681 LOCAL W bchanl_networkrequest_bbsmenu(bchanl_t *bchanl)
682 {
683         W msg = 1, err;
684         static UW lastrequest = 0;
685         UW etime;
686
687         if (bchanl->mbfid < 0) {
688                 return 0;
689         }
690
691         err = get_etm(&etime);
692         if (err < 0) {
693                 DP_ER("get_etm error:", err);
694                 return err;
695         }
696         if (lastrequest + 10000 > etime) {
697                 return 0;
698         }
699         lastrequest = etime;
700
701         err = snd_mbf(bchanl->mbfid, &msg, sizeof(W), T_FOREVER);
702         if (err < 0) {
703                 DP_ER("snd_mbf error:", err);
704                 return err;
705         }
706
707         bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_BUSY);
708         pdsp_msg(bchanl->hmistate.msg_retr_bbsmenu);
709
710         return 0;
711 }
712
713 LOCAL W bchanl_initialize(bchanl_t *bchanl, VID vid, W exectype)
714 {
715         static  RECT    r0 = {{400, 100, 700+7, 200+30}};
716         static  RECT    r1 = {{100, 100, 300+7, 300+30}};
717         TC *title0 = NULL, *title1 = NULL;
718         W err;
719         WID wid;
720         GID gid;
721         RECT w_work;
722         sbjtretriever_t *retriever;
723         bchanlhmi_t *hmi;
724         bchanl_subjecthash_t *subjecthash;
725         subjectwindow_t *subjectwindow;
726         bbsmenuwindow_t *bbsmenuwindow;
727
728         retriever = sbjtretriever_new();
729         if (retriever == NULL) {
730                 DP_ER("sbjtretriever_new error", 0);
731                 goto error_retriever;
732         }
733         hmi = bchanlhmi_new();
734         if (hmi == NULL) {
735                 DP_ER("bchanlhmi_new error", 0);
736                 goto error_bchanlhmi;
737         }
738         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_SUBJECT, (void**)&title0);
739         subjectwindow = bchanlhmi_newsubjectwindow(hmi, &r0, title0, NULL, bchanl_subjectwindow_scroll, bchanl);
740         if (subjectwindow == NULL) {
741                 DP_ER("bchanlhmi_newsubjectwindow error", 0);
742                 goto error_subjectwindow;
743         }
744         gid = subjectwindow_getGID(subjectwindow);
745         subjecthash = bchanl_subjecthash_new(gid, 100);
746         if (subjecthash == NULL) {
747                 DP_ER("bchanl_subjecthash_new error", 0);
748                 goto error_subjecthash;
749         }
750         dget_dtp(TEXT_DATA, BCHANL_DBX_TEXT_WINDOWTITLE_BBSMENU, (void**)&title1);
751         bbsmenuwindow = bchanlhmi_newbbsmenuwindow(hmi, &r1, title1, NULL, bchanl_bbsmenuwindow_scroll, bchanl);
752         if (bbsmenuwindow == NULL) {
753                 DP_ER("bchanlhmi_newbbsmenuwindow error", 0);
754                 goto error_bbsmenuwindow;
755         }
756         gid = bbsmenuwindow_getGID(bbsmenuwindow);
757         err = bchanl_bbsmenu_initialize(&(bchanl->bbsmenu), gid, subjecthash);
758         if (err < 0) {
759                 DP_ER("bchanl_bbsmenu_initialize error", err);
760                 goto error_bbsmenu;
761         }
762         err = bchanl_mainmenu_initialize(&(bchanl->mainmenu), BCHANL_DBX_MENU_TEST);
763         if (err < 0) {
764                 DP_ER("bchanl_mainmenu_initialize %d", err);
765                 goto error_mainmenu;
766         }
767
768         bchanl_hmistate_initialize(&bchanl->hmistate);
769
770         if (exectype == EXECREQ) {
771                 wid = bbsmenuwindow_getWID(bbsmenuwindow);
772                 osta_prc(vid, wid);
773         }
774
775         bbsmenuwindow_getworkrect(bbsmenuwindow, &w_work);
776         bbsmndraw_setviewrect(bchanl->bbsmenu.draw, 0, 0, w_work.c.right, w_work.c.bottom);
777         bbsmenuwindow_setworkrect(bbsmenuwindow, 0, 0, w_work.c.right, w_work.c.bottom);
778
779         bchanl->retriever = retriever;
780         bchanl->subjecthash = subjecthash;
781
782         bchanl->currentsubject = NULL;
783
784         bchanl->vid = vid;
785         bchanl->exectype = exectype;
786
787         bchanl->hmi = hmi;
788         bchanl->subjectwindow = subjectwindow;
789         bchanl->bbsmenuwindow = bbsmenuwindow;
790
791         return 0;
792
793 error_mainmenu:
794         //bchanl_bbsmenu_finalize(&(bchanl->bbsmenu));
795 error_bbsmenu:
796         bchanlhmi_deletebbsmenuwindow(hmi, bbsmenuwindow);
797 error_bbsmenuwindow:
798         bchanl_subjecthash_delete(subjecthash);
799 error_subjecthash:
800         bchanlhmi_deletesubjectwindow(hmi, subjectwindow);
801 error_subjectwindow:
802         bchanlhmi_delete(hmi);
803 error_bchanlhmi:
804         sbjtretriever_delete(retriever);
805 error_retriever:
806         return -1; /* TODO */
807 }
808
809 LOCAL VOID bchanl_killme(bchanl_t *bchanl)
810 {
811         gset_ptr(PS_BUSY, NULL, -1, -1);
812         pdsp_msg(NULL);
813
814         if (bchanl->exectype == EXECREQ) {
815                 oend_prc(bchanl->vid, NULL, 0);
816         }
817         bchanl_mainmenu_finalize(&bchanl->mainmenu);
818         bchanlhmi_deletebbsmenuwindow(bchanl->hmi, bchanl->bbsmenuwindow);
819         bchanl_subjecthash_delete(bchanl->subjecthash);
820         bchanlhmi_deletesubjectwindow(bchanl->hmi, bchanl->subjectwindow);
821         bchanlhmi_delete(bchanl->hmi);
822         sbjtretriever_delete(bchanl->retriever);
823
824         ext_prc(0);
825 }
826
827 LOCAL VOID bchanl_readbbsmenutestdata(bchanl_bbsmenu_t *bchanl, bbsmenuwindow_t *bchanl_window)
828 {
829         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};
830         LINK lnk;
831         W fd, len, err;
832         UB *bin;
833         RECT w_work;
834         bbsmncache_t *cache = bchanl->cache;
835         bbsmndraw_t *draw = bchanl->draw;
836
837         err = get_lnk(fname, &lnk, F_NORM);
838         if (err < 0) {
839                 DP_ER("error get_lnk", err);
840                 return;
841         }
842         fd = opn_fil(&lnk, F_READ, NULL);
843         if (fd < 0) {
844                 return;
845         }
846         err = rea_rec(fd, 0, NULL, 0, &len, NULL);
847         if (err < 0) {
848                 cls_fil(fd);
849                 return;
850         }
851         bin = malloc(len);
852         if (bin == NULL) {
853                 cls_fil(fd);
854                 return;
855         }
856         err = rea_rec(fd, 0, bin, len, 0, NULL);
857         if (err < 0) {
858                 free(bin);
859                 cls_fil(fd);
860                 return;
861         }
862         cls_fil(fd);
863
864         bbsmncache_appenddata(cache, bin, len);
865         free(bin);
866
867         req_tmg(0, BCHANL_MESSAGE_RETRIEVER_RELAYOUT);
868
869         bbsmenuwindow_getworkrect(bchanl_window, &w_work);
870         bbsmndraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
871         bbsmenuwindow_setworkrect(bchanl_window, 0, 0, w_work.c.right, w_work.c.bottom);
872 }
873
874 LOCAL VOID bchanl_subjectwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
875 {
876         W l,t,r,b,l1,t1,r1,b1,scr;
877         sbjtlayout_t *layout;
878         sbjtdraw_t *draw;
879
880         if (bchanl->currentsubject == NULL) {
881                 return;
882         }
883         draw = bchanl_subject_getdraw(bchanl->currentsubject);
884
885         switch (ch) {
886         case KC_CC_U:
887                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
888                 if (t < 16) {
889                         scr = -t;
890                 } else {
891                         scr = -16;
892                 }
893                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
894                 break;
895         case KC_CC_D:
896                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
897                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
898                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
899                 if (b + 16 > b1) {
900                         scr = b1 - b;
901                 } else {
902                         scr = 16;
903                 }
904                 if (scr > 0) {
905                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
906                 }
907                 break;
908         case KC_CC_R:
909                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
910                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
911                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
912                 if (r + 16 > r1) {
913                         scr = r1 - r;
914                 } else {
915                         scr = 16;
916                 }
917                 if (scr > 0) {
918                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
919                 }
920                 break;
921         case KC_CC_L:
922                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
923                 if (l < 16) {
924                         scr = -l;
925                 } else {
926                         scr = -16;
927                 }
928                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
929                 break;
930         case KC_PG_U:
931                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
932                 if (t < (b - t)) {
933                         scr = -t;
934                 } else {
935                         scr = - (b - t);
936                 }
937                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
938                 break;
939         case KC_PG_D:
940                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
941                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
942                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
943                 if (b + (b - t) > b1) {
944                         scr = b1 - b;
945                 } else {
946                         scr = (b - t);
947                 }
948                 if (scr > 0) {
949                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, 0, scr);
950                 }
951                 break;
952         case KC_PG_R:
953                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
954                 layout = bchanl_subject_getlayout(bchanl->currentsubject);
955                 sbjtlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
956                 if (r + (r - l) > r1) {
957                         scr = r1 - r;
958                 } else {
959                         scr = (r - l);
960                 }
961                 if (scr > 0) {
962                         subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
963                 }
964                 break;
965         case KC_PG_L:
966                 sbjtdraw_getviewrect(draw, &l, &t, &r, &b);
967                 if (l < (r - l)) {
968                         scr = -l;
969                 } else {
970                         scr = - (r - l);
971                 }
972                 subjectwindow_scrollbyvalue(bchanl->subjectwindow, scr, 0);
973                 break;
974         case TK_E: /* temporary */
975                 if (stat & ES_CMD) {
976                         bchanl_killme(bchanl);
977                 }
978                 break;
979         }
980 }
981
982 LOCAL VOID bchanl_bbsmenuwindow_keydwn(bchanl_t *bchanl, UH keycode, TC ch, UW stat)
983 {
984         W l,t,r,b,l1,t1,r1,b1,scr;
985         bbsmndraw_t *draw = bchanl->bbsmenu.draw;
986         bbsmnlayout_t *layout = bchanl->bbsmenu.layout;
987
988         switch (ch) {
989         case KC_CC_U:
990                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
991                 if (t < 16) {
992                         scr = -t;
993                 } else {
994                         scr = -16;
995                 }
996                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
997                 break;
998         case KC_CC_D:
999                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1000                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1001                 if (b + 16 > b1) {
1002                         scr = b1 - b;
1003                 } else {
1004                         scr = 16;
1005                 }
1006                 if (scr > 0) {
1007                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1008                 }
1009                 break;
1010         case KC_CC_R:
1011         case KC_CC_L:
1012                 break;
1013         case KC_PG_U:
1014                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1015                 if (t < (b - t)) {
1016                         scr = -t;
1017                 } else {
1018                         scr = - (b - t);
1019                 }
1020                 bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1021                 break;
1022         case KC_PG_D:
1023                 bbsmndraw_getviewrect(draw, &l, &t, &r, &b);
1024                 bbsmnlayout_getdrawrect(layout, &l1, &t1, &r1, &b1);
1025                 if (b + (b - t) > b1) {
1026                         scr = b1 - b;
1027                 } else {
1028                         scr = (b - t);
1029                 }
1030                 if (scr > 0) {
1031                         bbsmenuwindow_scrollbyvalue(bchanl->bbsmenuwindow, 0, scr);
1032                 }
1033                 break;
1034         case KC_PG_R:
1035         case KC_PG_L:
1036                 break;
1037         case KC_PF5:
1038                 bchanl_networkrequest_bbsmenu(bchanl);
1039                 break;
1040         case TK_E: /* temporary */
1041                 if (stat & ES_CMD) {
1042                         bchanl_killme(bchanl);
1043                 }
1044                 break;
1045         }
1046 }
1047
1048
1049 LOCAL VOID bchanl_keydwn(bchanl_t *bchanl, UH keytop, TC ch, UW stat)
1050 {
1051         Bool act;
1052
1053         act = subjectwindow_isactive(bchanl->subjectwindow);
1054         if (act == True) {
1055                 bchanl_subjectwindow_keydwn(bchanl, keytop, ch, stat);
1056                 return;
1057         }
1058         act = bbsmenuwindow_isactive(bchanl->bbsmenuwindow);
1059         if (act == True) {
1060                 bchanl_bbsmenuwindow_keydwn(bchanl, keytop, ch, stat);
1061                 return;
1062         }
1063 }
1064
1065 LOCAL VOID bchanl_setupmenu(bchanl_t *bchanl)
1066 {
1067         bchanl_mainmenu_setup(&bchanl->mainmenu);
1068 }
1069
1070 LOCAL VOID bchanl_selectmenu(bchanl_t *bchanl, W sel)
1071 {
1072         switch(sel) {
1073         case BCHANL_MAINMENU_SELECT_CLOSE: /* [½ªÎ»] */
1074                 bchanl_killme(bchanl);
1075                 break;
1076         case BCHANL_MAINMENU_SELECT_REDISPLAY: /* [ºÆɽ¼¨] */
1077                 subjectwindow_requestredisp(bchanl->subjectwindow);
1078                 bbsmenuwindow_requestredisp(bchanl->bbsmenuwindow);
1079                 break;
1080         case BCHANL_MAINMENU_SELECT_BBSMENUFETCH: /* [ÈÄ°ìÍ÷ºÆ¼èÆÀ] */
1081                 bchanl_networkrequest_bbsmenu(bchanl);
1082                 break;
1083         }
1084         return;
1085 }
1086
1087 LOCAL VOID bchanl_popupmenu(bchanl_t *bchanl, PNT pos)
1088 {
1089         W sel;
1090         bchanl_setupmenu(bchanl);
1091         gset_ptr(PS_SELECT, NULL, -1, -1);
1092         sel = bchanl_mainmenu_popup(&bchanl->mainmenu, pos);
1093         if (sel > 0) {
1094                 bchanl_selectmenu(bchanl, sel);
1095         }
1096 }
1097
1098 LOCAL W bchanl_keyselect(bchanl_t *bchanl, TC keycode)
1099 {
1100         W sel;
1101         bchanl_setupmenu(bchanl);
1102         sel = bchanl_mainmenu_keyselect(&bchanl->mainmenu, keycode);
1103         if (sel > 0) {
1104                 bchanl_selectmenu(bchanl, sel);
1105         }
1106         return 0;
1107 }
1108
1109 LOCAL VOID bchanl_handletimeout(bchanl_t *bchanl, W code)
1110 {
1111         switch (code) {
1112         case BCHANL_MESSAGE_RETRIEVER_RELAYOUT:
1113                 bchanl_bbsmenu_relayout(&bchanl->bbsmenu, bchanl->bbsmenuwindow);
1114                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1115                 pdsp_msg(NULL);
1116                 break;
1117         case BCHANL_MESSAGE_RETRIEVER_ERROR:
1118                 bchanl_hmistate_updateptrstyle(&bchanl->hmistate, PS_SELECT);
1119                 pdsp_msg(NULL);
1120                 break;
1121         }
1122 }
1123
1124 LOCAL VOID bchanl_eventdispatch(bchanl_t *bchanl)
1125 {
1126         bchanlhmievent_t *evt;
1127         W sel, err;
1128
1129         err = bchanlhmi_getevent(bchanl->hmi, &evt);
1130         if (err < 0) {
1131                 return;
1132         }
1133
1134         switch (evt->type) {
1135         case BCHANLHMIEVENT_TYPE_COMMON_MOUSEMOVE:
1136                 break;
1137         case BCHANLHMIEVENT_TYPE_COMMON_KEYDOWN:
1138                 if (evt->data.common_keydown.stat & ES_CMD) {   /*Ì¿Îᥭ¡¼*/
1139                         bchanl_setupmenu(bchanl);
1140                         sel = bchanl_keyselect(bchanl, evt->data.common_keydown.keycode);
1141                         if (sel > 0) {
1142                                 bchanl_selectmenu(bchanl, sel);
1143                                 break;
1144                         }
1145                 }
1146                 bchanl_keydwn(bchanl, evt->data.common_keydown.keytop, evt->data.common_keydown.keycode, evt->data.common_keydown.stat);
1147                 break;
1148         case BCHANLHMIEVENT_TYPE_COMMON_MENU:
1149                 bchanl_popupmenu(bchanl, evt->data.common_menu.pos);
1150                 break;
1151         case BCHANLHMIEVENT_TYPE_COMMON_TIMEOUT:
1152                 bchanl_handletimeout(bchanl, evt->data.common_timeout.code);
1153                 break;
1154         case BCHANLHMIEVENT_TYPE_SUBJECT_DRAW:
1155                 bchanl_subjectwindow_draw(bchanl);
1156                 break;
1157         case BCHANLHMIEVENT_TYPE_SUBJECT_RESIZE:
1158                 bchanl_subjectwindow_resize(bchanl, evt->data.subject_resize.work_sz);
1159                 break;
1160         case BCHANLHMIEVENT_TYPE_SUBJECT_CLOSE:
1161                 bchanl_subjectwindow_close(bchanl);
1162                 break;
1163         case BCHANLHMIEVENT_TYPE_SUBJECT_BUTDN:
1164                 bchanl_subjectwindow_butdn(bchanl, evt->data.subject_butdn.type, evt->data.subject_butdn.pos);
1165                 break;
1166         case BCHANLHMIEVENT_TYPE_SUBJECT_PASTE:
1167                 subjectwindow_responsepasterequest(bchanl->subjectwindow, /* NACK */ 1, NULL);
1168                 break;
1169         case BCHANLHMIEVENT_TYPE_SUBJECT_SWITCH:
1170                 if (evt->data.subject_switch.needdraw == True) {
1171                         bchanl_subjectwindow_draw(bchanl);
1172                 }
1173                 break;
1174         case BCHANLHMIEVENT_TYPE_SUBJECT_MOUSEMOVE:
1175                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
1176                 break;
1177         case BCHANLHMIEVENT_TYPE_BBSMENU_DRAW:
1178                 bchanl_bbsmenuwindow_draw(bchanl);
1179                 break;
1180         case BCHANLHMIEVENT_TYPE_BBSMENU_RESIZE:
1181                 bchanl_bbsmenuwindow_resize(bchanl, evt->data.bbsmenu_resize.work_sz);
1182                 break;
1183         case BCHANLHMIEVENT_TYPE_BBSMENU_CLOSE:
1184                 bchanl_bbsmenuwindow_close(bchanl);
1185                 break;
1186         case BCHANLHMIEVENT_TYPE_BBSMENU_BUTDN:
1187                 bchanl_bbsmenuwindow_butdn(bchanl, evt->data.bbsmenu_butdn.type, evt->data.bbsmenu_butdn.pos);
1188                 break;
1189         case BCHANLHMIEVENT_TYPE_BBSMENU_PASTE:
1190                 bbsmenuwindow_responsepasterequest(bchanl->bbsmenuwindow, /* NACK */ 1, NULL);
1191                 break;
1192         case BCHANLHMIEVENT_TYPE_BBSMENU_SWITCH:
1193                 if (evt->data.bbsmenu_switch.needdraw == True) {
1194                         bchanl_bbsmenuwindow_draw(bchanl);
1195                 }
1196                 break;
1197         case BCHANLHMIEVENT_TYPE_BBSMENU_MOUSEMOVE:
1198                 gset_ptr(bchanl->hmistate.ptr, NULL, -1, -1);
1199                 break;
1200         case BCHANLHMIEVENT_TYPE_NONE:
1201         }
1202 }
1203
1204 typedef struct _arg {
1205         W ac;
1206         TC **argv;
1207 } CLI_arg;
1208
1209 LOCAL    CLI_arg   MESSAGEtoargv(const MESSAGE *src)
1210 {
1211         W len,i,ac;
1212         TC *str;
1213         TC **argv;
1214         CLI_arg ret;
1215
1216         len = src->msg_size / sizeof(TC);
1217         str = (TC*)(src->msg_body.ANYMSG.msg_str);
1218         ac = 0;
1219         for(i=0;i<len;i++){
1220                 if(str[i] == TK_KSP){
1221                         str[i] = TNULL;
1222                         continue;
1223                 }
1224                 ac++;
1225                 for(;i<len;i++){
1226                         if(str[i] == TK_KSP){
1227                                 i--;
1228                                 break;
1229                         }
1230                 }
1231         }
1232
1233         argv = (TC**)malloc(sizeof(TC*)*ac);
1234
1235         ac = 0;
1236         for(i=0;i<len;i++){
1237                 if(str[i] == TNULL){
1238                         str[i] = TNULL;
1239                         continue;
1240                 }
1241                 argv[ac++] = str+i;
1242                 for(;i<len;i++){
1243                         if(str[i] == TNULL){
1244                                 i--;
1245                                 break;
1246                         }
1247                 }
1248         }
1249
1250         ret.ac = ac;
1251         ret.argv = argv;
1252
1253         return ret;
1254 }
1255
1256 EXPORT  W       MAIN(MESSAGE *msg)
1257 {
1258         W err;
1259         VID vid = -1;
1260         CLI_arg arg;
1261         LINK dbx;
1262         bchanl_t bchanl;
1263
1264         err = dopn_dat(NULL);
1265         if (err < 0) {
1266                 DP_ER("dopn_dat error:", err);
1267                 ext_prc(0);
1268         }
1269
1270         switch (msg->msg_type) {
1271         case 0: /* CLI */
1272                 arg = MESSAGEtoargv(msg);
1273                 err = get_lnk((TC[]){TK_b, TK_c, TK_h, TK_a, TK_n, TK_l, TK_PROD, TK_d, TK_b, TK_x,TNULL}, &dbx, F_NORM);
1274                 if (err < 0) {
1275                         DP_ER("get_lnk:databox error", err);
1276                         ext_prc(0);
1277                 }
1278                 err = dopn_dat(&dbx);
1279                 if (err < 0) {
1280                         DP_ER("dopn_dat error", err);
1281                         ext_prc(0);
1282                 }
1283                 break;
1284         case DISPREQ:
1285                 oend_req(((M_DISPREQ*)msg)->vid, -1);
1286                 ext_prc(0);
1287                 break;
1288         case PASTEREQ:
1289                 oend_req(((M_PASTEREQ*)msg)->vid, -1);
1290                 ext_prc(0);
1291                 break;
1292         case EXECREQ:
1293                 if ((((M_EXECREQ*)msg)->mode & 2) == 0) {
1294                         ext_prc(0);
1295                 }
1296                 err = dopn_dat(&((M_EXECREQ*)msg)->self);
1297                 if (err < 0) {
1298                         DP_ER("dopn_dat error", err);
1299                         ext_prc(0);
1300                 }
1301                 vid = ((M_EXECREQ*)msg)->vid;
1302                 break;
1303         default:
1304                 ext_prc(0);
1305                 break;
1306         }
1307
1308         err = bchanl_initialize(&bchanl, vid, msg->msg_type);
1309         if (err < 0) {
1310                 DP_ER("bchanl_initialize error", err);
1311                 ext_prc(0);
1312         }
1313         err = bchanl_prepare_network(&bchanl);
1314         if (err < 0) {
1315                 DP_ER("bchanl_prepare_network error", err);
1316                 bchanl_killme(&bchanl);
1317                 return err;
1318         }
1319
1320         if (msg->msg_type == 0) {
1321                 bchanl_readbbsmenutestdata(&(bchanl.bbsmenu), bchanl.bbsmenuwindow);
1322         } else if (msg->msg_type == EXECREQ) {
1323                 bchanl_networkrequest_bbsmenu(&bchanl);
1324         }
1325
1326         subjectwindow_requestredisp(bchanl.subjectwindow);
1327         bbsmenuwindow_requestredisp(bchanl.bbsmenuwindow);
1328
1329         for (;;) {
1330                 bchanl_eventdispatch(&bchanl);
1331         }
1332
1333         return 0;
1334 }