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