OSDN Git Service

implement displaying since and vigor.
[bbk/bchanl.git] / src / subjectlayout.c
1 /*
2  * subjectlayout.c
3  *
4  * Copyright (c) 2009-2012 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include    "subjectlayout.h"
28 #include    "subjectlist.h"
29 #include    "tadlib.h"
30
31 #include        <bstdio.h>
32 #include        <bstdlib.h>
33 #include        <tcode.h>
34 #include        <btron/btron.h>
35 #include        <btron/dp.h>
36 #include        <tad.h>
37
38 #ifdef BCHANL_CONFIG_DEBUG
39 # define DP(arg) printf arg
40 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
41 #else
42 # define DP(arg) /**/
43 # define DP_ER(msg, err) /**/
44 #endif
45
46 LOCAL TC dec[] = {TK_0,TK_1,TK_2,TK_3,TK_4,TK_5,TK_6,TK_7,TK_8,TK_9};
47
48 LOCAL W WtoTCS(W num, TC *dest)
49 {
50         W digit,draw = 0,i = 0;
51
52         digit = num / 1000000000 % 10;
53         if ((digit != 0)||(draw != 0)) {
54                 dest[i++] = dec[digit];
55                 draw = 1;
56         }
57         digit = num / 100000000 % 10;
58         if ((digit != 0)||(draw != 0)) {
59                 dest[i++] = dec[digit];
60                 draw = 1;
61         }
62         digit = num / 10000000 % 10;
63         if ((digit != 0)||(draw != 0)) {
64                 dest[i++] = dec[digit];
65                 draw = 1;
66         }
67         digit = num / 1000000 % 10;
68         if ((digit != 0)||(draw != 0)) {
69                 dest[i++] = dec[digit];
70                 draw = 1;
71         }
72         digit = num / 100000 % 10;
73         if ((digit != 0)||(draw != 0)) {
74                 dest[i++] = dec[digit];
75                 draw = 1;
76         }
77         digit = num / 10000 % 10;
78         if ((digit != 0)||(draw != 0)) {
79                 dest[i++] = dec[digit];
80                 draw = 1;
81         }
82         digit = num / 1000 % 10;
83         if ((digit != 0)||(draw != 0)) {
84                 dest[i++] = dec[digit];
85                 draw = 1;
86         }
87         digit = num / 100 % 10;
88         if ((digit != 0)||(draw != 0)) {
89                 dest[i++] = dec[digit];
90                 draw = 1;
91         }
92         digit = num / 10 % 10;
93         if ((digit != 0)||(draw != 0)) {
94                 dest[i++] = dec[digit];
95                 draw = 1;
96         }
97         digit = num % 10;
98         dest[i++] = dec[digit];
99         draw = 1;
100         dest[i] = TNULL;
101
102         return i;
103 }
104
105 LOCAL W DATE_TIMtoTCS(DATE_TIM *dtim, TC *dest)
106 {
107         W len;
108
109         len = WtoTCS(dtim->d_year + 1900, dest);
110         dest[len++] = TK_SLSH;
111         len += WtoTCS(dtim->d_month, dest + len);
112         dest[len++] = TK_SLSH;
113         len += WtoTCS(dtim->d_day, dest + len);
114         dest[len] = TNULL;
115
116         return len;
117 }
118
119 LOCAL W VIGORtoTCS(W vigor, TC *dest)
120 {
121         W n0 = vigor / 10;
122         W n1 = vigor % 10;
123         W i;
124
125         i = WtoTCS(n0, dest);
126         dest[i++] = TK_PROD;
127         i += WtoTCS(n1, dest + i);
128         dest[i++] = TK_r;
129         dest[i++] = TK_e;
130         dest[i++] = TK_s;
131         dest[i++] = TK_SLSH;
132         dest[i++] = TK_d;
133         dest[i++] = TK_a;
134         dest[i++] = TK_y;
135         dest[i] = TNULL;
136
137         return i;
138 }
139
140 typedef struct sbjtlayout_thread_t_ sbjtlayout_thread_t;
141 struct sbjtlayout_thread_t_ {
142         sbjtlist_tuple_t *tuple;
143         //W index;
144         W view_l,view_t,view_r,view_b;
145         SIZE sz_title;
146         W baseline;
147         RECT vframe;
148 };
149
150 struct sbjtlayout_t_ {
151         GID target;
152         W draw_l,draw_t,draw_r,draw_b;
153         sbjtlayout_thread_t **layout_thread; /* should be QUEUE? */
154         W len;
155         FSSPEC fspec;
156         COLOR vobjbgcol;
157 };
158
159 LOCAL sbjtlayout_thread_t* sbjtlayout_thread_new(sbjtlist_tuple_t *thread)
160 {
161         sbjtlayout_thread_t *layout_thread;
162
163         layout_thread = (sbjtlayout_thread_t*)malloc(sizeof(sbjtlayout_thread_t));
164         if (layout_thread == NULL) {
165                 return NULL;
166         }
167         layout_thread->tuple = thread;
168         layout_thread->view_l = 0;
169         layout_thread->view_t = 0;
170         layout_thread->view_r = 0;
171         layout_thread->view_b = 0;
172
173         return layout_thread;
174 }
175
176 LOCAL VOID sbjtlayout_thread_delete(sbjtlayout_thread_t *layout_thread)
177 {
178         free(layout_thread);
179 }
180
181 LOCAL W sbjtlayout_thread_calcindexdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
182 {
183         TC str[12];
184         W err, len, num;
185
186         sbjtlist_tuple_getnumber(layout_thread->tuple, &num);
187
188         len = WtoTCS(num, str);
189         str[len++] = TK_COLN;
190         str[len] = TNULL;
191
192         err = gget_stw(gid, str, len, NULL, NULL);
193         if (err < 0) {
194                 return err;
195         }
196         sz->h = err;
197         err = gget_sth(gid, str, len, NULL, NULL);
198         if (err < 0) {
199                 return err;
200         }
201         sz->v = err;
202
203         return 0;
204 }
205
206 LOCAL W sbjtlayout_thread_calctitledrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
207 {
208         TC *str;
209         W len;
210         sbjtlist_tuple_gettitle(layout_thread->tuple, &str, &len);
211         return tadlib_calcdrawsize(str, len, gid, sz);
212 }
213
214 LOCAL W sbjtlayout_thread_calcresnumdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
215 {
216         TC *str;
217         W len;
218         sbjtlist_tuple_getresnumberstr(layout_thread->tuple, &str, &len);
219         return tadlib_calcdrawsize(str, len, gid, sz);
220 }
221
222 LOCAL W sbjtlayout_thread_calcsincedrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
223 {
224         DATE_TIM dtim;
225         TC str[11];
226         W len = 10;
227         sbjtlist_tuple_getsince(layout_thread->tuple, &dtim);
228         len = DATE_TIMtoTCS(&dtim, str);
229         return tadlib_calcdrawsize(str, len, gid, sz);
230 }
231
232 LOCAL W sbjtlayout_thread_calcvigordrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
233 {
234         W vigor;
235         TC str[100];
236         W len;
237         sbjtlist_tuple_getvigor(layout_thread->tuple, &vigor);
238         len = VIGORtoTCS(vigor, str);
239         return tadlib_calcdrawsize(str, len, gid, sz);
240 }
241
242 LOCAL W sbjtlayout_thread_calcsize(sbjtlayout_thread_t *layout_res, GID gid, W top)
243 {
244         SIZE sz_index, sz_title, sz_resnum, sz_since, sz_vigor;
245         W err;
246
247         err = sbjtlayout_thread_calcindexdrawsize(layout_res, gid, &sz_index);
248         if (err < 0) {
249                 return err;
250         }
251         err = sbjtlayout_thread_calctitledrawsize(layout_res, gid, &sz_title);
252         if (err < 0) {
253                 return err;
254         }
255         err = sbjtlayout_thread_calcresnumdrawsize(layout_res, gid, &sz_resnum);
256         if (err < 0) {
257                 return err;
258         }
259         err = sbjtlayout_thread_calcsincedrawsize(layout_res, gid, &sz_since);
260         if (err < 0) {
261                 return err;
262         }
263         err = sbjtlayout_thread_calcvigordrawsize(layout_res, gid, &sz_vigor);
264         if (err < 0) {
265                 return err;
266         }
267
268         layout_res->sz_title = sz_title;
269
270         layout_res->view_t = top + 2;
271         layout_res->view_l = 0;
272         layout_res->view_b = layout_res->view_t + sz_title.v + 16;
273         layout_res->view_r = 16*6 + sz_title.h + sz_resnum.h + 16 + sz_since.h + 16 + sz_vigor.h;
274
275         layout_res->baseline = 20;
276         layout_res->vframe.c.left = sz_index.h + 16;
277         layout_res->vframe.c.top = layout_res->baseline - sz_title.v - 1;
278         layout_res->vframe.c.right = layout_res->vframe.c.left + sz_title.h + 21;
279         layout_res->vframe.c.bottom = layout_res->baseline + 3;
280
281         return err;
282 }
283
284 //#define sbjtlayout_fontconfig_class FTC_MINCHO
285 //#define sbjtlayout_fontconfig_class 0x000000c0 /* gothic */
286 #define sbjtlayout_fontconfig_class FTC_DEFAULT
287
288 LOCAL W sbjtlayout_setupgid(sbjtlayout_t *layout, GID gid)
289 {
290         return gset_fon(gid, &layout->fspec);
291 }
292
293 EXPORT W sbjtlayout_appendthread(sbjtlayout_t *layout, sbjtlist_tuple_t *tuple)
294 {
295         sbjtlayout_thread_t *layout_thread;
296         W len;
297
298         layout_thread = sbjtlayout_thread_new(tuple);
299         if (layout_thread == NULL) {
300                 return -1; /* TODO */
301         }
302
303         len = layout->len + 1;
304         layout->layout_thread = (sbjtlayout_thread_t**)realloc(layout->layout_thread, sizeof(sbjtlayout_thread_t*)*len);
305         layout->layout_thread[layout->len] = layout_thread;
306         layout->len = len;
307
308         sbjtlayout_setupgid(layout, layout->target);
309
310         sbjtlayout_thread_calcsize(layout_thread, layout->target, layout->draw_b);
311
312         /* orrect */
313         if (layout->draw_l > layout_thread->view_l) {
314                 layout->draw_l = layout_thread->view_l;
315         }
316         if (layout->draw_t > layout_thread->view_t) {
317                 layout->draw_t = layout_thread->view_t;
318         }
319         if (layout->draw_r < layout_thread->view_r) {
320                 layout->draw_r = layout_thread->view_r;
321         }
322         if (layout->draw_b < layout_thread->view_b) {
323                 layout->draw_b = layout_thread->view_b;
324         }
325
326         return 0;
327 }
328
329 EXPORT VOID sbjtlayout_getdrawrect(sbjtlayout_t *layout, W *l, W *t, W *r, W *b)
330 {
331         *l = layout->draw_l;
332         *t = layout->draw_t;
333         *r = layout->draw_r;
334         *b = layout->draw_b;
335 }
336
337 EXPORT VOID sbjtlayout_clear(sbjtlayout_t *layout)
338 {
339         W i;
340
341         if (layout->layout_thread != NULL) {
342                 for (i=0;i<layout->len;i++) {
343                         sbjtlayout_thread_delete(layout->layout_thread[i]);
344                 }
345                 free(layout->layout_thread);
346         }
347         layout->draw_l = 0;
348         layout->draw_t = 0;
349         layout->draw_r = 0;
350         layout->draw_b = 0;
351         layout->layout_thread = NULL;
352         layout->len = 0;
353 }
354
355 EXPORT VOID sbjtlayout_setfsspec(sbjtlayout_t *layout, FSSPEC *fspec)
356 {
357         memcpy(&layout->fspec, fspec, sizeof(FSSPEC));
358 }
359
360 EXPORT VOID sbjtlayout_setvobjbgcol(sbjtlayout_t *layout, COLOR color)
361 {
362         layout->vobjbgcol = color;
363 }
364
365 EXPORT COLOR sbjtlayout_getvobjbgcol(sbjtlayout_t *layout)
366 {
367         return layout->vobjbgcol;
368 }
369
370 EXPORT sbjtlayout_t* sbjtlayout_new(GID gid)
371 {
372         sbjtlayout_t *layout;
373
374         layout = (sbjtlayout_t*)malloc(sizeof(sbjtlayout_t));
375         if (layout == NULL) {
376                 return NULL;
377         }
378         layout->target = gid;
379         layout->draw_l = 0;
380         layout->draw_t = 0;
381         layout->draw_r = 0;
382         layout->draw_b = 0;
383         layout->layout_thread = NULL;
384         layout->len = 0;
385         layout->fspec.name[0] = TNULL;
386         layout->fspec.attr = FT_PROP|FT_GRAYSCALE;
387         layout->fspec.fclass = sbjtlayout_fontconfig_class;
388         layout->fspec.size.h = 16;
389         layout->fspec.size.v = 16;
390         layout->vobjbgcol = 0x10000000;
391
392         return layout;
393 }
394
395 EXPORT VOID sbjtlayout_delete(sbjtlayout_t *layout)
396 {
397         W i;
398
399         if (layout->layout_thread != NULL) {
400                 for (i=0;i<layout->len;i++) {
401                         sbjtlayout_thread_delete(layout->layout_thread[i]);
402                 }
403                 free(layout->layout_thread);
404         }
405         free(layout);
406 }
407
408 struct sbjtdraw_t_ {
409         sbjtlayout_t *layout;
410         W view_l, view_t, view_r, view_b;
411 };
412
413 LOCAL W sbjtdraw_entrydraw_drawtitle(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
414 {
415         TC *str;
416         W len;
417         sbjtlist_tuple_gettitle(entry->tuple, &str, &len);
418         return tadlib_drawtext(str, len, gid, dh, dv);
419 }
420
421 LOCAL W sbjtdraw_entrydraw_drawresnum(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
422 {
423         TC *str;
424         W len;
425         sbjtlist_tuple_getresnumberstr(entry->tuple, &str, &len);
426         return tadlib_drawtext(str, len, gid, dh, dv);
427 }
428
429 LOCAL W sbjtdraw_entrydraw_resnumber(sbjtlayout_thread_t *entry, W resnum, GID target)
430
431 {
432         TC str[11];
433         W len;
434
435         len = WtoTCS(resnum, str);
436         return gdra_str(target, str, len, G_STORE);
437 }
438
439 LOCAL W sbjtdraw_entrydraw_drawsince(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
440 {
441         DATE_TIM dtim;
442         TC str[11];
443         W len = 10;
444         sbjtlist_tuple_getsince(entry->tuple, &dtim);
445         len = DATE_TIMtoTCS(&dtim, str);
446         return gdra_str(gid, str, len, G_STORE);
447 }
448
449 LOCAL W sbjtdraw_entrydraw_drawvigor(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
450 {
451         W vigor;
452         TC str[100];
453         W len;
454         sbjtlist_tuple_getvigor(entry->tuple, &vigor);
455         len = VIGORtoTCS(vigor, str);
456         return gdra_str(gid, str, len, G_STORE);
457 }
458
459 LOCAL int sectrect_tmp(RECT a, W left, W top, W right, W bottom)
460 {
461         return (a.c.left<right && left<a.c.right && a.c.top<bottom && top<a.c.bottom);
462 }
463
464 LOCAL W sbjtdraw_drawthread(sbjtlayout_thread_t *entry, GID target, RECT *r, W dh, W dv, COLOR vobjbgcol)
465 {
466         W sect, err, num;
467         RECT view, vframe, vframe_b;
468         static  PAT     pat0 = {{
469                 0,
470                 16, 16,
471                 0x10000000,
472                 0x10000000,
473                 FILL100
474         }};
475         static  PAT     pat1 = {{
476                 0,
477                 16, 16,
478                 0x10000000,
479                 0x10000000,
480                 FILL100
481         }};
482
483         /* sectrect */
484         sect = sectrect_tmp(*r, entry->view_l - dh, entry->view_t - dv, entry->view_r - dh, entry->view_b - dv);
485         if (sect == 0) {
486                 return 0;
487         }
488
489         view.c.left = entry->view_l - dh;
490         view.c.top = entry->view_t - dv;
491         view.c.right = entry->view_r - dh;
492         view.c.bottom = entry->view_b - dv;
493
494         sbjtlist_tuple_getnumber(entry->tuple, &num);
495
496         err = gset_chp(target, - dh, entry->view_t + entry->baseline - dv, 1);
497         if (err < 0) {
498                 return err;
499         }
500         err = sbjtdraw_entrydraw_resnumber(entry, num, target);
501         if (err < 0) {
502                 return err;
503         }
504         err = gdra_chr(target, TK_COLN, G_STORE);
505         if (err < 0) {
506                 return err;
507         }
508
509         err = gset_chp(target, 16, 0, 0);
510         if (err < 0) {
511                 return err;
512         }
513
514         vframe.c.left = entry->vframe.c.left + view.c.left;
515         vframe.c.top = entry->vframe.c.top + view.c.top;
516         vframe.c.right = entry->vframe.c.right + view.c.left;
517         vframe.c.bottom = entry->vframe.c.bottom + view.c.top;
518         vframe_b.c.left = vframe.c.left + 2;
519         vframe_b.c.top = vframe.c.top + 2;
520         vframe_b.c.right = vframe.c.right + 2;
521         vframe_b.c.bottom = vframe.c.bottom + 2;
522         pat1.spat.fgcol = vobjbgcol;
523         gfra_rec(target, vframe_b, 1, &pat0, 0, G_STORE);
524         gfil_rec(target, vframe, &pat1, 0, G_STORE);
525         gfra_rec(target, vframe, 1, &pat0, 0, G_STORE);
526         gset_chc(target, 0x10000000, vobjbgcol);
527
528         err = gset_chp(target, entry->vframe.c.left+view.c.left+10, entry->baseline + view.c.top, 1);
529         if (err < 0) {
530                 return err;
531         }
532
533         err = sbjtdraw_entrydraw_drawtitle(entry, target, dh, dv);
534         if (err < 0) {
535                 return err;
536         }
537
538         gset_chc(target, 0x10000000, 0x10FFFFFF);
539         err = gset_chp(target, 16, 0, 0);
540         if (err < 0) {
541                 return err;
542         }
543         err = sbjtdraw_entrydraw_drawresnum(entry, target, dh, dv);
544         if (err < 0) {
545                 return err;
546         }
547         err = gset_chp(target, 16, 0, 0);
548         if (err < 0) {
549                 return err;
550         }
551         err = sbjtdraw_entrydraw_drawsince(entry, target, dh, dv);
552         if (err < 0) {
553                 return err;
554         }
555         err = gset_chp(target, 16, 0, 0);
556         if (err < 0) {
557                 return err;
558         }
559         err = sbjtdraw_entrydraw_drawvigor(entry, target, dh, dv);
560         if (err < 0) {
561                 return err;
562         }
563
564         return 0;
565 }
566
567 EXPORT W sbjtdraw_draw(sbjtdraw_t *draw, RECT *r)
568 {
569         W i,err;
570         GID target;
571         sbjtlayout_t *layout;
572
573         layout = draw->layout;
574         target = layout->target;
575
576         for (i=0;i < layout->len;i++) {
577                 sbjtlayout_setupgid(layout, layout->target);
578                 err = sbjtdraw_drawthread(layout->layout_thread[i], target, r, draw->view_l, draw->view_t, layout->vobjbgcol);
579                 if (err < 0) {
580                         return err;
581                 }
582         }
583
584         return 0;
585 }
586
587 EXPORT W sbjtdraw_findthread(sbjtdraw_t *draw, PNT rel_pos, sbjtlist_tuple_t **thread, RECT *vframe)
588 {
589         W i,abs_x,abs_y,l,t,r,b;
590         sbjtlayout_t *layout;
591         sbjtlayout_thread_t *sbjt_thread;
592
593         layout = draw->layout;
594         abs_x = rel_pos.x + draw->view_l;
595         abs_y = rel_pos.y + draw->view_t;
596
597         for (i=0;i < layout->len;i++) {
598                 sbjt_thread = layout->layout_thread[i];
599                 l = sbjt_thread->view_l + sbjt_thread->vframe.c.left;
600                 t = sbjt_thread->view_t + sbjt_thread->vframe.c.top;
601                 r = sbjt_thread->view_l + sbjt_thread->vframe.c.right;
602                 b = sbjt_thread->view_t + sbjt_thread->vframe.c.bottom;
603                 if ((l <= abs_x)&&(abs_x < r)
604                         &&(t <= abs_y)&&(abs_y < b)) {
605                         *thread = sbjt_thread->tuple;
606                         if (vframe != NULL) {
607                                 vframe->c.left = l - draw->view_l;
608                                 vframe->c.top = t - draw->view_t;
609                                 vframe->c.right = r - draw->view_l;
610                                 vframe->c.bottom = b - draw->view_t;
611                         }
612                         return 1;
613                 }
614         }
615
616         return 0;
617 }
618
619 EXPORT VOID sbjtdraw_setviewrect(sbjtdraw_t *draw, W l, W t, W r, W b)
620 {
621         draw->view_l = l;
622         draw->view_t = t;
623         draw->view_r = r;
624         draw->view_b = b;
625 }
626
627 EXPORT VOID sbjtdraw_getviewrect(sbjtdraw_t *draw, W *l, W *t, W *r, W *b)
628 {
629         *l = draw->view_l;
630         *t = draw->view_t;
631         *r = draw->view_r;
632         *b = draw->view_b;
633 }
634
635 EXPORT VOID sbjtdraw_scrollviewrect(sbjtdraw_t *draw, W dh, W dv)
636 {
637         draw->view_l += dh;
638         draw->view_t += dv;
639         draw->view_r += dh;
640         draw->view_b += dv;
641 }
642
643 EXPORT sbjtdraw_t* sbjtdraw_new(sbjtlayout_t *layout)
644 {
645         sbjtdraw_t *draw;
646
647         draw = (sbjtdraw_t*)malloc(sizeof(sbjtdraw_t));
648         if (draw == NULL) {
649                 return NULL;
650         }
651         draw->layout = layout;
652         draw->view_l = 0;
653         draw->view_t = 0;
654         draw->view_r = 0;
655         draw->view_b = 0;
656
657         return draw;
658 }
659
660 EXPORT VOID sbjtdraw_delete(sbjtdraw_t *draw)
661 {
662         free(draw);
663 }