sortdemo.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  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, AGraphics, Utility, GadTools, amsgbox;
  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. GfxMove(Rast,i,range); Draw(Rast,i,Round((1-sort[i])*range));
  165. END ELSE
  166. WritePixel(Rast,i,Round((1-sort[i])*range))
  167. END;
  168. PROCEDURE clearpixel(i: Integer);
  169. BEGIN
  170. SetAPen(Rast,0);
  171. IF needles THEN BEGIN
  172. GfxMove(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
  225. BEGIN
  226. IF rndom THEN sort[i] := Random { produces 0..1 }
  227. ELSE sort[i] := (num-i)/num;
  228. setpixel(i);
  229. END;
  230. END;
  231. { *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* }
  232. { *#*#*#*#*#*#*#*#*#*#*# The sorting algorithms! #*#*#*#*#*#*#*#*#*#*#*#* }
  233. { *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* }
  234. PROCEDURE bubblesort;
  235. { like the head of a beer, reaaal slow and easy-going }
  236. VAR i,j,max: Integer;
  237. BEGIN
  238. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  239. max := num;
  240. REPEAT
  241. j := 1;
  242. FOR i := 1 TO max-1 DO
  243. IF descending(i,i+1) THEN BEGIN
  244. swapit(i,i+1); j := i;
  245. END;
  246. max := j;
  247. UNTIL (max=1) OR cancel;
  248. RestoreWin;
  249. END;
  250. PROCEDURE shakersort;
  251. { interesting variant, but bubblesort still remains hopelessness }
  252. { (because it only compares and swaps immediate adjacent units) }
  253. VAR i,j,min,max: Integer;
  254. BEGIN
  255. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  256. min := 1;
  257. max := num;
  258. REPEAT
  259. j := min;
  260. FOR i := min TO max-1 DO
  261. IF descending(i,i+1) THEN BEGIN
  262. swapit(i,i+1); j := i;
  263. END;
  264. max := j;
  265. j := max;
  266. FOR i := max DOWNTO min+1 DO
  267. IF descending(i-1,i) THEN BEGIN
  268. swapit(i,i-1); j := i;
  269. END;
  270. min := j;
  271. UNTIL (max=min) OR cancel;
  272. RestoreWin;
  273. END;
  274. PROCEDURE e_sort;
  275. { Insert: a pretty human strategy }
  276. VAR i,j: Integer;
  277. BEGIN
  278. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  279. FOR i := 2 TO num DO BEGIN
  280. j := i;
  281. WHILE j>1 DO
  282. IF descending(j-1,j) THEN BEGIN
  283. swapit(j-1,j); Dec(j);
  284. END ELSE
  285. j := 1;
  286. IF cancel THEN begin
  287. RestoreWin;
  288. Exit;
  289. end;
  290. END;
  291. RestoreWin;
  292. END;
  293. PROCEDURE a_sort;
  294. { Pick out: Preparation is one half of a life }
  295. { Take a look at the ridiculous low percentage of successful comparisions: }
  296. { Although there are only n swaps, there are n^2/2 comparisions! }
  297. { Both is a record, one in a good sense, the other one in a bad sense. }
  298. VAR i,j,minpos: Integer;
  299. min: Real;
  300. BEGIN
  301. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  302. FOR i := 1 TO num-1 DO BEGIN
  303. minpos := i; min := sort[i];
  304. FOR j := i+1 TO num DO
  305. IF descending(minpos,j) THEN
  306. minpos := j;
  307. IF minpos<>i THEN swapit(i,minpos);
  308. IF cancel THEN begin
  309. RestoreWin;
  310. Exit;
  311. end;
  312. END;
  313. RestoreWin;
  314. END;
  315. PROCEDURE shellsort;
  316. { brilliant extension of E-Sort, stunning improvement of efficience }
  317. VAR i,j,gap: Integer;
  318. BEGIN
  319. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  320. gap := num DIV 2;
  321. REPEAT
  322. FOR i := 1+gap TO num DO BEGIN
  323. j := i;
  324. WHILE j>gap DO
  325. IF descending(j-gap,j) THEN BEGIN
  326. swapit(j,j-gap); j := j-gap;
  327. END ELSE
  328. j := 1;
  329. IF cancel THEN begin
  330. RestoreWin;
  331. Exit;
  332. end;
  333. END;
  334. gap := gap DIV 2;
  335. UNTIL gap=0;
  336. RestoreWin;
  337. END;
  338. PROCEDURE seepaway(i,max: Integer);
  339. { belongs to heapsort }
  340. VAR j: Integer;
  341. BEGIN
  342. j := 2*i;
  343. WHILE j<=max DO BEGIN
  344. IF j<max THEN IF descending(j+1,j) THEN
  345. Inc(j);
  346. IF descending(j,i) THEN BEGIN
  347. swapit(j,i);
  348. i := j; j := 2*i;
  349. END ELSE
  350. j := max+1; { cancels }
  351. END;
  352. END;
  353. PROCEDURE heapsort;
  354. { this genius rules over the chaos: it's the best algorithm, I know about }
  355. { The only disadvantage compared with shellsort: it's not easy to understand }
  356. { and impossible to know it by heart. }
  357. VAR i,j: Integer;
  358. BEGIN
  359. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  360. i := num DIV 2 + 1;
  361. j := num;
  362. WHILE i>1 DO BEGIN
  363. Dec(i); seepaway(i,j);
  364. END;
  365. WHILE j>1 DO BEGIN
  366. swapit(i,j);
  367. Dec(j); seepaway(i,j);
  368. END;
  369. RestoreWin;
  370. END;
  371. PROCEDURE quicksort;
  372. { "divide and rule": a classic, but recursive >>-( }
  373. { In this demonstration it is faster than heapsort, but does considerable }
  374. { more unsuccessful comparisions. }
  375. VAR stack: ARRAY[1..100] OF RECORD li,re: Integer; END;
  376. sp,l,r,m,i,j: Integer;
  377. BEGIN
  378. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  379. sp := 1; stack[1].li := 1; stack[1].re := num;
  380. REPEAT
  381. l := stack[sp].li; r := stack[sp].re; Dec(sp);
  382. showstack(sp);
  383. m := (l+r) DIV 2;
  384. i := l; j := r;
  385. REPEAT
  386. WHILE descending(m,i) DO Inc(i);
  387. WHILE descending(j,m) DO Dec(j);
  388. IF j>i THEN swapit(i,j);
  389. IF m=i THEN m := j ELSE IF m=j THEN m := i; { ahem ... }
  390. { This "Following" of the reference data is only required because }
  391. { I stubborn call the comparision function, and this one only gets }
  392. { indices on the values which have to be compared. }
  393. UNTIL i>=j;
  394. IF i>l THEN BEGIN
  395. Inc(sp); stack[sp].li := l; stack[sp].re := i; END;
  396. IF i+1<r THEN BEGIN
  397. Inc(sp); stack[sp].li := i+1; stack[sp].re := r; END;
  398. UNTIL (sp=0) OR cancel;
  399. RestoreWin;
  400. END;
  401. PROCEDURE mergesort;
  402. { *the* algorithm for lists with pointers on it, for arrays rather }
  403. { inacceptable. The non.recursive implementation came out pretty more }
  404. { complicated than the one for quicksort, as quicksort first does }
  405. { something and then recurses; with mergesort it is the other way round. }
  406. VAR stack: ARRAY[1..100] OF RECORD li,re,mi: Integer; END;
  407. sp,l,r,i,j,k,m: Integer;
  408. BEGIN
  409. LockWinSize(w^.Width,w^.Height,w^.Width,w^.Height);
  410. sp := 1; stack[1].li := 1; stack[1].re := num; stack[1].mi := 0;
  411. REPEAT
  412. l := stack[sp].li; r := stack[sp].re; m := stack[sp].mi; Dec(sp);
  413. showstack(sp);
  414. IF m>0 THEN BEGIN { put two halfs together }
  415. { Unfortunately it is only possible in an efficient way by using }
  416. { extra memory; mergesort really is something for lists with }
  417. { pointers originally ... }
  418. FOR i := m DOWNTO l do sort2[i] := sort[i]; i := l;
  419. FOR j := m+1 TO r DO sort2[r+m+1-j] := sort[j]; j := r;
  420. FOR k := l TO r DO BEGIN
  421. clearpixel(k);
  422. IF sort2[i]<sort2[j] THEN BEGIN
  423. sort[k] := sort2[i]; Inc(i);
  424. END ELSE BEGIN
  425. sort[k] := sort2[j]; Dec(j);
  426. END;
  427. setpixel(k);
  428. END;
  429. END ELSE IF l<r THEN BEGIN
  430. { create two halfs and the order to put them together }
  431. m := (l+r) DIV 2;
  432. Inc(sp); stack[sp].li := l; stack[sp].mi := m; stack[sp].re := r;
  433. Inc(sp); stack[sp].li := m+1; stack[sp].mi := 0; stack[sp].re := r;
  434. Inc(sp); stack[sp].li := l; stack[sp].mi := 0; stack[sp].re := m;
  435. END;
  436. UNTIL (sp=0) OR cancel;
  437. RestoreWin;
  438. END;
  439. Procedure OpenEverything;
  440. begin
  441. s := LockPubScreen(nil);
  442. if s = nil then CleanUp('Could not lock pubscreen',10);
  443. vi := GetVisualInfoA(s, NIL);
  444. if vi = nil then CleanUp('No visual info',10);
  445. w := OpenWindowTags(NIL, [
  446. WA_IDCMP, IDCMP_CLOSEWINDOW or IDCMP_MENUPICK or 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, AsTag(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 : Longword;
  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.