OSDN Git Service

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