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