Rev 745 | Rev 747 | 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 *) |
||
744 | daniel-mar | 6 | (* Revision: 2022-02-15 *) |
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 |
746 | daniel-mar | 21 | Dos, Crt, Drivers, StrList, VtsFuncs, VtsCui, OidFile, OidUtils; |
733 | daniel-mar | 22 | |
23 | const |
||
744 | daniel-mar | 24 | VERSIONINFO = 'Revision: 2022-02-15'; |
735 | daniel-mar | 25 | DEFAULT_STATUSBAR = '(C)2020-2022 ViaThinkSoft. Licensed under the terms of the Apache 2.0 license.'; |
740 | daniel-mar | 26 | TITLEBAR_LEFT_TEXT = 'OIDplus'; |
733 | daniel-mar | 27 | DISKIO_SOUND_DEBUGGING = false; |
735 | daniel-mar | 28 | DISKIO_SOUND_DELAY = 500; |
29 | ASNEDIT_LINES = 10; |
||
30 | DESCEDIT_LINES = 10; |
||
31 | DESCEDIT_PADDING = 3; |
||
32 | ACTIONMENU_SIZE = 5; |
||
33 | MAINMENU_WIDTH = 15; |
||
34 | MAINMENU_HEIGHT = 3; |
||
35 | MAINMENU_ALLOW_ESC = false; |
||
740 | daniel-mar | 36 | TREEVIEW_INDENT = 0; |
37 | TREEVIEW_INCLUDE_DESC = true; |
||
38 | TREEVIEW_WIDTH = 80; |
||
744 | daniel-mar | 39 | OID_EXTENSION = '.OID'; |
40 | TREEVIEW_FILENAME = 'OIDTREE.TXT'; |
||
733 | daniel-mar | 41 | |
743 | daniel-mar | 42 | procedure _Pause; |
733 | daniel-mar | 43 | begin |
743 | daniel-mar | 44 | DrawStatusBar('Press any key to continue'); |
746 | daniel-mar | 45 | CursorOn; |
743 | daniel-mar | 46 | ReadKey; |
746 | daniel-mar | 47 | CursorOff; |
743 | daniel-mar | 48 | DrawStatusBar(DEFAULT_STATUSBAR); |
49 | end; |
||
50 | |||
51 | function _WriteOidFile(filename: string; oid: POid; ShowErrorMessage: boolean): boolean; |
||
52 | var |
||
53 | res: boolean; |
||
54 | begin |
||
733 | daniel-mar | 55 | DrawStatusBar('Write file ' + filename + '...'); |
743 | daniel-mar | 56 | res := WriteOidFile(filename, oid); |
733 | daniel-mar | 57 | if DISKIO_SOUND_DEBUGGING then |
58 | begin |
||
59 | Sound(70); |
||
60 | Delay(DISKIO_SOUND_DELAY - 10); |
||
61 | NoSound; |
||
62 | Delay(10); |
||
63 | end; |
||
743 | daniel-mar | 64 | DrawStatusBar(DEFAULT_STATUSBAR); |
733 | daniel-mar | 65 | |
743 | daniel-mar | 66 | _WriteOidFile := res; |
67 | |||
68 | if ShowErrorMessage and not res then |
||
69 | begin |
||
70 | ShowMessage('Cannot write to file ' + filename, 'ERROR', true); |
||
71 | _Pause; |
||
72 | end; |
||
733 | daniel-mar | 73 | end; |
74 | |||
743 | daniel-mar | 75 | function _ReadOidFile(filename: string; oid: POid; ShowErrorMessage: boolean): boolean; |
76 | var |
||
77 | res: boolean; |
||
733 | daniel-mar | 78 | begin |
79 | DrawStatusBar('Read file ' + filename + '...'); |
||
743 | daniel-mar | 80 | res := ReadOidFile(filename, oid); |
733 | daniel-mar | 81 | if DISKIO_SOUND_DEBUGGING then |
82 | begin |
||
83 | Sound(50); |
||
84 | Delay(DISKIO_SOUND_DELAY - 10); |
||
85 | NoSound; |
||
86 | Delay(10); |
||
87 | end; |
||
88 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
89 | |||
743 | daniel-mar | 90 | _ReadOidFile := res; |
91 | |||
92 | if ShowErrorMessage and not res then |
||
93 | begin |
||
94 | ShowMessage('Cannot read file ' + filename, 'ERROR', true); |
||
95 | _Pause; |
||
96 | end; |
||
733 | daniel-mar | 97 | end; |
98 | |||
740 | daniel-mar | 99 | function _ShowASNIds(childOID: POID): string; |
733 | daniel-mar | 100 | var |
101 | j, jmax: integer; |
||
102 | sTmp: string; |
||
103 | begin |
||
104 | sTmp := ''; |
||
735 | daniel-mar | 105 | jmax := ListCount(childOID^.ASNIds)-1; |
733 | daniel-mar | 106 | for j := 0 to jmax do |
107 | begin |
||
108 | if j = 0 then sTmp := sTmp + ' ('; |
||
735 | daniel-mar | 109 | sTmp := sTmp + ListGetElement(childOID^.ASNIds, j); |
733 | daniel-mar | 110 | if j = jmax then |
111 | sTmp := sTmp + ')' |
||
112 | else |
||
113 | sTmp := sTmp + ', '; |
||
114 | end; |
||
115 | _ShowASNIds := sTmp; |
||
116 | end; |
||
117 | |||
118 | function AsnAlreadyExisting(oid: POID; asnid: string): boolean; |
||
119 | begin |
||
741 | daniel-mar | 120 | AsnAlreadyExisting := ListContains(oid^.AsnIds, asnid); |
733 | daniel-mar | 121 | end; |
122 | |||
123 | function AsnEditor(oid: POID): boolean; |
||
124 | var |
||
125 | asnList: PStringList; |
||
126 | i: integer; |
||
127 | x, y, w, h: integer; |
||
128 | res: integer; |
||
129 | sInput: string; |
||
735 | daniel-mar | 130 | menuIdNew, menuIdSave, menuIdExit: integer; |
733 | daniel-mar | 131 | begin |
132 | AsnEditor := false; |
||
133 | |||
134 | repeat |
||
735 | daniel-mar | 135 | CreateList(asnList); |
733 | daniel-mar | 136 | |
137 | for i := 0 to ListCount(oid^.ASNIds)-1 do |
||
138 | begin |
||
139 | ListAppend(asnList, ListGetElement(oid^.ASNIDs, i)); |
||
140 | end; |
||
735 | daniel-mar | 141 | menuIdNew := ListAppend(asnList, '<NEW>'); |
142 | menuIdSave := ListAppend(asnList, '<SAVE>'); |
||
143 | menuIdExit := ListAppend(asnList, '<CANCEL>'); |
||
733 | daniel-mar | 144 | |
145 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
146 | x := SINGLE_LINE_BOX_PADDING; |
||
147 | y := ScreenHeight div 2 - ASNEDIT_LINES div 2; |
||
148 | w := ScreenWidth - (SINGLE_LINE_BOX_PADDING-1)*2; |
||
149 | h := ASNEDIT_LINES; |
||
150 | res := DrawSelectionList(x, y, w, h, |
||
151 | asnList, true, |
||
152 | 'EDIT ASN.1 IDENTIFIERS', |
||
153 | 2); |
||
735 | daniel-mar | 154 | FreeList(asnList); |
733 | daniel-mar | 155 | |
156 | (* Change double-border to thin-border *) |
||
157 | DrawThinBorder(x-1, y-1, w+2, h+2); |
||
158 | GoToXY(x+1, y-1); |
||
159 | Write('EDIT ASN.1 IDENTIFIERS'); |
||
160 | |||
161 | if res = -1 then |
||
162 | begin |
||
163 | exit; |
||
164 | end |
||
735 | daniel-mar | 165 | else if res = menuIdNew then |
733 | daniel-mar | 166 | begin |
167 | (* "NEW" item was selected *) |
||
168 | sInput := ''; |
||
746 | daniel-mar | 169 | CursorOn; |
733 | daniel-mar | 170 | repeat |
171 | if QueryVal(sInput, |
||
172 | SINGLE_LINE_BOX_PADDING_INNER, |
||
173 | ScreenHeight div 2, |
||
174 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
175 | 1, |
||
176 | 'ADD SINGLE ASN.1 ID', |
||
177 | 2) then |
||
178 | begin |
||
179 | if sInput = '' then continue; |
||
180 | if not ASN1IDValid(sInput) then |
||
181 | begin |
||
182 | ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true); |
||
183 | _Pause; |
||
184 | end |
||
185 | else if AsnAlreadyExisting(oid, sInput) then |
||
186 | begin |
||
187 | ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true); |
||
188 | _Pause; |
||
189 | end |
||
190 | else |
||
191 | begin |
||
192 | ListAppend(oid^.ASNIDs, sInput); |
||
193 | break; |
||
194 | end; |
||
195 | end |
||
196 | else break; |
||
197 | until false; |
||
746 | daniel-mar | 198 | CursorOff; |
733 | daniel-mar | 199 | end |
735 | daniel-mar | 200 | else if res = menuIdSave then |
733 | daniel-mar | 201 | begin |
202 | (* "SAVE" item was selected *) |
||
203 | AsnEditor := true; |
||
204 | Exit; |
||
205 | end |
||
735 | daniel-mar | 206 | else if res = menuIdExit then |
733 | daniel-mar | 207 | begin |
208 | (* "CANCEL" item was selected *) |
||
209 | AsnEditor := false; |
||
210 | Exit; |
||
211 | end |
||
212 | else |
||
213 | begin |
||
214 | DrawStatusBar('Note: Remove the text to delete the ASN.1 identifier'); |
||
215 | sInput := ListGetElement(oid^.ASNIDs, res); |
||
746 | daniel-mar | 216 | CursorOn; |
733 | daniel-mar | 217 | repeat |
218 | if QueryVal(sInput, |
||
219 | SINGLE_LINE_BOX_PADDING_INNER, |
||
220 | ScreenHeight div 2, |
||
221 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
222 | 1, |
||
223 | 'EDIT SINGLE ASN.1 ID', |
||
224 | 2) then |
||
225 | begin |
||
226 | if sInput = '' then |
||
227 | begin |
||
228 | (* Empty input = Delete ASN.1 ID *) |
||
737 | daniel-mar | 229 | ListDeleteElementByIndex(oid^.ASNIDs, res); |
733 | daniel-mar | 230 | break; |
231 | end |
||
232 | else if not ASN1IDValid(sInput) then |
||
233 | begin |
||
234 | ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true); |
||
235 | _Pause; |
||
236 | end |
||
237 | else if AsnAlreadyExisting(oid, sInput) and |
||
238 | not (ListGetElement(oid^.ASNIDs, res) = sInput) then |
||
239 | begin |
||
240 | ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true); |
||
241 | _Pause; |
||
242 | end |
||
243 | else |
||
244 | begin |
||
245 | ListSetElement(oid^.ASNIDs, res, sInput); |
||
246 | break; |
||
247 | end; |
||
248 | end |
||
249 | else break; |
||
250 | until false; |
||
746 | daniel-mar | 251 | CursorOff; |
733 | daniel-mar | 252 | end; |
253 | until false; |
||
254 | end; |
||
255 | |||
256 | function DescEditor(oid: POID): boolean; |
||
257 | var |
||
258 | sInput: string; |
||
259 | begin |
||
260 | DescEditor := false; |
||
261 | |||
262 | DrawStatusBar('Note: Press Ctrl+Return for a line-break.'); |
||
263 | sInput := oid^.description; |
||
746 | daniel-mar | 264 | CursorOn; |
733 | daniel-mar | 265 | if QueryVal(sInput, |
266 | DESCEDIT_PADDING, |
||
267 | ScreenHeight div 2 - DESCEDIT_LINES div 2, |
||
268 | ScreenWidth - (DESCEDIT_PADDING-1)*2, |
||
269 | DESCEDIT_LINES, |
||
270 | 'EDIT DESCRIPTION', |
||
271 | 2) then |
||
272 | begin |
||
273 | oid^.description := sInput; |
||
740 | daniel-mar | 274 | DescEditor := true; (* request caller to save <oid> *) |
733 | daniel-mar | 275 | end; |
746 | daniel-mar | 276 | CursorOff; |
733 | daniel-mar | 277 | end; |
278 | |||
279 | function NextPossibleFileID: string; |
||
280 | var |
||
281 | DirInfo: SearchRec; |
||
282 | list: PStringList; |
||
283 | iId: LongInt; |
||
284 | sId: string; |
||
285 | begin |
||
286 | (* Put all found files into a list *) |
||
735 | daniel-mar | 287 | CreateList(list); |
744 | daniel-mar | 288 | FindFirst(RepeatStr('?',8)+OID_EXTENSION, Archive, DirInfo); |
733 | daniel-mar | 289 | while DosError = 0 do |
290 | begin |
||
291 | sId := Copy(DirInfo.Name, 1, 8); |
||
292 | ListAppend(list, sId); |
||
293 | FindNext(DirInfo); |
||
294 | end; |
||
295 | |||
296 | (* Search for the first non existing item in the list *) |
||
297 | sId := ''; |
||
298 | for iId := 0 to 99999999 do |
||
299 | begin |
||
300 | sId := ZeroPad(iId, 8); |
||
301 | if not ListContains(list, sId) then break; |
||
302 | end; |
||
303 | NextPossibleFileId := sId; |
||
304 | FreeList(list); |
||
305 | end; |
||
306 | |||
307 | function NumIdAlreadyExisting(parentOID: POID; sInput: string): boolean; |
||
308 | var |
||
309 | searchDotNotation: string; |
||
310 | sTmp: string; |
||
311 | i: integer; |
||
312 | begin |
||
313 | if parentOID^.DotNotation = '' then |
||
314 | searchDotNotation := sInput |
||
315 | else |
||
316 | searchDotNotation := parentOID^.DotNotation + '.' + sInput; |
||
317 | for i := 0 to ListCount(parentOID^.SubIds)-1 do |
||
318 | begin |
||
319 | sTmp := ListGetElement(parentOID^.SubIds, i); |
||
735 | daniel-mar | 320 | if DotNotationPart(sTmp) = searchDotNotation then |
733 | daniel-mar | 321 | begin |
322 | NumIdAlreadyExisting := true; |
||
323 | exit; |
||
324 | end; |
||
325 | end; |
||
326 | NumIdAlreadyExisting := false; |
||
327 | end; |
||
328 | |||
329 | function NumIdEditor(oid: POID; parentOID: POID): boolean; |
||
330 | var |
||
331 | sInput: string; |
||
332 | begin |
||
333 | NumIdEditor := false; |
||
334 | sInput := ''; |
||
335 | |||
746 | daniel-mar | 336 | CursorOn; |
733 | daniel-mar | 337 | repeat |
338 | if QueryVal(sInput, |
||
339 | SINGLE_LINE_BOX_PADDING_INNER, |
||
340 | ScreenHeight div 2, |
||
341 | ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2, |
||
342 | 1, |
||
343 | 'ENTER NUMERIC ID', |
||
344 | 2) then |
||
345 | begin |
||
346 | if sInput = '' then continue; |
||
739 | daniel-mar | 347 | if not IsPositiveInteger(sInput) then |
733 | daniel-mar | 348 | begin |
349 | ShowMessage('Invalid numeric ID (must be a positive integer)', 'ERROR', true); |
||
350 | _Pause; |
||
351 | end |
||
352 | else if (parentOID^.DotNotation='') and (StrToInt(sInput) > 2) then |
||
353 | begin |
||
354 | ShowMessage('Invalid numeric ID (root arc can only be 0, 1, or 2)', 'ERROR', true); |
||
355 | _Pause; |
||
356 | end |
||
357 | else if ((parentOID^.DotNotation='0') or (parentOID^.DotNotation='1')) and (StrToInt(sInput) > 39) then |
||
358 | begin |
||
359 | ShowMessage('Invalid numeric ID (root 0 and 1 must have sub-arc of 0..39)', 'ERROR', true); |
||
360 | _Pause; |
||
361 | end |
||
362 | else if NumIdAlreadyExisting(parentOID, sInput) then |
||
363 | begin |
||
364 | ShowMessage('This numeric ID is already used in this arc', 'ERROR', true); |
||
365 | _Pause; |
||
366 | end |
||
367 | else |
||
368 | begin |
||
369 | if parentOID^.DotNotation = '' then |
||
370 | oid^.DotNotation := sInput |
||
371 | else |
||
372 | oid^.DotNotation := parentOID^.DotNotation + '.' + sInput; |
||
740 | daniel-mar | 373 | NumIdEditor := true; (* request caller to save <oid> *) |
746 | daniel-mar | 374 | Break; |
733 | daniel-mar | 375 | end; |
376 | end |
||
377 | else |
||
378 | begin |
||
746 | daniel-mar | 379 | Break; |
733 | daniel-mar | 380 | end; |
381 | until false; |
||
746 | daniel-mar | 382 | CursorOff; |
733 | daniel-mar | 383 | end; |
384 | |||
385 | function NewOidEditor(oid: POID): boolean; |
||
386 | var |
||
387 | newfilename: string; |
||
735 | daniel-mar | 388 | newOID: POID; |
733 | daniel-mar | 389 | begin |
390 | NewOidEditor := false; |
||
391 | |||
735 | daniel-mar | 392 | CreateOidDef(newOID); |
393 | newOID^.FileId := NextPossibleFileID; |
||
745 | daniel-mar | 394 | newOID^.ParentFileId := oid^.FileId; |
395 | newOID^.ParentDotNotation := oid^.DotNotation; |
||
735 | daniel-mar | 396 | if NumIdEditor(newOID, oid) and |
397 | AsnEditor(newOID) and |
||
398 | DescEditor(newOID) then |
||
734 | daniel-mar | 399 | begin |
744 | daniel-mar | 400 | newfilename := newOID^.FileId + OID_EXTENSION; |
743 | daniel-mar | 401 | if _WriteOidFile(newfilename, newOID, true) then |
402 | begin |
||
403 | (* Add link to original file and enable the saving of it *) |
||
404 | ListAppend(oid^.SubIds, newOID^.FileId + newOID^.DotNotation); |
||
405 | NewOidEditor := true; (* request caller to save <oid> *) |
||
406 | end; |
||
734 | daniel-mar | 407 | end; |
735 | daniel-mar | 408 | FreeOidDef(newOID); |
733 | daniel-mar | 409 | end; |
410 | |||
411 | procedure DeleteChildrenRecursive(oid: POID); |
||
412 | var |
||
413 | i: integer; |
||
735 | daniel-mar | 414 | childOID: POID; |
733 | daniel-mar | 415 | filenameChild: string; |
416 | begin |
||
417 | for i := 0 to ListCount(oid^.SubIds)-1 do |
||
418 | begin |
||
744 | daniel-mar | 419 | filenameChild := FileIdPart(ListGetElement(oid^.SubIds, i)) + OID_EXTENSION; |
740 | daniel-mar | 420 | if FileExists(filenameChild) then |
421 | begin |
||
422 | CreateOidDef(childOID); |
||
744 | daniel-mar | 423 | if _ReadOidFile(filenameChild, childOID, false) and |
745 | daniel-mar | 424 | (childOID^.ParentFileId = oid^.FileId) and |
425 | (childOID^.ParentDotNotation = oid^.DotNotation) then |
||
743 | daniel-mar | 426 | begin |
427 | DeleteChildrenRecursive(childOID); |
||
428 | end; |
||
740 | daniel-mar | 429 | FreeOidDef(childOID); |
430 | DeleteFile(filenameChild); |
||
431 | end; |
||
733 | daniel-mar | 432 | end; |
433 | ListClear(oid^.SubIds); |
||
434 | end; |
||
435 | |||
436 | procedure DeleteOidRecursive(selfOID: POID); |
||
437 | var |
||
438 | i: integer; |
||
735 | daniel-mar | 439 | parentOID: POID; |
733 | daniel-mar | 440 | filenameSelf, filenameParent: string; |
441 | begin |
||
442 | (* Remove all children and their files recursively *) |
||
443 | DeleteChildrenRecursive(selfOID); |
||
444 | |||
445 | (* Remove forward reference in parent OID *) |
||
743 | daniel-mar | 446 | (* (this is the most important part) *) |
745 | daniel-mar | 447 | filenameParent := selfOID^.ParentFileId + OID_EXTENSION; |
740 | daniel-mar | 448 | if FileExists(filenameParent) then |
733 | daniel-mar | 449 | begin |
740 | daniel-mar | 450 | CreateOidDef(parentOID); |
743 | daniel-mar | 451 | if _ReadOidFile(filenameParent, parentOID, true) then |
740 | daniel-mar | 452 | begin |
743 | daniel-mar | 453 | if ListDeleteElementByValue(parentOID^.SubIds, selfOID^.FileId + selfOID^.DotNotation) then |
454 | begin |
||
455 | _WriteOidFile(filenameParent, parentOID, true); |
||
456 | end; |
||
740 | daniel-mar | 457 | end; |
458 | FreeOidDef(parentOID); |
||
733 | daniel-mar | 459 | end; |
460 | |||
461 | (* Delete own file *) |
||
744 | daniel-mar | 462 | filenameSelf := selfOID^.FileId + OID_EXTENSION; |
740 | daniel-mar | 463 | if FileExists(filenameSelf) then |
464 | begin |
||
465 | DeleteFile(filenameSelf); |
||
466 | end; |
||
733 | daniel-mar | 467 | end; |
468 | |||
735 | daniel-mar | 469 | function _DeleteConfirmation: boolean; |
470 | var |
||
471 | sc: Char; |
||
472 | begin |
||
473 | repeat |
||
474 | ShowMessage('Are you sure you want to delete this OID? (Y/N)', 'DELETE OID', true); |
||
737 | daniel-mar | 475 | DrawStatusBar('Y=Yes, N=No'); |
735 | daniel-mar | 476 | |
746 | daniel-mar | 477 | CursorOn; |
735 | daniel-mar | 478 | sc := ReadKey; |
746 | daniel-mar | 479 | CursorOff; |
735 | daniel-mar | 480 | if sc = #0 then |
481 | begin |
||
482 | (* Extended key. Nothing we care about. *) |
||
483 | ReadKey; |
||
484 | continue; |
||
485 | end; |
||
486 | |||
487 | if UpCase(sc) = 'Y' then |
||
488 | begin |
||
489 | _DeleteConfirmation := true; |
||
490 | break; |
||
737 | daniel-mar | 491 | end |
492 | else if UpCase(sc) = 'N' then |
||
735 | daniel-mar | 493 | begin |
494 | _DeleteConfirmation := false; |
||
495 | break; |
||
496 | end; |
||
497 | until false; |
||
498 | end; |
||
499 | |||
737 | daniel-mar | 500 | procedure _DrawOidTitleBar(filename: string; oid: POID); |
501 | begin |
||
502 | if oid^.DotNotation = '' then |
||
738 | daniel-mar | 503 | DrawTitleBar('OID ROOT', TITLEBAR_LEFT_TEXT, filename) |
737 | daniel-mar | 504 | else |
738 | daniel-mar | 505 | DrawTitleBar('OID ' + oid^.DotNotation, TITLEBAR_LEFT_TEXT, filename); |
737 | daniel-mar | 506 | end; |
507 | |||
733 | daniel-mar | 508 | procedure DisplayOIDFile(filename: string); |
509 | var |
||
510 | isRoot: boolean; |
||
740 | daniel-mar | 511 | oid, tmpOID: POID; |
733 | daniel-mar | 512 | i, menuX, menuY: integer; |
513 | linesLeft, linesRequired: integer; |
||
514 | sTmp, subfile: string; |
||
515 | subsel, subfiles: PStringList; |
||
516 | subselres: integer; |
||
735 | daniel-mar | 517 | exitRequest: boolean; |
518 | menuIdExit, menuIdAsnEdit, menuIdDescEdit, menuIdAdd, menuIdDelete: integer; |
||
733 | daniel-mar | 519 | begin |
735 | daniel-mar | 520 | exitRequest := false; |
733 | daniel-mar | 521 | repeat |
743 | daniel-mar | 522 | CreateOidDef(oid); |
523 | |||
524 | if not _ReadOidFile(filename, oid, true) then |
||
740 | daniel-mar | 525 | begin |
743 | daniel-mar | 526 | FreeOidDef(oid); |
740 | daniel-mar | 527 | exit; |
528 | end; |
||
529 | |||
733 | daniel-mar | 530 | (* Print OID information *) |
531 | |||
532 | ClrScr; |
||
737 | daniel-mar | 533 | _DrawOidTitleBar(filename, oid); |
733 | daniel-mar | 534 | DrawStatusBar(DEFAULT_STATUSBAR); |
535 | GotoXY(1,2); |
||
536 | |||
735 | daniel-mar | 537 | if oid^.DotNotation <> '' then |
733 | daniel-mar | 538 | begin |
539 | WriteLn('Dot-Notation:'); |
||
735 | daniel-mar | 540 | WriteLn(oid^.DotNotation); |
733 | daniel-mar | 541 | WriteLn(''); |
542 | end; |
||
543 | |||
735 | daniel-mar | 544 | if Trim(oid^.Description) <> '' then |
733 | daniel-mar | 545 | begin |
546 | WriteLn('Description:'); |
||
735 | daniel-mar | 547 | WriteLn(oid^.Description); |
733 | daniel-mar | 548 | WriteLn(''); |
549 | end; |
||
550 | |||
551 | menuX := WhereX + 1; |
||
735 | daniel-mar | 552 | menuY := ScreenHeight - ACTIONMENU_SIZE - 1; |
733 | daniel-mar | 553 | |
735 | daniel-mar | 554 | if ListCount(oid^.ASNIDs) > 0 then |
733 | daniel-mar | 555 | begin |
556 | linesLeft := menuY - WhereY - 1; |
||
735 | daniel-mar | 557 | linesRequired := 1 + ListCount(oid^.ASNIds); |
733 | daniel-mar | 558 | |
559 | if LinesLeft < LinesRequired then |
||
560 | begin |
||
561 | (* Compact display of ASN.1 identifiers *) |
||
562 | Write('ASN.1-Identifiers: '); |
||
735 | daniel-mar | 563 | for i := 0 to ListCount(oid^.ASNIds)-1 do |
733 | daniel-mar | 564 | begin |
565 | if i > 0 then Write(', '); |
||
735 | daniel-mar | 566 | Write(ListGetElement(oid^.ASNIds, i)); |
733 | daniel-mar | 567 | end; |
568 | WriteLn(''); |
||
569 | end |
||
570 | else |
||
571 | begin |
||
572 | (* Long display of ASN.1 identifiers *) |
||
573 | WriteLn('ASN.1-Identifiers:'); |
||
735 | daniel-mar | 574 | for i := 0 to ListCount(oid^.ASNIds)-1 do |
733 | daniel-mar | 575 | begin |
735 | daniel-mar | 576 | WriteLn('- '+ListGetElement(oid^.ASNIds, i)); |
733 | daniel-mar | 577 | end; |
578 | WriteLn(''); |
||
579 | end; |
||
580 | end; |
||
581 | |||
582 | (* Now prepare the menu entries *) |
||
583 | |||
744 | daniel-mar | 584 | CreateList(subsel); (* Contains the human-readable OID name *) |
737 | daniel-mar | 585 | CreateList(subfiles); (* Contains the file name *) |
733 | daniel-mar | 586 | |
745 | daniel-mar | 587 | if oid^.ParentFileId = '' then |
733 | daniel-mar | 588 | begin |
589 | isRoot := true; |
||
590 | end |
||
591 | else |
||
592 | begin |
||
745 | daniel-mar | 593 | isRoot := oid^.ParentDotNotation = oid^.DotNotation; |
733 | daniel-mar | 594 | end; |
595 | |||
745 | daniel-mar | 596 | if (oid^.ParentFileId <> '') and not isRoot then |
733 | daniel-mar | 597 | begin |
745 | daniel-mar | 598 | subfile := oid^.ParentFileId + OID_EXTENSION; |
740 | daniel-mar | 599 | if FileExists(subfile) then |
600 | begin |
||
601 | CreateOidDef(tmpOID); |
||
744 | daniel-mar | 602 | if not _ReadOidFile(subfile, tmpOID, true) then |
603 | begin |
||
745 | daniel-mar | 604 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + ' (READ ERROR)'); |
744 | daniel-mar | 605 | ListAppend(subfiles, 'ERROR: '+subfile+' Read error or file invalid'); |
606 | end |
||
743 | daniel-mar | 607 | else |
744 | daniel-mar | 608 | begin |
745 | daniel-mar | 609 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + _ShowASNIds(tmpOID)); |
744 | daniel-mar | 610 | ListAppend(subfiles, subfile); |
611 | end; |
||
740 | daniel-mar | 612 | FreeOidDef(tmpOID); |
613 | end |
||
614 | else |
||
615 | begin |
||
745 | daniel-mar | 616 | ListAppend(subsel, 'Go to parent ' + oid^.ParentDotNotation + ' (FILE NOT FOUND)'); |
744 | daniel-mar | 617 | ListAppend(subfiles, 'ERROR: File '+subfile+' was not found'); |
740 | daniel-mar | 618 | end; |
733 | daniel-mar | 619 | end; |
620 | |||
621 | if isRoot then |
||
622 | begin |
||
735 | daniel-mar | 623 | menuIdExit := ListAppend(subsel, 'Back to main menu'); |
624 | ListAppend(subfiles, ''); |
||
625 | end |
||
626 | else menuIdExit := -99; |
||
733 | daniel-mar | 627 | |
735 | daniel-mar | 628 | for i := 0 to ListCount(oid^.SubIds)-1 do |
733 | daniel-mar | 629 | begin |
735 | daniel-mar | 630 | sTmp := ListGetElement(oid^.SubIds, i); |
744 | daniel-mar | 631 | subfile := FileIdPart(sTmp) + OID_EXTENSION; |
740 | daniel-mar | 632 | if FileExists(subfile) then |
633 | begin |
||
634 | CreateOidDef(tmpOID); |
||
744 | daniel-mar | 635 | if not _ReadOidFile(subfile, tmpOID, true) then |
636 | begin |
||
637 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (READ ERROR)'); |
||
638 | ListAppend(subfiles, 'ERROR: Read error at file '+subfile+', or file is invalid.'); |
||
639 | end |
||
745 | daniel-mar | 640 | else if (tmpOID^.ParentFileId <> oid^.FileId) or |
641 | (tmpOID^.ParentDotNotation <> oid^.DotNotation) then |
||
744 | daniel-mar | 642 | begin |
643 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (BAD BACKREF)'); |
||
644 | ListAppend(subfiles, 'ERROR: File '+subfile+' has a wrong back-reference.'); |
||
645 | end |
||
743 | daniel-mar | 646 | else |
744 | daniel-mar | 647 | begin |
648 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + _ShowASNIds(tmpOID)); |
||
649 | ListAppend(subfiles, subfile); |
||
650 | end; |
||
740 | daniel-mar | 651 | FreeOidDef(tmpOID); |
652 | end |
||
653 | else |
||
654 | begin |
||
655 | ListAppend(subsel, 'Go to child ' + DotNotationPart(sTmp) + ' (FILE NOT FOUND)'); |
||
744 | daniel-mar | 656 | ListAppend(subfiles, 'ERROR: File '+subfile+' was not found'); |
740 | daniel-mar | 657 | end; |
733 | daniel-mar | 658 | end; |
659 | |||
735 | daniel-mar | 660 | if oid^.DotNotation <> '' then |
733 | daniel-mar | 661 | begin |
735 | daniel-mar | 662 | menuIdAsnEdit := ListAppend(subsel, 'Edit ASN.1 identifiers'); |
663 | ListAppend(subfiles, ''); |
||
664 | end |
||
665 | else menuIdAsnEdit := -99; |
||
733 | daniel-mar | 666 | |
735 | daniel-mar | 667 | menuIdDescEdit := ListAppend(subsel, 'Edit description'); |
668 | ListAppend(subfiles, ''); |
||
733 | daniel-mar | 669 | |
735 | daniel-mar | 670 | menuIdAdd := ListAppend(subsel, 'Add child'); |
671 | ListAppend(subfiles, ''); |
||
733 | daniel-mar | 672 | |
673 | if not isRoot then |
||
674 | begin |
||
735 | daniel-mar | 675 | menuIdDelete := ListAppend(subsel, 'Delete OID'); |
676 | ListAppend(subfiles, ''); |
||
677 | end |
||
678 | else menuIdDelete := -99; |
||
733 | daniel-mar | 679 | |
734 | daniel-mar | 680 | (* Show menu *) |
681 | |||
733 | daniel-mar | 682 | subselres := DrawSelectionList(menuX, menuY, |
683 | ScreenWidth-2, |
||
735 | daniel-mar | 684 | ACTIONMENU_SIZE, |
733 | daniel-mar | 685 | subsel, |
686 | true, |
||
687 | 'SELECT ACTION', |
||
688 | 1); |
||
734 | daniel-mar | 689 | |
690 | (* Process user selection *) |
||
691 | |||
733 | daniel-mar | 692 | if subselres = -1 then |
693 | begin |
||
735 | daniel-mar | 694 | exitRequest := true; |
733 | daniel-mar | 695 | end |
735 | daniel-mar | 696 | else if subselres = menuIdAsnEdit then |
733 | daniel-mar | 697 | begin |
735 | daniel-mar | 698 | if AsnEditor(oid) then |
743 | daniel-mar | 699 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 700 | end |
701 | else if subselres = menuIdDescEdit then |
||
702 | begin |
||
703 | if DescEditor(oid) then |
||
743 | daniel-mar | 704 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 705 | end |
706 | else if subselres = menuIdAdd then |
||
707 | begin |
||
708 | if NewOidEditor(oid) then |
||
743 | daniel-mar | 709 | _WriteOidFile(filename, oid, true); |
735 | daniel-mar | 710 | end |
711 | else if subselres = menuIdDelete then |
||
712 | begin |
||
713 | if _DeleteConfirmation then |
||
733 | daniel-mar | 714 | begin |
745 | daniel-mar | 715 | sTmp := oid^.ParentFileId + OID_EXTENSION; |
735 | daniel-mar | 716 | DeleteOidRecursive(oid); |
740 | daniel-mar | 717 | if FileExists(sTmp) then |
718 | begin |
||
719 | filename := sTmp; |
||
720 | end |
||
721 | else |
||
722 | begin |
||
744 | daniel-mar | 723 | ShowMessage('Parent file ' + sTmp + ' was not found', 'ERROR', true); |
740 | daniel-mar | 724 | _Pause; |
725 | exitRequest := true; |
||
726 | end; |
||
733 | daniel-mar | 727 | end; |
735 | daniel-mar | 728 | end |
729 | else if subselres = menuIdExit then |
||
730 | begin |
||
731 | exitRequest := true; |
||
732 | end |
||
733 | else |
||
734 | begin |
||
735 | (* Normal OID *) |
||
744 | daniel-mar | 736 | (* Above we already checked if the files are valild and existing *) |
740 | daniel-mar | 737 | sTmp := ListGetElement(subfiles, subselres); |
744 | daniel-mar | 738 | if Copy(sTmp, 1, Length('ERROR: ')) = 'ERROR: ' then |
740 | daniel-mar | 739 | begin |
744 | daniel-mar | 740 | Delete(sTmp, 1, Length('ERROR: ')); |
741 | ShowMessage(sTmp, 'ERROR', true); |
||
742 | _Pause; |
||
740 | daniel-mar | 743 | end |
744 | else |
||
745 | begin |
||
744 | daniel-mar | 746 | filename := sTmp; |
740 | daniel-mar | 747 | end; |
733 | daniel-mar | 748 | end; |
749 | FreeList(subsel); |
||
750 | FreeList(subfiles); |
||
751 | |||
735 | daniel-mar | 752 | FreeOidDef(oid); |
753 | until exitRequest; |
||
733 | daniel-mar | 754 | end; |
755 | |||
743 | daniel-mar | 756 | function CreateRootOIDFile(filename: string; ShowErrorMessage: boolean): boolean; |
733 | daniel-mar | 757 | var |
735 | daniel-mar | 758 | oid: POID; |
733 | daniel-mar | 759 | begin |
735 | daniel-mar | 760 | CreateOidDef(oid); |
745 | daniel-mar | 761 | oid^.Description := 'This is the root of the OID tree.' +#13#10 + |
762 | #13#10 + |
||
763 | 'Valid subsequent arcs are per definition:' + #13#10 + |
||
764 | '- 0 (itu-t)' + #13#10 + |
||
765 | '- 1 (iso)' + #13#10 + |
||
766 | '- 2 (joint-iso-itu-t)'; |
||
767 | oid^.FileId := ZeroPad(0, 8); |
||
768 | oid^.DotNotation := ''; |
||
769 | oid^.ParentFileId := ZeroPad(0, 8); |
||
770 | oid^.ParentDotNotation := ''; |
||
743 | daniel-mar | 771 | CreateRootOIDFile := _WriteOidFile(filename, oid, ShowErrorMessage); |
735 | daniel-mar | 772 | FreeOidDef(oid); |
733 | daniel-mar | 773 | end; |
774 | |||
742 | daniel-mar | 775 | function _GetRootFile(ShowErrorMessage: boolean): string; |
735 | daniel-mar | 776 | var |
742 | daniel-mar | 777 | rootFile: string; |
733 | daniel-mar | 778 | begin |
744 | daniel-mar | 779 | rootFile := ZeroPad(0, 8) + OID_EXTENSION; |
743 | daniel-mar | 780 | _GetRootFile := rootFile; |
742 | daniel-mar | 781 | if not FileExists(rootFile) then |
733 | daniel-mar | 782 | begin |
743 | daniel-mar | 783 | if not CreateRootOIDFile(rootFile, ShowErrorMessage) then |
742 | daniel-mar | 784 | begin |
743 | daniel-mar | 785 | _GetRootFile := ''; |
742 | daniel-mar | 786 | end; |
787 | end; |
||
733 | daniel-mar | 788 | end; |
789 | |||
740 | daniel-mar | 790 | procedure OP_ManageOIDs; |
742 | daniel-mar | 791 | var |
792 | rootfile: string; |
||
740 | daniel-mar | 793 | begin |
794 | ClrScr; |
||
795 | DrawTitleBar('Manage Object Identifiers', TITLEBAR_LEFT_TEXT, ''); |
||
796 | DrawStatusBar('Loading data... please wait...'); |
||
797 | |||
742 | daniel-mar | 798 | (* This will try creating a new root file if it does not exist *) |
799 | rootfile := _GetRootFile(true); |
||
800 | if rootfile = '' then Exit; |
||
801 | |||
802 | DisplayOIDFile(rootfile); |
||
740 | daniel-mar | 803 | end; |
804 | |||
733 | daniel-mar | 805 | procedure OP_ManageRAs; |
806 | begin |
||
807 | ClrScr; |
||
738 | daniel-mar | 808 | DrawTitleBar('Manage Registration Authorities', TITLEBAR_LEFT_TEXT, ''); |
733 | daniel-mar | 809 | DrawStatusBar(''); |
810 | |||
811 | (* TODO: Implement "Manage RAs" feature *) |
||
812 | end; |
||
813 | |||
814 | procedure OP_ReturnToMSDOS; |
||
815 | begin |
||
816 | ClrScr; |
||
743 | daniel-mar | 817 | TextBackground(Black); |
818 | TextColor(LightGray); |
||
746 | daniel-mar | 819 | ClrScr; (*Important, so that the DOS command prompt is also LightGray *) |
820 | |||
741 | daniel-mar | 821 | WriteLn('Thank you for using OIDplus for DOS.'); |
743 | daniel-mar | 822 | WriteLn(''); |
733 | daniel-mar | 823 | end; |
824 | |||
741 | daniel-mar | 825 | function _GetTreeViewLine(oid: POID; indent: integer): string; |
740 | daniel-mar | 826 | var |
827 | i: integer; |
||
828 | sTmp: string; |
||
829 | begin |
||
830 | (* Build line *) |
||
831 | sTmp := RepeatStr(' ', indent*TREEVIEW_INDENT); |
||
832 | if oid^.DotNotation = '' then |
||
833 | sTmp := sTmp + 'Object Identifiers' |
||
834 | else |
||
835 | sTmp := sTmp + oid^.DotNotation; |
||
836 | sTmp := sTmp + _ShowAsnIds(oid); |
||
837 | if TREEVIEW_INCLUDE_DESC then |
||
838 | begin |
||
839 | if Trim(oid^.Description) <> '' then |
||
840 | begin |
||
841 | sTmp := sTmp + ': ' + oid^.Description; |
||
842 | end; |
||
843 | end; |
||
844 | for i := 1 to Length(sTmp) do |
||
845 | begin |
||
846 | if (sTmp[i]=#13) or (sTmp[i]=#10) then sTmp[i] := ' '; |
||
847 | end; |
||
744 | daniel-mar | 848 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
741 | daniel-mar | 849 | _GetTreeViewLine := sTmp; |
740 | daniel-mar | 850 | end; |
851 | |||
852 | procedure _RecTreeExport(oid: POID; var F: Text; indent: integer); |
||
853 | var |
||
854 | i: integer; |
||
855 | sTmp: string; |
||
856 | suboid: POID; |
||
857 | childFilename: string; |
||
858 | begin |
||
741 | daniel-mar | 859 | sTmp := _GetTreeViewLine(oid, indent); |
740 | daniel-mar | 860 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
861 | WriteLn(F, sTmp); |
||
862 | |||
863 | (* Recursively call children *) |
||
864 | for i := 0 to ListCount(oid^.SubIds)-1 do |
||
865 | begin |
||
866 | sTmp := ListGetElement(oid^.SubIds, i); |
||
867 | CreateOidDef(suboid); |
||
744 | daniel-mar | 868 | childFilename := FileIdPart(sTmp) + OID_EXTENSION; |
743 | daniel-mar | 869 | if not FileExists(childFilename) then |
740 | daniel-mar | 870 | begin |
744 | daniel-mar | 871 | sTmp := 'ERROR: MISSING ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
743 | daniel-mar | 872 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
873 | WriteLn(F, sTmp); |
||
740 | daniel-mar | 874 | end |
743 | daniel-mar | 875 | else if not _ReadOidFile(childFilename, suboid, false) then |
740 | daniel-mar | 876 | begin |
744 | daniel-mar | 877 | sTmp := 'ERROR: READ ERROR AT ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
740 | daniel-mar | 878 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
879 | WriteLn(F, sTmp); |
||
743 | daniel-mar | 880 | end |
745 | daniel-mar | 881 | else if (suboid^.ParentFileId <> oid^.FileId) or |
882 | (suboid^.ParentDotNotation <> oid^.DotNotation) then |
||
744 | daniel-mar | 883 | begin |
884 | (* This can happen if a file is missing, and then another OID gets this filename since the number seems to be free *) |
||
885 | sTmp := 'ERROR: BAD BACKREF AT ' + childFilename + ' (SHALL CONTAIN ' + DotNotationPart(sTmp) + ')!'; |
||
886 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
||
887 | WriteLn(F, sTmp); |
||
888 | end |
||
743 | daniel-mar | 889 | else |
890 | begin |
||
891 | _RecTreeExport(suboid, F, indent+1); |
||
892 | FreeOidDef(suboid); |
||
893 | end |
||
740 | daniel-mar | 894 | end; |
895 | end; |
||
896 | |||
897 | procedure OP_TreeView; |
||
898 | var |
||
899 | F: Text; |
||
900 | rootoid: POID; |
||
742 | daniel-mar | 901 | rootfile: string; |
743 | daniel-mar | 902 | res: boolean; |
740 | daniel-mar | 903 | begin |
904 | ClrScr; |
||
905 | DrawTitleBar('TreeView Export', TITLEBAR_LEFT_TEXT, ''); |
||
906 | DrawStatusBar('Exporting data... please wait...'); |
||
907 | |||
742 | daniel-mar | 908 | (* This will try creating a new root file if it does not exist *) |
743 | daniel-mar | 909 | rootfile := _GetRootFile(true); |
910 | if rootfile = '' then |
||
911 | begin |
||
912 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
913 | Exit; |
||
914 | end; |
||
742 | daniel-mar | 915 | |
744 | daniel-mar | 916 | Assign(F, TREEVIEW_FILENAME); |
743 | daniel-mar | 917 | {$I-} |
740 | daniel-mar | 918 | Rewrite(F); |
743 | daniel-mar | 919 | {$I+} |
920 | if IoResult <> 0 then |
||
921 | begin |
||
922 | (* Can happen if disk is read-only (Runtime Error 150) *) |
||
744 | daniel-mar | 923 | ShowMessage('Cannot open '+TREEVIEW_FILENAME+' for writing.', 'ERROR', true); |
743 | daniel-mar | 924 | _Pause; |
925 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
926 | Exit; |
||
927 | end; |
||
740 | daniel-mar | 928 | |
743 | daniel-mar | 929 | res := false; |
740 | daniel-mar | 930 | CreateOidDef(rootoid); |
743 | daniel-mar | 931 | if _ReadOidFile(rootfile, rootoid, true) then |
932 | begin |
||
933 | _RecTreeExport(rootoid, F, 0); |
||
934 | res := true; |
||
935 | end; |
||
740 | daniel-mar | 936 | FreeOidDef(rootoid); |
937 | |||
743 | daniel-mar | 938 | Close(F); |
939 | |||
740 | daniel-mar | 940 | DrawStatusBar(DEFAULT_STATUSBAR); |
743 | daniel-mar | 941 | if res then |
942 | begin |
||
744 | daniel-mar | 943 | ShowMessage('TreeView successfully exported as '+TREEVIEW_FILENAME, 'TREEVIEW EXPORT', true); |
743 | daniel-mar | 944 | _Pause; |
945 | end; |
||
740 | daniel-mar | 946 | end; |
947 | |||
733 | daniel-mar | 948 | procedure OP_MainMenu; |
949 | var |
||
950 | menu: PStringList; |
||
951 | menuRes, menuLeft, menuTop: integer; |
||
740 | daniel-mar | 952 | menuIdOID, menuIdRA, menuIdTree, menuIdExit: integer; |
733 | daniel-mar | 953 | begin |
954 | repeat |
||
955 | ClrScr; |
||
956 | |||
738 | daniel-mar | 957 | DrawTitleBar('Welcome to OIDplus for DOS', '', ''); |
733 | daniel-mar | 958 | DrawStatusBar(DEFAULT_STATUSBAR); |
959 | GoToXY(ScreenWidth-Length(VERSIONINFO), ScreenHeight-1); |
||
960 | Write(VERSIONINFO); |
||
961 | |||
735 | daniel-mar | 962 | CreateList(menu); |
963 | |||
964 | menuIdOID := ListAppend(menu, 'Manage OIDs'); |
||
965 | menuIdRA := -99; (*ListAppend(menu, 'Manage RAs');*) |
||
740 | daniel-mar | 966 | menuIdTree := ListAppend(menu, 'Export TreeView'); |
735 | daniel-mar | 967 | menuIdExit := ListAppend(menu, 'Return to DOS'); |
968 | |||
969 | menuLeft := round(ScreenWidth/2 -MAINMENU_WIDTH/2); |
||
970 | menuTop := round(ScreenHeight/2-MAINMENU_HEIGHT/2); |
||
971 | menuRes := DrawSelectionList(menuLeft, menuTop, |
||
972 | MAINMENU_WIDTH, MAINMENU_HEIGHT, |
||
973 | menu, true, 'MAIN MENU', 2); |
||
733 | daniel-mar | 974 | FreeList(menu); |
975 | |||
735 | daniel-mar | 976 | if menuRes = menuIdOID then |
733 | daniel-mar | 977 | begin |
978 | OP_ManageOIDs; |
||
735 | daniel-mar | 979 | end |
980 | else if menuRes = menuIdRA then |
||
733 | daniel-mar | 981 | begin |
982 | OP_ManageRAs; |
||
740 | daniel-mar | 983 | end |
984 | else if menuRes = menuIdTree then |
||
985 | begin |
||
986 | OP_Treeview; |
||
733 | daniel-mar | 987 | end; |
735 | daniel-mar | 988 | until (menuRes = menuIdExit) or (MAINMENU_ALLOW_ESC and (menuRes = -1)); |
733 | daniel-mar | 989 | |
990 | OP_ReturnToMSDOS; |
||
991 | end; |
||
992 | |||
993 | begin |
||
746 | daniel-mar | 994 | InitVideo; (* sets ScreenWidth and ScreenHeight *) |
995 | CursorOff; |
||
733 | daniel-mar | 996 | OP_MainMenu; |
746 | daniel-mar | 997 | DoneVideo; |
733 | daniel-mar | 998 | end. |