Subversion Repositories SvarDOS

Rev

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

Rev 606 Rev 610
1
/*
1
/*
2
 * Locales configuration for SvarDOS
2
 * Locales configuration for SvarDOS
3
 *
3
 *
4
 * Copyright (C) Mateusz Viste 2015-2022
4
 * Copyright (C) Mateusz Viste 2015-2022
5
 *
5
 *
6
 * MIT license
6
 * MIT license
7
 *
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to
9
 * of this software and associated documentation files (the "Software"), to
10
 * deal in the Software without restriction, including without limitation the
10
 * deal in the Software without restriction, including without limitation the
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12
 * sell copies of the Software, and to permit persons to whom the Software is
12
 * sell copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
13
 * furnished to do so, subject to the following conditions:
14
 *
14
 *
15
 * 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
16
 * all copies or substantial portions of the Software.
16
 * all copies or substantial portions of the Software.
17
 *
17
 *
18
 * 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
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * 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
21
 * 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
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
 * IN THE SOFTWARE.
24
 * IN THE SOFTWARE.
25
 */
25
 */
26
 
26
 
27
#include <stdio.h>
27
#include <stdio.h>
28
#include <stdlib.h> /* atoi() */
28
#include <stdlib.h> /* atoi() */
29
#include <string.h> /* strchr */
29
#include <string.h> /* strchr */
30
 
30
 
31
#include "svarlang.lib/svarlang.h"
31
#include "svarlang.lib/svarlang.h"
32
 
32
 
33
#include "country.h"
33
#include "country.h"
34
 
34
 
35
#define PVER "20220203"
35
#define PVER "20220203"
36
#define PDATE "2015-2022"
36
#define PDATE "2015-2022"
37
 
37
 
38
 
38
 
39
enum NLS_STRINGS {
39
enum NLS_STRINGS {
40
  NLS_HLP_VER           = 0x0000,
40
  NLS_HLP_VER           = 0x0000,
41
  NLS_HLP_DESC          = 0x0001,
41
  NLS_HLP_DESC          = 0x0001,
42
  NLS_HLP_USAGE         = 0x0002,
42
  NLS_HLP_USAGE         = 0x0002,
43
  NLS_HLP_OPTIONS       = 0x0003,
43
  NLS_HLP_OPTIONS       = 0x0003,
44
  NLS_HLP_COUNTRY       = 0x000A,
44
  NLS_HLP_COUNTRY       = 0x000A,
45
  NLS_HLP_CP            = 0x000B,
45
  NLS_HLP_CP            = 0x000B,
46
  NLS_HLP_DECIM         = 0x000C,
46
  NLS_HLP_DECIM         = 0x000C,
47
  NLS_HLP_THOUS         = 0x000D,
47
  NLS_HLP_THOUS         = 0x000D,
48
  NLS_HLP_DATESEP       = 0x000E,
48
  NLS_HLP_DATESEP       = 0x000E,
49
  NLS_HLP_DATEFMT       = 0x000F,
49
  NLS_HLP_DATEFMT       = 0x000F,
50
  NLS_HLP_TIMESEP       = 0x0010,
50
  NLS_HLP_TIMESEP       = 0x0010,
51
  NLS_HLP_TIMEFMT       = 0x0011,
51
  NLS_HLP_TIMEFMT       = 0x0011,
52
  NLS_HLP_CURR          = 0x0012,
52
  NLS_HLP_CURR          = 0x0012,
53
  NLS_HLP_CURRPOS0      = 0x0013,
53
  NLS_HLP_CURRPOS0      = 0x0013,
54
  NLS_HLP_CURRPOS1      = 0x0014,
54
  NLS_HLP_CURRPOS1      = 0x0014,
55
  NLS_HLP_CURRPOS2      = 0x0015,
55
  NLS_HLP_CURRPOS2      = 0x0015,
56
  NLS_HLP_CURRSPC       = 0x0016,
56
  NLS_HLP_CURRSPC       = 0x0016,
57
  NLS_HLP_CURRPREC      = 0x0017,
57
  NLS_HLP_CURRPREC      = 0x0017,
58
  NLS_HLP_YESNO         = 0x0018,
58
  NLS_HLP_YESNO         = 0x0018,
59
  NLS_HLP_INFOLOC1      = 0x0032,
59
  NLS_HLP_INFOLOC1      = 0x0032,
60
  NLS_HLP_INFOLOC2      = 0x0033,
60
  NLS_HLP_INFOLOC2      = 0x0033,
61
 
61
 
62
  NLS_INFO_COUNTRY      = 0x0700,
62
  NLS_INFO_COUNTRY      = 0x0700,
63
  NLS_INFO_CODEPAGE     = 0x0701,
63
  NLS_INFO_CODEPAGE     = 0x0701,
64
  NLS_INFO_DECSEP       = 0x0702,
64
  NLS_INFO_DECSEP       = 0x0702,
65
  NLS_INFO_THOUSEP      = 0x0703,
65
  NLS_INFO_THOUSEP      = 0x0703,
66
  NLS_INFO_DATEFMT      = 0x0704,
66
  NLS_INFO_DATEFMT      = 0x0704,
67
  NLS_INFO_TIMEFMT      = 0x0705,
67
  NLS_INFO_TIMEFMT      = 0x0705,
68
  NLS_INFO_YESNO        = 0x0706,
68
  NLS_INFO_YESNO        = 0x0706,
69
  NLS_INFO_CURREXAMPLE  = 0x0707,
69
  NLS_INFO_CURREXAMPLE  = 0x0707,
70
  NLS_MAKESURE          = 0x0709,
70
  NLS_MAKESURE          = 0x0709,
71
 
71
 
72
  NLS_ERR_FILEPATHTWICE = 0x0900,
72
  NLS_ERR_FILEPATHTWICE = 0x0900,
73
  NLS_ERR_BADPATH       = 0x0901,
73
  NLS_ERR_BADPATH       = 0x0901,
74
  NLS_ERR_READFAIL      = 0x0902,
74
  NLS_ERR_READFAIL      = 0x0902,
75
  NLS_ERR_INVPARAM      = 0x0903
75
  NLS_ERR_INVPARAM      = 0x0903
76
};
76
};
77
 
77
 
78
 
78
 
79
static void output(const char *s) {
79
static void output(const char *s) {
80
  _asm {
80
  _asm {
81
    /* set cx to strlen(s) */
81
    /* set cx to strlen(s) */
82
    push ds
82
    push ds
83
    pop es
83
    pop es
84
    mov di, s
84
    mov di, s
85
    xor al, al
85
    xor al, al
86
    cld
86
    cld
87
    mov cx, 0xff
87
    mov cx, 0xff
88
    repne scasb  /* compare ES:DI with AL, inc DI until match */
88
    repne scasb  /* compare ES:DI with AL, inc DI until match */
89
    mov cx, di
89
    mov cx, di
90
    sub cx, s
90
    sub cx, s
91
    dec cx
91
    dec cx
92
    /* output via DOS */
92
    /* output via DOS */
93
    mov ah, 0x40  /* write to handle */
93
    mov ah, 0x40  /* write to handle */
94
    mov bx, 1     /* 1=stdout */
94
    mov bx, 1     /* 1=stdout */
95
    mov dx, s
95
    mov dx, s
96
    int 0x21
96
    int 0x21
97
  }
97
  }
98
}
98
}
99
 
99
 
100
 
100
 
101
static void crlf(void) {
101
static void crlf(void) {
102
  output("\r\n");
102
  output("\r\n");
103
}
103
}
104
 
104
 
105
 
105
 
106
static void outputnl(const char *s) {
106
static void outputnl(const char *s) {
107
  output(s);
107
  output(s);
108
  crlf();
108
  crlf();
109
}
109
}
110
 
110
 
111
 
111
 
112
static void nls_put(enum NLS_STRINGS id) {
112
static void nls_put(enum NLS_STRINGS id) {
113
  output(svarlang_strid(id));
113
  output(svarlang_strid(id));
114
}
114
}
115
 
115
 
116
 
116
 
117
static void nls_puts(enum NLS_STRINGS id) {
117
static void nls_puts(enum NLS_STRINGS id) {
118
  nls_put(id);
118
  nls_put(id);
119
  crlf();
119
  crlf();
120
}
120
}
121
 
121
 
122
 
122
 
123
static void about(void) {
123
static void about(void) {
124
  output("localcfg ");
124
  output("localcfg ");
125
  nls_put(NLS_HLP_VER);
125
  nls_put(NLS_HLP_VER);
126
  outputnl(" " PVER ", (C) " PDATE " Mateusz Viste");
126
  outputnl(" " PVER ", (C) " PDATE " Mateusz Viste");
127
  nls_puts(NLS_HLP_DESC);
127
  nls_puts(NLS_HLP_DESC);
128
  crlf();
128
  crlf();
129
  nls_puts(NLS_HLP_USAGE);
129
  nls_puts(NLS_HLP_USAGE);
130
  crlf();
130
  crlf();
131
  nls_puts(NLS_HLP_OPTIONS);
131
  nls_puts(NLS_HLP_OPTIONS);
132
  crlf();
132
  crlf();
133
  nls_puts(NLS_HLP_COUNTRY);
133
  nls_puts(NLS_HLP_COUNTRY);
134
  nls_puts(NLS_HLP_CP);
134
  nls_puts(NLS_HLP_CP);
135
  nls_puts(NLS_HLP_DECIM);
135
  nls_puts(NLS_HLP_DECIM);
136
  nls_puts(NLS_HLP_THOUS);
136
  nls_puts(NLS_HLP_THOUS);
137
  nls_puts(NLS_HLP_DATESEP);
137
  nls_puts(NLS_HLP_DATESEP);
138
  nls_puts(NLS_HLP_DATEFMT);
138
  nls_puts(NLS_HLP_DATEFMT);
139
  nls_puts(NLS_HLP_TIMESEP);
139
  nls_puts(NLS_HLP_TIMESEP);
140
  nls_puts(NLS_HLP_TIMEFMT);
140
  nls_puts(NLS_HLP_TIMEFMT);
141
  nls_puts(NLS_HLP_CURR);
141
  nls_puts(NLS_HLP_CURR);
142
  nls_puts(NLS_HLP_CURRPOS0);
142
  nls_puts(NLS_HLP_CURRPOS0);
143
  nls_puts(NLS_HLP_CURRPOS1);
143
  nls_puts(NLS_HLP_CURRPOS1);
144
  nls_puts(NLS_HLP_CURRPOS2);
144
  nls_puts(NLS_HLP_CURRPOS2);
145
  nls_puts(NLS_HLP_CURRSPC);
145
  nls_puts(NLS_HLP_CURRSPC);
146
  nls_puts(NLS_HLP_CURRPREC);
146
  nls_puts(NLS_HLP_CURRPREC);
147
  nls_puts(NLS_HLP_YESNO);
147
  nls_puts(NLS_HLP_YESNO);
148
  crlf();
148
  crlf();
149
  nls_puts(NLS_HLP_INFOLOC1);
149
  nls_puts(NLS_HLP_INFOLOC1);
150
  nls_puts(NLS_HLP_INFOLOC2);
150
  nls_puts(NLS_HLP_INFOLOC2);
151
}
151
}
152
 
152
 
153
 
153
 
154
static char *datestring(struct country *c) {
154
static char *datestring(char *result, struct country *c) {
155
  static char result[16];
-
 
156
  switch (c->CTYINFO.datefmt) {
155
  switch (c->CTYINFO.datefmt) {
157
    case COUNTRY_DATE_MDY:
156
    case COUNTRY_DATE_MDY:
158
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
157
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
159
      break;
158
      break;
160
    case COUNTRY_DATE_DMY:
159
    case COUNTRY_DATE_DMY:
161
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
160
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
162
      break;
161
      break;
163
    case COUNTRY_DATE_YMD:
162
    case COUNTRY_DATE_YMD:
164
    default:
163
    default:
165
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
164
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
166
      break;
165
      break;
167
  }
166
  }
168
  return(result);
167
  return(result);
169
}
168
}
170
 
169
 
171
 
170
 
172
static char *timestring(struct country *c) {
171
static char *timestring(char *result, struct country *c) {
173
  static char result[16];
-
 
174
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
172
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
175
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
173
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
176
  } else {
174
  } else {
177
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
175
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
178
  }
176
  }
179
  return(result);
177
  return(result);
180
}
178
}
181
 
179
 
182
 
180
 
183
static char *currencystring(struct country *c) {
181
static char *currencystring(char *result, struct country *c) {
184
  static char result[16];
-
 
185
  char decimalpart[16];
182
  char decimalpart[16];
186
  char space[2] = {0, 0};
183
  char space[2] = {0, 0};
187
  char decsym[8];
184
  char decsym[8];
188
  char cursym[8];
185
  char cursym[8];
189
  decimalpart[0] = '1';
186
  decimalpart[0] = '1';
190
  decimalpart[1] = '2';
187
  decimalpart[1] = '2';
191
  decimalpart[2] = '3';
188
  decimalpart[2] = '3';
192
  decimalpart[3] = '4';
189
  decimalpart[3] = '4';
193
  decimalpart[4] = '5';
190
  decimalpart[4] = '5';
194
  decimalpart[5] = '6';
191
  decimalpart[5] = '6';
195
  decimalpart[6] = '7';
192
  decimalpart[6] = '7';
196
  decimalpart[7] = '8';
193
  decimalpart[7] = '8';
197
  decimalpart[8] = '9';
194
  decimalpart[8] = '9';
198
  decimalpart[9] = 0;
195
  decimalpart[9] = 0;
199
  /* prepare the decimal string first */
196
  /* prepare the decimal string first */
200
  if (c->CTYINFO.currprec < 9) {
197
  if (c->CTYINFO.currprec < 9) {
201
    decimalpart[c->CTYINFO.currprec] = 0;
198
    decimalpart[c->CTYINFO.currprec] = 0;
202
  }
199
  }
203
  /* prepare the currency space string */
200
  /* prepare the currency space string */
204
  if (c->CTYINFO.currspace != 0) {
201
  if (c->CTYINFO.currspace != 0) {
205
    space[0] = ' ';
202
    space[0] = ' ';
206
  }
203
  }
207
  /* prepare the currency and decimal symbols */
204
  /* prepare the currency and decimal symbols */
208
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
205
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
209
    sprintf(decsym, "%s", c->CTYINFO.currsym);
206
    sprintf(decsym, "%s", c->CTYINFO.currsym);
210
    cursym[0] = 0;
207
    cursym[0] = 0;
211
  } else {
208
  } else {
212
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
209
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
213
    sprintf(cursym, "%s", c->CTYINFO.currsym);
210
    sprintf(cursym, "%s", c->CTYINFO.currsym);
214
  }
211
  }
215
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
212
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
216
  /* compute the final string */
213
  /* compute the final string */
217
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
214
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
218
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
215
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
219
  } else { /* currency follows value or replaces decimal symbol */
216
  } else { /* currency follows value or replaces decimal symbol */
220
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
217
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
221
  }
218
  }
222
  return(result);
219
  return(result);
223
}
220
}
224
 
221
 
225
 
222
 
226
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
223
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
227
static int stringstartswith(char *str, char *prefix) {
224
static int stringstartswith(char *str, char *prefix) {
228
  for (;;) {
225
  for (;;) {
229
    /* end of prefix means success */
226
    /* end of prefix means success */
230
    if (*prefix == 0) return(0);
227
    if (*prefix == 0) return(0);
231
    /* otherwise there is no match */
228
    /* otherwise there is no match */
232
    if (*str != *prefix) return(-1);
229
    if (*str != *prefix) return(-1);
233
    /* if match good so far, look at next char */
230
    /* if match good so far, look at next char */
234
    str += 1;
231
    str += 1;
235
    prefix += 1;
232
    prefix += 1;
236
  }
233
  }
237
}
234
}
238
 
235
 
239
 
236
 
240
/* processes an argument. returns 0 on success, non-zero otherwise. */
237
/* processes an argument. returns 0 on success, non-zero otherwise. */
241
static int processarg(char *arg, struct country *c) {
238
static int processarg(char *arg, struct country *c) {
242
  char *value;
239
  char *value;
243
  int intvalue;
240
  int intvalue;
244
  /* an option must start with a '/' */
241
  /* an option must start with a '/' */
245
  if (arg[0] != '/') return(-1);
242
  if (arg[0] != '/') return(-1);
246
  arg += 1; /* skip the slash */
243
  arg += 1; /* skip the slash */
247
  /* find where the value starts */
244
  /* find where the value starts */
248
  value = strchr(arg, ':');
245
  value = strchr(arg, ':');
249
  /* if no value present, fail */
246
  /* if no value present, fail */
250
  if (value == NULL) return(-2);
247
  if (value == NULL) return(-2);
251
  value += 1;
248
  value += 1;
252
  if (*value == 0) return(-3);
249
  if (*value == 0) return(-3);
253
  /* interpret the option now */
250
  /* interpret the option now */
254
  if (stringstartswith(arg, "country:") == 0) {
251
  if (stringstartswith(arg, "country:") == 0) {
255
    intvalue = atoi(value);
252
    intvalue = atoi(value);
256
    if ((intvalue > 0) && (intvalue < 1000)) {
253
    if ((intvalue > 0) && (intvalue < 1000)) {
257
      c->CTYINFO.id = intvalue;
254
      c->CTYINFO.id = intvalue;
258
      return(0);
255
      return(0);
259
    }
256
    }
260
  } else if (stringstartswith(arg, "cp:") == 0) {
257
  } else if (stringstartswith(arg, "cp:") == 0) {
261
    intvalue = atoi(value);
258
    intvalue = atoi(value);
262
    if ((intvalue > 0) && (intvalue < 1000)) {
259
    if ((intvalue > 0) && (intvalue < 1000)) {
263
      c->CTYINFO.codepage = intvalue;
260
      c->CTYINFO.codepage = intvalue;
264
      return(0);
261
      return(0);
265
    }
262
    }
266
  } else if (stringstartswith(arg, "decim:") == 0) {
263
  } else if (stringstartswith(arg, "decim:") == 0) {
267
    if (value[1] == 0) { /* value must be exactly one character */
264
    if (value[1] == 0) { /* value must be exactly one character */
268
      c->CTYINFO.decimal[0] = *value;
265
      c->CTYINFO.decimal[0] = *value;
269
      return(0);
266
      return(0);
270
    }
267
    }
271
  } else if (stringstartswith(arg, "thous:") == 0) {
268
  } else if (stringstartswith(arg, "thous:") == 0) {
272
    if (value[1] == 0) { /* value must be exactly one character */
269
    if (value[1] == 0) { /* value must be exactly one character */
273
      c->CTYINFO.thousands[0] = *value;
270
      c->CTYINFO.thousands[0] = *value;
274
      return(0);
271
      return(0);
275
    }
272
    }
276
  } else if (stringstartswith(arg, "datesep:") == 0) {
273
  } else if (stringstartswith(arg, "datesep:") == 0) {
277
    if (value[1] == 0) { /* value must be exactly one character */
274
    if (value[1] == 0) { /* value must be exactly one character */
278
      c->CTYINFO.datesep[0] = *value;
275
      c->CTYINFO.datesep[0] = *value;
279
      return(0);
276
      return(0);
280
    }
277
    }
281
  } else if (stringstartswith(arg, "timesep:") == 0) {
278
  } else if (stringstartswith(arg, "timesep:") == 0) {
282
    if (value[1] == 0) { /* value must be exactly one character */
279
    if (value[1] == 0) { /* value must be exactly one character */
283
      c->CTYINFO.timesep[0] = *value;
280
      c->CTYINFO.timesep[0] = *value;
284
      return(0);
281
      return(0);
285
    }
282
    }
286
  } else if (stringstartswith(arg, "datefmt:") == 0) {
283
  } else if (stringstartswith(arg, "datefmt:") == 0) {
287
    if (strcmp(value, "MDY") == 0) {
284
    if (strcmp(value, "MDY") == 0) {
288
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
285
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
289
      return(0);
286
      return(0);
290
    } else if (strcmp(value, "DMY") == 0) {
287
    } else if (strcmp(value, "DMY") == 0) {
291
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
288
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
292
      return(0);
289
      return(0);
293
    } else if (strcmp(value, "YMD") == 0) {
290
    } else if (strcmp(value, "YMD") == 0) {
294
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
291
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
295
      return(0);
292
      return(0);
296
    }
293
    }
297
  } else if (stringstartswith(arg, "timefmt:") == 0) {
294
  } else if (stringstartswith(arg, "timefmt:") == 0) {
298
    if (value[1] == 0) {
295
    if (value[1] == 0) {
299
      if ((value[0] >= '0') && (value[0] <= '1')) {
296
      if ((value[0] >= '0') && (value[0] <= '1')) {
300
        c->CTYINFO.timefmt = value[0] - '0';
297
        c->CTYINFO.timefmt = value[0] - '0';
301
        return(0);
298
        return(0);
302
      }
299
      }
303
    }
300
    }
304
  } else if (stringstartswith(arg, "curr:") == 0) {
301
  } else if (stringstartswith(arg, "curr:") == 0) {
305
    if (strlen(value) <= 4) {
302
    if (strlen(value) <= 4) {
306
      strcpy(c->CTYINFO.currsym, value);
303
      strcpy(c->CTYINFO.currsym, value);
307
      return(0);
304
      return(0);
308
    }
305
    }
309
  } else if (stringstartswith(arg, "currpos:") == 0) {
306
  } else if (stringstartswith(arg, "currpos:") == 0) {
310
    if (value[1] == 0) {
307
    if (value[1] == 0) {
311
      if (value[0] == '0') {
308
      if (value[0] == '0') {
312
        c->CTYINFO.currpos = 0;
309
        c->CTYINFO.currpos = 0;
313
        return(0);
310
        return(0);
314
      } else if (value[0] == '1') {
311
      } else if (value[0] == '1') {
315
        c->CTYINFO.currpos = 1;
312
        c->CTYINFO.currpos = 1;
316
        return(0);
313
        return(0);
317
      } else if (value[0] == '2') {
314
      } else if (value[0] == '2') {
318
        c->CTYINFO.currpos = 0;
315
        c->CTYINFO.currpos = 0;
319
        c->CTYINFO.currdecsym = 1;
316
        c->CTYINFO.currdecsym = 1;
320
        return(0);
317
        return(0);
321
      }
318
      }
322
    }
319
    }
323
  } else if (stringstartswith(arg, "currspc:") == 0) {
320
  } else if (stringstartswith(arg, "currspc:") == 0) {
324
    if (value[1] == 0) {
321
    if (value[1] == 0) {
325
      if ((value[0] >= '0') && (value[0] <= '1')) {
322
      if ((value[0] >= '0') && (value[0] <= '1')) {
326
        c->CTYINFO.currspace = value[0] - '0';
323
        c->CTYINFO.currspace = value[0] - '0';
327
        return(0);
324
        return(0);
328
      }
325
      }
329
    }
326
    }
330
  } else if (stringstartswith(arg, "currprec:") == 0) {
327
  } else if (stringstartswith(arg, "currprec:") == 0) {
331
    if (value[1] == 0) {
328
    if (value[1] == 0) {
332
      if ((value[0] >= '0') && (value[0] <= '9')) {
329
      if ((value[0] >= '0') && (value[0] <= '9')) {
333
        c->CTYINFO.currprec = value[0] - '0';
330
        c->CTYINFO.currprec = value[0] - '0';
334
        return(0);
331
        return(0);
335
      }
332
      }
336
    }
333
    }
337
  } else if (stringstartswith(arg, "yesno:") == 0) {
334
  } else if (stringstartswith(arg, "yesno:") == 0) {
338
    /* string must be exactly 2 characters long */
335
    /* string must be exactly 2 characters long */
339
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
336
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
340
      c->YESNO.yes[0] = value[0];
337
      c->YESNO.yes[0] = value[0];
341
      c->YESNO.no[0] = value[1];
338
      c->YESNO.no[0] = value[1];
342
      return(0);
339
      return(0);
343
    }
340
    }
344
  }
341
  }
345
  /* if I'm here, something went wrong */
342
  /* if I'm here, something went wrong */
346
  return(-4);
343
  return(-4);
347
}
344
}
348
 
345
 
349
 
346
 
350
/* converts a path to its canonic representation, returns 0 on success
347
/* converts a path to its canonic representation, returns 0 on success
351
 * or DOS err on failure (invalid drive) */
348
 * or DOS err on failure (invalid drive) */
352
static unsigned short file_truename(const char *dst, char *src) {
349
static unsigned short file_truename(const char *dst, char *src) {
353
  unsigned short res = 0;
350
  unsigned short res = 0;
354
  _asm {
351
  _asm {
355
    push es
352
    push es
356
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
353
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
357
    push ds
354
    push ds
358
    pop es
355
    pop es
359
    mov si, src
356
    mov si, src
360
    mov di, dst
357
    mov di, dst
361
    int 0x21
358
    int 0x21
362
    jnc DONE
359
    jnc DONE
363
    mov [res], ax
360
    mov [res], ax
364
    DONE:
361
    DONE:
365
    pop es
362
    pop es
366
  }
363
  }
367
  return(res);
364
  return(res);
368
}
365
}
369
 
366
 
370
 
367
 
371
static void default_country_path(char *s) {
368
static void default_country_path(char *s) {
372
  char *dosdir = getenv("DOSDIR");
369
  char *dosdir = getenv("DOSDIR");
373
  size_t dosdirlen;
370
  size_t dosdirlen;
374
  s[0] = 0;
371
  s[0] = 0;
375
  if (dosdir == NULL) return;
372
  if (dosdir == NULL) return;
376
  dosdirlen = strlen(dosdir);
373
  dosdirlen = strlen(dosdir);
377
  if (dosdirlen == 0) return;
374
  if (dosdirlen == 0) return;
378
  /* drop trailing backslash if present */
375
  /* drop trailing backslash if present */
379
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
376
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
380
  /* copy dosdir to s and append the rest of the path */
377
  /* copy dosdir to s and append the rest of the path */
381
  memcpy(s, dosdir, dosdirlen);
378
  memcpy(s, dosdir, dosdirlen);
382
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
379
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
383
}
380
}
384
 
381
 
385
 
382
 
386
int main(int argc, char **argv) {
383
int main(int argc, char **argv) {
387
  struct country cntdata;
384
  struct country cntdata;
388
  int changedflag;
385
  int changedflag;
389
  int x;
386
  int x;
390
  char fname[130];
387
  static char fname[130];
391
  char buff[128];
388
  static char buff[64];
392
 
389
 
393
  svarlang_autoload("localcfg");
390
  svarlang_autoload("localcfg");
394
 
391
 
395
  /* scan argv looking for the path to country.sys */
392
  /* scan argv looking for the path to country.sys */
396
  for (x = 1; x < argc; x++) {
393
  for (x = 1; x < argc; x++) {
397
    if (argv[x][0] != '/') {
394
    if (argv[x][0] != '/') {
398
      if (fname[0] != 0) {
395
      if (fname[0] != 0) {
399
        nls_puts(NLS_ERR_FILEPATHTWICE);
396
        nls_puts(NLS_ERR_FILEPATHTWICE);
400
        return(1);
397
        return(1);
401
      }
398
      }
402
      /* */
399
      /* */
403
      if (file_truename(fname, argv[x]) != 0) {
400
      if (file_truename(fname, argv[x]) != 0) {
404
        nls_puts(NLS_ERR_BADPATH);
401
        nls_puts(NLS_ERR_BADPATH);
405
        return(1);
402
        return(1);
406
      }
403
      }
407
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
404
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
408
      about();
405
      about();
409
      return(1);
406
      return(1);
410
    }
407
    }
411
  }
408
  }
412
 
409
 
413
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
410
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
414
  if (fname[0] == 0) default_country_path(fname);
411
  if (fname[0] == 0) default_country_path(fname);
415
 
412
 
416
  x = country_read(&cntdata, fname);
413
  x = country_read(&cntdata, fname);
417
  if (x != 0) {
414
  if (x != 0) {
418
    nls_puts(NLS_ERR_READFAIL);
415
    nls_puts(NLS_ERR_READFAIL);
419
    return(2);
416
    return(2);
420
  }
417
  }
421
 
418
 
422
  changedflag = 0;
419
  changedflag = 0;
423
 
420
 
424
  /* process command line arguments */
421
  /* process command line arguments */
425
  for (x = 1; x < argc; x++) {
422
  for (x = 1; x < argc; x++) {
426
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
423
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
427
    changedflag++;
424
    changedflag++;
428
    if (processarg(argv[x], &cntdata) != 0) {
425
    if (processarg(argv[x], &cntdata) != 0) {
429
      nls_puts(NLS_ERR_INVPARAM);
426
      nls_puts(NLS_ERR_INVPARAM);
430
      return(3);
427
      return(3);
431
    }
428
    }
432
  }
429
  }
433
 
430
 
434
  nls_put(NLS_INFO_COUNTRY);
431
  nls_put(NLS_INFO_COUNTRY);
435
  sprintf(buff, " %03d", cntdata.CTYINFO.id);
432
  sprintf(buff, " %03d", cntdata.CTYINFO.id);
436
  outputnl(buff);
433
  outputnl(buff);
437
  nls_put(NLS_INFO_CODEPAGE);
434
  nls_put(NLS_INFO_CODEPAGE);
438
  sprintf(buff, " %d", cntdata.CTYINFO.codepage);
435
  sprintf(buff, " %d", cntdata.CTYINFO.codepage);
439
  outputnl(buff);
436
  outputnl(buff);
440
  nls_put(NLS_INFO_DECSEP);
437
  nls_put(NLS_INFO_DECSEP);
441
  sprintf(buff, " %c", cntdata.CTYINFO.decimal[0]);
438
  sprintf(buff, " %c", cntdata.CTYINFO.decimal[0]);
442
  outputnl(buff);
439
  outputnl(buff);
443
  nls_put(NLS_INFO_THOUSEP);
440
  nls_put(NLS_INFO_THOUSEP);
444
  sprintf(buff, " %c", cntdata.CTYINFO.thousands[0]);
441
  sprintf(buff, " %c", cntdata.CTYINFO.thousands[0]);
445
  outputnl(buff);
442
  outputnl(buff);
446
  nls_put(NLS_INFO_DATEFMT);
443
  nls_put(NLS_INFO_DATEFMT);
447
  sprintf(buff, " %s", datestring(&cntdata));
444
  output(" ");
448
  outputnl(buff);
445
  outputnl(datestring(buff, &cntdata));
449
  nls_put(NLS_INFO_TIMEFMT);
446
  nls_put(NLS_INFO_TIMEFMT);
450
  sprintf(buff, " %s", timestring(&cntdata));
447
  output(" ");
451
  outputnl(buff);
448
  outputnl(timestring(buff, &cntdata));
452
  nls_put(NLS_INFO_YESNO);
449
  nls_put(NLS_INFO_YESNO);
453
  sprintf(buff, " %c/%c", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
450
  sprintf(buff, " %c/%c", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
454
  outputnl(buff);
451
  outputnl(buff);
455
  nls_put(NLS_INFO_CURREXAMPLE);
452
  nls_put(NLS_INFO_CURREXAMPLE);
456
  sprintf(" %s", currencystring(&cntdata));
453
  output(" ");
457
  outputnl(buff);
454
  outputnl(currencystring(buff, &cntdata));
458
 
455
 
459
  crlf();
456
  crlf();
460
  nls_puts(NLS_MAKESURE);
457
  nls_puts(NLS_MAKESURE);
461
  sprintf(buff, "COUNTRY=%03d,%03d,%s", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage, fname);
458
  sprintf(buff, "COUNTRY=%03d,%03d,", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage);
462
  outputnl(buff);
459
  output(buff);
-
 
460
  outputnl(fname);
463
 
461
 
464
  /* if anything changed, write the new file */
462
  /* if anything changed, write the new file */
465
  if (changedflag != 0) country_write(fname, &cntdata);
463
  if (changedflag != 0) country_write(fname, &cntdata);
466
 
464
 
467
  return(0);
465
  return(0);
468
}
466
}
469
 
467