OSDN Git Service

disable press number action when NG by word.
[bbk/bchan.git] / src / render.c
1 /*
2  * render.c
3  *
4  * Copyright (c) 2010-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    "render.h"
28 #include    "parser.h"
29 #include    "layoutarray.h"
30 #include    "layoutstyle.h"
31 #include    "tadlib.h"
32
33 #include        <bstdio.h>
34 #include        <bstdlib.h>
35 #include        <tcode.h>
36 #include        <btron/btron.h>
37 #include        <btron/libapp.h>
38 #include        <btron/dp.h>
39
40 struct datrender_t_ {
41         GID target;
42         datlayoutstyle_t *style;
43         datlayoutarray_t *array;
44         W view_l, view_t, view_r, view_b;
45 };
46
47 LOCAL W datrender_entrydraw_drawbody(datlayout_res_t *entry, GID gid, W dh, W dv)
48 {
49         TC *str = entry->parser_res->body;
50         W len = entry->parser_res->body_len;
51         return tadlib_drawtext(str, len, gid, dh, dv);
52 }
53
54 LOCAL W datrender_entrydraw_drawname(datlayout_res_t *entry, GID gid, W dh, W dv)
55 {
56         TC *str = entry->parser_res->name;
57         W len = entry->parser_res->name_len;
58         return tadlib_drawtext(str, len, gid, dh, dv);
59 }
60
61 LOCAL W datrender_entrydraw_drawmail(datlayout_res_t *entry, GID gid, W dh, W dv)
62 {
63         TC *str = entry->parser_res->mail;
64         W len = entry->parser_res->mail_len;
65         return tadlib_drawtext(str, len, gid, dh, dv);
66 }
67
68 LOCAL W datrender_entrydraw_drawdateidbeid(datlayout_res_t *entry, GID gid, W dh, W dv)
69 {
70         TC *str;
71         W len, err;
72
73         if (entry->parser_res->dateinfo.date != NULL) {
74                 err = gset_chp(gid, 16, 0, 0);
75                 if (err < 0) {
76                         return err;
77                 }
78                 str = entry->parser_res->dateinfo.date;
79                 len = entry->parser_res->dateinfo.date_len;
80                 err = tadlib_drawtext(str, len, gid, dh, dv);
81                 if (err < 0) {
82                         return err;
83                 }
84         }
85         if (entry->parser_res->dateinfo.id != NULL) {
86                 err = gset_chp(gid, 16, 0, 0);
87                 if (err < 0) {
88                         return err;
89                 }
90                 str = entry->parser_res->dateinfo.id;
91                 len = entry->parser_res->dateinfo.id_len;
92                 err = tadlib_drawtext(str, len, gid, dh, dv);
93                 if (err < 0) {
94                         return err;
95                 }
96         }
97         if (entry->parser_res->dateinfo.beid != NULL) {
98                 err = gset_chp(gid, 16, 0, 0);
99                 if (err < 0) {
100                         return err;
101                 }
102                 str = entry->parser_res->dateinfo.beid;
103                 len = entry->parser_res->dateinfo.beid_len;
104                 err = tadlib_drawtext(str, len, gid, dh, dv);
105                 if (err < 0) {
106                         return err;
107                 }
108         }
109         return 0;
110 #if 0
111         TC *str = entry->parser_res->date;
112         W len = entry->parser_res->date_len;
113         return tadlib_drawtext(str, len, gid, dh, dv);
114 #endif
115 }
116
117 LOCAL W datrender_entrydraw_resnumber(datlayout_res_t *entry, W resnum, GID target)
118 {
119         W err,numstr_len;
120         TC numstr[10];
121
122         numstr_len = tadlib_UW_to_str(resnum, numstr, 10);
123         err = gdra_str(target, numstr, numstr_len, G_STORE);
124         if (err < 0) {
125                 return err;
126         }
127
128         return 0;
129 }
130
131 LOCAL int sectrect_tmp(RECT a, W left, W top, W right, W bottom)
132 {
133         return (a.c.left<right && left<a.c.right && a.c.top<bottom && top<a.c.bottom);
134 }
135
136 LOCAL W andrect_tmp(W *l_dest, W *t_dest, W *r_dest, W *b_dest, W l2, W t2, W r2, W b2)
137 {
138         if (!(*l_dest<r2 && l2<*r_dest && *t_dest<b2 && t2<*b_dest)) {
139                 *l_dest = 0;
140                 *t_dest = 0;
141                 *r_dest = 0;
142                 *b_dest = 0;
143                 return 0;
144         }
145
146         if (*l_dest < l2) {
147                 *l_dest = l2;
148         }
149         if (*t_dest < t2) {
150                 *t_dest = t2;
151         }
152         if (*r_dest > r2) {
153                 *r_dest = r2;
154         }
155         if (*b_dest > b2) {
156                 *b_dest = b2;
157         }
158
159         return 1;
160 }
161
162 LOCAL W datrender_fillrect(datrender_t *render, RECT *rect, W l, W t, W r, W b)
163 {
164         static  PAT     pat0 = {{
165                 0,
166                 16, 16,
167                 0x10000000,
168                 0x10000000,
169                 FILL100
170         }};
171         W err, sect, dh, dv;
172         RECT border;
173
174         sect = andrect_tmp(&l, &t, &r, &b, render->view_l, render->view_t, render->view_r, render->view_b);
175         if (sect == 0) {
176                 return 0;
177         }
178
179         dh = render->view_l;
180         dv = render->view_t;
181
182         sect = sectrect_tmp(*rect, l - dh, t - dv, r - dh, b - dv);
183         if (sect == 0) {
184                 return 0;
185         }
186
187         border.c.left = l - dh;
188         border.c.top = t - dv;
189         border.c.right = r - dh;
190         border.c.bottom = b - dv;
191
192         err = gfil_rec(render->target, border, &pat0, 0, G_STORE);
193         if (err < 0) {
194                 return err;
195         }
196
197         return 0;
198 }
199
200 LOCAL W datlayout_box_drawleftborder(datlayout_box_t *box, datlayout_style_t *style, datrender_t *render, RECT *rect)
201 {
202         W l,t,r,b;
203
204         if (style->border_width_left <= 0) {
205                 return 0;
206         }
207
208         l = box->l - style->padding_width_left - style->border_width_left;
209         t = box->t - style->padding_width_top - style->border_width_top;
210         r = box->l - style->padding_width_left;
211         b = box->b + style->padding_width_bottom + style->border_width_bottom;
212
213         return datrender_fillrect(render, rect, l, t, r, b);
214 }
215
216 LOCAL W datlayout_box_drawtopborder(datlayout_box_t *box, datlayout_style_t *style, datrender_t *render, RECT *rect)
217 {
218         W l,t,r,b;
219
220         if (style->border_width_top <= 0) {
221                 return 0;
222         }
223
224         l = box->l - style->padding_width_left - style->border_width_left;
225         t = box->t - style->padding_width_top - style->border_width_top;
226         r = box->r + style->padding_width_right + style->border_width_right;
227         b = box->t - style->padding_width_bottom;
228
229         return datrender_fillrect(render, rect, l, t, r, b);
230 }
231
232 LOCAL W datlayout_box_drawrightborder(datlayout_box_t *box, datlayout_style_t *style, datrender_t *render, RECT *rect)
233 {
234         W l,t,r,b;
235
236         if (style->border_width_right <= 0) {
237                 return 0;
238         }
239
240         l = box->r + style->padding_width_right;
241         t = box->t - style->padding_width_top - style->border_width_top;
242         r = box->r + style->padding_width_right + style->border_width_right;
243         b = box->b + style->padding_width_bottom + style->border_width_bottom;
244
245         return datrender_fillrect(render, rect, l, t, r, b);
246 }
247
248 LOCAL W datlayout_box_drawbottomborder(datlayout_box_t *box, datlayout_style_t *style, datrender_t *render, RECT *rect)
249 {
250         W l,t,r,b;
251
252         if (style->border_width_top <= 0) {
253                 return 0;
254         }
255
256         l = box->l - style->padding_width_left - style->border_width_left;
257         t = box->b + style->padding_width_top;
258         r = box->r + style->padding_width_right + style->border_width_right;
259         b = box->b + style->padding_width_bottom + style->border_width_bottom;
260
261         return datrender_fillrect(render, rect, l, t, r, b);
262 }
263
264 LOCAL W datlayout_box_drawborder(datlayout_box_t *box, datlayout_style_t *style, datrender_t *render, RECT *r)
265 {
266         W err;
267
268         err = datlayout_box_drawleftborder(box, style, render, r);
269         if (err < 0) {
270                 return err;
271         }
272         err = datlayout_box_drawtopborder(box, style, render, r);
273         if (err < 0) {
274                 return err;
275         }
276         err = datlayout_box_drawrightborder(box, style, render, r);
277         if (err < 0) {
278                 return err;
279         }
280         err = datlayout_box_drawbottomborder(box, style, render, r);
281         if (err < 0) {
282                 return err;
283         }
284         return 0;
285 }
286
287 LOCAL W datrender_drawresborder(datrender_t *render, datlayout_res_t *layout_res, RECT *r)
288 {
289         W err;
290
291         err = datlayout_box_drawborder(&(layout_res->box.res), &render->style->res, render, r);
292         if (err < 0) {
293                 return err;
294         }
295         err = datlayout_box_drawborder(&(layout_res->box.resheader), &render->style->resheader, render, r);
296         if (err < 0) {
297                 return err;
298         }
299         err = datlayout_box_drawborder(&(layout_res->box.resmessage), &render->style->resmessage, render, r);
300         if (err < 0) {
301                 return err;
302         }
303
304         return 0;
305 }
306
307 LOCAL W datrender_entrydrawnormal(datlayout_res_t *entry, datlayout_style_t *resstyle, datlayout_style_t *resheaderstyle, datlayout_style_t *resmessagestyle, W index, datrender_t *render, GID target, RECT *r, W dh, W dv)
308 {
309         W sect, err;
310         W rv_l, rv_t, rv_r, rv_b;
311
312         datlayout_res_getviewrect(entry, resstyle, &rv_l, &rv_t, &rv_r, &rv_b);
313
314         /* sectrect */
315         sect = sectrect_tmp(*r, rv_l - dh, rv_t - dv, rv_r - dh, rv_b - dv);
316         if (sect == 0) {
317                 return 0;
318         }
319
320         err = datrender_drawresborder(render, entry, r);
321         if (err < 0) {
322                 return err;
323         }
324
325         gset_chc(target, 0x10000000, 0x10efefef);
326         err = gset_chp(target, entry->box.resheader.l - dh, entry->box.resheader.t + 16 - dv, 1);
327         if (err < 0) {
328                 return err;
329         }
330         err = datrender_entrydraw_resnumber(entry, index+1, target);
331         if (err < 0) {
332                 return err;
333         }
334         err = gset_chp(target, 16, 0, 0);
335         if (err < 0) {
336                 return err;
337         }
338         if (entry->parser_res->mail_len != 0) {
339                 gset_chc(target, 0x100000ff, 0x10efefef);
340         } else {
341                 gset_chc(target, 0x10008000, 0x10efefef);
342         }
343         err = datrender_entrydraw_drawname(entry, target, dh, dv);
344         if (err < 0) {
345                 return err;
346         }
347         err = gset_chp(target, 16, 0, 0);
348         if (err < 0) {
349                 return err;
350         }
351         gset_chc(target, 0x10000000, 0x10efefef);
352         layoutstyle_resetgenvfont(target);
353         gdra_chr(target, TK_LABR, G_STORE);
354         err = datrender_entrydraw_drawmail(entry, target, dh, dv);
355         if (err < 0) {
356                 return err;
357         }
358         layoutstyle_resetgenvfont(target);
359         gdra_chr(target, TK_RABR, G_STORE);
360
361         err = datrender_entrydraw_drawdateidbeid(entry, target, dh, dv);
362         if (err < 0) {
363                 return err;
364         }
365
366         err = gset_chp(target, entry->box.resmessage.l - dh, entry->box.resmessage.t + 16 - dv, 1);
367         if (err < 0) {
368                 return err;
369         }
370         layoutstyle_resetgenvfont(target);
371         err = datrender_entrydraw_drawbody(entry, target, dh - entry->box.resmessage.l/* Ugh! */, dv);
372         if (err < 0) {
373                 return err;
374         }
375
376         return 0;
377 }
378
379 LOCAL W datrender_entrydraw_drawNGrect(datrender_t *render, datlayout_res_t *entry, RECT *r)
380 {
381         W rv_l, rv_t, rv_r, rv_b;
382         W err;
383         static PAT pat0 = {{
384                 0,
385                 16, 16,
386                 0x10000000,
387                 0x10000000,
388                 FILL100
389         }};
390         RECT fr;
391         PNT p0, p1;
392
393         datlayout_res_getcontentrect(entry, &render->style->res, &rv_l, &rv_t, &rv_r, &rv_b);
394
395         fr.c.left = rv_l - render->view_l;
396         fr.c.top = rv_t - render->view_t;
397         fr.c.right = rv_r - render->view_l + 1;
398         fr.c.bottom = rv_b - render->view_t + 1;
399         err = gfra_rec(render->target, fr, 1, &pat0, 0, G_STORE);
400         if (err < 0) {
401                 return err;
402         }
403
404         p0.x = rv_l - render->view_l;
405         p0.y = rv_t - render->view_t;
406         p1.x = rv_r - render->view_l;
407         p1.y = rv_b - render->view_t;
408         err = gdra_lin(render->target, p0, p1, 1, &pat0, G_STORE);
409         if (err < 0) {
410                 return err;
411         }
412
413         p0.x = rv_l - render->view_l;
414         p0.y = rv_b - render->view_t;
415         p1.x = rv_r - render->view_l;
416         p1.y = rv_t - render->view_t;
417         err = gdra_lin(render->target, p0, p1, 1, &pat0, G_STORE);
418         if (err < 0) {
419                 return err;
420         }
421
422         return 0;
423 }
424
425 LOCAL W datrender_entrydrawNG(datrender_t *render, datlayout_res_t *entry, W index, RECT *r, W dh, W dv, Bool is_display_id, Bool is_number_grayout)
426 {
427         W sect, err, len;
428         W rv_l, rv_t, rv_r, rv_b;
429         datlayout_style_t *resstyle;
430         GID target;
431         TC *str;
432
433         target = render->target;
434         resstyle = &render->style->res;
435
436         datlayout_res_getviewrect(entry, resstyle, &rv_l, &rv_t, &rv_r, &rv_b);
437
438         /* sectrect */
439         sect = sectrect_tmp(*r, rv_l - dh, rv_t - dv, rv_r - dh, rv_b - dv);
440         if (sect == 0) {
441                 return 0;
442         }
443
444         err = datrender_entrydraw_drawNGrect(render, entry, r);
445         if (err < 0) {
446                 return err;
447         }
448
449         err = datrender_drawresborder(render, entry, r);
450         if (err < 0) {
451                 return err;
452         }
453
454         if (is_number_grayout == True) {
455                 gset_chc(target, 0x10888888, 0x10efefef); /* tmp color */
456         } else {
457                 gset_chc(target, 0x10000000, 0x10efefef);
458         }
459         err = gset_chp(target, entry->box.resheader.l - dh, entry->box.resheader.t + 16 - dv, 1);
460         if (err < 0) {
461                 return err;
462         }
463         err = datrender_entrydraw_resnumber(entry, index+1, target);
464         if (err < 0) {
465                 return err;
466         }
467
468         if ((is_display_id == True) && (entry->parser_res->dateinfo.id != NULL)) {
469                 gset_chc(target, 0x10000000, 0x10efefef);
470                 err = gset_chp(target, entry->box.resheader.l - dh + entry->headerinfo.rel_id_pos.c.left, entry->box.resheader.t + 16 - dv, 1);
471                 if (err < 0) {
472                         return err;
473                 }
474                 err = layoutstyle_sethankakufont(target);
475                 if (err < 0) {
476                         return err;
477                 }
478                 str = entry->parser_res->dateinfo.id;
479                 len = entry->parser_res->dateinfo.id_len;
480                 err = tadlib_drawtext(str, len, target, dh, dv);
481                 if (err < 0) {
482                         return err;
483                 }
484         }
485
486         return 0;
487 }
488
489 LOCAL W datrender_entrydraw(datlayout_res_t *entry, datlayout_style_t *resstyle, datlayout_style_t *resheaderstyle, datlayout_style_t *resmessagestyle, W index, datrender_t *render, GID target, RECT *r, W dh, W dv)
490 {
491         Bool isNG;
492
493         isNG = datlayout_res_isenableindexNG(entry);
494         if (isNG == True) {
495                 return datrender_entrydrawNG(render, entry, index, r, dh, dv, False, False);
496         }
497         isNG = datlayout_res_isenableidNG(entry);
498         if (isNG == True) {
499                 return datrender_entrydrawNG(render, entry, index, r, dh, dv, True, True);
500         }
501         isNG = datlayout_res_isenablewordNG(entry);
502         if (isNG == True) {
503                 return datrender_entrydrawNG(render, entry, index, r, dh, dv, False, True);
504         }
505         return datrender_entrydrawnormal(entry, resstyle, resheaderstyle, resmessagestyle, index, render, target, r, dh, dv);
506 }
507
508 LOCAL W datrender_bodyborderdraw(datrender_t *render, RECT *r)
509 {
510         datlayout_box_t bodybox;
511         datlayoutarray_getbodybox(render->array, &bodybox);
512         return datlayout_box_drawborder(&bodybox, &(render->style->body), render, r);
513 }
514
515 EXPORT W datrender_draw(datrender_t *render, RECT *r)
516 {
517         W i,len,err;
518         GID target;
519         datlayout_res_t *layout_res;
520         Bool exist;
521
522         target = render->target;
523         len = datlayoutarray_length(render->array);
524
525         for (i = 0; i < len; i++) {
526                 exist = datlayoutarray_getresbyindex(render->array, i, &layout_res);
527                 if (exist == False) {
528                         break;
529                 }
530                 layoutstyle_resetgenvfont(render->target);
531                 err = datrender_entrydraw(layout_res, &(render->style->res), &(render->style->resheader), &(render->style->resmessage), i, render, target, r, render->view_l, render->view_t);
532                 if (err < 0) {
533                         return err;
534                 }
535         }
536
537         err = datrender_bodyborderdraw(render, r);
538         if (err < 0) {
539                 return err;
540         }
541
542         return 0;
543 }
544
545 LOCAL W datrender_findentryaction(datlayout_res_t *entry, datlayout_style_t *resstyle, datlayout_style_t *resheaderstyle, datlayout_style_t *resmessagestyle, W abs_x, W abs_y, W *al, W *at, W *ar, W *ab, W *type, UB **start, W *len)
546 {
547         W l,t,r,b,in;
548         PNT pos;
549         W fnd;
550         RECT rect;
551
552         datlayout_res_getviewrect(entry, resstyle, &l, &t, &r, &b);
553         if (!((l <= abs_x)&&(abs_x < r)&&(t <= abs_y)&&(abs_y < b))) {
554                 return 0;
555         }
556         datlayout_resheader_getcontentrect(entry, resheaderstyle, &l, &t, &r, &b);
557         if ((l <= abs_x)&&(abs_x < r)&&(t <= abs_y)&&(abs_y < b)) {
558                 pos.x = abs_x - l;
559                 pos.y = abs_y - t;
560                 if (pos.y < 0) {
561                         return 0;
562                 }
563                 if (pos.y > 16) {
564                         return 0;
565                 }
566                 if (pos.x < 0) {
567                         return 0;
568                 }
569                 in = inrect(entry->headerinfo.rel_number_pos, pos);
570                 if (in == 1) {
571                         *type = DATRENDER_FINDACTION_TYPE_NUMBER;
572                         return 1;
573                 }
574                 in = inrect(entry->headerinfo.rel_id_pos, pos);
575                 if (in == 1) {
576                         *type = DATRENDER_FINDACTION_TYPE_RESID;
577                         return 1;
578                 }
579                 return 0;
580         }
581         datlayout_resmessage_getcontentrect(entry, resmessagestyle, &l, &t, &r, &b);
582         if ((l <= abs_x)&&(abs_x < r)&&(t <= abs_y)&&(abs_y < b)) {
583                 pos.x = abs_x - l;
584                 pos.y = abs_y - t;
585                 fnd = actionlist_findboard(entry->action.body, pos, &rect, type, start, len);
586                 if (fnd != 0) {
587                         *al = rect.c.left + l;
588                         *at = rect.c.top + t;
589                         *ar = rect.c.right + l;
590                         *ab = rect.c.bottom + t;
591                         return fnd;
592                 }
593         }
594         return 0;
595 }
596
597 EXPORT W datrender_findaction(datrender_t *render, PNT rel_pos, RECT *rect, W *type, UB **start, W *len, W *resindex)
598 {
599         W i,abs_x,abs_y,fnd,layout_len;
600         W l,t,r,b;
601         Bool exist;
602         datlayout_res_t *res;
603
604         abs_x = rel_pos.x + render->view_l;
605         abs_y = rel_pos.y + render->view_t;
606         layout_len = datlayoutarray_length(render->array);
607
608         for (i = 0; i < layout_len; i++) {
609                 exist = datlayoutarray_getresbyindex(render->array, i, &res);
610                 if (exist == False) {
611                         break;
612                 }
613
614                 fnd = datrender_findentryaction(res, &(render->style->res), &(render->style->resheader), &(render->style->resmessage), abs_x, abs_y, &l, &t, &r, &b, type, start, len);
615                 if (fnd == 1) {
616                         rect->c.left = l - render->view_l;
617                         rect->c.top = t - render->view_t;
618                         rect->c.right = r - render->view_l;
619                         rect->c.bottom = b - render->view_t;
620                         *resindex = i;
621                         return 1;
622                 }
623         }
624
625         return 0;
626 }
627
628 EXPORT VOID datrender_setviewrect(datrender_t *render, W l, W t, W r, W b)
629 {
630         render->view_l = l;
631         render->view_t = t;
632         render->view_r = r;
633         render->view_b = b;
634 }
635
636 EXPORT VOID datrender_getviewrect(datrender_t *render, W *l, W *t, W *r, W *b)
637 {
638         *l = render->view_l;
639         *t = render->view_t;
640         *r = render->view_r;
641         *b = render->view_b;
642 }
643
644 EXPORT VOID datrender_scrollviewrect(datrender_t *render, W dh, W dv)
645 {
646         render->view_l += dh;
647         render->view_t += dv;
648         render->view_r += dh;
649         render->view_b += dv;
650 }
651
652 EXPORT datrender_t* datrender_new(GID target, datlayoutstyle_t *style, datlayoutarray_t *layoutarray)
653 {
654         datrender_t *render;
655
656         render = (datrender_t*)malloc(sizeof(datrender_t));
657         if (render == NULL) {
658                 return NULL;
659         }
660         render->target = target;
661         render->style = style;
662         render->array = layoutarray;
663         render->view_l = 0;
664         render->view_t = 0;
665         render->view_r = 0;
666         render->view_b = 0;
667
668         return render;
669 }
670
671 EXPORT VOID datrender_delete(datrender_t *render)
672 {
673         free(render);
674 }