Rev 747 | Rev 749 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
733 | daniel-mar | 1 | program OIDPLUS; |
2 | |||
3 | (************************************************) |
||
4 | (* OIDPLUS.PAS *) |
||
5 | (* Author: Daniel Marschall *) |
||
748 | daniel-mar | 6 | (* Revision: 2022-02-19 *) |
733 | daniel-mar | 7 | (* License: Apache 2.0 *) |
8 | (* This file contains: *) |
||
9 | (* - "OIDplus for DOS" program *) |
||
10 | (************************************************) |
||
11 | |||
741 | daniel-mar | 12 | (* IMPORTANT: *) |
13 | (* When you compile this code with Turbo Pascal 7.01, *) |
||
14 | (* it won't run on fast PCs (Runtime Error 200). *) |
||
15 | (* The built EXE file needs to be patched. *) |
||
16 | (* The program "PatchCRT" by Kennedy Software *) |
||
17 | (* WON'T work because it somehow breaks our "_Pause" function. *) |
||
18 | (* Instead, use the tool "TPPATCH" by Andreas Bauer. *) |
||
19 | |||
733 | daniel-mar | 20 | uses |
748 | daniel-mar | 21 | Dos, Crt, Drivers, StrList, VtsFuncs, VtsCui, OidFile, OidUtils, |
22 | Weid; |
||
733 | daniel-mar | 23 | |
24 | const |
||
748 | daniel-mar | 25 | VERSIONINFO = 'Revision: 2022-02-19'; |
735 | daniel-mar | 26 | DEFAULT_STATUSBAR = '(C)2020-2022 ViaThinkSoft. Licensed under the terms of the Apache 2.0 license.'; |
740 | daniel-mar | 27 | TITLEBAR_LEFT_TEXT = 'OIDplus'; |
733 | daniel-mar | 28 | DISKIO_SOUND_DEBUGGING = false; |
735 | daniel-mar | 29 | DISKIO_SOUND_DELAY = 500; |
30 | ASNEDIT_LINES = 10; |
||
31 | DESCEDIT_LINES = 10; |
||
32 | DESCEDIT_PADDING = 3; |
||
33 | ACTIONMENU_SIZE = 5; |
||
34 | MAINMENU_WIDTH = 15; |
||
35 | MAINMENU_HEIGHT = 3; |
||
36 | MAINMENU_ALLOW_ESC = false; |
||
740 | daniel-mar | 37 | TREEVIEW_INDENT = 0; |
38 | TREEVIEW_INCLUDE_DESC = true; |
||
39 | TREEVIEW_WIDTH = 80; |
||
744 | daniel-mar | 40 | OID_EXTENSION = '.OID'; |
41 | TREEVIEW_FILENAME = 'OIDTREE.TXT'; |
||
733 | daniel-mar | 42 | |
743 | daniel-mar | 43 | procedure _Pause; |
733 | daniel-mar | 44 | begin |
743 | daniel-mar | 45 | DrawStatusBar('Press any key to continue'); |
746 | daniel-mar | 46 | CursorOn; |
743 | daniel-mar | 47 | ReadKey; |
746 | daniel-mar | 48 | CursorOff; |
743 | daniel-mar | 49 | DrawStatusBar(DEFAULT_STATUSBAR); |
50 | end; |
||
51 | |||
52 | function _WriteOidFile(filename: string; oid: POid; ShowErrorMessage: boolean): boolean; |
||
53 | var |
||
54 | res: boolean; |
||
55 | begin |
||
733 | daniel-mar | 56 | DrawStatusBar('Write file ' + filename + '...'); |
743 | daniel-mar | 57 | res := WriteOidFile(filename, oid); |
733 | daniel-mar | 58 | if DISKIO_SOUND_DEBUGGING then |
59 | begin |
||
60 | Sound(70); |
||
61 | Delay(DISKIO_SOUND_DELAY - 10); |
||
62 | NoSound; |
||
63 | Delay(10); |
||
64 | end; |
||
743 | daniel-mar | 65 | DrawStatusBar(DEFAULT_STATUSBAR); |
733 | daniel-mar | 66 | |
743 | daniel-mar | 67 | _WriteOidFile := res; |
68 | |||
69 | if ShowErrorMessage and not res then |
||
70 | begin |
||
71 | ShowMessage('Cannot write to file ' + filename, 'ERROR', true); |
||
72 | _Pause; |
||
73 | end; |
||
733 | daniel-mar | 74 | end; |
75 | |||
743 | daniel-mar | 76 | function _ReadOidFile(filename: string; oid: POid; ShowErrorMessage: boolean): boolean; |
77 | var |
||
78 | res: boolean; |
||
733 | daniel-mar | 79 | begin |
80 | DrawStatusBar('Read file ' + filename + '...'); |
||
743 | daniel-mar | 81 | res := ReadOidFile(filename, oid); |
733 | daniel-mar | 82 | if DISKIO_SOUND_DEBUGGING then |
83 | begin |
||
84 | Sound(50); |
||
85 | Delay(DISKIO_SOUND_DELAY - 10); |
||
86 | NoSound; |
||
87 | Delay(10); |
||
88 | end; |
||
89 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
90 | |||
743 | daniel-mar | 91 | _ReadOidFile := res; |
92 | |||
93 | if ShowErrorMessage and not res then |
||
94 | begin |
||
95 | ShowMessage('Cannot read file ' + filename, 'ERROR', true); |
||
96 | _Pause; |
||
97 | end; |
||
733 | daniel-mar | 98 | end; |
99 | |||
740 | daniel-mar | 100 | function _ShowASNIds(childOID: POID): string; |
733 | daniel-mar | 101 | var |
102 | j, jmax: integer; |
||
103 | sTmp: string; |
||
104 | begin |
||
105 | sTmp := ''; |
||
735 | daniel-mar | 106 | jmax := ListCount(childOID^.ASNIds)-1; |
733 | daniel-mar | 107 | for j := 0 to jmax do |
108 | begin |
||
109 | if j = 0 then sTmp := sTmp + ' ('; |
||
735 | daniel-mar | 110 | sTmp := sTmp + ListGetElement(childOID^.ASNIds, j); |
733 | daniel-mar | 111 | if j = jmax then |
112 | sTmp := sTmp + ')' |
||
113 | else |
||
114 | sTmp := sTmp + ', '; |
||
115 | end; |
||
116 | _ShowASNIds := sTmp; |
||
117 | end; |
||
118 | |||
119 | function AsnAlreadyExisting(oid: POID; asnid: string): boolean; |
||
120 | begin |
||
741 | daniel-mar | 121 | AsnAlreadyExisting := ListContains(oid^.AsnIds, asnid); |
733 | daniel-mar | 122 | end; |
123 | |||
124 | function AsnEditor(oid: POID): boolean; |
||
125 | var |
||
126 | asnList: PStringList; |
||
127 | i: integer; |
||
128 | x, y, w, h: integer; |
||
129 | res: integer; |
||
130 | sInput: string; |
||
735 | daniel-mar | 131 | menuIdNew, menuIdSave, menuIdExit: integer; |
733 | daniel-mar | 132 | begin |
133 | AsnEditor := false; |
||
134 | |||
135 | repeat |
||
735 | daniel-mar | 136 | CreateList(asnList); |
733 | daniel-mar | 137 | |
138 | for i := 0 to ListCount(oid^.ASNIds)-1 do |
||
139 | begin |
||
140 | ListAppend(asnList, ListGetElement(oid^.ASNIDs, i)); |
||
141 | end; |
||
735 | daniel-mar | 142 | menuIdNew := ListAppend(asnList, '<NEW>'); |
143 | menuIdSave := ListAppend(asnList, '<SAVE>'); |
||
144 | menuIdExit := ListAppend(asnList, '<CANCEL>'); |
||
733 | daniel-mar | 145 | |
146 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
147 | x := SINGLE_LINE_BOX_PADDING; |
||
148 | y := ScreenHeight div 2 - ASNEDIT_LINES div 2; |
||
149 | w := ScreenWidth - (SINGLE_LINE_BOX_PADDING-1)*2; |
||
150 | h := ASNEDIT_LINES; |
||
151 | res := DrawSelectionList(x, y, w, h, |
||
152 | asnList, true, |
||
153 | 'EDIT ASN.1 IDENTIFIERS', |
||
154 | 2); |
||
735 | daniel-mar | 155 | FreeList(asnList); |
733 | daniel-mar | 156 | |
157 | (* Change double-border to thin-border *) |
||
158 | DrawThinBorder(x-1, y-1, w+2, h+2); |
||
159 | GoToXY(x+1, y-1); |
||
160 | Write('EDIT ASN.1 IDENTIFIERS'); |
||
161 | |||
162 | if res = -1 then |
||
163 | begin |
||
164 | exit; |
||
165 | end |
||
735 | daniel-mar | 166 | else if res = menuIdNew then |
733 | daniel-mar | 167 | begin |
168 | (* "NEW" item was selected *) |
||
169 | sInput := ''; |
||
746 | daniel-mar | 170 | CursorOn; |
733 | daniel-mar | 171 | repeat |
172 | if QueryVal(sInput, |
||
173 | SINGLE_LINE_BOX_PADDING_INNER, |
||
174 | ScreenHeight div 2, |
||
175 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
176 | 1, |
||
177 | 'ADD SINGLE ASN.1 ID', |
||
178 | 2) then |
||
179 | begin |
||
180 | if sInput = '' then continue; |
||
181 | if not ASN1IDValid(sInput) then |
||
182 | begin |
||
183 | ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true); |
||
184 | _Pause; |
||
185 | end |
||
186 | else if AsnAlreadyExisting(oid, sInput) then |
||
187 | begin |
||
188 | ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true); |
||
189 | _Pause; |
||
190 | end |
||
191 | else |
||
192 | begin |
||
193 | ListAppend(oid^.ASNIDs, sInput); |
||
194 | break; |
||
195 | end; |
||
196 | end |
||
197 | else break; |
||
198 | until false; |
||
746 | daniel-mar | 199 | CursorOff; |
733 | daniel-mar | 200 | end |
735 | daniel-mar | 201 | else if res = menuIdSave then |
733 | daniel-mar | 202 | begin |
203 | (* "SAVE" item was selected *) |
||
204 | AsnEditor := true; |
||
205 | Exit; |
||
206 | end |
||
735 | daniel-mar | 207 | else if res = menuIdExit then |
733 | daniel-mar | 208 | begin |
209 | (* "CANCEL" item was selected *) |
||
210 | AsnEditor := false; |
||
211 | Exit; |
||
212 | end |
||
213 | else |
||
214 | begin |
||
215 | DrawStatusBar('Note: Remove the text to delete the ASN.1 identifier'); |
||
216 | sInput := ListGetElement(oid^.ASNIDs, res); |
||
746 | daniel-mar | 217 | CursorOn; |
733 | daniel-mar | 218 | repeat |
219 | if QueryVal(sInput, |
||
220 | SINGLE_LINE_BOX_PADDING_INNER, |
||
221 | ScreenHeight div 2, |
||
222 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
223 | 1, |
||
224 | 'EDIT SINGLE ASN.1 ID', |
||
225 | 2) then |
||
226 | begin |
||
227 | if sInput = '' then |
||
228 | begin |
||
229 | (* Empty input = Delete ASN.1 ID *) |
||
737 | daniel-mar | 230 | ListDeleteElementByIndex(oid^.ASNIDs, res); |
733 | daniel-mar | 231 | break; |
232 | end |
||
233 | else if not ASN1IDValid(sInput) then |
||
234 | begin |
||
235 | ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true); |
||
236 | _Pause; |
||
237 | end |
||
238 | else if AsnAlreadyExisting(oid, sInput) and |
||
239 | not (ListGetElement(oid^.ASNIDs, res) = sInput) then |
||
240 | begin |
||
241 | ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true); |
||
242 | _Pause; |
||
243 | end |
||
244 | else |
||
245 | begin |
||
246 | ListSetElement(oid^.ASNIDs, res, sInput); |
||
247 | break; |
||
248 | end; |
||
249 | end |
||
250 | else break; |
||
251 | until false; |
||
746 | daniel-mar | 252 | CursorOff; |
733 | daniel-mar | 253 | end; |
254 | until false; |
||
255 | end; |
||
256 | |||
748 | daniel-mar | 257 | function UnicodeLabelAlreadyExisting(oid: POID; unicodeLabel: string): boolean; |
258 | begin |
||
259 | UnicodeLabelAlreadyExisting := ListContains(oid^.UnicodeLabels, unicodeLabel); |
||
260 | end; |
||
261 | |||
262 | function IriEditor(oid: POID): boolean; |
||
263 | var |
||
264 | iriList: PStringList; |
||
265 | i: integer; |
||
266 | x, y, w, h: integer; |
||
267 | res: integer; |
||
268 | sInput: string; |
||
269 | menuIdNew, menuIdSave, menuIdExit: integer; |
||
270 | begin |
||
271 | IriEditor := false; |
||
272 | |||
273 | repeat |
||
274 | CreateList(iriList); |
||
275 | |||
276 | for i := 0 to ListCount(oid^.UnicodeLabels)-1 do |
||
277 | begin |
||
278 | ListAppend(iriList, ListGetElement(oid^.UnicodeLabels, i)); |
||
279 | end; |
||
280 | menuIdNew := ListAppend(iriList, '<NEW>'); |
||
281 | menuIdSave := ListAppend(iriList, '<SAVE>'); |
||
282 | menuIdExit := ListAppend(iriList, '<CANCEL>'); |
||
283 | |||
284 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
285 | x := SINGLE_LINE_BOX_PADDING; |
||
286 | y := ScreenHeight div 2 - ASNEDIT_LINES div 2; |
||
287 | w := ScreenWidth - (SINGLE_LINE_BOX_PADDING-1)*2; |
||
288 | h := ASNEDIT_LINES; |
||
289 | res := DrawSelectionList(x, y, w, h, |
||
290 | iriList, true, |
||
291 | 'EDIT UNICODE LABELS', |
||
292 | 2); |
||
293 | FreeList(iriList); |
||
294 | |||
295 | (* Change double-border to thin-border *) |
||
296 | DrawThinBorder(x-1, y-1, w+2, h+2); |
||
297 | GoToXY(x+1, y-1); |
||
298 | Write('EDIT UNICODE LABELS'); |
||
299 | |||
300 | if res = -1 then |
||
301 | begin |
||
302 | exit; |
||
303 | end |
||
304 | else if res = menuIdNew then |
||
305 | begin |
||
306 | (* "NEW" item was selected *) |
||
307 | sInput := ''; |
||
308 | CursorOn; |
||
309 | repeat |
||
310 | if QueryVal(sInput, |
||
311 | SINGLE_LINE_BOX_PADDING_INNER, |
||
312 | ScreenHeight div 2, |
||
313 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
314 | 1, |
||
315 | 'ADD SINGLE UNICODE LABEL', |
||
316 | 2) then |
||
317 | begin |
||
318 | if sInput = '' then continue; |
||
319 | if not UnicodeLabelValid(sInput) then |
||
320 | begin |
||
321 | ShowMessage('Invalid Unicode Label!', 'ERROR', true); |
||
322 | _Pause; |
||
323 | end |
||
324 | else if UnicodeLabelAlreadyExisting(oid, sInput) then |
||
325 | begin |
||
326 | ShowMessage('Unicode Label is already existing on this arc', 'ERROR', true); |
||
327 | _Pause; |
||
328 | end |
||
329 | else |
||
330 | begin |
||
331 | ListAppend(oid^.UnicodeLabels, sInput); |
||
332 | break; |
||
333 | end; |
||
334 | end |
||
335 | else break; |
||
336 | until false; |
||
337 | CursorOff; |
||
338 | end |
||
339 | else if res = menuIdSave then |
||
340 | begin |
||
341 | (* "SAVE" item was selected *) |
||
342 | IriEditor := true; |
||
343 | Exit; |
||
344 | end |
||
345 | else if res = menuIdExit then |
||
346 | begin |
||
347 | (* "CANCEL" item was selected *) |
||
348 | IriEditor := false; |
||
349 | Exit; |
||
350 | end |
||
351 | else |
||
352 | begin |
||
353 | DrawStatusBar('Note: Remove the text to delete the Unicode Label'); |
||
354 | sInput := ListGetElement(oid^.UnicodeLabels, res); |
||
355 | CursorOn; |
||
356 | repeat |
||
357 | if QueryVal(sInput, |
||
358 | SINGLE_LINE_BOX_PADDING_INNER, |
||
359 | ScreenHeight div 2, |
||
360 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
361 | 1, |
||
362 | 'EDIT SINGLE UNICODE LABEL', |
||
363 | 2) then |
||
364 | begin |
||
365 | if sInput = '' then |
||
366 | begin |
||
367 | (* Empty input = Delete Unicode label *) |
||
368 | ListDeleteElementByIndex(oid^.UnicodeLabels, res); |
||
369 | break; |
||
370 | end |
||
371 | else if not UnicodeLabelValid(sInput) then |
||
372 | begin |
||
373 | ShowMessage('Invalid Unicode Label!', 'ERROR', true); |
||
374 | _Pause; |
||
375 | end |
||
376 | else if UnicodeLabelAlreadyExisting(oid, sInput) and |
||
377 | not (ListGetElement(oid^.UnicodeLabels, res) = sInput) then |
||
378 | begin |
||
379 | ShowMessage('Unicode Label is already existing on this arc', 'ERROR', true); |
||
380 | _Pause; |
||
381 | end |
||
382 | else |
||
383 | begin |
||
384 | ListSetElement(oid^.UnicodeLabels, res, sInput); |
||
385 | break; |
||
386 | end; |
||
387 | end |
||
388 | else break; |
||
389 | until false; |
||
390 | CursorOff; |
||
391 | end; |
||
392 | until false; |
||
393 | end; |
||
394 | |||
733 | daniel-mar | 395 | function DescEditor(oid: POID): boolean; |
396 | var |
||
397 | sInput: string; |
||
398 | begin |
||
399 | DescEditor := false; |
||
400 | |||
401 | DrawStatusBar('Note: Press Ctrl+Return for a line-break.'); |
||
402 | sInput := oid^.description; |
||
746 | daniel-mar | 403 | CursorOn; |
733 | daniel-mar | 404 | if QueryVal(sInput, |
405 | DESCEDIT_PADDING, |
||
406 | ScreenHeight div 2 - DESCEDIT_LINES div 2, |
||
407 | ScreenWidth - (DESCEDIT_PADDING-1)*2, |
||
408 | DESCEDIT_LINES, |
||
409 | 'EDIT DESCRIPTION', |
||
410 | 2) then |
||
411 | begin |
||
412 | oid^.description := sInput; |
||
740 | daniel-mar | 413 | DescEditor := true; (* request caller to save <oid> *) |
733 | daniel-mar | 414 | end; |
746 | daniel-mar | 415 | CursorOff; |
733 | daniel-mar | 416 | end; |
417 | |||
418 | function NextPossibleFileID: string; |
||
419 | var |
||
420 | DirInfo: SearchRec; |
||
421 | list: PStringList; |
||
422 | iId: LongInt; |
||
423 | sId: string; |
||
424 | begin |
||
425 | (* Put all found files into a list *) |
||
735 | daniel-mar | 426 | CreateList(list); |
744 | daniel-mar | 427 | FindFirst(RepeatStr('?',8)+OID_EXTENSION, Archive, DirInfo); |
733 | daniel-mar | 428 | while DosError = 0 do |
429 | begin |
||
430 | sId := Copy(DirInfo.Name, 1, 8); |
||
431 | ListAppend(list, sId); |
||
432 | FindNext(DirInfo); |
||
433 | end; |
||
434 | |||
435 | (* Search for the first non existing item in the list *) |
||
436 | sId := ''; |
||
437 | for iId := 0 to 99999999 do |
||
438 | begin |
||
439 | sId := ZeroPad(iId, 8); |
||
440 | if not ListContains(list, sId) then break; |
||
441 | end; |
||
442 | NextPossibleFileId := sId; |
||
443 | FreeList(list); |
||
444 | end; |
||
445 | |||
446 | function NumIdAlreadyExisting(parentOID: POID; sInput: string): boolean; |
||
447 | var |
||
448 | searchDotNotation: string; |
||
449 | sTmp: string; |
||
450 | i: integer; |
||
451 | begin |
||
452 | if parentOID^.DotNotation = '' then |
||
453 | searchDotNotation := sInput |
||
454 | else |
||
455 | searchDotNotation := parentOID^.DotNotation + '.' + sInput; |
||
456 | for i := 0 to ListCount(parentOID^.SubIds)-1 do |
||
457 | begin |
||
458 | sTmp := ListGetElement(parentOID^.SubIds, i); |
||
735 | daniel-mar | 459 | if DotNotationPart(sTmp) = searchDotNotation then |
733 | daniel-mar | 460 | begin |
461 | NumIdAlreadyExisting := true; |
||
462 | exit; |
||
463 | end; |
||
464 | end; |
||
465 | NumIdAlreadyExisting := false; |
||
466 | end; |
||
467 | |||
468 | function NumIdEditor(oid: POID; parentOID: POID): boolean; |
||
469 | var |
||
470 | sInput: string; |
||
471 | begin |
||
472 | NumIdEditor := false; |
||
473 | sInput := ''; |
||
474 | |||
746 | daniel-mar | 475 | CursorOn; |
733 | daniel-mar | 476 | repeat |
477 | if QueryVal(sInput, |
||
478 | SINGLE_LINE_BOX_PADDING_INNER, |
||
479 | ScreenHeight div 2, |
||
480 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
481 | 1, |
||
482 | 'ENTER NUMERIC ID', |
||
483 | 2) then |
||
484 | begin |
||
485 | if sInput = '' then continue; |
||
747 | daniel-mar | 486 | if not IsPositiveIntegerOrZero(sInput) then |
733 | daniel-mar | 487 | begin |
488 | ShowMessage('Invalid numeric ID (must be a positive integer)', 'ERROR', true); |
||
489 | _Pause; |
||
490 | end |
||
491 | else if (parentOID^.DotNotation='') and (StrToInt(sInput) > 2) then |
||
492 | begin |
||
493 | ShowMessage('Invalid numeric ID (root arc can only be 0, 1, or 2)', 'ERROR', true); |
||
494 | _Pause; |
||
495 | end |
||
496 | else if ((parentOID^.DotNotation='0') or (parentOID^.DotNotation='1')) and (StrToInt(sInput) > 39) then |
||
497 | begin |
||
498 | ShowMessage('Invalid numeric ID (root 0 and 1 must have sub-arc of 0..39)', 'ERROR', true); |
||
499 | _Pause; |
||
500 | end |
||
501 | else if NumIdAlreadyExisting(parentOID, sInput) then |
||
502 | begin |
||
503 | ShowMessage('This numeric ID is already used in this arc', 'ERROR', true); |
||
504 | _Pause; |
||
505 | end |
||
506 | else |
||
507 | begin |
||
508 | if parentOID^.DotNotation = '' then |
||
509 | oid^.DotNotation := sInput |
||
510 | else |
||
511 | oid^.DotNotation := parentOID^.DotNotation + '.' + sInput; |
||
740 | daniel-mar | 512 | NumIdEditor := true; (* request caller to save <oid> *) |
746 | daniel-mar | 513 | Break; |
733 | daniel-mar | 514 | end; |
515 | end |
||
516 | else |
||
517 | begin |
||
746 | daniel-mar | 518 | Break; |
733 | daniel-mar | 519 | end; |
520 | until false; |
||
746 | daniel-mar | 521 | CursorOff; |
733 | daniel-mar | 522 | end; |
523 | |||
524 | function NewOidEditor(oid: POID): boolean; |
||
525 | var |
||
526 | newfilename: string; |
||
735 | daniel-mar | 527 | newOID: POID; |
733 | daniel-mar | 528 | begin |
529 | NewOidEditor := false; |
||
530 | |||
735 | daniel-mar | 531 | CreateOidDef(newOID); |
532 | newOID^.FileId := NextPossibleFileID; |
||
745 | daniel-mar | 533 | newOID^.ParentFileId := oid^.FileId; |
534 | newOID^.ParentDotNotation := oid^.DotNotation; |
||
735 | daniel-mar | 535 | if NumIdEditor(newOID, oid) and |
536 | AsnEditor(newOID) and |
||
748 | daniel-mar | 537 | IriEditor(newOID) and |
735 | daniel-mar | 538 | DescEditor(newOID) then |
734 | daniel-mar | 539 | begin |
744 | daniel-mar | 540 | newfilename := newOID^.FileId + OID_EXTENSION; |
743 | daniel-mar | 541 | if _WriteOidFile(newfilename, newOID, true) then |
542 | begin |
||
543 | (* Add link to original file and enable the saving of it *) |
||
544 | ListAppend(oid^.SubIds, newOID^.FileId + newOID^.DotNotation); |
||
545 | NewOidEditor := true; (* request caller to save <oid> *) |
||
546 | end; |
||
734 | daniel-mar | 547 | end; |
735 | daniel-mar | 548 | FreeOidDef(newOID); |
733 | daniel-mar | 549 | end; |
550 | |||
551 | procedure DeleteChildrenRecursive(oid: POID); |
||
552 | var |
||
553 | i: integer; |
||
735 | daniel-mar | 554 | childOID: POID; |
733 | daniel-mar | 555 | filenameChild: string; |
556 | begin |
||
557 | for i := 0 to ListCount(oid^.SubIds)-1 do |
||
558 | begin |
||
744 | daniel-mar | 559 | filenameChild := FileIdPart(ListGetElement(oid^.SubIds, i)) + OID_EXTENSION; |
740 | daniel-mar | 560 | if FileExists(filenameChild) then |
561 | begin |
||
562 | CreateOidDef(childOID); |
||
744 | daniel-mar | 563 | if _ReadOidFile(filenameChild, childOID, false) and |
745 | daniel-mar | 564 | (childOID^.ParentFileId = oid^.FileId) and |
565 | (childOID^.ParentDotNotation = oid^.DotNotation) then |
||
743 | daniel-mar | 566 | begin |
567 | DeleteChildrenRecursive(childOID); |
||
568 | end; |
||
740 | daniel-mar | 569 | FreeOidDef(childOID); |
570 | DeleteFile(filenameChild); |
||
571 | end; |
||
733 | daniel-mar | 572 | end; |
573 | ListClear(oid^.SubIds); |
||
574 | end; |
||
575 | |||
576 | procedure DeleteOidRecursive(selfOID: POID); |
||
577 | var |
||
578 | i: integer; |
||
735 | daniel-mar | 579 | parentOID: POID; |
733 | daniel-mar | 580 | filenameSelf, filenameParent: string; |
581 | begin |
||
582 | (* Remove all children and their files recursively *) |
||
583 | DeleteChildrenRecursive(selfOID); |
||
584 | |||
585 | (* Remove forward reference in parent OID *) |
||
743 | daniel-mar | 586 | (* (this is the most important part) *) |
745 | daniel-mar | 587 | filenameParent := selfOID^.ParentFileId + OID_EXTENSION; |
740 | daniel-mar | 588 | if FileExists(filenameParent) then |
733 | daniel-mar | 589 | begin |
740 | daniel-mar | 590 | CreateOidDef(parentOID); |
743 | daniel-mar | 591 | if _ReadOidFile(filenameParent, parentOID, true) then |
740 | daniel-mar | 592 | begin |
743 | daniel-mar | 593 | if ListDeleteElementByValue(parentOID^.SubIds, selfOID^.FileId + selfOID^.DotNotation) then |
594 | begin |
||
595 | _WriteOidFile(filenameParent, parentOID, true); |
||
596 | end; |
||
740 | daniel-mar | 597 | end; |
598 | FreeOidDef(parentOID); |
||
733 | daniel-mar | 599 | end; |
600 | |||
601 | (* Delete own file *) |
||
744 | daniel-mar | 602 | filenameSelf := selfOID^.FileId + OID_EXTENSION; |
740 | daniel-mar | 603 | if FileExists(filenameSelf) then |
604 | begin |
||
605 | DeleteFile(filenameSelf); |
||
606 | end; |
||
733 | daniel-mar | 607 | end; |
608 | |||
735 | daniel-mar | 609 | function _DeleteConfirmation: boolean; |
610 | var |
||
611 | sc: Char; |
||
612 | begin |
||
613 | repeat |
||
614 | ShowMessage('Are you sure you want to delete this OID? (Y/N)', 'DELETE OID', true); |
||
737 | daniel-mar | 615 | DrawStatusBar('Y=Yes, N=No'); |
735 | daniel-mar | 616 | |
746 | daniel-mar | 617 | CursorOn; |
735 | daniel-mar | 618 | sc := ReadKey; |
746 | daniel-mar | 619 | CursorOff; |
735 | daniel-mar | 620 | if sc = #0 then |
621 | begin |
||
622 | (* Extended key. Nothing we care about. *) |
||
623 | ReadKey; |
||
624 | continue; |
||
625 | end; |
||
626 | |||
627 | if UpCase(sc) = 'Y' then |
||
628 | begin |
||
629 | _DeleteConfirmation := true; |
||
630 | break; |
||
737 | daniel-mar | 631 | end |
632 | else if UpCase(sc) = 'N' then |
||
735 | daniel-mar | 633 | begin |
634 | _DeleteConfirmation := false; |
||
635 | break; |
||
636 | end; |
||
637 | until false; |
||
638 | end; |
||
639 | |||
737 | daniel-mar | 640 | procedure _DrawOidTitleBar(filename: string; oid: POID); |
641 | begin |
||
642 | if oid^.DotNotation = '' then |
||
738 | daniel-mar | 643 | DrawTitleBar('OID ROOT', TITLEBAR_LEFT_TEXT, filename) |
737 | daniel-mar | 644 | else |
738 | daniel-mar | 645 | DrawTitleBar('OID ' + oid^.DotNotation, TITLEBAR_LEFT_TEXT, filename); |
737 | daniel-mar | 646 | end; |
647 | |||
748 | daniel-mar | 648 | function DotNotation(oid: POid): string; |
649 | var |
||
650 | res: string; |
||
651 | begin |
||
652 | res := oid^.DotNotation; |
||
653 | if res = '' then res := '.'; (* root *) |
||
654 | DotNotation := res; |
||
655 | end; |
||
656 | |||
657 | function OidLastArc(oid: POid): string; |
||
658 | var |
||
659 | s: string; |
||
660 | p: integer; |
||
661 | begin |
||
662 | s := oid^.DotNotation; |
||
663 | |||
664 | while true do |
||
665 | begin |
||
666 | p := Pos('.', s); |
||
667 | if p = 0 then break; |
||
668 | Delete(s, 1, p); |
||
669 | end; |
||
670 | |||
671 | OidLastArc := s; |
||
672 | end; |
||
673 | |||
674 | function AsnNotation(oid: POid): string; |
||
675 | var |
||
676 | prevOid, curOid: POid; |
||
677 | res: string; |
||
678 | begin |
||
679 | CreateOidDef(curOid); |
||
680 | prevOid := oid; |
||
681 | res := ''; |
||
682 | |||
683 | while true do |
||
684 | begin |
||
685 | (* Note: BackRef is not checked yet! Infinite loop is possible! (TODO) *) |
||
686 | ReadOidFile(prevOid^.ParentFileId + '.OID', curOid); |
||
687 | if curOid^.ParentFileId = '' then break; |
||
688 | if curOid^.ParentFileId = curOid^.FileId then break; |
||
689 | if ListCount(curOid^.AsnIds) > 0 then |
||
690 | res := ListGetElement(curOid^.AsnIds, 0) + '('+OidLastArc(curOid)+') ' + res |
||
691 | else |
||
692 | res := OidLastArc(curOid) + ' ' + res; |
||
693 | prevOid := curOid; |
||
694 | end; |
||
695 | FreeOidDef(curOid); |
||
696 | if ListCount(oid^.AsnIds) > 0 then |
||
697 | res := res + ListGetElement(oid^.AsnIds, 0) + '('+OidLastArc(oid)+')' |
||
698 | else |
||
699 | res := res + OidLastArc(oid); |
||
700 | if res = '' then |
||
701 | AsnNotation := '' |
||
702 | else |
||
703 | AsnNotation := '{ ' + res + ' }'; |
||
704 | end; |
||
705 | |||
706 | function IriNotation(oid: POid): string; |
||
707 | var |
||
708 | prevOid, curOid: POid; |
||
709 | res: string; |
||
710 | begin |
||
711 | CreateOidDef(curOid); |
||
712 | prevOid := oid; |
||
713 | res := ''; |
||
714 | |||
715 | while true do |
||
716 | begin |
||
717 | (* Note: BackRef is not checked yet! Infinite loop is possible! (TODO) *) |
||
718 | ReadOidFile(prevOid^.ParentFileId + '.OID', curOid); |
||
719 | if curOid^.ParentFileId = '' then break; |
||
720 | if curOid^.ParentFileId = curOid^.FileId then break; |
||
721 | if ListCount(curOid^.UnicodeLabels) > 0 then |
||
722 | res := ListGetElement(curOid^.UnicodeLabels, 0) + '/' + res |
||
723 | else |
||
724 | res := OidLastArc(curOid) + '/' + res; |
||
725 | prevOid := curOid; |
||
726 | end; |
||
727 | FreeOidDef(curOid); |
||
728 | if ListCount(oid^.UnicodeLabels) > 0 then |
||
729 | res := res + ListGetElement(oid^.UnicodeLabels, 0) |
||
730 | else |
||
731 | res := res + OidLastArc(oid); |
||
732 | IriNotation := '/' + res; |
||
733 | end; |
||
734 | |||
735 | function WeidNotation(oid: POid): string; |
||
736 | begin |
||
737 | WeidNotation := OidToWeid(oid^.DotNotation); |
||
738 | end; |
||
739 | |||
733 | daniel-mar | 740 | procedure DisplayOIDFile(filename: string); |
741 | var |
||
742 | isRoot: boolean; |
||
740 | daniel-mar | 743 | oid, tmpOID: POID; |
748 | daniel-mar | 744 | i: integer; |
733 | daniel-mar | 745 | sTmp, subfile: string; |
746 | subsel, subfiles: PStringList; |
||
747 | subselres: integer; |
||
735 | daniel-mar | 748 | exitRequest: boolean; |
748 | daniel-mar | 749 | menuIdExit, menuIdAsnEdit, menuIdIriEdit, menuIdDescEdit, menuIdAdd, menuIdDelete: integer; |
750 | menuX, menuY: integer; |
||
733 | daniel-mar | 751 | begin |
735 | daniel-mar | 752 | exitRequest := false; |
733 | daniel-mar | 753 | repeat |
743 | daniel-mar | 754 | CreateOidDef(oid); |
755 | |||
756 | if not _ReadOidFile(filename, oid, true) then |
||
740 | daniel-mar | 757 | begin |
743 | daniel-mar | 758 | FreeOidDef(oid); |
740 | daniel-mar | 759 | exit; |
760 | end; |
||
761 | |||
733 | daniel-mar | 762 | (* Print OID information *) |
763 | |||
764 | ClrScr; |
||
737 | daniel-mar | 765 | _DrawOidTitleBar(filename, oid); |
733 | daniel-mar | 766 | DrawStatusBar(DEFAULT_STATUSBAR); |
767 | GotoXY(1,2); |
||
768 | |||
748 | daniel-mar | 769 | (*if oid^.DotNotation <> '' then*) |
733 | daniel-mar | 770 | begin |
748 | daniel-mar | 771 | Write('Dot notation: '); |
772 | WriteLnKeepX(DotNotation(oid)); |
||
773 | Write('IRI notation: '); |
||
774 | WriteLnKeepX(IriNotation(oid)); |
||
775 | Write('ASN.1 notation: '); |
||
776 | WriteLnKeepX(AsnNotation(oid)); |
||
777 | Write('WEID notation: '); |
||
778 | WriteLnKeepX(WeidNotation(oid)); |
||
733 | daniel-mar | 779 | WriteLn(''); |
780 | end; |
||
781 | |||
735 | daniel-mar | 782 | if Trim(oid^.Description) <> '' then |
733 | daniel-mar | 783 | begin |
748 | daniel-mar | 784 | (* WriteLn('Description:'); *) |
735 | daniel-mar | 785 | WriteLn(oid^.Description); |
733 | daniel-mar | 786 | WriteLn(''); |
748 | daniel-mar | 787 | end |
788 | else |
||
733 | daniel-mar | 789 | begin |
748 | daniel-mar | 790 | WriteLn('(No description has been added to this OID.)'); |
791 | WriteLn(''); |
||
733 | daniel-mar | 792 | end; |
793 | |||
794 | (* Now prepare the menu entries *) |
||
795 | |||
744 | daniel-mar | 796 | CreateList(subsel); (* Contains the human-readable OID name *) |
737 | daniel-mar | 797 | CreateList(subfiles); (* Contains the file name *) |
733 | daniel-mar | 798 | |
745 | daniel-mar | 799 | if oid^.ParentFileId = '' then |
733 | daniel-mar | 800 | begin |
801 | isRoot := true; |
||
802 | end |
||
803 | else |
||
804 | begin |
||
745 | daniel-mar | 805 | isRoot := oid^.ParentDotNotation = oid^.DotNotation; |
733 | daniel-mar | 806 | end; |
807 | |||
745 | daniel-mar | 808 | if (oid^.ParentFileId <> '') and not isRoot then |
733 | daniel-mar | 809 | begin |
745 | daniel-mar | 810 | subfile := oid^.ParentFileId + OID_EXTENSION; |
740 | daniel-mar | 811 | if FileExists(subfile) then |
812 | begin |
||
813 | CreateOidDef(tmpOID); |
||
744 | daniel-mar | 814 | if not _ReadOidFile(subfile, tmpOID, true) then |
815 | begin |
||
745 | daniel-mar | 816 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + ' (READ ERROR)'); |
744 | daniel-mar | 817 | ListAppend(subfiles, 'ERROR: '+subfile+' Read error or file invalid'); |
818 | end |
||
743 | daniel-mar | 819 | else |
744 | daniel-mar | 820 | begin |
745 | daniel-mar | 821 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + _ShowASNIds(tmpOID)); |
744 | daniel-mar | 822 | ListAppend(subfiles, subfile); |
823 | end; |
||
740 | daniel-mar | 824 | FreeOidDef(tmpOID); |
825 | end |
||
826 | else |
||
827 | begin |
||
745 | daniel-mar | 828 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + ' (FILE NOT FOUND)'); |
744 | daniel-mar | 829 | ListAppend(subfiles, 'ERROR: File '+subfile+' was not found'); |
740 | daniel-mar | 830 | end; |
733 | daniel-mar | 831 | end; |
832 | |||
833 | if isRoot then |
||
834 | begin |
||
735 | daniel-mar | 835 | menuIdExit := ListAppend(subsel, 'Back to main menu'); |
836 | ListAppend(subfiles, ''); |
||
837 | end |
||
838 | else menuIdExit := -99; |
||
733 | daniel-mar | 839 | |
735 | daniel-mar | 840 | for i := 0 to ListCount(oid^.SubIds)-1 do |
733 | daniel-mar | 841 | begin |
735 | daniel-mar | 842 | sTmp := ListGetElement(oid^.SubIds, i); |
744 | daniel-mar | 843 | subfile := FileIdPart(sTmp) + OID_EXTENSION; |
740 | daniel-mar | 844 | if FileExists(subfile) then |
845 | begin |
||
846 | CreateOidDef(tmpOID); |
||
744 | daniel-mar | 847 | if not _ReadOidFile(subfile, tmpOID, true) then |
848 | begin |
||
849 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (READ ERROR)'); |
||
850 | ListAppend(subfiles, 'ERROR: Read error at file '+subfile+', or file is invalid.'); |
||
851 | end |
||
745 | daniel-mar | 852 | else if (tmpOID^.ParentFileId <> oid^.FileId) or |
853 | (tmpOID^.ParentDotNotation <> oid^.DotNotation) then |
||
744 | daniel-mar | 854 | begin |
855 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (BAD BACKREF)'); |
||
856 | ListAppend(subfiles, 'ERROR: File '+subfile+' has a wrong back-reference.'); |
||
857 | end |
||
743 | daniel-mar | 858 | else |
744 | daniel-mar | 859 | begin |
860 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + _ShowASNIds(tmpOID)); |
||
861 | ListAppend(subfiles, subfile); |
||
862 | end; |
||
740 | daniel-mar | 863 | FreeOidDef(tmpOID); |
864 | end |
||
865 | else |
||
866 | begin |
||
867 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (FILE NOT FOUND)'); |
||
744 | daniel-mar | 868 | ListAppend(subfiles, 'ERROR: File '+subfile+' was not found'); |
740 | daniel-mar | 869 | end; |
733 | daniel-mar | 870 | end; |
871 | |||
735 | daniel-mar | 872 | if oid^.DotNotation <> '' then |
733 | daniel-mar | 873 | begin |
748 | daniel-mar | 874 | menuIdAsnEdit := ListAppend(subsel, 'View/Edit ASN.1 identifiers'); |
735 | daniel-mar | 875 | ListAppend(subfiles, ''); |
876 | end |
||
877 | else menuIdAsnEdit := -99; |
||
733 | daniel-mar | 878 | |
748 | daniel-mar | 879 | if oid^.DotNotation <> '' then |
880 | begin |
||
881 | menuIdIriEdit := ListAppend(subsel, 'View/Edit Unicode Labels'); |
||
882 | ListAppend(subfiles, ''); |
||
883 | end |
||
884 | else menuIdIriEdit := -99; |
||
885 | |||
735 | daniel-mar | 886 | menuIdDescEdit := ListAppend(subsel, 'Edit description'); |
887 | ListAppend(subfiles, ''); |
||
733 | daniel-mar | 888 | |
735 | daniel-mar | 889 | menuIdAdd := ListAppend(subsel, 'Add child'); |
890 | ListAppend(subfiles, ''); |
||
733 | daniel-mar | 891 | |
892 | if not isRoot then |
||
893 | begin |
||
735 | daniel-mar | 894 | menuIdDelete := ListAppend(subsel, 'Delete OID'); |
895 | ListAppend(subfiles, ''); |
||
896 | end |
||
897 | else menuIdDelete := -99; |
||
733 | daniel-mar | 898 | |
734 | daniel-mar | 899 | (* Show menu *) |
900 | |||
748 | daniel-mar | 901 | menuX := WhereX + 1; |
902 | menuY := ScreenHeight - ACTIONMENU_SIZE - 1; |
||
733 | daniel-mar | 903 | subselres := DrawSelectionList(menuX, menuY, |
904 | ScreenWidth-2, |
||
735 | daniel-mar | 905 | ACTIONMENU_SIZE, |
733 | daniel-mar | 906 | subsel, |
907 | true, |
||
908 | 'SELECT ACTION', |
||
909 | 1); |
||
734 | daniel-mar | 910 | |
911 | (* Process user selection *) |
||
912 | |||
733 | daniel-mar | 913 | if subselres = -1 then |
914 | begin |
||
735 | daniel-mar | 915 | exitRequest := true; |
733 | daniel-mar | 916 | end |
735 | daniel-mar | 917 | else if subselres = menuIdAsnEdit then |
733 | daniel-mar | 918 | begin |
735 | daniel-mar | 919 | if AsnEditor(oid) then |
743 | daniel-mar | 920 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 921 | end |
748 | daniel-mar | 922 | else if subselres = menuIdIriEdit then |
923 | begin |
||
924 | if IriEditor(oid) then |
||
925 | _WriteOidFile(filename, oid, true); |
||
926 | end |
||
735 | daniel-mar | 927 | else if subselres = menuIdDescEdit then |
928 | begin |
||
929 | if DescEditor(oid) then |
||
743 | daniel-mar | 930 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 931 | end |
932 | else if subselres = menuIdAdd then |
||
933 | begin |
||
934 | if NewOidEditor(oid) then |
||
743 | daniel-mar | 935 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 936 | end |
937 | else if subselres = menuIdDelete then |
||
938 | begin |
||
939 | if _DeleteConfirmation then |
||
733 | daniel-mar | 940 | begin |
745 | daniel-mar | 941 | sTmp := oid^.ParentFileId + OID_EXTENSION; |
735 | daniel-mar | 942 | DeleteOidRecursive(oid); |
740 | daniel-mar | 943 | if FileExists(sTmp) then |
944 | begin |
||
945 | filename := sTmp; |
||
946 | end |
||
947 | else |
||
948 | begin |
||
744 | daniel-mar | 949 | ShowMessage('Parent file ' + sTmp + ' was not found', 'ERROR', true); |
740 | daniel-mar | 950 | _Pause; |
951 | exitRequest := true; |
||
952 | end; |
||
733 | daniel-mar | 953 | end; |
735 | daniel-mar | 954 | end |
955 | else if subselres = menuIdExit then |
||
956 | begin |
||
957 | exitRequest := true; |
||
958 | end |
||
959 | else |
||
960 | begin |
||
961 | (* Normal OID *) |
||
744 | daniel-mar | 962 | (* Above we already checked if the files are valild and existing *) |
740 | daniel-mar | 963 | sTmp := ListGetElement(subfiles, subselres); |
744 | daniel-mar | 964 | if Copy(sTmp, 1, Length('ERROR: ')) = 'ERROR: ' then |
740 | daniel-mar | 965 | begin |
744 | daniel-mar | 966 | Delete(sTmp, 1, Length('ERROR: ')); |
967 | ShowMessage(sTmp, 'ERROR', true); |
||
968 | _Pause; |
||
740 | daniel-mar | 969 | end |
970 | else |
||
971 | begin |
||
744 | daniel-mar | 972 | filename := sTmp; |
740 | daniel-mar | 973 | end; |
733 | daniel-mar | 974 | end; |
975 | FreeList(subsel); |
||
976 | FreeList(subfiles); |
||
977 | |||
735 | daniel-mar | 978 | FreeOidDef(oid); |
979 | until exitRequest; |
||
733 | daniel-mar | 980 | end; |
981 | |||
743 | daniel-mar | 982 | function CreateRootOIDFile(filename: string; ShowErrorMessage: boolean): boolean; |
733 | daniel-mar | 983 | var |
735 | daniel-mar | 984 | oid: POID; |
733 | daniel-mar | 985 | begin |
735 | daniel-mar | 986 | CreateOidDef(oid); |
745 | daniel-mar | 987 | oid^.Description := 'This is the root of the OID tree.' +#13#10 + |
988 | #13#10 + |
||
989 | 'Valid subsequent arcs are per definition:' + #13#10 + |
||
990 | '- 0 (itu-t)' + #13#10 + |
||
991 | '- 1 (iso)' + #13#10 + |
||
992 | '- 2 (joint-iso-itu-t)'; |
||
993 | oid^.FileId := ZeroPad(0, 8); |
||
994 | oid^.DotNotation := ''; |
||
995 | oid^.ParentFileId := ZeroPad(0, 8); |
||
996 | oid^.ParentDotNotation := ''; |
||
743 | daniel-mar | 997 | CreateRootOIDFile := _WriteOidFile(filename, oid, ShowErrorMessage); |
735 | daniel-mar | 998 | FreeOidDef(oid); |
733 | daniel-mar | 999 | end; |
1000 | |||
742 | daniel-mar | 1001 | function _GetRootFile(ShowErrorMessage: boolean): string; |
735 | daniel-mar | 1002 | var |
742 | daniel-mar | 1003 | rootFile: string; |
733 | daniel-mar | 1004 | begin |
744 | daniel-mar | 1005 | rootFile := ZeroPad(0, 8) + OID_EXTENSION; |
743 | daniel-mar | 1006 | _GetRootFile := rootFile; |
742 | daniel-mar | 1007 | if not FileExists(rootFile) then |
733 | daniel-mar | 1008 | begin |
743 | daniel-mar | 1009 | if not CreateRootOIDFile(rootFile, ShowErrorMessage) then |
742 | daniel-mar | 1010 | begin |
743 | daniel-mar | 1011 | _GetRootFile := ''; |
742 | daniel-mar | 1012 | end; |
1013 | end; |
||
733 | daniel-mar | 1014 | end; |
1015 | |||
740 | daniel-mar | 1016 | procedure OP_ManageOIDs; |
742 | daniel-mar | 1017 | var |
1018 | rootfile: string; |
||
740 | daniel-mar | 1019 | begin |
1020 | ClrScr; |
||
1021 | DrawTitleBar('Manage Object Identifiers', TITLEBAR_LEFT_TEXT, ''); |
||
1022 | DrawStatusBar('Loading data... please wait...'); |
||
1023 | |||
742 | daniel-mar | 1024 | (* This will try creating a new root file if it does not exist *) |
1025 | rootfile := _GetRootFile(true); |
||
1026 | if rootfile = '' then Exit; |
||
1027 | |||
1028 | DisplayOIDFile(rootfile); |
||
740 | daniel-mar | 1029 | end; |
1030 | |||
733 | daniel-mar | 1031 | procedure OP_ReturnToMSDOS; |
1032 | begin |
||
747 | daniel-mar | 1033 | (* Note: These two lines don't seem to be necessary if you use DoneVideo *) |
1034 | ResetDefaultDosColors; |
||
746 | daniel-mar | 1035 | ClrScr; (*Important, so that the DOS command prompt is also LightGray *) |
1036 | |||
741 | daniel-mar | 1037 | WriteLn('Thank you for using OIDplus for DOS.'); |
743 | daniel-mar | 1038 | WriteLn(''); |
733 | daniel-mar | 1039 | end; |
1040 | |||
741 | daniel-mar | 1041 | function _GetTreeViewLine(oid: POID; indent: integer): string; |
740 | daniel-mar | 1042 | var |
1043 | i: integer; |
||
747 | daniel-mar | 1044 | sTmp, sTmp2: string; |
740 | daniel-mar | 1045 | begin |
1046 | (* Build line *) |
||
1047 | sTmp := RepeatStr(' ', indent*TREEVIEW_INDENT); |
||
1048 | if oid^.DotNotation = '' then |
||
1049 | sTmp := sTmp + 'Object Identifiers' |
||
1050 | else |
||
1051 | sTmp := sTmp + oid^.DotNotation; |
||
1052 | sTmp := sTmp + _ShowAsnIds(oid); |
||
1053 | if TREEVIEW_INCLUDE_DESC then |
||
1054 | begin |
||
1055 | if Trim(oid^.Description) <> '' then |
||
1056 | begin |
||
1057 | sTmp := sTmp + ': ' + oid^.Description; |
||
1058 | end; |
||
1059 | end; |
||
747 | daniel-mar | 1060 | |
1061 | sTmp := StringReplace(sTmp, #13#10, ' '); |
||
1062 | repeat |
||
1063 | sTmp2 := sTmp; |
||
1064 | sTmp := StringReplace(sTmp, ' ', ' '); |
||
1065 | until sTmp = sTmp2; |
||
1066 | |||
744 | daniel-mar | 1067 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
741 | daniel-mar | 1068 | _GetTreeViewLine := sTmp; |
740 | daniel-mar | 1069 | end; |
1070 | |||
1071 | procedure _RecTreeExport(oid: POID; var F: Text; indent: integer); |
||
1072 | var |
||
1073 | i: integer; |
||
1074 | sTmp: string; |
||
1075 | suboid: POID; |
||
1076 | childFilename: string; |
||
1077 | begin |
||
741 | daniel-mar | 1078 | sTmp := _GetTreeViewLine(oid, indent); |
740 | daniel-mar | 1079 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
1080 | WriteLn(F, sTmp); |
||
1081 | |||
1082 | (* Recursively call children *) |
||
1083 | for i := 0 to ListCount(oid^.SubIds)-1 do |
||
1084 | begin |
||
1085 | sTmp := ListGetElement(oid^.SubIds, i); |
||
1086 | CreateOidDef(suboid); |
||
744 | daniel-mar | 1087 | childFilename := FileIdPart(sTmp) + OID_EXTENSION; |
743 | daniel-mar | 1088 | if not FileExists(childFilename) then |
740 | daniel-mar | 1089 | begin |
744 | daniel-mar | 1090 | sTmp := 'ERROR: MISSING ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
743 | daniel-mar | 1091 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
1092 | WriteLn(F, sTmp); |
||
740 | daniel-mar | 1093 | end |
743 | daniel-mar | 1094 | else if not _ReadOidFile(childFilename, suboid, false) then |
740 | daniel-mar | 1095 | begin |
744 | daniel-mar | 1096 | sTmp := 'ERROR: READ ERROR AT ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
740 | daniel-mar | 1097 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
1098 | WriteLn(F, sTmp); |
||
743 | daniel-mar | 1099 | end |
745 | daniel-mar | 1100 | else if (suboid^.ParentFileId <> oid^.FileId) or |
1101 | (suboid^.ParentDotNotation <> oid^.DotNotation) then |
||
744 | daniel-mar | 1102 | begin |
1103 | (* This can happen if a file is missing, and then another OID gets this filename since the number seems to be free *) |
||
1104 | sTmp := 'ERROR: BAD BACKREF AT ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
||
1105 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
||
1106 | WriteLn(F, sTmp); |
||
1107 | end |
||
743 | daniel-mar | 1108 | else |
1109 | begin |
||
1110 | _RecTreeExport(suboid, F, indent+1); |
||
1111 | FreeOidDef(suboid); |
||
1112 | end |
||
740 | daniel-mar | 1113 | end; |
1114 | end; |
||
1115 | |||
747 | daniel-mar | 1116 | procedure TreeViewPreview; |
1117 | var |
||
1118 | list: PStringList; |
||
1119 | begin |
||
748 | daniel-mar | 1120 | ClrScr; |
1121 | DrawTitleBar('TreeView Export', TITLEBAR_LEFT_TEXT, TREEVIEW_FILENAME); |
||
1122 | DrawStatusBar('Press ESC to return to the main menu'); |
||
1123 | |||
747 | daniel-mar | 1124 | CreateList(list); |
1125 | |||
1126 | ListLoadFromFile(list, TREEVIEW_FILENAME); |
||
1127 | DrawSelectionList(2, 3, ScreenWidth-2, ScreenHeight-4, |
||
1128 | list, true, 'PREVIEW OF '+TREEVIEW_FILENAME, 2); |
||
1129 | (* TODO: Jump to selected OID *) |
||
1130 | |||
1131 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
1132 | |||
1133 | FreeList(list); |
||
1134 | end; |
||
1135 | |||
740 | daniel-mar | 1136 | procedure OP_TreeView; |
1137 | var |
||
1138 | F: Text; |
||
1139 | rootoid: POID; |
||
742 | daniel-mar | 1140 | rootfile: string; |
743 | daniel-mar | 1141 | res: boolean; |
740 | daniel-mar | 1142 | begin |
1143 | ClrScr; |
||
1144 | DrawTitleBar('TreeView Export', TITLEBAR_LEFT_TEXT, ''); |
||
1145 | DrawStatusBar('Exporting data... please wait...'); |
||
1146 | |||
742 | daniel-mar | 1147 | (* This will try creating a new root file if it does not exist *) |
743 | daniel-mar | 1148 | rootfile := _GetRootFile(true); |
1149 | if rootfile = '' then |
||
1150 | begin |
||
1151 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
1152 | Exit; |
||
1153 | end; |
||
742 | daniel-mar | 1154 | |
744 | daniel-mar | 1155 | Assign(F, TREEVIEW_FILENAME); |
743 | daniel-mar | 1156 | {$I-} |
740 | daniel-mar | 1157 | Rewrite(F); |
743 | daniel-mar | 1158 | {$I+} |
1159 | if IoResult <> 0 then |
||
1160 | begin |
||
1161 | (* Can happen if disk is read-only (Runtime Error 150) *) |
||
744 | daniel-mar | 1162 | ShowMessage('Cannot open '+TREEVIEW_FILENAME+' for writing.', 'ERROR', true); |
743 | daniel-mar | 1163 | _Pause; |
1164 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
1165 | Exit; |
||
1166 | end; |
||
740 | daniel-mar | 1167 | |
743 | daniel-mar | 1168 | res := false; |
740 | daniel-mar | 1169 | CreateOidDef(rootoid); |
743 | daniel-mar | 1170 | if _ReadOidFile(rootfile, rootoid, true) then |
1171 | begin |
||
1172 | _RecTreeExport(rootoid, F, 0); |
||
1173 | res := true; |
||
1174 | end; |
||
740 | daniel-mar | 1175 | FreeOidDef(rootoid); |
1176 | |||
743 | daniel-mar | 1177 | Close(F); |
1178 | |||
740 | daniel-mar | 1179 | DrawStatusBar(DEFAULT_STATUSBAR); |
743 | daniel-mar | 1180 | if res then |
1181 | begin |
||
744 | daniel-mar | 1182 | ShowMessage('TreeView successfully exported as '+TREEVIEW_FILENAME, 'TREEVIEW EXPORT', true); |
743 | daniel-mar | 1183 | _Pause; |
1184 | end; |
||
747 | daniel-mar | 1185 | |
1186 | TreeViewPreview; |
||
740 | daniel-mar | 1187 | end; |
1188 | |||
733 | daniel-mar | 1189 | procedure OP_MainMenu; |
1190 | var |
||
1191 | menu: PStringList; |
||
1192 | menuRes, menuLeft, menuTop: integer; |
||
747 | daniel-mar | 1193 | menuIdOID, menuIdTree, menuIdExit: integer; |
733 | daniel-mar | 1194 | begin |
1195 | repeat |
||
1196 | ClrScr; |
||
1197 | |||
738 | daniel-mar | 1198 | DrawTitleBar('Welcome to OIDplus for DOS', '', ''); |
733 | daniel-mar | 1199 | DrawStatusBar(DEFAULT_STATUSBAR); |
1200 | GoToXY(ScreenWidth-Length(VERSIONINFO), ScreenHeight-1); |
||
1201 | Write(VERSIONINFO); |
||
1202 | |||
735 | daniel-mar | 1203 | CreateList(menu); |
1204 | |||
1205 | menuIdOID := ListAppend(menu, 'Manage OIDs'); |
||
740 | daniel-mar | 1206 | menuIdTree := ListAppend(menu, 'Export TreeView'); |
735 | daniel-mar | 1207 | menuIdExit := ListAppend(menu, 'Return to DOS'); |
1208 | |||
1209 | menuLeft := round(ScreenWidth/2 -MAINMENU_WIDTH/2); |
||
1210 | menuTop := round(ScreenHeight/2-MAINMENU_HEIGHT/2); |
||
1211 | menuRes := DrawSelectionList(menuLeft, menuTop, |
||
1212 | MAINMENU_WIDTH, MAINMENU_HEIGHT, |
||
1213 | menu, true, 'MAIN MENU', 2); |
||
733 | daniel-mar | 1214 | FreeList(menu); |
1215 | |||
735 | daniel-mar | 1216 | if menuRes = menuIdOID then |
733 | daniel-mar | 1217 | begin |
1218 | OP_ManageOIDs; |
||
735 | daniel-mar | 1219 | end |
740 | daniel-mar | 1220 | else if menuRes = menuIdTree then |
1221 | begin |
||
1222 | OP_Treeview; |
||
733 | daniel-mar | 1223 | end; |
735 | daniel-mar | 1224 | until (menuRes = menuIdExit) or (MAINMENU_ALLOW_ESC and (menuRes = -1)); |
733 | daniel-mar | 1225 | |
1226 | OP_ReturnToMSDOS; |
||
1227 | end; |
||
1228 | |||
1229 | begin |
||
746 | daniel-mar | 1230 | InitVideo; (* sets ScreenWidth and ScreenHeight *) |
1231 | CursorOff; |
||
733 | daniel-mar | 1232 | OP_MainMenu; |
747 | daniel-mar | 1233 | CursorOn; |
746 | daniel-mar | 1234 | DoneVideo; |
733 | daniel-mar | 1235 | end. |