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