sortdemo.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. PROGRAM SortDemo;
  2. { Graphical demonstration of sorting algorithms (W. N~ker, 02/96) }
  3. { based on "Sortieren" of Purity #48 }
  4. {
  5. Translated to PCQ from Kick(Maxon) Pascal.
  6. Updated the source to 2.0+.
  7. Now uses GadTools for menus.
  8. Added CloseWindowSafely.
  9. Cleaned up the menuhandling.
  10. Added LockWinSize and RestoreWin, now the
  11. window will be locked on showtime.
  12. The German text was translated to English
  13. by Andreas Neumann, thanks Andreas.
  14. Jun 03 1998.
  15. Translated to FPC Pascal.
  16. Removed CloseWindowSafely, have do add
  17. that procedure to Intuition.
  18. Fixed a bug, when you halt the show the
  19. window stayed locked.
  20. Aug 23 1998.
  21. Added MessageBox for report.
  22. 31 Jul 2000.
  23. Removed opening of graphics.library.
  24. 21 Mar 2001.
  25. Reworked to use systemvartags.
  26. 28 Nov 2002.
  27. [email protected]
  28. One last remark, the heapsort can't be stoped
  29. so you have to wait until it's finished.
  30. }
  31. uses Exec, Intuition, Graphics, Utility, GadTools, msgbox,systemvartags;
  32. CONST
  33. vers : string = '$VER: SortDemo 1.3 ' + {$I %DATE%} + ' ' + {$I %TIME%}#0;
  34. nmax=2000;
  35. MinWinX = 80;
  36. MinWiny = 80;
  37. w : pWindow = Nil;
  38. s : pScreen = Nil;
  39. MenuStrip : pMenu = Nil;
  40. vi : Pointer = Nil;
  41. modenames : Array[0..7] of string[10] = (
  42. 'Heapsort',
  43. 'Shellsort',
  44. 'Pick out',
  45. 'Insert',
  46. 'Shakersort',
  47. 'Bubblesort',
  48. 'Quicksort',
  49. 'Mergesort');
  50. { The easiest way to use gadtoolsmenus in FPC is
  51. to have them as const types. No need to cast
  52. strings to PChar. That we have to use recordmembers
  53. name is a pain.
  54. }
  55. nm : array[0..21] of tNewMenu = (
  56. (nm_Type: NM_TITLE; nm_Label: 'Demo';nm_CommKey: NIL; nm_Flags: 0;
  57. nm_MutualExclude: 0; nm_UserData: NIL),
  58. (nm_Type: NM_ITEM; nm_Label: 'Start';nm_CommKey: 'S'; nm_Flags: 0;
  59. nm_MutualExclude: 0; nm_UserData: NIL),
  60. (nm_Type: NM_ITEM; nm_Label: 'Stop';nm_CommKey: 'H'; nm_Flags: 0;
  61. nm_MutualExclude: 0; nm_UserData: NIL),
  62. { this will be a barlabel, have to set this one later }
  63. (nm_Type: NM_ITEM; nm_Label: NIL; nm_CommKey: NIL; nm_Flags: 0;
  64. nm_MutualExclude: 0; nm_UserData: NIL),
  65. (nm_Type: NM_ITEM; nm_Label: 'Quit'; nm_CommKey: 'Q'; nm_Flags: 0;
  66. nm_MutualExclude: 0; nm_UserData: NIL),
  67. (nm_Type: NM_TITLE; nm_Label: 'Algorithm'; nm_CommKey: NIL; nm_Flags: 0;
  68. nm_MutualExclude: 0; nm_UserData: NIL),
  69. (nm_Type: NM_ITEM; nm_Label: 'HeapSort'; nm_CommKey: '1'; nm_Flags:
  70. CHECKIT+CHECKED+MENUTOGGLE; nm_MutualExclude: 254; nm_UserData: NIL),
  71. (nm_Type: NM_ITEM; nm_Label: 'ShellSort'; nm_CommKey: '2'; nm_Flags:
  72. CHECKIT+MENUTOGGLE; nm_MutualExclude: 253; nm_UserData: NIL),
  73. (nm_Type: NM_ITEM; nm_Label: 'Pick out'; nm_CommKey: '3'; nm_Flags:
  74. CHECKIT+MENUTOGGLE; nm_MutualExclude: 251; nm_UserData: NIL),
  75. (nm_Type: NM_ITEM; nm_Label: 'Insert'; nm_CommKey: '4'; nm_Flags:
  76. CHECKIT+MENUTOGGLE; nm_MutualExclude: 247; nm_UserData: NIL),
  77. (nm_Type: NM_ITEM; nm_Label: 'ShakerSort'; nm_CommKey: '5'; nm_Flags:
  78. CHECKIT+MENUTOGGLE; nm_MutualExclude: 239; nm_UserData: NIL),
  79. (nm_Type: NM_ITEM; nm_Label: 'BubbleSort'; nm_CommKey: '6'; nm_Flags:
  80. CHECKIT+MENUTOGGLE; nm_MutualExclude: 223; nm_UserData: NIL),
  81. (nm_Type: NM_ITEM; nm_Label: 'QuickSort'; nm_CommKey: '7'; nm_Flags:
  82. CHECKIT+MENUTOGGLE; nm_MutualExclude: 191; nm_UserData: NIL),
  83. (nm_Type: NM_ITEM; nm_Label: 'MergeSort'; nm_CommKey: '8'; nm_Flags:
  84. CHECKIT+MENUTOGGLE; nm_MutualExclude: 127; nm_UserData: NIL),
  85. (nm_Type: NM_TITLE; nm_Label: 'Preferences'; nm_CommKey: NIL; nm_Flags: 0;
  86. nm_MutualExclude: 0; nm_UserData: NIL),
  87. (nm_Type: NM_ITEM; nm_Label: 'Data'; nm_CommKey: NIL; nm_Flags: 0;
  88. nm_MutualExclude: 0; nm_UserData: NIL),
  89. (nm_Type: NM_SUB; nm_Label: 'Random'; nm_CommKey: 'R'; nm_Flags:
  90. CHECKIT+CHECKED+MENUTOGGLE; nm_MutualExclude: 2; nm_UserData: NIL),
  91. (nm_Type: NM_SUB; nm_Label: 'Malicious'; nm_CommKey: 'M'; nm_Flags:
  92. CHECKIT+MENUTOGGLE; nm_MutualExclude: 1; nm_UserData: NIL),
  93. (nm_Type: NM_ITEM; nm_Label: 'Diagram'; nm_CommKey: NIL; nm_Flags: 0;
  94. nm_MutualExclude: 0; nm_UserData: NIL),
  95. (nm_Type: NM_SUB; nm_Label: 'Needles'; nm_CommKey: 'N'; nm_Flags:
  96. CHECKIT+CHECKED+MENUTOGGLE; nm_MutualExclude: 2; nm_UserData: NIL),
  97. (nm_Type: NM_SUB; nm_Label: 'Dots'; nm_CommKey: 'D'; nm_Flags:
  98. CHECKIT+MENUTOGGLE; nm_MutualExclude: 1; nm_UserData: NIL),
  99. (nm_Type: NM_END; nm_Label: NIL; nm_CommKey: NIL; nm_Flags:
  100. 0;nm_MutualExclude:0;nm_UserData:NIL));
  101. VAR sort: ARRAY[1..nmax] OF Real;
  102. sort2: ARRAY[1..nmax] OF Real; { for dumb Mergesort %-( }
  103. num,range,modus : Integer;
  104. rndom,needles : Boolean;
  105. Rast : pRastPort;
  106. QuitStopDie : Boolean;
  107. Msg : pMessage;
  108. wintitle : string[80];
  109. scrtitle : string[80];
  110. Procedure CleanUp(s : string; err : Integer);
  111. begin
  112. if assigned(MenuStrip) then begin
  113. ClearMenuStrip(w);
  114. FreeMenus(MenuStrip);
  115. end;
  116. if assigned(vi) then FreeVisualInfo(vi);
  117. if assigned(w) then CloseWindow(w);
  118. if s <> '' then MessageBox('SortDemo Report',s,'OK');
  119. Halt(err);
  120. end;
  121. Procedure RestoreWin;
  122. var
  123. dummy : Boolean;
  124. begin
  125. dummy := WindowLimits(w,MinWinX,MinWinY,-1,-1);
  126. end;
  127. Procedure LockWinSize(x,y,x2,y2 : Integer);
  128. var
  129. dummy : Boolean;
  130. begin
  131. dummy := WindowLimits(w,x,y,x2,y2);
  132. end;
  133. FUNCTION cancel: Boolean;
  134. { checked while sorting }
  135. VAR m,i,s: Integer;
  136. result : boolean;
  137. IM : pIntuiMessage;
  138. BEGIN
  139. result := False;
  140. IM := pIntuiMessage(GetMsg(w^.UserPort));
  141. IF IM<>Nil THEN BEGIN
  142. IF IM^.IClass=IDCMP_CLOSEWINDOW THEN
  143. result := True; { Close-Gadget }
  144. IF IM^.IClass=IDCMP_MENUPICK THEN BEGIN
  145. m := IM^.Code AND $1F;
  146. i := (IM^.Code SHR 5) AND $3F;
  147. s := (IM^.Code SHR 11) AND $1F;
  148. IF (m=0) AND (i=1) THEN result := True; { Menu item "Stop" }
  149. END;
  150. ReplyMsg(pMessage(Msg));
  151. END;
  152. cancel := result;
  153. END;
  154. PROCEDURE showstack(size: Integer);
  155. { little diagram showing the depth of Quicksort's recursion :-) }
  156. BEGIN
  157. SetAPen(Rast,2); IF size>0 THEN RectFill(Rast,0,0,3,size-1);
  158. SetAPen(Rast,0); RectFill(Rast,0,size,3,size);
  159. END;
  160. PROCEDURE setpixel(i: Integer);
  161. BEGIN
  162. SetAPen(Rast,1);
  163. IF needles THEN BEGIN
  164. Move(Rast,i,range); Draw(Rast,i,Round((1-sort[i])*range));
  165. END ELSE
  166. IF WritePixel(Rast,i,Round((1-sort[i])*range))=0 THEN;
  167. END;
  168. PROCEDURE clearpixel(i: Integer);
  169. BEGIN
  170. SetAPen(Rast,0);
  171. IF needles THEN BEGIN
  172. Move(Rast,i,range); Draw(Rast,i,Round((1-sort[i])*range));
  173. END ELSE
  174. IF WritePixel(Rast,i,Round((1-sort[i])*range))=0 THEN;
  175. END;
  176. procedure Exchange(var first,second : real);
  177. var
  178. temp : real;
  179. begin
  180. temp := first;
  181. first := second;
  182. second := temp;
  183. end;
  184. PROCEDURE swapit(i,j: integer);
  185. BEGIN
  186. clearpixel(i); clearpixel(j);
  187. Exchange(sort[i],sort[j]);
  188. setpixel(i); setpixel(j);
  189. END;
  190. FUNCTION descending(i,j: Integer): Boolean;
  191. BEGIN
  192. descending := sort[i]>sort[j];
  193. END;
  194. Function IntToStr (I : Longint) : String;
  195. Var S : String;
  196. begin
  197. Str (I,S);
  198. IntToStr:=S;
  199. end;
  200. PROCEDURE settitles(time: Longint);
  201. VAR
  202. s : string[80];
  203. BEGIN
  204. s := modenames[modus];
  205. IF time=0 THEN
  206. wintitle := s + ' running ...'
  207. ELSE IF time < 0 then
  208. wintitle := '<- ' + IntToStr(num) + ' Data ->'
  209. ELSE
  210. wintitle := IntToStr(time) + ' Seconds';
  211. scrtitle := strpas(@vers[6]) + ' - ' + s;
  212. wintitle := wintitle + #0;
  213. scrtitle := scrtitle + #0;
  214. SetWindowTitles(w,@wintitle[1],@scrtitle[1]);
  215. END;
  216. PROCEDURE refresh;
  217. { react on new size of window/init data }
  218. VAR i: Integer;
  219. BEGIN
  220. num := w^.GZZWidth; IF num>nmax THEN num := nmax;
  221. range := w^.GZZHeight;
  222. settitles(-1);
  223. SetRast(Rast,0); { clear screen }
  224. FOR i := 1 TO num DO BEGIN
  225. IF rndom THEN sort[i] := Random { produces 0..1 }
  226. ELSE sort[i] := (num-i)/num;
  227. setpixel(i);
  228. END;
  229. END;
  230. { *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* }
  231. { *#*#*#*#*#*#*#*#*#*#*# The sorting algorithms! #*#*#*#*#*#*#*#*#*#*#*#* }
  232. { *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* }
  233. PROCEDURE bubblesort;
  234. { like the head of a beer, reaaal slow and easy-going }
  235. VAR i,j,max: Integer;
  236. BEGIN
  237. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  238. max := num;
  239. REPEAT
  240. j := 1;
  241. FOR i := 1 TO max-1 DO
  242. IF descending(i,i+1) THEN BEGIN
  243. swapit(i,i+1); j := i;
  244. END;
  245. max := j;
  246. UNTIL (max=1) OR cancel;
  247. RestoreWin;
  248. END;
  249. PROCEDURE shakersort;
  250. { interesting variant, but bubblesort still remains hopelessness }
  251. { (because it only compares and swaps immediate adjacent units) }
  252. VAR i,j,min,max: Integer;
  253. BEGIN
  254. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  255. min := 1;
  256. max := num;
  257. REPEAT
  258. j := min;
  259. FOR i := min TO max-1 DO
  260. IF descending(i,i+1) THEN BEGIN
  261. swapit(i,i+1); j := i;
  262. END;
  263. max := j;
  264. j := max;
  265. FOR i := max DOWNTO min+1 DO
  266. IF descending(i-1,i) THEN BEGIN
  267. swapit(i,i-1); j := i;
  268. END;
  269. min := j;
  270. UNTIL (max=min) OR cancel;
  271. RestoreWin;
  272. END;
  273. PROCEDURE e_sort;
  274. { Insert: a pretty human strategy }
  275. VAR i,j: Integer;
  276. BEGIN
  277. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  278. FOR i := 2 TO num DO BEGIN
  279. j := i;
  280. WHILE j>1 DO
  281. IF descending(j-1,j) THEN BEGIN
  282. swapit(j-1,j); Dec(j);
  283. END ELSE
  284. j := 1;
  285. IF cancel THEN begin
  286. RestoreWin;
  287. Exit;
  288. end;
  289. END;
  290. RestoreWin;
  291. END;
  292. PROCEDURE a_sort;
  293. { Pick out: Preparation is one half of a life }
  294. { Take a look at the ridiculous low percentage of successful comparisions: }
  295. { Although there are only n swaps, there are n^2/2 comparisions! }
  296. { Both is a record, one in a good sense, the other one in a bad sense. }
  297. VAR i,j,minpos: Integer;
  298. min: Real;
  299. BEGIN
  300. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  301. FOR i := 1 TO num-1 DO BEGIN
  302. minpos := i; min := sort[i];
  303. FOR j := i+1 TO num DO
  304. IF descending(minpos,j) THEN
  305. minpos := j;
  306. IF minpos<>i THEN swapit(i,minpos);
  307. IF cancel THEN begin
  308. RestoreWin;
  309. Exit;
  310. end;
  311. END;
  312. RestoreWin;
  313. END;
  314. PROCEDURE shellsort;
  315. { brilliant extension of E-Sort, stunning improvement of efficience }
  316. VAR i,j,gap: Integer;
  317. BEGIN
  318. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  319. gap := num DIV 2;
  320. REPEAT
  321. FOR i := 1+gap TO num DO BEGIN
  322. j := i;
  323. WHILE j>gap DO
  324. IF descending(j-gap,j) THEN BEGIN
  325. swapit(j,j-gap); j := j-gap;
  326. END ELSE
  327. j := 1;
  328. IF cancel THEN begin
  329. RestoreWin;
  330. Exit;
  331. end;
  332. END;
  333. gap := gap DIV 2;
  334. UNTIL gap=0;
  335. RestoreWin;
  336. END;
  337. PROCEDURE seepaway(i,max: Integer);
  338. { belongs to heapsort }
  339. VAR j: Integer;
  340. BEGIN
  341. j := 2*i;
  342. WHILE j<=max DO BEGIN
  343. IF j<max THEN IF descending(j+1,j) THEN
  344. Inc(j);
  345. IF descending(j,i) THEN BEGIN
  346. swapit(j,i);
  347. i := j; j := 2*i;
  348. END ELSE
  349. j := max+1; { cancels }
  350. END;
  351. END;
  352. PROCEDURE heapsort;
  353. { this genius rules over the chaos: it's the best algorithm, I know about }
  354. { The only disadvantage compared with shellsort: it's not easy to understand }
  355. { and impossible to know it by heart. }
  356. VAR i,j: Integer;
  357. BEGIN
  358. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  359. i := num DIV 2 + 1;
  360. j := num;
  361. WHILE i>1 DO BEGIN
  362. Dec(i); seepaway(i,j);
  363. END;
  364. WHILE j>1 DO BEGIN
  365. swapit(i,j);
  366. Dec(j); seepaway(i,j);
  367. END;
  368. RestoreWin;
  369. END;
  370. PROCEDURE quicksort;
  371. { "divide and rule": a classic, but recursive >>-( }
  372. { In this demonstration it is faster than heapsort, but does considerable }
  373. { more unsuccessful comparisions. }
  374. VAR stack: ARRAY[1..100] OF RECORD li,re: Integer; END;
  375. sp,l,r,m,i,j: Integer;
  376. BEGIN
  377. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  378. sp := 1; stack[1].li := 1; stack[1].re := num;
  379. REPEAT
  380. l := stack[sp].li; r := stack[sp].re; Dec(sp);
  381. showstack(sp);
  382. m := (l+r) DIV 2;
  383. i := l; j := r;
  384. REPEAT
  385. WHILE descending(m,i) DO Inc(i);
  386. WHILE descending(j,m) DO Dec(j);
  387. IF j>i THEN swapit(i,j);
  388. IF m=i THEN m := j ELSE IF m=j THEN m := i; { ahem ... }
  389. { This "Following" of the reference data is only required because }
  390. { I stubborn call the comparision function, and this one only gets }
  391. { indices on the values which have to be compared. }
  392. UNTIL i>=j;
  393. IF i>l THEN BEGIN
  394. Inc(sp); stack[sp].li := l; stack[sp].re := i; END;
  395. IF i+1<r THEN BEGIN
  396. Inc(sp); stack[sp].li := i+1; stack[sp].re := r; END;
  397. UNTIL (sp=0) OR cancel;
  398. RestoreWin;
  399. END;
  400. PROCEDURE mergesort;
  401. { *the* algorithm for lists with pointers on it, for arrays rather }
  402. { inacceptable. The non.recursive implementation came out pretty more }
  403. { complicated than the one for quicksort, as quicksort first does }
  404. { something and then recurses; with mergesort it is the other way round. }
  405. VAR stack: ARRAY[1..100] OF RECORD li,re,mi: Integer; END;
  406. sp,l,r,i,j,k,m: Integer;
  407. BEGIN
  408. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  409. sp := 1; stack[1].li := 1; stack[1].re := num; stack[1].mi := 0;
  410. REPEAT
  411. l := stack[sp].li; r := stack[sp].re; m := stack[sp].mi; Dec(sp);
  412. showstack(sp);
  413. IF m>0 THEN BEGIN { put two halfs together }
  414. { Unfortunately it is only possible in an efficient way by using }
  415. { extra memory; mergesort really is something for lists with }
  416. { pointers originally ... }
  417. FOR i := m DOWNTO l do sort2[i] := sort[i]; i := l;
  418. FOR j := m+1 TO r DO sort2[r+m+1-j] := sort[j]; j := r;
  419. FOR k := l TO r DO BEGIN
  420. clearpixel(k);
  421. IF sort2[i]<sort2[j] THEN BEGIN
  422. sort[k] := sort2[i]; Inc(i);
  423. END ELSE BEGIN
  424. sort[k] := sort2[j]; Dec(j);
  425. END;
  426. setpixel(k);
  427. END;
  428. END ELSE IF l<r THEN BEGIN
  429. { create two halfs and the order to put them together }
  430. m := (l+r) DIV 2;
  431. Inc(sp); stack[sp].li := l; stack[sp].mi := m; stack[sp].re := r;
  432. Inc(sp); stack[sp].li := m+1; stack[sp].mi := 0; stack[sp].re := r;
  433. Inc(sp); stack[sp].li := l; stack[sp].mi := 0; stack[sp].re := m;
  434. END;
  435. UNTIL (sp=0) OR cancel;
  436. RestoreWin;
  437. END;
  438. Procedure OpenEverything;
  439. begin
  440. s := LockPubScreen(nil);
  441. if s = nil then CleanUp('Could not lock pubscreen',10);
  442. vi := GetVisualInfoA(s, NIL);
  443. if vi = nil then CleanUp('No visual info',10);
  444. w := OpenWindowTags(NIL, [
  445. WA_IDCMP, IDCMP_CLOSEWINDOW or IDCMP_MENUPICK or
  446. IDCMP_NEWSIZE,
  447. WA_Left, 0,
  448. WA_Top, s^.BarHeight+1,
  449. WA_Width, 224,
  450. WA_Height, s^.Height-(s^.BarHeight-1),
  451. WA_MinWidth, MinWinX,
  452. WA_MinHeight, MinWinY,
  453. WA_MaxWidth, -1,
  454. WA_MaxHeight, -1,
  455. WA_DepthGadget, ltrue,
  456. WA_DragBar, ltrue,
  457. WA_CloseGadget, ltrue,
  458. WA_SizeGadget, ltrue,
  459. WA_Activate, ltrue,
  460. WA_SizeBRight, ltrue,
  461. WA_GimmeZeroZero, ltrue,
  462. WA_PubScreen, s,
  463. TAG_END]);
  464. IF w=NIL THEN CleanUp('Could not open window',20);
  465. Rast := w^.RPort;
  466. { Here we set the barlabel }
  467. nm[3].nm_Label := PChar(NM_BARLABEL);
  468. if pExecBase(_ExecBase)^.LibNode.Lib_Version >= 39 then begin
  469. MenuStrip := CreateMenus(@nm,[
  470. GTMN_FrontPen, 1, TAG_END]);
  471. end else MenuStrip := CreateMenusA(@nm,NIL);
  472. if MenuStrip = nil then CleanUp('Could not open Menus',10);
  473. if LayoutMenusA(MenuStrip,vi,NIL)=false then
  474. CleanUp('Could not layout Menus',10);
  475. if SetMenuStrip(w, MenuStrip) = false then
  476. CleanUp('Could not set the Menus',10);
  477. end;
  478. PROCEDURE ProcessIDCMP;
  479. VAR
  480. IMessage : tIntuiMessage;
  481. IPtr : pIntuiMessage;
  482. Procedure ProcessMenu;
  483. var
  484. MenuNumber : Integer;
  485. ItemNumber : Integer;
  486. SubItemNumber : Integer;
  487. t0,t1,l : Longint;
  488. begin
  489. if IMessage.Code = MENUNULL then
  490. Exit;
  491. MenuNumber := MenuNum(IMessage.Code);
  492. ItemNumber := ItemNum(IMessage.Code);
  493. SubItemNumber := SubNum(IMessage.Code);
  494. case MenuNumber of
  495. 0 : begin
  496. case ItemNumber of
  497. 0 : begin
  498. refresh;
  499. settitles(0);
  500. CurrentTime(t0,l);
  501. CASE modus OF
  502. 0: heapsort;
  503. 1: shellsort;
  504. 2: a_sort;
  505. 3: e_sort;
  506. 4: shakersort;
  507. 5: bubblesort;
  508. 6: quicksort;
  509. 7: mergesort;
  510. END;
  511. CurrentTime(t1,l);
  512. settitles(t1-t0);
  513. end;
  514. 3 : QuitStopDie := True;
  515. end;
  516. end;
  517. 1 : begin
  518. case ItemNumber of
  519. 0..7 : modus := ItemNumber;
  520. end;
  521. settitles(-1);
  522. end;
  523. 2 : begin
  524. case ItemNumber of
  525. 0 : begin
  526. case SubItemNumber of
  527. 0 : if not rndom then rndom := true;
  528. 1 : if rndom then rndom := false;
  529. end;
  530. end;
  531. 1 : begin
  532. case SubItemNumber of
  533. 0 : if not needles then needles := true;
  534. 1 : if needles then needles := false;
  535. end;
  536. end;
  537. end;
  538. end;
  539. end;
  540. end;
  541. begin
  542. IPtr := pIntuiMessage(Msg);
  543. IMessage := IPtr^;
  544. ReplyMsg(Msg);
  545. case IMessage.IClass of
  546. IDCMP_MENUPICK : ProcessMenu;
  547. IDCMP_NEWSIZE : refresh;
  548. IDCMP_CLOSEWINDOW : QuitStopDie := True;
  549. end;
  550. end;
  551. begin
  552. OpenEverything;
  553. QuitStopDie := False;
  554. modus := 0;
  555. needles := true;
  556. rndom := true;
  557. refresh;
  558. repeat
  559. Msg := WaitPort(w^.UserPort);
  560. Msg := GetMsg(w^.UserPort);
  561. ProcessIDCMP;
  562. until QuitStopDie;
  563. CleanUp('',0);
  564. end.