nuttest.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. Program nuttest;
  2. {$if not defined(netware)}
  3. {$error Sorry, this Demo is for netware and netwlibc only}
  4. {$endif}
  5. {$mode objfpc}
  6. {$if defined (netware_libc)}
  7. {$description FreePascal NUT Demo - libc}
  8. {$Screenname FreePascal NWSNUT Demo - libc}
  9. {$else}
  10. {$description FreePascal NUT Demo - clib}
  11. {$Screenname default}
  12. {$endif}
  13. {$Copyright 2005 Armin Diehl <[email protected]>}
  14. {$Version 1,0,0}
  15. {$if defined(netware_clib)}
  16. uses nwserv,nwsnut,sysutils;
  17. {$else}
  18. uses libc,nwsnut,sysutils;
  19. {$endif}
  20. var
  21. gExiting : boolean = FALSE;
  22. gThreadCount : integer = 0;
  23. gNUTHandle : PNUTInfo = NIL;
  24. const
  25. gMyName = 'NUT Demo';
  26. gMessageTable : array [0..26] of pchar = (
  27. gMyName,
  28. '1.00',
  29. 'Exit NUT Demo?',
  30. 'NUT Demo',
  31. 'NUTDEMO Tag',
  32. 'Main Menu',
  33. 'Sub-menu option #1',
  34. 'Unsorted Sub-menu Example',
  35. 'Program Trace Portal',
  36. 'Bobby',
  37. 'Sub-menu option #2',
  38. 'Sub-Menu',
  39. 'Bravo',
  40. 'Tango',
  41. 'Alpha',
  42. 'Zulu',
  43. 'Unsorted Menu',
  44. 'Sorted List',
  45. 'Sub-menu Example',
  46. 'Item List Example',
  47. 'Form Example',
  48. 'Menu In Form',
  49. 'Option 1',
  50. 'Option 2',
  51. 'Save Data?',
  52. 'Edit String Example',
  53. 'Edit Text Exampl');
  54. // keep in sync with above...
  55. PROGRAM_NAME = $0000;
  56. PROGRAM_VERSION = $0001;
  57. PROGRAM_EXIT = $0002;
  58. SCREEN_NAME = $0003;
  59. RS_TAG_NAME = $0004;
  60. MENU_MAIN__HDR = $0005;
  61. MENU_SUB_OPTION1 = $0006;
  62. MENU_MAIN_NOSORT = $0007;
  63. TRACE_PORTAL__HDR = $0008;
  64. MENU_NOSORT_OPTION_A = $0009;
  65. MENU_SUB_OPTION2 = $000A;
  66. MENU_SUB__HDR = $000B;
  67. MENU_NOSORT_OPTION_B = $000C;
  68. MENU_NOSORT_OPTION_C = $000D;
  69. MENU_NOSORT_OPTION_D = $000E;
  70. MENU_NOSORT_OPTION_E = $000F;
  71. MENU_NOSORT__HDR = $0010;
  72. LIST_SUBLIST__HDR = $0011;
  73. MENU_MAIN_SUBMENU = $0012;
  74. MENU_MAIN_LIST = $0013;
  75. MENU_MAIN_FORM = $0014;
  76. MENU_IN_FORM_TITLE = $0015;
  77. FORM_MENU_OPT1 = $0016;
  78. FORM_MENU_OPT2 = $0017;
  79. EXIT_FORM_MSG = $0018;
  80. MENU_MAIN_EDIT_STRING = $0019;
  81. MENU_MAIN_EDIT_TEXT = $001A;
  82. function NLM_VerifyProgramExit : longint; cdecl;
  83. var res : integer;
  84. begin
  85. res := NWSConfirm (PROGRAM_EXIT, // Header
  86. 0, // centerLine
  87. 0, // Center Column
  88. 1, // Default Choice
  89. nil, // Action Procedure
  90. gNUTHandle, // Handle
  91. nil); // Action Parameter
  92. // Escape(-1) means No(0).
  93. if (res = -1) then inc (res);
  94. Result := res;
  95. end;
  96. (****************************************************************************
  97. * Edit a string
  98. ****************************************************************************)
  99. procedure NLM_EditStringSub; cdecl;
  100. const
  101. maxLen = 40;
  102. var err : integer;
  103. str : ansistring;
  104. begin
  105. //------------------------------------------------------------------------
  106. // Generate dynamic messages - this allows you to call NUT functions
  107. // and specify messages on the fly
  108. //*/
  109. NWSSetDynamicMessage(DYNAMIC_MESSAGE_ONE, 'String Edit Function',gNUTHandle^.messages);
  110. NWSSetDynamicMessage(DYNAMIC_MESSAGE_TWO, ' Editing can be fun: ',gNUTHandle^.messages);
  111. str := 'String to edit';
  112. setlength (str, maxLen);
  113. err := NWSEditString(
  114. 10, // center line
  115. 40, // center column
  116. 1, // edit height
  117. 40, // edit width
  118. DYNAMIC_MESSAGE_ONE, // header msg
  119. DYNAMIC_MESSAGE_TWO, // prompt msg
  120. pchar(str), // buffer
  121. maxLen, // max length of string
  122. EF_ANY OR EF_UPPER, // acceptable chars
  123. gNUTHandle, // nut handle
  124. nil, // insert-key procedure
  125. nil, // action procedure
  126. nil); // parameters
  127. // if escape key was pressed
  128. if (err = 1) then
  129. NWSTrace(gNUTHandle,'String was not saved');
  130. end;
  131. (****************************************************************************
  132. * Edit text in a window
  133. ****************************************************************************)
  134. procedure NLM_EditTextSub;
  135. const maxLen = 1024;
  136. var err : integer;
  137. str : ansistring;
  138. begin
  139. // Generate dynamic messages - this allows you to call NUT functions
  140. // and specify messages on the fly
  141. NWSSetDynamicMessage(DYNAMIC_MESSAGE_ONE,'Text Edit Function', gNUTHandle^.messages);
  142. NWSSetDynamicMessage(DYNAMIC_MESSAGE_TWO,'Save changes?', gNUTHandle^.messages);
  143. str := 'This could be any kind of text'#13'that you might have.';
  144. setlength (str,maxLen+1);
  145. // Edit the text in a portal with scroll bars that appear only when the
  146. // text goes beyond the portal bounderies
  147. err := NWSEditTextWithScrollBars (
  148. 10, // center line
  149. 40, // center column
  150. 4, // edit height
  151. 40, // edit width
  152. DYNAMIC_MESSAGE_ONE, // header msg
  153. pchar(str), // buffer
  154. maxLen, // max length of string
  155. DYNAMIC_MESSAGE_TWO, // confirm msg
  156. true, // force confirm
  157. SHOW_VERTICAL_SCROLL_BAR OR // // scroll bar props
  158. SHOW_HORIZONTAL_SCROLL_BAR OR
  159. CONSTANT_SCROLL_BARS,
  160. gNUTHandle);
  161. // escape key was pressed
  162. if err = 1 then
  163. NWSTrace(gNUTHandle,'Text was not saved');
  164. end;
  165. function NLM_FormMenuAction (option : longint; param : pointer):longint; cdecl;
  166. begin
  167. // Do anything that might be needed by the selection of a given menu option
  168. // and the value returned will indicate which data item is to be displayed
  169. // in the menu field on the form.
  170. result := option;
  171. end;
  172. function NLM_HotSpotAction (fp : PField; selectKey : longint; var changedField : longint; Handle : PNUTInfo) : longint; cdecl;
  173. begin
  174. // do the work here. . .
  175. NWSTrace(handle, 'This is your hot spot routine');
  176. result :=K_RIGHT; // send us to the next field...
  177. end;
  178. (****************************************************************************
  179. * Form display with various fields
  180. ****************************************************************************)
  181. procedure NLM_FormSub;
  182. var
  183. line,
  184. formSaved,
  185. menuChoice,
  186. myInteger,
  187. myHexInteger : longint;
  188. MyOtherInteger : cardinal;
  189. myBoolean : longbool;
  190. myString : ansistring;
  191. mfctl : PMFCONTROL;
  192. begin
  193. myInteger := 600;
  194. myHexInteger := $2ffc;
  195. myOtherInteger := 900;
  196. // Don't do this list if we should be exiting.
  197. if gExiting then exit;
  198. // At this point, the current list is the Main Menu. If we begin adding
  199. // new items to the current list, it would mess up the Main menu (to say
  200. // the least). So, we will save the Main Menu List on the List stack
  201. // (PushList) and then initialize a new form (set head and tail to NULL)
  202. // by calling NWSInitForm().
  203. NWSPushList(gNUTHandle);
  204. NWSInitForm(gNUTHandle);
  205. // Define the fields in the form
  206. line := 0;
  207. NWSAppendCommentField (line, 1, 'Boolean Field:', gNUTHandle);
  208. NWSAppendBoolField (line, 25, NORMAL_FIELD, myBoolean, 0, gNUTHandle);
  209. line += 2;
  210. NWSAppendCommentField (line, 1, 'Integer Field:', gNUTHandle);
  211. NWSAppendIntegerField (line, 25, NORMAL_FIELD, myInteger, 0, 9999, 0, gNUTHandle);
  212. line += 2;
  213. NWSAppendCommentField (line, 1, 'String Field:', gNUTHandle);
  214. myString := 'Data String';
  215. setLength (myString,30);
  216. NWSAppendStringField (line, 25, 30, NORMAL_FIELD, pchar(myString), 'A..Za..z ',0, gNUTHandle);
  217. line += 2;
  218. NWSAppendCommentField (line, 1, 'Unsigned Integer Field:', gNUTHandle);
  219. NWSAppendUnsignedIntegerField (line, 25, NORMAL_FIELD, @myOtherInteger, 0, 99999, 0, gNUTHandle);
  220. line += 2;
  221. NWSAppendCommentField (line, 1, 'Hex Field:', gNUTHandle);
  222. NWSAppendHexField (line, 25, NORMAL_FIELD, @myHexInteger, 0, 99999, 0, gNUTHandle);
  223. line += 2;
  224. NWSAppendCommentField (line, 1, 'Comment Field:', gNUTHandle);
  225. NWSAppendCommentField (line, 25, 'A comment', gNUTHandle);
  226. line += 2;
  227. NWSAppendCommentField (line, 1, 'Hot Spot Field:', gNUTHandle);
  228. NWSAppendHotSpotField (line, 25, NORMAL_FIELD, 'Hot Field', @NLM_HotSpotAction, gNUTHandle);
  229. mfctl := NWSInitMenuField (MENU_IN_FORM_TITLE, 10, 40, @NLM_FormMenuAction, gNUTHandle);
  230. NWSAppendToMenuField (mfctl, FORM_MENU_OPT1, 1, gNUTHandle);
  231. NWSAppendToMenuField (mfctl, FORM_MENU_OPT2, 2, gNUTHandle);
  232. menuChoice := 1; // display the text for option one
  233. line += 2;
  234. NWSAppendCommentField (line, 1, 'Menu Field:', gNUTHandle);
  235. NWSAppendMenuField (line, 25, NORMAL_FIELD, @menuChoice, mfctl, 0, gNUTHandle);
  236. // Edit the form
  237. formSaved := NWSEditPortalForm (
  238. MENU_MAIN_FORM, // I- header
  239. 11, // I- center line
  240. 40, // I- center col
  241. 16, // I- form height
  242. 50, // I- form width
  243. F_VERIFY, // I- ctl flags
  244. F_NO_HELP, // I- form help
  245. EXIT_FORM_MSG, // I- confirm msg
  246. gNUTHandle);
  247. // This function returns TRUE if the form was saved, FALSE if not.
  248. // If the form was not saved you must restore all variables to their
  249. // original values manually
  250. if longbool (formSaved) then
  251. NWSTrace(gNUTHandle,'The form data was not saved');
  252. // cleanup and discard this form
  253. NWSDestroyForm(gNUTHandle);
  254. NWSPopList(gNUTHandle);
  255. end;
  256. (****************************************************************************
  257. * Display information in a portal given a selection from the list
  258. ****************************************************************************)
  259. procedure NLM_DisplayPortalInformation (selectedItem : pchar);
  260. var
  261. portal : longint;
  262. szTemp : ansistring; //char szTemp[80+1];
  263. portalPCB : PPCB;
  264. begin
  265. // Dim the current portal
  266. NWSDeselectPortal(gNUTHandle);
  267. // Create a portal in which we will display the connection information.
  268. // (A portal is a window).
  269. portal := NWSCreatePortal(
  270. 5, // I- line
  271. 2, // I- column
  272. 10, // I- frameHeight
  273. 76, // I- frameWidth
  274. 6, // I- virtualHeight
  275. 76, // I- virtualWidth
  276. SAVE, // I- saveFlag
  277. selectedItem, // I- headerText
  278. VNORMAL, // I- headerAttribute
  279. SINGLE, // I- borderType
  280. VINTENSE, // I- borderAttribute
  281. CURSOR_OFF, // I- cursorFlag
  282. VIRTUAL, // I- directflag
  283. gNUTHandle);
  284. case cardinal(portal) of
  285. $FFFFFFFE : begin
  286. NWSTrace(gNUTHandle, 'NWSCreatePortal reports: Unable to allocate memory for PCB, virtual screen, or save area.');
  287. exit;
  288. end;
  289. $FFFFFFFF : begin
  290. NWSTrace(gNUTHandle, 'NWSCreatePortal reports: Maximum number of portals already defined.');
  291. exit;
  292. end;
  293. end;
  294. // Get portal's PCB.
  295. NWSGetPCB (portalPCB, portal, gNUTHandle);
  296. // Make our portal current and clear it.
  297. NWSSelectPortal(portal, gNUTHandle);
  298. NWSClearPortal(portalPCB);
  299. // Place information on portal.
  300. NWSDisplayTextInPortal(1,0,'This is data displayed in a portal',VINTENSE,portalPCB);
  301. szTemp := format ('Item selected: %s',[selectedItem]);
  302. NWSDisplayTextInPortal(3,0,pchar(szTemp),VNORMAL,portalPCB);
  303. NWSDisplayTextInPortal(5,0,'<Press ESCAPE to exit>',VINTENSE,portalPCB);
  304. // Update portal content to user screen.
  305. NWSUpdatePortal(portalPCB);
  306. // Wait for user to press ESCAPE.
  307. NWSWaitForEscape(gNUTHandle);
  308. // Trash portal.
  309. NWSDestroyPortal(portal, gNUTHandle);
  310. end;
  311. (****************************************************************************
  312. * Action procedure for the list
  313. ****************************************************************************)
  314. function NLM_ListSubAction (keyPressed : longint;
  315. elementSelected:PPLIST;
  316. itemLineNumber:plongint;
  317. actionParameter:pointer) : longint; cdecl;
  318. begin
  319. result := -1;
  320. case keyPressed of
  321. M_ESCAPE : result := 0;
  322. M_SELECT : begin
  323. NLM_DisplayPortalInformation(@elementSelected^^.text);
  324. result := -1;
  325. end;
  326. end;
  327. end;
  328. (****************************************************************************
  329. * Build a list of items
  330. ****************************************************************************)
  331. procedure NLM_ListSubBuild;
  332. var i : integer;
  333. s : ansistring;
  334. begin
  335. for i := 1 to 50 do
  336. begin
  337. s := format ('Item number %02d',[i]);
  338. NWSAppendToList (pchar(s),nil,gNUTHandle);
  339. end;
  340. end;
  341. (****************************************************************************
  342. * Create and display the list
  343. ****************************************************************************)
  344. procedure NLM_DisplaySubList;
  345. begin
  346. if gExiting then exit;
  347. // At this point, the current list is the Main Menu. If we begin adding
  348. // new items to the current list, it would mess up the Main menu (to say
  349. // the least). So, we will save the Main Menu List on the List stack
  350. // (PushList) and then initialize a new list (set head and tail to NULL)
  351. // by calling InitList(). Note that Lists use NWInitList() and Menus use
  352. // NWInitMenu().
  353. NWSPushList(gNUTHandle);
  354. NWSInitList(gNUTHandle, nil);
  355. // Build a list
  356. NLM_ListSubBuild;
  357. // Display the list and allow user interaction.
  358. NWSList(
  359. LIST_SUBLIST__HDR, // I- header
  360. 0, // I- centerLine
  361. 0, // I- centerColumn
  362. 10, // I- height
  363. 72, // I- width
  364. M_ESCAPE OR M_SELECT, // I- validKeyFlags
  365. nil, // IO element
  366. gNUTHandle, // I- handle
  367. nil, // I- formatProcedure
  368. @NLM_ListSubAction, // I- actionProcedure
  369. nil); // I- actionParameter
  370. // Before returning, we must free the list items allocated by
  371. // NLM_ListSubBuild...(). Then the Main Menu list context
  372. // must be restored. Note that Lists use NWDestroyList() and
  373. // Menus use NWDestroyMenu().
  374. NWSDestroyList(gNUTHandle);
  375. NWSPopList(gNUTHandle);
  376. end;
  377. (****************************************************************************
  378. * Unsorted sub-menu (NWSLIST) action procedure. Note that the parameters
  379. * for an NWSList() action procedure are very different from the parameters
  380. * passed to an NWSMenu() action procedure.
  381. ****************************************************************************)
  382. function NLM_MenuNoSortAct (keyPressed:longint; elementSelected:PPLIST; itemLineNumber:plongint; actionParameter:pointer):longint; cdecl;
  383. var index : integer;
  384. begin
  385. // Setup index variable to be the same as it would be in a NWSMenu()
  386. // action procedure.
  387. if keypressed = M_ESCAPE then
  388. index := -1
  389. else
  390. index := integer(elementSelected^^.otherInfo^);
  391. // Perform the user-selected action.
  392. // (Just like a normal NWSMenu() action procedure...)
  393. case index of
  394. -1: begin
  395. result := 0; exit;
  396. end;
  397. MENU_NOSORT_OPTION_A :
  398. NWSTrace(gNUTHandle,'Insert no-sort sub-menu option #A here.');
  399. MENU_NOSORT_OPTION_B :
  400. NWSTrace(gNUTHandle,'Insert no-sort sub-menu option #B here.');
  401. MENU_NOSORT_OPTION_C :
  402. NWSTrace(gNUTHandle,'Insert no-sort sub-menu option #C here.');
  403. MENU_NOSORT_OPTION_D :
  404. NWSTrace(gNUTHandle,'Insert no-sort sub-menu option #D here.');
  405. MENU_NOSORT_OPTION_E :
  406. NWSTrace(gNUTHandle,'Insert no-sort sub-menu option #E here.')
  407. else
  408. NWSTrace(gNUTHandle,pchar(format('Option %d not implemented.',[index])));
  409. end;
  410. // If we should be exiting, pretend that ESCAPE was pressed.
  411. if gExiting then
  412. result := 0
  413. else
  414. result := -1;
  415. end;
  416. (****************************************************************************
  417. * Unsorted sub-menu.
  418. *
  419. * There are times when you would like to display a menu, but you don't want
  420. * the elements to be sorted. NWSMenu() automatically sorts the list of menu
  421. * items and there is no way to disable this feature.
  422. *
  423. * The NWSList() function has an M_NO_SORT flag that is not available to the
  424. * NWSMenu() function; however, using NWSList to display a menu can be scary
  425. * if you don't know how.
  426. *
  427. * The following code demonstrates how to build a menu and then display it as
  428. * a list. The action procedure (above) is specific to NWSList() and is not
  429. * a suitable action procedure for NWSMenu().
  430. ***************************************************************************)
  431. procedure NLM_MenuNoSort;
  432. var defItem : PLIST;
  433. begin
  434. if gExiting then exit;
  435. // At this point, the current list is the Main Menu. If we begin adding
  436. // new items to the current list, it would mess up the Main menu (to say
  437. // the least). So, we will save the Main Menu List on the List stack
  438. // (PushList) and then initialize a new list (set head and tail to NULL)
  439. // by calling InitMenu(). Note that Lists use NWInitList() and Menus use
  440. // NWInitMenu().
  441. NWSPushList(gNUTHandle);
  442. NWSInitMenu(gNUTHandle);
  443. // Insert menu items in the order they will be displayed.
  444. NWSAppendToMenu(MENU_NOSORT_OPTION_B, MENU_NOSORT_OPTION_B, gNUTHandle);
  445. NWSAppendToMenu(MENU_NOSORT_OPTION_A, MENU_NOSORT_OPTION_A, gNUTHandle);
  446. defItem := NWSAppendToMenu(MENU_NOSORT_OPTION_C, MENU_NOSORT_OPTION_C, gNUTHandle);
  447. NWSAppendToMenu(MENU_NOSORT_OPTION_E, MENU_NOSORT_OPTION_E, gNUTHandle);
  448. NWSAppendToMenu(MENU_NOSORT_OPTION_D, MENU_NOSORT_OPTION_D, gNUTHandle);
  449. // Display the menu (as though it were a list) and allow user interaction.
  450. NWSList(
  451. MENU_NOSORT__HDR, // header
  452. 0, // centerLine
  453. 65, // centerColumn
  454. 5, // height
  455. 20, // width
  456. M_ESCAPE OR M_SELECT OR
  457. M_NO_SORT, // validKeyFlags
  458. @defItem, // element
  459. gNUTHandle, // handle
  460. nil, // formatProcedure
  461. @NLM_MenuNoSortAct, // actionProcedure
  462. nil); // actionParameter
  463. // Before returning, we must free the list items allocated by
  464. // NWSAppendToMenu(). Then the Main Menu list context must be restored.
  465. // Note that Lists use NWDestroyList() and Menus use NWDestroyMenu().
  466. NWSDestroyMenu(gNUTHandle);
  467. NWSPopList(gNUTHandle);
  468. end;
  469. (****************************************************************************
  470. * Sub menu (sorted) action procedure.
  471. ****************************************************************************)
  472. function NLM_MenuSubAction (index:longint; parm:pointer):longint; cdecl;
  473. begin
  474. // Perform the user-selected action.
  475. case index of
  476. -1 : begin
  477. result := 0; exit;
  478. end;
  479. MENU_SUB_OPTION1: NWSTrace(gNUTHandle,'Insert sub-menu option #1 here.');
  480. MENU_SUB_OPTION2: NWSTrace(gNUTHandle,'Insert sub-menu option #2 here.')
  481. else
  482. NWSTrace(gNUTHandle,'Option not implemented.');
  483. end;
  484. // If we should be exiting, pretend that ESCAPE was pressed.
  485. if gExiting then
  486. result := 0
  487. else
  488. result := -1;
  489. end;
  490. procedure NLM_MenuSub;
  491. begin
  492. if gExiting then exit;
  493. // At this point, the current list is the Main Menu. If we begin adding
  494. // new items to the current list, it would mess up the Main menu (to say
  495. // the least). So, we will save the Main Menu List on the List stack
  496. // (PushList) and then initialize a new list (set head and tail to NULL)
  497. // by calling InitMenu(). Note that Lists use NWInitList() and Menus use
  498. // NWInitMenu().
  499. NWSPushList(gNUTHandle);
  500. NWSInitMenu(gNUTHandle);
  501. // Insert menu items. Note that the insertion order does not matter being
  502. // that NWSMenu() will always sort the Menu selections automatically.
  503. NWSAppendToMenu(MENU_SUB_OPTION1, MENU_SUB_OPTION1, gNUTHandle);
  504. NWSAppendToMenu(MENU_SUB_OPTION2, MENU_SUB_OPTION2, gNUTHandle);
  505. // Display the menu and allow user interaction.
  506. NWSMenu(MENU_SUB__HDR, // Header
  507. 0, // centerLine
  508. 15, // centerColumn
  509. nil, // defaultElement
  510. @NLM_MenuSubAction, // actionProcedure
  511. gNUTHandle,
  512. nil); // actionParameter
  513. // Before returning, we must free the list items allocated by
  514. // NWSAppendToMenu(). Then the Main Menu list context must be restored.
  515. // Note that Lists use NWDestroyList() and Menus use NWDestroyMenu().
  516. NWSDestroyMenu(gNUTHandle);
  517. NWSPopList(gNUTHandle);
  518. end;
  519. function NLM_MenuMainAction (index:longint; parm:pointer):longint; cdecl;
  520. begin
  521. case index of
  522. -1: if longbool(NLM_VerifyProgramExit) then // ESC pressed
  523. begin
  524. result := 0;
  525. exit;
  526. end;
  527. MENU_MAIN_SUBMENU : NLM_MenuSub;
  528. MENU_MAIN_NOSORT : NLM_MenuNoSort;
  529. MENU_MAIN_LIST : NLM_DisplaySubList;
  530. MENU_MAIN_FORM : NLM_FormSub;
  531. MENU_MAIN_EDIT_STRING : NLM_EditStringSub;
  532. MENU_MAIN_EDIT_TEXT : NLM_EditTextSub
  533. else
  534. NWSTrace(gNUTHandle,'Option not implemented.');
  535. end;
  536. if gExiting then
  537. result := 0
  538. else
  539. result := -1;
  540. end;
  541. procedure DoMainMenu;
  542. var defaultOption : PLIST;
  543. begin
  544. if gExiting then exit;
  545. // At this point, the current list is uninitialized (being that it is the
  546. // first list of the program.) Before using the current list it must be
  547. // initialized (set head and tail to NULL) by calling InitMenu().
  548. // Note that Lists use NWInitList() and Menus use NWInitMenu().
  549. NWSInitMenu(gNUTHandle);
  550. // Insert menu items. Note that the insertion order does not matter being
  551. // that NWSMenu() will always sort the Menu selections automatically.
  552. // The defaultOption stores a pointer to the menu item which we wish to be
  553. // highlighed by default.
  554. NWSAppendToMenu(MENU_MAIN_SUBMENU, MENU_MAIN_SUBMENU, gNUTHandle);
  555. NWSAppendToMenu(MENU_MAIN_NOSORT, MENU_MAIN_NOSORT, gNUTHandle);
  556. NWSAppendToMenu(MENU_MAIN_LIST, MENU_MAIN_LIST, gNUTHandle);
  557. NWSAppendToMenu(MENU_MAIN_FORM, MENU_MAIN_FORM, gNUTHandle);
  558. defaultOption :=
  559. NWSAppendToMenu(MENU_MAIN_EDIT_STRING, MENU_MAIN_EDIT_STRING, gNUTHandle);
  560. NWSAppendToMenu(MENU_MAIN_EDIT_TEXT, MENU_MAIN_EDIT_TEXT, gNUTHandle);
  561. // Display the menu and allow user interaction.
  562. NWSMenu(MENU_MAIN__HDR, // Header
  563. 0, // centerLine
  564. 0, // centerColumn
  565. defaultOption, // defaultElement
  566. @NLM_MenuMainAction, // procedure to handle events
  567. gNUTHandle,
  568. nil); // actionParameter
  569. // Before returning, we must free the list items allocated by
  570. // NWSAppendToMenu(). Note that Lists use NWDestroyList() and Menus use
  571. // NWDestroyMenu().
  572. NWSDestroyMenu(gNUTHandle);
  573. end;
  574. procedure DeinitializeNUT;
  575. begin
  576. if gNUTHandle <> nil then
  577. NWSRestoreNut(gNUTHandle);
  578. end;
  579. var oldNetwareUnloadProc : pointer = nil;
  580. procedure onUnload;
  581. var i : integer;
  582. begin
  583. gExiting := TRUE;
  584. // Wait for main() to terminate.
  585. // If main() has not terminateded within a 1/2 second, ungetch an
  586. // escape key. This will "trick" a blocking NWSList() or NWSMenu()
  587. // function and wake it up.
  588. i := 0;
  589. while (gThreadCount > 0) do
  590. begin
  591. delay (100);
  592. inc(i);
  593. if i = 5 then
  594. ungetcharacter(ESCAPE);
  595. {$if defined (netware_libc)}
  596. pthread_yield;
  597. {$else}
  598. ThreadSwitchWithDelay;
  599. {$endif}
  600. end;
  601. System.NetwareUnloadProc := oldNetwareUnloadProc;
  602. end;
  603. procedure InitializeNUT;
  604. var err : integer;
  605. NLMHandle : TNLMHandle;
  606. screen : TScr;
  607. allocTag : TRtag;
  608. begin
  609. // use the SIGTERM handler defined in system.pp to facilitate a console UNLOAD command.
  610. oldNetwareUnloadProc := System.NetwareUnloadProc;
  611. NetwareUnloadProc := @onUnload;
  612. NLMHandle := getnlmhandle;
  613. {$if defined(netware_clib)}
  614. screen := CreateScreen ('FreePascal NWSNUT Demo - clib',AUTO_DESTROY_SCREEN);
  615. if screen <> nil then
  616. DisplayScreen (screen);
  617. {$else}
  618. screen := getscreenhandle();
  619. {$endif}
  620. if ((pointer(NLMHandle) = nil) or (pointer(screen) = nil)) then
  621. begin
  622. gExiting := TRUE;
  623. Exit;
  624. end;
  625. // Fire up NWSNUT on our screen which was set up via the linker. LibC
  626. // doesn't have a great deal of flexibility with screens. Setting up your
  627. // own, additional screen may prove challenging, however, it should be
  628. // possible.
  629. allocTag := AllocateResourceTag(NLMHandle, gMyName, AllocSignature);
  630. if pointer(allocTag) = nil then
  631. begin
  632. gExiting := TRUE;
  633. Exit;
  634. end;
  635. err := NWSInitializeNut(PROGRAM_NAME, PROGRAM_VERSION, NORMAL_HEADER,
  636. NUT_REVISION_LEVEL, gMessageTable, nil, screen, allocTag,
  637. gNUTHandle);
  638. if err <> 0 then
  639. gExiting := TRUE;
  640. end;
  641. begin
  642. inc (gThreadCount);
  643. InitializeNUT;
  644. DoMainMenu;
  645. DeinitializeNUT;
  646. dec (gThreadCount);
  647. end.