1 /*
2  * Portions of this file are copyright Rebirth contributors and licensed as
3  * described in COPYING.txt.
4  * Portions of this file are copyright Parallax Software and licensed
5  * according to the Parallax license below.
6  * See COPYING.txt for license details.
7 
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18 */
19 
20 /*
21  *
22  * Autosave system:
23  * Saves current mine to disk to prevent loss of work, and support undo.
24  *
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <math.h>
31 #include <string.h>
32 #include <time.h>
33 
34 #include "dxxerror.h"
35 
36 #include "inferno.h"
37 #include "editor.h"
38 #include "u_mem.h"
39 #include "ui.h"
40 #include "strutil.h"
41 
42 #include "compiler-cf_assert.h"
43 
44 namespace dcx {
45 
46 #define AUTOSAVE_PERIOD 5			// Number of minutes for timed autosave
47 
48 int		Autosave_count;
49 
50 namespace {
51 
52 static int Autosave_numfiles;
53 static int Autosave_total;
54 static int undo_count;
55 
set_autosave_name(mine_filename_type & out,const std::array<char,PATH_MAX> & in,const unsigned i)56 const char *set_autosave_name(mine_filename_type &out, const std::array<char, PATH_MAX> &in, const unsigned i)
57 {
58 	d_strupr(out, in);
59 	char *ext;
60 #define DXX_AUTOSAVE_MINE_EXTENSION	".MIN"
61 	if (!strcmp(out.data(), "*" DXX_AUTOSAVE_MINE_EXTENSION))
62 	{
63 #define DXX_DEFAULT_AUTOSAVE_MINE_NAME	"TEMP" DXX_AUTOSAVE_MINE_EXTENSION
64 		strcpy(out.data(), DXX_DEFAULT_AUTOSAVE_MINE_NAME);
65 		ext = &out[sizeof(DXX_DEFAULT_AUTOSAVE_MINE_NAME) - sizeof(DXX_AUTOSAVE_MINE_EXTENSION)];
66 	}
67 	else
68 	{
69 		ext = strstr(out.data(), DXX_AUTOSAVE_MINE_EXTENSION);
70 		if (!ext)
71 			return ext;
72 	}
73 #undef DXX_AUTOSAVE_MINE_EXTENSION
74 	cf_assert(i < 10);
75 	snprintf(ext + 2, 3, "%u", i);
76 	return ext;
77 }
78 
79 static int Timer_save_flag;
80 
81 }
82 int		Autosave_flag;
83 
84 std::array<const char *, 10> undo_status;
85 
init_autosave(void)86 void init_autosave(void) {
87 //    int i;
88 
89     Autosave_count = 0;
90     Autosave_numfiles = 0;
91 	 Autosave_flag = 0;
92     undo_count = 0;
93     autosave_mine(mine_filename);
94 }
95 
close_autosave(void)96 void close_autosave(void) {
97 	const unsigned t = Autosave_total;
98 	cf_assert(t < 10);
99 	for (unsigned i = 0; i < t; ++i)
100 	{
101 		mine_filename_type delname;
102 		if (set_autosave_name(delname, mine_filename, i))
103 			PHYSFS_delete(delname.data());
104     }
105 }
106 
autosave_mine(const std::array<char,PATH_MAX> & name)107 void autosave_mine(const std::array<char, PATH_MAX> &name)
108 {
109 	if (Autosave_flag) {
110 		mine_filename_type savename;
111 		if (!set_autosave_name(savename, name, Autosave_count))
112 			return;
113 
114 	    med_save_mine( savename );
115 	    Autosave_count++;
116 	    if (undo_count > 0) undo_count--;
117 	    if (Autosave_count > 9) Autosave_count -= 10;
118 	    if (Autosave_numfiles < 10)
119 	        Autosave_numfiles++;
120 	    if (Autosave_total < 10)
121 	        Autosave_total++;
122 	}
123 }
124 
125 tm Editor_time_of_day;
126 
print_clock(grs_canvas & canvas,const grs_font & cv_font)127 static void print_clock(grs_canvas &canvas, const grs_font &cv_font)
128 {
129 	gr_set_fontcolor(canvas, CBLACK, CGREY);
130 	std::array<char, 20> message;
131 	if (!strftime(message.data(), message.size(), "%m-%d %H:%M:%S", &Editor_time_of_day))
132 		message[0] = 0;
133 	const auto &&[w, h] = gr_get_string_size(cv_font, message.data());
134 	const auto color = CGREY;
135 	gr_rect(canvas, 700, 0, 799, h + 1, color);
136 	gr_string(canvas, cv_font, 700, 0, message.data(), w, h);
137 	gr_set_fontcolor(canvas, CBLACK, CWHITE);
138 }
139 
set_editor_time_of_day()140 void set_editor_time_of_day()
141 {
142 	time_t	 ltime;
143 
144 	time( &ltime );
145 	Editor_time_of_day = *localtime( &ltime );
146 }
147 
TimedAutosave(const std::array<char,PATH_MAX> & name)148 void TimedAutosave(const std::array<char, PATH_MAX> &name)
149 {
150 	auto &canvas = grd_curscreen->sc_canvas;
151 	gr_set_current_canvas(canvas);
152 	{
153 		print_clock(canvas, *canvas.cv_font);
154 	}
155 
156 
157 #ifndef DEMO
158 	const auto &minute = Editor_time_of_day.tm_min;
159 	if (minute%AUTOSAVE_PERIOD != 0)
160 		Timer_save_flag = 1;
161 
162 	if ((minute%AUTOSAVE_PERIOD == 0) && (Timer_save_flag)) {
163 		time_t	 ltime;
164 
165 		autosave_mine(name);
166 		Timer_save_flag = 0;
167 		time( &ltime );
168    	diagnostic_message_fmt("Mine Autosaved at %s\n", ctime(&ltime));
169 	}
170 #endif
171 
172 }
173 
174 
undo(void)175 int undo( void ) {
176 	Int3();
177 	return 2;
178 }
179 
180 
181 }
182