Subversion Repositories SvarDOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
585 mateuszvis 1
/*
591 mateuszvis 2
 * functions that reads/writes from/to the localcfg country.sys-like file.
3
 * Copyright (C) Mateusz Viste 2015-2022
585 mateuszvis 4
 */
5
 
6
#include <stdio.h>
7
#include <string.h>
8
 
9
#include "country.h"
10
 
11
 
591 mateuszvis 12
struct funchdr {
13
  unsigned char funcname[8];
14
  unsigned short funcsiz;
15
};
585 mateuszvis 16
 
608 mateuszvis 17
static unsigned char filebuff[1024];
591 mateuszvis 18
 
608 mateuszvis 19
 
585 mateuszvis 20
/* fills a country struct with default values */
21
static void country_default(struct country *countrydata) {
591 mateuszvis 22
 
23
  /* first clear the memory */
24
  bzero(countrydata, sizeof(struct country));
25
 
26
  /* fill in CTYINFO fields (non-zero values only) */
27
  countrydata->CTYINFO.id = 1;
28
  countrydata->CTYINFO.codepage = 437;
29
  /* countrydata->CTYINFO.datefmt = COUNTRY_DATE_MDY;
30
  countrydata->CTYINFO.timefmt = COUNTRY_TIME12; */
31
  countrydata->CTYINFO.currsym[0] = '$';
32
  countrydata->CTYINFO.decimal[0] = '.';
33
  countrydata->CTYINFO.thousands[0] = ',';
34
  countrydata->CTYINFO.datesep[0] = '/';
35
  countrydata->CTYINFO.timesep[0] = ':';
36
  countrydata->CTYINFO.currprec = 2;
37
  /* countrydata->CTYINFO.currencydecsym = 0; */
38
  /* countrydata->CTYINFO.currencyspace = 0; */
39
  /* countrydata->CTYINFO.currencypos = 0; */
40
 
41
  /* fill in YESNO fields (non-zero values only) */
42
  countrydata->YESNO.yes[0] = 'Y';
43
  countrydata->YESNO.no[0] = 'N';
585 mateuszvis 44
}
45
 
46
 
47
/* Loads data from a country.sys file into a country struct.
48
 * Returns 0 on success, non-zero otherwise. */
591 mateuszvis 49
int country_read(struct country *countrydata, const char *fname) {
585 mateuszvis 50
  short firstentryoffs;
51
  unsigned char *subfunctions[16] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
52
                                     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
53
  short filesize;
54
  short subfunctionscount;
55
  unsigned char *functiondata;
56
  int x;
57
  FILE *fd;
58
 
59
  /* preload the country struct with default values */
60
  country_default(countrydata);
61
 
62
  /* load the file into buff, if file exists */
63
  fd = fopen(fname, "rb");
64
  if (fd == NULL) return(0); /* "file doesn't exist" is not an error condition */
65
  filesize = fread(filebuff, 1, sizeof(filebuff), fd);
66
  fclose(fd);
67
 
68
  /* check that it's a country file - should start with 0xFF COUNTRY 0x00 */
611 mateuszvis 69
  if (memcmp(filebuff, "\377COUNTRY\0", 9) != 0) return(COUNTRY_ERR_INV_FORMAT);
585 mateuszvis 70
 
71
  /* check that it's one of my country.sys files - should contain a trailer */
611 mateuszvis 72
  if (memcmp(filebuff + filesize - 8, "LOCALCFG", 8) != 0) return(COUNTRY_ERR_NOT_LOCALCFG);
585 mateuszvis 73
 
74
  /* read the offset of the entries index - must be at least 23 */
75
  functiondata = filebuff + 19;
591 mateuszvis 76
  firstentryoffs = *((unsigned short *)functiondata);
585 mateuszvis 77
  if ((firstentryoffs < 23) || (firstentryoffs >= filesize)) return(-4);
78
  functiondata = filebuff + firstentryoffs;
79
 
80
  /* how many entries do we have? I expect exactly one. */
591 mateuszvis 81
  if (*((unsigned short *)functiondata) != 1) return(-5);
585 mateuszvis 82
  /* skip to the first country entry */
83
  functiondata += 2;
84
 
85
  /* skip directly to the subfunctions of the first country */
86
  /* ddwords: size, country, codepage, reserved, reserved, offset */
87
  /* printf("Size = %d\n", READSHORT(functiondata)); */
88
  functiondata += 2; /* skip size */
89
  /* printf("Country = %d\n", READSHORT(functiondata[0]); */
90
  functiondata += 2; /* skip country */
91
  /* printf("Codepage = %d\n", READSHORT(functiondata)); */
92
  functiondata += 2; /* skip codepage */
93
  functiondata += 4; /* skip reserved fields */
591 mateuszvis 94
  firstentryoffs = *((unsigned short *)functiondata); /* read offset of the subfunctions index */
585 mateuszvis 95
  functiondata = filebuff + firstentryoffs;
96
 
97
  /* read all subfunctions, but no more than 15 */
591 mateuszvis 98
  subfunctionscount = *((unsigned short *)functiondata);
585 mateuszvis 99
  /* printf("Found %d subfunctions\n", subfunctionscount); */
100
  functiondata += 2;
101
  for (x = 0; (x < 15) && (x < subfunctionscount); x++) {
591 mateuszvis 102
    short size = *((unsigned short *)functiondata);
585 mateuszvis 103
    functiondata += 2;
104
    functiondata += 2; /* skip ID of the subfunction */
591 mateuszvis 105
    subfunctions[x] = filebuff + *((unsigned short *)functiondata);
585 mateuszvis 106
    /* printf("subfunction %d at 0x%p\n", x, subfunctions[x]); */
107
    functiondata += size - 2;
108
  }
109
 
110
  /* load every subfunction, and feed the country struct with data */
111
  for (x = 0; subfunctions[x] != NULL; x++) {
591 mateuszvis 112
    struct funchdr *hdr = (void *)(subfunctions[x]);
585 mateuszvis 113
    functiondata = subfunctions[x] + 10;
114
    /* */
591 mateuszvis 115
    if ((memcmp(hdr->funcname, "\377YESNO  ", 8) == 0) && (hdr->funcsiz == 4)) {
116
      memcpy(&(countrydata->YESNO), functiondata, hdr->funcsiz);
117
    } else if ((memcmp(hdr->funcname, "\377CTYINFO", 8) == 0) && (hdr->funcsiz == 22)) {
118
      memcpy(&(countrydata->CTYINFO), functiondata, hdr->funcsiz);
585 mateuszvis 119
    }
120
  }
121
 
122
  return(0);
123
}
124
 
125
 
126
#define MSB(x) (((x) >> 8) & 0xff)
127
#define LSB(x) ((x) & 0xff)
128
 
129
 
130
/* Computes a new country.sys file based on data from a country struct.
131
 * Returns 0 on success, non-zero otherwise. */
591 mateuszvis 132
int country_write(const char *fname, struct country *c) {
585 mateuszvis 133
  short filesize = 0;
134
  FILE *fd;
135
  int x;
136
  short subfunction_id[7] = {1,2,4,5,6,7,35};
137
  short subfunction_ptr[7];
138
 
139
  const unsigned char ucase_437[128] = {128, 154,  69,  65, 142,  65, 143, 128,
140
                                         69,  69,  69,  73,  73,  73, 142, 143,
141
                                        144, 146, 146,  79, 153,  79,  85,  85,
142
                                         89, 153, 154, 155, 156, 157, 158, 159,
143
                                         65,  73,  79,  85, 165, 165, 166, 167,
144
                                        168, 169, 170, 171, 172, 173, 174, 175,
145
                                        176, 177, 178, 179, 180, 181, 182, 183,
146
                                        184, 185, 186, 187, 188, 189, 190, 191,
147
                                        192, 193, 194, 195, 196, 197, 198, 199,
148
                                        200, 201, 202, 203, 204, 205, 206, 207,
149
                                        208, 209, 210, 211, 212, 213, 214, 215,
150
                                        216, 217, 218, 219, 220, 221, 222, 223,
151
                                        224, 225, 226, 227, 228, 229, 230, 231,
152
                                        232, 233, 234, 235, 236, 237, 238, 239,
153
                                        240, 241, 242, 243, 244, 245, 246, 247,
154
                                        248, 249, 250, 251, 252, 253, 254, 255};
155
 
156
  const unsigned char collate_437[256] = {  0,   1,   2,   3,   4,   5,   6,   7,
157
                                            8,   9,  10,  11,  12,  13,  14,  15,
158
                                           16,  17,  18,  19,  20,  21,  22,  23,
159
                                           24,  25,  26,  27,  28,  29,  30,  31,
160
                                           32,  33,  34,  35,  36,  37,  38,  39,
161
                                           40,  41,  42,  43,  44,  45,  46,  47,
162
                                           48,  49,  50,  51,  52,  53,  54,  55,
163
                                           56,  57,  58,  59,  60,  61,  62,  63,
164
                                           64,  65,  66,  67,  68,  69,  70,  71,
165
                                           72,  73,  74,  75,  76,  77,  78,  79,
166
                                           80,  81,  82,  83,  84,  85,  86,  87,
167
                                           88,  89,  90,  91,  92,  93,  94,  95,
168
                                           96,  65,  66,  67,  68,  69,  70,  71,
169
                                           72,  73,  74,  75,  76,  77,  78,  79,
170
                                           80,  81,  82,  83,  84,  85,  86,  87,
171
                                           88,  89,  90, 123, 124, 125, 126, 127,
172
                                           67,  85,  69,  65,  65,  65,  65,  67,
173
                                           69,  69,  69,  73,  73,  73,  65,  65,
174
                                           69,  65,  65,  79,  79,  79,  85,  85,
175
                                           89,  79,  85,  36,  36,  36,  36,  36,
176
                                           65,  73,  79,  85,  78,  78, 166, 167,
177
                                           63, 169, 170, 171, 172,  33,  34,  34,
178
                                          176, 177, 178, 179, 180, 181, 182, 183,
179
                                          184, 185, 186, 187, 188, 189, 190, 191,
180
                                          192, 193, 194, 195, 196, 197, 198, 199,
181
                                          200, 201, 202, 203, 204, 205, 206, 207,
182
                                          208, 209, 210, 211, 212, 213, 214, 215,
183
                                          216, 217, 218, 219, 220, 221, 222, 223,
184
                                          224,  83, 226, 227, 228, 229, 230, 231,
185
                                          232, 233, 234, 235, 236, 237, 238, 239,
186
                                          240, 241, 242, 243, 244, 245, 246, 247,
187
                                          248, 249, 250, 251, 252, 253, 254, 255};
188
 
591 mateuszvis 189
  /* zero out filebuff */
190
  bzero(filebuff, sizeof(filebuff));
191
 
585 mateuszvis 192
  /* compute the country.sys structures */
193
  memcpy(filebuff, "\377COUNTRY\0\0\0\0\0\0\0\0\1\0\1", 19); /* header */
194
  filesize = 19;
195
  /* first entry offset (always current offset+4) */
196
  filesize += 4;
591 mateuszvis 197
  memcpy(filebuff + filesize - 4, &filesize, sizeof(filesize));
585 mateuszvis 198
  /* number of entries */
591 mateuszvis 199
  filebuff[filesize] = 1;
200
  filesize += 2;
585 mateuszvis 201
  /* first (and only) entry / size, country, codepage, reserved(2), offset */
202
  filebuff[filesize++] = 12; /* size LSB */
203
  filebuff[filesize++] = 0;  /* size MSB */
591 mateuszvis 204
  filebuff[filesize++] = LSB(c->CTYINFO.id);   /* country LSB */
205
  filebuff[filesize++] = MSB(c->CTYINFO.id);   /* country MSB */
206
  filebuff[filesize++] = LSB(c->CTYINFO.codepage); /* codepage LSB */
207
  filebuff[filesize++] = MSB(c->CTYINFO.codepage); /* codepage MSB */
208
  filesize += 4;       /* reserved bytes */
209
 
585 mateuszvis 210
  filesize += 4;
591 mateuszvis 211
  memcpy(filebuff + filesize - 4, &filesize, sizeof(filesize));
212
 
585 mateuszvis 213
  /* index of subfunctions */
591 mateuszvis 214
  filebuff[filesize] = 7; /* there are 7 subfunctions */
215
  filesize += 2;
585 mateuszvis 216
  for (x = 0; x < 7; x++) { /* dump each subfunction (size, id, offset) */
217
    /* size is always 6 */
591 mateuszvis 218
    filebuff[filesize] = 6;
219
    filesize += 2;
585 mateuszvis 220
    /* id of the subfunction */
221
    filebuff[filesize++] = LSB(subfunction_id[x]);
222
    filebuff[filesize++] = MSB(subfunction_id[x]);
223
    /* remember the offset of the subfunction pointer for later */
224
    subfunction_ptr[x] = filesize;
225
    filesize += 4;
226
  }
591 mateuszvis 227
 
585 mateuszvis 228
  /* write the CTYINFO subfunction */
591 mateuszvis 229
  memcpy(filebuff + subfunction_ptr[0], &filesize, sizeof(filesize));
230
 
585 mateuszvis 231
  /* subfunction header */
232
  memcpy(filebuff + filesize, "\377CTYINFO", 8);
233
  filesize += 8;
234
  /* subfunction size */
591 mateuszvis 235
  filebuff[filesize] = 22;
236
  filesize += 2;
237
 
585 mateuszvis 238
  /* country preferences */
591 mateuszvis 239
  memcpy(filebuff + filesize, &(c->CTYINFO), 22);
240
  filesize += 22;
585 mateuszvis 241
 
242
  /* write the UCASE subfunction (used for LCASE, too) */
591 mateuszvis 243
  memcpy(filebuff + subfunction_ptr[1], &filesize, sizeof(filesize));
244
  memcpy(filebuff + subfunction_ptr[2], &filesize, sizeof(filesize));
245
 
585 mateuszvis 246
  /* subfunction header */
247
  memcpy(filebuff + filesize, "\377UCASE  ", 8);
248
  filesize += 8;
249
  /* subfunction size */
250
  filebuff[filesize++] = 128;
251
  filebuff[filesize++] = 0;
252
  /* UCASE table */
591 mateuszvis 253
  memcpy(filebuff + filesize, ucase_437, 128);
254
  filesize += 128;
585 mateuszvis 255
 
256
  /* write the FCHAR subfunction (filename terminator table) */
591 mateuszvis 257
  memcpy(filebuff + subfunction_ptr[3], &filesize, sizeof(filesize));
258
 
585 mateuszvis 259
  /* subfunction header */
260
  memcpy(filebuff + filesize, "\377FCHAR  ", 8);
261
  filesize += 8;
262
  /* subfunction size */
263
  filebuff[filesize++] = 22;
264
  filebuff[filesize++] = 0;
265
  /* values here are quite obscure, dumped from country.sys */
266
  filebuff[filesize++] = 142;
267
  filebuff[filesize++] = 0;
268
  filebuff[filesize++] = 255;
269
  filebuff[filesize++] = 65;
270
  filebuff[filesize++] = 0;
271
  filebuff[filesize++] = 32;
272
  filebuff[filesize++] = 238;
273
  /* list of characters that terminates a filename */
274
  filebuff[filesize++] = 14;  /* how many of them */
275
  filebuff[filesize++] = 46;  /* . */
276
  filebuff[filesize++] = 34;  /* " */
277
  filebuff[filesize++] = 47;  /* / */
278
  filebuff[filesize++] = 92;  /* \ */
279
  filebuff[filesize++] = 91;  /* [ */
280
  filebuff[filesize++] = 93;  /* ] */
281
  filebuff[filesize++] = 58;  /* : */
282
  filebuff[filesize++] = 124; /* | */
283
  filebuff[filesize++] = 60;  /* < */
284
  filebuff[filesize++] = 62;  /* > */
285
  filebuff[filesize++] = 43;  /* + */
286
  filebuff[filesize++] = 61;  /* = */
287
  filebuff[filesize++] = 59;  /* ; */
288
  filebuff[filesize++] = 44;  /* , */
289
 
290
  /* write the COLLATE subfunction */
591 mateuszvis 291
  memcpy(filebuff + subfunction_ptr[4], &filesize, sizeof(filesize));
292
 
585 mateuszvis 293
  /* subfunction header */
294
  memcpy(filebuff + filesize, "\377COLLATE", 8);
295
  filesize += 8;
296
  /* subfunction size */
297
  filebuff[filesize++] = LSB(256);
298
  filebuff[filesize++] = MSB(256);
299
  /* collation for standard CP437 */
591 mateuszvis 300
  memcpy(filebuff + filesize, collate_437, 256);
301
  filesize += 256;
585 mateuszvis 302
 
303
  /* write the DBCS subfunction */
591 mateuszvis 304
  memcpy(filebuff + subfunction_ptr[5], &filesize, sizeof(filesize));
585 mateuszvis 305
  /* subfunction header */
306
  memcpy(filebuff + filesize, "\377DBCS   ", 8);
307
  filesize += 8;
308
  /* subfunction size */
309
  filebuff[filesize++] = 0;
310
  filebuff[filesize++] = 0;
311
  /* table terminator (must be there even if no lenght is zero */
312
  filebuff[filesize++] = 0;
313
  filebuff[filesize++] = 0;
314
 
315
  /* write the YESNO subfunction */
591 mateuszvis 316
  memcpy(filebuff + subfunction_ptr[6], &filesize, sizeof(filesize));
585 mateuszvis 317
  memcpy(filebuff + filesize, "\377YESNO  ", 8);
318
  filesize += 8;
591 mateuszvis 319
  filebuff[filesize] = 4;  /* size (LSB) */
320
  filesize += 2;
321
  memcpy(filebuff + filesize, &(c->YESNO), 4);
322
  filesize += 4;
585 mateuszvis 323
 
324
  /* write the file trailer */
325
  memcpy(filebuff + filesize, "LOCALCFG", 8);
326
  filesize += 8;
327
 
328
  /* write the buffer to file */
329
  fd = fopen(fname, "wb");
330
  if (fd == NULL) return(-1);
331
  fwrite(filebuff, 1, filesize, fd);
332
  fclose(fd);
333
 
334
  return(0);
335
}