Rulers.txt 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676
  1. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Text/Mod/Rulers.odc *)
  2. (* DO NOT EDIT *)
  3. MODULE TextRulers;
  4. (**
  5. project = "BlackBox"
  6. organization = "www.oberon.ch"
  7. contributors = "Oberon microsystems"
  8. version = "System/Rsrc/About"
  9. copyright = "System/Rsrc/About"
  10. license = "Docu/BB-License"
  11. changes = ""
  12. issues = ""
  13. **)
  14. (* re-check alien attributes: consider projection semantics *)
  15. IMPORT
  16. Kernel, Strings, Services, Fonts, Ports, Stores,
  17. Models, Views, Controllers, Properties, Dialog,
  18. TextModels;
  19. CONST
  20. (** Attributes.valid, Prop.known/valid **) (* Mark.kind *)
  21. first* = 0; left* = 1; right* = 2; lead* = 3; asc* = 4; dsc* = 5; grid* = 6;
  22. opts* = 7; tabs* = 8;
  23. (* additional values for icons held by Mark.kind *)
  24. invalid = -1;
  25. firstIcon = 10; lastIcon = 25;
  26. rightToggle = 10;
  27. gridDec = 12; gridVal = 13; gridInc = 14;
  28. leftFlush = 16; centered = 17; rightFlush = 18; justified = 19;
  29. leadDec = 21; leadVal = 22; leadInc = 23;
  30. pageBrk = 25;
  31. modeIcons = {leftFlush .. justified};
  32. validIcons = {rightToggle, gridDec .. gridInc, leftFlush .. justified, leadDec .. leadInc, pageBrk};
  33. fieldIcons = {gridVal, leadVal};
  34. (** Attributes.opts **)
  35. leftAdjust* = 0; rightAdjust* = 1;
  36. (** both: fully justified; none: centered **)
  37. noBreakInside* = 2; pageBreak* = 3; parJoin* = 4;
  38. (** pageBreak of this ruler overrides parJoin request of previous ruler **)
  39. rightFixed* = 5; (** has fixed right border **)
  40. options = {leftAdjust .. rightFixed}; (* options mask *)
  41. adjMask = {leftAdjust, rightAdjust};
  42. (** Attributes.tabType[i] **)
  43. maxTabs* = 32;
  44. centerTab* = 0; rightTab* = 1;
  45. (** both: (reserved); none: leftTab **)
  46. barTab* = 2;
  47. tabOptions = {centerTab .. barTab}; (* mask for presently valid options *)
  48. mm = Ports.mm; inch16 = Ports.inch DIV 16; point = Ports.point;
  49. tabBarHeight = 11 * point; scaleHeight = 10 * point; iconBarHeight = 14 * point;
  50. rulerHeight = tabBarHeight + scaleHeight + iconBarHeight;
  51. iconHeight = 10 * point; iconWidth = 12 * point; iconGap = 2 * point;
  52. iconPin = rulerHeight - (iconBarHeight - iconHeight) DIV 2;
  53. rulerChangeKey = "#Text:RulerChange";
  54. minVersion = 0;
  55. maxAttrVersion = 2; maxStyleVersion = 0; maxStdStyleVersion = 0;
  56. maxRulerVersion = 0; maxStdRulerVersion = 0;
  57. TYPE
  58. Tab* = RECORD
  59. stop*: INTEGER;
  60. type*: SET
  61. END;
  62. TabArray* = RECORD (* should be POINTER TO ARRAY OF Tab -- but cannot protect *)
  63. len*: INTEGER;
  64. tab*: ARRAY maxTabs OF Tab
  65. END;
  66. Attributes* = POINTER TO EXTENSIBLE RECORD (Stores.Store)
  67. init-: BOOLEAN; (* immutable once init holds *)
  68. first-, left-, right-, lead-, asc-, dsc-, grid-: INTEGER;
  69. opts-: SET;
  70. tabs-: TabArray
  71. END;
  72. AlienAttributes* = POINTER TO RECORD (Attributes)
  73. store-: Stores.Alien
  74. END;
  75. Style* = POINTER TO ABSTRACT RECORD (Models.Model)
  76. attr-: Attributes
  77. END;
  78. Ruler* = POINTER TO ABSTRACT RECORD (Views.View)
  79. style-: Style
  80. END;
  81. Prop* = POINTER TO RECORD (Properties.Property)
  82. first*, left*, right*, lead*, asc*, dsc*, grid*: INTEGER;
  83. opts*: RECORD val*, mask*: SET END;
  84. tabs*: TabArray
  85. END;
  86. UpdateMsg* = RECORD (Models.UpdateMsg)
  87. (** domaincast upon style update **)
  88. style*: Style;
  89. oldAttr*: Attributes
  90. END;
  91. Directory* = POINTER TO ABSTRACT RECORD
  92. attr-: Attributes
  93. END;
  94. StdStyle = POINTER TO RECORD (Style) END;
  95. StdRuler = POINTER TO RECORD (Ruler)
  96. sel: INTEGER; (* sel # invalid => sel = kind of selected mark *)
  97. px, py: INTEGER (* sel # invalid => px, py of selected mark *)
  98. END;
  99. StdDirectory = POINTER TO RECORD (Directory) END;
  100. Mark = RECORD
  101. ruler: StdRuler;
  102. l, r, t, b: INTEGER;
  103. px, py, px0, py0, x, y: INTEGER;
  104. kind, index: INTEGER;
  105. type: SET; (* valid if kind = tabs *)
  106. tabs: TabArray; (* if valid: tabs[index].type = type *)
  107. dirty: BOOLEAN
  108. END;
  109. SetAttrOp = POINTER TO RECORD (Stores.Operation)
  110. style: Style;
  111. attr: Attributes
  112. END;
  113. NeutralizeMsg = RECORD (Views.Message) END;
  114. VAR
  115. dir-, stdDir-: Directory;
  116. def: Attributes;
  117. prop: Prop; (* recycled *)
  118. globRd: TextModels.Reader; (* cache for temp reader; beware of reentrance *)
  119. font: Fonts.Font;
  120. marginGrid, minTabWidth, tabGrid: INTEGER;
  121. PROCEDURE ^ DoSetAttrOp (s: Style; attr: Attributes);
  122. PROCEDURE CopyTabs (IN src: TabArray; OUT dst: TabArray);
  123. (* a TabArray is a 256 byte structure - copying of used parts is much faster than ":= all" *)
  124. VAR i, n: INTEGER;
  125. BEGIN
  126. n := src.len; dst.len := n;
  127. i := 0; WHILE i < n DO dst.tab[i] := src.tab[i]; INC(i) END
  128. END CopyTabs;
  129. (** Attributes **)
  130. PROCEDURE (a: Attributes) CopyFrom- (source: Stores.Store), EXTENSIBLE;
  131. BEGIN
  132. WITH source: Attributes DO
  133. ASSERT(~a.init, 20); ASSERT(source.init, 21);
  134. a.init := TRUE;
  135. a.first := source.first; a.left := source.left; a.right := source.right;
  136. a.lead := source.lead; a.asc := source.asc; a.dsc := source.dsc; a.grid := source.grid;
  137. a.opts := source.opts;
  138. CopyTabs(source.tabs, a.tabs)
  139. END
  140. END CopyFrom;
  141. PROCEDURE (a: Attributes) Externalize- (VAR wr: Stores.Writer), EXTENSIBLE;
  142. (** pre: a.init **)
  143. VAR i: INTEGER; typedTabs: BOOLEAN;
  144. BEGIN
  145. ASSERT(a.init, 20);
  146. a.Externalize^(wr);
  147. i := 0; WHILE (i < a.tabs.len) & (a.tabs.tab[i].type = {}) DO INC(i) END;
  148. typedTabs := i < a.tabs.len;
  149. IF typedTabs THEN
  150. wr.WriteVersion(maxAttrVersion)
  151. ELSE
  152. wr.WriteVersion(1) (* versions before 2 had only leftTabs *)
  153. END;
  154. wr.WriteInt(a.first); wr.WriteInt(a.left); wr.WriteInt(a.right);
  155. wr.WriteInt(a.lead); wr.WriteInt(a.asc); wr.WriteInt(a.dsc); wr.WriteInt(a.grid);
  156. wr.WriteSet(a.opts);
  157. wr.WriteXInt(a.tabs.len);
  158. i := 0; WHILE i < a.tabs.len DO wr.WriteInt(a.tabs.tab[i].stop); INC(i) END;
  159. IF typedTabs THEN
  160. i := 0; WHILE i < a.tabs.len DO wr.WriteSet(a.tabs.tab[i].type); INC(i) END
  161. END
  162. END Externalize;
  163. PROCEDURE (a: Attributes) Internalize- (VAR rd: Stores.Reader), EXTENSIBLE;
  164. (** pre: ~a.init **)
  165. (** post: a.init **)
  166. VAR thisVersion, i, n, trash: INTEGER; trashSet: SET;
  167. BEGIN
  168. ASSERT(~a.init, 20); a.init := TRUE;
  169. a.Internalize^(rd);
  170. IF rd.cancelled THEN RETURN END;
  171. rd.ReadVersion(minVersion, maxAttrVersion, thisVersion);
  172. IF rd.cancelled THEN RETURN END;
  173. rd.ReadInt(a.first); rd.ReadInt(a.left); rd.ReadInt(a.right);
  174. rd.ReadInt(a.lead); rd.ReadInt(a.asc); rd.ReadInt(a.dsc); rd.ReadInt(a.grid);
  175. rd.ReadSet(a.opts);
  176. rd.ReadXInt(n); a.tabs.len := MIN(n, maxTabs);
  177. i := 0; WHILE i < a.tabs.len DO rd.ReadInt(a.tabs.tab[i].stop); INC(i) END;
  178. WHILE i < n DO rd.ReadInt(trash); INC(i) END;
  179. IF thisVersion = 0 THEN (* convert from v0 rightFixed to v1 ~rightFixed default *)
  180. INCL(a.opts, rightFixed)
  181. END;
  182. IF thisVersion >= 2 THEN
  183. i := 0; WHILE i < a.tabs.len DO rd.ReadSet(a.tabs.tab[i].type); INC(i) END;
  184. WHILE i < n DO rd.ReadSet(trashSet); INC(i) END
  185. ELSE
  186. i := 0; WHILE i < a.tabs.len DO a.tabs.tab[i].type := {}; INC(i) END
  187. END
  188. END Internalize;
  189. PROCEDURE Set (p: Prop; opt: INTEGER; VAR x: INTEGER; min, max, new: INTEGER);
  190. BEGIN
  191. IF opt IN p.valid THEN x := MAX(min, MIN(max, new)) END
  192. END Set;
  193. PROCEDURE ModifyFromProp (a: Attributes; p: Properties.Property);
  194. CONST maxW = 10000*mm; maxH = 32767 * point;
  195. VAR i: INTEGER; type, mask: SET;
  196. BEGIN
  197. WHILE p # NIL DO
  198. WITH p: Prop DO
  199. Set(p, first, a.first, 0, maxW, p.first);
  200. Set(p, left, a.left, 0, maxW, p.left);
  201. Set(p, right, a.right, MAX(a.left, a.first), maxW, p.right);
  202. Set(p, lead, a.lead, 0, maxH, p.lead);
  203. Set(p, asc, a.asc, 0, maxH, p.asc);
  204. Set(p, dsc, a.dsc, 0, maxH - a.asc, p.dsc);
  205. Set(p, grid, a.grid, 1, maxH, p.grid);
  206. IF opts IN p.valid THEN
  207. a.opts := a.opts * (-p.opts.mask) + p.opts.val * p.opts.mask
  208. END;
  209. IF (tabs IN p.valid) & (p.tabs.len >= 0) THEN
  210. IF (p.tabs.len > 0) & (p.tabs.tab[0].stop >= 0) THEN
  211. i := 0; a.tabs.len := MIN(p.tabs.len, maxTabs);
  212. REPEAT
  213. a.tabs.tab[i].stop := p.tabs.tab[i].stop;
  214. type := p.tabs.tab[i].type; mask := tabOptions;
  215. IF type * {centerTab, rightTab} = {centerTab, rightTab} THEN
  216. mask := mask - {centerTab, rightTab}
  217. END;
  218. a.tabs.tab[i].type := a.tabs.tab[i].type * (-mask) + type * mask;
  219. INC(i)
  220. UNTIL (i = a.tabs.len) OR (p.tabs.tab[i].stop < p.tabs.tab[i - 1].stop);
  221. a.tabs.len := i
  222. ELSE a.tabs.len := 0
  223. END
  224. END
  225. ELSE
  226. END;
  227. p := p.next
  228. END
  229. END ModifyFromProp;
  230. PROCEDURE (a: Attributes) ModifyFromProp- (p: Properties.Property), NEW, EXTENSIBLE;
  231. BEGIN
  232. ModifyFromProp(a, p)
  233. END ModifyFromProp;
  234. PROCEDURE (a: Attributes) InitFromProp* (p: Properties.Property), NEW, EXTENSIBLE;
  235. (** pre: ~a.init **)
  236. (** post: (a.init, p # NIL & x IN p.valid) => x set in a, else x defaults in a **)
  237. BEGIN
  238. ASSERT(~a.init, 20);
  239. a.init := TRUE;
  240. a.first := def.first; a.left := def.left; a.right := def.right;
  241. a.lead := def.lead; a.asc := def.asc; a.dsc := def.dsc; a.grid := def.grid;
  242. a.opts := def.opts;
  243. CopyTabs(def.tabs, a.tabs);
  244. ModifyFromProp(a, p)
  245. END InitFromProp;
  246. PROCEDURE (a: Attributes) Equals* (b: Attributes): BOOLEAN, NEW, EXTENSIBLE;
  247. (** pre: a.init, b.init **)
  248. VAR i: INTEGER;
  249. BEGIN
  250. ASSERT(a.init, 20); ASSERT(b.init, 21);
  251. IF a # b THEN
  252. i := 0;
  253. WHILE (i < a.tabs.len)
  254. & (a.tabs.tab[i].stop = b.tabs.tab[i].stop)
  255. & (a.tabs.tab[i].type = b.tabs.tab[i].type) DO
  256. INC(i)
  257. END;
  258. RETURN (Services.SameType(a, b))
  259. & (a.first = b.first) & (a.left = b.left) & (a.right = b.right)
  260. & (a.lead = b.lead) & (a.asc = b.asc) & (a.dsc = b.dsc) & (a.grid = b.grid)
  261. & (a.opts = b.opts) & (a.tabs.len = b.tabs.len) & (i = a.tabs.len)
  262. ELSE RETURN TRUE
  263. END
  264. END Equals;
  265. PROCEDURE (a: Attributes) Prop* (): Properties.Property, NEW, EXTENSIBLE;
  266. (** pre: a.init **)
  267. (** post: x attr in a => x IN p.valid, m set to value of attr in a **)
  268. VAR p: Prop;
  269. BEGIN
  270. ASSERT(a.init, 20);
  271. NEW(p);
  272. p.known := {first .. tabs}; p.valid := p.known;
  273. p.first := a.first; p.left := a.left; p.right := a.right;
  274. p.lead := a.lead; p.asc := a.asc; p.dsc := a.dsc; p.grid := a.grid;
  275. p.opts.val := a.opts; p.opts.mask := options;
  276. CopyTabs(a.tabs, p.tabs);
  277. RETURN p
  278. END Prop;
  279. PROCEDURE ReadAttr* (VAR rd: Stores.Reader; OUT a: Attributes);
  280. VAR st: Stores.Store; alien: AlienAttributes;
  281. BEGIN
  282. rd.ReadStore(st);
  283. ASSERT(st # NIL, 100);
  284. IF st IS Stores.Alien THEN
  285. NEW(alien); alien.store := st(Stores.Alien); Stores.Join(alien, alien.store);
  286. alien.InitFromProp(NIL); a := alien
  287. ELSE a := st(Attributes)
  288. END
  289. END ReadAttr;
  290. PROCEDURE WriteAttr* (VAR wr: Stores.Writer; a: Attributes);
  291. BEGIN
  292. ASSERT(a # NIL, 20); ASSERT(a.init, 21);
  293. WITH a: AlienAttributes DO wr.WriteStore(a.store) ELSE wr.WriteStore(a) END
  294. END WriteAttr;
  295. PROCEDURE ModifiedAttr* (a: Attributes; p: Properties.Property): Attributes;
  296. (** pre: a.init **)
  297. (** post: x IN p.valid => x in new attr set to value in p, else set to value in a **)
  298. VAR h: Attributes;
  299. BEGIN
  300. ASSERT(a.init, 20);
  301. h := Stores.CopyOf(a)(Attributes); h.ModifyFromProp(p);
  302. RETURN h
  303. END ModifiedAttr;
  304. (** AlienAttributes **)
  305. PROCEDURE (a: AlienAttributes) Externalize- (VAR wr: Stores.Writer);
  306. BEGIN
  307. HALT(100)
  308. END Externalize;
  309. PROCEDURE (a: AlienAttributes) Internalize- (VAR rd: Stores.Reader);
  310. BEGIN
  311. HALT(100)
  312. END Internalize;
  313. PROCEDURE (a: AlienAttributes) InitFromProp* (p: Properties.Property);
  314. BEGIN
  315. a.InitFromProp^(NIL)
  316. END InitFromProp;
  317. PROCEDURE (a: AlienAttributes) ModifyFromProp- (p: Properties.Property);
  318. BEGIN
  319. (* a.InitFromProp^(NIL) *)
  320. a.InitFromProp(NIL)
  321. END ModifyFromProp;
  322. (** Style **)
  323. (*
  324. PROCEDURE (s: Style) PropagateDomain-, EXTENSIBLE;
  325. VAR dom: Stores.Domain;
  326. BEGIN
  327. ASSERT(s.attr # NIL, 20);
  328. dom := s.attr.Domain();
  329. IF (dom # NIL) & (dom # s.Domain()) THEN s.attr := Stores.CopyOf(s.attr)(Attributes) END;
  330. Stores.InitDomain(s.attr, s.Domain())
  331. END PropagateDomain;
  332. *)
  333. PROCEDURE (s: Style) Externalize- (VAR wr: Stores.Writer), EXTENSIBLE;
  334. BEGIN
  335. s.Externalize^(wr);
  336. wr.WriteVersion(maxStyleVersion);
  337. WriteAttr(wr, s.attr)
  338. END Externalize;
  339. PROCEDURE (s: Style) Internalize- (VAR rd: Stores.Reader), EXTENSIBLE;
  340. VAR thisVersion: INTEGER;
  341. BEGIN
  342. s.Internalize^(rd);
  343. IF rd.cancelled THEN RETURN END;
  344. rd.ReadVersion(minVersion, maxStyleVersion, thisVersion);
  345. IF rd.cancelled THEN RETURN END;
  346. ReadAttr(rd, s.attr); Stores.Join(s, s.attr)
  347. END Internalize;
  348. PROCEDURE (s: Style) SetAttr* (attr: Attributes), NEW, EXTENSIBLE;
  349. (** pre: attr.init **)
  350. (** post: s.attr = attr OR s.attr.Equals(attr) **)
  351. BEGIN
  352. ASSERT(attr.init, 20);
  353. DoSetAttrOp(s, attr)
  354. END SetAttr;
  355. PROCEDURE (s: Style) CopyFrom- (source: Stores.Store), EXTENSIBLE;
  356. BEGIN
  357. WITH source: Style DO
  358. ASSERT(source.attr # NIL, 21);
  359. s.SetAttr(Stores.CopyOf(source.attr)(Attributes))
  360. (* bkwd-comp hack to avoid link *)
  361. (* copy would not be necessary if Attributes were immutable (and assigned to an Immutable Domain) *)
  362. END
  363. END CopyFrom;
  364. (*
  365. PROCEDURE (s: Style) InitFrom- (source: Models.Model), EXTENSIBLE;
  366. BEGIN
  367. WITH source: Style DO
  368. ASSERT(source.attr # NIL, 21);
  369. s.SetAttr(Stores.CopyOf(source.attr)(Attributes))
  370. (* bkwd-comp hack to avoid link *)
  371. END
  372. END InitFrom;
  373. *)
  374. (** Directory **)
  375. PROCEDURE (d: Directory) SetAttr* (attr: Attributes), NEW, EXTENSIBLE;
  376. (** pre: attr.init **)
  377. (** post: d.attr = ModifiedAttr(attr, p)
  378. [ p.valid = {opts, tabs}, p.tabs.len = 0, p.opts.mask = {noBreakInside.. parJoin}, p.opts.val = {} ]
  379. **)
  380. VAR p: Prop;
  381. BEGIN
  382. ASSERT(attr.init, 20);
  383. IF attr.tabs.len > 0 THEN
  384. NEW(p);
  385. p.valid := {opts, tabs};
  386. p.opts.mask := {noBreakInside, pageBreak, parJoin}; p.opts.val := {};
  387. p.tabs.len := 0;
  388. attr := ModifiedAttr(attr, p)
  389. END;
  390. d.attr := attr
  391. END SetAttr;
  392. PROCEDURE (d: Directory) NewStyle* (attr: Attributes): Style, NEW, ABSTRACT;
  393. PROCEDURE (d: Directory) New* (style: Style): Ruler, NEW, ABSTRACT;
  394. PROCEDURE (d: Directory) NewFromProp* (p: Prop): Ruler, NEW, EXTENSIBLE;
  395. BEGIN
  396. RETURN d.New(d.NewStyle(ModifiedAttr(d.attr, p)))
  397. END NewFromProp;
  398. PROCEDURE Deposit*;
  399. BEGIN
  400. Views.Deposit(dir.New(NIL))
  401. END Deposit;
  402. (** Ruler **)
  403. PROCEDURE (r: Ruler) Externalize- (VAR wr: Stores.Writer), EXTENSIBLE;
  404. BEGIN
  405. ASSERT(r.style # NIL, 20);
  406. r.Externalize^(wr);
  407. wr.WriteVersion(maxRulerVersion); wr.WriteStore(r.style)
  408. END Externalize;
  409. PROCEDURE (r: Ruler) InitStyle* (s: Style), NEW;
  410. (** pre: r.style = NIL, s # NIL, style.attr # NIL **)
  411. (** post: r.style = s **)
  412. BEGIN
  413. ASSERT((r.style = NIL) OR (r.style = s), 20);
  414. ASSERT(s # NIL, 21); ASSERT(s.attr # NIL, 22);
  415. r.style := s; Stores.Join(r, s)
  416. END InitStyle;
  417. PROCEDURE (r: Ruler) Internalize- (VAR rd: Stores.Reader), EXTENSIBLE;
  418. VAR st: Stores.Store; thisVersion: INTEGER;
  419. BEGIN
  420. r.Internalize^(rd);
  421. IF rd.cancelled THEN RETURN END;
  422. rd.ReadVersion(minVersion, maxRulerVersion, thisVersion);
  423. IF rd.cancelled THEN RETURN END;
  424. rd.ReadStore(st);
  425. IF st IS Stores.Alien THEN rd.TurnIntoAlien(Stores.alienComponent); RETURN END;
  426. r.InitStyle(st(Style))
  427. END Internalize;
  428. (*
  429. PROCEDURE (r: Ruler) InitModel* (m: Models.Model), EXTENSIBLE;
  430. (** pre: r.style = NIL, m # NIL, style.attr # NIL, m IS Style **)
  431. (** post: r.style = m **)
  432. BEGIN
  433. WITH m: Style DO
  434. ASSERT((r.style = NIL) OR (r.style = m), 20);
  435. ASSERT(m # NIL, 21); ASSERT(m.attr # NIL, 22);
  436. r.style := m
  437. ELSE HALT(23)
  438. END
  439. END InitModel;
  440. *)
  441. (*
  442. PROCEDURE (r: Ruler) PropagateDomain-, EXTENSIBLE;
  443. BEGIN
  444. ASSERT(r.style # NIL, 20);
  445. Stores.InitDomain(r.style, r.Domain())
  446. END PropagateDomain;
  447. *)
  448. PROCEDURE CopyOf* (r: Ruler; shallow: BOOLEAN): Ruler;
  449. VAR v: Views.View;
  450. BEGIN
  451. ASSERT(r # NIL, 20);
  452. v := Views.CopyOf(r, shallow); RETURN v(Ruler)
  453. END CopyOf;
  454. (** Prop **)
  455. PROCEDURE (p: Prop) IntersectWith* (q: Properties.Property; OUT equal: BOOLEAN);
  456. VAR valid: SET; i: INTEGER; c, m: SET; eq: BOOLEAN;
  457. BEGIN
  458. WITH q: Prop DO
  459. valid := p.valid * q.valid; equal := TRUE;
  460. i := 0;
  461. WHILE (i < p.tabs.len)
  462. & (p.tabs.tab[i].stop = q.tabs.tab[i].stop)
  463. & (p.tabs.tab[i].type = q.tabs.tab[i].type)
  464. DO
  465. INC(i)
  466. END;
  467. IF p.first # q.first THEN EXCL(valid, first) END;
  468. IF p.left # q.left THEN EXCL(valid, left) END;
  469. IF p.right # q.right THEN EXCL(valid, right) END;
  470. IF p.lead # q.lead THEN EXCL(valid, lead) END;
  471. IF p.asc # q.asc THEN EXCL(valid, asc) END;
  472. IF p.dsc # q.dsc THEN EXCL(valid, dsc) END;
  473. IF p.grid # q.grid THEN EXCL(valid, grid) END;
  474. Properties.IntersectSelections(p.opts.val, p.opts.mask, q.opts.val, q.opts.mask, c, m, eq);
  475. IF m = {} THEN EXCL(valid, opts)
  476. ELSIF (opts IN valid) & ~eq THEN p.opts.mask := m; equal := FALSE
  477. END;
  478. IF (p.tabs.len # q.tabs.len) OR (q.tabs.len # i) THEN EXCL(valid, tabs) END;
  479. IF p.valid # valid THEN p.valid := valid; equal := FALSE END
  480. END
  481. END IntersectWith;
  482. (** ruler construction **)
  483. (*property-based facade procedures *)
  484. PROCEDURE SetFirst* (r: Ruler; x: INTEGER);
  485. BEGIN
  486. ASSERT(r.style # NIL, 20);
  487. prop.valid := {first}; prop.first := x;
  488. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  489. END SetFirst;
  490. PROCEDURE SetLeft* (r: Ruler; x: INTEGER);
  491. BEGIN
  492. ASSERT(r.style # NIL, 20);
  493. prop.valid := {left}; prop.left := x;
  494. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  495. END SetLeft;
  496. PROCEDURE SetRight* (r: Ruler; x: INTEGER);
  497. BEGIN
  498. ASSERT(r.style # NIL, 20);
  499. prop.valid := {right}; prop.right := x;
  500. prop.opts.mask := {rightFixed}; prop.opts.val := {};
  501. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  502. END SetRight;
  503. PROCEDURE SetFixedRight* (r: Ruler; x: INTEGER);
  504. BEGIN
  505. ASSERT(r.style # NIL, 20);
  506. prop.valid := {right, opts}; prop.right := x;
  507. prop.opts.mask := {rightFixed}; prop.opts.val := {rightFixed};
  508. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  509. END SetFixedRight;
  510. PROCEDURE SetLead* (r: Ruler; h: INTEGER);
  511. BEGIN
  512. ASSERT(r.style # NIL, 20);
  513. prop.valid := {lead}; prop.lead := h;
  514. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  515. END SetLead;
  516. PROCEDURE SetAsc* (r: Ruler; h: INTEGER);
  517. BEGIN
  518. ASSERT(r.style # NIL, 20);
  519. prop.valid := {asc}; prop.asc := h;
  520. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  521. END SetAsc;
  522. PROCEDURE SetDsc* (r: Ruler; h: INTEGER);
  523. BEGIN
  524. ASSERT(r.style # NIL, 20);
  525. prop.valid := {dsc}; prop.dsc := h;
  526. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  527. END SetDsc;
  528. PROCEDURE SetGrid* (r: Ruler; h: INTEGER);
  529. BEGIN
  530. ASSERT(r.style # NIL, 20);
  531. prop.valid := {grid}; prop.grid := h;
  532. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  533. END SetGrid;
  534. PROCEDURE SetLeftFlush* (r: Ruler);
  535. BEGIN
  536. ASSERT(r.style # NIL, 20);
  537. prop.valid := {opts};
  538. prop.opts.mask := {leftAdjust, rightAdjust}; prop.opts.val := {leftAdjust};
  539. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  540. END SetLeftFlush;
  541. PROCEDURE SetRightFlush* (r: Ruler);
  542. BEGIN
  543. ASSERT(r.style # NIL, 20);
  544. prop.valid := {opts};
  545. prop.opts.mask := {leftAdjust, rightAdjust}; prop.opts.val := {rightAdjust};
  546. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  547. END SetRightFlush;
  548. PROCEDURE SetCentered* (r: Ruler);
  549. BEGIN
  550. ASSERT(r.style # NIL, 20);
  551. prop.valid := {opts};
  552. prop.opts.mask := {leftAdjust, rightAdjust}; prop.opts.val := {};
  553. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  554. END SetCentered;
  555. PROCEDURE SetJustified* (r: Ruler);
  556. BEGIN
  557. ASSERT(r.style # NIL, 20);
  558. prop.valid := {opts};
  559. prop.opts.mask := {leftAdjust, rightAdjust}; prop.opts.val := {leftAdjust, rightAdjust};
  560. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  561. END SetJustified;
  562. PROCEDURE SetNoBreakInside* (r: Ruler);
  563. BEGIN
  564. ASSERT(r.style # NIL, 20);
  565. prop.valid := {opts};
  566. prop.opts.mask := {noBreakInside}; prop.opts.val := {noBreakInside};
  567. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  568. END SetNoBreakInside;
  569. PROCEDURE SetPageBreak* (r: Ruler);
  570. BEGIN
  571. ASSERT(r.style # NIL, 20);
  572. prop.valid := {opts};
  573. prop.opts.mask := {pageBreak}; prop.opts.val := {pageBreak};
  574. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  575. END SetPageBreak;
  576. PROCEDURE SetParJoin* (r: Ruler);
  577. BEGIN
  578. ASSERT(r.style # NIL, 20);
  579. prop.valid := {opts};
  580. prop.opts.mask := {parJoin}; prop.opts.val := {parJoin};
  581. r.style.SetAttr(ModifiedAttr(r.style.attr, prop))
  582. END SetParJoin;
  583. PROCEDURE AddTab* (r: Ruler; x: INTEGER);
  584. VAR ra: Attributes; i: INTEGER;
  585. BEGIN
  586. ASSERT(r.style # NIL, 20); ra := r.style.attr; i := ra.tabs.len; ASSERT(i < maxTabs, 21);
  587. ASSERT((i = 0) OR (ra.tabs.tab[i - 1].stop < x), 22);
  588. prop.valid := {tabs};
  589. CopyTabs(ra.tabs, prop.tabs);
  590. prop.tabs.tab[i].stop := x; prop.tabs.tab[i].type := {}; INC(prop.tabs.len);
  591. r.style.SetAttr(ModifiedAttr(ra, prop))
  592. END AddTab;
  593. PROCEDURE MakeCenterTab* (r: Ruler);
  594. VAR ra: Attributes; i: INTEGER;
  595. BEGIN
  596. ASSERT(r.style # NIL, 20); ra := r.style.attr; i := ra.tabs.len; ASSERT(i > 0, 21);
  597. prop.valid := {tabs};
  598. CopyTabs(ra.tabs, prop.tabs);
  599. prop.tabs.tab[i - 1].type := prop.tabs.tab[i - 1].type + {centerTab} - {rightTab};
  600. r.style.SetAttr(ModifiedAttr(ra, prop))
  601. END MakeCenterTab;
  602. PROCEDURE MakeRightTab* (r: Ruler);
  603. VAR ra: Attributes; i: INTEGER;
  604. BEGIN
  605. ASSERT(r.style # NIL, 20); ra := r.style.attr; i := ra.tabs.len; ASSERT(i > 0, 21);
  606. prop.valid := {tabs};
  607. CopyTabs(ra.tabs, prop.tabs);
  608. prop.tabs.tab[i - 1].type := prop.tabs.tab[i - 1].type - {centerTab} + {rightTab};
  609. r.style.SetAttr(ModifiedAttr(ra, prop))
  610. END MakeRightTab;
  611. PROCEDURE MakeBarTab* (r: Ruler);
  612. VAR ra: Attributes; i: INTEGER;
  613. BEGIN
  614. ASSERT(r.style # NIL, 20); ra := r.style.attr; i := ra.tabs.len; ASSERT(i > 0, 21);
  615. prop.valid := {tabs};
  616. CopyTabs(ra.tabs, prop.tabs);
  617. prop.tabs.tab[i - 1].type := prop.tabs.tab[i - 1].type + {barTab};
  618. r.style.SetAttr(ModifiedAttr(ra, prop))
  619. END MakeBarTab;
  620. (* SetAttrOp *)
  621. PROCEDURE (op: SetAttrOp) Do;
  622. VAR s: Style; attr: Attributes; upd: UpdateMsg;
  623. BEGIN
  624. s := op.style;
  625. attr := s.attr; s.attr := op.attr; op.attr := attr;
  626. (*Stores.InitDomain(s.attr, s.Domain());*) (* Stores.Join(s, s.attr); *)
  627. ASSERT((s.attr=NIL) OR Stores.Joined(s, s.attr), 100);
  628. upd.style := s; upd.oldAttr := attr; Models.Domaincast(s.Domain(), upd)
  629. END Do;
  630. PROCEDURE DoSetAttrOp (s: Style; attr: Attributes);
  631. VAR op: SetAttrOp;
  632. BEGIN
  633. IF (s.attr # attr) OR ~s.attr.Equals(attr) THEN
  634. (* IF attr.Domain() # s.Domain() THEN attr := Stores.CopyOf(attr)(Attributes) END; *)
  635. IF ~Stores.Joined(s, attr) THEN
  636. IF ~Stores.Unattached(attr) THEN attr := Stores.CopyOf(attr)(Attributes) END;
  637. Stores.Join(s, attr)
  638. END;
  639. NEW(op); op.style := s; op.attr := attr;
  640. Models.Do(s, rulerChangeKey, op)
  641. END
  642. END DoSetAttrOp;
  643. (* grid definitions *)
  644. PROCEDURE MarginGrid (x: INTEGER): INTEGER;
  645. BEGIN
  646. RETURN (x + marginGrid DIV 2) DIV marginGrid * marginGrid
  647. END MarginGrid;
  648. PROCEDURE TabGrid (x: INTEGER): INTEGER;
  649. BEGIN
  650. RETURN (x + tabGrid DIV 2) DIV tabGrid * tabGrid
  651. END TabGrid;
  652. (* nice graphical primitives *)
  653. PROCEDURE DrawCenteredInt (f: Views.Frame; x, y, n: INTEGER);
  654. VAR sw: INTEGER; s: ARRAY 32 OF CHAR;
  655. BEGIN
  656. Strings.IntToString(n, s); sw := font.StringWidth(s);
  657. f.DrawString(x - sw DIV 2, y, Ports.defaultColor, s, font)
  658. END DrawCenteredInt;
  659. PROCEDURE DrawNiceRect (f: Views.Frame; l, t, r, b: INTEGER);
  660. VAR u: INTEGER;
  661. BEGIN
  662. u := f.dot;
  663. f.DrawRect(l, t, r - u, b - u, 0, Ports.defaultColor);
  664. f.DrawLine(l + u, b - u, r - u, b - u, u, Ports.grey25);
  665. f.DrawLine(r - u, t + u, r - u, b - u, u, Ports.grey25)
  666. END DrawNiceRect;
  667. PROCEDURE DrawScale (f: Views.Frame; l, t, r, b, clipL, clipR: INTEGER);
  668. VAR u, h, x, px, sw: INTEGER; i, n, d1, d2: INTEGER; s: ARRAY 32 OF CHAR;
  669. BEGIN
  670. f.DrawRect(l, t, r, b, Ports.fill, Ports.grey12);
  671. u := f.dot;
  672. IF Dialog.metricSystem THEN d1 := 2; d2 := 10 ELSE d1 := 2; d2 := 16 END;
  673. DEC(b, point);
  674. sw := 2*u + font.StringWidth("8888888888");
  675. x := l + tabGrid; i := 0; n := 0;
  676. WHILE x <= r DO
  677. INC(i); px := TabGrid(x);
  678. IF i = d2 THEN
  679. h := 6*point; i := 0; INC(n);
  680. IF (px >= clipL - sw) & (px < clipR) THEN
  681. Strings.IntToString(n, s);
  682. f.DrawString(px - 2*u - font.StringWidth(s), b - 3*point, Ports.defaultColor, s, font)
  683. END
  684. ELSIF i MOD d1 = 0 THEN
  685. h := 2*point
  686. ELSE
  687. h := 0
  688. END;
  689. IF (px >= clipL) & (px < clipR) & (h > 0) THEN
  690. f.DrawLine(px, b, px, b - h, 0, Ports.defaultColor)
  691. END;
  692. INC(x, tabGrid)
  693. END
  694. END DrawScale;
  695. PROCEDURE InvertTabMark (f: Views.Frame; l, t, r, b: INTEGER; type: SET; show: BOOLEAN);
  696. VAR u, u2, u3, yc, i, ih: INTEGER;
  697. BEGIN
  698. u := f.dot; u2 := 2*u; u3 := 3*u;
  699. IF ~ODD((r - l) DIV u) THEN DEC(r, u) END;
  700. yc := l + (r - l) DIV u DIV 2 * u;
  701. IF barTab IN type THEN
  702. f.MarkRect(yc, b - u3, yc + u, b - u2, Ports.fill, Ports.invert, show);
  703. f.MarkRect(yc, b - u, yc + u, b, Ports.fill, Ports.invert, show)
  704. END;
  705. IF centerTab IN type THEN
  706. f.MarkRect(l + u, b - u2, r - u, b - u, Ports.fill, Ports.invert, show)
  707. ELSIF rightTab IN type THEN
  708. f.MarkRect(l, b - u2, yc + u, b - u, Ports.fill, Ports.invert, show)
  709. ELSE
  710. f.MarkRect(yc, b - u2, r, b - u, Ports.fill, Ports.invert, show)
  711. END;
  712. DEC(b, u3); INC(l, u2); DEC(r, u2);
  713. ih := (r - l) DIV 2;
  714. i := b - t; t := b - u;
  715. WHILE (i > 0) & (r > l) DO
  716. DEC(i, u);
  717. f.MarkRect(l, t, r, b, Ports.fill, Ports.invert, show);
  718. IF i <= ih THEN INC(l, u); DEC(r, u) END;
  719. DEC(t, u); DEC(b, u)
  720. END
  721. END InvertTabMark;
  722. PROCEDURE InvertFirstMark (f: Views.Frame; l, t, r, b: INTEGER; show: BOOLEAN);
  723. VAR u, i, ih: INTEGER;
  724. BEGIN
  725. u := f.dot;
  726. i := b - t; t := b - u;
  727. ih := r - l;
  728. WHILE (i > 0) & (r > l) DO
  729. DEC(i, u);
  730. f.MarkRect(l, t, r, b, Ports.fill, Ports.invert, show);
  731. IF i <= ih THEN DEC(r, u) END;
  732. DEC(t, u); DEC(b, u)
  733. END
  734. END InvertFirstMark;
  735. PROCEDURE InvertLeftMark (f: Views.Frame; l, t, r, b: INTEGER; show: BOOLEAN);
  736. VAR u, i, ih: INTEGER;
  737. BEGIN
  738. u := f.dot;
  739. i := b - t; b := t + u;
  740. ih := r - l;
  741. WHILE (i > 0) & (r > l) DO
  742. DEC(i, u);
  743. f.MarkRect(l, t, r, b, Ports.fill, Ports.invert, show);
  744. IF i <= ih THEN DEC(r, u) END;
  745. INC(t, u); INC(b, u)
  746. END
  747. END InvertLeftMark;
  748. PROCEDURE InvertRightMark (f: Views.Frame; l, t, r, b: INTEGER; show: BOOLEAN);
  749. VAR u, i, ih: INTEGER;
  750. BEGIN
  751. u := f.dot;
  752. IF ~ODD((b - t) DIV u) THEN INC(t, u) END;
  753. ih := r - l; l := r - u;
  754. i := b - t; b := t + u;
  755. WHILE (i > 0) & (i > ih) DO
  756. DEC(i, u);
  757. f.MarkRect(l, t, r, b, Ports.fill, Ports.invert, show);
  758. DEC(l, u);
  759. INC(t, u); INC(b, u)
  760. END;
  761. WHILE (i > 0) & (r > l) DO
  762. DEC(i, u);
  763. f.MarkRect(l, t, r, b, Ports.fill, Ports.invert, show);
  764. INC(l, u);
  765. INC(t, u); INC(b, u)
  766. END
  767. END InvertRightMark;
  768. (* marks *)
  769. PROCEDURE SetMark (VAR m: Mark; r: StdRuler; px, py: INTEGER; kind, index: INTEGER);
  770. BEGIN
  771. m.ruler := r; m.kind := kind;
  772. m.px := px; m.py := py;
  773. CASE kind OF
  774. first:
  775. m.l := px; m.r := m.l + 4*point;
  776. m.b := py - 7*point; m.t := m.b - 4*point
  777. | left:
  778. m.l := px; m.r := m.l + 4*point;
  779. m.b := py - 2*point; m.t := m.b - 4*point
  780. | right:
  781. m.r := px; m.l := m.r - 4*point;
  782. m.b := py - 3*point; m.t := m.b - 7*point
  783. | tabs:
  784. m.l := px - 4*point; m.r := m.l + 9*point;
  785. m.b := py - 5*point; m.t := m.b - 6*point;
  786. m.type := r.style.attr.tabs.tab[index].type
  787. | firstIcon .. lastIcon:
  788. m.l := px; m.r := px + iconWidth;
  789. m.t := py; m.b := py + iconHeight
  790. ELSE HALT(100)
  791. END
  792. END SetMark;
  793. PROCEDURE Try (VAR m: Mark; r: StdRuler; px, py, x, y: INTEGER; kind, index: INTEGER);
  794. BEGIN
  795. IF m.kind = invalid THEN
  796. SetMark(m, r, px, py, kind, index);
  797. IF (m.l - point <= x) & (x < m.r + point) & (m.t - point <= y) & (y < m.b + point) THEN
  798. m.px0 := m.px; m.py0 := m.py; m.x := x; m.y := y;
  799. IF kind = tabs THEN
  800. m.index := index; CopyTabs(r.style.attr.tabs, m.tabs)
  801. END
  802. ELSE
  803. m.kind := invalid
  804. END
  805. END
  806. END Try;
  807. PROCEDURE InvertMark (VAR m: Mark; f: Views.Frame; show: BOOLEAN);
  808. (* pre: kind # invalid *)
  809. BEGIN
  810. CASE m.kind OF
  811. first: InvertFirstMark(f, m.l, m.t, m.r, m.b, show)
  812. | left: InvertLeftMark(f, m.l, m.t, m.r, m.b, show)
  813. | right: InvertRightMark(f, m.l, m.t, m.r, m.b, show)
  814. | tabs: InvertTabMark(f, m.l, m.t, m.r, m.b, m.type, show)
  815. END
  816. END InvertMark;
  817. PROCEDURE HiliteMark (VAR m: Mark; f: Views.Frame; show: BOOLEAN);
  818. BEGIN
  819. f.MarkRect(m.l, m.t, m.r - point, m.b - point, Ports.fill, Ports.hilite, show)
  820. END HiliteMark;
  821. PROCEDURE HiliteThisMark (r: StdRuler; f: Views.Frame; kind: INTEGER; show: BOOLEAN);
  822. VAR m: Mark; px, w, h: INTEGER;
  823. BEGIN
  824. IF (kind # invalid) & (kind IN validIcons) THEN
  825. px := iconGap + (kind - firstIcon) * (iconWidth + iconGap);
  826. r.context.GetSize(w, h);
  827. SetMark(m, r, px, h - iconPin, kind, -1);
  828. HiliteMark(m, f, show)
  829. END
  830. END HiliteThisMark;
  831. PROCEDURE DrawMark (VAR m: Mark; f: Views.Frame);
  832. (* pre: kind # invalid *)
  833. VAR a: Attributes; l, t, r, b, y, d, e, asc, dsc, fw: INTEGER; i: INTEGER;
  834. w: ARRAY 4 OF INTEGER;
  835. BEGIN
  836. a := m.ruler.style.attr;
  837. l := m.l + 2 * point; t := m.t + 2 * point; r := m.r - 4 * point; b := m.b - 3 * point;
  838. font.GetBounds(asc, dsc, fw);
  839. y := (m.t + m.b + asc) DIV 2;
  840. w[0] := (r - l) DIV 2; w[1] := r - l; w[2] := (r - l) DIV 3; w[3] := (r - l) * 2 DIV 3;
  841. CASE m.kind OF
  842. rightToggle:
  843. IF rightFixed IN a.opts THEN
  844. d := 0; y := (t + b) DIV 2 - point; e := (l + r) DIV 2 + point;
  845. WHILE t < y DO
  846. f.DrawLine(e - d, t, e, t, point, Ports.defaultColor); INC(d, point); INC(t, point)
  847. END;
  848. WHILE t < b DO
  849. f.DrawLine(e - d, t, e, t, point, Ports.defaultColor); DEC(d, point); INC(t, point)
  850. END
  851. ELSE
  852. DEC(b, point);
  853. f.DrawLine(l, t, r, t, point, Ports.defaultColor);
  854. f.DrawLine(l, b, r, b, point, Ports.defaultColor);
  855. f.DrawLine(l, t, l, b, point, Ports.defaultColor);
  856. f.DrawLine(r, t, r, b, point, Ports.defaultColor)
  857. END
  858. | gridDec:
  859. WHILE t < b DO f.DrawLine(l, t, r, t, point, Ports.defaultColor); INC(t, 2 * point) END
  860. | gridVal:
  861. DrawCenteredInt(f, (l + r) DIV 2, y, a.grid DIV point)
  862. | gridInc:
  863. WHILE t < b DO f.DrawLine(l, t, r, t, point, Ports.defaultColor); INC(t, 3 * point) END
  864. | leftFlush:
  865. i := 0;
  866. WHILE t < b DO
  867. d := w[i]; i := (i + 1) MOD LEN(w);
  868. f.DrawLine(l, t, l + d, t, point, Ports.defaultColor); INC(t, 2 * point)
  869. END
  870. | centered:
  871. i := 0;
  872. WHILE t < b DO
  873. d := (r - l - w[i]) DIV 2; i := (i + 1) MOD LEN(w);
  874. f.DrawLine(l + d, t, r - d, t, point, Ports.defaultColor); INC(t, 2 * point)
  875. END
  876. | rightFlush:
  877. i := 0;
  878. WHILE t < b DO
  879. d := w[i]; i := (i + 1) MOD LEN(w);
  880. f.DrawLine(r - d, t, r, t, point, Ports.defaultColor); INC(t, 2 * point)
  881. END
  882. | justified:
  883. WHILE t < b DO f.DrawLine(l, t, r, t, point, Ports.defaultColor); INC(t, 2 * point) END
  884. | leadDec:
  885. f.DrawLine(l, t, l, t + point, point, Ports.defaultColor); INC(t, 2 * point);
  886. WHILE t < b DO f.DrawLine(l, t, r, t, point, Ports.defaultColor); INC(t, 2 * point) END
  887. | leadVal:
  888. DrawCenteredInt(f, (l + r) DIV 2, y, m.ruler.style.attr.lead DIV point)
  889. | leadInc:
  890. f.DrawLine(l, t, l, t + 3 * point, point, Ports.defaultColor); INC(t, 4 * point);
  891. WHILE t < b DO f.DrawLine(l, t, r, t, point, Ports.defaultColor); INC(t, 2 * point) END
  892. | pageBrk:
  893. DEC(b, point);
  894. IF pageBreak IN a.opts THEN
  895. y := (t + b) DIV 2 - point;
  896. f.DrawLine(l, t, l, y, point, Ports.defaultColor);
  897. f.DrawLine(r, t, r, y, point, Ports.defaultColor);
  898. f.DrawLine(l, y, r, y, point, Ports.defaultColor);
  899. INC(y, 2 * point);
  900. f.DrawLine(l, y, r, y, point, Ports.defaultColor);
  901. f.DrawLine(l, y, l, b, point, Ports.defaultColor);
  902. f.DrawLine(r, y, r, b, point, Ports.defaultColor)
  903. ELSE
  904. f.DrawLine(l, t, l, b, point, Ports.defaultColor);
  905. f.DrawLine(r, t, r, b, point, Ports.defaultColor)
  906. END
  907. ELSE
  908. HALT(100)
  909. END;
  910. IF ~(m.kind IN {gridVal, leadVal}) THEN
  911. DrawNiceRect(f, m.l, m.t, m.r, m.b)
  912. END
  913. END DrawMark;
  914. PROCEDURE GetMark (VAR m: Mark; r: StdRuler; f: Views.Frame;
  915. x, y: INTEGER; canCreate: BOOLEAN
  916. );
  917. (* pre: ~canCreate OR (f # NIL) *)
  918. VAR a: Attributes; px, w, h: INTEGER; i: INTEGER;
  919. BEGIN
  920. m.kind := invalid; m.dirty := FALSE;
  921. a := r.style.attr;
  922. r.context.GetSize(w, h);
  923. (* first try scale *)
  924. Try(m, r, a.first, h, x, y, first, 0);
  925. Try(m, r, a.left, h, x, y, left, 0);
  926. IF rightFixed IN a.opts THEN
  927. Try(m, r, a.right, h, x, y, right, 0)
  928. END;
  929. i := 0;
  930. WHILE (m.kind = invalid) & (i < a.tabs.len) DO
  931. Try(m, r, a.tabs.tab[i].stop, h, x, y, tabs, i);
  932. INC(i)
  933. END;
  934. IF (m.kind = invalid) & (y >= h - tabBarHeight) & (a.tabs.len < maxTabs) THEN
  935. i := 0; px := TabGrid(x);
  936. WHILE (i < a.tabs.len) & (a.tabs.tab[i].stop < px) DO INC(i) END;
  937. IF (i = 0) OR (px - a.tabs.tab[i - 1].stop >= minTabWidth) THEN
  938. IF (i = a.tabs.len) OR (a.tabs.tab[i].stop - px >= minTabWidth) THEN
  939. IF canCreate THEN (* set new tab stop, initially at end of list *)
  940. m.kind := tabs; m.index := a.tabs.len; m.dirty := TRUE;
  941. CopyTabs(a.tabs, m.tabs); m.tabs.len := a.tabs.len + 1;
  942. m.tabs.tab[a.tabs.len].stop := px; m.tabs.tab[a.tabs.len].type := {};
  943. a.tabs.tab[a.tabs.len].stop := px; a.tabs.tab[a.tabs.len].type := {};
  944. SetMark(m, r, px, h, tabs, m.index); InvertMark(m, f, Ports.show);
  945. m.px0 := m.px; m.py0 := m.py; m.x := x; m.y := y
  946. END
  947. END
  948. END
  949. END;
  950. (* next try icon bar *)
  951. px := iconGap; i := firstIcon;
  952. WHILE i <= lastIcon DO
  953. IF i IN validIcons THEN
  954. Try(m, r, px, h - iconPin, x, y, i, 0)
  955. END;
  956. INC(px, iconWidth + iconGap); INC(i)
  957. END
  958. END GetMark;
  959. PROCEDURE SelectMark (r: StdRuler; f: Views.Frame; IN m: Mark);
  960. BEGIN
  961. r.sel := m.kind; r.px := m.px; r.py := m.py
  962. END SelectMark;
  963. PROCEDURE DeselectMark (r: StdRuler; f: Views.Frame);
  964. BEGIN
  965. HiliteThisMark(r, f, r.sel, Ports.hide); r.sel := invalid
  966. END DeselectMark;
  967. (* mark interaction *)
  968. PROCEDURE Mode (r: StdRuler): INTEGER;
  969. VAR a: Attributes; i: INTEGER;
  970. BEGIN
  971. a := r.style.attr;
  972. IF a.opts * adjMask = {leftAdjust} THEN
  973. i := leftFlush
  974. ELSIF a.opts * adjMask = {} THEN
  975. i := centered
  976. ELSIF a.opts * adjMask = {rightAdjust} THEN
  977. i := rightFlush
  978. ELSE (* a.opts * adjMask = adjMask *)
  979. i := justified
  980. END;
  981. RETURN i
  982. END Mode;
  983. PROCEDURE GrabMark (VAR m: Mark; r: StdRuler; f: Views.Frame; x, y: INTEGER);
  984. BEGIN
  985. GetMark(m, r, f, x, y, TRUE);
  986. DeselectMark(r, f);
  987. IF m.kind = Mode(r) THEN m.kind := invalid END
  988. END GrabMark;
  989. PROCEDURE TrackMark (VAR m: Mark; f: Views.Frame; x, y: INTEGER; modifiers: SET);
  990. VAR px, py, w, h: INTEGER;
  991. BEGIN
  992. IF m.kind # invalid THEN
  993. px := m.px + x - m.x; py := m.py + y - m.y;
  994. IF m.kind = tabs THEN
  995. px := TabGrid(px)
  996. ELSIF m.kind IN validIcons THEN
  997. IF (m.l <= x) & (x < m.r) THEN px := 1 ELSE px := 0 END
  998. ELSE
  999. px := MarginGrid(px)
  1000. END;
  1001. IF m.kind IN {right, tabs} THEN
  1002. m.ruler.context.GetSize(w, h);
  1003. IF (0 <= y) & (y < h + scaleHeight) OR (Controllers.extend IN modifiers) THEN
  1004. py := h
  1005. ELSE
  1006. py := -1 (* moved mark out of ruler: delete tab stop or fixed right margin *)
  1007. END
  1008. ELSIF m.kind IN validIcons THEN
  1009. IF (m.t <= y) & (y < m.b) THEN py := 1 ELSE py := 0 END
  1010. ELSE
  1011. py := MarginGrid(py)
  1012. END;
  1013. IF (m.kind IN {right, tabs}) & ((m.px # px) OR (m.py # py)) THEN
  1014. INC(m.x, px - m.px); INC(m.y, py - m.py);
  1015. InvertMark(m, f, Ports.hide); SetMark(m, m.ruler, px, py, m.kind, m.index);
  1016. InvertMark(m, f, Ports.show);
  1017. m.dirty := TRUE
  1018. ELSIF (m.kind IN {first, left}) & (m.px # px) THEN
  1019. INC(m.x, px - m.px);
  1020. InvertMark(m, f, Ports.hide); SetMark(m, m.ruler, px, m.py, m.kind, m.index);
  1021. InvertMark(m, f, Ports.show)
  1022. ELSIF (m.kind IN validIcons) & (m.px * m.py # px * py) THEN
  1023. HiliteMark(m, f, Ports.show);
  1024. IF m.kind IN modeIcons THEN HiliteThisMark(m.ruler, f, Mode(m.ruler), Ports.hide) END;
  1025. m.px := px; m.py := py
  1026. END
  1027. END
  1028. END TrackMark;
  1029. PROCEDURE ShiftMarks (a: Attributes; p: Prop; mask: SET; x0, dx: INTEGER);
  1030. VAR new: SET; i, j, t0, t1: INTEGER; tab0, tab1: TabArray;
  1031. BEGIN
  1032. new := mask - p.valid;
  1033. IF first IN new THEN p.first := a.first END;
  1034. IF tabs IN new THEN CopyTabs(a.tabs, p.tabs) END;
  1035. p.valid := p.valid + mask;
  1036. IF first IN mask THEN INC(p.first, dx) END;
  1037. IF tabs IN mask THEN
  1038. i := 0;
  1039. WHILE (i < p.tabs.len) & (p.tabs.tab[i].stop < x0) DO tab0.tab[i] := p.tabs.tab[i]; INC(i) END;
  1040. t0 := i;
  1041. t1 := 0;
  1042. WHILE i < p.tabs.len DO
  1043. tab1.tab[t1].stop := p.tabs.tab[i].stop + dx;
  1044. tab1.tab[t1].type := p.tabs.tab[i].type;
  1045. INC(t1); INC(i)
  1046. END;
  1047. i := 0; j := 0; p.tabs.len := 0;
  1048. WHILE i < t0 DO (* merge sort *)
  1049. WHILE (j < t1) & (tab1.tab[j].stop < tab0.tab[i].stop) DO
  1050. p.tabs.tab[p.tabs.len] := tab1.tab[j]; INC(p.tabs.len); INC(j)
  1051. END;
  1052. IF (j < t1) & (tab1.tab[j].stop = tab0.tab[i].stop) THEN INC(j) END;
  1053. p.tabs.tab[p.tabs.len] := tab0.tab[i]; INC(p.tabs.len); INC(i)
  1054. END;
  1055. WHILE j < t1 DO
  1056. p.tabs.tab[p.tabs.len] := tab1.tab[j]; INC(p.tabs.len); INC(j)
  1057. END
  1058. END
  1059. END ShiftMarks;
  1060. PROCEDURE ShiftDependingMarks (VAR m: Mark; p: Prop);
  1061. VAR a: Attributes; dx: INTEGER;
  1062. BEGIN
  1063. a := m.ruler.style.attr; dx := m.px - m.px0;
  1064. CASE m.kind OF
  1065. first: ShiftMarks(a, p, {tabs}, 0, dx)
  1066. | left: ShiftMarks(a, p, {first, tabs}, 0, dx)
  1067. | tabs: ShiftMarks(a, p, {tabs}, m.px0, dx)
  1068. ELSE
  1069. END
  1070. END ShiftDependingMarks;
  1071. PROCEDURE AdjustMarks (VAR m: Mark; f: Views.Frame; modifiers: SET);
  1072. VAR r: StdRuler; a: Attributes; p: Prop;
  1073. g: INTEGER; i, j: INTEGER; shift: BOOLEAN; type: SET;
  1074. BEGIN
  1075. r := m.ruler;
  1076. IF (m.kind # invalid) & (m.kind IN validIcons)
  1077. & (m.px = 1) & (m.py = 1)
  1078. OR (m.kind # invalid) & ~(m.kind IN validIcons)
  1079. & ((m.px # m.px0) OR (m.py # m.py0)
  1080. OR (m.kind = tabs) (*(m.tabs.len # r.style.attr.tabs.len)*) )
  1081. THEN
  1082. a := r.style.attr; NEW(p);
  1083. p.valid := {};
  1084. shift := (Controllers.modify IN modifiers) & (m.tabs.len = r.style.attr.tabs.len);
  1085. CASE m.kind OF
  1086. first:
  1087. p.valid := {first}; p.first := m.px
  1088. | left:
  1089. p.valid := {left}; p.left := m.px
  1090. | right:
  1091. IF m.py >= 0 THEN
  1092. p.valid := {right}; p.right := m.px
  1093. ELSE
  1094. p.valid := {opts}; p.opts.val := {}; p.opts.mask := {rightFixed}
  1095. END
  1096. | tabs:
  1097. IF ~m.dirty THEN
  1098. p.valid := {tabs}; CopyTabs(m.tabs, p.tabs);
  1099. i := m.index; type := m.tabs.tab[i].type;
  1100. IF shift THEN
  1101. type := type * {barTab};
  1102. IF type = {} THEN type := {barTab}
  1103. ELSE type := {}
  1104. END;
  1105. p.tabs.tab[i].type := p.tabs.tab[i].type - {barTab} + type
  1106. ELSE
  1107. type := type * {centerTab, rightTab};
  1108. IF type = {} THEN type := {centerTab}
  1109. ELSIF type = {centerTab} THEN type := {rightTab}
  1110. ELSE type := {}
  1111. END;
  1112. p.tabs.tab[i].type := p.tabs.tab[i].type - {centerTab, rightTab} + type
  1113. END
  1114. ELSIF ~shift THEN
  1115. p.valid := {tabs}; p.tabs.len := m.tabs.len - 1;
  1116. i := 0;
  1117. WHILE i < m.index DO p.tabs.tab[i] := m.tabs.tab[i]; INC(i) END;
  1118. INC(i);
  1119. WHILE i < m.tabs.len DO p.tabs.tab[i - 1] := m.tabs.tab[i]; INC(i) END;
  1120. i := 0;
  1121. WHILE (i < p.tabs.len) & (p.tabs.tab[i].stop < m.px) DO INC(i) END;
  1122. IF (m.px >= MIN(a.first, a.left)) & (m.px <= f.r) & (m.py >= 0)
  1123. & ((i = 0) OR (m.px - p.tabs.tab[i - 1].stop >= minTabWidth))
  1124. & ((i = p.tabs.len) OR (p.tabs.tab[i].stop - m.px >= minTabWidth)) THEN
  1125. j := p.tabs.len;
  1126. WHILE j > i DO p.tabs.tab[j] := p.tabs.tab[j - 1]; DEC(j) END;
  1127. p.tabs.tab[i].stop := m.px; p.tabs.tab[i].type := m.tabs.tab[m.index].type;
  1128. INC(p.tabs.len)
  1129. END;
  1130. i := 0;
  1131. WHILE (i < p.tabs.len)
  1132. & (p.tabs.tab[i].stop = a.tabs.tab[i].stop)
  1133. & (p.tabs.tab[i].type = a.tabs.tab[i].type) DO
  1134. INC(i)
  1135. END;
  1136. IF (i = p.tabs.len) & (p.tabs.len = a.tabs.len) THEN RETURN END (* did not change *)
  1137. END
  1138. | rightToggle:
  1139. p.valid := {right, opts};
  1140. IF ~(rightFixed IN a.opts) THEN
  1141. p.right := f.r DIV marginGrid * marginGrid
  1142. END;
  1143. p.opts.val := a.opts / {rightFixed}; p.opts.mask := {rightFixed}
  1144. | gridDec:
  1145. p.valid := {asc, grid}; g := a.grid - point;
  1146. IF g = 0 THEN p.grid := 1; p.asc := 0 ELSE p.grid := g; p.asc := g - a.dsc END
  1147. | gridVal:
  1148. SelectMark(r, f, m); RETURN
  1149. | gridInc:
  1150. p.valid := {asc, grid}; g := a.grid + point; DEC(g, g MOD point);
  1151. p.grid := g; p.asc := g - a.dsc
  1152. | leftFlush:
  1153. p.valid := {opts}; p.opts.val := {leftAdjust}; p.opts.mask := adjMask
  1154. | centered:
  1155. p.valid := {opts}; p.opts.val := {}; p.opts.mask := adjMask
  1156. | rightFlush:
  1157. p.valid := {opts}; p.opts.val := {rightAdjust}; p.opts.mask := adjMask
  1158. | justified:
  1159. p.valid := {opts}; p.opts.val := adjMask; p.opts.mask := adjMask
  1160. | leadDec:
  1161. p.valid := {lead}; p.lead := a.lead - point
  1162. | leadVal:
  1163. SelectMark(r, f, m); RETURN
  1164. | leadInc:
  1165. p.valid := {lead}; p.lead := a.lead + point
  1166. | pageBrk:
  1167. p.valid := {opts}; p.opts.val := a.opts / {pageBreak}; p.opts.mask := {pageBreak}
  1168. ELSE HALT(100)
  1169. END;
  1170. IF shift THEN ShiftDependingMarks(m, p) END;
  1171. IF m.kind IN validIcons - modeIcons THEN HiliteMark(m, f, Ports.hide) END;
  1172. r.style.SetAttr(ModifiedAttr(a, p))
  1173. END
  1174. END AdjustMarks;
  1175. (* primitivies for standard ruler *)
  1176. PROCEDURE Track (r: StdRuler; f: Views.Frame; IN msg: Controllers.TrackMsg);
  1177. VAR m: Mark; x, y, res: INTEGER; modifiers: SET; isDown: BOOLEAN;
  1178. cmd: ARRAY 128 OF CHAR;
  1179. BEGIN
  1180. GrabMark(m, r, f, msg.x, msg.y);
  1181. REPEAT
  1182. f.Input(x, y, modifiers, isDown); TrackMark(m, f, x, y, modifiers)
  1183. UNTIL ~isDown;
  1184. AdjustMarks(m, f, modifiers);
  1185. IF Controllers.doubleClick IN msg.modifiers THEN
  1186. CASE m.kind OF
  1187. | invalid:
  1188. Dialog.MapString("#Text:OpenRulerDialog", cmd); Dialog.Call(cmd, "", res)
  1189. | gridVal, leadVal:
  1190. Dialog.MapString("#Text:OpenSizeDialog", cmd); Dialog.Call(cmd, "", res)
  1191. ELSE
  1192. END
  1193. END
  1194. END Track;
  1195. PROCEDURE Edit (r: StdRuler; f: Views.Frame; VAR msg: Controllers.EditMsg);
  1196. VAR v: Views.View;
  1197. BEGIN
  1198. CASE msg.op OF
  1199. Controllers.copy:
  1200. msg.view := Views.CopyOf(r, Views.deep);
  1201. msg.isSingle := TRUE
  1202. | Controllers.paste:
  1203. v := msg.view;
  1204. WITH v: Ruler DO r.style.SetAttr(v.style.attr) ELSE END
  1205. ELSE
  1206. END
  1207. END Edit;
  1208. PROCEDURE PollOps (r: StdRuler; f: Views.Frame; VAR msg: Controllers.PollOpsMsg);
  1209. BEGIN
  1210. msg.type := "TextRulers.Ruler";
  1211. msg.pasteType := "TextRulers.Ruler";
  1212. msg.selectable := FALSE;
  1213. msg.valid := {Controllers.copy, Controllers.paste}
  1214. END PollOps;
  1215. PROCEDURE SetProp (r: StdRuler; VAR msg: Properties.SetMsg; VAR requestFocus: BOOLEAN);
  1216. VAR a1: Attributes; px, py, g: INTEGER; sel: INTEGER;
  1217. p: Properties.Property; sp: Properties.StdProp; rp: Prop;
  1218. BEGIN
  1219. p := msg.prop; sel := r.sel; px := r.px; py := r.py;
  1220. IF sel # invalid THEN
  1221. WHILE (p # NIL) & ~(p IS Properties.StdProp) DO p := p.next END;
  1222. IF p # NIL THEN
  1223. sp := p(Properties.StdProp);
  1224. IF (r.sel = leadVal) & (Properties.size IN sp.valid) THEN
  1225. NEW(rp); rp.valid := {lead};
  1226. rp.lead := sp.size
  1227. ELSIF (r.sel = gridVal) & (Properties.size IN sp.valid) THEN
  1228. g := sp.size; DEC(g, g MOD point);
  1229. NEW(rp); rp.valid := {asc, grid};
  1230. IF g = 0 THEN rp.asc := 0; rp.grid := 1
  1231. ELSE rp.asc := g - r.style.attr.dsc; rp.grid := g
  1232. END
  1233. ELSE
  1234. rp := NIL
  1235. END
  1236. END;
  1237. p := rp
  1238. END;
  1239. a1 := ModifiedAttr(r.style.attr, p);
  1240. IF ~a1.Equals(r.style.attr) THEN
  1241. r.style.SetAttr(a1);
  1242. IF requestFocus & (r.sel = invalid) THEN (* restore mark selection *)
  1243. r.sel := sel; r.px := px; r.py := py
  1244. END
  1245. ELSE requestFocus := FALSE
  1246. END
  1247. END SetProp;
  1248. PROCEDURE PollProp (r: StdRuler; VAR msg: Properties.PollMsg);
  1249. VAR p: Properties.StdProp;
  1250. BEGIN
  1251. CASE r.sel OF
  1252. invalid:
  1253. msg.prop := r.style.attr.Prop()
  1254. | leadVal:
  1255. NEW(p); p.known := {Properties.size}; p.valid := p.known;
  1256. p.size := r.style.attr.lead;
  1257. msg.prop := p
  1258. | gridVal:
  1259. NEW(p); p.known := {Properties.size}; p.valid := p.known;
  1260. p.size := r.style.attr.grid;
  1261. msg.prop := p
  1262. ELSE HALT(100)
  1263. END
  1264. END PollProp;
  1265. (* StdStyle *)
  1266. PROCEDURE (r: StdStyle) Internalize (VAR rd: Stores.Reader);
  1267. VAR thisVersion: INTEGER;
  1268. BEGIN
  1269. r.Internalize^(rd);
  1270. IF rd.cancelled THEN RETURN END;
  1271. rd.ReadVersion(minVersion, maxStdStyleVersion, thisVersion)
  1272. END Internalize;
  1273. PROCEDURE (r: StdStyle) Externalize (VAR wr: Stores.Writer);
  1274. BEGIN
  1275. r.Externalize^(wr);
  1276. wr.WriteVersion(maxStdStyleVersion)
  1277. END Externalize;
  1278. (*
  1279. PROCEDURE (r: StdStyle) CopyFrom (source: Stores.Store);
  1280. BEGIN
  1281. r.SetAttr(source(StdStyle).attr)
  1282. END CopyFrom;
  1283. *)
  1284. (* StdRuler *)
  1285. PROCEDURE (r: StdRuler) Internalize (VAR rd: Stores.Reader);
  1286. VAR thisVersion: INTEGER;
  1287. BEGIN
  1288. r.Internalize^(rd);
  1289. IF rd.cancelled THEN RETURN END;
  1290. rd.ReadVersion(minVersion, maxStdRulerVersion, thisVersion);
  1291. IF rd.cancelled THEN RETURN END;
  1292. r.sel := invalid
  1293. END Internalize;
  1294. PROCEDURE (r: StdRuler) Externalize (VAR wr: Stores.Writer);
  1295. BEGIN
  1296. r.Externalize^(wr);
  1297. wr.WriteVersion(maxStdRulerVersion)
  1298. END Externalize;
  1299. PROCEDURE (r: StdRuler) ThisModel (): Models.Model;
  1300. BEGIN
  1301. RETURN r.style
  1302. END ThisModel;
  1303. PROCEDURE (r: StdRuler) CopyFromModelView (source: Views.View; model: Models.Model);
  1304. BEGIN
  1305. r.sel := invalid; r.InitStyle(model(Style))
  1306. END CopyFromModelView;
  1307. PROCEDURE (ruler: StdRuler) Restore (f: Views.Frame; l, t, r, b: INTEGER);
  1308. VAR a: Attributes; m: Mark; u, scale, tabBar, px, w, h: INTEGER; i: INTEGER;
  1309. BEGIN
  1310. u := f.dot; a := ruler.style.attr;
  1311. ruler.context.GetSize(w, h);
  1312. tabBar := h - tabBarHeight; scale := tabBar - scaleHeight;
  1313. w := MIN(f.r + 10 * mm, 10000 * mm); (* high-level clipping *)
  1314. f.DrawLine(0, scale - u, w - u, scale - u, u, Ports.grey25);
  1315. f.DrawLine(0, tabBar - u, w - u, tabBar - u, u, Ports.grey50);
  1316. DrawScale(f, 0, scale, w, tabBar, l, r);
  1317. DrawNiceRect(f, 0, h - rulerHeight, w, h);
  1318. SetMark(m, ruler, a.first, h, first, -1); InvertMark(m, f, Ports.show);
  1319. SetMark(m, ruler, a.left, h, left, -1); InvertMark(m, f, Ports.show);
  1320. IF rightFixed IN a.opts THEN
  1321. SetMark(m, ruler, a.right, h, right, -1); InvertMark(m, f, Ports.show)
  1322. END;
  1323. i := 0;
  1324. WHILE i < a.tabs.len DO
  1325. SetMark(m, ruler, a.tabs.tab[i].stop, h, tabs, i); InvertMark(m, f, Ports.show); INC(i)
  1326. END;
  1327. px := iconGap; i := firstIcon;
  1328. WHILE i <= lastIcon DO
  1329. IF i IN validIcons THEN
  1330. SetMark(m, ruler, px, h - iconPin, i, -1); DrawMark(m, f)
  1331. END;
  1332. INC(px, iconWidth + iconGap); INC(i)
  1333. END;
  1334. HiliteThisMark(ruler, f, Mode(ruler), Ports.show)
  1335. END Restore;
  1336. PROCEDURE (ruler: StdRuler) RestoreMarks (f: Views.Frame; l, t, r, b: INTEGER);
  1337. BEGIN
  1338. HiliteThisMark(ruler, f, ruler.sel, Ports.show)
  1339. END RestoreMarks;
  1340. PROCEDURE (r: StdRuler) GetBackground (VAR color: Ports.Color);
  1341. BEGIN
  1342. color := Ports.background
  1343. END GetBackground;
  1344. PROCEDURE (r: StdRuler) Neutralize;
  1345. VAR msg: NeutralizeMsg;
  1346. BEGIN
  1347. Views.Broadcast(r, msg)
  1348. END Neutralize;
  1349. PROCEDURE (r: StdRuler) HandleModelMsg (VAR msg: Models.Message);
  1350. BEGIN
  1351. WITH msg: UpdateMsg DO
  1352. Views.Update(r, Views.keepFrames)
  1353. ELSE
  1354. END
  1355. END HandleModelMsg;
  1356. PROCEDURE (r: StdRuler) HandleViewMsg (f: Views.Frame; VAR msg: Views.Message);
  1357. BEGIN
  1358. WITH msg: NeutralizeMsg DO
  1359. DeselectMark(r, f)
  1360. ELSE
  1361. END
  1362. END HandleViewMsg;
  1363. PROCEDURE (r: StdRuler) HandleCtrlMsg (f: Views.Frame;
  1364. VAR msg: Controllers.Message; VAR focus: Views.View
  1365. );
  1366. VAR requestFocus: BOOLEAN;
  1367. BEGIN
  1368. WITH msg: Controllers.TrackMsg DO
  1369. Track(r, f, msg)
  1370. | msg: Controllers.EditMsg DO
  1371. Edit(r, f, msg)
  1372. | msg: Controllers.MarkMsg DO
  1373. r.RestoreMarks(f, f.l, f.t, f.r, f.b)
  1374. | msg: Controllers.SelectMsg DO
  1375. IF ~msg.set THEN DeselectMark(r, f) END
  1376. | msg: Controllers.PollOpsMsg DO
  1377. PollOps(r, f, msg)
  1378. | msg: Properties.CollectMsg DO
  1379. PollProp(r, msg.poll)
  1380. | msg: Properties.EmitMsg DO
  1381. requestFocus := f.front;
  1382. SetProp(r, msg.set, requestFocus);
  1383. msg.requestFocus := requestFocus
  1384. ELSE
  1385. END
  1386. END HandleCtrlMsg;
  1387. PROCEDURE (r: StdRuler) HandlePropMsg (VAR msg: Properties.Message);
  1388. VAR m: Mark; requestFocus: BOOLEAN; w, h: INTEGER;
  1389. BEGIN
  1390. WITH msg: Properties.SizePref DO
  1391. msg.w := 10000 * Ports.mm; msg.h := rulerHeight
  1392. | msg: Properties.ResizePref DO
  1393. msg.fixed := TRUE
  1394. | msg: Properties.FocusPref DO
  1395. IF msg.atLocation THEN
  1396. r.context.GetSize(w, h);
  1397. GetMark(m, r, NIL, msg.x, msg.y, FALSE);
  1398. msg.hotFocus := (m.kind # invalid) & ~(m.kind IN fieldIcons) OR (msg.y >= h - tabBarHeight);
  1399. msg.setFocus := ~msg.hotFocus
  1400. END
  1401. | msg: TextModels.Pref DO
  1402. msg.opts := {TextModels.maskChar, TextModels.hideable};
  1403. msg.mask := TextModels.para
  1404. | msg: Properties.SetMsg DO
  1405. requestFocus := FALSE;
  1406. SetProp(r, msg, requestFocus)
  1407. | msg: Properties.PollMsg DO
  1408. PollProp(r, msg)
  1409. ELSE
  1410. END
  1411. END HandlePropMsg;
  1412. (* StdDirectory *)
  1413. PROCEDURE (d: StdDirectory) NewStyle (attr: Attributes): Style;
  1414. VAR s: StdStyle;
  1415. BEGIN
  1416. IF attr = NIL THEN attr := d.attr END;
  1417. NEW(s); s.SetAttr(attr); RETURN s
  1418. END NewStyle;
  1419. PROCEDURE (d: StdDirectory) New (style: Style): Ruler;
  1420. VAR r: StdRuler;
  1421. BEGIN
  1422. IF style = NIL THEN style := d.NewStyle(NIL) END;
  1423. NEW(r); r.InitStyle(style); r.sel := invalid; RETURN r
  1424. END New;
  1425. (** miscellaneous **)
  1426. PROCEDURE GetValidRuler* (text: TextModels.Model; pos, hint: INTEGER;
  1427. VAR ruler: Ruler; VAR rpos: INTEGER
  1428. );
  1429. (** pre: (hint < 0 OR (ruler, rpos) is first ruler before hint & 0 <= pos <= t.Length() **)
  1430. (** post: hint < rpos <= pos & rpos = Pos(ruler) & (no ruler in (rpos, pos])
  1431. OR ((ruler, rpos) unmodified)
  1432. **)
  1433. VAR view: Views.View;
  1434. BEGIN
  1435. IF pos < text.Length() THEN INC(pos) END; (* let a ruler dominate its own position *)
  1436. IF pos < hint THEN hint := -1 END;
  1437. globRd := text.NewReader(globRd); globRd.SetPos(pos);
  1438. REPEAT
  1439. globRd.ReadPrevView(view)
  1440. UNTIL globRd.eot OR (view IS Ruler) OR (globRd.Pos() < hint);
  1441. IF (view # NIL) & (view IS Ruler) THEN
  1442. ruler := view(Ruler); rpos := globRd.Pos()
  1443. END
  1444. END GetValidRuler;
  1445. PROCEDURE SetDir* (d: Directory);
  1446. (** pre: d # NIL, d.attr # NIL **)
  1447. (** post: dir = d **)
  1448. BEGIN
  1449. ASSERT(d # NIL, 20); ASSERT(d.attr.init, 21); dir := d
  1450. END SetDir;
  1451. PROCEDURE Init;
  1452. VAR d: StdDirectory; fnt: Fonts.Font; asc, dsc, w: INTEGER;
  1453. BEGIN
  1454. IF Dialog.metricSystem THEN
  1455. marginGrid := 1*mm; minTabWidth := 1*mm; tabGrid := 1*mm
  1456. ELSE
  1457. marginGrid := inch16; minTabWidth := inch16; tabGrid := inch16
  1458. END;
  1459. fnt := Fonts.dir.Default();
  1460. font := Fonts.dir.This(fnt.typeface, 7*point, {}, Fonts.normal); (* font for ruler scales *)
  1461. NEW(prop);
  1462. prop.valid := {first .. tabs};
  1463. prop.first := 0; prop.left := 0;
  1464. IF Dialog.metricSystem THEN
  1465. prop.right := 165*mm
  1466. ELSE
  1467. prop.right := 104*inch16
  1468. END;
  1469. fnt.GetBounds(asc, dsc, w);
  1470. prop.lead := 0; prop.asc := asc; prop.dsc := dsc; prop.grid := 1;
  1471. prop.opts.val := {leftAdjust}; prop.opts.mask := options;
  1472. prop.tabs.len := 0;
  1473. NEW(def); def.InitFromProp(prop);
  1474. NEW(d); d.attr := def; dir := d; stdDir := d
  1475. END Init;
  1476. PROCEDURE Cleaner;
  1477. BEGIN
  1478. globRd := NIL
  1479. END Cleaner;
  1480. BEGIN
  1481. Init;
  1482. Kernel.InstallCleaner(Cleaner)
  1483. CLOSE
  1484. Kernel.RemoveCleaner(Cleaner)
  1485. END TextRulers.