Subversion Repositories SvarDOS

Rev

Rev 619 | Rev 625 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 619 Rev 624
1
/*
1
/*
2
 * SVARDOS INSTALL PROGRAM
2
 * SVARDOS INSTALL PROGRAM
3
 * Copyright (C) 2021 Mateusz Viste
-
 
4
 *
3
 *
5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
4
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
6
 *
5
 *
7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
6
 * COPYRIGHT (C) 2016-2022 MATEUSZ VISTE, ALL RIGHTS RESERVED.
8
 *
7
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
9
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
10
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
13
 * Software is furnished to do so, subject to the following conditions:
15
 *
14
 *
16
 * The above copyright notice and this permission notice shall be included in
15
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
16
 * all copies or substantial portions of the Software.
18
 *
17
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
24
 * DEALINGS IN THE SOFTWARE.
26
 *
25
 *
27
 * http://svardos.osdn.io
26
 * http://svardos.osdn.io
28
 */
27
 */
29
 
28
 
30
#include <dos.h>
29
#include <dos.h>
31
#include <direct.h>  /* mkdir() */
30
#include <direct.h>  /* mkdir() */
32
#include <stdio.h>   /* printf() and friends */
31
#include <stdio.h>   /* printf() and friends */
33
#include <stdlib.h>  /* system() */
32
#include <stdlib.h>  /* system() */
34
#include <string.h>  /* memcpy() */
33
#include <string.h>  /* memcpy() */
35
#include <unistd.h>
34
#include <unistd.h>
36
 
35
 
37
#include "kitten\kitten.h"
36
#include "svarlang.lib\svarlang.h"
38
 
37
 
39
#include "input.h"
38
#include "input.h"
40
#include "video.h"
39
#include "video.h"
41
 
40
 
42
/* keyboard layouts and locales */
41
/* keyboard layouts and locales */
43
#include "keylay.h"
42
#include "keylay.h"
44
#include "keyoff.h"
43
#include "keyoff.h"
45
 
44
 
46
/* color scheme (color, mono) */
45
/* color scheme (color, mono) */
47
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
46
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
48
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
47
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
49
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
48
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
50
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
49
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
51
 
50
 
52
/* mono flag */
51
/* mono flag */
53
static int mono = 0;
52
static int mono = 0;
54
 
53
 
55
/* how much disk space does SvarDOS require (in MiB) */
54
/* how much disk space does SvarDOS require (in MiB) */
56
#define SVARDOS_DISK_REQ 8
55
#define SVARDOS_DISK_REQ 8
57
 
56
 
58
/* menu screens can output only one of these: */
57
/* menu screens can output only one of these: */
59
#define MENUNEXT 0
58
#define MENUNEXT 0
60
#define MENUPREV -1
59
#define MENUPREV -1
61
#define MENUQUIT -2
60
#define MENUQUIT -2
62
 
61
 
63
/* a convenience 'function' used for debugging */
62
/* a convenience 'function' used for debugging */
64
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
63
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
65
 
64
 
66
struct slocales {
65
struct slocales {
67
  char lang[4];
66
  char lang[4];
68
  char *keybcode;
67
  const char *keybcode;
69
  unsigned int codepage;
68
  unsigned int codepage;
70
  int egafile;
69
  int egafile;
71
  int keybfile;
70
  int keybfile;
72
  int keyboff;
71
  int keyboff;
73
  int keyblen;
72
  int keyblen;
74
  unsigned int keybid;
73
  unsigned int keybid;
75
};
74
};
76
 
75
 
77
 
76
 
78
/* reboot the computer */
77
/* reboot the computer */
79
static void reboot(void) {
78
static void reboot(void) {
80
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
79
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
81
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
80
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
82
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
81
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
83
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
82
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
84
}
83
}
85
 
84
 
86
 
85
 
87
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
86
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
88
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
87
static int putstringwrap(int y, int x, unsigned short attr, const char *s) {
89
  int linew, lincount;
88
  int linew, lincount;
90
  linew = 80;
89
  linew = 80;
91
  if (x >= 0) linew -= (x << 1);
90
  if (x >= 0) linew -= (x << 1);
92
 
91
 
93
  for (lincount = 1; y+lincount < 25; lincount++) {
92
  for (lincount = 1; y+lincount < 25; lincount++) {
94
    int i, len = linew;
93
    int i, len = linew;
95
    for (i = 0; i <= linew; i++) {
94
    for (i = 0; i <= linew; i++) {
96
      if (s[i] == ' ') len = i;
95
      if (s[i] == ' ') len = i;
97
      if (s[i] == '\n') {
96
      if (s[i] == '\n') {
98
        len = i;
97
        len = i;
99
        break;
98
        break;
100
      }
99
      }
101
      if (s[i] == 0) {
100
      if (s[i] == 0) {
102
        len = i;
101
        len = i;
103
        break;
102
        break;
104
      }
103
      }
105
    }
104
    }
106
    video_putstring(y++, x, attr, s, len);
105
    video_putstring(y++, x, attr, s, len);
107
    s += len;
106
    s += len;
108
    if (*s == 0) break;
107
    if (*s == 0) break;
109
    s += 1; /* skip the whitespace char */
108
    s += 1; /* skip the whitespace char */
110
  }
109
  }
111
  return(lincount);
110
  return(lincount);
112
}
111
}
113
 
112
 
114
 
113
 
115
/* an NLS wrapper around video_putstring(), also performs line wrapping when
114
/* an NLS wrapper around video_putstring(), also performs line wrapping when
116
 * needed. returns the amount of lines that were output */
115
 * needed. returns the amount of lines that were output */
117
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
116
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin) {
118
  s = kittengets(nlsmaj, nlsmin, s);
117
  const char *s = svarlang_str(nlsmaj, nlsmin);
-
 
118
  if (s == NULL) s = "";
119
  return(putstringwrap(y, x, attr, s));
119
  return(putstringwrap(y, x, attr, s));
120
}
120
}
121
 
121
 
122
 
122
 
123
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
123
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
124
 * exists already! returns 0 on success. */
124
 * exists already! returns 0 on success. */
125
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
125
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
126
  FILE *fd1, *fd2;
126
  FILE *fd1, *fd2;
127
  size_t sz;
127
  size_t sz;
128
  int res = -1; /* assume failure */
128
  int res = -1; /* assume failure */
129
 
129
 
130
  /* open files */
130
  /* open files */
131
  fd1 = fopen(f1, "rb");
131
  fd1 = fopen(f1, "rb");
132
  fd2 = fopen(f2, "wb");
132
  fd2 = fopen(f2, "wb");
133
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
133
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
134
 
134
 
135
  /* copy data */
135
  /* copy data */
136
  for (;;) {
136
  for (;;) {
137
    sz = fread(buff, 1, buffsz, fd1);
137
    sz = fread(buff, 1, buffsz, fd1);
138
    if (sz == 0) {
138
    if (sz == 0) {
139
      if (feof(fd1) != 0) break;
139
      if (feof(fd1) != 0) break;
140
      goto QUIT;
140
      goto QUIT;
141
    }
141
    }
142
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
142
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
143
  }
143
  }
144
 
144
 
145
  res = 0; /* success */
145
  res = 0; /* success */
146
 
146
 
147
  QUIT:
147
  QUIT:
148
  if (fd1 != NULL) fclose(fd1);
148
  if (fd1 != NULL) fclose(fd1);
149
  if (fd2 != NULL) fclose(fd2);
149
  if (fd2 != NULL) fclose(fd2);
150
  return(res);
150
  return(res);
151
}
151
}
152
 
152
 
153
 
153
 
154
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
154
static int menuselect(int ypos, int xpos, int height, const char **list, int listlen) {
155
  int i, offset = 0, res = 0, count, width = 0;
155
  int i, offset = 0, res = 0, count, width = 0;
156
  /* count how many positions there is, and check their width */
156
  /* count how many positions there is, and check their width */
157
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
157
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
158
    int len = strlen(list[count]);
158
    int len = strlen(list[count]);
159
    if (len > width) width = len;
159
    if (len > width) width = len;
160
  }
160
  }
161
 
161
 
162
  /* if xpos negative, means 'center out' */
162
  /* if xpos negative, means 'center out' */
163
  if (xpos < 0) xpos = 39 - (width >> 1);
163
  if (xpos < 0) xpos = 39 - (width >> 1);
164
 
164
 
165
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
165
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
166
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
166
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
167
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
167
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
168
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
168
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
169
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
169
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
170
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
170
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
171
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
171
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
172
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
172
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
173
 
173
 
174
  for (;;) {
174
  for (;;) {
175
    int key;
175
    int key;
176
    /* list of selectable items */
176
    /* list of selectable items */
177
    for (i = 0; i < height - 2; i++) {
177
    for (i = 0; i < height - 2; i++) {
178
      if (i + offset == res) {
178
      if (i + offset == res) {
179
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
179
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
180
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
180
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
181
        video_movecursor(ypos + 1 + i, xpos);
181
        video_movecursor(ypos + 1 + i, xpos);
182
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
182
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
183
      } else if (i + offset < count) {
183
      } else if (i + offset < count) {
184
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
184
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
185
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
185
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
186
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
186
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
187
      } else {
187
      } else {
188
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
188
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
189
      }
189
      }
190
    }
190
    }
191
    key = input_getkey();
191
    key = input_getkey();
192
    if (key == 0x0D) { /* ENTER */
192
    if (key == 0x0D) { /* ENTER */
193
      return(res);
193
      return(res);
194
    } else if (key == 0x148) { /* up */
194
    } else if (key == 0x148) { /* up */
195
      if (res > 0) {
195
      if (res > 0) {
196
        res--;
196
        res--;
197
        if (res < offset) offset = res;
197
        if (res < offset) offset = res;
198
      }
198
      }
199
    } else if (key == 0x150) { /* down */
199
    } else if (key == 0x150) { /* down */
200
      if (res+1 < count) {
200
      if (res+1 < count) {
201
        res++;
201
        res++;
202
        if (res > offset + height - 3) offset = res - (height - 3);
202
        if (res > offset + height - 3) offset = res - (height - 3);
203
      }
203
      }
204
    } else if (key == 0x147) { /* home */
204
    } else if (key == 0x147) { /* home */
205
      res = 0;
205
      res = 0;
206
      offset = 0;
206
      offset = 0;
207
    } else if (key == 0x14F) { /* end */
207
    } else if (key == 0x14F) { /* end */
208
      res = count - 1;
208
      res = count - 1;
209
      if (res > offset + height - 3) offset = res - (height - 3);
209
      if (res > offset + height - 3) offset = res - (height - 3);
210
    } else if (key == 0x1B) {  /* ESC */
210
    } else if (key == 0x1B) {  /* ESC */
211
      return(-1);
211
      return(-1);
212
    }/* else {
212
    }/* else {
213
      char buf[8];
213
      char buf[8];
214
      snprintf(buf, sizeof(buf), "0x%02X ", key);
214
      snprintf(buf, sizeof(buf), "0x%02X ", key);
215
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
215
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
216
    }*/
216
    }*/
217
  }
217
  }
218
}
218
}
219
 
219
 
220
static void newscreen(int statusbartype) {
220
static void newscreen(int statusbartype) {
221
  char *msg;
221
  const char *msg;
222
  msg = kittengets(0, 0, "SVARDOS INSTALLATION");
222
  msg = svarlang_strid(0x00); /* "SVARDOS INSTALLATION" */
223
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
223
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
224
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
224
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
225
  video_clear(COLOR_BODY[mono], 80, -80);
225
  video_clear(COLOR_BODY[mono], 80, -80);
226
  switch (statusbartype) {
226
  switch (statusbartype) {
227
    case 1:
227
    case 1:
228
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
228
      msg = svarlang_strid(0x000B); /* "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS" */
229
      break;
229
      break;
230
    case 2:
230
    case 2:
231
      msg = kittengets(0, 5, "Press any key...");
231
      msg = svarlang_strid(0x0005); /* "Press any key..." */
232
      break;
232
      break;
233
    case 3:
233
    case 3:
234
      msg = "";
234
      msg = "";
235
      break;
235
      break;
236
    default:
236
    default:
237
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
237
      msg = svarlang_strid(0x000A); /* "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen" */
238
      break;
238
      break;
239
  }
239
  }
240
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
240
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
241
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
241
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
242
  video_movecursor(25,0);
242
  video_movecursor(25,0);
243
}
243
}
244
 
244
 
245
/* fills a slocales struct accordingly to the value of its keyboff member */
245
/* fills a slocales struct accordingly to the value of its keyboff member */
246
static void kblay2slocal(struct slocales *locales) {
246
static void kblay2slocal(struct slocales *locales) {
247
  char *m;
247
  const char *m;
248
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
248
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
249
  m++;
249
  m++;
250
  /* skip keyb code and copy it to locales.keybcode */
250
  /* skip keyb code and copy it to locales.keybcode */
251
  locales->keybcode = m;
251
  locales->keybcode = m;
252
  for (; *m != 0; m++);
252
  for (; *m != 0; m++);
253
  /* */
253
  /* */
254
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
254
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
255
  locales->egafile = m[3];
255
  locales->egafile = m[3];
256
  locales->keybfile = m[4];
256
  locales->keybfile = m[4];
257
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
257
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
258
}
258
}
259
 
259
 
260
static int selectlang(struct slocales *locales) {
260
static int selectlang(struct slocales *locales) {
261
  int choice, x;
261
  int choice, x;
262
  char *msg;
262
  const char *msg;
263
  char *langlist[] = {
263
  const char *langlist[] = {
264
    "English",
264
    "English",
265
    "French",
265
    "French",
266
    "German",
266
    "German",
267
    "Italian",
267
    "Italian",
268
    "Polish",
268
    "Polish",
269
    "Russian",
269
    "Russian",
270
    "Slovene",
270
    "Slovene",
271
    "Swedish",
271
    "Swedish",
272
    "Turkish",
272
    "Turkish",
273
    NULL
273
    NULL
274
  };
274
  };
275
 
275
 
276
  newscreen(1);
276
  newscreen(1);
277
  msg = kittengets(1, 0, "Welcome to SvarDOS");
277
  msg = svarlang_strid(0x0100); /* "Welcome to SvarDOS" */
278
  x = 40 - (strlen(msg) >> 1);
278
  x = 40 - (strlen(msg) >> 1);
279
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
279
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
280
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
280
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
281
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
281
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1); /* "Please select your language from the list below:" */
282
  choice = menuselect(11, -1, 11, langlist, -1);
282
  choice = menuselect(11, -1, 11, langlist, -1);
283
  if (choice < 0) return(MENUPREV);
283
  if (choice < 0) return(MENUPREV);
284
  /* populate locales with default values */
284
  /* populate locales with default values */
285
  memset(locales, 0, sizeof(struct slocales));
285
  memset(locales, 0, sizeof(struct slocales));
286
  switch (choice) {
286
  switch (choice) {
287
    case 1:
287
    case 1:
288
      strcpy(locales->lang, "FR");
288
      strcpy(locales->lang, "FR");
289
      locales->keyboff = OFFLOC_FR;
289
      locales->keyboff = OFFLOC_FR;
290
      locales->keyblen = OFFLEN_FR;
290
      locales->keyblen = OFFLEN_FR;
291
      break;
291
      break;
292
    case 2:
292
    case 2:
293
      strcpy(locales->lang, "DE");
293
      strcpy(locales->lang, "DE");
294
      locales->keyboff = OFFLOC_DE;
294
      locales->keyboff = OFFLOC_DE;
295
      locales->keyblen = OFFLEN_DE;
295
      locales->keyblen = OFFLEN_DE;
296
      break;
296
      break;
297
    case 3:
297
    case 3:
298
      strcpy(locales->lang, "IT");
298
      strcpy(locales->lang, "IT");
299
      locales->keyboff = OFFLOC_IT;
299
      locales->keyboff = OFFLOC_IT;
300
      locales->keyblen = OFFLEN_IT;
300
      locales->keyblen = OFFLEN_IT;
301
      break;
301
      break;
302
    case 4:
302
    case 4:
303
      strcpy(locales->lang, "PL");
303
      strcpy(locales->lang, "PL");
304
      locales->keyboff = OFFLOC_PL;
304
      locales->keyboff = OFFLOC_PL;
305
      locales->keyblen = OFFLEN_PL;
305
      locales->keyblen = OFFLEN_PL;
306
      break;
306
      break;
307
    case 5:
307
    case 5:
308
      strcpy(locales->lang, "RU");
308
      strcpy(locales->lang, "RU");
309
      locales->keyboff = OFFLOC_RU;
309
      locales->keyboff = OFFLOC_RU;
310
      locales->keyblen = OFFLEN_RU;
310
      locales->keyblen = OFFLEN_RU;
311
      break;
311
      break;
312
    case 6:
312
    case 6:
313
      strcpy(locales->lang, "SI");
313
      strcpy(locales->lang, "SI");
314
      locales->keyboff = OFFLOC_SI;
314
      locales->keyboff = OFFLOC_SI;
315
      locales->keyblen = OFFLEN_SI;
315
      locales->keyblen = OFFLEN_SI;
316
      break;
316
      break;
317
    case 7:
317
    case 7:
318
      strcpy(locales->lang, "SV");
318
      strcpy(locales->lang, "SV");
319
      locales->keyboff = OFFLOC_SV;
319
      locales->keyboff = OFFLOC_SV;
320
      locales->keyblen = OFFLEN_SV;
320
      locales->keyblen = OFFLEN_SV;
321
      break;
321
      break;
322
    case 8:
322
    case 8:
323
      strcpy(locales->lang, "TR");
323
      strcpy(locales->lang, "TR");
324
      locales->keyboff = OFFLOC_TR;
324
      locales->keyboff = OFFLOC_TR;
325
      locales->keyblen = OFFLEN_TR;
325
      locales->keyblen = OFFLEN_TR;
326
      break;
326
      break;
327
    default:
327
    default:
328
      strcpy(locales->lang, "EN");
328
      strcpy(locales->lang, "EN");
329
      locales->keyboff = 0;
329
      locales->keyboff = 0;
330
      locales->keyblen = OFFCOUNT;
330
      locales->keyblen = OFFCOUNT;
331
      break;
331
      break;
332
  }
332
  }
333
  /* populate the slocales struct accordingly to the keyboff member */
333
  /* populate the slocales struct accordingly to the keyboff member */
334
  kblay2slocal(locales);
334
  kblay2slocal(locales);
335
  /* */
335
  /* */
336
  return(MENUNEXT);
336
  return(MENUNEXT);
337
}
337
}
338
 
338
 
339
 
339
 
340
static int selectkeyb(struct slocales *locales) {
340
static int selectkeyb(struct slocales *locales) {
341
  int menuheight, choice;
341
  int menuheight, choice;
342
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
342
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
343
  newscreen(0);
343
  newscreen(0);
344
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
344
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5); /* "SvarDOS supports different keyboard layouts */
345
  menuheight = locales->keyblen + 2;
345
  menuheight = locales->keyblen + 2;
346
  if (menuheight > 13) menuheight = 13;
346
  if (menuheight > 13) menuheight = 13;
347
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
347
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
348
  if (choice < 0) return(MENUPREV);
348
  if (choice < 0) return(MENUPREV);
349
  /* (re)load the keyboard layout & codepage setup */
349
  /* (re)load the keyboard layout & codepage setup */
350
  locales->keyboff += choice;
350
  locales->keyboff += choice;
351
  kblay2slocal(locales);
351
  kblay2slocal(locales);
352
  return(MENUNEXT);
352
  return(MENUNEXT);
353
}
353
}
354
 
354
 
355
 
355
 
356
/* returns 0 if installation must proceed, non-zero otherwise */
356
/* returns 0 if installation must proceed, non-zero otherwise */
357
static int welcomescreen(void) {
357
static int welcomescreen(void) {
358
  int c;
358
  int c;
359
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
359
  const char *choice[3];
360
  choice[0] = kittengets(0, 1, choice[0]);
360
  choice[0] = svarlang_strid(0x0001);
361
  choice[1] = kittengets(0, 2, choice[1]);
361
  choice[1] = svarlang_strid(0x0002);
-
 
362
  choice[2] = NULL;
362
  newscreen(0);
363
  newscreen(0);
363
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install SvarDOS: a free, MSDOS-compatible operating system based on the FreeDOS kernel. SvarDOS targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once SvarDOS is installed.");
364
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0); /* "You are about to install SvarDOS */
364
  c = menuselect(13, -1, 4, choice, -1);
365
  c = menuselect(13, -1, 4, choice, -1);
365
  if (c < 0) return(MENUPREV);
366
  if (c < 0) return(MENUPREV);
366
  if (c == 0) return(MENUNEXT);
367
  if (c == 0) return(MENUNEXT);
367
  return(MENUQUIT);
368
  return(MENUQUIT);
368
}
369
}
369
 
370
 
370
 
371
 
371
/* returns 1 if drive is removable, 0 if not, -1 on error */
372
/* returns 1 if drive is removable, 0 if not, -1 on error */
372
static int isdriveremovable(int drv) {
373
static int isdriveremovable(int drv) {
373
  union REGS r;
374
  union REGS r;
374
  r.x.ax = 0x4408;
375
  r.x.ax = 0x4408;
375
  r.h.bl = drv;
376
  r.h.bl = drv;
376
  int86(0x21, &r, &r);
377
  int86(0x21, &r, &r);
377
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
378
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
378
  if (r.x.cflag != 0) return(-1);
379
  if (r.x.cflag != 0) return(-1);
379
  if (r.x.ax == 0) return(1);
380
  if (r.x.ax == 0) return(1);
380
  return(0);
381
  return(0);
381
}
382
}
382
 
383
 
383
 
384
 
384
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
385
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
385
static int disksize(int drv) {
386
static int disksize(int drv) {
386
  long res;
387
  long res;
387
  union REGS r;
388
  union REGS r;
388
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
389
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
389
  r.h.dl = drv;  /* A=1, B=2, etc */
390
  r.h.dl = drv;  /* A=1, B=2, etc */
390
  int86(0x21, &r, &r);
391
  int86(0x21, &r, &r);
391
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
392
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
392
  res = r.x.ax;  /* sectors per cluster */
393
  res = r.x.ax;  /* sectors per cluster */
393
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
394
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
394
  res *= r.x.cx; /* bytes per sector */
395
  res *= r.x.cx; /* bytes per sector */
395
  res >>= 20;    /* convert bytes to MiB */
396
  res >>= 20;    /* convert bytes to MiB */
396
  return(res);
397
  return(res);
397
}
398
}
398
 
399
 
399
 
400
 
400
/* returns 0 if disk is empty, non-zero otherwise */
401
/* returns 0 if disk is empty, non-zero otherwise */
401
static int diskempty(int drv) {
402
static int diskempty(int drv) {
402
  unsigned int rc;
403
  unsigned int rc;
403
  int res;
404
  int res;
404
  char buff[8];
405
  char buff[8];
405
  struct find_t fileinfo;
406
  struct find_t fileinfo;
406
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
407
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
407
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
408
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
408
  if (rc == 0) {
409
  if (rc == 0) {
409
    res = 1; /* call successfull means disk is not empty */
410
    res = 1; /* call successfull means disk is not empty */
410
  } else {
411
  } else {
411
    res = 0;
412
    res = 0;
412
  }
413
  }
413
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
414
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
414
  return(res);
415
  return(res);
415
}
416
}
416
 
417
 
417
#ifdef DEADCODE
418
#ifdef DEADCODE
418
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
419
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
419
static int set_cur_drive(char drv) {
420
static int set_cur_drive(char drv) {
420
  union REGS r;
421
  union REGS r;
421
  if ((drv < 'A') || (drv > 'Z')) return(-1);
422
  if ((drv < 'A') || (drv > 'Z')) return(-1);
422
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
423
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
423
  r.h.dl = drv - 'A';
424
  r.h.dl = drv - 'A';
424
  int86(0x21, &r, &r);
425
  int86(0x21, &r, &r);
425
  if (r.h.al < drv - 'A') return(-1);
426
  if (r.h.al < drv - 'A') return(-1);
426
  return(0);
427
  return(0);
427
}
428
}
428
#endif
429
#endif
429
 
430
 
430
 
431
 
431
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
432
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
432
static int get_cur_drive(void) {
433
static int get_cur_drive(void) {
433
  union REGS r;
434
  union REGS r;
434
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
435
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
435
  int86(0x21, &r, &r);
436
  int86(0x21, &r, &r);
436
  return(r.h.al);
437
  return(r.h.al);
437
}
438
}
438
 
439
 
439
 
440
 
440
/* returns 0 if file exists, non-zero otherwise */
441
/* returns 0 if file exists, non-zero otherwise */
441
static int fileexists(const char *fname) {
442
static int fileexists(const char *fname) {
442
  FILE *fd;
443
  FILE *fd;
443
  fd = fopen(fname, "rb");
444
  fd = fopen(fname, "rb");
444
  if (fd == NULL) return(-1);
445
  if (fd == NULL) return(-1);
445
  fclose(fd);
446
  fclose(fd);
446
  return(0);
447
  return(0);
447
}
448
}
448
 
449
 
449
 
450
 
450
static int preparedrive(char sourcedrv) {
451
static int preparedrive(char sourcedrv) {
451
  int driveremovable;
452
  int driveremovable;
452
  int selecteddrive = 3; /* default to 'C:' */
453
  int selecteddrive = 3; /* default to 'C:' */
453
  int cselecteddrive;
454
  int cselecteddrive;
454
  int ds;
455
  int ds;
455
  int choice;
456
  int choice;
456
  char buff[1024];
457
  char buff[1024];
457
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
458
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
458
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
459
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
459
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
460
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
460
    driveid = 2; /* primary drive is the emulated USB storage */
461
    driveid = 2; /* primary drive is the emulated USB storage */
461
  }
462
  }
462
  cselecteddrive = 'A' + selecteddrive - 1;
463
  cselecteddrive = 'A' + selecteddrive - 1;
463
  for (;;) {
464
  for (;;) {
464
    driveremovable = isdriveremovable(selecteddrive);
465
    driveremovable = isdriveremovable(selecteddrive);
465
    if (driveremovable < 0) {
466
    if (driveremovable < 0) {
466
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
467
      const char *list[4];
467
      newscreen(0);
468
      newscreen(0);
468
      list[0] = kittengets(0, 3, list[0]);
469
      list[0] = svarlang_str(0, 3); /* Create a partition automatically */
469
      list[1] = kittengets(0, 4, list[1]);
470
      list[1] = svarlang_str(0, 4); /* Run the FDISK tool */
470
      list[2] = kittengets(0, 2, list[2]);
471
      list[2] = svarlang_str(0, 2); /* Quit to DOS */
-
 
472
      list[3] = NULL;
471
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so SvarDOS can be installed on it. Note, that SvarDOS requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVARDOS_DISK_REQ);
473
      snprintf(buff, sizeof(buff), svarlang_strid(0x0300), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: could not be found. Note, that SvarDOS requires at least %d MiB of available disk space */
472
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY[mono], buff), -1, 5, list, -1)) {
474
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY[mono], buff), -1, 5, list, -1)) {
473
        case 0:
475
        case 0:
474
          sprintf(buff, "FDISK /AUTO %d", driveid);
476
          sprintf(buff, "FDISK /AUTO %d", driveid);
475
          system(buff);
477
          system(buff);
476
          break;
478
          break;
477
        case 1:
479
        case 1:
478
          video_clear(0x0700, 0, 0);
480
          video_clear(0x0700, 0, 0);
479
          video_movecursor(0, 0);
481
          video_movecursor(0, 0);
480
          sprintf(buff, "FDISK %d", driveid);
482
          sprintf(buff, "FDISK %d", driveid);
481
          system(buff);
483
          system(buff);
482
          break;
484
          break;
483
        case 2:
485
        case 2:
484
          return(MENUQUIT);
486
          return(MENUQUIT);
485
        default:
487
        default:
486
          return(-1);
488
          return(-1);
487
      }
489
      }
488
      /* write a temporary MBR which only skips the drive (in case BIOS would
490
      /* write a temporary MBR which only skips the drive (in case BIOS would
489
       * try to boot off the not-yet-ready C: disk) */
491
       * try to boot off the not-yet-ready C: disk) */
490
      sprintf(buff, "FDISK /AMBR %d", driveid);
492
      sprintf(buff, "FDISK /AMBR %d", driveid);
491
      system(buff); /* writes BOOT.MBR into actual MBR */
493
      system(buff); /* writes BOOT.MBR into actual MBR */
492
      newscreen(2);
494
      newscreen(2);
493
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
495
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1); /* "Your computer will reboot now." */
494
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
496
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
495
      input_getkey();
497
      input_getkey();
496
      reboot();
498
      reboot();
497
      return(MENUQUIT);
499
      return(MENUQUIT);
498
    } else if (driveremovable > 0) {
500
    } else if (driveremovable > 0) {
499
      newscreen(2);
501
      newscreen(2);
500
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
502
      snprintf(buff, sizeof(buff), svarlang_strid(0x0302), cselecteddrive); /* "ERROR: Drive %c: is a removable device */
501
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
503
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
502
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
504
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
503
      return(MENUQUIT);
505
      return(MENUQUIT);
504
    }
506
    }
505
    /* if not formatted, propose to format it right away (try to create a directory) */
507
    /* if not formatted, propose to format it right away (try to create a directory) */
506
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
508
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
507
    if (mkdir(buff) == 0) {
509
    if (mkdir(buff) == 0) {
508
      rmdir(buff);
510
      rmdir(buff);
509
    } else {
511
    } else {
510
      char *list[3];
512
      const char *list[3];
511
      newscreen(0);
513
      newscreen(0);
512
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
514
      snprintf(buff, sizeof(buff), svarlang_str(3, 3), cselecteddrive); /* "ERROR: Drive %c: seems to be unformated. Do you wish to format it?") */
513
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
515
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
514
 
516
 
515
      snprintf(buff, sizeof(buff), kittengets(0, 7, "Format drive %c:"), cselecteddrive);
517
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
516
      list[0] = buff;
518
      list[0] = buff;
517
      list[1] = kittengets(0, 2, "Quit to DOS");
519
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
518
      list[2] = NULL;
520
      list[2] = NULL;
519
 
521
 
520
      choice = menuselect(12, -1, 4, list, -1);
522
      choice = menuselect(12, -1, 4, list, -1);
521
      if (choice < 0) return(MENUPREV);
523
      if (choice < 0) return(MENUPREV);
522
      if (choice == 1) return(MENUQUIT);
524
      if (choice == 1) return(MENUQUIT);
523
      video_clear(0x0700, 0, 0);
525
      video_clear(0x0700, 0, 0);
524
      video_movecursor(0, 0);
526
      video_movecursor(0, 0);
525
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
527
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
526
      system(buff);
528
      system(buff);
527
      continue;
529
      continue;
528
    }
530
    }
529
    /* check total disk space */
531
    /* check total disk space */
530
    ds = disksize(selecteddrive);
532
    ds = disksize(selecteddrive);
531
    if (ds < SVARDOS_DISK_REQ) {
533
    if (ds < SVARDOS_DISK_REQ) {
532
      int y = 9;
534
      int y = 9;
533
      newscreen(2);
535
      newscreen(2);
534
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB."), cselecteddrive, SVARDOS_DISK_REQ);
536
      snprintf(buff, sizeof(buff), svarlang_strid(0x0304), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB." */
535
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
537
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
536
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
538
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
537
      input_getkey();
539
      input_getkey();
538
      return(MENUQUIT);
540
      return(MENUQUIT);
539
    }
541
    }
540
    /* is the disk empty? */
542
    /* is the disk empty? */
541
    newscreen(0);
543
    newscreen(0);
542
    if (diskempty(selecteddrive) != 0) {
544
    if (diskempty(selecteddrive) != 0) {
543
      char *list[3];
545
      const char *list[3];
544
      int y = 6;
546
      int y = 6;
545
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. SvarDOS must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
547
      snprintf(buff, sizeof(buff), svarlang_strid(0x0305), cselecteddrive); /* "ERROR: Drive %c: not empty" */
546
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
548
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
547
 
549
 
548
      snprintf(buff, sizeof(buff), kittengets(0, 7, "Format drive %c:"), cselecteddrive);
550
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
549
      list[0] = buff;
551
      list[0] = buff;
550
      list[1] = kittengets(0, 2, "Quit to DOS");
552
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
551
      list[2] = NULL;
553
      list[2] = NULL;
552
 
554
 
553
      choice = menuselect(++y, -1, 4, list, -1);
555
      choice = menuselect(++y, -1, 4, list, -1);
554
      if (choice < 0) return(MENUPREV);
556
      if (choice < 0) return(MENUPREV);
555
      if (choice == 1) return(MENUQUIT);
557
      if (choice == 1) return(MENUQUIT);
556
      video_clear(0x0700, 0, 0);
558
      video_clear(0x0700, 0, 0);
557
      video_movecursor(0, 0);
559
      video_movecursor(0, 0);
558
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
560
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
559
      system(buff);
561
      system(buff);
560
      continue;
562
      continue;
561
    } else {
563
    } else {
562
      /* final confirmation */
564
      /* final confirmation */
-
 
565
      const char *list[3];
563
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
566
      list[0] = svarlang_strid(0x0001); /* Install SvarDOS */
564
      list[0] = kittengets(0, 1, list[0]);
567
      list[1] = svarlang_strid(0x0002); /* Quit to DOS */
565
      list[1] = kittengets(0, 2, list[1]);
568
      list[2] = NULL;
566
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
569
      snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
567
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
570
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
568
      choice = menuselect(10, -1, 4, list, -1);
571
      choice = menuselect(10, -1, 4, list, -1);
569
      if (choice < 0) return(MENUPREV);
572
      if (choice < 0) return(MENUPREV);
570
      if (choice == 1) return(MENUQUIT);
573
      if (choice == 1) return(MENUQUIT);
571
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
574
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
572
      system(buff);
575
      system(buff);
573
      sprintf(buff, "FDISK /MBR %d", driveid);
576
      sprintf(buff, "FDISK /MBR %d", driveid);
574
      system(buff);
577
      system(buff);
575
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
578
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
576
      mkdir(buff);
579
      mkdir(buff);
577
      return(cselecteddrive);
580
      return(cselecteddrive);
578
    }
581
    }
579
  }
582
  }
580
}
583
}
581
 
584
 
582
 
585
 
583
/* generates locales-related configurations and writes them to file (this
586
/* generates locales-related configurations and writes them to file (this
584
 * is used to compute autoexec.bat content) */
587
 * is used to compute autoexec.bat content) */
585
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
588
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
586
  if (locales == NULL) return;
589
  if (locales == NULL) return;
587
 
590
 
588
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
591
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
589
 
592
 
590
  if (locales->egafile > 0) {
593
  if (locales->egafile > 0) {
591
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
594
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
592
    if (locales->egafile == 1) {
595
    if (locales->egafile == 1) {
593
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
596
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
594
    } else {
597
    } else {
595
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
598
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
596
    }
599
    }
597
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
600
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
598
  }
601
  }
599
 
602
 
600
  if (locales->keybfile > 0) {
603
  if (locales->keybfile > 0) {
601
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
604
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
602
    if (locales->keybfile == 1) {
605
    if (locales->keybfile == 1) {
603
      fprintf(fd, "KEYBOARD.SYS");
606
      fprintf(fd, "KEYBOARD.SYS");
604
    } else {
607
    } else {
605
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
608
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
606
    }
609
    }
607
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
610
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
608
    fprintf(fd, "\r\n");
611
    fprintf(fd, "\r\n");
609
  }
612
  }
610
}
613
}
611
 
614
 
612
 
615
 
613
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
616
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
614
  char buff[128];
617
  char buff[128];
615
  FILE *fd;
618
  FILE *fd;
616
  /*** CONFIG.SYS ***/
619
  /*** CONFIG.SYS ***/
617
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
620
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
618
  fd = fopen(buff, "wb");
621
  fd = fopen(buff, "wb");
619
  if (fd == NULL) return;
622
  if (fd == NULL) return;
620
  fprintf(fd, "DOS=UMB,HIGH\r\n"
623
  fprintf(fd, "DOS=UMB,HIGH\r\n"
621
              "LASTDRIVE=Z\r\n"
624
              "LASTDRIVE=Z\r\n"
622
              "FILES=50\r\n");
625
              "FILES=50\r\n");
623
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
626
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
624
  if (strcmp(locales->lang, "EN") == 0) {
627
  if (strcmp(locales->lang, "EN") == 0) {
625
    strcpy(buff, "COMMAND");
628
    strcpy(buff, "COMMAND");
626
  } else {
629
  } else {
627
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
630
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
628
  }
631
  }
629
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
632
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
630
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
633
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
631
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
634
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
632
  fclose(fd);
635
  fclose(fd);
633
  /*** AUTOEXEC.BAT ***/
636
  /*** AUTOEXEC.BAT ***/
634
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
637
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
635
  fd = fopen(buff, "wb");
638
  fd = fopen(buff, "wb");
636
  if (fd == NULL) return;
639
  if (fd == NULL) return;
637
  fprintf(fd, "@ECHO OFF\r\n");
640
  fprintf(fd, "@ECHO OFF\r\n");
638
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
641
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
639
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
642
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
640
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
643
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
641
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
644
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
642
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
645
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
643
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
646
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
644
  fprintf(fd, "PROMPT $P$G\r\n");
647
  fprintf(fd, "PROMPT $P$G\r\n");
645
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
648
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
646
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
649
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
647
  fprintf(fd, "FDAPM APMDOS\r\n");
650
  fprintf(fd, "FDAPM APMDOS\r\n");
648
  fprintf(fd, "\r\n");
651
  fprintf(fd, "\r\n");
649
  genlocalesconf(fd, locales);
652
  genlocalesconf(fd, locales);
650
  fprintf(fd, "\r\n");
653
  fprintf(fd, "\r\n");
651
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
654
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
652
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
655
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
653
  fprintf(fd, "\r\n");
656
  fprintf(fd, "\r\n");
654
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
657
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
655
  fprintf(fd, "REM CTMOUSE\r\n");
658
  fprintf(fd, "REM CTMOUSE\r\n");
656
  fprintf(fd, "\r\n");
659
  fprintf(fd, "\r\n");
657
  fprintf(fd, "ECHO.\r\n");
660
  fprintf(fd, "ECHO.\r\n");
658
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
661
  fprintf(fd, "ECHO %s\r\n", svarlang_strid(0x0600)); /* "Welcome to SvarDOS!" */
659
  fclose(fd);
662
  fclose(fd);
660
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
663
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
661
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
664
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
662
  mkdir(buff);
665
  mkdir(buff);
663
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
666
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
664
  mkdir(buff);
667
  mkdir(buff);
665
  /*** PKG.CFG ***/
668
  /*** PKG.CFG ***/
666
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
669
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
667
  fd = fopen(buff, "wb");
670
  fd = fopen(buff, "wb");
668
  if (fd == NULL) return;
671
  if (fd == NULL) return;
669
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
672
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
670
              "\r\n"
673
              "\r\n"
671
              "# Programs\r\n"
674
              "# Programs\r\n"
672
              "DIR PROGS C:\\\r\n"
675
              "DIR PROGS C:\\\r\n"
673
              "\r\n"
676
              "\r\n"
674
              "# Games \r\n"
677
              "# Games \r\n"
675
              "DIR GAMES C:\\\r\n"
678
              "DIR GAMES C:\\\r\n"
676
              "\r\n"
679
              "\r\n"
677
              "# Drivers\r\n"
680
              "# Drivers\r\n"
678
              "DIR DRIVERS C:\\DRIVERS\r\n"
681
              "DIR DRIVERS C:\\DRIVERS\r\n"
679
              "\r\n"
682
              "\r\n"
680
              "# Development tools\r\n"
683
              "# Development tools\r\n"
681
              "DIR DEVEL C:\\DEVEL\r\n");
684
              "DIR DEVEL C:\\DEVEL\r\n");
682
  fclose(fd);
685
  fclose(fd);
683
  /*** COUNTRY.SYS ***/
686
  /*** COUNTRY.SYS ***/
684
  /*** PICOTCP ***/
687
  /*** PICOTCP ***/
685
  /*** WATTCP ***/
688
  /*** WATTCP ***/
686
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
689
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
687
  fd = fopen(buff, "wb");
690
  fd = fopen(buff, "wb");
688
  if (fd == NULL) return;
691
  if (fd == NULL) return;
689
  fprintf(fd, "my_ip = dhcp\r\n"
692
  fprintf(fd, "my_ip = dhcp\r\n"
690
              "#my_ip = 192.168.0.7\r\n"
693
              "#my_ip = 192.168.0.7\r\n"
691
              "#netmask = 255.255.255.0\r\n"
694
              "#netmask = 255.255.255.0\r\n"
692
              "#nameserver = 192.168.0.1\r\n"
695
              "#nameserver = 192.168.0.1\r\n"
693
              "#nameserver = 192.168.0.2\r\n"
696
              "#nameserver = 192.168.0.2\r\n"
694
              "#gateway = 192.168.0.1\r\n");
697
              "#gateway = 192.168.0.1\r\n");
695
  fclose(fd);
698
  fclose(fd);
696
}
699
}
697
 
700
 
698
 
701
 
699
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
702
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
700
  char pkglist[512];
703
  char pkglist[512];
701
  int i, pkglistlen;
704
  int i, pkglistlen;
702
  size_t pkglistflen;
705
  size_t pkglistflen;
703
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
706
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
704
  FILE *fd = NULL;
707
  FILE *fd = NULL;
705
  char *pkgptr;
708
  char *pkgptr;
706
  newscreen(3);
709
  newscreen(3);
707
  /* load pkg list */
710
  /* load pkg list */
708
  fd = fopen("install.lst", "rb");
711
  fd = fopen("install.lst", "rb");
709
  if (fd == NULL) {
712
  if (fd == NULL) {
710
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
713
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
711
    input_getkey();
714
    input_getkey();
712
    return(-1);
715
    return(-1);
713
  }
716
  }
714
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
717
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
715
  fclose(fd);
718
  fclose(fd);
716
  if (pkglistflen == sizeof(pkglist)) {
719
  if (pkglistflen == sizeof(pkglist)) {
717
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
720
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
718
    input_getkey();
721
    input_getkey();
719
    return(-1);
722
    return(-1);
720
  }
723
  }
721
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
724
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
722
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
725
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
723
  pkglistlen = 0;
726
  pkglistlen = 0;
724
  for (i = 0; i < pkglistflen; i++) {
727
  for (i = 0; i < pkglistflen; i++) {
725
    switch (pkglist[i]) {
728
    switch (pkglist[i]) {
726
      case '\n':
729
      case '\n':
727
        pkglistlen++;
730
        pkglistlen++;
728
        /* FALLTHRU */
731
        /* FALLTHRU */
729
      case '\r':
732
      case '\r':
730
        pkglist[i] = 0;
733
        pkglist[i] = 0;
731
        break;
734
        break;
732
    }
735
    }
733
  }
736
  }
734
  /* copy pkg.exe to the new drive, along with all packages */
737
  /* copy pkg.exe to the new drive, along with all packages */
735
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
738
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
736
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
739
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
737
  fcopy(buff, buff + 64, buff, sizeof(buff));
740
  fcopy(buff, buff + 64, buff, sizeof(buff));
738
 
741
 
739
  /* open the post-install autoexec.bat and prepare initial instructions */
742
  /* open the post-install autoexec.bat and prepare initial instructions */
740
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
743
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
741
  fd = fopen(buff, "wb");
744
  fd = fopen(buff, "wb");
742
  if (fd == NULL) return(-1);
745
  if (fd == NULL) return(-1);
743
  fprintf(fd, "@ECHO OFF\r\n");
746
  fprintf(fd, "@ECHO OFF\r\n");
744
 
747
 
745
  /* copy packages */
748
  /* copy packages */
746
  pkgptr = pkglist;
749
  pkgptr = pkglist;
747
  for (i = 0;; i++) {
750
  for (i = 0;; i++) {
748
    /* move forward to nearest entry or end of list */
751
    /* move forward to nearest entry or end of list */
749
    while (*pkgptr == 0) pkgptr++;
752
    while (*pkgptr == 0) pkgptr++;
750
    if (*pkgptr == 0xff) break;
753
    if (*pkgptr == 0xff) break;
751
    /* install the package */
754
    /* install the package */
752
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
755
    snprintf(buff, sizeof(buff), svarlang_strid(0x0400), i+1, pkglistlen, pkgptr); /* "Installing package %d/%d: %s" */
753
    strcat(buff, "       ");
756
    strcat(buff, "       ");
754
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
757
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
755
    /* wait for new diskette if package not found */
758
    /* wait for new diskette if package not found */
756
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
759
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
757
    while (fileexists(buff) != 0) {
760
    while (fileexists(buff) != 0) {
758
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
761
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1); /* "INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY" */
759
      input_getkey();
762
      input_getkey();
760
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
763
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
761
    }
764
    }
762
    /* proceed with package copy (buff contains the src filename already) */
765
    /* proceed with package copy (buff contains the src filename already) */
763
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
766
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
764
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
767
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
765
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
768
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
766
      input_getkey();
769
      input_getkey();
767
      fclose(fd);
770
      fclose(fd);
768
      return(-1);
771
      return(-1);
769
    }
772
    }
770
    /* write install instruction to post-install script */
773
    /* write install instruction to post-install script */
771
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
774
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
772
    /* jump to next entry or end of list */
775
    /* jump to next entry or end of list */
773
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
776
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
774
    if (*pkgptr == 0xff) break;
777
    if (*pkgptr == 0xff) break;
775
  }
778
  }
776
  /* set up locales so the "installation over" message is nicely displayed */
779
  /* set up locales so the "installation over" message is nicely displayed */
777
  genlocalesconf(fd, locales);
780
  genlocalesconf(fd, locales);
778
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
781
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
779
  fprintf(fd, "DEL pkg.exe\r\n"
782
  fprintf(fd, "DEL pkg.exe\r\n"
780
              "COPY CONFIG.SYS C:\\\r\n"
783
              "COPY CONFIG.SYS C:\\\r\n"
781
              "DEL CONFIG.SYS\r\n"
784
              "DEL CONFIG.SYS\r\n"
782
              "DEL C:\\AUTOEXEC.BAT\r\n"
785
              "DEL C:\\AUTOEXEC.BAT\r\n"
783
              "COPY AUTOEXEC.BAT C:\\\r\n"
786
              "COPY AUTOEXEC.BAT C:\\\r\n"
784
              "DEL AUTOEXEC.BAT\r\n");
787
              "DEL AUTOEXEC.BAT\r\n");
785
  /* print out the "installation over" message */
788
  /* print out the "installation over" message */
786
  fprintf(fd, "ECHO.\r\n"
789
  fprintf(fd, "ECHO.\r\n"
787
              "ECHO %s\r\n"
790
              "ECHO %s\r\n"
788
              "ECHO.\r\n", kittengets(5, 1, "SvarDOS installation is over. Please restart your computer now."));
791
              "ECHO.\r\n", svarlang_strid(0x0501)); /* "SvarDOS installation is over. Please restart your computer now" */
789
  fclose(fd);
792
  fclose(fd);
790
 
793
 
791
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
794
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
792
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
795
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
793
  fd = fopen(buff, "wb");
796
  fd = fopen(buff, "wb");
794
  if (fd == NULL) return(-1);
797
  if (fd == NULL) return(-1);
795
  fprintf(fd, "@ECHO OFF\r\n"
798
  fprintf(fd, "@ECHO OFF\r\n"
796
              "SET DOSDIR=C:\\SVARDOS\r\n"
799
              "SET DOSDIR=C:\\SVARDOS\r\n"
797
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
800
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
798
              "PATH %%DOSDIR%%\\BIN\r\n");
801
              "PATH %%DOSDIR%%\\BIN\r\n");
799
  fprintf(fd, "CD TEMP\r\n"
802
  fprintf(fd, "CD TEMP\r\n"
800
              "postinst.bat\r\n");
803
              "postinst.bat\r\n");
801
  fclose(fd);
804
  fclose(fd);
802
 
805
 
803
  return(0);
806
  return(0);
804
}
807
}
805
 
808
 
806
 
809
 
807
static void finalreboot(void) {
810
static void finalreboot(void) {
808
  int y = 9;
811
  int y = 9;
809
  newscreen(2);
812
  newscreen(2);
810
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Your computer will reboot now.\nPlease remove the installation disk from your drive.");
813
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0); /* "Your computer will reboot now.\nPlease remove the installation disk from your drive" */
811
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
814
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
812
  input_getkey();
815
  input_getkey();
813
  reboot();
816
  reboot();
814
}
817
}
815
 
818
 
816
 
819
 
817
static void loadcp(const struct slocales *locales) {
820
static void loadcp(const struct slocales *locales) {
818
  char buff[64];
821
  char buff[64];
819
  if (locales->codepage == 437) return;
822
  if (locales->codepage == 437) return;
820
  video_movecursor(1, 0);
823
  video_movecursor(1, 0);
821
  if (locales->egafile == 1) {
824
  if (locales->egafile == 1) {
822
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
825
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
823
  } else {
826
  } else {
824
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
827
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
825
  }
828
  }
826
  system(buff);
829
  system(buff);
827
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
830
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
828
  system(buff);
831
  system(buff);
829
  /* below I re-init the video controller - apparently this is required if
832
  /* below I re-init the video controller - apparently this is required if
830
   * I want the new glyph symbols to be actually applied, at least some
833
   * I want the new glyph symbols to be actually applied, at least some
831
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
834
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
832
  {
835
  {
833
  union REGS r;
836
  union REGS r;
834
  r.h.ah = 0x0F; /* get current video mode */
837
  r.h.ah = 0x0F; /* get current video mode */
835
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
838
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
836
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
839
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
837
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
840
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
838
  int86(0x10, &r, &r);
841
  int86(0x10, &r, &r);
839
  }
842
  }
840
}
843
}
841
 
844
 
842
 
845
 
843
#ifdef DEADCODE
846
#ifdef DEADCODE
844
/* checks that drive drv contains SvarDOS packages
847
/* checks that drive drv contains SvarDOS packages
845
 * returns 0 if found, non-zero otherwise */
848
 * returns 0 if found, non-zero otherwise */
846
static int checkinstsrc(char drv) {
849
static int checkinstsrc(char drv) {
847
  char fname[16];
850
  char fname[16];
848
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
851
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
849
  return(fileexists(fname));
852
  return(fileexists(fname));
850
}
853
}
851
#endif
854
#endif
852
 
855
 
853
 
856
 
854
int main(void) {
857
int main(void) {
855
  struct slocales locales;
858
  struct slocales locales;
856
  int targetdrv;
859
  int targetdrv;
857
  int sourcedrv;
860
  int sourcedrv;
858
  int action;
861
  int action;
859
 
862
 
860
  sourcedrv = get_cur_drive() + 'A';
863
  sourcedrv = get_cur_drive() + 'A';
861
 
864
 
862
  /* init screen and detect mono status */
865
  /* init screen and detect mono status */
863
  mono = video_init();
866
  mono = video_init();
864
 
867
 
865
  kittenopen("INSTALL"); /* load initial NLS support */
-
 
866
 
-
 
867
 SelectLang:
868
 SelectLang:
868
  action = selectlang(&locales); /* welcome to svardos, select your language */
869
  action = selectlang(&locales); /* welcome to svardos, select your language */
869
  if (action != MENUNEXT) goto Quit;
870
  if (action != MENUNEXT) goto Quit;
870
  setenv("LANG", locales.lang, 1);
-
 
871
  loadcp(&locales);
871
  loadcp(&locales);
872
  kittenclose(); /* reload NLS with new language */
-
 
873
  kittenopen("INSTALL"); /* NLS support */
872
  svarlang_load("INSTALL", locales.lang, ".\\"); /* NLS support */
874
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
873
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
875
  if (action == MENUQUIT) goto Quit;
874
  if (action == MENUQUIT) goto Quit;
876
  if (action == MENUPREV) goto SelectLang;
875
  if (action == MENUPREV) goto SelectLang;
877
 
876
 
878
 WelcomeScreen:
877
 WelcomeScreen:
879
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
878
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
880
  if (action == MENUQUIT) goto Quit;
879
  if (action == MENUQUIT) goto Quit;
881
  if (action == MENUPREV) goto SelectLang;
880
  if (action == MENUPREV) goto SelectLang;
882
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
881
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
883
  if (targetdrv == MENUQUIT) goto Quit;
882
  if (targetdrv == MENUQUIT) goto Quit;
884
  if (targetdrv == MENUPREV) goto WelcomeScreen;
883
  if (targetdrv == MENUPREV) goto WelcomeScreen;
885
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
884
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
886
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
885
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
887
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
886
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
888
  /*netcfg();*/ /* basic networking config */
887
  /*netcfg();*/ /* basic networking config */
889
  finalreboot(); /* remove the CD and reboot */
888
  finalreboot(); /* remove the CD and reboot */
890
 
889
 
891
 Quit:
890
 Quit:
892
  kittenclose(); /* close NLS support */
-
 
893
  video_clear(0x0700, 0, 0);
891
  video_clear(0x0700, 0, 0);
894
  video_movecursor(0, 0);
892
  video_movecursor(0, 0);
895
  return(0);
893
  return(0);
896
}
894
}
897
 
895