Subversion Repositories SvarDOS

Rev

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

Rev 610 Rev 611
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
  NLS_ERR_INVFORMAT     = 0x0904,
-
 
77
  NLS_ERR_NOTLOCALCFG   = 0x0905
76
};
78
};
77
 
79
 
78
 
80
 
79
static void output(const char *s) {
81
static void output(const char *s) {
80
  _asm {
82
  _asm {
81
    /* set cx to strlen(s) */
83
    /* set cx to strlen(s) */
82
    push ds
84
    push ds
83
    pop es
85
    pop es
84
    mov di, s
86
    mov di, s
85
    xor al, al
87
    xor al, al
86
    cld
88
    cld
87
    mov cx, 0xff
89
    mov cx, 0xff
88
    repne scasb  /* compare ES:DI with AL, inc DI until match */
90
    repne scasb  /* compare ES:DI with AL, inc DI until match */
89
    mov cx, di
91
    mov cx, di
90
    sub cx, s
92
    sub cx, s
91
    dec cx
93
    dec cx
92
    /* output via DOS */
94
    /* output via DOS */
93
    mov ah, 0x40  /* write to handle */
95
    mov ah, 0x40  /* write to handle */
94
    mov bx, 1     /* 1=stdout */
96
    mov bx, 1     /* 1=stdout */
95
    mov dx, s
97
    mov dx, s
96
    int 0x21
98
    int 0x21
97
  }
99
  }
98
}
100
}
99
 
101
 
100
 
102
 
101
static void crlf(void) {
103
static void crlf(void) {
102
  output("\r\n");
104
  output("\r\n");
103
}
105
}
104
 
106
 
105
 
107
 
106
static void outputnl(const char *s) {
108
static void outputnl(const char *s) {
107
  output(s);
109
  output(s);
108
  crlf();
110
  crlf();
109
}
111
}
110
 
112
 
111
 
113
 
112
static void nls_put(enum NLS_STRINGS id) {
114
static void nls_put(enum NLS_STRINGS id) {
113
  output(svarlang_strid(id));
115
  output(svarlang_strid(id));
114
}
116
}
115
 
117
 
116
 
118
 
117
static void nls_puts(enum NLS_STRINGS id) {
119
static void nls_puts(enum NLS_STRINGS id) {
118
  nls_put(id);
120
  nls_put(id);
119
  crlf();
121
  crlf();
120
}
122
}
121
 
123
 
122
 
124
 
123
static void about(void) {
125
static void about(void) {
124
  output("localcfg ");
126
  output("localcfg ");
125
  nls_put(NLS_HLP_VER);
127
  nls_put(NLS_HLP_VER);
126
  outputnl(" " PVER ", (C) " PDATE " Mateusz Viste");
128
  outputnl(" " PVER ", (C) " PDATE " Mateusz Viste");
127
  nls_puts(NLS_HLP_DESC);
129
  nls_puts(NLS_HLP_DESC);
128
  crlf();
130
  crlf();
129
  nls_puts(NLS_HLP_USAGE);
131
  nls_puts(NLS_HLP_USAGE);
130
  crlf();
132
  crlf();
131
  nls_puts(NLS_HLP_OPTIONS);
133
  nls_puts(NLS_HLP_OPTIONS);
132
  crlf();
134
  crlf();
133
  nls_puts(NLS_HLP_COUNTRY);
135
  nls_puts(NLS_HLP_COUNTRY);
134
  nls_puts(NLS_HLP_CP);
136
  nls_puts(NLS_HLP_CP);
135
  nls_puts(NLS_HLP_DECIM);
137
  nls_puts(NLS_HLP_DECIM);
136
  nls_puts(NLS_HLP_THOUS);
138
  nls_puts(NLS_HLP_THOUS);
137
  nls_puts(NLS_HLP_DATESEP);
139
  nls_puts(NLS_HLP_DATESEP);
138
  nls_puts(NLS_HLP_DATEFMT);
140
  nls_puts(NLS_HLP_DATEFMT);
139
  nls_puts(NLS_HLP_TIMESEP);
141
  nls_puts(NLS_HLP_TIMESEP);
140
  nls_puts(NLS_HLP_TIMEFMT);
142
  nls_puts(NLS_HLP_TIMEFMT);
141
  nls_puts(NLS_HLP_CURR);
143
  nls_puts(NLS_HLP_CURR);
142
  nls_puts(NLS_HLP_CURRPOS0);
144
  nls_puts(NLS_HLP_CURRPOS0);
143
  nls_puts(NLS_HLP_CURRPOS1);
145
  nls_puts(NLS_HLP_CURRPOS1);
144
  nls_puts(NLS_HLP_CURRPOS2);
146
  nls_puts(NLS_HLP_CURRPOS2);
145
  nls_puts(NLS_HLP_CURRSPC);
147
  nls_puts(NLS_HLP_CURRSPC);
146
  nls_puts(NLS_HLP_CURRPREC);
148
  nls_puts(NLS_HLP_CURRPREC);
147
  nls_puts(NLS_HLP_YESNO);
149
  nls_puts(NLS_HLP_YESNO);
148
  crlf();
150
  crlf();
149
  nls_puts(NLS_HLP_INFOLOC1);
151
  nls_puts(NLS_HLP_INFOLOC1);
150
  nls_puts(NLS_HLP_INFOLOC2);
152
  nls_puts(NLS_HLP_INFOLOC2);
151
}
153
}
152
 
154
 
153
 
155
 
154
static char *datestring(char *result, struct country *c) {
156
static char *datestring(char *result, struct country *c) {
155
  switch (c->CTYINFO.datefmt) {
157
  switch (c->CTYINFO.datefmt) {
156
    case COUNTRY_DATE_MDY:
158
    case COUNTRY_DATE_MDY:
157
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
159
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
158
      break;
160
      break;
159
    case COUNTRY_DATE_DMY:
161
    case COUNTRY_DATE_DMY:
160
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
162
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
161
      break;
163
      break;
162
    case COUNTRY_DATE_YMD:
164
    case COUNTRY_DATE_YMD:
163
    default:
165
    default:
164
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
166
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
165
      break;
167
      break;
166
  }
168
  }
167
  return(result);
169
  return(result);
168
}
170
}
169
 
171
 
170
 
172
 
171
static char *timestring(char *result, struct country *c) {
173
static char *timestring(char *result, struct country *c) {
172
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
174
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
173
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
175
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
174
  } else {
176
  } else {
175
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
177
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
176
  }
178
  }
177
  return(result);
179
  return(result);
178
}
180
}
179
 
181
 
180
 
182
 
181
static char *currencystring(char *result, struct country *c) {
183
static char *currencystring(char *result, struct country *c) {
182
  char decimalpart[16];
184
  char decimalpart[16];
183
  char space[2] = {0, 0};
185
  char space[2] = {0, 0};
184
  char decsym[8];
186
  char decsym[8];
185
  char cursym[8];
187
  char cursym[8];
186
  decimalpart[0] = '1';
188
  decimalpart[0] = '1';
187
  decimalpart[1] = '2';
189
  decimalpart[1] = '2';
188
  decimalpart[2] = '3';
190
  decimalpart[2] = '3';
189
  decimalpart[3] = '4';
191
  decimalpart[3] = '4';
190
  decimalpart[4] = '5';
192
  decimalpart[4] = '5';
191
  decimalpart[5] = '6';
193
  decimalpart[5] = '6';
192
  decimalpart[6] = '7';
194
  decimalpart[6] = '7';
193
  decimalpart[7] = '8';
195
  decimalpart[7] = '8';
194
  decimalpart[8] = '9';
196
  decimalpart[8] = '9';
195
  decimalpart[9] = 0;
197
  decimalpart[9] = 0;
196
  /* prepare the decimal string first */
198
  /* prepare the decimal string first */
197
  if (c->CTYINFO.currprec < 9) {
199
  if (c->CTYINFO.currprec < 9) {
198
    decimalpart[c->CTYINFO.currprec] = 0;
200
    decimalpart[c->CTYINFO.currprec] = 0;
199
  }
201
  }
200
  /* prepare the currency space string */
202
  /* prepare the currency space string */
201
  if (c->CTYINFO.currspace != 0) {
203
  if (c->CTYINFO.currspace != 0) {
202
    space[0] = ' ';
204
    space[0] = ' ';
203
  }
205
  }
204
  /* prepare the currency and decimal symbols */
206
  /* prepare the currency and decimal symbols */
205
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
207
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
206
    sprintf(decsym, "%s", c->CTYINFO.currsym);
208
    sprintf(decsym, "%s", c->CTYINFO.currsym);
207
    cursym[0] = 0;
209
    cursym[0] = 0;
208
  } else {
210
  } else {
209
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
211
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
210
    sprintf(cursym, "%s", c->CTYINFO.currsym);
212
    sprintf(cursym, "%s", c->CTYINFO.currsym);
211
  }
213
  }
212
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
214
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
213
  /* compute the final string */
215
  /* compute the final string */
214
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
216
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
215
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
217
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
216
  } else { /* currency follows value or replaces decimal symbol */
218
  } else { /* currency follows value or replaces decimal symbol */
217
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
219
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
218
  }
220
  }
219
  return(result);
221
  return(result);
220
}
222
}
221
 
223
 
222
 
224
 
223
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
225
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
224
static int stringstartswith(char *str, char *prefix) {
226
static int stringstartswith(char *str, char *prefix) {
225
  for (;;) {
227
  for (;;) {
226
    /* end of prefix means success */
228
    /* end of prefix means success */
227
    if (*prefix == 0) return(0);
229
    if (*prefix == 0) return(0);
228
    /* otherwise there is no match */
230
    /* otherwise there is no match */
229
    if (*str != *prefix) return(-1);
231
    if (*str != *prefix) return(-1);
230
    /* if match good so far, look at next char */
232
    /* if match good so far, look at next char */
231
    str += 1;
233
    str += 1;
232
    prefix += 1;
234
    prefix += 1;
233
  }
235
  }
234
}
236
}
235
 
237
 
236
 
238
 
237
/* processes an argument. returns 0 on success, non-zero otherwise. */
239
/* processes an argument. returns 0 on success, non-zero otherwise. */
238
static int processarg(char *arg, struct country *c) {
240
static int processarg(char *arg, struct country *c) {
239
  char *value;
241
  char *value;
240
  int intvalue;
242
  int intvalue;
241
  /* an option must start with a '/' */
243
  /* an option must start with a '/' */
242
  if (arg[0] != '/') return(-1);
244
  if (arg[0] != '/') return(-1);
243
  arg += 1; /* skip the slash */
245
  arg += 1; /* skip the slash */
244
  /* find where the value starts */
246
  /* find where the value starts */
245
  value = strchr(arg, ':');
247
  value = strchr(arg, ':');
246
  /* if no value present, fail */
248
  /* if no value present, fail */
247
  if (value == NULL) return(-2);
249
  if (value == NULL) return(-2);
248
  value += 1;
250
  value += 1;
249
  if (*value == 0) return(-3);
251
  if (*value == 0) return(-3);
250
  /* interpret the option now */
252
  /* interpret the option now */
251
  if (stringstartswith(arg, "country:") == 0) {
253
  if (stringstartswith(arg, "country:") == 0) {
252
    intvalue = atoi(value);
254
    intvalue = atoi(value);
253
    if ((intvalue > 0) && (intvalue < 1000)) {
255
    if ((intvalue > 0) && (intvalue < 1000)) {
254
      c->CTYINFO.id = intvalue;
256
      c->CTYINFO.id = intvalue;
255
      return(0);
257
      return(0);
256
    }
258
    }
257
  } else if (stringstartswith(arg, "cp:") == 0) {
259
  } else if (stringstartswith(arg, "cp:") == 0) {
258
    intvalue = atoi(value);
260
    intvalue = atoi(value);
259
    if ((intvalue > 0) && (intvalue < 1000)) {
261
    if ((intvalue > 0) && (intvalue < 1000)) {
260
      c->CTYINFO.codepage = intvalue;
262
      c->CTYINFO.codepage = intvalue;
261
      return(0);
263
      return(0);
262
    }
264
    }
263
  } else if (stringstartswith(arg, "decim:") == 0) {
265
  } else if (stringstartswith(arg, "decim:") == 0) {
264
    if (value[1] == 0) { /* value must be exactly one character */
266
    if (value[1] == 0) { /* value must be exactly one character */
265
      c->CTYINFO.decimal[0] = *value;
267
      c->CTYINFO.decimal[0] = *value;
266
      return(0);
268
      return(0);
267
    }
269
    }
268
  } else if (stringstartswith(arg, "thous:") == 0) {
270
  } else if (stringstartswith(arg, "thous:") == 0) {
269
    if (value[1] == 0) { /* value must be exactly one character */
271
    if (value[1] == 0) { /* value must be exactly one character */
270
      c->CTYINFO.thousands[0] = *value;
272
      c->CTYINFO.thousands[0] = *value;
271
      return(0);
273
      return(0);
272
    }
274
    }
273
  } else if (stringstartswith(arg, "datesep:") == 0) {
275
  } else if (stringstartswith(arg, "datesep:") == 0) {
274
    if (value[1] == 0) { /* value must be exactly one character */
276
    if (value[1] == 0) { /* value must be exactly one character */
275
      c->CTYINFO.datesep[0] = *value;
277
      c->CTYINFO.datesep[0] = *value;
276
      return(0);
278
      return(0);
277
    }
279
    }
278
  } else if (stringstartswith(arg, "timesep:") == 0) {
280
  } else if (stringstartswith(arg, "timesep:") == 0) {
279
    if (value[1] == 0) { /* value must be exactly one character */
281
    if (value[1] == 0) { /* value must be exactly one character */
280
      c->CTYINFO.timesep[0] = *value;
282
      c->CTYINFO.timesep[0] = *value;
281
      return(0);
283
      return(0);
282
    }
284
    }
283
  } else if (stringstartswith(arg, "datefmt:") == 0) {
285
  } else if (stringstartswith(arg, "datefmt:") == 0) {
284
    if (strcmp(value, "MDY") == 0) {
286
    if (strcmp(value, "MDY") == 0) {
285
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
287
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
286
      return(0);
288
      return(0);
287
    } else if (strcmp(value, "DMY") == 0) {
289
    } else if (strcmp(value, "DMY") == 0) {
288
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
290
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
289
      return(0);
291
      return(0);
290
    } else if (strcmp(value, "YMD") == 0) {
292
    } else if (strcmp(value, "YMD") == 0) {
291
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
293
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
292
      return(0);
294
      return(0);
293
    }
295
    }
294
  } else if (stringstartswith(arg, "timefmt:") == 0) {
296
  } else if (stringstartswith(arg, "timefmt:") == 0) {
295
    if (value[1] == 0) {
297
    if (value[1] == 0) {
296
      if ((value[0] >= '0') && (value[0] <= '1')) {
298
      if ((value[0] >= '0') && (value[0] <= '1')) {
297
        c->CTYINFO.timefmt = value[0] - '0';
299
        c->CTYINFO.timefmt = value[0] - '0';
298
        return(0);
300
        return(0);
299
      }
301
      }
300
    }
302
    }
301
  } else if (stringstartswith(arg, "curr:") == 0) {
303
  } else if (stringstartswith(arg, "curr:") == 0) {
302
    if (strlen(value) <= 4) {
304
    if (strlen(value) <= 4) {
303
      strcpy(c->CTYINFO.currsym, value);
305
      strcpy(c->CTYINFO.currsym, value);
304
      return(0);
306
      return(0);
305
    }
307
    }
306
  } else if (stringstartswith(arg, "currpos:") == 0) {
308
  } else if (stringstartswith(arg, "currpos:") == 0) {
307
    if (value[1] == 0) {
309
    if (value[1] == 0) {
308
      if (value[0] == '0') {
310
      if (value[0] == '0') {
309
        c->CTYINFO.currpos = 0;
311
        c->CTYINFO.currpos = 0;
310
        return(0);
312
        return(0);
311
      } else if (value[0] == '1') {
313
      } else if (value[0] == '1') {
312
        c->CTYINFO.currpos = 1;
314
        c->CTYINFO.currpos = 1;
313
        return(0);
315
        return(0);
314
      } else if (value[0] == '2') {
316
      } else if (value[0] == '2') {
315
        c->CTYINFO.currpos = 0;
317
        c->CTYINFO.currpos = 0;
316
        c->CTYINFO.currdecsym = 1;
318
        c->CTYINFO.currdecsym = 1;
317
        return(0);
319
        return(0);
318
      }
320
      }
319
    }
321
    }
320
  } else if (stringstartswith(arg, "currspc:") == 0) {
322
  } else if (stringstartswith(arg, "currspc:") == 0) {
321
    if (value[1] == 0) {
323
    if (value[1] == 0) {
322
      if ((value[0] >= '0') && (value[0] <= '1')) {
324
      if ((value[0] >= '0') && (value[0] <= '1')) {
323
        c->CTYINFO.currspace = value[0] - '0';
325
        c->CTYINFO.currspace = value[0] - '0';
324
        return(0);
326
        return(0);
325
      }
327
      }
326
    }
328
    }
327
  } else if (stringstartswith(arg, "currprec:") == 0) {
329
  } else if (stringstartswith(arg, "currprec:") == 0) {
328
    if (value[1] == 0) {
330
    if (value[1] == 0) {
329
      if ((value[0] >= '0') && (value[0] <= '9')) {
331
      if ((value[0] >= '0') && (value[0] <= '9')) {
330
        c->CTYINFO.currprec = value[0] - '0';
332
        c->CTYINFO.currprec = value[0] - '0';
331
        return(0);
333
        return(0);
332
      }
334
      }
333
    }
335
    }
334
  } else if (stringstartswith(arg, "yesno:") == 0) {
336
  } else if (stringstartswith(arg, "yesno:") == 0) {
335
    /* string must be exactly 2 characters long */
337
    /* string must be exactly 2 characters long */
336
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
338
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
337
      c->YESNO.yes[0] = value[0];
339
      c->YESNO.yes[0] = value[0];
338
      c->YESNO.no[0] = value[1];
340
      c->YESNO.no[0] = value[1];
339
      return(0);
341
      return(0);
340
    }
342
    }
341
  }
343
  }
342
  /* if I'm here, something went wrong */
344
  /* if I'm here, something went wrong */
343
  return(-4);
345
  return(-4);
344
}
346
}
345
 
347
 
346
 
348
 
347
/* converts a path to its canonic representation, returns 0 on success
349
/* converts a path to its canonic representation, returns 0 on success
348
 * or DOS err on failure (invalid drive) */
350
 * or DOS err on failure (invalid drive) */
349
static unsigned short file_truename(const char *dst, char *src) {
351
static unsigned short file_truename(const char *dst, char *src) {
350
  unsigned short res = 0;
352
  unsigned short res = 0;
351
  _asm {
353
  _asm {
352
    push es
354
    push es
353
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
355
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
354
    push ds
356
    push ds
355
    pop es
357
    pop es
356
    mov si, src
358
    mov si, src
357
    mov di, dst
359
    mov di, dst
358
    int 0x21
360
    int 0x21
359
    jnc DONE
361
    jnc DONE
360
    mov [res], ax
362
    mov [res], ax
361
    DONE:
363
    DONE:
362
    pop es
364
    pop es
363
  }
365
  }
364
  return(res);
366
  return(res);
365
}
367
}
366
 
368
 
367
 
369
 
368
static void default_country_path(char *s) {
370
static void default_country_path(char *s) {
369
  char *dosdir = getenv("DOSDIR");
371
  char *dosdir = getenv("DOSDIR");
370
  size_t dosdirlen;
372
  size_t dosdirlen;
371
  s[0] = 0;
373
  s[0] = 0;
372
  if (dosdir == NULL) return;
374
  if (dosdir == NULL) return;
373
  dosdirlen = strlen(dosdir);
375
  dosdirlen = strlen(dosdir);
374
  if (dosdirlen == 0) return;
376
  if (dosdirlen == 0) return;
375
  /* drop trailing backslash if present */
377
  /* drop trailing backslash if present */
376
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
378
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
377
  /* copy dosdir to s and append the rest of the path */
379
  /* copy dosdir to s and append the rest of the path */
378
  memcpy(s, dosdir, dosdirlen);
380
  memcpy(s, dosdir, dosdirlen);
379
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
381
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
380
}
382
}
381
 
383
 
382
 
384
 
383
int main(int argc, char **argv) {
385
int main(int argc, char **argv) {
384
  struct country cntdata;
386
  struct country cntdata;
385
  int changedflag;
387
  int changedflag;
386
  int x;
388
  int x;
387
  static char fname[130];
389
  static char fname[130];
388
  static char buff[64];
390
  static char buff[64];
389
 
391
 
390
  svarlang_autoload("localcfg");
392
  svarlang_autoload("localcfg");
391
 
393
 
392
  /* scan argv looking for the path to country.sys */
394
  /* scan argv looking for the path to country.sys */
393
  for (x = 1; x < argc; x++) {
395
  for (x = 1; x < argc; x++) {
394
    if (argv[x][0] != '/') {
396
    if (argv[x][0] != '/') {
395
      if (fname[0] != 0) {
397
      if (fname[0] != 0) {
396
        nls_puts(NLS_ERR_FILEPATHTWICE);
398
        nls_puts(NLS_ERR_FILEPATHTWICE);
397
        return(1);
399
        return(1);
398
      }
400
      }
399
      /* */
401
      /* */
400
      if (file_truename(fname, argv[x]) != 0) {
402
      if (file_truename(fname, argv[x]) != 0) {
401
        nls_puts(NLS_ERR_BADPATH);
403
        nls_puts(NLS_ERR_BADPATH);
402
        return(1);
404
        return(1);
403
      }
405
      }
404
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
406
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
405
      about();
407
      about();
406
      return(1);
408
      return(1);
407
    }
409
    }
408
  }
410
  }
409
 
411
 
410
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
412
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
411
  if (fname[0] == 0) default_country_path(fname);
413
  if (fname[0] == 0) default_country_path(fname);
412
 
414
 
413
  x = country_read(&cntdata, fname);
415
  x = country_read(&cntdata, fname);
414
  if (x != 0) {
416
  if (x != 0) {
-
 
417
    if (x == COUNTRY_ERR_INV_FORMAT) {
-
 
418
      nls_puts(NLS_ERR_INVFORMAT);
-
 
419
    } else if (x == COUNTRY_ERR_NOT_LOCALCFG) {
-
 
420
      nls_puts(NLS_ERR_NOTLOCALCFG);
-
 
421
    } else {
415
    nls_puts(NLS_ERR_READFAIL);
422
      nls_puts(NLS_ERR_READFAIL);
-
 
423
    }
416
    return(2);
424
    return(2);
417
  }
425
  }
418
 
426
 
419
  changedflag = 0;
427
  changedflag = 0;
420
 
428
 
421
  /* process command line arguments */
429
  /* process command line arguments */
422
  for (x = 1; x < argc; x++) {
430
  for (x = 1; x < argc; x++) {
423
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
431
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
424
    changedflag++;
432
    changedflag++;
425
    if (processarg(argv[x], &cntdata) != 0) {
433
    if (processarg(argv[x], &cntdata) != 0) {
426
      nls_puts(NLS_ERR_INVPARAM);
434
      nls_puts(NLS_ERR_INVPARAM);
427
      return(3);
435
      return(3);
428
    }
436
    }
429
  }
437
  }
430
 
438
 
431
  nls_put(NLS_INFO_COUNTRY);
439
  nls_put(NLS_INFO_COUNTRY);
432
  sprintf(buff, " %03d", cntdata.CTYINFO.id);
440
  sprintf(buff, " %03d", cntdata.CTYINFO.id);
433
  outputnl(buff);
441
  outputnl(buff);
434
  nls_put(NLS_INFO_CODEPAGE);
442
  nls_put(NLS_INFO_CODEPAGE);
435
  sprintf(buff, " %d", cntdata.CTYINFO.codepage);
443
  sprintf(buff, " %d", cntdata.CTYINFO.codepage);
436
  outputnl(buff);
444
  outputnl(buff);
437
  nls_put(NLS_INFO_DECSEP);
445
  nls_put(NLS_INFO_DECSEP);
438
  sprintf(buff, " %c", cntdata.CTYINFO.decimal[0]);
446
  sprintf(buff, " %c", cntdata.CTYINFO.decimal[0]);
439
  outputnl(buff);
447
  outputnl(buff);
440
  nls_put(NLS_INFO_THOUSEP);
448
  nls_put(NLS_INFO_THOUSEP);
441
  sprintf(buff, " %c", cntdata.CTYINFO.thousands[0]);
449
  sprintf(buff, " %c", cntdata.CTYINFO.thousands[0]);
442
  outputnl(buff);
450
  outputnl(buff);
443
  nls_put(NLS_INFO_DATEFMT);
451
  nls_put(NLS_INFO_DATEFMT);
444
  output(" ");
452
  output(" ");
445
  outputnl(datestring(buff, &cntdata));
453
  outputnl(datestring(buff, &cntdata));
446
  nls_put(NLS_INFO_TIMEFMT);
454
  nls_put(NLS_INFO_TIMEFMT);
447
  output(" ");
455
  output(" ");
448
  outputnl(timestring(buff, &cntdata));
456
  outputnl(timestring(buff, &cntdata));
449
  nls_put(NLS_INFO_YESNO);
457
  nls_put(NLS_INFO_YESNO);
450
  sprintf(buff, " %c/%c", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
458
  sprintf(buff, " %c/%c", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
451
  outputnl(buff);
459
  outputnl(buff);
452
  nls_put(NLS_INFO_CURREXAMPLE);
460
  nls_put(NLS_INFO_CURREXAMPLE);
453
  output(" ");
461
  output(" ");
454
  outputnl(currencystring(buff, &cntdata));
462
  outputnl(currencystring(buff, &cntdata));
455
 
463
 
456
  crlf();
464
  crlf();
457
  nls_puts(NLS_MAKESURE);
465
  nls_puts(NLS_MAKESURE);
458
  sprintf(buff, "COUNTRY=%03d,%03d,", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage);
466
  sprintf(buff, "COUNTRY=%03d,%03d,", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage);
459
  output(buff);
467
  output(buff);
460
  outputnl(fname);
468
  outputnl(fname);
461
 
469
 
462
  /* if anything changed, write the new file */
470
  /* if anything changed, write the new file */
463
  if (changedflag != 0) country_write(fname, &cntdata);
471
  if (changedflag != 0) country_write(fname, &cntdata);
464
 
472
 
465
  return(0);
473
  return(0);
466
}
474
}
467
 
475