OSDN Git Service

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