OSDN Git Service

move title and res number count parser.
[bbk/bchanl.git] / src / subjectlayout.c
1 /*
2  * subjectlayout.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    "subjectlayout.h"
28 #include    "subjectparser.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         if ((digit != 0)||(draw != 0)) {
99                 dest[i++] = dec[digit];
100                 draw = 1;
101         }
102         dest[i] = TNULL;
103
104         return i;
105 }
106
107 typedef struct sbjtlayout_thread_t_ sbjtlayout_thread_t;
108 struct sbjtlayout_thread_t_ {
109         sbjtparser_thread_t *parser_thread;
110         W index;
111         W view_l,view_t,view_r,view_b;
112         SIZE sz_title;
113         W baseline;
114         RECT vframe;
115 };
116
117 struct sbjtlayout_t_ {
118         GID target;
119         W draw_l,draw_t,draw_r,draw_b;
120         sbjtlayout_thread_t **layout_thread; /* should be QUEUE? */
121         W len;
122         FSSPEC fspec;
123         COLOR vobjbgcol;
124 };
125
126 LOCAL sbjtlayout_thread_t* sbjtlayout_thread_new(sbjtparser_thread_t *thread)
127 {
128         sbjtlayout_thread_t *layout_thread;
129
130         layout_thread = (sbjtlayout_thread_t*)malloc(sizeof(sbjtlayout_thread_t));
131         if (layout_thread == NULL) {
132                 return NULL;
133         }
134         layout_thread->parser_thread = thread;
135         layout_thread->view_l = 0;
136         layout_thread->view_t = 0;
137         layout_thread->view_r = 0;
138         layout_thread->view_b = 0;
139
140         return layout_thread;
141 }
142
143 LOCAL VOID sbjtlayout_thread_delete(sbjtlayout_thread_t *layout_thread)
144 {
145         sbjtparser_thread_delete(layout_thread->parser_thread);
146         free(layout_thread);
147 }
148
149 LOCAL W sbjtlayout_thread_calcindexdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
150 {
151         TC str[12];
152         W err, len;
153
154         len = WtoTCS(layout_thread->index, str);
155         str[len++] = TK_COLN;
156         str[len] = TNULL;
157
158         err = gget_stw(gid, str, len, NULL, NULL);
159         if (err < 0) {
160                 return err;
161         }
162         sz->h = err;
163         err = gget_sth(gid, str, len, NULL, NULL);
164         if (err < 0) {
165                 return err;
166         }
167         sz->v = err;
168
169         return 0;
170 }
171
172 LOCAL W sbjtlayout_thread_calctitledrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
173 {
174         TC *str;
175         W len;
176         sbjtparser_thread_gettitlestr(layout_thread->parser_thread, &str, &len);
177         return tadlib_calcdrawsize(str, len, gid, sz);
178 }
179
180 LOCAL W sbjtlayout_thread_calcresnumdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
181 {
182         TC *str;
183         W len;
184         sbjtparser_thread_getresnumstr(layout_thread->parser_thread, &str, &len);
185         return tadlib_calcdrawsize(str, len, gid, sz);
186 }
187
188 LOCAL W sbjtlayout_thread_calcsize(sbjtlayout_thread_t *layout_res, GID gid, W top, W index)
189 {
190         SIZE sz_index, sz_title, sz_resnum;
191         W err;
192
193         layout_res->index = index;
194
195         err = sbjtlayout_thread_calcindexdrawsize(layout_res, gid, &sz_index);
196         if (err < 0) {
197                 return err;
198         }
199         err = sbjtlayout_thread_calctitledrawsize(layout_res, gid, &sz_title);
200         if (err < 0) {
201                 return err;
202         }
203         err = sbjtlayout_thread_calcresnumdrawsize(layout_res, gid, &sz_resnum);
204         if (err < 0) {
205                 return err;
206         }
207
208         layout_res->sz_title = sz_title;
209
210         layout_res->view_t = top + 2;
211         layout_res->view_l = 0;
212         layout_res->view_b = layout_res->view_t + sz_title.v + 16;
213         layout_res->view_r = 16*6 + sz_title.h + sz_resnum.h;
214
215         layout_res->baseline = 20;
216         layout_res->vframe.c.left = sz_index.h + 16;
217         layout_res->vframe.c.top = layout_res->baseline - sz_title.v - 1;
218         layout_res->vframe.c.right = layout_res->vframe.c.left + sz_title.h + 21;
219         layout_res->vframe.c.bottom = layout_res->baseline + 3;
220
221         return err;
222 }
223
224 //#define sbjtlayout_fontconfig_class FTC_MINCHO
225 //#define sbjtlayout_fontconfig_class 0x000000c0 /* gothic */
226 #define sbjtlayout_fontconfig_class FTC_DEFAULT
227
228 LOCAL W sbjtlayout_setupgid(sbjtlayout_t *layout, GID gid)
229 {
230         return gset_fon(gid, &layout->fspec);
231 }
232
233 EXPORT W sbjtlayout_appendthread(sbjtlayout_t *layout, sbjtparser_thread_t *parser_thread)
234 {
235         sbjtlayout_thread_t *layout_thread;
236         W len;
237
238         layout_thread = sbjtlayout_thread_new(parser_thread);
239         if (layout_thread == NULL) {
240                 return -1; /* TODO */
241         }
242
243         len = layout->len + 1;
244         layout->layout_thread = (sbjtlayout_thread_t**)realloc(layout->layout_thread, sizeof(sbjtlayout_thread_t*)*len);
245         layout->layout_thread[layout->len] = layout_thread;
246         layout->len = len;
247
248         sbjtlayout_setupgid(layout, layout->target);
249
250         sbjtlayout_thread_calcsize(layout_thread, layout->target, layout->draw_b, layout->len);
251
252         /* orrect */
253         if (layout->draw_l > layout_thread->view_l) {
254                 layout->draw_l = layout_thread->view_l;
255         }
256         if (layout->draw_t > layout_thread->view_t) {
257                 layout->draw_t = layout_thread->view_t;
258         }
259         if (layout->draw_r < layout_thread->view_r) {
260                 layout->draw_r = layout_thread->view_r;
261         }
262         if (layout->draw_b < layout_thread->view_b) {
263                 layout->draw_b = layout_thread->view_b;
264         }
265
266         return 0;
267 }
268
269 EXPORT VOID sbjtlayout_getdrawrect(sbjtlayout_t *layout, W *l, W *t, W *r, W *b)
270 {
271         *l = layout->draw_l;
272         *t = layout->draw_t;
273         *r = layout->draw_r;
274         *b = layout->draw_b;
275 }
276
277 EXPORT VOID sbjtlayout_clear(sbjtlayout_t *layout)
278 {
279         W i;
280
281         if (layout->layout_thread != NULL) {
282                 for (i=0;i<layout->len;i++) {
283                         sbjtlayout_thread_delete(layout->layout_thread[i]);
284                 }
285                 free(layout->layout_thread);
286         }
287         layout->draw_l = 0;
288         layout->draw_t = 0;
289         layout->draw_r = 0;
290         layout->draw_b = 0;
291         layout->layout_thread = NULL;
292         layout->len = 0;
293 }
294
295 EXPORT VOID sbjtlayout_setfsspec(sbjtlayout_t *layout, FSSPEC *fspec)
296 {
297         memcpy(&layout->fspec, fspec, sizeof(FSSPEC));
298 }
299
300 EXPORT VOID sbjtlayout_setvobjbgcol(sbjtlayout_t *layout, COLOR color)
301 {
302         layout->vobjbgcol = color;
303 }
304
305 EXPORT COLOR sbjtlayout_getvobjbgcol(sbjtlayout_t *layout)
306 {
307         return layout->vobjbgcol;
308 }
309
310 EXPORT sbjtlayout_t* sbjtlayout_new(GID gid)
311 {
312         sbjtlayout_t *layout;
313
314         layout = (sbjtlayout_t*)malloc(sizeof(sbjtlayout_t));
315         if (layout == NULL) {
316                 return NULL;
317         }
318         layout->target = gid;
319         layout->draw_l = 0;
320         layout->draw_t = 0;
321         layout->draw_r = 0;
322         layout->draw_b = 0;
323         layout->layout_thread = NULL;
324         layout->len = 0;
325         layout->fspec.name[0] = TNULL;
326         layout->fspec.attr = FT_PROP|FT_GRAYSCALE;
327         layout->fspec.fclass = sbjtlayout_fontconfig_class;
328         layout->fspec.size.h = 16;
329         layout->fspec.size.v = 16;
330         layout->vobjbgcol = 0x10000000;
331
332         return layout;
333 }
334
335 EXPORT VOID sbjtlayout_delete(sbjtlayout_t *layout)
336 {
337         W i;
338
339         if (layout->layout_thread != NULL) {
340                 for (i=0;i<layout->len;i++) {
341                         sbjtlayout_thread_delete(layout->layout_thread[i]);
342                 }
343                 free(layout->layout_thread);
344         }
345         free(layout);
346 }
347
348 struct sbjtdraw_t_ {
349         sbjtlayout_t *layout;
350         W view_l, view_t, view_r, view_b;
351 };
352
353 LOCAL W sbjtdraw_entrydraw_drawtitle(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
354 {
355         TC *str;
356         W len;
357         sbjtparser_thread_gettitlestr(entry->parser_thread, &str, &len);
358         return tadlib_drawtext(str, len, gid, dh, dv);
359 }
360
361 LOCAL W sbjtdraw_entrydraw_drawresnum(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
362 {
363         TC *str;
364         W len;
365         sbjtparser_thread_getresnumstr(entry->parser_thread, &str, &len);
366         return tadlib_drawtext(str, len, gid, dh, dv);
367 }
368
369 LOCAL W sbjtdraw_entrydraw_resnumber(sbjtlayout_thread_t *entry, W resnum, GID target)
370 {
371         TC str[11];
372         W len;
373
374         len = WtoTCS(resnum, str);
375         return gdra_str(target, str, len, G_STORE);
376 }
377
378 LOCAL int sectrect_tmp(RECT a, W left, W top, W right, W bottom)
379 {
380         return (a.c.left<right && left<a.c.right && a.c.top<bottom && top<a.c.bottom);
381 }
382
383 LOCAL W sbjtdraw_drawthread(sbjtlayout_thread_t *entry, W index, GID target, RECT *r, W dh, W dv, COLOR vobjbgcol)
384 {
385         W sect, err;
386         RECT view, vframe, vframe_b;
387         static  PAT     pat0 = {{
388                 0,
389                 16, 16,
390                 0x10000000,
391                 0x10000000,
392                 FILL100
393         }};
394         static  PAT     pat1 = {{
395                 0,
396                 16, 16,
397                 0x10000000,
398                 0x10000000,
399                 FILL100
400         }};
401
402         /* sectrect */
403         sect = sectrect_tmp(*r, entry->view_l - dh, entry->view_t - dv, entry->view_r - dh, entry->view_b - dv);
404         if (sect == 0) {
405                 return 0;
406         }
407
408         view.c.left = entry->view_l - dh;
409         view.c.top = entry->view_t - dv;
410         view.c.right = entry->view_r - dh;
411         view.c.bottom = entry->view_b - dv;
412
413         err = gset_chp(target, - dh, entry->view_t + entry->baseline - dv, 1);
414         if (err < 0) {
415                 return err;
416         }
417         err = sbjtdraw_entrydraw_resnumber(entry, index+1, target);
418         if (err < 0) {
419                 return err;
420         }
421         err = gdra_chr(target, TK_COLN, G_STORE);
422         if (err < 0) {
423                 return err;
424         }
425
426         err = gset_chp(target, 16, 0, 0);
427         if (err < 0) {
428                 return err;
429         }
430
431         vframe.c.left = entry->vframe.c.left + view.c.left;
432         vframe.c.top = entry->vframe.c.top + view.c.top;
433         vframe.c.right = entry->vframe.c.right + view.c.left;
434         vframe.c.bottom = entry->vframe.c.bottom + view.c.top;
435         vframe_b.c.left = vframe.c.left + 2;
436         vframe_b.c.top = vframe.c.top + 2;
437         vframe_b.c.right = vframe.c.right + 2;
438         vframe_b.c.bottom = vframe.c.bottom + 2;
439         pat1.spat.fgcol = vobjbgcol;
440         gfra_rec(target, vframe_b, 1, &pat0, 0, G_STORE);
441         gfil_rec(target, vframe, &pat1, 0, G_STORE);
442         gfra_rec(target, vframe, 1, &pat0, 0, G_STORE);
443         gset_chc(target, 0x10000000, vobjbgcol);
444
445         err = gset_chp(target, entry->vframe.c.left+view.c.left+10, entry->baseline + view.c.top, 1);
446         if (err < 0) {
447                 return err;
448         }
449
450         err = sbjtdraw_entrydraw_drawtitle(entry, target, dh, dv);
451         if (err < 0) {
452                 return err;
453         }
454
455         gset_chc(target, 0x10000000, 0x10FFFFFF);
456         err = gset_chp(target, 16, 0, 0);
457         if (err < 0) {
458                 return err;
459         }
460         err = sbjtdraw_entrydraw_drawresnum(entry, target, dh, dv);
461         if (err < 0) {
462                 return err;
463         }
464
465         return 0;
466 }
467
468 EXPORT W sbjtdraw_draw(sbjtdraw_t *draw, RECT *r)
469 {
470         W i,err;
471         GID target;
472         sbjtlayout_t *layout;
473
474         layout = draw->layout;
475         target = layout->target;
476
477         for (i=0;i < layout->len;i++) {
478                 sbjtlayout_setupgid(layout, layout->target);
479                 err = sbjtdraw_drawthread(layout->layout_thread[i], i, target, r, draw->view_l, draw->view_t, layout->vobjbgcol);
480                 if (err < 0) {
481                         return err;
482                 }
483         }
484
485         return 0;
486 }
487
488 EXPORT W sbjtdraw_findthread(sbjtdraw_t *draw, PNT rel_pos, sbjtparser_thread_t **thread, RECT *vframe)
489 {
490         W i,abs_x,abs_y,l,t,r,b;
491         sbjtlayout_t *layout;
492         sbjtlayout_thread_t *sbjt_thread;
493
494         layout = draw->layout;
495         abs_x = rel_pos.x + draw->view_l;
496         abs_y = rel_pos.y + draw->view_t;
497
498         for (i=0;i < layout->len;i++) {
499                 sbjt_thread = layout->layout_thread[i];
500                 l = sbjt_thread->view_l + sbjt_thread->vframe.c.left;
501                 t = sbjt_thread->view_t + sbjt_thread->vframe.c.top;
502                 r = sbjt_thread->view_l + sbjt_thread->vframe.c.right;
503                 b = sbjt_thread->view_t + sbjt_thread->vframe.c.bottom;
504                 if ((l <= abs_x)&&(abs_x < r)
505                         &&(t <= abs_y)&&(abs_y < b)) {
506                         *thread = sbjt_thread->parser_thread;
507                         if (vframe != NULL) {
508                                 vframe->c.left = l - draw->view_l;
509                                 vframe->c.top = t - draw->view_t;
510                                 vframe->c.right = r - draw->view_l;
511                                 vframe->c.bottom = b - draw->view_t;
512                         }
513                         return 1;
514                 }
515         }
516
517         return 0;
518 }
519
520 EXPORT VOID sbjtdraw_setviewrect(sbjtdraw_t *draw, W l, W t, W r, W b)
521 {
522         draw->view_l = l;
523         draw->view_t = t;
524         draw->view_r = r;
525         draw->view_b = b;
526 }
527
528 EXPORT VOID sbjtdraw_getviewrect(sbjtdraw_t *draw, W *l, W *t, W *r, W *b)
529 {
530         *l = draw->view_l;
531         *t = draw->view_t;
532         *r = draw->view_r;
533         *b = draw->view_b;
534 }
535
536 EXPORT VOID sbjtdraw_scrollviewrect(sbjtdraw_t *draw, W dh, W dv)
537 {
538         draw->view_l += dh;
539         draw->view_t += dv;
540         draw->view_r += dh;
541         draw->view_b += dv;
542 }
543
544 EXPORT sbjtdraw_t* sbjtdraw_new(sbjtlayout_t *layout)
545 {
546         sbjtdraw_t *draw;
547
548         draw = (sbjtdraw_t*)malloc(sizeof(sbjtdraw_t));
549         if (draw == NULL) {
550                 return NULL;
551         }
552         draw->layout = layout;
553         draw->view_l = 0;
554         draw->view_t = 0;
555         draw->view_r = 0;
556         draw->view_b = 0;
557
558         return draw;
559 }
560
561 EXPORT VOID sbjtdraw_delete(sbjtdraw_t *draw)
562 {
563         free(draw);
564 }