OV.Mod 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557
  1. MODULE OV;
  2. (* Copyright 2017-2023 Arthur Yefimov
  3. This file is part of Free Oberon.
  4. Free Oberon is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Free Oberon is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with Free Oberon. If not, see <http://www.gnu.org/licenses/>.
  14. *)
  15. IMPORT T := TermBox, Strings, StrList, Out, SYSTEM, Kernel;
  16. (** Oberon Vision *)
  17. CONST
  18. minInt = -70000000H-1;
  19. maxInt = 7FFFFFFFH;
  20. dblClickDelay* = 500;
  21. (* ControlDesc.status possible values *)
  22. normal* = 0;
  23. disabled* = 1;
  24. selected* = 2;
  25. open* = 3;
  26. moving* = 4;
  27. resizing* = 5;
  28. (* Align constants *)
  29. left* = 0;
  30. center* = 1;
  31. right* = 2;
  32. (* Simple Hotkeys *)
  33. hF1* = 47;
  34. hF2* = 48;
  35. hF3* = 49;
  36. hF4* = 50;
  37. hF5* = 51;
  38. hF6* = 52;
  39. hF7* = 53;
  40. hF8* = 54;
  41. hF9* = 55;
  42. hF10* = 56;
  43. hF11* = 57;
  44. hF12* = 58;
  45. hPause* = 93;
  46. (* Ctrl Hotkeys *)
  47. hCtrlA* = 100H + T.kA;
  48. hCtrlB* = 100H + T.kB;
  49. hCtrlC* = 100H + T.kC;
  50. hCtrlD* = 100H + T.kD;
  51. hCtrlE* = 100H + T.kE;
  52. hCtrlF* = 100H + T.kF;
  53. hCtrlG* = 100H + T.kG;
  54. hCtrlH* = 100H + T.kH;
  55. hCtrlI* = 100H + T.kI;
  56. hCtrlJ* = 100H + T.kJ;
  57. hCtrlK* = 100H + T.kK;
  58. hCtrlL* = 100H + T.kL;
  59. hCtrlM* = 100H + T.kM;
  60. hCtrlN* = 100H + T.kN;
  61. hCtrlO* = 100H + T.kO;
  62. hCtrlP* = 100H + T.kP;
  63. hCtrlQ* = 100H + T.kQ;
  64. hCtrlR* = 100H + T.kR;
  65. hCtrlS* = 100H + T.kS;
  66. hCtrlT* = 100H + T.kT;
  67. hCtrlU* = 100H + T.kU;
  68. hCtrlV* = 100H + T.kV;
  69. hCtrlW* = 100H + T.kW;
  70. hCtrlX* = 100H + T.kX;
  71. hCtrlY* = 100H + T.kY;
  72. hCtrlZ* = 100H + T.kZ;
  73. hCtrl0* = 100H + T.k0;
  74. hCtrl1* = 100H + T.k1;
  75. hCtrl2* = 100H + T.k2;
  76. hCtrl3* = 100H + T.k3;
  77. hCtrl4* = 100H + T.k4;
  78. hCtrl5* = 100H + T.k5;
  79. hCtrl6* = 100H + T.k6;
  80. hCtrl7* = 100H + T.k7;
  81. hCtrl8* = 100H + T.k8;
  82. hCtrl9* = 100H + T.k9;
  83. hCtrlF1* = 100H + T.kF1;
  84. hCtrlF2* = 100H + T.kF2;
  85. hCtrlF3* = 100H + T.kF3;
  86. hCtrlF4* = 100H + T.kF4;
  87. hCtrlF5* = 100H + T.kF5;
  88. hCtrlF6* = 100H + T.kF6;
  89. hCtrlF7* = 100H + T.kF7;
  90. hCtrlF8* = 100H + T.kF8;
  91. hCtrlF9* = 100H + T.kF9;
  92. hCtrlF10* = 100H + T.kF10;
  93. hCtrlF11* = 100H + T.kF11;
  94. hCtrlF12* = 100H + T.kF12;
  95. hCtrlEsc* = 100H + T.kEsc;
  96. hCtrlTilde* = 100H + T.kTilde;
  97. hCtrlMinus* = 100H + T.kMinus;
  98. hCtrlEquals* = 100H + T.kEquals;
  99. hCtrlBackspace* = 100H + T.kBackspace;
  100. hCtrlTab* = 100H + T.kTab;
  101. hCtrlEnter* = 100H + T.kEnter;
  102. hCtrlColon* = 100H + T.kColon;
  103. hCtrlQuote* = 100H + T.kQuote;
  104. hCtrlBackslash* = 100H + T.kBackslash;
  105. hCtrlComma* = 100H + T.kComma;
  106. hCtrlStop* = 100H + T.kStop;
  107. hCtrlSlash* = 100H + T.kSlash;
  108. hCtrlInsert* = 100H + T.kInsert;
  109. hCtrlDel* = 100H + T.kDel;
  110. hCtrlHome* = 100H + T.kHome;
  111. hCtrlEnd* = 100H + T.kEnd;
  112. hCtrlPgUp* = 100H + T.kPgUp;
  113. hCtrlPgDn* = 100H + T.kPgDn;
  114. hCtrlLeft* = 100H + T.kLeft;
  115. hCtrlRight* = 100H + T.kRight;
  116. hCtrlUp* = 100H + T.kUp;
  117. hCtrlDown* = 100H + T.kDown;
  118. hCtrlPause* = 100H + T.kPause;
  119. (* Alt Hotkeys 200H *)
  120. hAltA* = 200H + T.kA;
  121. hAltB* = 200H + T.kB;
  122. hAltC* = 200H + T.kC;
  123. hAltD* = 200H + T.kD;
  124. hAltE* = 200H + T.kE;
  125. hAltF* = 200H + T.kF;
  126. hAltG* = 200H + T.kG;
  127. hAltH* = 200H + T.kH;
  128. hAltI* = 200H + T.kI;
  129. hAltJ* = 200H + T.kJ;
  130. hAltK* = 200H + T.kK;
  131. hAltL* = 200H + T.kL;
  132. hAltM* = 200H + T.kM;
  133. hAltN* = 200H + T.kN;
  134. hAltO* = 200H + T.kO;
  135. hAltP* = 200H + T.kP;
  136. hAltQ* = 200H + T.kQ;
  137. hAltR* = 200H + T.kR;
  138. hAltS* = 200H + T.kS;
  139. hAltT* = 200H + T.kT;
  140. hAltU* = 200H + T.kU;
  141. hAltV* = 200H + T.kV;
  142. hAltW* = 200H + T.kW;
  143. hAltX* = 200H + T.kX;
  144. hAltY* = 200H + T.kY;
  145. hAltZ* = 200H + T.kZ;
  146. hAlt0* = 200H + T.k0;
  147. hAlt1* = 200H + T.k1;
  148. hAlt2* = 200H + T.k2;
  149. hAlt3* = 200H + T.k3;
  150. hAlt4* = 200H + T.k4;
  151. hAlt5* = 200H + T.k5;
  152. hAlt6* = 200H + T.k6;
  153. hAlt7* = 200H + T.k7;
  154. hAlt8* = 200H + T.k8;
  155. hAlt9* = 200H + T.k9;
  156. hAltF1* = 200H + T.kF1;
  157. hAltF2* = 200H + T.kF2;
  158. hAltF3* = 200H + T.kF3;
  159. hAltF4* = 200H + T.kF4;
  160. hAltF5* = 200H + T.kF5;
  161. hAltF6* = 200H + T.kF6;
  162. hAltF7* = 200H + T.kF7;
  163. hAltF8* = 200H + T.kF8;
  164. hAltF9* = 200H + T.kF9;
  165. hAltF10* = 200H + T.kF10;
  166. hAltF11* = 200H + T.kF11;
  167. hAltF12* = 200H + T.kF12;
  168. hAltEsc* = 200H + T.kEsc;
  169. hAltTilde* = 200H + T.kTilde;
  170. hAltMinus* = 200H + T.kMinus;
  171. hAltEquals* = 200H + T.kEquals;
  172. hAltBackspace* = 200H + T.kBackspace;
  173. hAltTab* = 200H + T.kTab;
  174. hAltEnter* = 200H + T.kEnter;
  175. hAltColon* = 200H + T.kColon;
  176. hAltQuote* = 200H + T.kQuote;
  177. hAltBackslash* = 200H + T.kBackslash;
  178. hAltComma* = 200H + T.kComma;
  179. hAltStop* = 200H + T.kStop;
  180. hAltSlash* = 200H + T.kSlash;
  181. hAltInsert* = 200H + T.kInsert;
  182. hAltDel* = 200H + T.kDel;
  183. hAltHome* = 200H + T.kHome;
  184. hAltEnd* = 200H + T.kEnd;
  185. hAltPgUp* = 200H + T.kPgUp;
  186. hAltPgDn* = 200H + T.kPgDn;
  187. hAltLeft* = 200H + T.kLeft;
  188. hAltRight* = 200H + T.kRight;
  189. hAltUp* = 200H + T.kUp;
  190. hAltDown* = 200H + T.kDown;
  191. hAltPause* = 200H + T.kPause;
  192. (* Shift Hotkeys 400H *)
  193. hShiftA* = 400H + T.kA;
  194. hShiftB* = 400H + T.kB;
  195. hShiftC* = 400H + T.kC;
  196. hShiftD* = 400H + T.kD;
  197. hShiftE* = 400H + T.kE;
  198. hShiftF* = 400H + T.kF;
  199. hShiftG* = 400H + T.kG;
  200. hShiftH* = 400H + T.kH;
  201. hShiftI* = 400H + T.kI;
  202. hShiftJ* = 400H + T.kJ;
  203. hShiftK* = 400H + T.kK;
  204. hShiftL* = 400H + T.kL;
  205. hShiftM* = 400H + T.kM;
  206. hShiftN* = 400H + T.kN;
  207. hShiftO* = 400H + T.kO;
  208. hShiftP* = 400H + T.kP;
  209. hShiftQ* = 400H + T.kQ;
  210. hShiftR* = 400H + T.kR;
  211. hShiftS* = 400H + T.kS;
  212. hShiftT* = 400H + T.kT;
  213. hShiftU* = 400H + T.kU;
  214. hShiftV* = 400H + T.kV;
  215. hShiftW* = 400H + T.kW;
  216. hShiftX* = 400H + T.kX;
  217. hShiftY* = 400H + T.kY;
  218. hShiftZ* = 400H + T.kZ;
  219. hShift0* = 400H + T.k0;
  220. hShift1* = 400H + T.k1;
  221. hShift2* = 400H + T.k2;
  222. hShift3* = 400H + T.k3;
  223. hShift4* = 400H + T.k4;
  224. hShift5* = 400H + T.k5;
  225. hShift6* = 400H + T.k6;
  226. hShift7* = 400H + T.k7;
  227. hShift8* = 400H + T.k8;
  228. hShift9* = 400H + T.k9;
  229. hShiftF1* = 400H + T.kF1;
  230. hShiftF2* = 400H + T.kF2;
  231. hShiftF3* = 400H + T.kF3;
  232. hShiftF4* = 400H + T.kF4;
  233. hShiftF5* = 400H + T.kF5;
  234. hShiftF6* = 400H + T.kF6;
  235. hShiftF7* = 400H + T.kF7;
  236. hShiftF8* = 400H + T.kF8;
  237. hShiftF9* = 400H + T.kF9;
  238. hShiftF10* = 400H + T.kF10;
  239. hShiftF11* = 400H + T.kF11;
  240. hShiftF12* = 400H + T.kF12;
  241. hShiftEsc* = 400H + T.kEsc;
  242. hShiftTilde* = 400H + T.kTilde;
  243. hShiftMinus* = 400H + T.kMinus;
  244. hShiftEquals* = 400H + T.kEquals;
  245. hShiftBackspace* = 400H + T.kBackspace;
  246. hShiftTab* = 400H + T.kTab;
  247. hShiftEnter* = 400H + T.kEnter;
  248. hShiftColon* = 400H + T.kColon;
  249. hShiftQuote* = 400H + T.kQuote;
  250. hShiftBackslash* = 400H + T.kBackslash;
  251. hShiftComma* = 400H + T.kComma;
  252. hShiftStop* = 400H + T.kStop;
  253. hShiftSlash* = 400H + T.kSlash;
  254. hShiftInsert* = 400H + T.kInsert;
  255. hShiftDel* = 400H + T.kDel;
  256. hShiftHome* = 400H + T.kHome;
  257. hShiftEnd* = 400H + T.kEnd;
  258. hShiftPgUp* = 400H + T.kPgUp;
  259. hShiftPgDn* = 400H + T.kPgDn;
  260. hShiftLeft* = 400H + T.kLeft;
  261. hShiftRight* = 400H + T.kRight;
  262. hShiftUp* = 400H + T.kUp;
  263. hShiftDown* = 400H + T.kDown;
  264. hShiftPause* = 400H + T.kPause;
  265. (* Ctrl+Shift Hotkeys 500H *)
  266. hCtrlShiftA* = 500H + T.kA;
  267. hCtrlShiftB* = 500H + T.kB;
  268. hCtrlShiftC* = 500H + T.kC;
  269. hCtrlShiftD* = 500H + T.kD;
  270. hCtrlShiftE* = 500H + T.kE;
  271. hCtrlShiftF* = 500H + T.kF;
  272. hCtrlShiftG* = 500H + T.kG;
  273. hCtrlShiftH* = 500H + T.kH;
  274. hCtrlShiftI* = 500H + T.kI;
  275. hCtrlShiftJ* = 500H + T.kJ;
  276. hCtrlShiftK* = 500H + T.kK;
  277. hCtrlShiftL* = 500H + T.kL;
  278. hCtrlShiftM* = 500H + T.kM;
  279. hCtrlShiftN* = 500H + T.kN;
  280. hCtrlShiftO* = 500H + T.kO;
  281. hCtrlShiftP* = 500H + T.kP;
  282. hCtrlShiftQ* = 500H + T.kQ;
  283. hCtrlShiftR* = 500H + T.kR;
  284. hCtrlShiftS* = 500H + T.kS;
  285. hCtrlShiftT* = 500H + T.kT;
  286. hCtrlShiftU* = 500H + T.kU;
  287. hCtrlShiftV* = 500H + T.kV;
  288. hCtrlShiftW* = 500H + T.kW;
  289. hCtrlShiftX* = 500H + T.kX;
  290. hCtrlShiftY* = 500H + T.kY;
  291. hCtrlShiftZ* = 500H + T.kZ;
  292. hCtrlShift0* = 500H + T.k0;
  293. hCtrlShift1* = 500H + T.k1;
  294. hCtrlShift2* = 500H + T.k2;
  295. hCtrlShift3* = 500H + T.k3;
  296. hCtrlShift4* = 500H + T.k4;
  297. hCtrlShift5* = 500H + T.k5;
  298. hCtrlShift6* = 500H + T.k6;
  299. hCtrlShift7* = 500H + T.k7;
  300. hCtrlShift8* = 500H + T.k8;
  301. hCtrlShift9* = 500H + T.k9;
  302. hCtrlShiftF1* = 500H + T.kF1;
  303. hCtrlShiftF2* = 500H + T.kF2;
  304. hCtrlShiftF3* = 500H + T.kF3;
  305. hCtrlShiftF4* = 500H + T.kF4;
  306. hCtrlShiftF5* = 500H + T.kF5;
  307. hCtrlShiftF6* = 500H + T.kF6;
  308. hCtrlShiftF7* = 500H + T.kF7;
  309. hCtrlShiftF8* = 500H + T.kF8;
  310. hCtrlShiftF9* = 500H + T.kF9;
  311. hCtrlShiftF10* = 500H + T.kF10;
  312. hCtrlShiftF11* = 500H + T.kF11;
  313. hCtrlShiftF12* = 500H + T.kF12;
  314. hCtrlShiftEsc* = 500H + T.kEsc;
  315. hCtrlShiftTilde* = 500H + T.kTilde;
  316. hCtrlShiftMinus* = 500H + T.kMinus;
  317. hCtrlShiftEquals* = 500H + T.kEquals;
  318. hCtrlShiftBackspace* = 500H + T.kBackspace;
  319. hCtrlShiftTab* = 500H + T.kTab;
  320. hCtrlShiftEnter* = 500H + T.kEnter;
  321. hCtrlShiftColon* = 500H + T.kColon;
  322. hCtrlShiftQuote* = 500H + T.kQuote;
  323. hCtrlShiftBackslash* = 500H + T.kBackslash;
  324. hCtrlShiftComma* = 500H + T.kComma;
  325. hCtrlShiftStop* = 500H + T.kStop;
  326. hCtrlShiftSlash* = 500H + T.kSlash;
  327. hCtrlShiftInsert* = 500H + T.kInsert;
  328. hCtrlShiftDel* = 500H + T.kDel;
  329. hCtrlShiftHome* = 500H + T.kHome;
  330. hCtrlShiftEnd* = 500H + T.kEnd;
  331. hCtrlShiftPgUp* = 500H + T.kPgUp;
  332. hCtrlShiftPgDn* = 500H + T.kPgDn;
  333. hCtrlShiftLeft* = 500H + T.kLeft;
  334. hCtrlShiftRight* = 500H + T.kRight;
  335. hCtrlShiftUp* = 500H + T.kUp;
  336. hCtrlShiftDown* = 500H + T.kDown;
  337. hCtrlShiftPause* = 500H + T.kPause;
  338. (* Ctrl+Alt Hotkeys 300H *)
  339. hCtrlAltA* = 300H + T.kA;
  340. hCtrlAltB* = 300H + T.kB;
  341. hCtrlAltC* = 300H + T.kC;
  342. hCtrlAltD* = 300H + T.kD;
  343. hCtrlAltE* = 300H + T.kE;
  344. hCtrlAltF* = 300H + T.kF;
  345. hCtrlAltG* = 300H + T.kG;
  346. hCtrlAltH* = 300H + T.kH;
  347. hCtrlAltI* = 300H + T.kI;
  348. hCtrlAltJ* = 300H + T.kJ;
  349. hCtrlAltK* = 300H + T.kK;
  350. hCtrlAltL* = 300H + T.kL;
  351. hCtrlAltM* = 300H + T.kM;
  352. hCtrlAltN* = 300H + T.kN;
  353. hCtrlAltO* = 300H + T.kO;
  354. hCtrlAltP* = 300H + T.kP;
  355. hCtrlAltQ* = 300H + T.kQ;
  356. hCtrlAltR* = 300H + T.kR;
  357. hCtrlAltS* = 300H + T.kS;
  358. hCtrlAltT* = 300H + T.kT;
  359. hCtrlAltU* = 300H + T.kU;
  360. hCtrlAltV* = 300H + T.kV;
  361. hCtrlAltW* = 300H + T.kW;
  362. hCtrlAltX* = 300H + T.kX;
  363. hCtrlAltY* = 300H + T.kY;
  364. hCtrlAltZ* = 300H + T.kZ;
  365. hCtrlAlt0* = 300H + T.k0;
  366. hCtrlAlt1* = 300H + T.k1;
  367. hCtrlAlt2* = 300H + T.k2;
  368. hCtrlAlt3* = 300H + T.k3;
  369. hCtrlAlt4* = 300H + T.k4;
  370. hCtrlAlt5* = 300H + T.k5;
  371. hCtrlAlt6* = 300H + T.k6;
  372. hCtrlAlt7* = 300H + T.k7;
  373. hCtrlAlt8* = 300H + T.k8;
  374. hCtrlAlt9* = 300H + T.k9;
  375. hCtrlAltF1* = 300H + T.kF1;
  376. hCtrlAltF2* = 300H + T.kF2;
  377. hCtrlAltF3* = 300H + T.kF3;
  378. hCtrlAltF4* = 300H + T.kF4;
  379. hCtrlAltF5* = 300H + T.kF5;
  380. hCtrlAltF6* = 300H + T.kF6;
  381. hCtrlAltF7* = 300H + T.kF7;
  382. hCtrlAltF8* = 300H + T.kF8;
  383. hCtrlAltF9* = 300H + T.kF9;
  384. hCtrlAltF10* = 300H + T.kF10;
  385. hCtrlAltF11* = 300H + T.kF11;
  386. hCtrlAltF12* = 300H + T.kF12;
  387. hCtrlAltEsc* = 300H + T.kEsc;
  388. hCtrlAltTilde* = 300H + T.kTilde;
  389. hCtrlAltMinus* = 300H + T.kMinus;
  390. hCtrlAltEquals* = 300H + T.kEquals;
  391. hCtrlAltBackspace* = 300H + T.kBackspace;
  392. hCtrlAltTab* = 300H + T.kTab;
  393. hCtrlAltEnter* = 300H + T.kEnter;
  394. hCtrlAltColon* = 300H + T.kColon;
  395. hCtrlAltQuote* = 300H + T.kQuote;
  396. hCtrlAltBackslash* = 300H + T.kBackslash;
  397. hCtrlAltComma* = 300H + T.kComma;
  398. hCtrlAltStop* = 300H + T.kStop;
  399. hCtrlAltSlash* = 300H + T.kSlash;
  400. hCtrlAltInsert* = 300H + T.kInsert;
  401. hCtrlAltDel* = 300H + T.kDel;
  402. hCtrlAltHome* = 300H + T.kHome;
  403. hCtrlAltEnd* = 300H + T.kEnd;
  404. hCtrlAltPgUp* = 300H + T.kPgUp;
  405. hCtrlAltPgDn* = 300H + T.kPgDn;
  406. hCtrlAltLeft* = 300H + T.kLeft;
  407. hCtrlAltRight* = 300H + T.kRight;
  408. hCtrlAltUp* = 300H + T.kUp;
  409. hCtrlAltDown* = 300H + T.kDown;
  410. hCtrlAltPause* = 300H + T.kPause;
  411. (* Alt+Shift Hotkeys 600H *)
  412. hAltShiftA* = 600H + T.kA;
  413. hAltShiftB* = 600H + T.kB;
  414. hAltShiftC* = 600H + T.kC;
  415. hAltShiftD* = 600H + T.kD;
  416. hAltShiftE* = 600H + T.kE;
  417. hAltShiftF* = 600H + T.kF;
  418. hAltShiftG* = 600H + T.kG;
  419. hAltShiftH* = 600H + T.kH;
  420. hAltShiftI* = 600H + T.kI;
  421. hAltShiftJ* = 600H + T.kJ;
  422. hAltShiftK* = 600H + T.kK;
  423. hAltShiftL* = 600H + T.kL;
  424. hAltShiftM* = 600H + T.kM;
  425. hAltShiftN* = 600H + T.kN;
  426. hAltShiftO* = 600H + T.kO;
  427. hAltShiftP* = 600H + T.kP;
  428. hAltShiftQ* = 600H + T.kQ;
  429. hAltShiftR* = 600H + T.kR;
  430. hAltShiftS* = 600H + T.kS;
  431. hAltShiftT* = 600H + T.kT;
  432. hAltShiftU* = 600H + T.kU;
  433. hAltShiftV* = 600H + T.kV;
  434. hAltShiftW* = 600H + T.kW;
  435. hAltShiftX* = 600H + T.kX;
  436. hAltShiftY* = 600H + T.kY;
  437. hAltShiftZ* = 600H + T.kZ;
  438. hAltShift0* = 600H + T.k0;
  439. hAltShift1* = 600H + T.k1;
  440. hAltShift2* = 600H + T.k2;
  441. hAltShift3* = 600H + T.k3;
  442. hAltShift4* = 600H + T.k4;
  443. hAltShift5* = 600H + T.k5;
  444. hAltShift6* = 600H + T.k6;
  445. hAltShift7* = 600H + T.k7;
  446. hAltShift8* = 600H + T.k8;
  447. hAltShift9* = 600H + T.k9;
  448. hAltShiftF1* = 600H + T.kF1;
  449. hAltShiftF2* = 600H + T.kF2;
  450. hAltShiftF3* = 600H + T.kF3;
  451. hAltShiftF4* = 600H + T.kF4;
  452. hAltShiftF5* = 600H + T.kF5;
  453. hAltShiftF6* = 600H + T.kF6;
  454. hAltShiftF7* = 600H + T.kF7;
  455. hAltShiftF8* = 600H + T.kF8;
  456. hAltShiftF9* = 600H + T.kF9;
  457. hAltShiftF10* = 600H + T.kF10;
  458. hAltShiftF11* = 600H + T.kF11;
  459. hAltShiftF12* = 600H + T.kF12;
  460. hAltShiftEsc* = 600H + T.kEsc;
  461. hAltShiftTilde* = 600H + T.kTilde;
  462. hAltShiftMinus* = 600H + T.kMinus;
  463. hAltShiftEquals* = 600H + T.kEquals;
  464. hAltShiftBackspace* = 600H + T.kBackspace;
  465. hAltShiftTab* = 600H + T.kTab;
  466. hAltShiftEnter* = 600H + T.kEnter;
  467. hAltShiftColon* = 600H + T.kColon;
  468. hAltShiftQuote* = 600H + T.kQuote;
  469. hAltShiftBackslash* = 600H + T.kBackslash;
  470. hAltShiftComma* = 600H + T.kComma;
  471. hAltShiftStop* = 600H + T.kStop;
  472. hAltShiftSlash* = 600H + T.kSlash;
  473. hAltShiftInsert* = 600H + T.kInsert;
  474. hAltShiftDel* = 600H + T.kDel;
  475. hAltShiftHome* = 600H + T.kHome;
  476. hAltShiftEnd* = 600H + T.kEnd;
  477. hAltShiftPgUp* = 600H + T.kPgUp;
  478. hAltShiftPgDn* = 600H + T.kPgDn;
  479. hAltShiftLeft* = 600H + T.kLeft;
  480. hAltShiftRight* = 600H + T.kRight;
  481. hAltShiftUp* = 600H + T.kUp;
  482. hAltShiftDown* = 600H + T.kDown;
  483. hAltShiftPause* = 600H + T.kPause;
  484. (* Ctrl+Alt+Shift Hotkeys 700H *)
  485. hCtrlAltShiftA* = 700H + T.kA;
  486. hCtrlAltShiftB* = 700H + T.kB;
  487. hCtrlAltShiftC* = 700H + T.kC;
  488. hCtrlAltShiftD* = 700H + T.kD;
  489. hCtrlAltShiftE* = 700H + T.kE;
  490. hCtrlAltShiftF* = 700H + T.kF;
  491. hCtrlAltShiftG* = 700H + T.kG;
  492. hCtrlAltShiftH* = 700H + T.kH;
  493. hCtrlAltShiftI* = 700H + T.kI;
  494. hCtrlAltShiftJ* = 700H + T.kJ;
  495. hCtrlAltShiftK* = 700H + T.kK;
  496. hCtrlAltShiftL* = 700H + T.kL;
  497. hCtrlAltShiftM* = 700H + T.kM;
  498. hCtrlAltShiftN* = 700H + T.kN;
  499. hCtrlAltShiftO* = 700H + T.kO;
  500. hCtrlAltShiftP* = 700H + T.kP;
  501. hCtrlAltShiftQ* = 700H + T.kQ;
  502. hCtrlAltShiftR* = 700H + T.kR;
  503. hCtrlAltShiftS* = 700H + T.kS;
  504. hCtrlAltShiftT* = 700H + T.kT;
  505. hCtrlAltShiftU* = 700H + T.kU;
  506. hCtrlAltShiftV* = 700H + T.kV;
  507. hCtrlAltShiftW* = 700H + T.kW;
  508. hCtrlAltShiftX* = 700H + T.kX;
  509. hCtrlAltShiftY* = 700H + T.kY;
  510. hCtrlAltShiftZ* = 700H + T.kZ;
  511. hCtrlAltShift0* = 700H + T.k0;
  512. hCtrlAltShift1* = 700H + T.k1;
  513. hCtrlAltShift2* = 700H + T.k2;
  514. hCtrlAltShift3* = 700H + T.k3;
  515. hCtrlAltShift4* = 700H + T.k4;
  516. hCtrlAltShift5* = 700H + T.k5;
  517. hCtrlAltShift6* = 700H + T.k6;
  518. hCtrlAltShift7* = 700H + T.k7;
  519. hCtrlAltShift8* = 700H + T.k8;
  520. hCtrlAltShift9* = 700H + T.k9;
  521. hCtrlAltShiftF1* = 700H + T.kF1;
  522. hCtrlAltShiftF2* = 700H + T.kF2;
  523. hCtrlAltShiftF3* = 700H + T.kF3;
  524. hCtrlAltShiftF4* = 700H + T.kF4;
  525. hCtrlAltShiftF5* = 700H + T.kF5;
  526. hCtrlAltShiftF6* = 700H + T.kF6;
  527. hCtrlAltShiftF7* = 700H + T.kF7;
  528. hCtrlAltShiftF8* = 700H + T.kF8;
  529. hCtrlAltShiftF9* = 700H + T.kF9;
  530. hCtrlAltShiftF10* = 700H + T.kF10;
  531. hCtrlAltShiftF11* = 700H + T.kF11;
  532. hCtrlAltShiftF12* = 700H + T.kF12;
  533. hCtrlAltShiftEsc* = 700H + T.kEsc;
  534. hCtrlAltShiftTilde* = 700H + T.kTilde;
  535. hCtrlAltShiftMinus* = 700H + T.kMinus;
  536. hCtrlAltShiftEquals* = 700H + T.kEquals;
  537. hCtrlAltShiftBackspace* = 700H + T.kBackspace;
  538. hCtrlAltShiftTab* = 700H + T.kTab;
  539. hCtrlAltShiftEnter* = 700H + T.kEnter;
  540. hCtrlAltShiftColon* = 700H + T.kColon;
  541. hCtrlAltShiftQuote* = 700H + T.kQuote;
  542. hCtrlAltShiftBackslash* = 700H + T.kBackslash;
  543. hCtrlAltShiftComma* = 700H + T.kComma;
  544. hCtrlAltShiftStop* = 700H + T.kStop;
  545. hCtrlAltShiftSlash* = 700H + T.kSlash;
  546. hCtrlAltShiftInsert* = 700H + T.kInsert;
  547. hCtrlAltShiftDel* = 700H + T.kDel;
  548. hCtrlAltShiftHome* = 700H + T.kHome;
  549. hCtrlAltShiftEnd* = 700H + T.kEnd;
  550. hCtrlAltShiftPgUp* = 700H + T.kPgUp;
  551. hCtrlAltShiftPgDn* = 700H + T.kPgDn;
  552. hCtrlAltShiftLeft* = 700H + T.kLeft;
  553. hCtrlAltShiftRight* = 700H + T.kRight;
  554. hCtrlAltShiftUp* = 700H + T.kUp;
  555. hCtrlAltShiftDown* = 700H + T.kDown;
  556. hCtrlAltShiftPause* = 700H + T.kPause;
  557. TYPE
  558. App* = POINTER TO AppDesc;
  559. Control* = POINTER TO ControlDesc;
  560. ControlMethod* = POINTER TO ControlMethodDesc;
  561. ClickHandler* = PROCEDURE (c: Control);
  562. ChangeHandler* = ClickHandler;
  563. ControlDesc* = RECORD
  564. app*: App;
  565. parent*, children*: Control;
  566. prev*, next*: Control;
  567. x*, y*, w*, h*: INTEGER;
  568. tabIndex*: INTEGER;
  569. enabled*: BOOLEAN;
  570. default*: BOOLEAN;
  571. focused*: BOOLEAN;
  572. mouseActive*: BOOLEAN; (* FALSE if control does not capture mouse events *)
  573. status*: INTEGER;
  574. caption*: ARRAY 256 OF CHAR;
  575. onClick*: ClickHandler;
  576. onDblClick*: ClickHandler;
  577. onChange*: ChangeHandler;
  578. do*: ControlMethod
  579. END;
  580. ControlMethodDesc* = RECORD
  581. added*: PROCEDURE (c, child: Control);
  582. draw*: PROCEDURE (c: Control; x, y: INTEGER);
  583. resize*: PROCEDURE (c: Control; x, y, w, h: INTEGER);
  584. refresh*: PROCEDURE (c: Control);
  585. click*: PROCEDURE (c: Control);
  586. dblClick*: PROCEDURE (c: Control);
  587. keyDown*: PROCEDURE (c: Control; VAR E: T.Event);
  588. textInput*: PROCEDURE (c: Control; ch: CHAR);
  589. getFocus*: PROCEDURE (c: Control);
  590. lostFocus*: PROCEDURE (c: Control);
  591. mouseMove*: PROCEDURE (c: Control; x, y: INTEGER; button: INTEGER);
  592. mouseDown*: PROCEDURE (c: Control; x, y, button: INTEGER);
  593. mouseUp*: PROCEDURE (c: Control; x, y, button: INTEGER);
  594. close*: PROCEDURE (c: Control; VAR cancel: BOOLEAN)
  595. END;
  596. Menu* = POINTER TO MenuDesc;
  597. MenuDesc* = RECORD(ControlDesc)
  598. innerW*, innerH*: INTEGER;
  599. hint*: ARRAY 40 OF CHAR;
  600. hintW*: INTEGER;
  601. hotkey*: INTEGER;
  602. lastSelected*: Control
  603. END;
  604. Label* = POINTER TO LabelDesc;
  605. LabelDesc* = RECORD(ControlDesc)
  606. len*: INTEGER;
  607. align*: INTEGER (* See constants above *)
  608. END;
  609. QuickBtn* = POINTER TO QuickBtnDesc;
  610. QuickBtnDesc* = RECORD(MenuDesc) END;
  611. Button* = POINTER TO ButtonDesc;
  612. ButtonDesc* = RECORD(ControlDesc) END;
  613. WinBtn* = POINTER TO WinBtnDesc;
  614. WinBtnDesc* = RECORD(ButtonDesc) END;
  615. Scrollbar* = POINTER TO ScrollbarDesc;
  616. ScrollbarDesc* = RECORD(ControlDesc)
  617. max*, cur*: INTEGER; (* cur is runner position in range 0..max *)
  618. runnerOffset*: INTEGER; (* Current visual position of runner *)
  619. runnerW*: INTEGER; (* Visual width of runner *)
  620. onScrollbar*: PROCEDURE (c: Control)
  621. END;
  622. Edit* = POINTER TO EditDesc;
  623. EditDesc* = RECORD(ControlDesc)
  624. len*: INTEGER; (* Actual amount of characters before 0X *)
  625. pos*: INTEGER
  626. END;
  627. ColumnList* = POINTER TO ColumnListDesc;
  628. ColumnListDesc* = RECORD(ControlDesc)
  629. cols*: INTEGER; (* Column count *)
  630. items*: StrList.List;
  631. begin*: INTEGER; (* What index list begins with visually *)
  632. cur*: INTEGER;
  633. lastMouseDownItem*: INTEGER;
  634. scrollbar: Scrollbar
  635. END;
  636. Window* = POINTER TO WindowDesc;
  637. WindowDesc* = RECORD(ControlDesc)
  638. cur*: Control;
  639. modal*: BOOLEAN;
  640. resizable*: BOOLEAN;
  641. closeable*: BOOLEAN;
  642. closeOnEsc*: BOOLEAN;
  643. closeBtn*, zoomBtn*: WinBtn;
  644. bg*: INTEGER;
  645. minW*, minH*: INTEGER;
  646. mx*, my*, mw*, mh*: INTEGER (* To store x, y, w, h when maximized *)
  647. END;
  648. AppDesc* = RECORD
  649. windows*: Window;
  650. menu*: Menu;
  651. statusbar*: Menu;
  652. statusText*: ARRAY 256 OF CHAR;
  653. cur*: Control;
  654. dragged*: Control;
  655. dragX*, dragY*: INTEGER;
  656. onResize: PROCEDURE (w, h: INTEGER);
  657. lastMouseDownTime*: INTEGER;
  658. quit*: BOOLEAN;
  659. needRedraw*: BOOLEAN;
  660. sync*: BOOLEAN;
  661. mouseBtn*: INTEGER
  662. END;
  663. VAR
  664. controlMethod*: ControlMethod;
  665. labelMethod*: ControlMethod;
  666. quickBtnMethod*: ControlMethod;
  667. buttonMethod*: ControlMethod;
  668. winBtnMethod*: ControlMethod;
  669. scrollbarMethod*: ControlMethod;
  670. editMethod*: ControlMethod;
  671. columnListMethod*: ControlMethod;
  672. windowMethod*: ControlMethod;
  673. menuMethod*: ControlMethod;
  674. ticks: INTEGER;
  675. PROCEDURE DrawAppWindows*(app: App);
  676. VAR w, br: Control;
  677. tW, tH: INTEGER;
  678. BEGIN T.Size(tW, tH);
  679. T.Fill(0, 1, tW, tH - 2, T.lightShade, 1, 7);
  680. IF app.windows # NIL THEN
  681. w := app.windows.next; br := w;
  682. REPEAT w.do.draw(w, 0, 0); w := w.next UNTIL w = br
  683. END
  684. END DrawAppWindows;
  685. PROCEDURE DrawAppStatusbar(app: App);
  686. VAR m, br: Control;
  687. x: INTEGER;
  688. tW, tH: INTEGER;
  689. BEGIN T.Size(tW, tH); x := 0;
  690. T.Fill(0, tH - 1, tW, 1, ' ', 0, 7);
  691. IF app.statusbar.children # NIL THEN
  692. m := app.statusbar.children; br := m;
  693. REPEAT m.do.draw(m, 0, tH - 1); INC(x, m.w); m := m.next
  694. UNTIL m = br
  695. END;
  696. IF app.statusText[0] # 0X THEN
  697. T.SetCell(x, tH - 1, T.lineVert, 0, 7);
  698. T.Print(x + 2, tH - 1, -1, app.statusText, 0, 7)
  699. END
  700. END DrawAppStatusbar;
  701. PROCEDURE DrawAppMenu(app: App);
  702. VAR m, br: Control;
  703. tW, tH: INTEGER;
  704. BEGIN T.Size(tW, tH);
  705. T.Fill(0, 0, tW, 1, ' ', 0, 7);
  706. IF app.menu.children # NIL THEN
  707. m := app.menu.children; br := m;
  708. REPEAT m.do.draw(m, 0, 0); m := m.next UNTIL m = br
  709. END
  710. END DrawAppMenu;
  711. PROCEDURE DrawApp*(app: App);
  712. BEGIN
  713. DrawAppWindows(app);
  714. DrawAppStatusbar(app);
  715. DrawAppMenu(app);
  716. app.needRedraw := FALSE
  717. END DrawApp;
  718. PROCEDURE NeedRedraw*(app: App);
  719. BEGIN IF app # NIL THEN app.needRedraw := TRUE END
  720. END NeedRedraw;
  721. (* Set the given element as currently focused, notify it with getFocus,
  722. notify previously focused element and all its (grand-)parents with
  723. lostFocus, up to but not including the closest common parent.
  724. If c is NIL, use main window if it exists. *)
  725. PROCEDURE SetAppFocus*(app: App; c: Control);
  726. VAR p, common: Control;
  727. BEGIN
  728. p := app.cur;
  729. IF c = NIL THEN c := app.windows END;
  730. IF p # c THEN
  731. IF p # NIL THEN
  732. REPEAT
  733. IF c = NIL THEN common := NIL
  734. ELSE common := c.parent;
  735. WHILE (common # NIL) & (p # common) DO common := common.parent END
  736. END;
  737. IF common = NIL THEN
  738. IF p.do.lostFocus # NIL THEN p.do.lostFocus(p) END;
  739. p := p.parent
  740. END
  741. UNTIL (p = NIL) OR (p = common)
  742. END;
  743. app.cur := c;
  744. IF c = NIL THEN T.HideCursor
  745. ELSIF c.do.getFocus # NIL THEN c.do.getFocus(c)
  746. END
  747. END
  748. END SetAppFocus;
  749. PROCEDURE UnsetFocus*(app: App);
  750. BEGIN SetAppFocus(app, NIL)
  751. END UnsetFocus;
  752. PROCEDURE SetFocus*(c: Control);
  753. BEGIN IF (c # NIL) & (c.app # NIL) THEN SetAppFocus(c.app, c) END
  754. END SetFocus;
  755. (* Sets c.app for the control and all his children recursively. *)
  756. PROCEDURE SetApp(c: Control; app: App);
  757. VAR p, br: Control;
  758. BEGIN c.app := app; p := c.children;
  759. IF p # NIL THEN br := p;
  760. REPEAT SetApp(p, app); p := p.next UNTIL p = br
  761. END
  762. END SetApp;
  763. (* Common *)
  764. PROCEDURE Cap(c: CHAR): CHAR;
  765. BEGIN
  766. IF ('a' <= c) & (c <= 'z') THEN c := CHR(ORD('Q') - ORD('q') + ORD(c))
  767. ELSIF ('а' <= c) & (c <= 'я') THEN c := CHR(ORD('Б') - ORD('б') + ORD(c))
  768. ELSIF c = 'ё' THEN c := 'Ё'
  769. END ;
  770. RETURN c END Cap;
  771. PROCEDURE Refresh*(c: Control);
  772. BEGIN
  773. IF c.do.refresh # NIL THEN c.do.refresh(c) END
  774. END Refresh;
  775. (** fg2 is a color of marked letters, that are escaped with '&'. *)
  776. PROCEDURE PutMarkedString*(x, y: INTEGER; s: ARRAY OF CHAR; fg, fg2, bg, limit: INTEGER);
  777. VAR i, c, tW, tH: INTEGER;
  778. mark: BOOLEAN;
  779. BEGIN T.Size(tW, tH);
  780. IF limit = 0 THEN limit := tW END;
  781. i := 0; mark := FALSE;
  782. WHILE (i < LEN(s)) & (s[i] # 0X) & (x <= limit) DO
  783. IF s[i] = '&' THEN mark := TRUE
  784. ELSE
  785. IF mark THEN c := fg2; mark := FALSE ELSE c := fg END;
  786. T.SetCell(x, y, s[i], c, bg);
  787. INC(x)
  788. END;
  789. INC(i)
  790. END
  791. END PutMarkedString;
  792. PROCEDURE SetCharColor(x, y, fg, bg: INTEGER);
  793. BEGIN T.SetFg(x, y, fg); T.SetBg(x, y, bg)
  794. END SetCharColor;
  795. PROCEDURE DrawWindowBorder*(x, y, w, h, fg, bg: INTEGER;
  796. title: ARRAY OF CHAR; resizable, moving, inactive: BOOLEAN);
  797. VAR i, x2, y2, len, tW, tH: INTEGER; ch: CHAR;
  798. single: BOOLEAN; (* Sigle border *)
  799. BEGIN single := moving OR inactive;
  800. T.Size(tW, tH);
  801. IF moving THEN fg := 10
  802. ELSIF inactive THEN
  803. IF bg = 7 THEN fg := 8 ELSE fg := 7 END
  804. END;
  805. x2 := x + w - 1; y2 := y + h - 1;
  806. IF single THEN ch := T.lineHor ELSE ch := T.doubleHor END;
  807. FOR i := x + 1 TO x2 - 1 DO
  808. T.SetCell(i, y, ch, fg, bg);
  809. T.SetCell(i, y2, ch, fg, bg)
  810. END;
  811. IF single THEN ch := T.lineVert ELSE ch := T.doubleVert END;
  812. FOR i := y + 1 TO y2 - 1 DO T.SetCell(x, i, ch, fg, bg) END;
  813. IF resizable & ~inactive THEN (* Vertical Scrollbarbar: *)
  814. FOR i := y + 2 TO y2 - 2 DO T.SetCell(x2, i, T.mediumShade, bg, 3) END;
  815. T.SetCell(x2, y + 1, T.triangleUp, bg, 3);
  816. T.SetCell(x2, y2 - 1, T.triangleDown, bg, 3)
  817. ELSE
  818. IF single THEN ch := T.lineVert ELSE ch := T.doubleVert END;
  819. FOR i := y + 1 TO y2 - 1 DO T.SetCell(x2, i, ch, fg, bg) END
  820. END; (* Corners: *)
  821. IF single THEN
  822. T.SetCell(x, y, T.lineDownRight, fg, bg);
  823. T.SetCell(x2, y, T.lineDownLeft, fg, bg);
  824. T.SetCell(x, y2, T.lineUpRight, fg, bg)
  825. ELSE
  826. T.SetCell(x, y, T.doubleDownRight, fg, bg);
  827. T.SetCell(x2, y, T.doubleDownLeft, fg, bg);
  828. T.SetCell(x, y2, T.doubleUpRight, fg, bg)
  829. END;
  830. IF resizable & ~inactive THEN (* Corner: *)
  831. T.SetCell(x2 - 1, y2, T.lineHor, 10, bg);
  832. T.SetCell(x2, y2, T.lineUpLeft, 10, bg);
  833. T.SetCell(x2 - 4, y, '[', fg, bg); (* Maximize button *)
  834. IF (w = tW) & (h = tH - 2) THEN ch := T.arrowUpDown
  835. ELSE ch := T.arrowUp
  836. END;
  837. T.SetCell(x2 - 3, y, ch, 10, bg);
  838. T.SetCell(x2 - 2, y, ']', fg, bg);
  839. ELSIF single THEN T.SetCell(x2, y2, T.lineUpLeft, fg, bg)
  840. ELSE T.SetCell(x2, y2, T.doubleUpLeft, fg, bg)
  841. END; (* Close button: *)
  842. IF ~inactive THEN
  843. T.SetCell(x + 2, y, '[', fg, bg);
  844. T.SetCell(x + 3, y, T.blackSquare, 10, bg);
  845. T.SetCell(x + 4, y, ']', fg, bg)
  846. END;
  847. IF x2 < tW - 1 THEN (* Right shadow: *)
  848. FOR i := y + 1 TO y2 DO SetCharColor(x2 + 1, i, 8, 0) END;
  849. IF x2 < tW - 2 THEN (* Most right column: *)
  850. FOR i := y + 1 TO y2 DO SetCharColor(x2 + 2, i, 8, 0) END
  851. END
  852. END;
  853. IF y2 < tH - 2 THEN (* Bottom shadow: *)
  854. FOR i := x + 2 TO x2 + 2 DO SetCharColor(i, y2 + 1, 8, 0) END
  855. END; (* Title: *)
  856. IF title[0] # 0X THEN
  857. len := Strings.Length(title);
  858. i := x + (w - len) DIV 2;
  859. IF i < x + 5 THEN i := x + 5 END;
  860. IF i + len > x2 - 4 THEN len := x2 - i - 4 END;
  861. IF i # x + 5 THEN T.SetCell(i - 1, y, ' ', fg, bg) END;
  862. IF i + len # x2 - 4 THEN T.SetCell(i + len, y, ' ', fg, bg) END;
  863. T.Print(i, y, len, title, fg, bg)
  864. END
  865. END DrawWindowBorder;
  866. PROCEDURE FindChildAt*(c: Control; x, y: INTEGER): Control;
  867. VAR p, br: Control;
  868. BEGIN
  869. p := c.children; br := p;
  870. WHILE (p # NIL) &
  871. ~(p.mouseActive &
  872. (p.x <= x) & (x < p.x + p.w) &
  873. (p.y <= y) & (y < p.y + p.h)) DO
  874. IF p.next = br THEN p := NIL ELSE p := p.next END
  875. END
  876. RETURN p END FindChildAt;
  877. PROCEDURE PassMouseDown*(c: Control; x, y, button: INTEGER): BOOLEAN;
  878. VAR p: Control;
  879. BEGIN p := FindChildAt(c, x, y);
  880. IF (p # NIL) & (p.do.mouseDown # NIL) THEN
  881. p.do.mouseDown(p, x - p.x, y - p.y, button)
  882. END
  883. RETURN p # NIL END PassMouseDown;
  884. PROCEDURE PassMouseMove*(c: Control; x, y: INTEGER; button: INTEGER): BOOLEAN;
  885. VAR p: Control;
  886. BEGIN p := FindChildAt(c, x, y);
  887. IF (p # NIL) & (p.do.mouseMove # NIL) THEN
  888. p.do.mouseMove(p, x - p.x, y - p.y, button)
  889. END
  890. RETURN p # NIL END PassMouseMove;
  891. PROCEDURE SetEnabled*(c: Control; enabled: BOOLEAN);
  892. BEGIN c.enabled := enabled
  893. END SetEnabled;
  894. (* Control *)
  895. PROCEDURE InitControl*(c: Control);
  896. BEGIN c.x := 0; c.y := 0; c.w := 0; c.h := 0; c.tabIndex := 0;
  897. c.parent := NIL; c.children := NIL; c.prev := NIL; c.next := NIL;
  898. c.enabled := TRUE; c.default := FALSE; c.focused := FALSE;
  899. c.mouseActive := TRUE; c.status := 0; c.caption[0] := 0X;
  900. c.onClick := NIL; c.onDblClick := NIL; c.onChange := NIL;
  901. c.do := controlMethod
  902. END InitControl;
  903. PROCEDURE NewControl*(): Control;
  904. VAR c: Control;
  905. BEGIN NEW(c); InitControl(c) ;
  906. RETURN c END NewControl;
  907. PROCEDURE Add*(c, child: Control);
  908. BEGIN
  909. child.parent := c;
  910. IF c.children = NIL THEN
  911. c.children := child;
  912. child.prev := child; child.next := child
  913. ELSE
  914. c.children.prev.next := child;
  915. child.prev := c.children.prev;
  916. c.children.prev := child;
  917. child.next := c.children
  918. END;
  919. IF c.do.added # NIL THEN c.do.added(c, child) END
  920. END Add;
  921. PROCEDURE Remove*(c: Control);
  922. BEGIN
  923. IF c.parent # NIL THEN
  924. IF c.next = c THEN c.parent.children := NIL
  925. ELSE c.prev.next := c.next;
  926. c.next.prev := c.prev
  927. END
  928. END
  929. END Remove;
  930. PROCEDURE DrawChildren*(c: Control; x, y: INTEGER);
  931. VAR p, br: Control;
  932. BEGIN
  933. IF c.children # NIL THEN
  934. INC(x, c.x); INC(y, c.y);
  935. p := c.children.prev; br := p;
  936. REPEAT p.do.draw(p, x, y); p := p.prev UNTIL p = br
  937. END
  938. END DrawChildren;
  939. PROCEDURE SetDragged*(app: App; c: Control);
  940. VAR x, y: INTEGER;
  941. BEGIN
  942. SetFocus(c);
  943. app.dragged := c; x := 0; y := 0;
  944. WHILE c # NIL DO
  945. INC(x, c.x); INC(y, c.y);
  946. c := c.parent
  947. END;
  948. app.dragX := x; app.dragY := y
  949. END SetDragged;
  950. (* ControlMethod *)
  951. PROCEDURE ControlResize*(c: Control; x, y, w, h: INTEGER);
  952. BEGIN c.x := x; c.y := y; c.w := w; c.h := h
  953. END ControlResize;
  954. PROCEDURE ControlGetFocus*(c: Control);
  955. BEGIN c.focused := TRUE
  956. END ControlGetFocus;
  957. PROCEDURE ControlLostFocus*(c: Control);
  958. BEGIN c.focused := FALSE;
  959. T.HideCursor; NeedRedraw(c.app)
  960. END ControlLostFocus;
  961. PROCEDURE ControlClick*(c: Control);
  962. BEGIN IF c.onClick # NIL THEN c.onClick(c) END
  963. END ControlClick;
  964. PROCEDURE ControlDblClick*(c: Control);
  965. BEGIN IF c.onDblClick # NIL THEN c.onDblClick(c) END
  966. END ControlDblClick;
  967. PROCEDURE ControlMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  968. BEGIN
  969. END ControlMouseMove;
  970. PROCEDURE ControlMouseDown*(c: Control; x, y, button: INTEGER);
  971. VAR n: INTEGER;
  972. BEGIN n := ticks;
  973. IF n - c.app.lastMouseDownTime <= dblClickDelay THEN
  974. IF c.do.dblClick # NIL THEN c.do.dblClick(c) END;
  975. c.app.lastMouseDownTime := 0
  976. ELSE c.app.lastMouseDownTime := n
  977. END
  978. END ControlMouseDown;
  979. PROCEDURE ControlMouseUp*(c: Control; x, y, button: INTEGER);
  980. BEGIN
  981. END ControlMouseUp;
  982. PROCEDURE InitControlMethod*(m: ControlMethod);
  983. BEGIN
  984. m.added := NIL;
  985. m.draw := NIL;
  986. m.resize := ControlResize;
  987. m.refresh := NIL;
  988. m.click := ControlClick;
  989. m.dblClick := ControlDblClick;
  990. m.keyDown := NIL;
  991. m.getFocus := ControlGetFocus;
  992. m.lostFocus := ControlLostFocus;
  993. m.mouseMove := ControlMouseMove;
  994. m.mouseDown := ControlMouseDown;
  995. m.mouseUp := ControlMouseUp;
  996. m.close := NIL
  997. END InitControlMethod;
  998. (* Menu *)
  999. PROCEDURE InitMenu*(m: Menu; caption, hint: ARRAY OF CHAR;
  1000. hotkey: INTEGER; onClick: ClickHandler);
  1001. BEGIN InitControl(m);
  1002. m.caption := caption;
  1003. m.innerW := 0; m.innerH := 0;
  1004. m.hint := hint; m.hintW := 0;
  1005. m.hotkey := hotkey;
  1006. m.lastSelected := NIL;
  1007. m.onClick := onClick;
  1008. m.do := menuMethod
  1009. END InitMenu;
  1010. PROCEDURE NewMenu*(caption, hint: ARRAY OF CHAR;
  1011. hotkey: INTEGER; onClick: ClickHandler): Menu;
  1012. VAR m: Menu;
  1013. BEGIN NEW(m); InitMenu(m, caption, hint, hotkey, onClick) ;
  1014. RETURN m END NewMenu;
  1015. PROCEDURE DrawMenuCaption(m: Control; x, y: INTEGER);
  1016. VAR i, w, bg, fg: INTEGER;
  1017. hl: BOOLEAN; (* Highlighted letter *)
  1018. BEGIN
  1019. INC(x, m.x); INC(y, m.y); w := m.w - 2;
  1020. IF m.caption = '-' THEN
  1021. T.Fill(x, y, m.w, 1, T.lineHor, 0, 7); (* - *)
  1022. T.SetCell(x - 1, y, T.lineVertRight, 0, 7);
  1023. T.SetCell(x + w + 2, y, T.lineVertLeft, 0, 7)
  1024. ELSE
  1025. IF (m.status = selected) OR (m.status = open) THEN bg := 2
  1026. ELSE bg := 7
  1027. END;
  1028. T.SetCell(x, y, ' ', 0, bg); INC(x);
  1029. i := 0; hl := FALSE;
  1030. WHILE m.caption[i] # 0X DO
  1031. IF (m.caption[i] = '&') & ~hl THEN hl := TRUE
  1032. ELSE
  1033. IF m.status = disabled THEN fg := 8
  1034. ELSIF hl & (m.caption[i] # '&') THEN fg := 4
  1035. ELSE fg := 0
  1036. END;
  1037. T.SetCell(x, y, m.caption[i], fg, bg);
  1038. DEC(w); INC(x); hl := FALSE
  1039. END;
  1040. INC(i)
  1041. END;
  1042. T.SetCell(x, y, ' ', 0, bg); INC(x);
  1043. WHILE w > 0 DO
  1044. T.SetCell(x, y, ' ', 0, bg);
  1045. DEC(w); INC(x)
  1046. END;
  1047. IF m.status = disabled THEN fg := 8 ELSE fg := 0 END;
  1048. IF m(Menu).hint[0] # 0X THEN
  1049. T.Print(x - m(Menu).hintW - 1, y, -1, m(Menu).hint, fg, bg)
  1050. ELSIF (m.children # NIL) & (m.y # 0) THEN
  1051. T.SetCell(x - 2, y, T.triangleRight, fg, bg)
  1052. END
  1053. END
  1054. END DrawMenuCaption;
  1055. PROCEDURE DrawSubmenuFrame(x, y, w, h: INTEGER);
  1056. VAR i: INTEGER;
  1057. BEGIN
  1058. T.Fill(x, y, 1, h, ' ', 0, 7);
  1059. T.Fill(x + 1, y + 1, 1, h - 2, T.lineVert, 0, 7); (* | *)
  1060. T.Fill(x + w - 2, y + 1, 1, h - 2, T.lineVert, 0, 7);
  1061. T.Fill(x + w - 1, y, 1, h, ' ', 0, 7);
  1062. T.Fill(x + 2, y, w - 4, h, ' ', 0, 7);
  1063. T.Fill(x + 2, y, w - 4, 1, T.lineHor, 0, 7); (* - *)
  1064. T.Fill(x + 2, y + h - 1, w - 4, 1, T.lineHor, 0, 7);
  1065. T.SetCell(x + 1, y, T.lineDownRight, 0, 7); (* Corners *)
  1066. T.SetCell(x + w - 2, y, T.lineDownLeft, 0, 7); (* Corners *)
  1067. T.SetCell(x + w - 2, y + h - 1, T.lineUpLeft, 0, 7); (* Corners *)
  1068. T.SetCell(x + 1, y + h - 1, T.lineUpRight, 0, 7); (* Corners *)
  1069. FOR i := y + 1 TO y + h DO
  1070. SetCharColor(x + w, i, 8, 0);
  1071. SetCharColor(x + w + 1, i, 8, 0)
  1072. END;
  1073. FOR i := x + 2 TO x + w - 1 DO SetCharColor(i, y + h, 8, 0) END;
  1074. END DrawSubmenuFrame;
  1075. PROCEDURE MenuDraw(c: Control; x, y: INTEGER);
  1076. VAR p, openMenu: Control;
  1077. w, h, tW, tH: INTEGER;
  1078. BEGIN T.Size(tW, tH); DrawMenuCaption(c, x, y);
  1079. IF c.status = open THEN
  1080. INC(x, c.x); INC(y, c.y);
  1081. IF c.parent # c.app.menu THEN INC(x) END; (* 2nd+-level menus *)
  1082. IF c.children # NIL THEN
  1083. w := c(Menu).innerW; h := c(Menu).innerH;
  1084. IF x + w + 3 > tW THEN x := tW - w - 3 END;
  1085. DrawSubmenuFrame(x - 1, y + 1, w + 4, h + 2);
  1086. p := c.children; openMenu := NIL;
  1087. REPEAT (* Don't draw the submenu until all items are drawn *)
  1088. IF p.status = open THEN openMenu := p; p.status := selected END;
  1089. p.do.draw(p, x, y); p := p.next
  1090. UNTIL p = c.children;
  1091. IF openMenu # NIL THEN
  1092. openMenu.status := open; openMenu.do.draw(openMenu, x, y)
  1093. END
  1094. END
  1095. END
  1096. END MenuDraw;
  1097. PROCEDURE MenuRefresh(m: Control);
  1098. VAR i, w: INTEGER; esc: BOOLEAN;
  1099. BEGIN w := 2; i := 0; esc := FALSE;
  1100. WHILE m.caption[i] # 0X DO
  1101. IF (m.caption[i] = '&') & ~esc THEN esc := TRUE
  1102. ELSE INC(w); esc := FALSE
  1103. END;
  1104. INC(i)
  1105. END;
  1106. i := Strings.Length(m(Menu).hint);
  1107. IF i # 0 THEN INC(w, i + 4); m(Menu).hintW := i END;
  1108. m.w := w; m.h := 1
  1109. END MenuRefresh;
  1110. (* Returns the first child with status = selected,
  1111. or just the first non-disabled child, or NIL. *)
  1112. PROCEDURE FindSelectedChild(c: Control): Control;
  1113. VAR p: Control;
  1114. BEGIN p := c.children;
  1115. WHILE (p # NIL) & (p.status # selected) & (p # c(Menu).lastSelected) DO
  1116. IF p.next = c.children THEN p := NIL ELSE p := p.next END
  1117. END;
  1118. IF (p = NIL) OR (p.status = disabled) THEN
  1119. p := c.children;
  1120. WHILE (p # NIL) & ((p.status = disabled) OR (p.caption = '-')) DO
  1121. IF p.next = c.children THEN p := NIL ELSE p := p.next END
  1122. END
  1123. END;
  1124. IF p # NIL THEN p.status := selected END
  1125. RETURN p END FindSelectedChild;
  1126. PROCEDURE MenuHotkey*(c: Control; ch: CHAR): BOOLEAN;
  1127. VAR i: INTEGER; x: CHAR;
  1128. BEGIN i := 0; x := c.caption[0];
  1129. WHILE (x # 0X) & ~((x = '&') & (c.caption[i + 1] # '&')) DO
  1130. IF (x = '&') & (c.caption[i + 1] = '&') THEN INC(i, 2) ELSE INC(i) END;
  1131. x := c.caption[i]
  1132. END
  1133. RETURN (c.caption[i] # 0X) & (Cap(c.caption[i + 1]) = Cap(ch)) END MenuHotkey;
  1134. PROCEDURE MenuKeyDown*(c: Control; VAR E: T.Event);
  1135. VAR p, p2, br: Control; found: BOOLEAN;
  1136. BEGIN
  1137. IF (E.key = T.kUp) OR (E.key = T.kDown) THEN
  1138. IF c.parent # c.app.menu THEN p := c;
  1139. REPEAT
  1140. IF E.key = T.kUp THEN p := p.prev ELSE p := p.next END
  1141. UNTIL (p = c) OR (p.caption # '-') & (p.status # disabled);
  1142. c.status := normal; p.status := selected; SetFocus(p);
  1143. NeedRedraw(c.app)
  1144. END
  1145. ELSIF (E.key = T.kLeft) OR (E.key = T.kRight) THEN p := c;
  1146. WHILE p.parent # p.app.menu DO p := p.parent END;
  1147. IF E.key = T.kLeft THEN p := p.prev ELSE p := p.next END;
  1148. p.status := open;
  1149. p2 := FindSelectedChild(p);
  1150. IF p2 = NIL THEN p2 := p END;
  1151. SetFocus(p2);
  1152. NeedRedraw(c.app)
  1153. ELSIF E.key = T.kEnter THEN c.do.click(c)
  1154. ELSIF E.key = T.kEsc THEN
  1155. IF (c.parent.parent = NIL) OR (c.parent.parent.parent = NIL) THEN
  1156. c.parent.status := normal; UnsetFocus(c.app)
  1157. ELSE c.parent.status := selected; SetFocus(c.parent)
  1158. END;
  1159. NeedRedraw(c.app)
  1160. ELSE p := c;
  1161. WHILE (p # NIL) & ~MenuHotkey(p, E.ch) DO
  1162. IF p.next = c THEN p := NIL ELSE p := p.next END
  1163. END;
  1164. IF p # NIL THEN
  1165. c.status := normal; p.status := selected;
  1166. c.parent(Menu).lastSelected := p; p.do.click(p)
  1167. END
  1168. END
  1169. END MenuKeyDown;
  1170. PROCEDURE MenuGetFocus*(c: Control);
  1171. BEGIN ControlGetFocus(c);
  1172. IF c.status = normal THEN c.status := selected; NeedRedraw(c.app) END;
  1173. IF c.parent # NIL THEN c.parent(Menu).lastSelected := c END;
  1174. T.HideCursor
  1175. END MenuGetFocus;
  1176. PROCEDURE MenuLostFocus*(c: Control);
  1177. BEGIN ControlLostFocus(c); c.status := normal; NeedRedraw(c.app)
  1178. END MenuLostFocus;
  1179. PROCEDURE MenuClick*(c: Control);
  1180. VAR p: Control;
  1181. BEGIN
  1182. IF c.children = NIL THEN
  1183. IF c.status # disabled THEN
  1184. UnsetFocus(c.app);
  1185. IF c.onClick # NIL THEN c.onClick(c) END
  1186. END
  1187. ELSE c.status := open;
  1188. p := FindSelectedChild(c);
  1189. IF p = NIL THEN p := c END;
  1190. SetFocus(p)
  1191. END;
  1192. NeedRedraw(c.app)
  1193. END MenuClick;
  1194. PROCEDURE GetMenuAt(app: App; x, y: INTEGER): Control;
  1195. VAR menu, p, br: Control;
  1196. count: INTEGER;
  1197. BEGIN p := NIL;
  1198. IF app.menu.children # NIL THEN
  1199. IF y = 0 THEN p := app.menu.children; br := p;
  1200. WHILE (p # NIL) & (x >= p.x + p.w) DO
  1201. IF p.next = br THEN p := NIL ELSE p := p.next END
  1202. END;
  1203. IF p # NIL THEN DEC(x, p.x) END
  1204. ELSE menu := app.menu;
  1205. REPEAT (* menu := the deepest open menu *)
  1206. p := menu.children; br := p; count := 2;
  1207. WHILE (p # NIL) & (p.status # open) DO
  1208. IF menu = app.menu THEN DEC(x, p.w) ELSE INC(count) END;
  1209. IF p.next = br THEN p := NIL ELSE p := p.next END
  1210. END;
  1211. IF p # NIL THEN
  1212. IF menu # app.menu THEN DEC(y, count); menu.h := count END;
  1213. menu := p
  1214. END
  1215. UNTIL p = NIL;
  1216. IF menu # app.menu THEN
  1217. REPEAT p := menu.children; br := p;
  1218. WHILE (p # NIL) & ~((x >= p.x) & (x < p.x + p.w) & (y = p.y)) DO
  1219. IF p.next = br THEN p := NIL ELSE p := p.next END
  1220. END;
  1221. IF p = NIL THEN menu := menu.parent; INC(y, menu.h) END
  1222. UNTIL (menu = app.menu) OR (p # NIL);
  1223. IF p # NIL THEN DEC(x, p.x); DEC(y, p.y) END
  1224. END
  1225. END
  1226. END
  1227. RETURN p END GetMenuAt;
  1228. PROCEDURE GetStatusbarAt(app: App; x, y: INTEGER): Control;
  1229. VAR p, br: Control;
  1230. tW, tH: INTEGER;
  1231. BEGIN T.Size(tW, tH);
  1232. IF y = tH - 1 THEN
  1233. p := app.statusbar.children; br := p;
  1234. WHILE (p # NIL) & ~((p.x <= x) & (x < p.x + p.w)) DO
  1235. IF p.next = br THEN p := NIL ELSE p := p.next END
  1236. END
  1237. ELSE p := NIL
  1238. END
  1239. RETURN p END GetStatusbarAt;
  1240. PROCEDURE MenuMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  1241. VAR p: Control;
  1242. BEGIN p := c;
  1243. IF c = c.app.menu THEN c := GetMenuAt(c.app, x, y)
  1244. ELSIF c = c.app.statusbar THEN c := GetStatusbarAt(c.app, x, y)
  1245. END;
  1246. IF (c = NIL) & (p = p.app.statusbar) THEN UnsetFocus(p.app)
  1247. ELSIF (c # NIL) & (button = 1(*!FIXME LEFT BTN*)) & (c.status = normal) THEN
  1248. IF c.parent.parent = NIL THEN (* Top level menu *)
  1249. IF c.do.mouseDown # NIL THEN c.do.mouseDown(c, x, y, 1(*!FIXME LEFT*)) END
  1250. ELSE
  1251. IF (c.app.cur # NIL) & (c.app.cur.status # selected) THEN
  1252. c.app.cur.status := selected;
  1253. NeedRedraw(c.app)
  1254. END;
  1255. SetFocus(c)
  1256. END
  1257. END
  1258. END MenuMouseMove;
  1259. PROCEDURE MenuMouseDown*(c: Control; x, y, button: INTEGER);
  1260. VAR p: Control;
  1261. BEGIN
  1262. IF (button = 1(*!FIXME LEFT BTN*)) & (c.status # disabled) THEN
  1263. SetFocus(c);
  1264. p := c; WHILE p.parent # NIL DO p := p.parent END;
  1265. c.app.dragged := p; c.app.dragX := p.x; c.app.dragY := p.y;
  1266. IF c.children = NIL THEN SetFocus(c)
  1267. ELSE c.status := open; p := FindSelectedChild(c);
  1268. IF p = NIL THEN p := c END;
  1269. SetFocus(p); p.status := normal
  1270. END;
  1271. IF c.parent # c.app.menu THEN
  1272. IF c.app.cur # NIL THEN c.app.cur.status := normal END;
  1273. c.status := selected; SetFocus(c)
  1274. END;
  1275. NeedRedraw(c.app)
  1276. END
  1277. END MenuMouseDown;
  1278. PROCEDURE MenuMouseUp*(c: Control; x, y, button: INTEGER);
  1279. VAR p: Control;
  1280. BEGIN
  1281. IF button = 1 THEN
  1282. IF c = c.app.menu THEN p := GetMenuAt(c.app, x, y)
  1283. ELSIF c = c.app.statusbar THEN p := GetStatusbarAt(c.app, x, y)
  1284. ELSE p := c
  1285. END;
  1286. IF p = NIL THEN UnsetFocus(c.app) ELSE p.do.click(p) END
  1287. END
  1288. END MenuMouseUp;
  1289. PROCEDURE RefreshMenu*(c: Control);
  1290. VAR br, p: Control;
  1291. x, y, w: INTEGER;
  1292. BEGIN
  1293. IF c.children # NIL THEN
  1294. w := 0; p := c.children;
  1295. REPEAT p.do.refresh(p);
  1296. IF p.w > w THEN w := p.w END;
  1297. p := p.next
  1298. UNTIL p = c.children;
  1299. y := 2;
  1300. REPEAT p.w := w; p.x := 1; p.y := y; INC(y);
  1301. RefreshMenu(p); p := p.next
  1302. UNTIL p = c.children
  1303. END
  1304. END RefreshMenu;
  1305. PROCEDURE MenuAdded*(c, child: Control);
  1306. BEGIN RefreshMenu(c); INC(c(Menu).innerH);
  1307. IF child.w > c(Menu).innerW THEN c(Menu).innerW := child.w END
  1308. END MenuAdded;
  1309. (* MenuMethod *)
  1310. PROCEDURE InitMenuMethod*(m: ControlMethod);
  1311. BEGIN InitControlMethod(m);
  1312. m.added := MenuAdded;
  1313. m.draw := MenuDraw;
  1314. m.refresh := MenuRefresh;
  1315. m.click := MenuClick;
  1316. m.keyDown := MenuKeyDown;
  1317. m.getFocus := MenuGetFocus;
  1318. m.lostFocus := MenuLostFocus;
  1319. m.mouseMove := MenuMouseMove;
  1320. m.mouseDown := MenuMouseDown;
  1321. m.mouseUp := MenuMouseUp
  1322. END InitMenuMethod;
  1323. (* Label *)
  1324. PROCEDURE InitLabel*(c: Label; caption: ARRAY OF CHAR);
  1325. BEGIN InitControl(c); c.do := labelMethod;
  1326. c.caption := caption; c.len := Strings.Length(caption);
  1327. c.align := left
  1328. END InitLabel;
  1329. PROCEDURE NewLabel*(caption: ARRAY OF CHAR): Label;
  1330. VAR c: Label;
  1331. BEGIN NEW(c); InitLabel(c, caption);
  1332. RETURN c END NewLabel;
  1333. PROCEDURE LabelDraw(c: Control; x, y: INTEGER);
  1334. VAR L: Label; X: INTEGER;
  1335. BEGIN L := c(Label); INC(x, c.x); INC(y, c.y); X := x;
  1336. IF L.align = right THEN INC(X, c.w - L.len)
  1337. ELSIF L.align = center THEN INC(X, (c.w - L.len) DIV 2)
  1338. END;
  1339. T.Print(X, y, x + c.w - 1, c.caption, 0, 7)
  1340. END LabelDraw;
  1341. (* LabelMethod *)
  1342. PROCEDURE InitLabelMethod*(m: ControlMethod);
  1343. BEGIN InitControlMethod(m);
  1344. m.draw := LabelDraw
  1345. END InitLabelMethod;
  1346. (* QuickBtn *)
  1347. PROCEDURE InitQuickBtn*(c: QuickBtn; caption, hint: ARRAY OF CHAR;
  1348. hotkey: INTEGER; onClick: ClickHandler);
  1349. BEGIN InitMenu(c, caption, hint, hotkey, onClick); c.do := quickBtnMethod
  1350. END InitQuickBtn;
  1351. PROCEDURE NewQuickBtn*(caption, hint: ARRAY OF CHAR;
  1352. hotkey: INTEGER; onClick: ClickHandler): QuickBtn;
  1353. VAR c: QuickBtn;
  1354. BEGIN NEW(c); InitQuickBtn(c, caption, hint, hotkey, onClick) ;
  1355. RETURN c END NewQuickBtn;
  1356. PROCEDURE QuickBtnDraw(c: Control; x, y: INTEGER);
  1357. VAR i, w, bg, fg: INTEGER;
  1358. hl: BOOLEAN; (* Highlighted letter *)
  1359. BEGIN INC(x, c.x); INC(y, c.y);
  1360. IF c.status = normal THEN bg := 7 ELSE bg := 2 END;
  1361. T.SetCell(x, y, ' ', 0, bg); INC(x); i := 0;
  1362. WHILE c(Menu).hint[i] # 0X DO
  1363. T.SetCell(x, y, c(Menu).hint[i], 4, bg);
  1364. INC(x); INC(i)
  1365. END;
  1366. T.SetCell(x, y, ' ', 0, bg); INC(x); i := 0;
  1367. WHILE c.caption[i] # 0X DO
  1368. T.SetCell(x, y, c.caption[i], 0, bg);
  1369. INC(x); INC(i)
  1370. END;
  1371. T.SetCell(x, y, ' ', 0, bg)
  1372. END QuickBtnDraw;
  1373. PROCEDURE QuickBtnRefresh(m: Control);
  1374. VAR i, w: INTEGER; esc: BOOLEAN;
  1375. BEGIN
  1376. m.w := Strings.Length(m.caption) + 2;
  1377. i := Strings.Length(m(Menu).hint);
  1378. IF i # 0 THEN INC(m.w, i + 1) END
  1379. END QuickBtnRefresh;
  1380. (* QuickBtnMethod *)
  1381. PROCEDURE InitQuickBtnMethod*(m: ControlMethod);
  1382. BEGIN InitMenuMethod(m);
  1383. m.draw := QuickBtnDraw;
  1384. m.refresh := QuickBtnRefresh
  1385. END InitQuickBtnMethod;
  1386. (* Button *)
  1387. PROCEDURE InitButton*(c: Button; caption: ARRAY OF CHAR);
  1388. BEGIN InitControl(c);
  1389. c.w := 10; c.h := 1;
  1390. c.caption := caption;
  1391. c.do := buttonMethod
  1392. END InitButton;
  1393. PROCEDURE NewButton*(caption: ARRAY OF CHAR): Button;
  1394. VAR c: Button;
  1395. BEGIN NEW(c); InitButton(c, caption) ;
  1396. RETURN c END NewButton;
  1397. (* Button Method *)
  1398. PROCEDURE ButtonDraw*(c: Control; x, y: INTEGER);
  1399. VAR i, n, fg, bg: INTEGER;
  1400. BEGIN INC(x, c.x); INC(y, c.y);
  1401. IF c.status = selected THEN INC(x) END;
  1402. IF (c.parent # NIL) & (c.parent IS Window) THEN bg := c.parent(Window).bg
  1403. ELSE bg := 7
  1404. END;
  1405. T.Fill(x, y, c.w, c.h, ' ', 0, 2);
  1406. i := 0; n := 0;
  1407. WHILE c.caption[i] # 0X DO IF c.caption[i] # '&' THEN INC(n) END; INC(i) END;
  1408. IF n > c.w THEN n := c.w END;
  1409. IF c.focused THEN fg := 15 ELSIF c.default THEN fg := 11 ELSE fg := 0 END;
  1410. PutMarkedString(x + (c.w - n) DIV 2, y + c.h DIV 2,
  1411. c.caption, fg, 14, 2, x + c.w - 1);
  1412. IF c.status # selected THEN
  1413. T.SetCell(x + c.w, y, T.lowerHalfBlock, 0, bg);
  1414. T.Fill(x + c.w, y + 1, 1, c.h - 1, T.fullBlock, 0, bg);
  1415. T.Fill(x + 1, y + c.h, c.w, 1, T.upperHalfBlock, 0, bg)
  1416. END
  1417. END ButtonDraw;
  1418. PROCEDURE ButtonMouseDown*(c: Control; x, y, button: INTEGER);
  1419. BEGIN
  1420. IF (c.parent # NIL) & (c.parent IS Window) THEN
  1421. c.status := selected;
  1422. SetDragged(c.app, c);
  1423. NeedRedraw(c.app)
  1424. END
  1425. END ButtonMouseDown;
  1426. PROCEDURE ButtonMouseUp*(c: Control; x, y, button: INTEGER);
  1427. BEGIN
  1428. IF (c.status = selected) & (c.do.click # NIL) THEN c.do.click(c) END;
  1429. c.status := normal;
  1430. NeedRedraw(c.app)
  1431. END ButtonMouseUp;
  1432. PROCEDURE ButtonMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  1433. VAR status: INTEGER;
  1434. BEGIN
  1435. IF (0 <= x) & (x <= c.w) & (0 <= y) & (y < c.h) THEN status := selected
  1436. ELSE status := normal
  1437. END;
  1438. IF c.status # status THEN c.status := status; NeedRedraw(c.app) END
  1439. END ButtonMouseMove;
  1440. PROCEDURE ButtonClick*(c: Control);
  1441. BEGIN
  1442. IF c.onClick # NIL THEN c.onClick(c) END
  1443. END ButtonClick;
  1444. PROCEDURE InitButtonMethod*(m: ControlMethod);
  1445. BEGIN InitControlMethod(m);
  1446. m.draw := ButtonDraw;
  1447. m.mouseDown := ButtonMouseDown;
  1448. m.mouseUp := ButtonMouseUp;
  1449. m.mouseMove := ButtonMouseMove;
  1450. m.click := ButtonClick
  1451. END InitButtonMethod;
  1452. (* WinBtn *)
  1453. PROCEDURE InitWinBtn*(c: WinBtn; ch: CHAR);
  1454. BEGIN InitButton(c, ''); c.w := 3; c.h := 1;
  1455. c.caption[0] := ch; c.caption[1] := 0X;
  1456. c.do := winBtnMethod
  1457. END InitWinBtn;
  1458. PROCEDURE NewWinBtn*(ch: CHAR): WinBtn;
  1459. VAR c: WinBtn;
  1460. BEGIN NEW(c); InitWinBtn(c, ch) ;
  1461. RETURN c END NewWinBtn;
  1462. (* WinBtn Method *)
  1463. PROCEDURE WinBtnMouseUp*(c: Control; x, y, button: INTEGER);
  1464. BEGIN
  1465. IF c.status = selected THEN
  1466. T.SetCell(c.app.dragX + 1, c.app.dragY,
  1467. c.caption[0], 10, c.parent(Window).bg);
  1468. IF c.do.click # NIL THEN c.do.click(c) END
  1469. END
  1470. END WinBtnMouseUp;
  1471. PROCEDURE WinBtnMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  1472. VAR status: INTEGER; ch: CHAR;
  1473. BEGIN status := c.status;
  1474. ButtonMouseMove(c, x, y, button);
  1475. IF status # c.status THEN
  1476. IF c.status = normal THEN ch := c.caption[0] ELSE ch := 0FX(*star*) END;
  1477. T.SetCell(c.app.dragX + 1, c.app.dragY, ch, 10, c.parent(Window).bg)
  1478. END
  1479. END WinBtnMouseMove;
  1480. PROCEDURE InitWinBtnMethod*(m: ControlMethod);
  1481. BEGIN InitButtonMethod(m);
  1482. m.draw := NIL;
  1483. m.mouseUp := WinBtnMouseUp;
  1484. m.mouseMove := WinBtnMouseMove
  1485. END InitWinBtnMethod;
  1486. (* Scrollbar *)
  1487. PROCEDURE InitScrollbar*(c: Scrollbar);
  1488. BEGIN InitControl(c); c.max := 100; c.runnerOffset := 1; c.runnerW := 5;
  1489. c.w := 30; c.h := 1; c.cur := 0; c.onScrollbar := NIL;
  1490. c.do := scrollbarMethod
  1491. END InitScrollbar;
  1492. PROCEDURE NewScrollbar*(): Scrollbar;
  1493. VAR c: Scrollbar;
  1494. BEGIN NEW(c); InitScrollbar(c) ;
  1495. RETURN c END NewScrollbar;
  1496. PROCEDURE ScrollbarUpdateCur*(S: Scrollbar; x, y: INTEGER; end: BOOLEAN);
  1497. VAR w, oldOff: INTEGER;
  1498. BEGIN oldOff := S.runnerOffset; w := S.w - S.runnerW - 2;
  1499. (* Horizontal scrollbar *)
  1500. DEC(x, S.runnerW DIV 2 + 1);
  1501. IF x < 0 THEN x := 0 ELSIF x > w THEN x := w END;
  1502. S.cur := (x * S.max + w DIV 2) DIV w;
  1503. IF end THEN S.runnerOffset := S.cur * w DIV S.max + 1
  1504. ELSE S.runnerOffset := x + 1
  1505. END;
  1506. IF S.runnerOffset # oldOff THEN
  1507. NeedRedraw(S.app);
  1508. IF S.onScrollbar # NIL THEN S.onScrollbar(S) END
  1509. END
  1510. END ScrollbarUpdateCur;
  1511. PROCEDURE SetScrollbarCur*(S: Scrollbar; cur: INTEGER);
  1512. BEGIN
  1513. IF cur < 0 THEN cur := 0 ELSIF cur > S.max THEN cur := S.max END;
  1514. IF S.cur # cur THEN
  1515. S.cur := cur;
  1516. S.runnerOffset := cur * (S.w - S.runnerW - 2) DIV S.max + 1
  1517. END
  1518. END SetScrollbarCur;
  1519. (* Scrollbar Method *)
  1520. PROCEDURE ScrollbarDraw*(c: Control; x, y: INTEGER);
  1521. VAR S: Scrollbar;
  1522. w, fg, bg: INTEGER;
  1523. ch: CHAR;
  1524. BEGIN S := c(Scrollbar); INC(x, S.x); INC(y, S.y); fg := 3; bg := 1;
  1525. IF S.enabled THEN ch := T.lightShade ELSE ch := T.mediumShade END;
  1526. T.Fill(x + 1, y, S.w - 1, 1, ch, fg, bg);
  1527. T.SetCell(x, y, T.triangleLeft, fg, bg);
  1528. T.SetCell(x + S.w - 1, y, T.triangleRight, fg, bg);
  1529. IF S.enabled THEN
  1530. T.Fill(x + S.runnerOffset, y, S.runnerW, 1, T.mediumShade, fg, bg)
  1531. END
  1532. END ScrollbarDraw;
  1533. PROCEDURE ScrollbarMouseDown*(c: Control; x, y, button: INTEGER);
  1534. VAR S: Scrollbar;
  1535. col, colw: INTEGER;
  1536. BEGIN S := c(Scrollbar);
  1537. IF S.enabled & (button = 1(*!FIXME BTN LEFT*)) THEN
  1538. SetDragged(S.app, S);
  1539. ScrollbarUpdateCur(S, x, y, FALSE)
  1540. END
  1541. END ScrollbarMouseDown;
  1542. PROCEDURE ScrollbarMouseUp*(c: Control; x, y, button: INTEGER);
  1543. VAR S: Scrollbar;
  1544. col, colw: INTEGER;
  1545. BEGIN S := c(Scrollbar);
  1546. IF S.enabled & (button = 1(*!FIXME BTN LEFT*)) THEN
  1547. ScrollbarUpdateCur(S, x, y, TRUE);
  1548. SetFocus(S.parent)
  1549. END
  1550. END ScrollbarMouseUp;
  1551. PROCEDURE ScrollbarMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  1552. VAR S: Scrollbar;
  1553. oldCur, col, colw: INTEGER;
  1554. BEGIN S := c(Scrollbar);
  1555. IF button = 1 (*!FIXME BTN LEFT*) THEN ScrollbarUpdateCur(S, x, y, FALSE) END
  1556. END ScrollbarMouseMove;
  1557. PROCEDURE InitScrollbarMethod*(m: ControlMethod);
  1558. BEGIN InitControlMethod(m);
  1559. m.draw := ScrollbarDraw;
  1560. m.mouseDown := ScrollbarMouseDown;
  1561. m.mouseUp := ScrollbarMouseUp;
  1562. m.mouseMove := ScrollbarMouseMove
  1563. END InitScrollbarMethod;
  1564. (* Edit *)
  1565. PROCEDURE InitEdit*(c: Edit);
  1566. BEGIN InitControl(c);
  1567. c.w := 10; c.h := 1; c.len := 0; c.pos := 0;
  1568. c.do := editMethod
  1569. END InitEdit;
  1570. PROCEDURE NewEdit*(): Edit;
  1571. VAR c: Edit;
  1572. BEGIN NEW(c); InitEdit(c) ;
  1573. RETURN c END NewEdit;
  1574. (* Edit Method *)
  1575. PROCEDURE EditSetCaption*(c: Edit; s: ARRAY OF CHAR);
  1576. VAR i: INTEGER;
  1577. BEGIN i := 0;
  1578. WHILE (s[i] # 0X) & (i < LEN(c.caption) - 1) DO
  1579. c.caption[i] := s[i]; INC(i)
  1580. END;
  1581. c.caption[i] := 0X; c.len := i; c.pos := i;
  1582. NeedRedraw(c.app)
  1583. END EditSetCaption;
  1584. PROCEDURE InsertChar(ch: CHAR; pos: INTEGER;
  1585. VAR s: ARRAY OF CHAR; VAR len: INTEGER);
  1586. VAR i: INTEGER;
  1587. BEGIN
  1588. IF len + 1 < LEN(s) THEN
  1589. FOR i := len TO pos + 1 BY -1 DO s[i] := s[i - 1] END;
  1590. s[pos] := ch; INC(len); s[len] := 0X
  1591. END
  1592. END InsertChar;
  1593. PROCEDURE DeleteChar(VAR s: ARRAY OF CHAR;
  1594. pos: INTEGER; VAR len: INTEGER);
  1595. VAR i: INTEGER;
  1596. BEGIN
  1597. FOR i := pos TO len - 1 DO s[i] := s[i + 1] END;
  1598. DEC(len); s[len] := 0X
  1599. END DeleteChar;
  1600. PROCEDURE EditDraw*(c: Control; x, y: INTEGER);
  1601. VAR i, j: INTEGER; e: Edit;
  1602. BEGIN e := c(Edit); INC(x, e.x); INC(y, e.y);
  1603. T.SetCell(x, y, ' ', 0, 1);
  1604. i := 0; j := x + 1;
  1605. WHILE (e.caption[i] # 0X) & (i < e.w - 1) DO
  1606. T.SetCell(j, y, e.caption[i], 15, 1); INC(i); INC(j)
  1607. END;
  1608. WHILE i < e.w - 1 DO
  1609. T.SetCell(j, y, ' ', 15, 1); INC(i); INC(j)
  1610. END;
  1611. i := e.pos + 1; IF i >= e.w THEN i := e.w - 1 END;
  1612. IF c.app.cur = c THEN T.SetCursor(x + i, y) END
  1613. END EditDraw;
  1614. PROCEDURE EditMouseDown*(c: Control; x, y, edit: INTEGER);
  1615. BEGIN (*!TODO*)
  1616. END EditMouseDown;
  1617. PROCEDURE EditKeyDown*(c: Control; VAR E: T.Event);
  1618. VAR e: Edit; redraw: BOOLEAN;
  1619. BEGIN e := c(Edit); redraw := TRUE;
  1620. IF E.key = T.kLeft THEN
  1621. IF e.pos > 0 THEN DEC(e.pos) END
  1622. ELSIF E.key = T.kRight THEN
  1623. IF e.pos < e.len THEN INC(e.pos) END
  1624. ELSIF E.key = T.kBackspace THEN
  1625. IF e.pos > 0 THEN DeleteChar(e.caption, e.pos - 1, e.len); DEC(e.pos) END
  1626. ELSIF E.key = T.kDel THEN
  1627. IF e.pos < e.len THEN DeleteChar(e.caption, e.pos, e.len) END
  1628. ELSIF E.key = T.kHome THEN e.pos := 0
  1629. ELSIF E.key = T.kEnd THEN e.pos := e.len
  1630. ELSE redraw := FALSE
  1631. END;
  1632. IF redraw THEN NeedRedraw(c.app) END
  1633. END EditKeyDown;
  1634. PROCEDURE EditTextInput*(c: Control; ch: CHAR);
  1635. VAR e: Edit;
  1636. BEGIN
  1637. IF ch # 0X THEN e := c(Edit);
  1638. InsertChar(ch, e.pos, e.caption, e.len);
  1639. IF e.pos < e.len THEN INC(e.pos) END;
  1640. NeedRedraw(c.app)
  1641. END
  1642. END EditTextInput;
  1643. PROCEDURE EditGetFocus*(c: Control);
  1644. BEGIN ControlGetFocus(c); T.SetCursor(c.x, c.y) (*!FIXME c.x, c.y correct???*)
  1645. END EditGetFocus;
  1646. PROCEDURE InitEditMethod*(m: ControlMethod);
  1647. BEGIN InitControlMethod(m);
  1648. m.draw := EditDraw;
  1649. m.getFocus := EditGetFocus;
  1650. m.mouseDown := EditMouseDown;
  1651. m.keyDown := EditKeyDown;
  1652. m.textInput := EditTextInput
  1653. END InitEditMethod;
  1654. (* ColumnList *)
  1655. PROCEDURE InitColumnList*(c: ColumnList);
  1656. BEGIN InitControl(c); c.cols := 2; c.items := StrList.New();
  1657. c.w := 30; c.h := 6; c.cur := 0; c.lastMouseDownItem := -1;
  1658. c.scrollbar := NewScrollbar();
  1659. Add(c, c.scrollbar);
  1660. c.do.resize(c, 0, c.h - 1, c.w, 1);
  1661. c.do := columnListMethod
  1662. END InitColumnList;
  1663. PROCEDURE NewColumnList*(): ColumnList;
  1664. VAR c: ColumnList;
  1665. BEGIN NEW(c); InitColumnList(c) ;
  1666. RETURN c END NewColumnList;
  1667. (* ColumnList Method *)
  1668. PROCEDURE ColumnListSetCur*(C: ColumnList; cur: INTEGER);
  1669. VAR sb: Scrollbar;
  1670. h, count, oldCur, sbCur, oldSbCur: INTEGER;
  1671. BEGIN sb := C.scrollbar;
  1672. sbCur := sb.cur; oldSbCur := sbCur;
  1673. h := C.h - 1; count := StrList.Count(C.items);
  1674. IF cur < 0 THEN cur := 0 ELSIF cur >= count THEN cur := count - 1 END;
  1675. IF cur < sbCur * h THEN sbCur := cur DIV h
  1676. ELSIF cur >= (sbCur + C.cols - 1) * h THEN sbCur := cur DIV h - C.cols + 1
  1677. END;
  1678. IF sbCur < 0 THEN sbCur := 0 ELSIF sbCur > sb.max THEN sbCur := sb.max END;
  1679. IF sbCur # oldSbCur THEN SetScrollbarCur(sb, sbCur) END;
  1680. IF C.cur # cur THEN C.cur := cur;
  1681. IF C.onChange # NIL THEN C.onChange(C) END;
  1682. NeedRedraw(C.app)
  1683. END
  1684. END ColumnListSetCur;
  1685. PROCEDURE ColumnListDraw*(c: Control; x, y: INTEGER);
  1686. VAR i, x2, y2, colw, fg, bg: INTEGER;
  1687. C: ColumnList;
  1688. s: ARRAY 256 OF CHAR;
  1689. BEGIN C := c(ColumnList); INC(x, C.x); INC(y, C.y);
  1690. bg := 3; x2 := x + 1; y2 := y;
  1691. colw := (C.w - C.cols + 1) DIV C.cols;
  1692. T.Fill(x, y, C.w, C.h - 1, ' ', 0, bg);
  1693. (* Column separators *)
  1694. i := x + colw;
  1695. WHILE i < x + C.w - 2 DO
  1696. T.Fill(i, y, 1, C.h - 1, T.lineVert, 1, bg); INC(i, colw + 1)
  1697. END;
  1698. i := C.scrollbar.cur * (C.h - 1);
  1699. StrList.SetPos(C.items, i);
  1700. StrList.Next(C.items, s);
  1701. WHILE ~C.items.eol & (x2 + colw <= x + C.w) DO fg := 0; bg := 3;
  1702. IF i = C.cur THEN
  1703. IF C.focused THEN fg := 15; bg := 2;
  1704. T.Fill(x2 - 1, y2, colw, 1, ' ', fg, bg)
  1705. ELSE fg := 14
  1706. END
  1707. END;
  1708. T.Print(x2, y2, colw - 1, s, fg, bg);
  1709. IF y2 < y + C.h - 2 THEN INC(y2) ELSE y2 := y; INC(x2, colw + 1) END;
  1710. StrList.Next(C.items, s); INC(i)
  1711. END;
  1712. DrawChildren(c, x - C.x, y - C.y)
  1713. END ColumnListDraw;
  1714. PROCEDURE ColumnListGetFocus*(c: Control);
  1715. BEGIN ControlGetFocus(c)
  1716. END ColumnListGetFocus;
  1717. PROCEDURE ColumnListUpdateCur*(C: ColumnList; x, y: INTEGER);
  1718. VAR h, cur, col, colw, count: INTEGER;
  1719. BEGIN h := C.h - 1;
  1720. IF (x < 0) OR (x >= C.w) THEN
  1721. (*!TODO autoscroll*)
  1722. (*IF ... THEN NeedRedraw(C.app) END*)
  1723. ELSIF y # h THEN cur := C.cur;
  1724. IF y < 0 THEN (* Scroll to top within column *)
  1725. cur := (cur DIV h) * h
  1726. ELSIF y >= C.h THEN (* Scroll to bottom within column *)
  1727. cur := cur DIV h * h + h - 1
  1728. ELSE
  1729. colw := (C.w - C.cols + 1) DIV C.cols;
  1730. col := x DIV (colw + 1);
  1731. cur := col * h + y + C.scrollbar.cur * h
  1732. END;
  1733. count := StrList.Count(C.items);
  1734. IF cur >= count THEN cur := count - 1 END;
  1735. ColumnListSetCur(C, cur)
  1736. END
  1737. END ColumnListUpdateCur;
  1738. PROCEDURE ColumnListMouseDown*(c: Control; x, y, button: INTEGER);
  1739. VAR C: ColumnList;
  1740. col, colw, n: INTEGER;
  1741. BEGIN C := c(ColumnList);
  1742. IF ~PassMouseDown(C, x, y, button) &
  1743. (C.parent # NIL) & (C.parent IS Window) THEN
  1744. C.status := selected;
  1745. SetDragged(C.app, C);
  1746. ColumnListUpdateCur(C, x, y);
  1747. n := ticks;
  1748. IF (n - C.app.lastMouseDownTime <= dblClickDelay) &
  1749. (C.lastMouseDownItem = C.cur)
  1750. THEN
  1751. IF C.do.dblClick # NIL THEN C.do.dblClick(C) END;
  1752. C.app.lastMouseDownTime := 0
  1753. ELSE C.app.lastMouseDownTime := n;
  1754. C.lastMouseDownItem := C.cur;
  1755. NeedRedraw(C.app)
  1756. END
  1757. END
  1758. END ColumnListMouseDown;
  1759. PROCEDURE ColumnListMouseUp*(c: Control; x, y, button: INTEGER);
  1760. BEGIN ControlMouseUp(c, x, y, button);
  1761. IF (c.status = selected) & (c.do.click # NIL) THEN c.do.click(c) END
  1762. END ColumnListMouseUp;
  1763. PROCEDURE ColumnListMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  1764. VAR C: ColumnList;
  1765. oldCur, col, colw: INTEGER;
  1766. BEGIN ControlMouseMove(c, x, y, button); C := c(ColumnList);
  1767. IF button = 1 THEN ColumnListUpdateCur(C, x, y) END
  1768. END ColumnListMouseMove;
  1769. PROCEDURE ColumnListKeyDown*(c: Control; VAR E: T.Event);
  1770. VAR C: ColumnList; sb: Scrollbar;
  1771. h, cur: INTEGER;
  1772. BEGIN C := c(ColumnList); sb := C.scrollbar; cur := C.cur; h := C.h - 1;
  1773. IF E.key = T.kLeft THEN DEC(cur, h)
  1774. ELSIF E.key = T.kRight THEN INC(cur, h)
  1775. ELSIF E.key = T.kUp THEN DEC(cur)
  1776. ELSIF E.key = T.kDown THEN INC(cur)
  1777. ELSIF E.key = T.kHome THEN cur := sb.cur * h
  1778. ELSIF E.key = T.kEnd THEN cur := (sb.cur + C.cols) * h - 1
  1779. ELSIF E.key = T.kPgUp THEN DEC(cur, C.cols * h); DEC(sb.cur, C.cols)
  1780. ELSIF E.key = T.kPgDn THEN INC(cur, C.cols * h); INC(sb.cur, C.cols)
  1781. END;
  1782. ColumnListSetCur(C, cur)
  1783. END ColumnListKeyDown;
  1784. PROCEDURE ColumnListRefresh*(c: Control);
  1785. VAR C: ColumnList;
  1786. cols, w: INTEGER; (* Total amount of columns in the list *)
  1787. BEGIN C := c(ColumnList);
  1788. cols := StrList.Count(C.items) DIV (C.h - 1) + 1;
  1789. IF cols > C.cols THEN
  1790. C.scrollbar.max := cols - C.cols;
  1791. w := (C.w - 2) DIV (C.scrollbar.max + 1);
  1792. IF w < 3 THEN w := 3 END;
  1793. C.scrollbar.runnerW := w
  1794. END;
  1795. SetEnabled(C.scrollbar, cols > C.cols)
  1796. END ColumnListRefresh;
  1797. PROCEDURE ColumnListResize*(c: Control; x, y, w, h: INTEGER);
  1798. VAR C: ColumnList;
  1799. BEGIN C := c(ColumnList);
  1800. ControlResize(c, x, y, w, h);
  1801. C.scrollbar.do.resize(C.scrollbar, 0, C.h - 1, w, 1);
  1802. C.do.refresh(C)
  1803. END ColumnListResize;
  1804. PROCEDURE FindFirstLetterInList(L: StrList.List; ch: CHAR): INTEGER;
  1805. VAR s: ARRAY 3 OF CHAR; n: INTEGER;
  1806. BEGIN StrList.First(L, s); n := 0;
  1807. WHILE ~L.eol & ~((Cap(s[0]) = ch) OR (s[0] = '[') & (Cap(s[1]) = ch)) DO
  1808. StrList.Next(L, s); INC(n)
  1809. END;
  1810. IF L.eol THEN n := -1 END
  1811. RETURN n END FindFirstLetterInList;
  1812. PROCEDURE ColumnListTextInput*(c: Control; ch: CHAR);
  1813. VAR C: ColumnList; n: INTEGER;
  1814. BEGIN C := c(ColumnList);
  1815. IF ch # 0X THEN
  1816. n := FindFirstLetterInList(C.items, Cap(ch));
  1817. IF n # -1 THEN ColumnListSetCur(C, n) END
  1818. END
  1819. END ColumnListTextInput;
  1820. PROCEDURE InitColumnListMethod*(m: ControlMethod);
  1821. BEGIN InitControlMethod(m);
  1822. m.draw := ColumnListDraw;
  1823. m.getFocus := ColumnListGetFocus;
  1824. m.mouseDown := ColumnListMouseDown;
  1825. m.mouseUp := ColumnListMouseUp;
  1826. m.mouseMove := ColumnListMouseMove;
  1827. m.keyDown := ColumnListKeyDown;
  1828. m.textInput := ColumnListTextInput;
  1829. m.refresh := ColumnListRefresh;
  1830. m.resize := ColumnListResize
  1831. END InitColumnListMethod;
  1832. (* Standard Click Handlers *)
  1833. PROCEDURE QuitApp*(c: Control);
  1834. BEGIN c.app.quit := TRUE
  1835. END QuitApp;
  1836. PROCEDURE NextWindow*(c: Control);
  1837. BEGIN
  1838. IF c.app.windows # NIL THEN
  1839. c.app.windows := c.app.windows.next(Window);
  1840. SetFocus(c.app.windows);
  1841. NeedRedraw(c.app)
  1842. END
  1843. END NextWindow;
  1844. PROCEDURE PrevWindow*(c: Control);
  1845. BEGIN
  1846. IF c.app.windows # NIL THEN
  1847. c.app.windows := c.app.windows.prev(Window);
  1848. SetFocus(c.app.windows);
  1849. NeedRedraw(c.app)
  1850. END
  1851. END PrevWindow;
  1852. PROCEDURE ZoomCurWindow*(c: Control);
  1853. VAR w: Window;
  1854. tW, tH: INTEGER;
  1855. BEGIN T.Size(tW, tH); w := c.app.windows(Window);
  1856. IF w # NIL THEN
  1857. IF (w.x = 0) & (w.w = tW) &
  1858. (w.y = 1) & (w.h = tH - 2) THEN
  1859. w.x := w.mx; w.y := w.my; w.w := w.mw; w.h := w.mh
  1860. ELSE
  1861. w.mx := w.x; w.my := w.y; w.mw := w.w; w.mh := w.h;
  1862. w.x := 0; w.w := tW;
  1863. w.y := 1; w.h := tH - 2
  1864. END;
  1865. NeedRedraw(c.app)
  1866. END
  1867. END ZoomCurWindow;
  1868. PROCEDURE CloseCurWindowEx*(c: Control; VAR cancel: BOOLEAN);
  1869. VAR w: Window;
  1870. BEGIN w := c.app.windows; cancel := FALSE;
  1871. IF w # NIL THEN
  1872. IF w.do.close # NIL THEN w.do.close(w, cancel) END;
  1873. IF ~cancel THEN
  1874. IF w.next = w THEN c.app.windows := NIL
  1875. ELSE
  1876. w.prev.next := w.next;
  1877. w.next.prev := w.prev;
  1878. c.app.windows := w.prev(Window)
  1879. END;
  1880. SetAppFocus(c.app, c.app.windows);
  1881. NeedRedraw(c.app)
  1882. END
  1883. END
  1884. END CloseCurWindowEx;
  1885. PROCEDURE CloseCurWindow*(c: Control);
  1886. VAR cancel: BOOLEAN;
  1887. BEGIN CloseCurWindowEx(c, cancel)
  1888. END CloseCurWindow;
  1889. PROCEDURE CloseAllWindows*(c: Control);
  1890. VAR cancel: BOOLEAN;
  1891. BEGIN cancel := FALSE;
  1892. WHILE ~cancel & (c.app.windows # NIL) DO CloseCurWindowEx(c, cancel) END
  1893. END CloseAllWindows;
  1894. PROCEDURE RefreshDisplay*(c: Control);
  1895. BEGIN T.ClearTo(0, 7); NeedRedraw(c.app); c.app.sync := TRUE
  1896. END RefreshDisplay;
  1897. (* Window *)
  1898. PROCEDURE InitWindow*(w: Window);
  1899. VAR tW, tH: INTEGER;
  1900. BEGIN InitControl(w); T.Size(tW, tH);
  1901. w.cur := NIL;
  1902. w.x := 0; w.y := 1;
  1903. w.w := tW; w.h := tH - 2;
  1904. w.mx := 0; w.my := 1; w.mw := w.w; w.mh := w.h;
  1905. w.modal := FALSE; w.resizable := FALSE;
  1906. w.closeable := TRUE; w.closeOnEsc := TRUE;
  1907. w.bg := 7; w.minW := 10; w.minH := 3;
  1908. w.closeBtn := NewWinBtn(T.blackSquare); (* Square *)
  1909. w.closeBtn.x := 2; w.closeBtn.w := 3;
  1910. w.closeBtn.parent := w;
  1911. w.closeBtn.onClick := CloseCurWindow;
  1912. w.zoomBtn := NewWinBtn(12X); (* Up-down arrow *)
  1913. w.zoomBtn.w := 3; w.zoomBtn.parent := w;
  1914. w.zoomBtn.onClick := ZoomCurWindow;
  1915. w.do := windowMethod
  1916. END InitWindow;
  1917. PROCEDURE NewWindow*(): Window;
  1918. VAR w: Window;
  1919. BEGIN NEW(w); InitWindow(w); RETURN w
  1920. END NewWindow;
  1921. PROCEDURE HasModalWindow*(app: App): BOOLEAN;
  1922. BEGIN
  1923. RETURN (app.windows # NIL) & app.windows.modal
  1924. END HasModalWindow;
  1925. PROCEDURE CenterWindow*(c: Window);
  1926. VAR tW, tH: INTEGER;
  1927. BEGIN T.Size(tW, tH);
  1928. c.x := (tW - c.w) DIV 2; c.y := (tH - c.h - 1) DIV 2;
  1929. IF c.x < 0 THEN c.x := 0 END;
  1930. IF c.y < 1 THEN c.y := 1 END
  1931. END CenterWindow;
  1932. (* WindowMethod *)
  1933. PROCEDURE WindowAdded*(c, child: Control);
  1934. BEGIN
  1935. IF c(Window).cur = NIL THEN c(Window).cur := child END
  1936. END WindowAdded;
  1937. PROCEDURE WindowDraw*(c: Control; x, y: INTEGER);
  1938. BEGIN
  1939. T.Fill(c.x + 1, c.y + 1,
  1940. c.w - 2, c.h - 2, ' ', 15, c(Window).bg);
  1941. DrawWindowBorder(c.x, c.y, c.w, c.h, 15,
  1942. c(Window).bg, c.caption, c(Window).resizable,
  1943. c.status # normal, c # c.app.windows);
  1944. DrawChildren(c, x, y)
  1945. END WindowDraw;
  1946. PROCEDURE WindowRefresh*(c: Control);
  1947. VAR tW, tH: INTEGER;
  1948. BEGIN T.Size(tW, tH);
  1949. IF c(Window).zoomBtn # NIL THEN
  1950. IF (c.x = 0) & (c.w = tW) & (c.y = 1) & (c.h = tH - 2) THEN
  1951. c(Window).zoomBtn.caption[0] := 12X
  1952. ELSE c(Window).zoomBtn.caption[0] := 18X
  1953. END
  1954. END
  1955. END WindowRefresh;
  1956. PROCEDURE WindowResize*(c: Control; x, y, w, h: INTEGER);
  1957. BEGIN ControlResize(c, x, y, w, h);
  1958. IF c.do.refresh # NIL THEN c.do.refresh(c) END
  1959. END WindowResize;
  1960. PROCEDURE WindowCloseMouseDown(c: Control);
  1961. BEGIN c.app.dragged := c(Window).closeBtn;
  1962. c(Window).closeBtn.status := selected;
  1963. c.app.dragX := c.x + 2; c.app.dragY := c.y;
  1964. T.SetCell(c.x + 3, c.y, 0FX, 10, c(Window).bg) (* star *)
  1965. END WindowCloseMouseDown;
  1966. PROCEDURE WindowZoomMouseDown(c: Control);
  1967. BEGIN c.app.dragged := c(Window).zoomBtn;
  1968. c(Window).zoomBtn.status := selected;
  1969. c(Window).zoomBtn.x := c.w - 5;
  1970. c.app.dragX := c.x + c.w - 5; c.app.dragY := c.y;
  1971. T.SetCell(c.x + c.w - 4, c.y, 0FX, 10, c(Window).bg) (* star *)
  1972. END WindowZoomMouseDown;
  1973. PROCEDURE WindowMoveStart(c: Control; x: INTEGER);
  1974. BEGIN
  1975. c.app.dragX := c.x; c.app.dragY := c.y;
  1976. c(Window).mx := c.x - x; (* For calculations in move handler *)
  1977. c.status := moving; NeedRedraw(c.app)
  1978. END WindowMoveStart;
  1979. PROCEDURE WindowResizeStart(c: Control; x: INTEGER);
  1980. BEGIN
  1981. c.app.dragX := c.x; c.app.dragY := c.y;
  1982. c(Window).mx := c.w - x; (* For calculations in resize handler *)
  1983. c.status := resizing; NeedRedraw(c.app)
  1984. END WindowResizeStart;
  1985. PROCEDURE BringToFront*(c: Control);
  1986. BEGIN c.prev.next := c.next; c.next.prev := c.prev;
  1987. c.app.windows.next.prev := c; c.next := c.app.windows.next;
  1988. c.app.windows.next := c; c.prev := c.app.windows;
  1989. c.app.windows := c(Window);
  1990. SetFocus(c);
  1991. NeedRedraw(c.app)
  1992. END BringToFront;
  1993. PROCEDURE WindowMouseDown*(c: Control; x, y, button: INTEGER);
  1994. VAR p, br: Control;
  1995. BEGIN
  1996. IF button # 2 THEN
  1997. SetFocus(c);
  1998. IF c.app.windows # c THEN BringToFront(c)
  1999. ELSIF y = 0 THEN
  2000. IF c(Window).closeable & (2 <= x) & (x <= 4) THEN
  2001. WindowCloseMouseDown(c)
  2002. ELSIF c(Window).resizable & (c.w - 5 <= x) & (x <= c.w - 3) THEN
  2003. WindowZoomMouseDown(c)
  2004. ELSE WindowMoveStart(c, x)
  2005. END
  2006. ELSIF y = c.h - 1 THEN
  2007. IF c(Window).resizable & (x >= c.w - 2) THEN
  2008. WindowResizeStart(c, x)
  2009. END
  2010. ELSIF x = c.w - 1 THEN
  2011. ELSIF (x # 0) & (c.children # NIL) THEN
  2012. p := FindChildAt(c, x, y);
  2013. IF (p # NIL) & (p.do.mouseDown # NIL) THEN
  2014. p.do.mouseDown(p, x - p.x, y - p.y, button)
  2015. END
  2016. END
  2017. END
  2018. END WindowMouseDown;
  2019. PROCEDURE WindowMouseUp*(c: Control; x, y, button: INTEGER);
  2020. BEGIN
  2021. IF c.status # normal THEN c.status := normal; NeedRedraw(c.app) END
  2022. END WindowMouseUp;
  2023. PROCEDURE WindowMouseMove*(c: Control; x, y: INTEGER; button: INTEGER);
  2024. VAR tW, tH: INTEGER;
  2025. BEGIN T.Size(tW, tH);
  2026. IF c.status = moving THEN
  2027. c.x := x + c(Window).mx; c.y := y + c.app.dragY;
  2028. IF c.y < 1 THEN c.y := 1 END;
  2029. IF c.do.refresh # NIL THEN c.do.refresh(c) END;
  2030. NeedRedraw(c.app)
  2031. ELSIF c.status = resizing THEN
  2032. c.w := x + c(Window).mx; c.h := y + 1;
  2033. IF c.w < c(Window).minW THEN c.w := c(Window).minW
  2034. ELSIF c.w > tW THEN c.w := tW
  2035. END;
  2036. IF c.h < c(Window).minH THEN c.h := c(Window).minH
  2037. ELSIF c.h > tH - 2 THEN c.h := tH - 2
  2038. END;
  2039. IF c.do.refresh # NIL THEN c.do.refresh(c) END;
  2040. NeedRedraw(c.app)
  2041. END
  2042. END WindowMouseMove;
  2043. PROCEDURE FindDefaultControl(c: Control): Control;
  2044. VAR p, br: Control;
  2045. BEGIN p := c.children;
  2046. IF p # NIL THEN br := p;
  2047. REPEAT p := p.next UNTIL (p = br) OR p.default;
  2048. IF ~p.default THEN p := NIL END
  2049. END
  2050. RETURN p END FindDefaultControl;
  2051. PROCEDURE WindowKeyDown*(c: Control; VAR E: T.Event);
  2052. VAR d: Control;
  2053. BEGIN
  2054. IF E.key = T.kEsc THEN
  2055. IF c(Window).closeOnEsc THEN CloseCurWindow(c) END
  2056. ELSIF E.key = T.kEnter THEN
  2057. d := FindDefaultControl(c);
  2058. IF (d # NIL) & (d.do.click # NIL) THEN d.do.click(d) END
  2059. END
  2060. END WindowKeyDown;
  2061. PROCEDURE WindowGetFocus*(c: Control);
  2062. BEGIN ControlGetFocus(c);
  2063. IF c(Window).cur # NIL THEN SetFocus(c(Window).cur) END
  2064. END WindowGetFocus;
  2065. PROCEDURE InitWindowMethod*(m: ControlMethod);
  2066. BEGIN InitControlMethod(m);
  2067. m.added := WindowAdded;
  2068. m.draw := WindowDraw;
  2069. m.refresh := WindowRefresh;
  2070. m.resize := WindowResize;
  2071. m.mouseDown := WindowMouseDown;
  2072. m.mouseUp := WindowMouseUp;
  2073. m.mouseMove := WindowMouseMove;
  2074. m.keyDown := WindowKeyDown;
  2075. m.getFocus := WindowGetFocus
  2076. END InitWindowMethod;
  2077. (* App *)
  2078. PROCEDURE InitApp*(app: App);
  2079. BEGIN app.windows := NIL;
  2080. app.menu := NewMenu('ROOT', '', 0, NIL); app.menu.app := app;
  2081. app.statusbar := NewMenu('ROOT', '', 0, NIL); app.statusbar.app := app;
  2082. app.statusText[0] := 0X;
  2083. app.dragged := NIL; app.dragX := 0; app.dragY := 0;
  2084. app.onResize := NIL;
  2085. app.cur := NIL;
  2086. app.lastMouseDownTime := 0;
  2087. app.quit := FALSE;
  2088. app.needRedraw := TRUE;
  2089. app.sync := TRUE;
  2090. app.mouseBtn := 0
  2091. END InitApp;
  2092. PROCEDURE NewApp*(): App;
  2093. VAR a: App;
  2094. BEGIN NEW(a); InitApp(a); RETURN a
  2095. END NewApp;
  2096. PROCEDURE SetOnResize*(a: App; p: PROCEDURE (w, h: INTEGER));
  2097. BEGIN a.onResize := p
  2098. END SetOnResize;
  2099. PROCEDURE RefreshAppMenu*(menu: Menu);
  2100. VAR p, br: Control;
  2101. x, y: INTEGER;
  2102. BEGIN
  2103. IF menu.children # NIL THEN
  2104. p := menu.children; br := p; x := 0;
  2105. REPEAT p.do.refresh(p); p.y := 0; p.x := x; INC(x, p.w);
  2106. RefreshMenu(p); p := p.next
  2107. UNTIL p = br
  2108. END
  2109. END RefreshAppMenu;
  2110. PROCEDURE AddWindow*(app: App; w: Window);
  2111. BEGIN SetApp(w, app);
  2112. IF w.closeBtn # NIL THEN w.closeBtn.app := app END;
  2113. IF w.zoomBtn # NIL THEN w.zoomBtn.app := app END;
  2114. IF app.windows = NIL THEN
  2115. app.windows := w; w.prev := w; w.next := w
  2116. ELSE
  2117. w.prev := app.windows;
  2118. w.next := app.windows.next;
  2119. app.windows.next.prev := w;
  2120. app.windows.next := w;
  2121. (*w.prev := app.windows.prev;
  2122. w.next := app.windows;
  2123. app.windows.prev.next := w;
  2124. app.windows.prev := w;*)
  2125. app.windows := w
  2126. END;
  2127. SetFocus(w)
  2128. END AddWindow;
  2129. PROCEDURE AddStatusbar*(app: App; c: Control);
  2130. BEGIN SetApp(c, app); Add(app.statusbar, c); RefreshAppMenu(app.statusbar)
  2131. END AddStatusbar;
  2132. PROCEDURE AddMenu*(app: App; m: Menu);
  2133. BEGIN SetApp(m, app); Add(app.menu, m); RefreshAppMenu(app.menu)
  2134. END AddMenu;
  2135. PROCEDURE SetStatusText*(app: App; text: ARRAY OF CHAR);
  2136. BEGIN Strings.Extract(text, 0, LEN(app.statusText), app.statusText)
  2137. END SetStatusText;
  2138. PROCEDURE CheckMenuOpenKey(app: App; VAR E: T.Event): BOOLEAN;
  2139. VAR p, q, br: Control; found: BOOLEAN;
  2140. BEGIN found := FALSE;
  2141. IF ~HasModalWindow(app) THEN
  2142. p := app.menu.children.prev; br := p;
  2143. REPEAT p := p.next; found := MenuHotkey(p(Menu), E.ch)
  2144. UNTIL found OR (p = br);
  2145. IF found THEN UnsetFocus(app); p.do.click(p) END
  2146. END;
  2147. RETURN found
  2148. END CheckMenuOpenKey;
  2149. PROCEDURE FindMenuWithHotkey(c: Menu; hotkey: INTEGER): Menu;
  2150. VAR p, br: Control;
  2151. BEGIN
  2152. IF c.hotkey # hotkey THEN
  2153. IF c.children # NIL THEN
  2154. p := c.children.prev; br := p;
  2155. REPEAT p := p.next; c := FindMenuWithHotkey(p(Menu), hotkey)
  2156. UNTIL (p = br) OR (c # NIL)
  2157. ELSE c := NIL
  2158. END
  2159. END;
  2160. RETURN c
  2161. END FindMenuWithHotkey;
  2162. PROCEDURE CheckHotkey(app: App; VAR E: T.Event): BOOLEAN;
  2163. VAR m: Menu;
  2164. hotkey: INTEGER;
  2165. handled: BOOLEAN;
  2166. BEGIN handled := FALSE; hotkey := E.key;
  2167. IF (hotkey # 0) & ~HasModalWindow(app) THEN
  2168. IF T.mCtrl IN E.mod THEN INC(hotkey, 100H) END;
  2169. IF E.mod * {T.mMenu, T.mAlt, T.mAltGr} # {} THEN INC(hotkey, 200H) END;
  2170. IF T.mShift IN E.mod THEN INC(hotkey, 400H) END;
  2171. m := FindMenuWithHotkey(app.menu, hotkey);
  2172. IF m # NIL THEN handled := TRUE;
  2173. IF m.do.click # NIL THEN m.do.click(m) END
  2174. END
  2175. END;
  2176. RETURN handled
  2177. END CheckHotkey;
  2178. PROCEDURE FindNextTabControl(p: Control; back: BOOLEAN): Control;
  2179. VAR br, next: Control;
  2180. t, nextT: INTEGER;
  2181. BEGIN t := p.tabIndex; next := NIL;
  2182. IF back THEN nextT := minInt ELSE nextT := maxInt END;
  2183. br := p; p := p.next;
  2184. WHILE p # br DO
  2185. IF ~back & (p.tabIndex >= t) & (p.tabIndex < nextT) OR
  2186. back & (p.tabIndex <= t) & (p.tabIndex > nextT)
  2187. THEN next := p; nextT := p.tabIndex
  2188. END;
  2189. p := p.next
  2190. END;
  2191. IF next = NIL THEN
  2192. IF back THEN
  2193. nextT := minInt;
  2194. REPEAT
  2195. IF p.tabIndex > nextT THEN next := p; nextT := p.tabIndex END;
  2196. p := p.next
  2197. UNTIL p = br
  2198. ELSE
  2199. nextT := maxInt;
  2200. REPEAT
  2201. IF p.tabIndex < nextT THEN next := p; nextT := p.tabIndex END;
  2202. p := p.next
  2203. UNTIL p = br
  2204. END
  2205. END
  2206. RETURN next END FindNextTabControl;
  2207. PROCEDURE OnTabPress(app: App; back: BOOLEAN): BOOLEAN;
  2208. VAR p: Control;
  2209. worked: BOOLEAN;
  2210. BEGIN worked := FALSE; p := app.cur;
  2211. IF p # NIL THEN p := FindNextTabControl(p, back);
  2212. IF (p # NIL) & (p # app.cur) & ~(p IS Window) THEN
  2213. SetAppFocus(app, p);
  2214. worked := TRUE
  2215. END
  2216. END
  2217. RETURN worked END OnTabPress;
  2218. PROCEDURE OnKey(app: App; VAR E: T.Event);
  2219. VAR handled: BOOLEAN; p: Control;
  2220. BEGIN handled := FALSE; p := app.cur;
  2221. IF (E.mod * {T.mCtrl, T.mShift, T.mAlt, T.mAltGr, T.mMenu} # {}) OR
  2222. (T.kF1 <= E.key) & (E.key <= T.kF12) OR (E.key = T.kPause)
  2223. THEN handled := CheckHotkey(app, E);
  2224. IF ~handled & (E.mod * {T.mAlt, T.mAltGr, T.mMenu} # {}) THEN
  2225. handled := CheckMenuOpenKey(app, E)
  2226. END
  2227. END;
  2228. IF ~handled & (p # NIL) &
  2229. ((E.key # T.kTab) OR ~OnTabPress(app, T.mShift IN E.mod))
  2230. THEN
  2231. IF p.do.keyDown # NIL THEN p.do.keyDown(p, E) END;
  2232. IF (p.parent # NIL) & (p.parent IS Window) &
  2233. (p.parent.do.keyDown # NIL) THEN
  2234. p.parent.do.keyDown(p.parent, E)
  2235. END
  2236. END;
  2237. IF ~handled & (p # NIL) & (E.ch >= 20X) & (E.ch # 07FX) THEN
  2238. IF p.do.textInput # NIL THEN p.do.textInput(p, E.ch) END
  2239. END
  2240. END OnKey;
  2241. PROCEDURE GetWindowAt(app: App; x, y: INTEGER): Control;
  2242. VAR p, br: Control;
  2243. BEGIN
  2244. IF app.windows = NIL THEN p := NIL
  2245. ELSE p := app.windows; br := p;
  2246. WHILE (p # NIL) &
  2247. ~((p.x <= x) & (x < p.x + p.w) &
  2248. (p.y <= y) & (y < p.y + p.h)) DO
  2249. IF p.prev = br THEN p := NIL ELSE p := p.prev END
  2250. END
  2251. END;
  2252. RETURN p
  2253. END GetWindowAt;
  2254. PROCEDURE GetControlAt*(app: App; x, y: INTEGER): Control;
  2255. VAR c: Control;
  2256. BEGIN c := GetMenuAt(app, x, y);
  2257. IF c = NIL THEN
  2258. c := GetStatusbarAt(app, x, y);
  2259. IF c = NIL THEN
  2260. c := GetWindowAt(app, x, y)
  2261. END
  2262. END;
  2263. RETURN c
  2264. END GetControlAt;
  2265. PROCEDURE OnMouse(app: App; VAR E: T.Event);
  2266. VAR c: Control;
  2267. btn: INTEGER;
  2268. BEGIN
  2269. IF E.button = 0 THEN (* Release mouse *)
  2270. btn := app.mouseBtn; app.mouseBtn := 0;
  2271. IF app.dragged # NIL THEN c := app.dragged
  2272. ELSE c := GetControlAt(app, E.x, E.y);
  2273. IF HasModalWindow(app) & (c # app.windows) THEN c := NIL END
  2274. END;
  2275. app.dragged := NIL;
  2276. IF (c # NIL) & (c.do.mouseUp # NIL) THEN
  2277. c.do.mouseUp(c, E.x - app.dragX, E.y - app.dragY, btn)
  2278. END
  2279. ELSIF app.mouseBtn = 0 THEN (* Mouse down event *)
  2280. app.mouseBtn := E.button;
  2281. IF app.dragged = NIL THEN
  2282. c := GetControlAt(app, E.x, E.y);
  2283. IF c = NIL THEN UnsetFocus(app)
  2284. ELSIF (c.do.mouseDown # NIL) &
  2285. (~HasModalWindow(app) OR (c = app.windows)) THEN
  2286. SetDragged(app, c);
  2287. c.do.mouseDown(c, E.x - c.x, E.y - c.y, E.button)
  2288. END
  2289. END
  2290. ELSE (* Drag *)
  2291. c := app.dragged;
  2292. IF (c # NIL) & (c.do.mouseMove # NIL) THEN
  2293. c.do.mouseMove(c, E.x - app.dragX, E.y - app.dragY, E.button)
  2294. END
  2295. END
  2296. END OnMouse;
  2297. PROCEDURE OnResize(app: App; E: T.Event);
  2298. BEGIN
  2299. app.needRedraw := TRUE;
  2300. IF app.onResize # NIL THEN app.onResize(E.w, E.h) END
  2301. END OnResize;
  2302. PROCEDURE RunApp*(app: App);
  2303. VAR E: T.Event;
  2304. break: BOOLEAN;
  2305. BEGIN
  2306. ticks := 0;
  2307. T.StartTimer(1/4);
  2308. app.quit := FALSE;
  2309. DrawApp(app); T.Flush;
  2310. REPEAT
  2311. break := FALSE;
  2312. REPEAT
  2313. T.WaitEvent(E);
  2314. IF E.type = T.mouse THEN OnMouse(app, E)
  2315. ELSIF E.type = T.timer THEN INC(ticks); break := TRUE
  2316. ELSIF E.type = T.key THEN OnKey(app, E)
  2317. ELSIF E.type = T.resize THEN OnResize(app, E)
  2318. ELSIF E.type = T.quit THEN app.quit := TRUE
  2319. END
  2320. UNTIL break OR ~T.HasEvents();
  2321. IF app.needRedraw THEN
  2322. DrawApp(app);
  2323. IF app.sync THEN T.Sync; app.sync := FALSE ELSE T.Flush END
  2324. END
  2325. UNTIL app.quit
  2326. END RunApp;
  2327. BEGIN
  2328. NEW(controlMethod); InitControlMethod(controlMethod);
  2329. NEW(labelMethod); InitLabelMethod(labelMethod);
  2330. NEW(quickBtnMethod); InitQuickBtnMethod(quickBtnMethod);
  2331. NEW(buttonMethod); InitButtonMethod(buttonMethod);
  2332. NEW(winBtnMethod); InitWinBtnMethod(winBtnMethod);
  2333. NEW(scrollbarMethod); InitScrollbarMethod(scrollbarMethod);
  2334. NEW(editMethod); InitEditMethod(editMethod);
  2335. NEW(columnListMethod); InitColumnListMethod(columnListMethod);
  2336. NEW(windowMethod); InitWindowMethod(windowMethod);
  2337. NEW(menuMethod); InitMenuMethod(menuMethod)
  2338. END OV.