xref: /reactos/base/applications/calc/convert.c (revision 1734f297)
1 /*
2  * ReactOS Calc (Unit conversion engine)
3  *
4  * Copyright 2007-2017, Carlo Bramini
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "calc.h"
22 
23 /*
24     The conversion is made by converting the "from" unit
25     into the I.S. unit and then the I.S. unit is converted
26     into the "from" one.
27 
28     The base units for all categories are:
29 
30     ANGLE..........degrees
31     AREA...........square meters
32     CONSUMPTION....kilometers per liter
33     CURRENCY.......Euro
34     ENERGY.........joule
35     LENGTHS........meters
36     POWER..........Watt
37     PRESSURE.......Pascal
38     TEMPERATURE....kelvin
39     TIME...........seconds
40     VELOCITY.......meters per second
41     VOLUME.........liter
42     WEIGHT.........gram
43 
44     The '$' character is used as "what you read into the display".
45 */
46 typedef struct {
47     DWORD unit;
48     const char *formula_from;
49     const char *formula_to;
50 } conv_t;
51 
52 typedef struct {
53     const DWORD   category;
54     const conv_t *items;
55 } conv_category_t;
56 
57 #define DECLARE_CONV_CAT(_category) \
58     { IDS_CONV_##_category, conv_##_category },
59 
60 #define DECLARE_CONV_UNIT(_category, _unit, _from, _to ) \
61     { IDS_##_category##_##_unit, _from, _to },
62 
63 #define DECLARE_CONV_END \
64     { 0, NULL, NULL },
65 
66 /*
67     1 arcminute ....... = 1/60 deg
68     1 arcsecond ....... = 1/3600 deg
69     1 gradian ......... = 0.9 deg
70     1 radian .......... = 57.29577951308233 deg
71 */
72 static const conv_t conv_ANGLE[] = {
73     DECLARE_CONV_UNIT(ANGLE, ARCMINUTES, "$/60",    "$*60")
74     DECLARE_CONV_UNIT(ANGLE, ARCSECONDS, "$/3600",  "$*3600")
75     DECLARE_CONV_UNIT(ANGLE, DEGREES,    "$",       "$")
76     DECLARE_CONV_UNIT(ANGLE, GRADIANS,   "$*0.9",   "$/0.9")
77     DECLARE_CONV_UNIT(ANGLE, RADIANS,    "$/P*180", "$*P/180")
78     DECLARE_CONV_END
79 };
80 
81 /*
82     1 acre ................ = 4840 square yd = 4046,8564224 mq
83     1 acre brazil ......... =
84     1 acre france ......... =
85     1 acre scots .......... = 5000 mq
86     1 acre us ............. = 4840*(36/39.37)^2 m = 6272640/1549.9969 m
87     1 are ................. = 100 mq
88     1 chou ................ = 108000*(10/33)^2 mq
89     1 danbo ............... = 991.74 mq
90     1 ha .................. = 10000 mq
91     1 jeongbo ............. = 9917.4 mq
92     1 morgen hungary ...... = 5754.642 mq
93     1 mu .................. = 2000/3 mq
94     1 ping ................ =
95     1 pyeong .............. = 400/121 mq
96     1 pyeongbangja ........ =
97     1 rai ................. = 1600 mq
98     1 se .................. = 1080*(10/33)^2 mq
99     1 square cm ........... = 0.0001 mq
100     1 square chr .......... =
101     1 square fathom ....... = 1.8288^2 = 3.34450944 mq
102     1 square fathom hungary = 1.8964838^2 = 3.59665080366244 mq
103     1 square ft ........... = 0,09290304 mq
104     1 square in ........... = 0,00064516 mq
105     1 square km ........... = 1000000 mq
106     1 square lar .......... =
107     1 square mile ......... = 1609.344^2 = 2589988.110336 mq
108     1 square mm ........... = 0,000001 mq
109     1 square shaku ........ = (10/33)^2 mq
110     1 square tsuen ........ =
111     1 square va ........... = 4 mq
112     1 square yard ......... = 0,83612736 mq
113     1 tan ................. = 10800*(10/33)^2 mq
114     1 tsubo ............... = 36*(10/33)^2 mq
115 */
116 static const conv_t conv_AREA[] = {
117     DECLARE_CONV_UNIT(AREA, ACRES,                  "$*4046,8564224",    "$/4046,8564224")
118 //    DECLARE_CONV_UNIT(AREA, ACRES_BRAZIL,           "$", "$")
119 //    DECLARE_CONV_UNIT(AREA, ACRES_FRANCE,           "$", "$")
120     DECLARE_CONV_UNIT(AREA, ACRES_US,               "$*627264/154.99969", "$/627264*154.99969")
121     DECLARE_CONV_UNIT(AREA, ACRES_SCOTS,            "$*5000",            "$/5000")
122     DECLARE_CONV_UNIT(AREA, ARES,                   "$*100",             "$/100")
123     DECLARE_CONV_UNIT(AREA, CHOU,                   "$*10800000/1089",   "$*1089/10800000")
124     DECLARE_CONV_UNIT(AREA, DANBO,                  "$*991.74",          "$/991.74")
125     DECLARE_CONV_UNIT(AREA, HECTARES,               "$*10000",           "$/10000")
126     DECLARE_CONV_UNIT(AREA, JEONGBO,                "$*9917.4",          "$/9917.4")
127 //    DECLARE_CONV_UNIT(AREA, MORGEN_HUNGARY,         "$", "$")
128     DECLARE_CONV_UNIT(AREA, MU,                     "$*(2000/3)",        "$/(2000/3)")
129 //    DECLARE_CONV_UNIT(AREA, PING,                   "$", "$")
130     DECLARE_CONV_UNIT(AREA, PYEONG,                 "$*400/121",         "$*121/400")
131 //    DECLARE_CONV_UNIT(AREA, PYEONGBANGJA,           "$", "$")
132     DECLARE_CONV_UNIT(AREA, RAI,                    "$*1600",            "$/1600")
133     DECLARE_CONV_UNIT(AREA, SE,                     "$*108000/1089",     "$*1089/108000")
134     DECLARE_CONV_UNIT(AREA, SQUARE_CENTIMETERS,     "$*0,0001",          "$/0,0001")
135 //    DECLARE_CONV_UNIT(AREA, SQUARE_CHR,             "$", "$")
136     DECLARE_CONV_UNIT(AREA, SQUARE_FATHOMS,         "$*3.34450944",      "$/3.34450944")
137     DECLARE_CONV_UNIT(AREA, SQUARE_FATHOMS_HUNGARY, "$*3.59665080366244", "$/3.59665080366244")
138     DECLARE_CONV_UNIT(AREA, SQUARE_FEET,            "$*0,09290304",      "$/0,09290304")
139     DECLARE_CONV_UNIT(AREA, SQUARE_INCHES,          "$*0,00064516",      "$/0.00064516")
140     DECLARE_CONV_UNIT(AREA, SQUARE_KILOMETERS,      "$*1000000",         "$/1000000")
141 //    DECLARE_CONV_UNIT(AREA, SQUARE_LAR,             "$", "$")
142     DECLARE_CONV_UNIT(AREA, SQUARE_METER,           "$",                 "$")
143     DECLARE_CONV_UNIT(AREA, SQUARE_MILES,           "$*2589988.110336",  "$/2589988.110336")
144     DECLARE_CONV_UNIT(AREA, SQUARE_MILLIMETERS,     "$*1000000",         "$/1000000")
145     DECLARE_CONV_UNIT(AREA, SQUARE_SHAKU,           "$*100/1089",        "$/1089*100")
146 //    DECLARE_CONV_UNIT(AREA, SQUARE_TSUEN,           "$", "$")
147     DECLARE_CONV_UNIT(AREA, SQUARE_VA,              "$*4",               "$/4")
148     DECLARE_CONV_UNIT(AREA, SQUARE_YARD,            "$*0,83612736",      "$/0,83612736")
149     DECLARE_CONV_UNIT(AREA, TAN,                    "$*1080000/1089",    "$*1089/1080000")
150     DECLARE_CONV_UNIT(AREA, TSUBO,                  "$*1188/1089",       "$*1089/1188")
151     DECLARE_CONV_END
152 };
153 
154 /*
155     1 l/100Km = 100 km/l -> y = 100/x
156     1 miles/gal uk = 1.609344/4.54609 km/l
157     1 miles/gal us = 1.609344/3.785411784 km/l
158 */
159 static const conv_t conv_CONSUMPTION[] = {
160     DECLARE_CONV_UNIT(CONSUMPTION, KM_PER_L,        "$", "$")
161     DECLARE_CONV_UNIT(CONSUMPTION, L_PER_100_KM,    "100/$", "100/$")
162     DECLARE_CONV_UNIT(CONSUMPTION, MILES_GALLON_UK, "$*1.609344/4.54609", "$/1.609344*4.54609")
163     DECLARE_CONV_UNIT(CONSUMPTION, MILES_GALLON_US, "$*1.609344/3.785411784", "$/1.609344*3.785411784")
164     DECLARE_CONV_END
165 };
166 
167 static const conv_t conv_CURRENCY[] = {
168     DECLARE_CONV_UNIT(CURRENCY, AUSTRIAN_SCHILLING, "$/13,7603", "$*13,7603")
169     DECLARE_CONV_UNIT(CURRENCY, BELGIAN_FRANC,      "$/40,3399", "$*40,3399")
170     DECLARE_CONV_UNIT(CURRENCY, CYPRIOT_POUND,      "$/0,585274","$*0,585274")
171     DECLARE_CONV_UNIT(CURRENCY, DEUTSCHE_MARK,      "$/1,95583", "$*1,95583")
172     DECLARE_CONV_UNIT(CURRENCY, DUTCH_GUILDER,      "$/2,20371", "$*2,20371")
173     DECLARE_CONV_UNIT(CURRENCY, ESTONIAN_KROON,     "$/15,6466", "$*15,6466")
174     DECLARE_CONV_UNIT(CURRENCY, EURO,               "$",         "$")
175     DECLARE_CONV_UNIT(CURRENCY, FINNISH_MARKKA,     "$/5,94573", "$*5,94573")
176     DECLARE_CONV_UNIT(CURRENCY, FRENCH_FRANC,       "$/6,55957", "$*6,55957")
177     DECLARE_CONV_UNIT(CURRENCY, GREEK_DRACHMA,      "$/340,751", "$*340,751")
178     DECLARE_CONV_UNIT(CURRENCY, IRISH_POUND,        "$/0,787564","$*0,787564")
179     DECLARE_CONV_UNIT(CURRENCY, ITALIAN_LIRA,       "$/1936.27", "$*1936.27")
180     DECLARE_CONV_UNIT(CURRENCY, LATVIAN_LATS,       "$/0,7028",  "$*0,7028")
181     DECLARE_CONV_UNIT(CURRENCY, LITHUANIAN_LITAS,   "$/3,45280", "$*3,45280")
182     DECLARE_CONV_UNIT(CURRENCY, LUXEMBOURG_FRANC,   "$/40,3399", "$*40,3399")
183     DECLARE_CONV_UNIT(CURRENCY, MALTESE_LIRA,       "$/0.42930", "$*0.42930")
184     DECLARE_CONV_UNIT(CURRENCY, PORTOGUESE_ESCUDO,  "$/200,482", "$*200,482")
185     DECLARE_CONV_UNIT(CURRENCY, SLOVAK_KORUNA,      "$/30,126",  "$*30,126")
186     DECLARE_CONV_UNIT(CURRENCY, SLOVENIAN_TOLAR,    "$/239,640", "$*239,640")
187     DECLARE_CONV_UNIT(CURRENCY, SPANISH_PESETA,     "$/166,386", "$*166,386")
188     DECLARE_CONV_END
189 };
190 
191 /*
192     1 cal15 .... = 4.1855 J
193     1 BTU ...... = 1055.056 J
194     1 ERG ...... = 0.0000001 J
195     1 eV ....... = 0.000000000000000000160217653 J
196     1 Foot-Pound = 1.3558179483314004 J
197     1 IT calorie = 4.1868 J
198     1 KCa ...... = 4186.8 J
199     1 KJ ....... = 1000 J
200     1 KWh ...... = 3600 J
201     1 IUNS ..... = 4.182 J
202     1 calth .... = 4.184 J
203 */
204 static const conv_t conv_ENERGY[] = {
205     DECLARE_CONV_UNIT(ENERGY, 15_C_CALORIES,        "$*4.1855",   "$/4.1855")
206     DECLARE_CONV_UNIT(ENERGY, BTUS,                 "$*1055.056", "$/1055.056")
207     DECLARE_CONV_UNIT(ENERGY, ERGS,                 "$*.0000001", "$/.0000001")
208     DECLARE_CONV_UNIT(ENERGY, EVS,                  "$*1.60217653/1X19", "$/1.60217653*1X19")
209     DECLARE_CONV_UNIT(ENERGY, FOOT_POUNDS,          "$*1.3558179483314004",   "$/1.3558179483314004")
210     DECLARE_CONV_UNIT(ENERGY, IT_CALORIES,          "$*4.1868",   "$/4.1868")
211     DECLARE_CONV_UNIT(ENERGY, IT_KILOCALORIES,      "$*4186.8",   "$/4186.8")
212     DECLARE_CONV_UNIT(ENERGY, JOULES,               "$",          "$")
213     DECLARE_CONV_UNIT(ENERGY, KILOJOULES,           "$*1000",     "$/1000")
214     DECLARE_CONV_UNIT(ENERGY, KILOWATT_HOURS,       "$*3600",     "$/3600")
215     DECLARE_CONV_UNIT(ENERGY, NUTRITION_CALORIES,   "$*4.182",    "$/4.182")
216     DECLARE_CONV_UNIT(ENERGY, TH_CALORIES,          "$*4.184",    "$/4.184")
217     DECLARE_CONV_END
218 };
219 
220 /*
221     1 angstrom ....... = 0.0000000001 m
222     1 astronomical unit= 149598000000 m
223     1 barleycorn ..... = 1/3 inch = 0.9144/108 m
224     1 cm ............. = 1/100 m
225     1 chain uk ....... = 22 yards = 22*0.9144 m
226     1 chi ............ = 1/3 m
227     1 chou ........... = 3600/33 m
228     1 chr ............ =
229     1 cun ............ = 1/10 chi = 1/30 m
230     1 fathom ......... = 2 yard = 2*0.9144 m
231     1 fathom ungary .. = 1.8964838 m (fixed)
232     1 feet ........... = 12 inch = 0.9144/3 m
233     1 furlong ........ = 10 chains = 220*0.9144 m
234     1 gan ............ =
235     1 hand ........... = 4 inches = 0.9144/9 m
236     1 hunh ........... = 1/8 nieu = 9.144/3456 m
237     1 inch ........... = yard/36 = 0.9144/36 m
238     1 ja ............. =
239     1 jeong .......... =
240     1 kabiet ......... = 1/4 nieu = 9.144/1728 m
241     1 ken ............ = 60/33 m
242     1 keub ........... = 12 nieu = 10 inch = 9.144/36 m
243     1 km ............. = 1000 m
244     1 lar ............ =
245     1 light year ..... = 9460730472580800 m
246     1 link uk ........ = 0.01 chains = 0.22*0.9144 m
247     1 micron ......... = 0.000001 m
248     1 mile ........... = 1760 yards = 1609.344 m
249     1 millimeter ..... = 1/1000 m
250     1 nautical mile .. = 1852 m
251     1 nieu ........... = 10/12 inch = 9.144/432 m
252     1 parsec ......... = 30856800000000000 m
253     1 pica ........... = yard/216 = 0.9144/216 m
254     1 ri japan ....... = 129600/33 m
255     1 ri korea ....... = 12960/33 m
256     1 rod ............ = 5.0292 m
257     1 sawk ........... = 2 keub = 20 inch = 9.144/18 m
258     1 sen ............ = 20 va = 40.64 m
259     1 shaku .......... = 10/33 m
260     1 span ........... = 9 inches = 0.9144/4 m
261     1 sun ............ = 1/33 m
262     1 tsuen .......... =
263     1 va ............. = 4 sawk = 80 inch = 2.032 m
264     1 yard ........... = 0.9144 m
265     1 yote ........... = 400 sen = 16256 m
266     1 zhang .......... = 3+1/3 m = 10/3 m
267 */
268 static const conv_t conv_LENGTH[] = {
269     DECLARE_CONV_UNIT(LENGTH, ANGSTROMS,            "$/1X10",           "$*1X10")
270     DECLARE_CONV_UNIT(LENGTH, ASTRONOMICAL_UNITS,   "$*149598000000",   "$/149598000000")
271     DECLARE_CONV_UNIT(LENGTH, BARLEYCORNS,          "$*0.9144/108",     "$/0.9144*108")
272     DECLARE_CONV_UNIT(LENGTH, CENTIMETERS,          "$/100",            "$*100")
273     DECLARE_CONV_UNIT(LENGTH, CHAINS_UK,            "$*20.1168",        "$/20.1168")
274     DECLARE_CONV_UNIT(LENGTH, CHI,                  "$/3",              "$*3")
275     DECLARE_CONV_UNIT(LENGTH, CHOU,                 "$*3600/33",        "$*33/3600")
276 //    DECLARE_CONV_UNIT(LENGTH, CHR,                  "$", "$")
277     DECLARE_CONV_UNIT(LENGTH, CUN,                  "$/30",             "$*30")
278     DECLARE_CONV_UNIT(LENGTH, FATHOMS,              "$*1.8288",         "$/1.8288")
279     DECLARE_CONV_UNIT(LENGTH, FATHOMS_HUNGARY,      "$*1.8964838",      "$/1.8964838")
280     DECLARE_CONV_UNIT(LENGTH, FEET,                 "$*0.3048",         "$/0.3048")
281     DECLARE_CONV_UNIT(LENGTH, FURLONGS,             "$*201.168",        "$/201.168")
282 //    DECLARE_CONV_UNIT(LENGTH, GAN,                  "$", "$")
283     DECLARE_CONV_UNIT(LENGTH, HANDS,                "$*0,1016",         "$/0,1016")
284     DECLARE_CONV_UNIT(LENGTH, HUNH,                 "$*9.144/3456",     "$/9.144*3456")
285     DECLARE_CONV_UNIT(LENGTH, INCHES,               "$*0.0254",         "$/0.0254")
286 //    DECLARE_CONV_UNIT(LENGTH, JA,                   "$", "$")
287 //    DECLARE_CONV_UNIT(LENGTH, JEONG,                "$", "$")
288     DECLARE_CONV_UNIT(LENGTH, KABIET,               "$*9.144/1728",     "$/9.144*1728")
289     DECLARE_CONV_UNIT(LENGTH, KEN,                  "$*60/33",          "$*33/60")
290     DECLARE_CONV_UNIT(LENGTH, KEUB,                 "$*9.144/36",       "$/9.144*36")
291     DECLARE_CONV_UNIT(LENGTH, KILOMETERS,           "$*1000",           "$/1000")
292 //    DECLARE_CONV_UNIT(LENGTH, LAR,                  "$", "$")
293     DECLARE_CONV_UNIT(LENGTH, LIGHT_YEARS,          "$*9460730472580800", "$/9460730472580800")
294     DECLARE_CONV_UNIT(LENGTH, LINKS_UK,             "$*0.201168",       "$/0.201168")
295     DECLARE_CONV_UNIT(LENGTH, METERS,               "$",                "$")
296     DECLARE_CONV_UNIT(LENGTH, MICRONS,              "$*0.000001",       "$/0.000001")
297     DECLARE_CONV_UNIT(LENGTH, MILES,                "$*1609.344",       "$/1609.344")
298     DECLARE_CONV_UNIT(LENGTH, MILLIMETERS,          "$/1000",           "$*1000")
299     DECLARE_CONV_UNIT(LENGTH, NAUTICAL_MILES,       "$*1852",           "$/1852")
300     DECLARE_CONV_UNIT(LENGTH, NIEU,                 "$*9.144/432",      "$/9.144*432")
301     DECLARE_CONV_UNIT(LENGTH, PARSECS,              "$*3.085678X16",    "$/3.085678X16")
302     DECLARE_CONV_UNIT(LENGTH, PICAS,                "$*0.9144/216",     "$/0.9144*216")
303     DECLARE_CONV_UNIT(LENGTH, RODS,                 "$*5.0292",         "$/5.0292")
304     DECLARE_CONV_UNIT(LENGTH, RI_JAPAN,             "$*129600/33",      "$*33/129600")
305     DECLARE_CONV_UNIT(LENGTH, RI_KOREA,             "$*12960/33",       "$*33/12960")
306     DECLARE_CONV_UNIT(LENGTH, SAWK,                 "$*9.144/18",       "$/9.144*18")
307     DECLARE_CONV_UNIT(LENGTH, SEN,                  "$*40.64",          "$/40.64")
308     DECLARE_CONV_UNIT(LENGTH, SHAKU,                "$*10/33",          "$*33/10")
309     DECLARE_CONV_UNIT(LENGTH, SPAN,                 "$*0.9144/4",       "$*4/0.9144")
310     DECLARE_CONV_UNIT(LENGTH, SUN,                  "$*1/33",            "$*33")
311 //    DECLARE_CONV_UNIT(LENGTH, TSUEN,                "$", "$")
312     DECLARE_CONV_UNIT(LENGTH, VA,                   "$*2.032",          "$/2.032")
313     DECLARE_CONV_UNIT(LENGTH, YARDS,                "$*0.9144",         "$/0.9144")
314     DECLARE_CONV_UNIT(LENGTH, YOTE,                 "$*16256",          "$/16256")
315     DECLARE_CONV_UNIT(LENGTH, ZHANG,                "$/0.3",            "$*0.3")
316     DECLARE_CONV_END
317 };
318 
319 /*
320     1 BTU/min = 17.5842642 W
321     1 Foot-pound/minute = 0.02259696580552333 W
322     1 hp = 745.69987158227022 W
323     1 KW = 1000 W
324     1 MW = 1000000 W
325 */
326 static const conv_t conv_POWER[] = {
327     DECLARE_CONV_UNIT(POWER, BTUS_PER_MINUTE, "$*17.5842642", "$/17.5842642")
328     DECLARE_CONV_UNIT(POWER, FPS_PER_MINUTE,  "$*0.02259696580552333", "$/0.02259696580552333")
329     DECLARE_CONV_UNIT(POWER, HORSEPOWER,      "$*745.69987158227022", "$/745.69987158227022")
330     DECLARE_CONV_UNIT(POWER, KILOWATTS,       "$*1000", "$/1000")
331     DECLARE_CONV_UNIT(POWER, MEGAWATTS,       "$*1000000", "$/1000000")
332     DECLARE_CONV_UNIT(POWER, WATTS,           "$", "$")
333     DECLARE_CONV_END
334 };
335 
336 /*
337     1 ATM   = 101325 Pa
338     1 BAR   = 100000 Pa
339     1 hPa   = 100 Pa
340     1 kPa   = 1000 Pa
341     1 mm HG = 133.322 Pa
342     1 psi   = 6894.757 Pa
343 */
344 static const conv_t conv_PRESSURE[] = {
345     DECLARE_CONV_UNIT(PRESSURE, ATMOSPHERES,   "$*101325",   "$/101325")
346     DECLARE_CONV_UNIT(PRESSURE, BARS,          "$*100000",   "$/100000")
347     DECLARE_CONV_UNIT(PRESSURE, HECTOPASCALS,  "$*100",      "$/100")
348     DECLARE_CONV_UNIT(PRESSURE, KILOPASCALS,   "$*1000",     "$/1000")
349     DECLARE_CONV_UNIT(PRESSURE, MM_OF_MERCURY, "$*133.322",  "$/133.322")
350     DECLARE_CONV_UNIT(PRESSURE, PASCALS,       "$",          "$")
351     DECLARE_CONV_UNIT(PRESSURE, PSI,           "$*6894.757", "$/6894.757")
352     DECLARE_CONV_END
353 };
354 
355 /*
356     1 day ....... = 86400 s
357     1 hour ...... = 3600 s
358     1 microsecond = 0.000001 s
359     1 millisecond = 0.001 s
360     1 nanosecond. = 0.000000001 s
361     1 minute .... = 60 s
362     1 week ...... = 669600 s
363 */
364 static const conv_t conv_TIME[] = {
365     DECLARE_CONV_UNIT(TIME, MINUTES,      "$*60",          "$/60")
366     DECLARE_CONV_UNIT(TIME, DAYS,         "$*86400",       "$/86400")
367     DECLARE_CONV_UNIT(TIME, HOURS,        "$*3600",        "$/3600")
368     DECLARE_CONV_UNIT(TIME, MILLISECONDS, "$*0.001",       "$/0.001")
369     DECLARE_CONV_UNIT(TIME, MICROSECONDS, "$*0.000001",    "$/0.000001")
370     DECLARE_CONV_UNIT(TIME, NANOSECONDS,  "$*0.000000001", "$/0.000000001")
371     DECLARE_CONV_UNIT(TIME, SECONDS,      "$",             "$")
372     DECLARE_CONV_UNIT(TIME, WEEKS,        "$*604800",      "$/604800")
373     DECLARE_CONV_UNIT(TIME, YEARS,        "$*31556952",    "$/31556952")
374     DECLARE_CONV_END
375 };
376 
377 /*
378     C = K - 273.15
379     F = K * 9/5 - 459.67
380     R = K * 9/5
381  */
382 static const conv_t conv_TEMPERATURE[] = {
383     DECLARE_CONV_UNIT(TEMPERATURE, CELSIUS,     "$+273.15",       "$-273.15")
384     DECLARE_CONV_UNIT(TEMPERATURE, FAHRENHEIT,  "($+459.67)*5/9", "$*9/5-459.67")
385     DECLARE_CONV_UNIT(TEMPERATURE, KELVIN,      "$",              "$")
386     DECLARE_CONV_UNIT(TEMPERATURE, RANKINE,     "$*5/9",          "$*9/5")
387     DECLARE_CONV_END
388 };
389 
390 /*
391     1 cm/s = 0.01 m/s
392     1 f/h  = 0.0000846666667 m/s
393     1 f/s  = 0.3048 m/s
394     1 Km/h = 10/36 m/s -> 0.27778 m/s
395     1 knot = 18.52/36 m/s -> 0.51444444 m/s
396     1 mach = 340.3 m/s
397     1 mph  = 0.44704 m/s
398 */
399 static const conv_t conv_VELOCITY[] = {
400     DECLARE_CONV_UNIT(VELOCITY, CMS_SECOND,         "$*.01",      "$/.01")
401     DECLARE_CONV_UNIT(VELOCITY, FEET_SECOND,        "$*.3048",    "$/.3048")
402     DECLARE_CONV_UNIT(VELOCITY, FEET_HOUR,          "$*.0000846666667", "$/.0000846666667")
403     DECLARE_CONV_UNIT(VELOCITY, KILOMETERS_HOUR,    "$*10/36",    "$*36/10")
404     DECLARE_CONV_UNIT(VELOCITY, KNOTS,              "$*18.52/36", "$*36/18.52")
405     DECLARE_CONV_UNIT(VELOCITY, MACH,               "$*340.3",    "$/340.3")
406     DECLARE_CONV_UNIT(VELOCITY, METERS_SECOND,      "$",          "$")
407     DECLARE_CONV_UNIT(VELOCITY, MILES_HOUR,         "$*.44704",   "$/.44704")
408     DECLARE_CONV_END
409 };
410 
411 /*
412     1 barrel uk ...... = 163.65924 l
413     1 barrel oil ..... = 158.987295 l
414     1 bun ............ = 1000 l
415     1 bushel uk ...... = 36.36872 l
416     1 bushel us ...... = 35.23907017 l
417     1 cubic cm  ...... = 0.001 l
418     1 cubic feet ..... = 28.316846 l
419     1 cubic inch ..... = 0.016387064 l
420     1 cubic meter .... = 1000 l
421     1 cubic yard ..... = 764.554857 l
422     1 doe ............ =
423     1 fluid ounce uk   = 0.0284130625 l
424     1 fluid ounce us   = 0.0295735295625 l
425     1 gallon uk ...... = 4.54609 l
426     1 gallon dry us .. = 4.40488377086 l
427     1 gallon liquid us = 3.785411784 l
428     1 gou ............ = 0.1809 l
429     1 hop ............ =
430     1 icce ........... =
431     1 kwian .......... = 2000 l
432     1 mal ............ =
433     1 milliliter ..... = 0.001 l
434     1 pint uk ........ = 0.56826125 l
435     1 pint dry us .... = 0.5506104713575 l
436     1 pint liquid us   = 0.473176473 l
437     1 quart uk ....... = 1.1365225 l
438     1 quart dry us ... = 1.101220942715 l
439     1 quart liquid us  = 0.946352946 l
440     1 seki ........... =
441     1 syou ........... =
442     1 tananloung ..... = 1 l
443     1 tang ........... = 20 l
444     1 to ............. = 18040 l
445 */
446 static const conv_t conv_VOLUME[] = {
447     DECLARE_CONV_UNIT(VOLUME, BARRELS_UK,           "$*163.65924",       "$/163.65924")
448     DECLARE_CONV_UNIT(VOLUME, BARRELS_OIL,          "$*158.987295",      "$/158.987295")
449     DECLARE_CONV_UNIT(VOLUME, BUN,                  "$*1000",            "$/1000")
450     DECLARE_CONV_UNIT(VOLUME, BUSHELS_UK,           "$*36.36872",        "$/36.36872")
451     DECLARE_CONV_UNIT(VOLUME, BUSHELS_US,           "$*35.23907017",     "$/35.23907017")
452     DECLARE_CONV_UNIT(VOLUME, CUBIC_CENTIMETERS,    "$*0.001",           "$/0.001")
453     DECLARE_CONV_UNIT(VOLUME, CUBIC_FEET,           "$*28.316846",       "$/28.316846")
454     DECLARE_CONV_UNIT(VOLUME, CUBIC_INCHES,         "$*0.016387064",     "$/0.016387064")
455     DECLARE_CONV_UNIT(VOLUME, CUBIC_METERS,         "$*1000",            "$/1000")
456     DECLARE_CONV_UNIT(VOLUME, CUBIC_YARDS,          "$*764.554857",      "$/764.554857")
457 //    DECLARE_CONV_UNIT(VOLUME, DOE,                  "$", "$")
458     DECLARE_CONV_UNIT(VOLUME, FLUID_OUNCES_UK,      "$*0.0284130625",    "$/0.0284130625")
459     DECLARE_CONV_UNIT(VOLUME, FLUID_OUNCES_US,      "$*0.0295735295625", "$/0.0295735295625")
460     DECLARE_CONV_UNIT(VOLUME, GALLONS_UK,           "$*4.54609",         "$/4.54609")
461     DECLARE_CONV_UNIT(VOLUME, GALLONS_DRY_US,       "$*4.40488377086",   "$/4.40488377086")
462     DECLARE_CONV_UNIT(VOLUME, GALLONS_LIQUID_US,    "$*3.785411784",     "$/3.785411784")
463     DECLARE_CONV_UNIT(VOLUME, GOU,                  "$*0.1809",          "$/0.1809")
464 //    DECLARE_CONV_UNIT(VOLUME, HOP,                  "$", "$")
465 //    DECLARE_CONV_UNIT(VOLUME, ICCE,                 "$", "$")
466     DECLARE_CONV_UNIT(VOLUME, KWIAN,                "$*2000",            "$/2000")
467     DECLARE_CONV_UNIT(VOLUME, LITERS,               "$",                 "$")
468 //    DECLARE_CONV_UNIT(VOLUME, MAL,                  "$", "$")
469     DECLARE_CONV_UNIT(VOLUME, MILLILITERS,          "$*0.001",           "$/0.001")
470     DECLARE_CONV_UNIT(VOLUME, PINTS_UK,             "$*0.56826125",      "$/0.56826125")
471     DECLARE_CONV_UNIT(VOLUME, PINTS_DRY_US,         "$*0.5506104713575", "$/0.5506104713575")
472     DECLARE_CONV_UNIT(VOLUME, PINTS_LIQUID_US,      "$*0.473176473",     "$/0.473176473")
473     DECLARE_CONV_UNIT(VOLUME, QUARTS_UK,            "$*1.1365225",       "$/1.1365225")
474     DECLARE_CONV_UNIT(VOLUME, QUARTS_DRY_US,        "$*1.101220942715",  "$/1.101220942715")
475     DECLARE_CONV_UNIT(VOLUME, QUARTS_LIQUID_US,     "$*0.946352946",     "$/0.946352946")
476 //    DECLARE_CONV_UNIT(VOLUME, SEKI,                 "$", "$")
477 //    DECLARE_CONV_UNIT(VOLUME, SYOU,                 "$", "$")
478     DECLARE_CONV_UNIT(VOLUME, TANANLOUNG,           "$",                 "$")
479     DECLARE_CONV_UNIT(VOLUME, TANG,                 "$*20",              "$/20")
480     DECLARE_CONV_UNIT(VOLUME, TO,                   "$*18040",           "$/18040")
481     DECLARE_CONV_END
482 };
483 
484 /*
485     1 baht ............ = 12.244 g
486     1 carat ........... = 0.2 g
487     1 chung ........... =
488     1 don ............. =
489     1 geun ............ =
490     1 gwan ............ =
491     1 harb ............ =
492     1 jin china ....... =
493     1 jin taiwan ...... =
494     1 Kan ............. = 3750 g
495     1 Kilograms ....... = 1000 g
496     1 Kin ............. = 600 g
497     1 Liang China ..... =
498     1 Liang Taiwan .... =
499     1 monme ........... = 3.75 g
500     1 ounce avoirdupois = 28.349523125 g
501     1 ounce troy ...... = 31.1034768 g
502     1 pound ........... = 453.59237 g
503     1 quintal metric .. = 100000 g
504     1 saloung ......... =
505     1 stone ........... = 6350.29318 g
506     1 tamlung ......... =
507     1 ton ............. = 1000000 g
508     1 ton uk .......... = 1016046.9088 g  // long ton
509     1 ton us .......... = 907184.74 g     // short ton
510 */
511 /*
512 1 chang = 20 tamlung
513 1 tamlung = 4 baht
514 1 baht = 4 saloung
515 1 saloung =
516 
517 1 chang = 6/5 kg = 1200 g
518 1 tamlung = 1/20 chang = 60 g
519 1 baht = 1/4 tamlung = 15 g
520 1 saloung = 1/4 bath = 15/4 g
521 */
522 static const conv_t conv_WEIGHT[] = {
523     DECLARE_CONV_UNIT(WEIGHT, BAHT,                 "$*12.244",       "$/12.244")
524     DECLARE_CONV_UNIT(WEIGHT, CARATS,               "$*0.2",          "$/0.2")
525 //    DECLARE_CONV_UNIT(WEIGHT, CHUNG,                "$", "$")
526 //    DECLARE_CONV_UNIT(WEIGHT, DON,                  "$", "$")
527 //    DECLARE_CONV_UNIT(WEIGHT, GEUN,                 "$", "$")
528     DECLARE_CONV_UNIT(WEIGHT, GRAMS,                "$",              "$")
529 //    DECLARE_CONV_UNIT(WEIGHT, GWAN,                 "$", "$")
530 //    DECLARE_CONV_UNIT(WEIGHT, HARB,                 "$", "$")
531 //    DECLARE_CONV_UNIT(WEIGHT, JIN_CHINA,            "$", "$")
532 //    DECLARE_CONV_UNIT(WEIGHT, JIN_TAIWAN,           "$", "$")
533     DECLARE_CONV_UNIT(WEIGHT, KAN,                  "$*3750",         "$/3750")
534     DECLARE_CONV_UNIT(WEIGHT, KILOGRAMS,            "$*1000",         "$/1000")
535     DECLARE_CONV_UNIT(WEIGHT, KIN,                  "$*600",          "$/600")
536 //    DECLARE_CONV_UNIT(WEIGHT, LIANG_CHINA,          "$", "$")
537 //    DECLARE_CONV_UNIT(WEIGHT, LIANG_TAIWAN,         "$", "$")
538     DECLARE_CONV_UNIT(WEIGHT, MONME,                "$*3.75",         "$/3.75")
539     DECLARE_CONV_UNIT(WEIGHT, OUNCES_AVOIRDUPOIS,   "$*28.349523125", "$/28.349523125")
540     DECLARE_CONV_UNIT(WEIGHT, OUNCES_TROY,          "$*31.1034768",   "$/31.1034768")
541     DECLARE_CONV_UNIT(WEIGHT, POUNDS,               "$*453.59237",    "$/453.59237")
542     DECLARE_CONV_UNIT(WEIGHT, QUINTAL_METRIC,       "$*100000",       "$/100000")
543 //    DECLARE_CONV_UNIT(WEIGHT, SALOUNG,              "$", "$")
544     DECLARE_CONV_UNIT(WEIGHT, STONES,               "$*6350.29318",    "$/6350.29318")
545 //    DECLARE_CONV_UNIT(WEIGHT, TAMLUNG,              "$", "$")
546     DECLARE_CONV_UNIT(WEIGHT, TONNES,               "$*1000000",       "$/1000000")
547     DECLARE_CONV_UNIT(WEIGHT, TONS_UK,              "$*1016046.9088",  "$/1016046.9088")
548     DECLARE_CONV_UNIT(WEIGHT, TONS_US,              "$*907184.74",     "$/907184.74")
549     DECLARE_CONV_END
550 };
551 
552 static const conv_category_t conv_table[] = {
553     DECLARE_CONV_CAT(ANGLE)
554     DECLARE_CONV_CAT(AREA)
555     DECLARE_CONV_CAT(CONSUMPTION)
556     DECLARE_CONV_CAT(CURRENCY)
557     DECLARE_CONV_CAT(ENERGY)
558     DECLARE_CONV_CAT(LENGTH)
559     DECLARE_CONV_CAT(POWER)
560     DECLARE_CONV_CAT(PRESSURE)
561     DECLARE_CONV_CAT(TIME)
562     DECLARE_CONV_CAT(TEMPERATURE)
563     DECLARE_CONV_CAT(VELOCITY)
564     DECLARE_CONV_CAT(VOLUME)
565     DECLARE_CONV_CAT(WEIGHT)
566 };
567 
568 void ConvExecute(HWND hWnd)
569 {
570     DWORD         c_cat = (DWORD)SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETCURSEL, 0, 0);
571     const conv_t *items = NULL;
572     DWORD         from  = SendDlgItemMessage(hWnd, IDC_COMBO_FROM, CB_GETCURSEL, 0, 0);
573     DWORD         to    = SendDlgItemMessage(hWnd, IDC_COMBO_TO,   CB_GETCURSEL, 0, 0);
574     TCHAR         txt_cb[128];
575     TCHAR         txt[128];
576     const conv_t *item;
577 
578     /* do nothing if the indexes point to the same unit */
579     if (from == to)
580         return;
581 
582     /* Search correct category, since it can be sorted too */
583     SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETLBTEXT, c_cat, (LPARAM)txt_cb);
584     for (c_cat=0; c_cat < SIZEOF(conv_table); c_cat++) {
585         LoadString(calc.hInstance, conv_table[c_cat].category, txt, SIZEOF(txt));
586         if (!_tcscmp(txt_cb, txt)) {
587             items = conv_table[c_cat].items;
588             break;
589         }
590     }
591 
592     /* The units can be sorted, so I must search the exact match */
593     item = items;
594     SendDlgItemMessage(hWnd, IDC_COMBO_FROM, CB_GETLBTEXT, from, (LPARAM)txt_cb);
595     while (item->unit) {
596         LoadString(calc.hInstance, item->unit, txt, SIZEOF(txt));
597         if (!_tcscmp(txt_cb, txt)) {
598             from = item-items;
599             break;
600         }
601         item++;
602     }
603     SendDlgItemMessage(hWnd, IDC_COMBO_TO, CB_GETLBTEXT, to, (LPARAM)txt_cb);
604     item = items;
605     while (item->unit) {
606         LoadString(calc.hInstance, item->unit, txt, SIZEOF(txt));
607         if (!_tcscmp(txt_cb, txt)) {
608             to = item-items;
609             break;
610         }
611         item++;
612     }
613 
614     calc.Convert[0].data = (char *)items[from].formula_from;
615     calc.Convert[1].data = (char *)items[to].formula_to;
616     calc.Convert[0].wm_msg = WM_HANDLE_FROM;
617     calc.Convert[1].wm_msg = WM_HANDLE_TO;
618     PostMessage(hWnd, WM_START_CONV, 0, MAKELPARAM(0, WM_HANDLE_FROM));
619 }
620 
621 void ConvAdjust(HWND hWnd, int n_cat)
622 {
623     TCHAR         txt[128];
624     TCHAR         txt_cat[128];
625     HWND          hFromWnd = GetDlgItem(hWnd, IDC_COMBO_FROM);
626     HWND          hToWnd   = GetDlgItem(hWnd, IDC_COMBO_TO);
627     const conv_t *item;
628     unsigned int  n;
629 
630     SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETLBTEXT, n_cat, (LPARAM)txt_cat);
631     for (n=0; n<SIZEOF(conv_table); n++) {
632         item = conv_table[n].items;
633         LoadString(calc.hInstance, conv_table[n].category, txt, SIZEOF(txt));
634         if (!_tcscmp(txt_cat, txt))
635             break;
636     }
637 
638     SendMessage(hFromWnd, CB_RESETCONTENT, 0, 0);
639     SendMessage(hToWnd,   CB_RESETCONTENT, 0, 0);
640     while (item->unit) {
641         LoadString(calc.hInstance, item->unit, txt, SIZEOF(txt));
642         SendMessage(hFromWnd, CB_ADDSTRING, 0, (LPARAM)txt);
643         SendMessage(hToWnd,   CB_ADDSTRING, 0, (LPARAM)txt);
644         item++;
645     }
646     SendMessage(hFromWnd, CB_SETCURSEL, 0, 0);
647     SendMessage(hToWnd,   CB_SETCURSEL, 0, 0);
648 }
649 
650 void ConvInit(HWND hWnd)
651 {
652     HWND         hCatWnd = GetDlgItem(hWnd, IDC_COMBO_CATEGORY);
653     TCHAR        txt[128];
654     unsigned int n;
655 
656     /* Fill category combo */
657     for (n=0; n<SIZEOF(conv_table); n++) {
658         LoadString(calc.hInstance, conv_table[n].category, txt, SIZEOF(txt));
659         SendMessage(hCatWnd, CB_ADDSTRING, 0, (LPARAM)txt);
660     }
661     SendMessage(hCatWnd, CB_SETCURSEL, 0, 0);
662     ConvAdjust(hWnd, 0);
663 }
664 
665