]> git.decadent.org.uk Git - ion3.git/blob - ioncore/saveload.c
Imported Upstream version 20090110
[ion3.git] / ioncore / saveload.c
1 /*
2  * ion/ioncore/saveload.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 #include <time.h>
11 #include <unistd.h>
12
13 #include <libtu/objp.h>
14 #include <libextl/readconfig.h>
15 #include <libextl/extl.h>
16
17 #include "common.h"
18 #include "global.h"
19 #include "region.h"
20 #include "screen.h"
21 #include "saveload.h"
22 #include "names.h"
23 #include "attach.h"
24 #include "reginfo.h"
25 #include "extlconv.h"
26 #include "group-ws.h"
27
28
29 static bool loading_layout=FALSE;
30 static bool layout_load_error=FALSE;
31
32
33 /*{{{ Session management module support */
34
35
36 static SMAddCallback *add_cb;
37 static SMCfgCallback *cfg_cb;
38
39
40 void ioncore_set_sm_callbacks(SMAddCallback *add, SMCfgCallback *cfg)
41 {
42     add_cb=add;
43     cfg_cb=cfg;
44 }
45
46
47 void ioncore_get_sm_callbacks(SMAddCallback **add, SMCfgCallback **cfg)
48 {
49     *add=add_cb;
50     *cfg=cfg_cb;
51 }
52
53
54 /*}}}*/
55
56
57 /*{{{ Load support functions */
58
59
60 static WPHolder **current_ph_p=NULL;
61
62
63 WPHolder *ioncore_get_load_pholder()
64 {
65     if(current_ph_p==NULL){
66         return NULL;
67     }else{
68         WPHolder *ph=*current_ph_p;
69         *current_ph_p=NULL;
70         return ph;
71     }
72 }
73
74
75 WRegion *create_region_load(WWindow *par, const WFitParams *fp, 
76                             ExtlTab tab, WPHolder **sm_ph_p)
77 {
78     char *objclass=NULL, *name=NULL;
79     WRegionLoadCreateFn* fn=NULL;
80     WRegClassInfo *info=NULL;
81     WRegion *reg=NULL;
82     bool grouped=FALSE;
83     char *grouped_name=NULL;
84     WPHolder **old_ph_p;
85     
86     if(!extl_table_gets_s(tab, "type", &objclass))
87         return NULL;
88     
89     if(objclass==NULL)
90         return NULL;
91     
92     info=ioncore_lookup_regclass(objclass, FALSE);
93     if(info!=NULL)
94         fn=info->lc_fn;
95     
96     if(fn==NULL){
97         warn(TR("Unknown class \"%s\", cannot create region."),
98              objclass);
99         layout_load_error=loading_layout;
100         return NULL;
101     }
102
103     free(objclass);
104     
105     old_ph_p=current_ph_p;
106     current_ph_p=sm_ph_p;
107     
108     reg=fn(par, fp, tab);
109     
110     current_ph_p=old_ph_p;
111     
112     if(reg!=NULL){
113         if(!OBJ_IS(reg, WClientWin)){
114             if(extl_table_gets_s(tab, "name", &name)){
115                 region_set_name(reg, name);
116                 free(name);
117             }
118         }
119     }
120     
121     return reg;
122 }
123
124     
125 /*}}}*/
126
127
128 /*{{{ Save support functions */
129
130
131 bool region_supports_save(WRegion *reg)
132 {
133     return HAS_DYN(reg, region_get_configuration);
134 }
135
136
137 ExtlTab region_get_base_configuration(WRegion *reg)
138 {
139     const char *name;
140     ExtlTab tab;
141     
142     tab=extl_create_table();
143     
144     extl_table_sets_s(tab, "type", OBJ_TYPESTR(reg));
145     
146     name=region_name(reg);
147     
148     if(name!=NULL && !OBJ_IS(reg, WClientWin))
149         extl_table_sets_s(tab, "name", name);
150     
151     return tab;
152 }
153
154
155 static bool get_config_clientwins=TRUE;
156
157
158 ExtlTab region_get_configuration(WRegion *reg)
159 {
160     ExtlTab tab=extl_table_none();
161     if(get_config_clientwins || !OBJ_IS(reg, WClientWin)){
162         CALL_DYN_RET(tab, ExtlTab, region_get_configuration, reg, (reg));
163     }
164     return tab;
165 }
166
167
168 /*EXTL_DOC
169  * Get configuration tree. If \var{clientwins} is unset, client windows
170  * are filtered out.
171  */
172 EXTL_EXPORT_AS(WRegion, get_configuration)
173 ExtlTab region_get_configuration_extl(WRegion *reg, bool clientwins)
174 {
175     ExtlTab tab;
176     
177     get_config_clientwins=clientwins;
178     
179     tab=region_get_configuration(reg);
180     
181     get_config_clientwins=TRUE;
182     
183     return tab;
184 }
185
186
187 /*}}}*/
188
189
190 /*{{{ save_workspaces, load_workspaces */
191
192
193 static const char backup_msg[]=DUMMY_TR(
194 "There were errors loading layout. Backing up current layout savefile as\n"
195 "%s.\n"
196 "If you are _not_ running under a session manager and wish to restore your\n"
197 "old layout, copy this backup file over the layout savefile found in the\n"
198 "same directory while Ion is not running and after having fixed your other\n"
199 "configuration files that are causing this problem. (Maybe a missing\n"
200 "module?)");
201
202
203 bool ioncore_init_layout()
204 {
205     ExtlTab tab;
206     WScreen *scr;
207     bool ok;
208     int n=0;
209     
210     ok=extl_read_savefile("saved_layout", &tab);
211     
212     loading_layout=TRUE;
213     layout_load_error=FALSE;
214     
215     FOR_ALL_SCREENS(scr){
216         ExtlTab scrtab=extl_table_none();
217         bool scrok=FALSE;
218         
219         /* Potential Xinerama or such support should set the screen ID
220          * of the root window to less than zero, and number its own
221          * fake screens up from 0.
222          */
223         if(screen_id(scr)<0)
224             continue;
225
226         if(ok)
227             scrok=extl_table_geti_t(tab, screen_id(scr), &scrtab);
228         
229         n+=(TRUE==screen_init_layout(scr, scrtab));
230         
231         if(scrok)
232             extl_unref_table(scrtab);
233     }
234
235     loading_layout=FALSE;
236
237     if(layout_load_error){
238         time_t t=time(NULL);
239         char tm[]="saved_layout.backup-YYYYMMDDHHMMSS\0\0\0\0";
240         char *backup;
241         
242         strftime(tm+20, 15, "%Y%m%d%H%M%S", localtime(&t));
243         backup=extl_get_savefile(tm);
244         if(backup==NULL){
245             warn(TR("Unable to get file for layout backup."));
246             return FALSE;
247         }
248         if(access(backup, F_OK)==0){
249             warn(TR("Backup file %s already exists."), backup);
250             free(backup);
251             return FALSE;
252         }
253         warn(TR(backup_msg), backup);
254         if(!extl_serialise(backup, tab))
255             warn(TR("Failed backup."));
256         free(backup);
257     }
258         
259     if(n==0){
260         warn(TR("Unable to initialise layout on any screen."));
261         return FALSE;
262     }else{
263         return TRUE;
264     }
265 }
266
267
268 bool ioncore_save_layout()
269 {
270     WScreen *scr=NULL;
271     ExtlTab tab=extl_create_table();
272     bool ret;
273     
274     if(tab==extl_table_none())
275         return FALSE;
276     
277     FOR_ALL_SCREENS(scr){
278         ExtlTab scrtab;
279         
280         /* See note above */
281         if(screen_id(scr)<0)
282             continue;
283             
284         scrtab=region_get_configuration((WRegion*)scr);
285         
286         if(scrtab==extl_table_none()){
287             warn(TR("Unable to get configuration for screen %d."),
288                  screen_id(scr));
289         }else{
290             extl_table_seti_t(tab, screen_id(scr), scrtab);
291             extl_unref_table(scrtab);
292         }
293     }
294     
295     ret=extl_write_savefile("saved_layout", tab);
296     
297     extl_unref_table(tab);
298     
299     if(!ret)
300         warn(TR("Unable to save layout."));
301         
302     return ret;
303 }
304
305
306 /*}}}*/
307
308