]> git.decadent.org.uk Git - ion3.git/blob - ioncore/infowin.c
5dd0b2871d9c955443f882792ce211c33a68c72c
[ion3.git] / ioncore / infowin.c
1 /*
2  * ion/ioncore/infowin.h
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2008. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10
11 #include <libtu/objp.h>
12 #include "common.h"
13 #include "global.h"
14 #include "window.h"
15 #include "infowin.h"
16 #include "resize.h"
17 #include "gr.h"
18 #include "event.h"
19 #include "strings.h"
20
21
22 /*{{{ Init/deinit */
23
24
25 bool infowin_init(WInfoWin *p, WWindow *parent, const WFitParams *fp,
26                   const char *style)
27 {
28     XSetWindowAttributes attr;
29     
30     if(!window_init(&(p->wwin), parent, fp))
31         return FALSE;
32     
33     p->buffer=ALLOC_N(char, INFOWIN_BUFFER_LEN);
34     if(p->buffer==NULL)
35         goto fail;
36     p->buffer[0]='\0';
37     
38     if(style==NULL)
39         p->style=scopy("*");
40     else
41         p->style=scopy(style);
42     if(p->style==NULL)
43         goto fail2;
44     
45     p->brush=NULL;
46     
47     gr_stylespec_init(&p->attr);
48     
49     infowin_updategr(p);
50     
51     if(p->brush==NULL)
52         goto fail3;
53     
54     /* Enable save unders */
55     attr.save_under=True;
56     XChangeWindowAttributes(ioncore_g.dpy, p->wwin.win, CWSaveUnder, &attr);
57     
58     window_select_input(&(p->wwin), IONCORE_EVENTMASK_NORMAL);
59
60     return TRUE;
61
62 fail3:
63     gr_stylespec_unalloc(&p->attr);
64     free(p->style);
65 fail2:
66     free(p->buffer);
67 fail:    
68     window_deinit(&(p->wwin));
69     return FALSE;
70 }
71
72
73 WInfoWin *create_infowin(WWindow *parent, const WFitParams *fp,
74                          const char *style)
75 {
76     CREATEOBJ_IMPL(WInfoWin, infowin, (p, parent, fp, style));
77 }
78
79
80 void infowin_deinit(WInfoWin *p)
81 {
82     if(p->buffer!=NULL){
83         free(p->buffer);
84         p->buffer=NULL;
85     }
86
87     if(p->style!=NULL){
88         free(p->style);
89         p->style=NULL;
90     }
91     
92     if(p->brush!=NULL){
93         grbrush_release(p->brush);
94         p->brush=NULL;
95     }
96     
97     gr_stylespec_unalloc(&p->attr);
98     
99     window_deinit(&(p->wwin));
100 }
101
102
103 /*}}}*/
104
105
106 /*{{{ Drawing and geometry */
107
108
109 void infowin_draw(WInfoWin *p, bool complete)
110 {
111     WRectangle g;
112     
113     if(p->brush==NULL)
114         return;
115     
116     g.x=0;
117     g.y=0;
118     g.w=REGION_GEOM(p).w;
119     g.h=REGION_GEOM(p).h;
120
121     grbrush_begin(p->brush, &g, GRBRUSH_NO_CLEAR_OK);
122     grbrush_init_attr(p->brush, &p->attr);
123     grbrush_draw_textbox(p->brush, &g, p->buffer, TRUE);
124     grbrush_end(p->brush);
125 }
126
127
128 void infowin_updategr(WInfoWin *p)
129 {
130     GrBrush *nbrush;
131     
132     assert(p->style!=NULL);
133     
134     nbrush=gr_get_brush(p->wwin.win, 
135                         region_rootwin_of((WRegion*)p),
136                         p->style);
137     if(nbrush==NULL)
138         return;
139     
140     if(p->brush!=NULL)
141         grbrush_release(p->brush);
142     
143     p->brush=nbrush;
144     
145     window_draw(&(p->wwin), TRUE);
146 }
147
148
149
150 /*}}}*/
151
152
153 /*{{{ Content-setting */
154
155
156 GrStyleSpec *infowin_stylespec(WInfoWin *p)
157 {
158     return &p->attr;
159 }
160
161
162 static void infowin_do_set_text(WInfoWin *p, const char *str)
163 {
164     strncpy(INFOWIN_BUFFER(p), str, INFOWIN_BUFFER_LEN);
165     INFOWIN_BUFFER(p)[INFOWIN_BUFFER_LEN-1]='\0';
166 }
167
168
169 static void infowin_resize(WInfoWin *p)
170 {
171     WRQGeomParams rq=RQGEOMPARAMS_INIT;
172     const char *str=INFOWIN_BUFFER(p);
173     GrBorderWidths bdw;
174     GrFontExtents fnte;
175     
176     rq.flags=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
177     
178     rq.geom.x=REGION_GEOM(p).x;
179     rq.geom.y=REGION_GEOM(p).y;
180     
181     grbrush_get_border_widths(p->brush, &bdw);
182     grbrush_get_font_extents(p->brush, &fnte);
183         
184     rq.geom.w=bdw.left+bdw.right;
185     rq.geom.w+=grbrush_get_text_width(p->brush, str, strlen(str));
186     rq.geom.h=fnte.max_height+bdw.top+bdw.bottom;
187
188     if(rectangle_compare(&rq.geom, &REGION_GEOM(p))!=RECTANGLE_SAME)
189         region_rqgeom((WRegion*)p, &rq, NULL);
190 }
191
192
193 /*EXTL_DOC
194  * Set contents of the info window.
195  */
196 EXTL_EXPORT_MEMBER
197 void infowin_set_text(WInfoWin *p, const char *str, int maxw)
198 {
199     bool set=FALSE;
200     
201     if(maxw>0 && p->brush!=NULL){
202         char *tmp=grbrush_make_label(p->brush, str, maxw);
203         if(tmp!=NULL){
204             infowin_do_set_text(p, tmp);
205             free(tmp);
206             set=TRUE;
207         }
208     }
209     
210     if(!set)
211         infowin_do_set_text(p, str);
212
213     infowin_resize(p);
214     
215     /* sometimes unnecessary */
216     window_draw((WWindow*)p, TRUE);
217 }
218
219
220 /*}}}*/
221
222
223 /*{{{ Load */
224
225
226 WRegion *infowin_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
227 {
228     char *style=NULL, *text=NULL;
229     WInfoWin *p;
230     
231     extl_table_gets_s(tab, "style", &style);
232     
233     p=create_infowin(par, fp, style);
234     
235     free(style);
236     
237     if(p==NULL)
238         return NULL;
239
240     if(extl_table_gets_s(tab, "text", &text)){
241         infowin_do_set_text(p, text);
242         free(text);
243     }
244     
245     return (WRegion*)p;
246 }
247
248
249 /*}}}*/
250
251
252 /*{{{ Dynamic function table and class implementation */
253
254
255 static DynFunTab infowin_dynfuntab[]={
256     {window_draw, infowin_draw},
257     {region_updategr, infowin_updategr},
258     END_DYNFUNTAB
259 };
260
261
262 EXTL_EXPORT
263 IMPLCLASS(WInfoWin, WWindow, infowin_deinit, infowin_dynfuntab);
264
265     
266 /*}}}*/
267