Released version 3-2015061300
[notion.git] / ioncore / saveload.c
blob150bf8dc43f94dd546a0b18295751c136f493f5f
1 /*
2 * ion/ioncore/saveload.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
10 #include <time.h>
11 #include <unistd.h>
13 #include <libtu/objp.h>
14 #include <libextl/readconfig.h>
15 #include <libextl/extl.h>
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"
29 static bool loading_layout=FALSE;
30 static bool layout_load_error=FALSE;
33 /*{{{ Session management module support */
36 static SMAddCallback *add_cb;
37 static SMCfgCallback *cfg_cb;
40 void ioncore_set_sm_callbacks(SMAddCallback *add, SMCfgCallback *cfg)
42 add_cb=add;
43 cfg_cb=cfg;
47 void ioncore_get_sm_callbacks(SMAddCallback **add, SMCfgCallback **cfg)
49 *add=add_cb;
50 *cfg=cfg_cb;
54 /*}}}*/
57 /*{{{ Load support functions */
60 static WPHolder **current_ph_p=NULL;
63 WPHolder *ioncore_get_load_pholder()
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;
75 WRegion *create_region_load(WWindow *par, const WFitParams *fp,
76 ExtlTab tab, WPHolder **sm_ph_p)
78 char *objclass=NULL, *name=NULL;
79 WRegionLoadCreateFn* fn=NULL;
80 WRegClassInfo *info=NULL;
81 WRegion *reg=NULL;
82 WPHolder **old_ph_p;
84 if(!extl_table_gets_s(tab, "type", &objclass))
85 return NULL;
87 if(objclass==NULL)
88 return NULL;
90 info=ioncore_lookup_regclass(objclass, FALSE);
91 if(info!=NULL)
92 fn=info->lc_fn;
94 if(fn==NULL){
95 warn(TR("Unknown class \"%s\", cannot create region."),
96 objclass);
97 layout_load_error=loading_layout;
98 return NULL;
101 free(objclass);
103 old_ph_p=current_ph_p;
104 current_ph_p=sm_ph_p;
106 reg=fn(par, fp, tab);
108 current_ph_p=old_ph_p;
110 if(reg!=NULL){
111 if(!OBJ_IS(reg, WClientWin)){
112 if(extl_table_gets_s(tab, "name", &name)){
113 region_set_name(reg, name);
114 free(name);
119 return reg;
123 /*}}}*/
126 /*{{{ Save support functions */
129 bool region_supports_save(WRegion *reg)
131 return HAS_DYN(reg, region_get_configuration);
135 ExtlTab region_get_base_configuration(WRegion *reg)
137 const char *name;
138 ExtlTab tab;
140 tab=extl_create_table();
142 extl_table_sets_s(tab, "type", OBJ_TYPESTR(reg));
144 name=region_name(reg);
146 if(name!=NULL && !OBJ_IS(reg, WClientWin))
147 extl_table_sets_s(tab, "name", name);
149 return tab;
153 static bool get_config_clientwins=TRUE;
156 ExtlTab region_get_configuration(WRegion *reg)
158 ExtlTab tab=extl_table_none();
159 if(get_config_clientwins || !OBJ_IS(reg, WClientWin)){
160 CALL_DYN_RET(tab, ExtlTab, region_get_configuration, reg, (reg));
162 return tab;
166 /*EXTL_DOC
167 * Get configuration tree. If \var{clientwins} is unset, client windows
168 * are filtered out.
170 EXTL_EXPORT_AS(WRegion, get_configuration)
171 ExtlTab region_get_configuration_extl(WRegion *reg, bool clientwins)
173 ExtlTab tab;
175 get_config_clientwins=clientwins;
177 tab=region_get_configuration(reg);
179 get_config_clientwins=TRUE;
181 return tab;
185 /*}}}*/
188 /*{{{ save_workspaces, load_workspaces */
191 static const char backup_msg[]=DUMMY_TR(
192 "There were errors loading layout. Backing up current layout savefile as\n"
193 "%s.\n"
194 "If you are _not_ running under a session manager and wish to restore your\n"
195 "old layout, copy this backup file over the layout savefile found in the\n"
196 "same directory while Ion is not running and after having fixed your other\n"
197 "configuration files that are causing this problem. (Maybe a missing\n"
198 "module?)");
201 bool ioncore_init_layout()
203 ExtlTab tab;
204 WScreen *scr;
205 bool ok;
206 int n=0;
208 ok=extl_read_savefile("saved_layout", &tab);
210 loading_layout=TRUE;
211 layout_load_error=FALSE;
213 FOR_ALL_SCREENS(scr){
214 ExtlTab scrtab=extl_table_none();
215 bool scrok=FALSE;
217 /* Potential Xinerama or such support should set the screen ID
218 * of the root window to less than zero, and number its own
219 * fake screens up from 0.
221 if(screen_id(scr)<0)
222 continue;
224 if(ok)
225 scrok=extl_table_geti_t(tab, screen_id(scr), &scrtab);
227 n+=(TRUE==screen_init_layout(scr, scrtab));
229 if(scrok)
230 extl_unref_table(scrtab);
233 loading_layout=FALSE;
235 if(layout_load_error){
236 time_t t=time(NULL);
237 char tm[]="saved_layout.backup-YYYYMMDDHHMMSS\0\0\0\0";
238 char *backup;
240 strftime(tm+20, 15, "%Y%m%d%H%M%S", localtime(&t));
241 backup=extl_get_savefile(tm);
242 if(backup==NULL){
243 warn(TR("Unable to get file for layout backup."));
244 return FALSE;
246 if(access(backup, F_OK)==0){
247 warn(TR("Backup file %s already exists."), backup);
248 free(backup);
249 return FALSE;
251 warn(TR(backup_msg), backup);
252 if(!extl_serialize(backup, tab))
253 warn(TR("Failed backup."));
254 free(backup);
257 if(n==0){
258 warn(TR("Unable to initialise layout on any screen."));
259 return FALSE;
260 }else{
261 return TRUE;
266 bool ioncore_save_layout()
268 WScreen *scr=NULL;
269 ExtlTab tab=extl_create_table();
270 bool ret;
272 if(tab==extl_table_none())
273 return FALSE;
275 FOR_ALL_SCREENS(scr){
276 ExtlTab scrtab;
278 /* See note above */
279 if(screen_id(scr)<0)
280 continue;
282 scrtab=region_get_configuration((WRegion*)scr);
284 if(scrtab==extl_table_none()){
285 warn(TR("Unable to get configuration for screen %d."),
286 screen_id(scr));
287 }else{
288 extl_table_seti_t(tab, screen_id(scr), scrtab);
289 extl_unref_table(scrtab);
293 ret=extl_write_savefile("saved_layout", tab);
295 extl_unref_table(tab);
297 if(!ret)
298 warn(TR("Unable to save layout."));
300 return ret;
304 /*}}}*/