1 unit common;
2
3 {
4 Copyright (C) 2005-2008 Olaf Klein, o.b.klein@gpsbabel.org
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program 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
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
19 }
20
21 interface
22
23 uses
24 Windows, SysUtils, Classes, Messages, Controls, StdCtrls, ExtCtrls;
25
26 const
27 OTypes: array[0..6] of PChar =
28 ('unknown', 'integer', 'float', 'string', 'boolean', 'file', 'outfile');
29
30 gpsbabel_knows_inifile: Boolean = False;
31 //gpsbabel_ini: TInifile = nil;
32 gpsbabel_knows_swap_filter: Boolean = False;
33
34 resourcestring
35 SGPSBabelURL = 'http://www.gpsbabel.org';
36 SGPSBabelTitle = 'GPSBabelGUI-2';
37
38 const
39 SGPSBabelIniFilename = 'gpsbabel.ini';
40 SGPSBabelExeFilename = 'gpsbabel.exe';
41
42 var
43 gpsbabel_exe: string;
44 gpsbabel_version: string; // 1.101.010-beta...
45 gpsbabel_vfmt: string; // 001.101.010
46 gpsbabel_minor, gpsbabel_major, gpsbabel_release: Integer;
47 SGPSBabelGUIVersion: string;
48 CFixedFileinfo: TVSFixedFileInfo;
49
50 const
51 WM_STARTUP = WM_USER + 1;
52 WM_OPTIONS_CHANGED = WM_USER + 2;
53
54 const
55 MAX_NO_OF_SERIAL_PORTS = 8;
56
57 const
58 SREG_TARGET_DIR = 'Target:Directory';
59 SREG_SOURCE_DIR = 'Source:Directory';
60
61 SREG_TARGET_DEV = 'Target:Device';
62 SREG_SOURCE_DEV = 'Source:Device';
63
64 SREG_SOURCE_FMT = 'Source:FileFormat';
65 SREG_TARGET_FMT = 'Target:FileFormat';
66
67 SREG_SOURCE_SER = 'Source:DeviceFormat';
68 SREG_TARGET_SER = 'Target:DeviceFormat';
69
70 SREG_TARGET_FILE = 'Target:File';
71 SREG_SOURCE_FILE = 'Source:File';
72
73 SREG_GLOBAL_LANG = 'Global:Language';
74
75 SREG_MAIN_LAYOUT = 'Main:Layout';
76 SREG_MAIN_WAYPOINTS = 'Main:Waypoints';
77 SREG_MAIN_ROUTES = 'Main:Routes';
78 SREG_MAIN_TRACKS = 'Main:Tracks';
79
80 const
81 Profile: array[0..15] of string =
82 ('?',
83 SREG_SOURCE_DIR,
84 SREG_SOURCE_FMT,
85 SREG_SOURCE_DEV,
86 SREG_SOURCE_SER,
87 SREG_TARGET_DIR,
88 SREG_TARGET_FMT,
89 SREG_TARGET_DEV,
90 SREG_TARGET_SER,
91 SREG_TARGET_FILE,
92 SREG_SOURCE_FILE,
93 SREG_GLOBAL_LANG,
94 SREG_MAIN_LAYOUT,
95 SREG_MAIN_WAYPOINTS,
96 SREG_MAIN_ROUTES,
97 SREG_MAIN_TRACKS
98 );
99
100 const
101 GPSBabel_Domain = 'gpsbabel';
102
103 type
104 TCapability = class
105 protected
106 FName : String;
107 FDescription : string;
108 FExt: string;
109 internal: string;
110 Furl: PChar;
111 protected
CanReadAnynull112 function CanReadAny : Boolean;
CanWriteAnynull113 function CanWriteAny : Boolean;
FIsDevicenull114 function FIsDevice : Boolean;
FIsFilenull115 function FIsFile : Boolean;
116 public
117 Capas: Integer;
118 property Name : String read FName;
119 property Description : String read FDescription write FDescription;
120 property Ext : String read FExt;
121 property ReadAny : Boolean read CanReadAny;
122 property WriteAny : Boolean read CanWriteAny;
123 property IsDevice : Boolean read FIsDevice;
124 property IsFile : Boolean read FIsFile;
125 end;
126
127 type
128 TOptionEdit = class;
129
130 TOption = record
131 format: string;
132 name: string;
133 hint: string;
134 defname: string;
135 otype: Byte;
136 def: PChar; // default value from gpsbabel or ini-file
137 gbdef: PChar; // default value from gpsbabel
138 min: PChar;
139 max: PChar;
140 chb: TCheckBox;
141 edit: TOptionEdit;
142 dir: Byte; // 1 = only in; 2 = only out
143 end;
144 POption = ^TOption;
145
146 TOptionEdit = class(TObject)
147 protected
148 FOption : POption;
GetValuenull149 function GetValue : String; virtual; abstract;
150 procedure SetValue(Value : String); virtual; abstract;
GetEnablednull151 function GetEnabled : Boolean; virtual; abstract;
152 procedure SetEnabled(Value : Boolean); virtual; abstract;
153 public
154 property Value : String read GetValue write SetValue;
155 property Option : POption read FOption;
156 property Enabled : Boolean read GetEnabled write SetEnabled;
157 end;
158
159 TCapabilities = class;
160
161 TOptions = class(TStringList)
162 private
163 FCaps: TCapabilities;
GetListnull164 function GetList: TStrings;
165 procedure SetList(const Value: TStrings);
166 protected
167 public
168 constructor Create(ACapabilities: TCapabilities);
169 procedure AddOptionLine(const ALine: string);
170 procedure DebugGetHints(List: TStringList);
FormatOptsnull171 function FormatOpts(const Descr: string): TStringList; overload;
FormatOptsnull172 function FormatOpts(cap : TCapability): TStringList; overload;
HasFormatOptsnull173 function HasFormatOpts(const Format: string): Boolean; overload;
HasFormatOptsnull174 function HasFormatOpts(cap : TCapability): Boolean; overload;
175 property
176 List: TStrings read GetList write SetList;
177 end;
178
179 TCapabilities = class(TStringList)
180 private
181 FList: TStrings;
182 procedure AddFormat(const Line: string);
GetListnull183 function GetList: TStrings;
184 procedure SetList(const Value: TStrings);
185 public
GetCapabilityByNamenull186 function GetCapabilityByName(const Descr: string): TCapability;
GetCapabilitynull187 function GetCapability(Index: Integer) : TCapability;
188
189 property List: TStrings read GetList write SetList;
190 property Capability[Index : Integer] : TCapability read GetCapability;
191 end;
192
193 type
194 eGPSBabelError = class(Exception);
195
atoinull196 function atoi(str: PChar): Integer;
197
198 implementation
199
atoinull200 function atoi(str: PChar): Integer;
201 begin
202 Result := 0;
203 while (str^ <> #0) do
204 begin
205 if ((str^ < '0') or (str^ > '9')) then Break;
206 Result := (Result * 10) + (Ord(str^) - Ord('0'));
207 str := str + 1;
208 end;
209 end;
210
GetFileVersionnull211 function GetFileVersion(const Filename: string): string;
212 var
213 buff: PChar;
214 hdl: DWORD;
215 len: DWORD;
216 sub: PChar;
217 sublen: UINT;
218 fix: PVSFixedFileInfo;
219 i: Integer;
220 begin
221 Result := '?.?';
222
223 FillChar(CFixedFileinfo, SizeOf(CFixedFileinfo), #0);
224
225 len := GetFileVersionInfoSize(PChar(Filename), hdl);
226 if not(len > 0) then exit;
227
228 GetMem(buff, len);
229 try
230
231 if not GetFileVersionInfo(PChar(FileName), 0, len, buff) then Exit;
232
233 fix := Pointer(buff);
234 i := len - SizeOf(fix^);
235 while (i > 0) do
236 begin
237 Dec(i);
238 if (fix.dwSignature = $feef04bd) then
239 begin
240 CFixedFileinfo := fix^;
241 Break;
242 end;
243 PChar(fix) := PChar(fix) + 1;
244 end;
245
246 if not VerQueryValue(buff, PChar('\\StringFileInfo\\040904E4\\FileVersion'),
247 Pointer(sub), sublen) then Exit;
248 if not(sublen > 0) then Exit;
249 Result := string(sub);
250 finally
251 FreeMem(buff);
252 end;
253 end;
254
255 { TOptions }
256
257 constructor TOptions.Create(ACapabilities: TCapabilities);
258 begin
259 inherited Create;
260 FCaps := ACapabilities;
261 Sorted := False;
262 end;
263
264 procedure TOptions.AddOptionLine(const ALine: string);
265 var
266 buff: array[0..1023] of Char;
267 cin, cend: PChar;
268 index: Integer;
269 opt, opt2: POption;
270 list: TStringList;
271 i: Integer;
272 s: string;
273 begin
274 StrPCopy(buff, ALine);
275 StrCat(buff, #9);
276
277 cin := @buff;
278 index := 0;
279 while (true) do
280 begin
281 cend := StrScan(cin, #9);
282 if (cend = nil) then break;
283 cend^ := #0;
284
285 case index of
286 0:
287 if (StrIComp(cin, 'option') <> 0) then
288 Exit else
289 begin
290 New(opt);
291 FillChar(opt^, SizeOf(opt^), #0);
292 end;
293 1:
294 opt.format := string(cin);
295 2:
296 opt.name := string(cin);
297 3:
298 opt.hint := string(cin);
299 4:
300 for i := 0 to high(OTypes) do
301 if (StrIComp(cin, OTypes[i]) = 0) then
302 begin
303 opt.otype := i;
304 Break;
305 end;
306 5:
307 if (cin^ <> #0) then
308 begin
309 opt.gbdef := StrNew(cin);
310 if (opt.def = nil) then
311 opt.def := opt.gbdef;
312 end;
313 6:
314 if (cin^ <> #0) then
315 opt.min := StrNew(cin);
316 7:
317 if (cin^ <> #0) then
318 opt.max := StrNew(cin);
319 end;
320
321 index := index + 1;
322 cin := cend + 1;
323 end;
324
325 if (opt.name = 'snlen') and (opt.gbdef = nil) then
326 begin
327 opt.gbdef := StrNew('10');
328 opt.def := opt.gbdef;
329 end;
330
331 opt.dir := 3; // in and out
332 opt.defname := opt.name;
333
334 index := Self.IndexOf(opt.format);
335 if (index >= 0) then
336 list := TStringList(Self.Objects[index])
337 else begin
338 list := TStringList.Create;
339 list.Sorted := True;
340 Self.AddObject(opt.format, list);
341 end;
342 list.AddObject(opt.name, Pointer(opt));
343 if (opt.format = 'xcsv') then
344 begin
345 if (opt.name = 'style') then
346 begin
347 opt.dir := 1;
348 New(opt2);
349 opt2^ := opt^;
350 opt2.name := 'style_out';
351 opt2.dir := 2;
352 list.AddObject(opt2.name, Pointer(opt2));
353 end;
354 end;
355 end;
356
357 procedure TOptions.DebugGetHints(List: TStringList);
358 var
359 i, j, k: Integer;
360 l: TStrings;
361 o: POption;
362 begin
363 List.Clear;
364 List.Sorted := True;
365 for i := 0 to Count - 1 do
366 begin
367 l := Pointer(Objects[i]);
368 for j := 0 to l.Count - 1 do
369 begin
370 o := Pointer(l.Objects[j]);
371 k := List.IndexOf(o.hint);
372 if (k < 0) then
373 List.Add(o.hint);
374 end;
375 end;
376 end;
377
TOptions.FormatOptsnull378 function TOptions.FormatOpts(const Descr: string): TStringList;
379 var
380 i: Integer;
381 s: string;
382 cap : TCapability;
383 begin
384 cap:=FCaps.GetCapabilityByName(Descr);
385 result:=FormatOpts(cap);
386 end;
387
TOptions.FormatOptsnull388 function TOptions.FormatOpts(cap : TCapability): TStringList;
389 var
390 i: Integer;
391 s: string;
392 begin
393 if (Assigned(Cap)) and Self.Find(Cap.Name, i) then
394 Result := TStringList(Self.Objects[i])
395 else
396 Result := nil;
397 end;
398
TOptions.GetListnull399 function TOptions.GetList: TStrings;
400 begin
401 Result := Self;
402 end;
403
HasFormatOptsnull404 function TOptions.HasFormatOpts(const Format: string): Boolean;
405 begin
406 Result := (FormatOpts(Format) <> nil);
407 end;
408
HasFormatOptsnull409 function TOptions.HasFormatOpts(cap : TCapability): Boolean;
410 begin
411 Result := (FormatOpts(cap) <> nil);
412 end;
413
414 procedure TOptions.SetList(const Value: TStrings);
415 var
416 i: Integer;
417 begin
418 Clear;
419 for i := 0 to Value.Count - 1 do
420 AddOptionLine(Value[i]);
421 Sorted := True;
422 end;
423
424 { TCapabilities }
425
426 procedure TCapabilities.AddFormat(const Line: string);
427 var
428 index: Integer;
429 buff: array[0..1023] of Char;
430 cin, cend: PChar;
431 i: Integer;
432 scaps: string;
433 ext: string;
434 comment: string;
435 name: string;
436 internal: string;
437 caps: Integer;
438 info: TCapability;
439
440 begin
441 StrPCopy(buff, Line);
442 StrCat(buff, #9);
443 //OutputDebugString(buff);
444
445 cin := @buff;
446 index := 0;
447
448 while (true) do
449 begin
450 cend := StrScan(cin, #9);
451 if (cend = nil) then break;
452 cend^ := #0;
453
454 case index of
455 0:
456 if (StrIComp(cin, 'option') = 0) then
457 Exit
458 else
459 internal := StrPas(cin);
460 1:
461 scaps := StrPas(cin);
462 2:
463 name := StrPas(cin);
464 3:
465 begin
466 ext := StrPas(cin);
467 while (Pos('.', ext) <> 0) do
468 System.Delete(ext, Pos('.', ext), 1);
469 end
470 else begin
471 comment := StrPas(cin);
472 if (Length(comment) = 0) or (Length(name) = 0) then break;
473
474 // if (comment[1] = '?') then break;
475
476 caps := 0;
477 for i := 1 to Length(scaps) do
478 if (scaps[i] <> '-') then caps := caps or (1 shl (i - 1));
479
480 info:=TCapability.Create;
481 info.FName:=name;
482 info.FDescription := comment;
483 info.FExt := ext;
484 info.internal := internal;
485 info.Capas := caps;
486
487 SELF.AddObject(name,info);
488
489 if (name = 'garmin_txt') then
490 begin
491 gpsbabel_knows_inifile := True;
492 // add -p "" to command-line
493 end
494 else if (name = 'xcsv') then
495 info.internal := 'file';
496 break;
497 end;
498 end;
499
500 index := index + 1;
501 cin := cend + 1;
502 end;
503 end;
504
TCapability.FIsDevicenull505 function TCapability.FIsDevice : Boolean;
506 begin
507 Result := (AnsiCompareText(Internal, 'serial') = 0);
508 end;
509
FIsFilenull510 function TCapability.FIsFile : Boolean;
511 begin
512 Result := (AnsiCompareText(Internal, 'file') = 0);
513 end;
514
CanReadAnynull515 function TCapability.CanReadAny : Boolean;
516 begin
517 Result := capas and (1 or 4 or 16) <> 0;
518 end;
519
TCapability.CanWriteAnynull520 function TCapability.CanWriteAny : Boolean;
521 begin
522 Result := capas and (2 or 8 or 32) <> 0;
523 end;
524
TCapabilities.GetListnull525 function TCapabilities.GetList: TStrings;
526 begin
527 Result := TStringList.Create;
528 end;
529
GetCapabilityByNamenull530 function TCapabilities.GetCapabilityByName(const Descr: string): TCapability;
531 var
532 i: Integer;
533 info: TCapability;
534 begin
535 for i := 0 to Count - 1 do
536 begin
537 info := TCapability(Objects[i]);
538 if (AnsiCompareText(info.Description, Descr) = 0) then
539 begin
540 Result := info;
541 Exit;
542 end;
543 end;
544 Result := nil;
545 end;
546
GetCapabilitynull547 function TCapabilities.GetCapability(Index: Integer) : TCapability;
548 begin
549 Result := TCapability(Objects[Index]);
550 end;
551
552
553 procedure TCapabilities.SetList(const Value: TStrings);
554 var
555 i: Integer;
556 s: string;
557 begin
558 Clear;
559 for i := 0 to Value.Count - 1 do
560 begin
561 s := Value.Strings[i];
562 AddFormat(s);
563 end;
564 end;
565
566 (*
567 function Open_gpsbabel_ini(): TInifile;
568 var
569 s: string;
570 begin
571 s := SysUtils.ExpandFileName(SGPSBabelIniFilename);
572 if not(SysUtils.FileExists(s)) then
573 s := SysUtils.ExtractFilePath(ParamStr(0)) + SGPSBabelIniFilename;
574 if not(SysUtils.FileExists(s)) then
575 Result := TIniFile.Create(SGPSBabelIniFilename)
576 else
577 Result := TIniFile.Create(s)
578 end;
579 *)
580
581 initialization
582
583 gpsbabel_exe := SysUtils.ExtractFilePath(ParamStr(0)) + SGPSBabelExeFilename;
584 SGPSBabelGUIVersion := GetFileVersion(ParamStr(0));
585 //gpsbabel_ini := Open_gpsbabel_ini();
586 DecimalSeparator := '.';
587
588 end.
589