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