OSDN Git Service

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