OSDN Git Service

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