]> git.decadent.org.uk Git - ion3.git/blob - mod_query/wmessage.c
Imported Upstream version 20090110
[ion3.git] / mod_query / wmessage.c
1 /*
2  * ion/mod_query/wmessage.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2009. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10
11 #include <libtu/objp.h>
12 #include <ioncore/common.h>
13 #include <ioncore/strings.h>
14 #include <ioncore/global.h>
15 #include <ioncore/event.h>
16 #include <ioncore/gr-util.h>
17 #include <ioncore/sizehint.h>
18 #include <ioncore/resize.h>
19 #include "wmessage.h"
20 #include "inputp.h"
21
22
23 #define WMSG_BRUSH(WMSG) ((WMSG)->input.brush)
24 #define WMSG_WIN(WMSG) ((WMSG)->input.win.win)
25
26
27 /*{{{ Sizecalc */
28
29
30 static void get_geom(WMessage *wmsg, bool max, WRectangle *geom)
31 {
32     if(max){
33         geom->w=wmsg->input.last_fp.g.w;
34         geom->h=wmsg->input.last_fp.g.h;
35     }else{
36         geom->w=REGION_GEOM(wmsg).w;
37         geom->h=REGION_GEOM(wmsg).h;
38     }
39     geom->x=0;
40     geom->y=0;
41 }
42
43
44 static void wmsg_calc_size(WMessage *wmsg, WRectangle *geom)
45 {
46     WRectangle max_geom=*geom;
47     GrBorderWidths bdw;
48     int h=16;
49
50     if(WMSG_BRUSH(wmsg)!=NULL){
51         WRectangle g;
52         g.w=max_geom.w;
53         g.h=max_geom.h;
54         g.x=0;
55         g.y=0;
56         
57         fit_listing(WMSG_BRUSH(wmsg), &g, &(wmsg->listing));
58
59         grbrush_get_border_widths(WMSG_BRUSH(wmsg), &bdw);
60         
61         h=bdw.top+bdw.bottom+wmsg->listing.toth;
62     }
63     
64     if(h>max_geom.h || !(wmsg->input.last_fp.mode&REGION_FIT_BOUNDS))
65         h=max_geom.h;
66     
67     geom->h=h;
68     geom->w=max_geom.w;
69     geom->y=max_geom.y+max_geom.h-geom->h;
70     geom->x=max_geom.x;
71 }
72
73
74 void wmsg_size_hints(WMessage *wmsg, WSizeHints *hints_ret)
75 {
76     int w=1, h=1;
77     
78     if(WMSG_BRUSH(wmsg)!=NULL){
79         mod_query_get_minimum_extents(WMSG_BRUSH(wmsg), FALSE, &w, &h);
80
81         w+=grbrush_get_text_width(WMSG_BRUSH(wmsg), "xxxxx", 5);
82     }
83     
84     hints_ret->min_set=TRUE;
85     hints_ret->min_width=w;
86     hints_ret->min_height=h;
87 }
88
89
90 /*}}}*/
91
92
93 /*{{{ Draw */
94
95
96 GR_DEFATTR(active);
97 GR_DEFATTR(inactive);
98
99
100 static void init_attr()
101 {
102     GR_ALLOCATTR_BEGIN;
103     GR_ALLOCATTR(active);
104     GR_ALLOCATTR(inactive);
105     GR_ALLOCATTR_END;
106 }
107
108
109 static void wmsg_draw(WMessage *wmsg, bool complete)
110 {
111     WRectangle geom;
112     
113     if(WMSG_BRUSH(wmsg)==NULL)
114         return;
115     
116     get_geom(wmsg, FALSE, &geom);
117     
118     grbrush_begin(WMSG_BRUSH(wmsg), &geom, 
119                   (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
120     
121     grbrush_set_attr(WMSG_BRUSH(wmsg), REGION_IS_ACTIVE(wmsg)
122                                        ? GR_ATTR(active)
123                                        : GR_ATTR(inactive));
124     
125     draw_listing(WMSG_BRUSH(wmsg), &geom, &(wmsg->listing), 
126                  FALSE, GRATTR_NONE);
127     
128     grbrush_end(WMSG_BRUSH(wmsg));
129 }
130
131
132 /*}}}*/
133
134
135 /*{{{ Scroll */
136
137
138 static void wmsg_scrollup(WMessage *wmsg)
139 {
140     if(scrollup_listing(&(wmsg->listing)))
141         wmsg_draw(wmsg, TRUE);
142 }
143
144
145 static void wmsg_scrolldown(WMessage *wmsg)
146 {
147     if(scrolldown_listing(&(wmsg->listing)))
148         wmsg_draw(wmsg, TRUE);
149 }
150
151
152 /*}}}*/
153
154
155 /*{{{ Init, deinit draw config update */
156
157
158 static bool wmsg_init(WMessage *wmsg, WWindow *par, const WFitParams *fp,
159                       const char *msg)
160 {
161     char **ptr;
162     int k, n=0;
163     char *cmsg;
164     const char *p;
165     size_t l;
166     
167     p=msg;
168     while(1){
169         n=n+1;
170         p=strchr(p, '\n');
171         if(p==NULL || *(p+1)=='\0')
172             break;
173         p=p+1;
174     }
175     
176     if(n==0)
177         return FALSE;
178         
179     ptr=ALLOC_N(char*, n);
180     
181     if(ptr==NULL)
182         return FALSE;
183     
184     for(k=0; k<n; k++)
185         ptr[k]=NULL;
186     
187     p=msg;
188     k=0;
189     while(k<n){
190         l=strcspn(p, "\n");
191         cmsg=ALLOC_N(char, l+1);
192         if(cmsg==NULL){
193             while(k>0){
194                 k--;
195                 free(ptr[k]);
196             }
197             free(ptr);
198             return FALSE;
199         }
200         strncpy(cmsg, p, l);
201         cmsg[l]='\0';
202         ptr[k]=cmsg;
203         k++;
204         if(p[l]=='\0')
205             break;
206         p=p+l+1;
207     }
208     
209     init_attr();
210     
211     init_listing(&(wmsg->listing));
212     setup_listing(&(wmsg->listing), ptr, k, TRUE);
213     
214     if(!input_init((WInput*)wmsg, par, fp)){
215         deinit_listing(&(wmsg->listing));
216         return FALSE;
217     }
218
219     return TRUE;
220 }
221
222
223 WMessage *create_wmsg(WWindow *par, const WFitParams *fp, const char *msg)
224 {
225     CREATEOBJ_IMPL(WMessage, wmsg, (p, par, fp, msg));
226 }
227
228
229 static void wmsg_deinit(WMessage *wmsg)
230 {
231     if(wmsg->listing.strs!=NULL)
232         deinit_listing(&(wmsg->listing));
233
234     input_deinit((WInput*)wmsg);
235 }
236
237
238 static const char *wmsg_style(WMessage *wmsg)
239 {
240     return "input-message";
241 }
242
243
244 /*}}}*/
245
246
247 /*{{{ Dynamic function table and class implementation */
248
249
250 static DynFunTab wmsg_dynfuntab[]={
251     {window_draw, wmsg_draw},
252     {input_calc_size, wmsg_calc_size},
253     {input_scrollup, wmsg_scrollup},
254     {input_scrolldown, wmsg_scrolldown},
255     {(DynFun*)input_style, (DynFun*)wmsg_style},
256     {region_size_hints, wmsg_size_hints},
257     END_DYNFUNTAB
258 };
259
260
261 EXTL_EXPORT
262 IMPLCLASS(WMessage, WInput, wmsg_deinit, wmsg_dynfuntab);
263
264     
265 /*}}}*/