OSDN Git Service

rename bchan_resmenu_t to bchan_resnumbermenu_t.
[bbk/bchan.git] / src / main.c
1 /*
2  * main.c
3  *
4  * Copyright (c) 2009-2010 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        <tctype.h>
36 #include        <btron/btron.h>
37 #include        <btron/dp.h>
38 #include        <btron/hmi.h>
39 #include        <btron/vobj.h>
40 #include        <btron/libapp.h>
41 #include        <btron/bsocket.h>
42
43 #include        "postres.h"
44 #include        "poptray.h"
45 #include        "confirm.h"
46 #include        "window.h"
47 #include        "cache.h"
48 #include        "parser.h"
49 #include        "layout.h"
50 #include        "retriever.h"
51 #include        "submit.h"
52 #include        "tadurl.h"
53 #include        "sjisstring.h"
54 #include        "bchan_vobj.h"
55 #include        "bchan_panels.h"
56 #include        "bchan_menus.h"
57
58 #ifdef BCHAN_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 BCHAN_DBX_MENU_TEST 20
67 #define BCHAN_DBX_TEXT_MLIST0   21
68 #define BCHAN_DBX_TEXT_MLIST1   22
69 #define BCHAN_DBX_TEXT_MLIST2   23
70 #define BCHAN_DBX_MSGTEXT_RETRIEVING 24
71 #define BCHAN_DBX_MSGTEXT_NOTMODIFIED 25
72 #define BCHAN_DBX_MSGTEXT_POSTSUCCEED 26
73 #define BCHAN_DBX_MSGTEXT_POSTDENIED 27
74 #define BCHAN_DBX_MSGTEXT_POSTERROR     28
75 #define BCHAN_DBX_MS_CONFIRM_POST 29
76 #define BCHAN_DBX_MS_CONFIRM_CANCEL     30
77 #define BCHAN_DBX_TEXT_CONFIRM_TITLE 31
78 #define BCHAN_DBX_MSGTEXT_NONAUTHORITATIVE 32
79 #define BCHAN_DBX_MSGTEXT_NETWORKERROR  33
80 #define BCHAN_DBX_FFUSEN_BBB 34
81 #define BCHAN_DBX_FFUSEN_TEXEDIT 35
82 #define BCHAN_DBX_FFUSEN_VIEWER 36
83 #define BCHAN_DBX_MSGTEXT_NOTFOUND      37
84 #define BCHAN_DBX_MSGTEXT_CANTRETRIEVE 44
85 #define BCHAN_DBX_GMENU_RESNUMBER 45
86 #define BCHAN_DBX_GMENU_RESID 47
87
88 #define BCHAN_MENU_WINDOW 4
89
90 typedef struct bchan_hmistate_t_ bchan_hmistate_t;
91 struct bchan_hmistate_t_ {
92         PTRSTL ptr;
93
94         TC *msg_retrieving;
95         TC *msg_notmodified;
96         TC *msg_nonauthoritative;
97         TC *msg_postsucceed;
98         TC *msg_postdenied;
99         TC *msg_posterror;
100         TC *msg_networkerror;
101         TC *msg_notfound;
102         TC *msg_cantretrieve;
103 };
104
105 LOCAL VOID bchan_hmistate_updateptrstyle(bchan_hmistate_t *hmistate, PTRSTL ptr)
106 {
107         if (hmistate->ptr == ptr) {
108                 return;
109         }
110         hmistate->ptr = ptr;
111         gset_ptr(hmistate->ptr, NULL, -1, -1);
112 }
113
114 LOCAL VOID bchan_hmistate_display_postdenied(bchan_hmistate_t *hmistate, TC *str, W len)
115 {
116         W size, msg_len;
117         TC *msg;
118
119         size = tc_strlen(hmistate->msg_postdenied);
120         msg_len = size + len + 2;
121         msg = malloc((msg_len + 1)*sizeof(TC));
122         if (msg == NULL) {
123                 pdsp_msg(hmistate->msg_postdenied);
124         }
125
126         tc_strcpy(msg, hmistate->msg_postdenied);
127         msg[size] = TK_LPAR;
128         memcpy((UB*)(msg + size + 1), str, len * sizeof(TC));
129         msg[msg_len - 1] = TK_RPAR;
130         msg[msg_len] = TNULL;
131
132         pdsp_msg(msg);
133
134         free(msg);
135 }
136
137 typedef struct bchan_t_ bchan_t;
138 struct bchan_t_ {
139         W wid;
140         W gid;
141         W taskid;
142         W mbfid;
143         VID vid;
144         W exectype;
145
146         Bool request_confirm_open; /* TODO: should be other implememt? */
147
148         MENUITEM *mnitem;
149         MNID mnid;
150
151         bchan_hmistate_t hmistate;
152         bchan_resnumbermenu_t resnumbermenu;
153         bchan_residmenu_t residmenu;
154
155         datretriever_t *retriever;
156         datcache_t *cache;
157         datparser_t *parser;
158         datlayout_t *layout;
159         datdraw_t *draw;
160         datwindow_t *window;
161         ressubmit_t *submit;
162         cfrmwindow_t *confirm;
163
164         postresdata_t *resdata;
165 };
166
167 #define BCHAN_MESSAGE_RETRIEVER_UPDATE   1
168 #define BCHAN_MESSAGE_RETRIEVER_RELAYOUT 2
169 #define BCHAN_MESSAGE_RETRIEVER_NOTMODIFIED 3
170 #define BCHAN_MESSAGE_RETRIEVER_NONAUTHORITATIVE 4
171 #define BCHAN_MESSAGE_RETRIEVER_NOTFOUND 5
172 #define BCHAN_MESSAGE_RETRIEVER_ERROR -1
173
174 static  WEVENT  wev0;
175
176 void    killme(bchan_t *bchan)
177 {
178         gset_ptr(PS_BUSY, NULL, -1, -1);
179         pdsp_msg(NULL);
180         bchan_residmenu_finalize(&bchan->residmenu);
181         bchan_resnumbermenu_finalize(&bchan->resnumbermenu);
182         if (bchan->exectype == EXECREQ) {
183                 oend_prc(bchan->vid, NULL, 0);
184         }
185         if (bchan->wid > 0) {
186                 wcls_wnd(bchan->wid, CLR);
187         }
188         ext_prc(0);
189 }
190
191 LOCAL VOID bchan_scroll(VP arg, W dh, W dv)
192 {
193         bchan_t *bchan = (bchan_t*)arg;
194         datdraw_scrollviewrect(bchan->draw, dh, dv);
195         wscr_wnd(bchan->wid, NULL, -dh, -dv, W_MOVE|W_RDSET);
196 }
197
198 LOCAL VOID bchan_draw(VP arg, RECT *r)
199 {
200         bchan_t *bchan = (bchan_t*)arg;
201         datdraw_draw(bchan->draw, r);
202 }
203
204 LOCAL VOID bchan_resize(VP arg)
205 {
206         bchan_t *bchan = (bchan_t*)arg;
207         W l,t,r,b;
208         RECT work;
209         Bool workchange = False;
210
211         wget_wrk(bchan->wid, &work);
212         if (work.c.left != 0) {
213                 work.c.left = 0;
214                 workchange = True;
215         }
216         if (work.c.top != 0) {
217                 work.c.top = 0;
218                 workchange = True;
219         }
220         wset_wrk(bchan->wid, &work);
221         gset_vis(bchan->gid, work);
222
223         datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
224
225         r = l + work.c.right - work.c.left;
226         b = t + work.c.bottom - work.c.top;
227
228         datdraw_setviewrect(bchan->draw, l, t, r, b);
229         datwindow_setworkrect(bchan->window, l, t, r, b);
230
231         if (workchange == True) {
232                 wera_wnd(bchan->wid, NULL);
233                 wreq_dsp(bchan->wid);
234         }
235 }
236
237 LOCAL VOID bchan_close(VP arg)
238 {
239         bchan_t *bchan = (bchan_t*)arg;
240         /* TODO: guard request event W_DELETE and W_FINISH. */
241         datcache_writefile(bchan->cache);
242         killme(bchan);
243 }
244
245 LOCAL VOID bchan_pushstringtotray(TC *str, W len)
246 {
247         W err;
248         TRAYREC trayrec[2];
249         UB bin[4+24];
250         TADSEG *base = (TADSEG*)bin;
251         TEXTSEG *textseg = (TEXTSEG*)(bin + 4);
252
253         base->id = 0xFFE1;
254         base->len = 24;
255         textseg->view = (RECT){{0, 0, 0, 0}};
256         textseg->draw = (RECT){{0, 0, 0, 0}};
257         textseg->h_unit = -120;
258         textseg->v_unit = -120;
259         textseg->lang = 0x21;
260         textseg->bgpat = 0;
261
262         trayrec[0].id = 0xE1;
263         trayrec[0].len = 28;
264         trayrec[0].dt = bin;
265         trayrec[1].id = TR_TEXT;
266         trayrec[1].len = len * sizeof(TC);
267         trayrec[1].dt = (B*)str;
268
269         err = tpsh_dat(trayrec, 2, NULL);
270         if (err < 0) {
271                 DP_ER("tpsh_dat", err);
272         }
273 }
274
275 LOCAL VOID bchan_pushthreadtitle(bchan_t *bchan)
276 {
277         W len;
278         TC *str;
279
280         str = datlayout_gettitle(bchan->layout);
281         len = datlayout_gettitlelen(bchan->layout);
282         bchan_pushstringtotray(str, len);
283 }
284
285 LOCAL VOID bchan_pushthreadurl(bchan_t *bchan)
286 {
287         W host_len, board_len, thread_len, len, i, ret;
288         UB *host, *board, *thread;
289         TC *str;
290
291         datcache_gethost(bchan->cache, &host, &host_len);
292         datcache_getborad(bchan->cache, &board, &board_len);
293         datcache_getthread(bchan->cache, &thread, &thread_len);
294
295         len = 7 + host_len + 15 + board_len + 1 + thread_len + 1;
296         str = malloc(sizeof(TC)*len);
297
298         str[0] = TK_h;
299         str[1] = TK_t;
300         str[2] = TK_t;
301         str[3] = TK_p;
302         str[4] = TK_COLN;
303         str[5] = TK_SLSH;
304         str[6] = TK_SLSH;
305         for (i = 0; i < host_len; i++) {
306                 ret = sjtotc(str + 7 + i, host + i);
307                 if (ret != 1) {
308                         DP(("invalid charactor\n"));
309                         free(str);
310                         return;
311                 }
312         }
313         str[7 + host_len] = TK_SLSH;
314         str[7 + host_len + 1] = TK_t;
315         str[7 + host_len + 2] = TK_e;
316         str[7 + host_len + 3] = TK_s;
317         str[7 + host_len + 4] = TK_t;
318         str[7 + host_len + 5] = TK_SLSH;
319         str[7 + host_len + 6] = TK_r;
320         str[7 + host_len + 7] = TK_e;
321         str[7 + host_len + 8] = TK_a;
322         str[7 + host_len + 9] = TK_d;
323         str[7 + host_len + 10] = TK_PROD;
324         str[7 + host_len + 11] = TK_c;
325         str[7 + host_len + 12] = TK_g;
326         str[7 + host_len + 13] = TK_i;
327         str[7 + host_len + 14] = TK_SLSH;
328         for (i = 0; i < board_len; i++) {
329                 ret = sjtotc(str + 7 + host_len + 15 + i, board + i);
330                 if (ret != 1) {
331                         DP(("invalid charactor\n"));
332                         free(str);
333                         return;
334                 }
335         }
336         str[7 + host_len + 15 + board_len] = TK_SLSH;
337         for (i = 0; i < thread_len; i++) {
338                 ret = sjtotc(str + 7 + host_len + 15 + board_len + 1 + i, thread + i);
339                 if (ret != 1) {
340                         DP(("invalid charactor\n"));
341                         free(str);
342                         return;
343                 }
344         }
345         str[7 + host_len + 15 + board_len + 1 + thread_len] = TK_SLSH;
346
347         bchan_pushstringtotray(str, len);
348
349         free(str);
350 }
351
352 LOCAL Bool bchan_is_bbs_url(UB *data, W data_len)
353 {
354         TC *str;
355         W str_len, cmp, i, n_slsh = 0;
356
357         if ((tadurl_cmpscheme(data, data_len, "http", 4) != 0)
358                 &&(tadurl_cmpscheme(data, data_len, "ttp", 3) != 0)) {
359                 return False;
360         }
361
362         cmp = tadurl_cmppath(data, data_len, "test/read.cgi/", 14);
363         if (cmp != 0) {
364                 return False;
365         }
366
367         str = (TC*)data;
368         str_len = data_len/2;
369
370         for (i=0;; i++) {
371                 if (i >= str_len) {
372                         return False;
373                 }
374                 if (n_slsh == 6) {
375                         break;
376                 }
377                 if (str[i] == TK_SLSH) {
378                         n_slsh++;
379                 }
380         }
381
382         for (;; i++) {
383                 if (i >= str_len) {
384                         return False;
385                 }
386                 if (str[i] == TK_SLSH) {
387                         break;
388                 }
389                 if (tc_isdigit(str[i]) == 0) {
390                         return False;
391                 }
392         }
393
394         return True;
395 }
396
397 LOCAL W bchan_createvobj_allocate_url(UB *data, W data_len, TC **url, W *url_len)
398 {
399         TC *str;
400         W len;
401
402         if (tadurl_cmpscheme(data, data_len, "http", 4) == 0) {
403                 len = data_len;
404                 str = malloc(len);
405                 if (str == NULL) {
406                         return -1; /* TODO */
407                 }
408                 memcpy(str, data, data_len);
409         } else if (tadurl_cmpscheme(data, data_len, "ttp", 3) == 0) {
410                 len = data_len + sizeof(TC)*1;
411                 str = malloc(len);
412                 if (str == NULL) {
413                         return -1; /* TODO */
414                 }
415                 memcpy(str + 1, data, data_len);
416                 str[0] = TK_h;
417         } else if (tadurl_cmpscheme(data, data_len, "sssp", 4) == 0) {
418                 len = data_len;
419                 str = malloc(len);
420                 if (str == NULL) {
421                         return -1; /* TODO */
422                 }
423                 memcpy(str + 4, data + 8, data_len - 8);
424                 str[0] = TK_h;
425                 str[1] = TK_t;
426                 str[2] = TK_t;
427                 str[3] = TK_p;
428         } else {
429                 return -1; /* TODO */
430         }
431
432         *url = str;
433         *url_len = len/sizeof(TC);
434
435         return 0;
436 }
437
438 LOCAL VOID bchan_separete_bbs_url(UB *url, W url_len, UB **host, W *host_len, UB **board, W *board_len, UB **thread, W *thread_len)
439 {
440         W i,n_slsh = 0;
441
442         for (i=0; i < url_len; i++) {
443                 if (n_slsh == 2) {
444                         break;
445                 }
446                 if (url[i] == '/') {
447                         n_slsh++;
448                 }
449         }
450         *host = url + i;
451         *host_len = 0;
452         for (; i < url_len; i++) {
453                 if (n_slsh == 3) {
454                         break;
455                 }
456                 if (url[i] == '/') {
457                         n_slsh++;
458                 } else {
459                         (*host_len)++;
460                 }
461         }
462         for (; i < url_len; i++) {
463                 if (n_slsh == 5) {
464                         break;
465                 }
466                 if (url[i] == '/') {
467                         n_slsh++;
468                 }
469         }
470         *board = url + i;
471         *board_len = 0;
472         for (; i < url_len; i++) {
473                 if (n_slsh == 6) {
474                         break;
475                 }
476                 if (url[i] == '/') {
477                         n_slsh++;
478                 } else {
479                         (*board_len)++;
480                 }
481         }
482         *thread = url + i;
483         *thread_len = 0;
484         for (; i < url_len; i++) {
485                 if (n_slsh == 7) {
486                         break;
487                 }
488                 if (url[i] == '/') {
489                         n_slsh++;
490                 } else {
491                         (*thread_len)++;
492                 }
493         }
494 }
495
496 #define BCHAN_CREATEVOBJ_CANCELED 0
497 #define BCHAN_CREATEVOBJ_CREATED 1
498
499 LOCAL W bchan_createvobj(bchan_t *bchan, UB *data, W data_len, VOBJSEG *vseg, LINK *lnk)
500 {
501         W err, fsn_bbb_len, fsn_texedit_len, fsn_viewer_len, url_len, ascii_url_len;
502         TC *url;
503         void *fsn_bbb, *fsn_texedit, *fsn_viewer;
504         UB *ascii_url;
505         UB *host, *board, *thread;
506         W host_len, board_len, thread_len;
507         LTADSEG *lseg;
508         Bool is_bbs;
509         TC title[] = {TK_T, TK_h, TK_r, TK_e, TK_a, TK_d, TNULL}; /* tmp */
510
511         err = dget_dtp(64, BCHAN_DBX_FFUSEN_BBB, (void**)&fsn_bbb);
512         if (err < 0) {
513                 DP_ER("dget_dtp: BCHAN_DBX_FFUSEN_BBB", err);
514                 return err;
515         }
516         fsn_bbb_len = dget_siz((B*)fsn_bbb);
517         err = dget_dtp(64, BCHAN_DBX_FFUSEN_TEXEDIT, (void**)&fsn_texedit);
518         if (err < 0) {
519                 DP_ER("dget_dtp: BCHAN_DBX_FFUSEN_TEXEDIT", err);
520                 return err;
521         }
522         fsn_texedit_len = dget_siz((B*)fsn_texedit);
523         err = dget_dtp(64, BCHAN_DBX_FFUSEN_VIEWER, (void**)&fsn_viewer);
524         if (err < 0) {
525                 DP_ER("dget_dtp: BCHAN_DBX_FFUSEN_VIEWER", err);
526                 return err;
527         }
528         fsn_viewer_len = dget_siz((B*)fsn_viewer);
529
530         for (;;) {
531                 if(((*(UH*)data) & 0xFF80) == 0xFF80) {
532                         lseg = (LTADSEG*)(data);
533                         if (lseg->len == 0xffff) {
534                                 data += lseg->llen + 8;
535                                 data_len -= lseg->llen + 8;
536                         } else {
537                                 data += lseg->len + 4;
538                                 data_len -= lseg->len + 4;
539                         }
540                 } else {
541                         break;
542                 }
543         }
544
545         is_bbs = bchan_is_bbs_url(data, data_len);
546         if (is_bbs == True) {
547                 ascii_url = NULL;
548                 ascii_url_len = 0;
549                 err = sjstring_appendconvartingTCstring(&ascii_url, &ascii_url_len, (TC*)data, data_len/2);
550                 if (err < 0) {
551                         return 0;
552                 }
553
554                 bchan_separete_bbs_url(ascii_url, ascii_url_len, &host, &host_len, &board, &board_len, &thread, &thread_len);
555                 err = bchan_createviewervobj(title, fsn_viewer, fsn_viewer_len, host, host_len, board, board_len, thread, thread_len, vseg, lnk);
556                 if (err < 0) {
557                         return 0;
558                 }
559
560                 free(ascii_url);
561         } else {
562                 err = bchan_createvobj_allocate_url(data, data_len, &url, &url_len);
563                 if (err < 0) {
564                         DP_ER("bchan_createvobj_allocate_url", err);
565                         return err;
566                 }
567
568                 err = bchan_createbbbvobj(fsn_bbb, fsn_bbb_len, fsn_texedit, fsn_texedit_len, (UB*)url, url_len*2, vseg, lnk);
569                 if (err < 0) {
570                         DP_ER("bchan_createbbbvobj", err);
571                         return err;
572                 }
573
574                 free(url);
575         }
576
577         return BCHAN_CREATEVOBJ_CREATED;
578 }
579
580 LOCAL VOID bchan_scrollbyahcnor(bchan_t *bchan, UB *data, W data_len)
581 {
582         LTADSEG *lseg;
583         W num, len;
584         TC *str;
585         W fnd;
586         W cl, ct, cr, cb, tl, tt, tr, tb;
587
588         for (;;) {
589                 if(((*(UH*)data) & 0xFF80) == 0xFF80) {
590                         lseg = (LTADSEG*)(data);
591                         if (lseg->len == 0xffff) {
592                                 data += lseg->llen + 8;
593                                 data_len -= lseg->llen + 8;
594                         } else {
595                                 data += lseg->len + 4;
596                                 data_len -= lseg->len + 4;
597                         }
598                 } else {
599                         break;
600                 }
601         }
602
603         str = (TC*)data;
604         len = data_len;
605
606         num = tc_atoi(str + 2);
607         DP(("num = %d\n", num));
608
609         fnd = datlayout_getthreadviewrectbyindex(bchan->layout, num - 1, &tl, &tt, &tr, &tb);
610         if (fnd == 0) {
611                 return;
612         }
613         datdraw_getviewrect(bchan->draw, &cl, &ct, &cr, &cb);
614         datwindow_scrollbyvalue(bchan->window, 0 - cl, tt - ct);
615 }
616
617 LOCAL VOID bchan_butdn_pressnumber(bchan_t *bchan, WEVENT *wev, W resindex)
618 {
619         W size, err;
620         PNT pos;
621         B *data;
622
623         DP(("press DATDRAW_FINDACTION_TYPE_NUMBER: %d\n", resindex + 1));
624         pos.x = wev->s.pos.x;
625         pos.y = wev->s.pos.y;
626         gcnv_abs(bchan->gid, &pos);
627         err = bchan_resnumbermenu_select(&bchan->resnumbermenu, pos);
628         if (err == BCHAN_RESNUMBERMENU_SELECT_PUSHTRAY) {
629                 size = datlayout_resindextotraytextdata(bchan->layout, resindex, NULL, 0);
630                 data = malloc(size);
631                 if (data == NULL) {
632                         return;
633                 }
634                 datlayout_resindextotraytextdata(bchan->layout, resindex, data, size);
635                 bchan_pushstringtotray((TC*)data, size/2);
636                 free(data);
637         }
638 }
639
640 LOCAL VOID bchan_butdn_pressresheaderid(bchan_t *bchan, WEVENT *wev, W resindex)
641 {
642         W id_len, size, err;
643         TC *id;
644         PNT pos;
645         B *data;
646
647         DP(("press DATDRAW_FINDACTION_TYPE_ID\n"));
648
649         datlayout_getidfromindex(bchan->layout, resindex, &id, &id_len);
650         if (id == NULL) {
651                 DP(("      id is not exist\n"));
652                 return;
653         }
654
655         pos.x = wev->s.pos.x;
656         pos.y = wev->s.pos.y;
657         gcnv_abs(bchan->gid, &pos);
658         err = bchan_residmenu_select(&bchan->residmenu, pos);
659         if (err == BCHAN_RESIDMENU_SELECT_PUSHTRAY) {
660                 size = datlayout_idtotraytextdata(bchan->layout, id, id_len, NULL, 0);
661                 data = malloc(size);
662                 if (data == NULL) {
663                         return;
664                 }
665                 datlayout_idtotraytextdata(bchan->layout, id, id_len, data, size);
666                 bchan_pushstringtotray((TC*)data, size/2);
667                 free(data);
668         }
669 }
670
671 LOCAL VOID bchan_butdn(VP arg, WEVENT *wev)
672 {
673         bchan_t *bchan = (bchan_t*)arg;
674         W fnd, event_type, type, len, dx, dy, err, size, resindex;
675         WID wid_butup;
676         GID gid;
677         RECT r, r0;
678         UB *start;
679         PNT p1, pos;
680         TR_VOBJREC vrec;
681         TRAYREC tr_rec;
682         WEVENT paste_ev;
683         SEL_RGN sel;
684
685         /* TODO: change to same as bchanl's commonwindow */
686         switch (wchk_dck(wev->s.time)) {
687         case    W_CLICK:
688                 fnd = datdraw_findaction(bchan->draw, wev->s.pos, &r, &type, &start, &len, &resindex);
689                 if (fnd == 0) {
690                         return;
691                 }
692                 if (type != DATDRAW_FINDACTION_TYPE_ANCHOR) {
693                         return;
694                 }
695                 bchan_scrollbyahcnor(bchan, start, len);
696                 return;
697         case    W_DCLICK:
698         case    W_QPRESS:
699         default:
700                 return;
701         case    W_PRESS:
702         }
703
704         fnd = datdraw_findaction(bchan->draw, wev->s.pos, &r, &type, &start, &len, &resindex);
705         if (fnd == 0) {
706                 return;
707         }
708         if (type == DATDRAW_FINDACTION_TYPE_NUMBER) {
709                 bchan_butdn_pressnumber(bchan, wev, resindex);
710                 return;
711         }
712         if (type == DATDRAW_FINDACTION_TYPE_RESID) {
713                 bchan_butdn_pressresheaderid(bchan, wev, resindex);
714                 return;
715         }
716         if (type != DATDRAW_FINDACTION_TYPE_URL) {
717                 return;
718         }
719
720         gid = wsta_drg(bchan->wid, 0);
721         if (gid < 0) {
722                 DP_ER("wsta_drg error:", gid);
723                 return;
724         }
725
726         gget_fra(gid, &r0);
727         gset_vis(gid, r0);
728
729         dx = r.c.left - wev->s.pos.x;
730         dy = r.c.top - wev->s.pos.y;
731
732         p1 = wev->s.pos;
733         sel.sts = 0;
734         sel.rgn.r.c.left = r.c.left;
735         sel.rgn.r.c.top = r.c.top;
736         sel.rgn.r.c.right = r.c.right;
737         sel.rgn.r.c.bottom = r.c.bottom;
738         adsp_sel(gid, &sel, 1);
739
740         gset_ptr(PS_GRIP, NULL, -1, -1);
741         for (;;) {
742                 event_type = wget_drg(&pos, wev);
743                 if (event_type == EV_BUTUP) {
744                         wid_butup = wev->s.wid;
745                         break;
746                 }
747                 if (event_type != EV_NULL) {
748                         continue;
749                 }
750                 if ((pos.x == p1.x)&&(pos.y == p1.y)) {
751                         continue;
752                 }
753                 adsp_sel(gid, &sel, 0);
754                 sel.rgn.r.c.left += pos.x - p1.x;
755                 sel.rgn.r.c.top += pos.y - p1.y;
756                 sel.rgn.r.c.right += pos.x - p1.x;
757                 sel.rgn.r.c.bottom += pos.y - p1.y;
758                 adsp_sel(gid, &sel, 1);
759                 p1 = pos;
760         }
761         gset_ptr(PS_SELECT, NULL, -1, -1);
762         adsp_sel(gid, &sel, 0);
763         wend_drg();
764
765         /* BUTUP on self window or no window or system message panel */
766         if ((wid_butup == bchan->wid)||(wid_butup == 0)||(wid_butup == -1)) {
767                 return;
768         }
769
770         err = oget_vob(-wid_butup, &vrec.vlnk, NULL, 0, &size);
771         if (err < 0) {
772                 return;
773         }
774
775         err = bchan_createvobj(bchan, start, len, &vrec.vseg, (LINK*)&vrec.vlnk);
776         if (err < 0) {
777                 DP_ER("bchan_createvobj error", err);
778                 return;
779         }
780         if (err == BCHAN_CREATEVOBJ_CANCELED) {
781                 DP(("canceled\n"));
782                 return;
783         }
784
785         tr_rec.id = TR_VOBJ;
786         tr_rec.len = sizeof(TR_VOBJREC);
787         tr_rec.dt = (B*)&vrec;
788         err = tset_dat(&tr_rec, 1);
789         if (err < 0) {
790                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
791                 if (err < 0) {
792                         DP_ER("error del_fil:", err);
793                 }
794                 return;
795         }
796
797         paste_ev.r.type = EV_REQUEST;
798         paste_ev.r.r.p.rightbot.x = wev->s.pos.x + dx;
799         paste_ev.r.r.p.rightbot.y = wev->s.pos.y + dy;
800         paste_ev.r.cmd = W_PASTE;
801         paste_ev.r.wid = wid_butup;
802         err = wsnd_evt(&paste_ev);
803         if (err < 0) {
804                 tset_dat(NULL, 0);
805                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
806                 if (err < 0) {
807                         DP_ER("error del_fil:", err);
808                 }
809                 return;
810         }
811         err = wwai_rsp(NULL, W_PASTE, 60000);
812         if (err != W_ACK) {
813                 tset_dat(NULL, 0);
814                 err = del_fil(NULL, (LINK*)&vrec.vlnk, 0);
815                 if (err < 0) {
816                         DP_ER("error del_fil:", err);
817                 }
818         }
819
820         wswi_wnd(wid_butup, NULL);
821
822         /* temporary fix. to fix canceling layout. */
823         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_UPDATE);
824 }
825
826 LOCAL W bchan_paste(VP arg, WEVENT *wev)
827 {
828         bchan_t *bchan = (bchan_t*)arg;
829         W err;
830         postresdata_t *post = NULL;
831
832         err = poptray_gettraydata(&post);
833         if (err < 0) {
834                 return 1; /* NACK */
835         }
836
837         wev->r.r.p.rightbot.x = 0x8000;
838         wev->r.r.p.rightbot.y = 0x8000;
839
840         if (post != NULL) {
841                 if (bchan->resdata != NULL) {
842                         postresdata_delete(bchan->resdata);
843                 }
844                 bchan->resdata = post;
845                 cfrmwindow_setpostresdata(bchan->confirm, post);
846                 bchan->request_confirm_open = True;
847         }
848
849         return 0; /* ACK */
850 }
851
852 LOCAL VOID bchan_recieveclose(VP arg, W send)
853 {
854         bchan_t *bchan = (bchan_t*)arg;
855         TC *dmsg = NULL;
856         W dmsg_len, err;
857
858         DP(("bchan_recieveclose = %d\n", send));
859         if (send == 1) {
860                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_BUSY);
861                 err = ressubmit_respost(bchan->submit, bchan->resdata, &dmsg, &dmsg_len);
862                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
863                 switch (err) {
864                 case RESSUBMIT_RESPOST_SUCCEED:
865                         pdsp_msg(bchan->hmistate.msg_postsucceed);
866                         break;
867                 case RESSUBMIT_RESPOST_DENIED:
868                         bchan_hmistate_display_postdenied(&bchan->hmistate, dmsg, dmsg_len);
869                         break;
870                 case RESSUBMIT_RESPOST_ERROR_CLIENT:
871                 case RESSUBMIT_RESPOST_ERROR_STATUS:
872                 case RESSUBMIT_RESPOST_ERROR_CONTENT:
873                 default:
874                         pdsp_msg(bchan->hmistate.msg_posterror);
875                         break;
876                 }
877                 if (dmsg != NULL) {
878                         free(dmsg);
879                 }
880         }
881 }
882
883 LOCAL VOID bchan_hmistate_initialize(bchan_hmistate_t *hmistate)
884 {
885         W err;
886
887         hmistate->ptr = PS_SELECT;
888
889         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_RETRIEVING, (void**)&hmistate->msg_retrieving);
890         if (err < 0) {
891                 DP_ER("dget_dtp: message retrieving error", err);
892                 hmistate->msg_retrieving = NULL;
893         }
894         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_NOTMODIFIED, (void**)&hmistate->msg_notmodified);
895         if (err < 0) {
896                 DP_ER("dget_dtp: message not modified error", err);
897                 hmistate->msg_notmodified = NULL;
898         }
899         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_NONAUTHORITATIVE, (void**)&hmistate->msg_nonauthoritative);
900         if (err < 0) {
901                 DP_ER("dget_dtp: message non-authoritative error", err);
902                 hmistate->msg_nonauthoritative = NULL;
903         }
904         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_POSTSUCCEED, (void**)&hmistate->msg_postsucceed);
905         if (err < 0) {
906                 DP_ER("dget_dtp: message post succeed error", err);
907                 hmistate->msg_postsucceed = NULL;
908         }
909         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_POSTDENIED, (void**)&hmistate->msg_postdenied);
910         if (err < 0) {
911                 DP_ER("dget_dtp: message post denied error", err);
912                 hmistate->msg_postdenied = NULL;
913         }
914         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_POSTERROR, (void**)&hmistate->msg_posterror);
915         if (err < 0) {
916                 DP_ER("dget_dtp: message post error error", err);
917                 hmistate->msg_posterror = NULL;
918         }
919         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_NETWORKERROR, (void**)&hmistate->msg_networkerror);
920         if (err < 0) {
921                 DP_ER("dget_dtp: message network error error", err);
922                 hmistate->msg_networkerror = NULL;
923         }
924         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_NOTFOUND, (void**)&hmistate->msg_notfound);
925         if (err < 0) {
926                 DP_ER("dget_dtp: message notfound error", err);
927                 hmistate->msg_notfound = NULL;
928         }
929         err = dget_dtp(TEXT_DATA, BCHAN_DBX_MSGTEXT_CANTRETRIEVE, (void**)&hmistate->msg_cantretrieve);
930         if (err < 0) {
931                 DP_ER("dget_dtp: message cantretrieve error", err);
932                 hmistate->msg_cantretrieve = NULL;
933         }
934 }
935
936 LOCAL W bchan_initialize(bchan_t *bchan, VID vid, WID wid, W exectype)
937 {
938         GID gid;
939         datcache_t *cache;
940         datparser_t *parser;
941         datlayout_t *layout;
942         datdraw_t *draw;
943         datwindow_t *window;
944         datretriever_t *retriever;
945         ressubmit_t *submit;
946         cfrmwindow_t *confirm;
947         MENUITEM *mnitem_dbx, *mnitem;
948         MNID mnid;
949         static  RECT    r0 = {{200, 80, 500+7, 230+30}};
950         RECT w_work;
951         W len, err;
952
953         gid = wget_gid(wid);
954
955         cache = datcache_new(vid);
956         if (cache == NULL) {
957                 DP_ER("datcache_new error", 0);
958                 goto error_cache;
959         }
960         parser = datparser_new(cache);
961         if (parser == NULL) {
962                 DP_ER("datparser_new error", 0);
963                 goto error_parser;
964         }
965         layout = datlayout_new(gid);
966         if (layout == NULL) {
967                 DP_ER("datlayout_new error", 0);
968                 goto error_layout;
969         }
970         draw = datdraw_new(layout);
971         if (draw == NULL) {
972                 DP_ER("datdraw_new error", 0);
973                 goto error_draw;
974         }
975         window = datwindow_new(wid, bchan_scroll, bchan_draw, bchan_resize, bchan_close, bchan_butdn, bchan_paste, bchan);
976         if (window == NULL) {
977                 DP_ER("datwindow_new error", 0);
978                 goto error_window;
979         }
980         retriever = datretriever_new(cache);
981         if (retriever == NULL) {
982                 DP_ER("datretriever_new error", 0);
983                 goto error_retriever;
984         }
985         submit = ressubmit_new(cache);
986         if (submit == NULL) {
987                 DP_ER("ressubmit_new error", 0);
988                 goto error_submit;
989         }
990         confirm = cfrmwindow_new(&r0, wid, bchan_recieveclose, bchan, BCHAN_DBX_TEXT_CONFIRM_TITLE, BCHAN_DBX_MS_CONFIRM_POST, BCHAN_DBX_MS_CONFIRM_CANCEL);
991         if (confirm == NULL) {
992                 DP_ER("dfrmwindow_new error", 0);
993                 goto error_confirm;
994         }
995         err = dget_dtp(8, BCHAN_DBX_MENU_TEST, (void**)&mnitem_dbx);
996         if (err < 0) {
997                 DP_ER("dget_dtp error:", err);
998                 goto error_dget_dtp;
999         }
1000         len = dget_siz((B*)mnitem_dbx);
1001         mnitem = malloc(len);
1002         if (mnitem == NULL) {
1003                 DP_ER("mallod error", err);
1004                 goto error_mnitem;
1005         }
1006         memcpy(mnitem, mnitem_dbx, len);
1007         mnid = mcre_men(BCHAN_MENU_WINDOW+2, mnitem, NULL);
1008         if (mnid < 0) {
1009                 DP_ER("mcre_men error", mnid);
1010                 goto error_mcre_men;
1011         }
1012         err = bchan_resnumbermenu_initialize(&bchan->resnumbermenu, BCHAN_DBX_GMENU_RESNUMBER);
1013         if (err < 0) {
1014                 DP_ER("bchan_resnumbermenu_initialize", err);
1015                 goto error_resnumbermenu_initialize;
1016         }
1017         err = bchan_residmenu_initialize(&bchan->residmenu, BCHAN_DBX_GMENU_RESID);
1018         if (err < 0) {
1019                 DP_ER("bchan_residmenu_initialize", err);
1020                 goto error_residmenu_initialize;
1021         }
1022
1023         bchan_hmistate_initialize(&bchan->hmistate);
1024
1025         wget_wrk(wid, &w_work);
1026         datdraw_setviewrect(draw, 0, 0, w_work.c.right, w_work.c.bottom);
1027         datwindow_setworkrect(window, 0, 0, w_work.c.right, w_work.c.bottom);
1028
1029         if (exectype == EXECREQ) {
1030                 osta_prc(vid, wid);
1031         }
1032
1033         bchan->wid = wid;
1034         bchan->gid = gid;
1035         bchan->taskid = -1;
1036         bchan->mbfid = -1;
1037         bchan->vid = vid;
1038         bchan->exectype = exectype;
1039         bchan->request_confirm_open = False;
1040         bchan->cache = cache;
1041         bchan->parser = parser;
1042         bchan->layout = layout;
1043         bchan->draw = draw;
1044         bchan->window = window;
1045         bchan->retriever = retriever;
1046         bchan->submit = submit;
1047         bchan->confirm = confirm;
1048         bchan->resdata = NULL;
1049         bchan->mnitem = mnitem;
1050         bchan->mnid = mnid;
1051
1052         return 0;
1053
1054 error_residmenu_initialize:
1055         bchan_resnumbermenu_finalize(&bchan->resnumbermenu);
1056 error_resnumbermenu_initialize:
1057         mdel_men(mnid);
1058 error_mcre_men:
1059         free(mnitem);
1060 error_mnitem:
1061 error_dget_dtp:
1062         cfrmwindow_delete(confirm);
1063 error_confirm:
1064         ressubmit_delete(submit);
1065 error_submit:
1066         datretriever_delete(retriever);
1067 error_retriever:
1068         datwindow_delete(window);
1069 error_window:
1070         datdraw_delete(draw);
1071 error_draw:
1072         datlayout_delete(layout);
1073 error_layout:
1074         datparser_delete(parser);
1075 error_parser:
1076         datcache_delete(cache);
1077 error_cache:
1078         return -1; /* TODO */
1079 }
1080
1081 #define BCHAN_LAYOUT_MAXBLOCKING 20
1082
1083 LOCAL VOID bchan_relayout(bchan_t *bchan)
1084 {
1085         datparser_res_t *res = NULL;
1086         RECT w_work;
1087         W i, err, l, t, r, b;
1088         TC *title;
1089
1090         datlayout_clear(bchan->layout);
1091         datparser_clear(bchan->parser);
1092
1093         for (i=0;;i++) {
1094                 if (i >= BCHAN_LAYOUT_MAXBLOCKING) {
1095                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_UPDATE);
1096                         break;
1097                 }
1098
1099                 err = datparser_getnextres(bchan->parser, &res);
1100                 if (err != 1) {
1101                         break;
1102                 }
1103                 if (res == NULL) {
1104                         break;
1105                 }
1106                 datlayout_appendres(bchan->layout, res);
1107         }
1108
1109         wget_wrk(bchan->wid, &w_work);
1110
1111         datlayout_getdrawrect(bchan->layout, &l, &t, &r, &b);
1112         datwindow_setdrawrect(bchan->window, l, t, r, b);
1113
1114         title = datlayout_gettitle(bchan->layout);
1115         wset_tit(bchan->wid, -1, title, 0);
1116
1117         wreq_dsp(bchan->wid);
1118 }
1119
1120 LOCAL VOID bchan_update(bchan_t *bchan)
1121 {
1122         datparser_res_t *res = NULL;
1123         RECT w_work;
1124         W i, err, l, t, r, b;
1125
1126         for (i=0;;i++) {
1127                 if (i >= BCHAN_LAYOUT_MAXBLOCKING) {
1128                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_UPDATE);
1129                         break;
1130                 }
1131
1132                 err = datparser_getnextres(bchan->parser, &res);
1133                 if (err != 1) {
1134                         break;
1135                 }
1136                 if (res == NULL) {
1137                         break;
1138                 }
1139                 datlayout_appendres(bchan->layout, res);
1140         }
1141
1142         wget_wrk(bchan->wid, &w_work);
1143
1144         datlayout_getdrawrect(bchan->layout, &l, &t, &r, &b);
1145         datwindow_setdrawrect(bchan->window, l, t, r, b);
1146
1147         wreq_dsp(bchan->wid);
1148 }
1149
1150 LOCAL VOID bchan_retriever_task(W arg)
1151 {
1152         bchan_t *bchan;
1153         datretriever_t *retr;
1154         W msg,err;
1155
1156         bchan = (bchan_t*)arg;
1157         retr = bchan->retriever;
1158
1159         for (;;) {
1160                 DP(("before rcv_mbf %d\n", bchan->mbfid));
1161                 err = rcv_mbf(bchan->mbfid, (VP)&msg, T_FOREVER);
1162                 DP_ER("rcv_mbf", err);
1163                 if (err != 4) {
1164                         continue;
1165                 }
1166
1167                 err = datretriever_request(retr);
1168
1169                 switch (err) {
1170                 case DATRETRIEVER_REQUEST_ALLRELOAD:
1171                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_RELAYOUT);
1172                         break;
1173                 case DATRETRIEVER_REQUEST_PARTIAL_CONTENT:
1174                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_UPDATE);
1175                         break;
1176                 case DATRETRIEVER_REQUEST_NOT_MODIFIED:
1177                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_NOTMODIFIED);
1178                         break;
1179                 case DATRETRIEVER_REQUEST_NON_AUTHORITATIVE:
1180                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_NONAUTHORITATIVE);
1181                         break;
1182                 case DATRETRIEVER_REQUEST_NOT_FOUND:
1183                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_NOTFOUND);
1184                         break;
1185                 case DATRETRIEVER_REQUEST_UNEXPECTED:
1186                 default:
1187                         DP_ER("datretreiver_request error:",err);
1188                         DATRETRIEVER_DP(retr);
1189                         req_tmg(0, BCHAN_MESSAGE_RETRIEVER_ERROR);
1190                         break;
1191                 }
1192         }
1193
1194         ext_tsk();
1195 }
1196
1197 LOCAL W bchan_prepare_network(bchan_t *bchan)
1198 {
1199         if (bchan->retriever == NULL) {
1200                 return 0;
1201         }
1202         if (datretriever_isenablenetwork(bchan->retriever) == False) {
1203                 return 0;
1204         }
1205
1206         bchan->mbfid = cre_mbf(sizeof(W), sizeof(W), DELEXIT);
1207         if (bchan->mbfid < 0) {
1208                 DP_ER("cre_mbf error:", bchan->mbfid);
1209                 return -1;
1210         }
1211         bchan->taskid = cre_tsk(bchan_retriever_task, -1, (W)bchan);
1212         if (bchan->taskid < 0) {
1213                 del_mbf(bchan->mbfid);
1214                 bchan->mbfid = -1;
1215                 DP_ER("cre_tsk error:", bchan->taskid);
1216                 return -1;
1217         }
1218
1219         return 0;
1220 }
1221
1222 LOCAL W bchan_networkrequest(bchan_t *bchan)
1223 {
1224         W msg = 1, err;
1225         static UW lastrequest = 0;
1226         UW etime;
1227
1228         if (datretriever_isenablenetwork(bchan->retriever) == False) {
1229                 pdsp_msg(bchan->hmistate.msg_cantretrieve);
1230                 return 0;
1231         }
1232         if (bchan->mbfid < 0) {
1233                 return 0;
1234         }
1235
1236         err = get_etm(&etime);
1237         if (err < 0) {
1238                 DP_ER("get_etm error:", err);
1239                 return err;
1240         }
1241         if (lastrequest + 10000 > etime) {
1242                 return 0;
1243         }
1244         lastrequest = etime;
1245
1246         err = snd_mbf(bchan->mbfid, &msg, sizeof(W), T_FOREVER);
1247         if (err < 0) {
1248                 DP_ER("snd_mbf error:", err);
1249                 return err;
1250         }
1251
1252         bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_BUSY);
1253         pdsp_msg(bchan->hmistate.msg_retrieving);
1254
1255         return 0;
1256 }
1257
1258 LOCAL VOID keydwn(bchan_t *bchan, UH keycode, TC ch)
1259 {
1260         W l,t,r,b,l1,t1,r1,b1,scr;
1261
1262         switch (ch) {
1263         case KC_CC_U:
1264                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1265                 if (t < 16) {
1266                         scr = -t;
1267                 } else {
1268                         scr = -16;
1269                 }
1270                 datwindow_scrollbyvalue(bchan->window, 0, scr);
1271                 break;
1272         case KC_CC_D:
1273                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1274                 datlayout_getdrawrect(bchan->layout, &l1, &t1, &r1, &b1);
1275                 if (b + 16 > b1) {
1276                         scr = b1 - b;
1277                 } else {
1278                         scr = 16;
1279                 }
1280                 if (scr > 0) {
1281                         datwindow_scrollbyvalue(bchan->window, 0, scr);
1282                 }
1283                 break;
1284         case KC_CC_R:
1285                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1286                 datlayout_getdrawrect(bchan->layout, &l1, &t1, &r1, &b1);
1287                 if (r + 16 > r1) {
1288                         scr = r1 - r;
1289                 } else {
1290                         scr = 16;
1291                 }
1292                 if (scr > 0) {
1293                         datwindow_scrollbyvalue(bchan->window, scr, 0);
1294                 }
1295                 break;
1296         case KC_CC_L:
1297                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1298                 if (l < 16) {
1299                         scr = -l;
1300                 } else {
1301                         scr = -16;
1302                 }
1303                 datwindow_scrollbyvalue(bchan->window, scr, 0);
1304                 break;
1305         case KC_PG_U:
1306                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1307                 if (t < b - t) {
1308                         scr = -t;
1309                 } else {
1310                         scr = - (b - t);
1311                 }
1312                 datwindow_scrollbyvalue(bchan->window, 0, scr);
1313                 break;
1314         case KC_PG_D:
1315                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1316                 datlayout_getdrawrect(bchan->layout, &l1, &t1, &r1, &b1);
1317                 if (b + (b - t) > b1) {
1318                         scr = b1 - b;
1319                 } else {
1320                         scr = (b - t);
1321                 }
1322                 if (scr > 0) {
1323                         datwindow_scrollbyvalue(bchan->window, 0, scr);
1324                 }
1325                 break;
1326         case KC_PG_R:
1327                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1328                 datlayout_getdrawrect(bchan->layout, &l1, &t1, &r1, &b1);
1329                 if (r + (r - l) > r1) {
1330                         scr = r1 - r;
1331                 } else {
1332                         scr = (r - l);
1333                 }
1334                 if (scr > 0) {
1335                         datwindow_scrollbyvalue(bchan->window, scr, 0);
1336                 }
1337                 break;
1338         case KC_PG_L:
1339                 datdraw_getviewrect(bchan->draw, &l, &t, &r, &b);
1340                 if (l < r - l) {
1341                         scr = -l;
1342                 } else {
1343                         scr = - (r - l);
1344                 }
1345                 datwindow_scrollbyvalue(bchan->window, scr, 0);
1346                 break;
1347         case KC_PF5:
1348                 bchan_networkrequest(bchan);
1349                 break;
1350         }
1351 }
1352
1353 LOCAL VOID bchan_setupmenu(bchan_t *bchan)
1354 {
1355         TC *str;
1356
1357         /* [Áàºî] -> [¥¹¥ì¥¿¥¤¤ò¥È¥ì¡¼¤ËÊ£¼Ì] */
1358         str = datlayout_gettitle(bchan->layout);
1359         if (str == NULL) {
1360                 mchg_atr(bchan->mnid, (2 << 8)|1, M_INACT);
1361         } else {
1362                 mchg_atr(bchan->mnid, (2 << 8)|1, M_ACT);
1363         }
1364
1365         /* [ɽ¼¨] -> [¥¹¥ì¥Ã¥É¾ðÊó¤òɽ¼¨] */
1366         /* [ÊÔ½¸] -> [¥¹¥ì¥Ã¥É£Õ£Ò£Ì¤ò¥È¥ì¡¼¤ËÊ£¼Ì] */
1367         /* [Áàºî] -> [¥¹¥ì¥Ã¥É¼èÆÀ] */
1368         if (datretriever_isenablenetwork(bchan->retriever) == False) {
1369                 mchg_atr(bchan->mnid, (1 << 8)|2, M_INACT);
1370                 mchg_atr(bchan->mnid, (2 << 8)|2, M_INACT);
1371                 mchg_atr(bchan->mnid, (3 << 8)|1, M_INACT);
1372         } else {
1373                 mchg_atr(bchan->mnid, (1 << 8)|2, M_ACT);
1374                 mchg_atr(bchan->mnid, (2 << 8)|2, M_ACT);
1375                 mchg_atr(bchan->mnid, (3 << 8)|1, M_ACT);
1376         }
1377
1378         wget_dmn(&(bchan->mnitem[BCHAN_MENU_WINDOW].ptr));
1379         mset_itm(bchan->mnid, BCHAN_MENU_WINDOW, bchan->mnitem+BCHAN_MENU_WINDOW);
1380         oget_men(0, NULL, &(bchan->mnitem[BCHAN_MENU_WINDOW+1].ptr), NULL, NULL);
1381         mset_itm(bchan->mnid, BCHAN_MENU_WINDOW+1, bchan->mnitem+BCHAN_MENU_WINDOW+1);
1382 }
1383
1384 LOCAL VOID bchan_selectmenu(bchan_t *bchan, W i)
1385 {
1386         UB *host, *board, *thread;
1387         W host_len, board_len, thread_len;
1388
1389         switch(i >> 8) {
1390         case 0: /* [½ªÎ»] */
1391                 killme(bchan);
1392                 break;
1393         case 1: /* [ɽ¼¨] */
1394                 switch(i & 0xff) {
1395                 case 1: /* [ºÆɽ¼¨] */
1396                         wreq_dsp(bchan->wid);
1397                         break;
1398                 case 2: /* [¥¹¥ì¥Ã¥É¾ðÊó¤òɽ¼¨] */
1399                         datcache_gethost(bchan->cache, &host, &host_len);
1400                         datcache_getborad(bchan->cache, &board, &board_len);
1401                         datcache_getthread(bchan->cache, &thread, &thread_len);
1402                         bchan_panels_threadinfo(host, host_len, board, board_len, thread, thread_len);
1403                         break;
1404                 }
1405                 break;
1406         case 2: /* [Áàºî] */
1407                 switch(i & 0xff) {
1408                 case 1: /* [¥¹¥ì¥¿¥¤¤ò¥È¥ì¡¼¤ËÊ£¼Ì] */
1409                         bchan_pushthreadtitle(bchan);
1410                         break;
1411                 case 2: /* [¥¹¥ì¥Ã¥É£Õ£Ò£Ì¤ò¥È¥ì¡¼¤ËÊ£¼Ì] */
1412                         bchan_pushthreadurl(bchan);
1413                         break;
1414                 }
1415                 break;
1416         case 3: /* [Áàºî] */
1417                 switch(i & 0xff) {
1418                 case 1: /* [¥¹¥ì¥Ã¥É¼èÆÀ] */
1419                         bchan_networkrequest(bchan);
1420                         break;
1421                 }
1422                 break;
1423         case BCHAN_MENU_WINDOW: /* [¥¦¥£¥ó¥É¥¦] */
1424                 wexe_dmn(i);
1425                 break;
1426         case BCHAN_MENU_WINDOW+1: /* [¾®Êª] */
1427             oexe_apg(0, i);
1428                 break;
1429         }
1430         return;
1431 }
1432
1433 LOCAL VOID bchan_popupmenu(bchan_t *bchan, PNT pos)
1434 {
1435         W       i;
1436
1437         bchan_setupmenu(bchan);
1438         gset_ptr(PS_SELECT, NULL, -1, -1);
1439         i = msel_men(bchan->mnid, pos);
1440         if (i > 0) {
1441                 bchan_selectmenu(bchan, i);
1442         }
1443 }
1444
1445 LOCAL VOID receive_message(bchan_t *bchan)
1446 {
1447         MESSAGE msg;
1448         W code, err;
1449
1450     err = rcv_msg(MM_ALL, &msg, sizeof(MESSAGE), WAIT|NOCLR);
1451         if (err >= 0) {
1452                 if (msg.msg_type == MS_TMOUT) { /* should be use other type? */
1453                         code = msg.msg_body.TMOUT.code;
1454                         switch (code) {
1455                         case BCHAN_MESSAGE_RETRIEVER_UPDATE:
1456                                 bchan_update(bchan);
1457                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1458                                 pdsp_msg(NULL);
1459                                 break;
1460                         case BCHAN_MESSAGE_RETRIEVER_RELAYOUT:
1461                                 bchan_relayout(bchan);
1462                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1463                                 pdsp_msg(NULL);
1464                                 break;
1465                         case BCHAN_MESSAGE_RETRIEVER_NOTMODIFIED:
1466                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1467                                 pdsp_msg(bchan->hmistate.msg_notmodified);
1468                                 break;
1469                         case BCHAN_MESSAGE_RETRIEVER_NONAUTHORITATIVE:
1470                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1471                                 pdsp_msg(bchan->hmistate.msg_nonauthoritative);
1472                                 break;
1473                         case BCHAN_MESSAGE_RETRIEVER_NOTFOUND:
1474                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1475                                 pdsp_msg(bchan->hmistate.msg_notfound);
1476                                 break;
1477                         case BCHAN_MESSAGE_RETRIEVER_ERROR:
1478                                 bchan_hmistate_updateptrstyle(&bchan->hmistate, PS_SELECT);
1479                                 pdsp_msg(bchan->hmistate.msg_networkerror);
1480                                 break;
1481                         }
1482                 }
1483         }
1484         clr_msg(MM_ALL, MM_ALL);
1485 }
1486
1487 typedef struct _arg {
1488         W ac;
1489         TC **argv;
1490 } CLI_arg;
1491
1492 LOCAL    CLI_arg   MESSAGEtoargv(const MESSAGE *src)
1493 {
1494         W len,i,ac;
1495         TC *str;
1496         TC **argv;
1497         CLI_arg ret;
1498
1499         len = src->msg_size / sizeof(TC);
1500         str = (TC*)(src->msg_body.ANYMSG.msg_str);
1501         ac = 0;
1502         for(i=0;i<len;i++){
1503                 if(str[i] == TK_KSP){
1504                         str[i] = TNULL;
1505                         continue;
1506                 }
1507                 ac++;
1508                 for(;i<len;i++){
1509                         if(str[i] == TK_KSP){
1510                                 i--;
1511                                 break;
1512                         }
1513                 }
1514         }
1515
1516         argv = (TC**)malloc(sizeof(TC*)*ac);
1517
1518         ac = 0;
1519         for(i=0;i<len;i++){
1520                 if(str[i] == TNULL){
1521                         str[i] = TNULL;
1522                         continue;
1523                 }
1524                 argv[ac++] = str+i;
1525                 for(;i<len;i++){
1526                         if(str[i] == TNULL){
1527                                 i--;
1528                                 break;
1529                         }
1530                 }
1531         }
1532
1533         ret.ac = ac;
1534         ret.argv = argv;
1535
1536         return ret;
1537 }
1538
1539 EXPORT  W       MAIN(MESSAGE *msg)
1540 {
1541         static  RECT    r0 = {{100, 100, 650+7, 400+30}};
1542         static  TC      tit0[21];
1543         static  PAT     pat0 = {{
1544                 0,
1545                 16, 16,
1546                 0x10efefef,
1547                 0x10efefef,
1548                 FILL100
1549         }};
1550         W       i, err, size;
1551         WID wid;
1552         VID vid;
1553         LINK lnk, dbx;
1554         CLI_arg arg;
1555         bchan_t bchan;
1556         datwindow_t *window;
1557         VOBJSEG vseg = {
1558                 {{0,0,100,20}},
1559                 16, 16,
1560                 0x10000000, 0x10000000, 0x10FFFFFF, 0x10FFFFFF,
1561                 0
1562         };
1563
1564         err = dopn_dat(NULL);
1565         if (err < 0) {
1566                 ext_prc(0);
1567         }
1568
1569         switch (msg->msg_type) {
1570         case 0: /* CLI */
1571                 arg = MESSAGEtoargv(msg);
1572                 if (arg.ac <= 1) {
1573                         ext_prc(0);
1574                 }
1575                 err = get_lnk(arg.argv[1], &lnk, F_NORM);
1576                 if (err < 0) {
1577                         DP_ER("get_lnk error", err);
1578                         ext_prc(0);
1579                 }
1580                 vid = oreg_vob((VLINK*)&lnk, (VP)&vseg, -1, V_NODISP);
1581                 if (vid < 0) {
1582                         DP_ER("error oreq_vob", vid);
1583                         ext_prc(0);
1584                 }
1585                 err = get_lnk((TC[]){TK_b, TK_c, TK_h, TK_a, TK_n, TK_PROD, TK_d, TK_b, TK_x,TNULL}, &dbx, F_NORM);
1586                 if (err < 0) {
1587                         DP_ER("get_lnk error", err);
1588                         ext_prc(0);
1589                 }
1590                 err = dopn_dat(&dbx);
1591                 if (err < 0) {
1592                         DP_ER("dopn_dat error", err);
1593                         ext_prc(0);
1594                 }
1595                 fil_sts(&lnk, tit0, NULL, NULL);
1596                 break;
1597         case DISPREQ:
1598                 oend_req(((M_DISPREQ*)msg)->vid, -1);
1599                 ext_prc(0);
1600                 break;
1601         case PASTEREQ:
1602                 oend_req(((M_PASTEREQ*)msg)->vid, -1);
1603                 ext_prc(0);
1604                 break;
1605         case EXECREQ:
1606                 if ((((M_EXECREQ*)msg)->mode & 2) != 0) {
1607                         ext_prc(0);
1608                 }
1609                 err = dopn_dat(&((M_EXECREQ*)msg)->self);
1610                 if (err < 0) {
1611                         ext_prc(0);
1612                 }
1613                 fil_sts(&((M_EXECREQ*)msg)->lnk, tit0, NULL, NULL);
1614                 vid = ((M_EXECREQ*)msg)->vid;
1615                 break;
1616         default:
1617                 ext_prc(0);
1618                 break;
1619         }
1620
1621         wid = wopn_wnd(WA_SIZE|WA_HHDL|WA_VHDL|WA_BBAR|WA_RBAR, 0, &r0, NULL, 1, tit0, &pat0, NULL);
1622         if (wid < 0) {
1623                 ext_prc(0);
1624         }
1625         
1626         err = bchan_initialize(&bchan, vid, wid, msg->msg_type);
1627         if (err < 0) {
1628                 DP_ER("bchan_initialize error", err);
1629                 ext_prc(0);
1630         }
1631         window = bchan.window;
1632
1633         err = bchan_prepare_network(&bchan);
1634         if (err < 0) {
1635                 DP_ER("bchan_prepare_network error:", err);
1636                 killme(&bchan);
1637         }
1638
1639         size = datcache_datasize(bchan.cache);
1640         if ((msg->msg_type == EXECREQ)&&(size == 0)) {
1641                 bchan_networkrequest(&bchan);
1642         } else {
1643                 req_tmg(0, BCHAN_MESSAGE_RETRIEVER_RELAYOUT);
1644         }
1645
1646         wreq_dsp(bchan.wid);
1647
1648         /*¥¤¥Ù¥ó¥È¥ë¡¼¥×*/
1649         for (;;) {
1650                 wget_evt(&wev0, WAIT);
1651                 switch (wev0.s.type) {
1652                         case    EV_NULL:
1653                                 if ((wev0.s.wid != wid)
1654                                         &&(cfrmwindow_compairwid(bchan.confirm, wev0.s.wid) == False)) {
1655                                         gset_ptr(bchan.hmistate.ptr, NULL, -1, -1);
1656                                         break;          /*¥¦¥£¥ó¥É¥¦³°*/
1657                                 }
1658                                 if (wev0.s.cmd != W_WORK)
1659                                         break;          /*ºî¶ÈÎΰ賰*/
1660                                 if (wev0.s.stat & ES_CMD)
1661                                         break;  /*Ì¿Îᥭ¡¼¤¬²¡¤µ¤ì¤Æ¤¤¤ë*/
1662                                 gset_ptr(bchan.hmistate.ptr, NULL, -1, -1);
1663                                 break;
1664                         case    EV_REQUEST:
1665                                 if (wev0.g.wid == wid) {
1666                                         datwindow_weventrequest(window, &wev0);
1667                                 }
1668                                 if (cfrmwindow_compairwid(bchan.confirm, wev0.s.wid)) {
1669                                         cfrmwindow_weventrequest(bchan.confirm, &wev0);
1670                                 }
1671                                 break;
1672                         case    EV_RSWITCH:
1673                                 if (wev0.s.wid == wid) {
1674                                         datwindow_weventreswitch(window, &wev0);
1675                                         if (bchan.request_confirm_open == True) {
1676                                                 cfrmwindow_open(bchan.confirm);
1677                                                 bchan.request_confirm_open = False;
1678                                         }
1679                                 }
1680                                 if (cfrmwindow_compairwid(bchan.confirm, wev0.s.wid)) {
1681                                         cfrmwindow_weventreswitch(bchan.confirm, &wev0);
1682                                 }
1683                                 break;
1684                         case    EV_SWITCH:
1685                                 if (wev0.s.wid == wid) {
1686                                         datwindow_weventswitch(window, &wev0);
1687                                         if (bchan.request_confirm_open == True) {
1688                                                 cfrmwindow_open(bchan.confirm);
1689                                                 bchan.request_confirm_open = False;
1690                                         }
1691                                 }
1692                                 if (cfrmwindow_compairwid(bchan.confirm, wev0.s.wid)) {
1693                                         cfrmwindow_weventswitch(bchan.confirm, &wev0);
1694                                 }
1695                                 break;
1696                         case    EV_BUTDWN:
1697                                 if (wev0.g.wid == wid) {
1698                                         datwindow_weventbutdn(window, &wev0);
1699                                 }
1700                                 if (cfrmwindow_compairwid(bchan.confirm, wev0.s.wid)) {
1701                                         cfrmwindow_weventbutdn(bchan.confirm, &wev0);
1702                                 }
1703                                 break;
1704                         case    EV_KEYDWN:
1705                                 if (wev0.s.stat & ES_CMD) {     /*Ì¿Îᥭ¡¼*/
1706                                         bchan_setupmenu(&bchan);
1707                                         i = mfnd_key(bchan.mnid, wev0.e.data.key.code);
1708                                         if (i >= 0) {
1709                                                 bchan_selectmenu(&bchan, i);
1710                                                 break;
1711                                         }
1712                                 }
1713                         case    EV_AUTKEY:
1714                                 keydwn(&bchan, wev0.e.data.key.keytop, wev0.e.data.key.code);
1715                                 break;
1716                         case    EV_INACT:
1717                                 pdsp_msg(NULL);
1718                                 break;
1719                         case    EV_DEVICE:
1720                                 oprc_dev(&wev0.e, NULL, 0);
1721                                 break;
1722                         case    EV_MSG:
1723                                 receive_message(&bchan);
1724                                 break;
1725                         case    EV_MENU:
1726                                 bchan_popupmenu(&bchan, wev0.s.pos);
1727                                 break;
1728                 }
1729         }
1730
1731         return 0;
1732 }