OSDN Git Service

implement display attribute setter and getter interface.
[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 #define SBJTLAYOUT_FLAG_RESNUM_DISPLAY 0x00000001
151 #define SBJTLAYOUT_FLAG_SINCE_DISPLAY 0x00000002
152 #define SBJTLAYOUT_FLAG_VIGOR_DISPLAY 0x00000004
153
154 struct sbjtlayout_t_ {
155         GID target;
156         W draw_l,draw_t,draw_r,draw_b;
157         sbjtlayout_thread_t **layout_thread; /* should be QUEUE? */
158         W len;
159         FSSPEC fspec;
160         COLOR vobjbgcol;
161         UW flag;
162 };
163
164 LOCAL sbjtlayout_thread_t* sbjtlayout_thread_new(sbjtlist_tuple_t *thread)
165 {
166         sbjtlayout_thread_t *layout_thread;
167
168         layout_thread = (sbjtlayout_thread_t*)malloc(sizeof(sbjtlayout_thread_t));
169         if (layout_thread == NULL) {
170                 return NULL;
171         }
172         layout_thread->tuple = thread;
173         layout_thread->view_l = 0;
174         layout_thread->view_t = 0;
175         layout_thread->view_r = 0;
176         layout_thread->view_b = 0;
177
178         return layout_thread;
179 }
180
181 LOCAL VOID sbjtlayout_thread_delete(sbjtlayout_thread_t *layout_thread)
182 {
183         free(layout_thread);
184 }
185
186 LOCAL W sbjtlayout_thread_calcindexdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
187 {
188         TC str[12];
189         W err, len, num;
190
191         sbjtlist_tuple_getnumber(layout_thread->tuple, &num);
192
193         len = WtoTCS(num, str);
194         str[len++] = TK_COLN;
195         str[len] = TNULL;
196
197         err = gget_stw(gid, str, len, NULL, NULL);
198         if (err < 0) {
199                 return err;
200         }
201         sz->h = err;
202         err = gget_sth(gid, str, len, NULL, NULL);
203         if (err < 0) {
204                 return err;
205         }
206         sz->v = err;
207
208         return 0;
209 }
210
211 LOCAL W sbjtlayout_thread_calctitledrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
212 {
213         TC *str;
214         W len;
215         sbjtlist_tuple_gettitle(layout_thread->tuple, &str, &len);
216         return tadlib_calcdrawsize(str, len, gid, sz);
217 }
218
219 LOCAL W sbjtlayout_thread_calcresnumdrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
220 {
221         TC *str;
222         W len;
223         sbjtlist_tuple_getresnumberstr(layout_thread->tuple, &str, &len);
224         return tadlib_calcdrawsize(str, len, gid, sz);
225 }
226
227 LOCAL W sbjtlayout_thread_calcsincedrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
228 {
229         DATE_TIM dtim;
230         TC str[11];
231         W len = 10;
232         sbjtlist_tuple_getsince(layout_thread->tuple, &dtim);
233         len = DATE_TIMtoTCS(&dtim, str);
234         return tadlib_calcdrawsize(str, len, gid, sz);
235 }
236
237 LOCAL W sbjtlayout_thread_calcvigordrawsize(sbjtlayout_thread_t *layout_thread, GID gid, SIZE *sz)
238 {
239         W vigor;
240         TC str[100];
241         W len;
242         sbjtlist_tuple_getvigor(layout_thread->tuple, &vigor);
243         len = VIGORtoTCS(vigor, str);
244         return tadlib_calcdrawsize(str, len, gid, sz);
245 }
246
247 LOCAL W sbjtlayout_thread_calcsize(sbjtlayout_thread_t *layout_res, GID gid, W top)
248 {
249         SIZE sz_index, sz_title, sz_resnum, sz_since, sz_vigor;
250         W err;
251
252         err = sbjtlayout_thread_calcindexdrawsize(layout_res, gid, &sz_index);
253         if (err < 0) {
254                 return err;
255         }
256         err = sbjtlayout_thread_calctitledrawsize(layout_res, gid, &sz_title);
257         if (err < 0) {
258                 return err;
259         }
260         err = sbjtlayout_thread_calcresnumdrawsize(layout_res, gid, &sz_resnum);
261         if (err < 0) {
262                 return err;
263         }
264         err = sbjtlayout_thread_calcsincedrawsize(layout_res, gid, &sz_since);
265         if (err < 0) {
266                 return err;
267         }
268         err = sbjtlayout_thread_calcvigordrawsize(layout_res, gid, &sz_vigor);
269         if (err < 0) {
270                 return err;
271         }
272
273         layout_res->sz_title = sz_title;
274
275         layout_res->view_t = top + 2;
276         layout_res->view_l = 0;
277         layout_res->view_b = layout_res->view_t + sz_title.v + 16;
278         layout_res->view_r = 16*6 + sz_title.h + sz_resnum.h + 16 + sz_since.h + 16 + sz_vigor.h;
279
280         layout_res->baseline = 20;
281         layout_res->vframe.c.left = sz_index.h + 16;
282         layout_res->vframe.c.top = layout_res->baseline - sz_title.v - 1;
283         layout_res->vframe.c.right = layout_res->vframe.c.left + sz_title.h + 21;
284         layout_res->vframe.c.bottom = layout_res->baseline + 3;
285
286         return err;
287 }
288
289 //#define sbjtlayout_fontconfig_class FTC_MINCHO
290 //#define sbjtlayout_fontconfig_class 0x000000c0 /* gothic */
291 #define sbjtlayout_fontconfig_class FTC_DEFAULT
292
293 LOCAL W sbjtlayout_setupgid(sbjtlayout_t *layout, GID gid)
294 {
295         return gset_fon(gid, &layout->fspec);
296 }
297
298 EXPORT W sbjtlayout_appendthread(sbjtlayout_t *layout, sbjtlist_tuple_t *tuple)
299 {
300         sbjtlayout_thread_t *layout_thread;
301         W len;
302
303         layout_thread = sbjtlayout_thread_new(tuple);
304         if (layout_thread == NULL) {
305                 return -1; /* TODO */
306         }
307
308         len = layout->len + 1;
309         layout->layout_thread = (sbjtlayout_thread_t**)realloc(layout->layout_thread, sizeof(sbjtlayout_thread_t*)*len);
310         layout->layout_thread[layout->len] = layout_thread;
311         layout->len = len;
312
313         sbjtlayout_setupgid(layout, layout->target);
314
315         sbjtlayout_thread_calcsize(layout_thread, layout->target, layout->draw_b);
316
317         /* orrect */
318         if (layout->draw_l > layout_thread->view_l) {
319                 layout->draw_l = layout_thread->view_l;
320         }
321         if (layout->draw_t > layout_thread->view_t) {
322                 layout->draw_t = layout_thread->view_t;
323         }
324         if (layout->draw_r < layout_thread->view_r) {
325                 layout->draw_r = layout_thread->view_r;
326         }
327         if (layout->draw_b < layout_thread->view_b) {
328                 layout->draw_b = layout_thread->view_b;
329         }
330
331         return 0;
332 }
333
334 EXPORT VOID sbjtlayout_getdrawrect(sbjtlayout_t *layout, W *l, W *t, W *r, W *b)
335 {
336         *l = layout->draw_l;
337         *t = layout->draw_t;
338         *r = layout->draw_r;
339         *b = layout->draw_b;
340 }
341
342 EXPORT VOID sbjtlayout_clear(sbjtlayout_t *layout)
343 {
344         W i;
345
346         if (layout->layout_thread != NULL) {
347                 for (i=0;i<layout->len;i++) {
348                         sbjtlayout_thread_delete(layout->layout_thread[i]);
349                 }
350                 free(layout->layout_thread);
351         }
352         layout->draw_l = 0;
353         layout->draw_t = 0;
354         layout->draw_r = 0;
355         layout->draw_b = 0;
356         layout->layout_thread = NULL;
357         layout->len = 0;
358 }
359
360 EXPORT VOID sbjtlayout_setfsspec(sbjtlayout_t *layout, FSSPEC *fspec)
361 {
362         memcpy(&layout->fspec, fspec, sizeof(FSSPEC));
363 }
364
365 EXPORT VOID sbjtlayout_setvobjbgcol(sbjtlayout_t *layout, COLOR color)
366 {
367         layout->vobjbgcol = color;
368 }
369
370 EXPORT COLOR sbjtlayout_getvobjbgcol(sbjtlayout_t *layout)
371 {
372         return layout->vobjbgcol;
373 }
374
375 EXPORT VOID sbjtlayout_setresnumberdisplay(sbjtlayout_t *layout, Bool display)
376 {
377         if (display == False) {
378                 layout->flag = layout->flag & ~SBJTLAYOUT_FLAG_RESNUM_DISPLAY;
379         } else {
380                 layout->flag |= SBJTLAYOUT_FLAG_RESNUM_DISPLAY;
381         }
382 }
383
384 EXPORT VOID sbjtlayout_setsincedisplay(sbjtlayout_t *layout, Bool display)
385 {
386         if (display == False) {
387                 layout->flag = layout->flag & ~SBJTLAYOUT_FLAG_SINCE_DISPLAY;
388         } else {
389                 layout->flag |= SBJTLAYOUT_FLAG_SINCE_DISPLAY;
390         }
391 }
392
393 EXPORT VOID sbjtlayout_setvigordisplay(sbjtlayout_t *layout, Bool display)
394 {
395         if (display == False) {
396                 layout->flag = layout->flag & ~SBJTLAYOUT_FLAG_VIGOR_DISPLAY;
397         } else {
398                 layout->flag |= SBJTLAYOUT_FLAG_VIGOR_DISPLAY;
399         }
400 }
401
402 EXPORT Bool sbjtlayout_getresnumberdisplay(sbjtlayout_t *layout)
403 {
404         if ((layout->flag & SBJTLAYOUT_FLAG_RESNUM_DISPLAY) != 0) {
405                 return True;
406         } else {
407                 return False;
408         }
409 }
410
411 EXPORT Bool sbjtlayout_getsincedisplay(sbjtlayout_t *layout)
412 {
413         if ((layout->flag & SBJTLAYOUT_FLAG_SINCE_DISPLAY) != 0) {
414                 return True;
415         } else {
416                 return False;
417         }
418 }
419
420 EXPORT Bool sbjtlayout_getvigordisplay(sbjtlayout_t *layout)
421 {
422         if ((layout->flag & SBJTLAYOUT_FLAG_VIGOR_DISPLAY) != 0) {
423                 return True;
424         } else {
425                 return False;
426         }
427 }
428
429 EXPORT sbjtlayout_t* sbjtlayout_new(GID gid)
430 {
431         sbjtlayout_t *layout;
432
433         layout = (sbjtlayout_t*)malloc(sizeof(sbjtlayout_t));
434         if (layout == NULL) {
435                 return NULL;
436         }
437         layout->target = gid;
438         layout->draw_l = 0;
439         layout->draw_t = 0;
440         layout->draw_r = 0;
441         layout->draw_b = 0;
442         layout->layout_thread = NULL;
443         layout->len = 0;
444         layout->fspec.name[0] = TNULL;
445         layout->fspec.attr = FT_PROP|FT_GRAYSCALE;
446         layout->fspec.fclass = sbjtlayout_fontconfig_class;
447         layout->fspec.size.h = 16;
448         layout->fspec.size.v = 16;
449         layout->vobjbgcol = 0x10000000;
450         layout->flag = 0;
451
452         return layout;
453 }
454
455 EXPORT VOID sbjtlayout_delete(sbjtlayout_t *layout)
456 {
457         W i;
458
459         if (layout->layout_thread != NULL) {
460                 for (i=0;i<layout->len;i++) {
461                         sbjtlayout_thread_delete(layout->layout_thread[i]);
462                 }
463                 free(layout->layout_thread);
464         }
465         free(layout);
466 }
467
468 struct sbjtdraw_t_ {
469         sbjtlayout_t *layout;
470         W view_l, view_t, view_r, view_b;
471 };
472
473 LOCAL W sbjtdraw_entrydraw_drawtitle(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
474 {
475         TC *str;
476         W len;
477         sbjtlist_tuple_gettitle(entry->tuple, &str, &len);
478         return tadlib_drawtext(str, len, gid, dh, dv);
479 }
480
481 LOCAL W sbjtdraw_entrydraw_drawresnum(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
482 {
483         TC *str;
484         W len;
485         sbjtlist_tuple_getresnumberstr(entry->tuple, &str, &len);
486         return tadlib_drawtext(str, len, gid, dh, dv);
487 }
488
489 LOCAL W sbjtdraw_entrydraw_resnumber(sbjtlayout_thread_t *entry, W resnum, GID target)
490
491 {
492         TC str[11];
493         W len;
494
495         len = WtoTCS(resnum, str);
496         return gdra_str(target, str, len, G_STORE);
497 }
498
499 LOCAL W sbjtdraw_entrydraw_drawsince(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
500 {
501         DATE_TIM dtim;
502         TC str[11];
503         W len = 10;
504         sbjtlist_tuple_getsince(entry->tuple, &dtim);
505         len = DATE_TIMtoTCS(&dtim, str);
506         return gdra_str(gid, str, len, G_STORE);
507 }
508
509 LOCAL W sbjtdraw_entrydraw_drawvigor(sbjtlayout_thread_t *entry, GID gid, W dh, W dv)
510 {
511         W vigor;
512         TC str[100];
513         W len;
514         sbjtlist_tuple_getvigor(entry->tuple, &vigor);
515         len = VIGORtoTCS(vigor, str);
516         return gdra_str(gid, str, len, G_STORE);
517 }
518
519 LOCAL int sectrect_tmp(RECT a, W left, W top, W right, W bottom)
520 {
521         return (a.c.left<right && left<a.c.right && a.c.top<bottom && top<a.c.bottom);
522 }
523
524 LOCAL W sbjtdraw_drawthread(sbjtlayout_thread_t *entry, GID target, RECT *r, W dh, W dv, COLOR vobjbgcol)
525 {
526         W sect, err, num;
527         RECT view, vframe, vframe_b;
528         static  PAT     pat0 = {{
529                 0,
530                 16, 16,
531                 0x10000000,
532                 0x10000000,
533                 FILL100
534         }};
535         static  PAT     pat1 = {{
536                 0,
537                 16, 16,
538                 0x10000000,
539                 0x10000000,
540                 FILL100
541         }};
542
543         /* sectrect */
544         sect = sectrect_tmp(*r, entry->view_l - dh, entry->view_t - dv, entry->view_r - dh, entry->view_b - dv);
545         if (sect == 0) {
546                 return 0;
547         }
548
549         view.c.left = entry->view_l - dh;
550         view.c.top = entry->view_t - dv;
551         view.c.right = entry->view_r - dh;
552         view.c.bottom = entry->view_b - dv;
553
554         sbjtlist_tuple_getnumber(entry->tuple, &num);
555
556         err = gset_chp(target, - dh, entry->view_t + entry->baseline - dv, 1);
557         if (err < 0) {
558                 return err;
559         }
560         err = sbjtdraw_entrydraw_resnumber(entry, num, target);
561         if (err < 0) {
562                 return err;
563         }
564         err = gdra_chr(target, TK_COLN, G_STORE);
565         if (err < 0) {
566                 return err;
567         }
568
569         err = gset_chp(target, 16, 0, 0);
570         if (err < 0) {
571                 return err;
572         }
573
574         vframe.c.left = entry->vframe.c.left + view.c.left;
575         vframe.c.top = entry->vframe.c.top + view.c.top;
576         vframe.c.right = entry->vframe.c.right + view.c.left;
577         vframe.c.bottom = entry->vframe.c.bottom + view.c.top;
578         vframe_b.c.left = vframe.c.left + 2;
579         vframe_b.c.top = vframe.c.top + 2;
580         vframe_b.c.right = vframe.c.right + 2;
581         vframe_b.c.bottom = vframe.c.bottom + 2;
582         pat1.spat.fgcol = vobjbgcol;
583         gfra_rec(target, vframe_b, 1, &pat0, 0, G_STORE);
584         gfil_rec(target, vframe, &pat1, 0, G_STORE);
585         gfra_rec(target, vframe, 1, &pat0, 0, G_STORE);
586         gset_chc(target, 0x10000000, vobjbgcol);
587
588         err = gset_chp(target, entry->vframe.c.left+view.c.left+10, entry->baseline + view.c.top, 1);
589         if (err < 0) {
590                 return err;
591         }
592
593         err = sbjtdraw_entrydraw_drawtitle(entry, target, dh, dv);
594         if (err < 0) {
595                 return err;
596         }
597
598         gset_chc(target, 0x10000000, 0x10FFFFFF);
599         err = gset_chp(target, 16, 0, 0);
600         if (err < 0) {
601                 return err;
602         }
603         err = sbjtdraw_entrydraw_drawresnum(entry, target, dh, dv);
604         if (err < 0) {
605                 return err;
606         }
607         err = gset_chp(target, 16, 0, 0);
608         if (err < 0) {
609                 return err;
610         }
611         err = sbjtdraw_entrydraw_drawsince(entry, target, dh, dv);
612         if (err < 0) {
613                 return err;
614         }
615         err = gset_chp(target, 16, 0, 0);
616         if (err < 0) {
617                 return err;
618         }
619         err = sbjtdraw_entrydraw_drawvigor(entry, target, dh, dv);
620         if (err < 0) {
621                 return err;
622         }
623
624         return 0;
625 }
626
627 EXPORT W sbjtdraw_draw(sbjtdraw_t *draw, RECT *r)
628 {
629         W i,err;
630         GID target;
631         sbjtlayout_t *layout;
632
633         layout = draw->layout;
634         target = layout->target;
635
636         for (i=0;i < layout->len;i++) {
637                 sbjtlayout_setupgid(layout, layout->target);
638                 err = sbjtdraw_drawthread(layout->layout_thread[i], target, r, draw->view_l, draw->view_t, layout->vobjbgcol);
639                 if (err < 0) {
640                         return err;
641                 }
642         }
643
644         return 0;
645 }
646
647 EXPORT W sbjtdraw_findthread(sbjtdraw_t *draw, PNT rel_pos, sbjtlist_tuple_t **thread, RECT *vframe)
648 {
649         W i,abs_x,abs_y,l,t,r,b;
650         sbjtlayout_t *layout;
651         sbjtlayout_thread_t *sbjt_thread;
652
653         layout = draw->layout;
654         abs_x = rel_pos.x + draw->view_l;
655         abs_y = rel_pos.y + draw->view_t;
656
657         for (i=0;i < layout->len;i++) {
658                 sbjt_thread = layout->layout_thread[i];
659                 l = sbjt_thread->view_l + sbjt_thread->vframe.c.left;
660                 t = sbjt_thread->view_t + sbjt_thread->vframe.c.top;
661                 r = sbjt_thread->view_l + sbjt_thread->vframe.c.right;
662                 b = sbjt_thread->view_t + sbjt_thread->vframe.c.bottom;
663                 if ((l <= abs_x)&&(abs_x < r)
664                         &&(t <= abs_y)&&(abs_y < b)) {
665                         *thread = sbjt_thread->tuple;
666                         if (vframe != NULL) {
667                                 vframe->c.left = l - draw->view_l;
668                                 vframe->c.top = t - draw->view_t;
669                                 vframe->c.right = r - draw->view_l;
670                                 vframe->c.bottom = b - draw->view_t;
671                         }
672                         return 1;
673                 }
674         }
675
676         return 0;
677 }
678
679 EXPORT VOID sbjtdraw_setviewrect(sbjtdraw_t *draw, W l, W t, W r, W b)
680 {
681         draw->view_l = l;
682         draw->view_t = t;
683         draw->view_r = r;
684         draw->view_b = b;
685 }
686
687 EXPORT VOID sbjtdraw_getviewrect(sbjtdraw_t *draw, W *l, W *t, W *r, W *b)
688 {
689         *l = draw->view_l;
690         *t = draw->view_t;
691         *r = draw->view_r;
692         *b = draw->view_b;
693 }
694
695 EXPORT VOID sbjtdraw_scrollviewrect(sbjtdraw_t *draw, W dh, W dv)
696 {
697         draw->view_l += dh;
698         draw->view_t += dv;
699         draw->view_r += dh;
700         draw->view_b += dv;
701 }
702
703 EXPORT sbjtdraw_t* sbjtdraw_new(sbjtlayout_t *layout)
704 {
705         sbjtdraw_t *draw;
706
707         draw = (sbjtdraw_t*)malloc(sizeof(sbjtdraw_t));
708         if (draw == NULL) {
709                 return NULL;
710         }
711         draw->layout = layout;
712         draw->view_l = 0;
713         draw->view_t = 0;
714         draw->view_r = 0;
715         draw->view_b = 0;
716
717         return draw;
718 }
719
720 EXPORT VOID sbjtdraw_delete(sbjtdraw_t *draw)
721 {
722         free(draw);
723 }