Pratt 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. data/.exrc +61 -0
  2. data/.gitignore +4 -0
  3. data/History.txt +6 -0
  4. data/Manifest.txt +46 -0
  5. data/Pratt.gemspec +351 -0
  6. data/README.txt +66 -0
  7. data/Rakefile +85 -0
  8. data/TODO +54 -0
  9. data/VERSION +1 -0
  10. data/bin/pratt.rb +13 -0
  11. data/config.rb +34 -0
  12. data/lib/pratt.rb +527 -0
  13. data/lib/pratt/array.rb +11 -0
  14. data/lib/pratt/string.rb +18 -0
  15. data/models/app.rb +40 -0
  16. data/models/customer.rb +24 -0
  17. data/models/payment.rb +22 -0
  18. data/models/pratt.rb +19 -0
  19. data/models/project.rb +82 -0
  20. data/models/whence.rb +70 -0
  21. data/pkgs/tile-0.8.2.tar.gz +0 -0
  22. data/pkgs/tile-0.8.2/ANNOUNCE.txt +95 -0
  23. data/pkgs/tile-0.8.2/ChangeLog +4651 -0
  24. data/pkgs/tile-0.8.2/Makefile +250 -0
  25. data/pkgs/tile-0.8.2/Makefile.in +250 -0
  26. data/pkgs/tile-0.8.2/README.txt +86 -0
  27. data/pkgs/tile-0.8.2/aclocal.m4 +2 -0
  28. data/pkgs/tile-0.8.2/altTheme.o +0 -0
  29. data/pkgs/tile-0.8.2/blink.o +0 -0
  30. data/pkgs/tile-0.8.2/button.o +0 -0
  31. data/pkgs/tile-0.8.2/cache.o +0 -0
  32. data/pkgs/tile-0.8.2/clamTheme.o +0 -0
  33. data/pkgs/tile-0.8.2/classicTheme.o +0 -0
  34. data/pkgs/tile-0.8.2/config.log +1330 -0
  35. data/pkgs/tile-0.8.2/config.status +795 -0
  36. data/pkgs/tile-0.8.2/configure +15248 -0
  37. data/pkgs/tile-0.8.2/configure.in +89 -0
  38. data/pkgs/tile-0.8.2/demos/autocomplete.tcl +59 -0
  39. data/pkgs/tile-0.8.2/demos/demo.tcl +870 -0
  40. data/pkgs/tile-0.8.2/demos/dirbrowser.tcl +167 -0
  41. data/pkgs/tile-0.8.2/demos/dlgtest.tcl +97 -0
  42. data/pkgs/tile-0.8.2/demos/iconlib.tcl +110 -0
  43. data/pkgs/tile-0.8.2/demos/repeater.tcl +117 -0
  44. data/pkgs/tile-0.8.2/demos/toolbutton.tcl +101 -0
  45. data/pkgs/tile-0.8.2/doc/Geometry.3 +230 -0
  46. data/pkgs/tile-0.8.2/doc/INDEX.MAP +153 -0
  47. data/pkgs/tile-0.8.2/doc/Makefile +36 -0
  48. data/pkgs/tile-0.8.2/doc/TILE.XML +45 -0
  49. data/pkgs/tile-0.8.2/doc/Theme.3 +34 -0
  50. data/pkgs/tile-0.8.2/doc/button.n +75 -0
  51. data/pkgs/tile-0.8.2/doc/checkbutton.n +61 -0
  52. data/pkgs/tile-0.8.2/doc/combobox.n +98 -0
  53. data/pkgs/tile-0.8.2/doc/converting.txt +97 -0
  54. data/pkgs/tile-0.8.2/doc/dialog.n +122 -0
  55. data/pkgs/tile-0.8.2/doc/entry.n +438 -0
  56. data/pkgs/tile-0.8.2/doc/frame.n +43 -0
  57. data/pkgs/tile-0.8.2/doc/html/Geometry.html +304 -0
  58. data/pkgs/tile-0.8.2/doc/html/Theme.html +48 -0
  59. data/pkgs/tile-0.8.2/doc/html/button.html +120 -0
  60. data/pkgs/tile-0.8.2/doc/html/category-index.html +18 -0
  61. data/pkgs/tile-0.8.2/doc/html/checkbutton.html +94 -0
  62. data/pkgs/tile-0.8.2/doc/html/combobox.html +164 -0
  63. data/pkgs/tile-0.8.2/doc/html/converting.txt +97 -0
  64. data/pkgs/tile-0.8.2/doc/html/dialog.html +159 -0
  65. data/pkgs/tile-0.8.2/doc/html/entry.html +613 -0
  66. data/pkgs/tile-0.8.2/doc/html/frame.html +76 -0
  67. data/pkgs/tile-0.8.2/doc/html/image.html +100 -0
  68. data/pkgs/tile-0.8.2/doc/html/index.html +25 -0
  69. data/pkgs/tile-0.8.2/doc/html/keyword-index.html +228 -0
  70. data/pkgs/tile-0.8.2/doc/html/label.html +133 -0
  71. data/pkgs/tile-0.8.2/doc/html/labelframe.html +91 -0
  72. data/pkgs/tile-0.8.2/doc/html/manpage.css +212 -0
  73. data/pkgs/tile-0.8.2/doc/html/menubutton.html +63 -0
  74. data/pkgs/tile-0.8.2/doc/html/notebook.html +280 -0
  75. data/pkgs/tile-0.8.2/doc/html/paned.html +149 -0
  76. data/pkgs/tile-0.8.2/doc/html/progressbar.html +138 -0
  77. data/pkgs/tile-0.8.2/doc/html/radiobutton.html +89 -0
  78. data/pkgs/tile-0.8.2/doc/html/scrollbar.html +221 -0
  79. data/pkgs/tile-0.8.2/doc/html/separator.html +48 -0
  80. data/pkgs/tile-0.8.2/doc/html/sizegrip.html +62 -0
  81. data/pkgs/tile-0.8.2/doc/html/style.html +172 -0
  82. data/pkgs/tile-0.8.2/doc/html/tile-intro.html +164 -0
  83. data/pkgs/tile-0.8.2/doc/html/treeview.html +634 -0
  84. data/pkgs/tile-0.8.2/doc/html/widget.html +342 -0
  85. data/pkgs/tile-0.8.2/doc/image.n +81 -0
  86. data/pkgs/tile-0.8.2/doc/internals.txt +409 -0
  87. data/pkgs/tile-0.8.2/doc/label.n +75 -0
  88. data/pkgs/tile-0.8.2/doc/labelframe.n +64 -0
  89. data/pkgs/tile-0.8.2/doc/man.macros +239 -0
  90. data/pkgs/tile-0.8.2/doc/menubutton.n +41 -0
  91. data/pkgs/tile-0.8.2/doc/notebook.n +188 -0
  92. data/pkgs/tile-0.8.2/doc/paned.n +95 -0
  93. data/pkgs/tile-0.8.2/doc/progressbar.n +79 -0
  94. data/pkgs/tile-0.8.2/doc/radiobutton.n +57 -0
  95. data/pkgs/tile-0.8.2/doc/scrollbar.n +160 -0
  96. data/pkgs/tile-0.8.2/doc/separator.n +30 -0
  97. data/pkgs/tile-0.8.2/doc/sizegrip.n +53 -0
  98. data/pkgs/tile-0.8.2/doc/style.n +119 -0
  99. data/pkgs/tile-0.8.2/doc/tile-intro.n +165 -0
  100. data/pkgs/tile-0.8.2/doc/tmml.options +4 -0
  101. data/pkgs/tile-0.8.2/doc/treeview.n +415 -0
  102. data/pkgs/tile-0.8.2/doc/widget.n +227 -0
  103. data/pkgs/tile-0.8.2/doc/xml/Geometry.tmml +379 -0
  104. data/pkgs/tile-0.8.2/doc/xml/INDEX.MAP +153 -0
  105. data/pkgs/tile-0.8.2/doc/xml/Theme.tmml +63 -0
  106. data/pkgs/tile-0.8.2/doc/xml/button.tmml +134 -0
  107. data/pkgs/tile-0.8.2/doc/xml/checkbutton.tmml +119 -0
  108. data/pkgs/tile-0.8.2/doc/xml/combobox.tmml +184 -0
  109. data/pkgs/tile-0.8.2/doc/xml/dialog.tmml +195 -0
  110. data/pkgs/tile-0.8.2/doc/xml/entry.tmml +630 -0
  111. data/pkgs/tile-0.8.2/doc/xml/frame.tmml +98 -0
  112. data/pkgs/tile-0.8.2/doc/xml/image.tmml +101 -0
  113. data/pkgs/tile-0.8.2/doc/xml/label.tmml +154 -0
  114. data/pkgs/tile-0.8.2/doc/xml/labelframe.tmml +116 -0
  115. data/pkgs/tile-0.8.2/doc/xml/menubutton.tmml +80 -0
  116. data/pkgs/tile-0.8.2/doc/xml/notebook.tmml +306 -0
  117. data/pkgs/tile-0.8.2/doc/xml/paned.tmml +154 -0
  118. data/pkgs/tile-0.8.2/doc/xml/progressbar.tmml +151 -0
  119. data/pkgs/tile-0.8.2/doc/xml/radiobutton.tmml +109 -0
  120. data/pkgs/tile-0.8.2/doc/xml/scrollbar.tmml +233 -0
  121. data/pkgs/tile-0.8.2/doc/xml/separator.tmml +59 -0
  122. data/pkgs/tile-0.8.2/doc/xml/sizegrip.tmml +82 -0
  123. data/pkgs/tile-0.8.2/doc/xml/style.tmml +171 -0
  124. data/pkgs/tile-0.8.2/doc/xml/tile-intro.tmml +192 -0
  125. data/pkgs/tile-0.8.2/doc/xml/treeview.tmml +604 -0
  126. data/pkgs/tile-0.8.2/doc/xml/widget.tmml +372 -0
  127. data/pkgs/tile-0.8.2/entry.o +0 -0
  128. data/pkgs/tile-0.8.2/frame.o +0 -0
  129. data/pkgs/tile-0.8.2/generic/Makefile.in +221 -0
  130. data/pkgs/tile-0.8.2/generic/TODO +493 -0
  131. data/pkgs/tile-0.8.2/generic/altTheme.c +1172 -0
  132. data/pkgs/tile-0.8.2/generic/blink.c +168 -0
  133. data/pkgs/tile-0.8.2/generic/button.c +858 -0
  134. data/pkgs/tile-0.8.2/generic/cache.c +354 -0
  135. data/pkgs/tile-0.8.2/generic/clamTheme.c +974 -0
  136. data/pkgs/tile-0.8.2/generic/classicTheme.c +518 -0
  137. data/pkgs/tile-0.8.2/generic/configure +10334 -0
  138. data/pkgs/tile-0.8.2/generic/configure.in +100 -0
  139. data/pkgs/tile-0.8.2/generic/entry.c +1922 -0
  140. data/pkgs/tile-0.8.2/generic/frame.c +648 -0
  141. data/pkgs/tile-0.8.2/generic/gunk.h +44 -0
  142. data/pkgs/tile-0.8.2/generic/image.c +416 -0
  143. data/pkgs/tile-0.8.2/generic/label.c +663 -0
  144. data/pkgs/tile-0.8.2/generic/layout.c +1215 -0
  145. data/pkgs/tile-0.8.2/generic/manager.c +554 -0
  146. data/pkgs/tile-0.8.2/generic/manager.h +91 -0
  147. data/pkgs/tile-0.8.2/generic/notebook.c +1380 -0
  148. data/pkgs/tile-0.8.2/generic/paned.c +958 -0
  149. data/pkgs/tile-0.8.2/generic/pkgIndex.tcl.in +7 -0
  150. data/pkgs/tile-0.8.2/generic/progress.c +549 -0
  151. data/pkgs/tile-0.8.2/generic/scale.c +526 -0
  152. data/pkgs/tile-0.8.2/generic/scroll.c +253 -0
  153. data/pkgs/tile-0.8.2/generic/scrollbar.c +346 -0
  154. data/pkgs/tile-0.8.2/generic/separator.c +132 -0
  155. data/pkgs/tile-0.8.2/generic/square.c +306 -0
  156. data/pkgs/tile-0.8.2/generic/tagset.c +147 -0
  157. data/pkgs/tile-0.8.2/generic/tile.c +296 -0
  158. data/pkgs/tile-0.8.2/generic/tkElements.c +1280 -0
  159. data/pkgs/tile-0.8.2/generic/tkTheme.c +1708 -0
  160. data/pkgs/tile-0.8.2/generic/tkTheme.h +419 -0
  161. data/pkgs/tile-0.8.2/generic/tkThemeInt.h +45 -0
  162. data/pkgs/tile-0.8.2/generic/tkstate.c +268 -0
  163. data/pkgs/tile-0.8.2/generic/trace.c +145 -0
  164. data/pkgs/tile-0.8.2/generic/track.c +174 -0
  165. data/pkgs/tile-0.8.2/generic/treeview.c +3211 -0
  166. data/pkgs/tile-0.8.2/generic/ttk.decls +154 -0
  167. data/pkgs/tile-0.8.2/generic/ttkDecls.h +340 -0
  168. data/pkgs/tile-0.8.2/generic/ttkStubInit.c +61 -0
  169. data/pkgs/tile-0.8.2/generic/ttkStubLib.c +70 -0
  170. data/pkgs/tile-0.8.2/generic/widget.c +785 -0
  171. data/pkgs/tile-0.8.2/generic/widget.h +263 -0
  172. data/pkgs/tile-0.8.2/image.o +0 -0
  173. data/pkgs/tile-0.8.2/label.o +0 -0
  174. data/pkgs/tile-0.8.2/layout.o +0 -0
  175. data/pkgs/tile-0.8.2/library/altTheme.tcl +101 -0
  176. data/pkgs/tile-0.8.2/library/aquaTheme.tcl +62 -0
  177. data/pkgs/tile-0.8.2/library/button.tcl +85 -0
  178. data/pkgs/tile-0.8.2/library/clamTheme.tcl +139 -0
  179. data/pkgs/tile-0.8.2/library/classicTheme.tcl +108 -0
  180. data/pkgs/tile-0.8.2/library/combobox.tcl +439 -0
  181. data/pkgs/tile-0.8.2/library/cursors.tcl +36 -0
  182. data/pkgs/tile-0.8.2/library/defaults.tcl +118 -0
  183. data/pkgs/tile-0.8.2/library/dialog.tcl +274 -0
  184. data/pkgs/tile-0.8.2/library/entry.tcl +580 -0
  185. data/pkgs/tile-0.8.2/library/fonts.tcl +153 -0
  186. data/pkgs/tile-0.8.2/library/icons.tcl +105 -0
  187. data/pkgs/tile-0.8.2/library/keynav.tcl +192 -0
  188. data/pkgs/tile-0.8.2/library/menubutton.tcl +171 -0
  189. data/pkgs/tile-0.8.2/library/notebook.tcl +193 -0
  190. data/pkgs/tile-0.8.2/library/paned.tcl +87 -0
  191. data/pkgs/tile-0.8.2/library/progress.tcl +51 -0
  192. data/pkgs/tile-0.8.2/library/scale.tcl +54 -0
  193. data/pkgs/tile-0.8.2/library/scrollbar.tcl +125 -0
  194. data/pkgs/tile-0.8.2/library/sizegrip.tcl +77 -0
  195. data/pkgs/tile-0.8.2/library/tile.tcl +211 -0
  196. data/pkgs/tile-0.8.2/library/treeview.tcl +382 -0
  197. data/pkgs/tile-0.8.2/library/utils.tcl +254 -0
  198. data/pkgs/tile-0.8.2/library/winTheme.tcl +77 -0
  199. data/pkgs/tile-0.8.2/library/xpTheme.tcl +63 -0
  200. data/pkgs/tile-0.8.2/libtile0.8.2.so +0 -0
  201. data/pkgs/tile-0.8.2/libttkstub.a +0 -0
  202. data/pkgs/tile-0.8.2/license.terms +24 -0
  203. data/pkgs/tile-0.8.2/macosx/aquaTheme.c +1076 -0
  204. data/pkgs/tile-0.8.2/manager.o +0 -0
  205. data/pkgs/tile-0.8.2/notebook.o +0 -0
  206. data/pkgs/tile-0.8.2/paned.o +0 -0
  207. data/pkgs/tile-0.8.2/pkgIndex.tcl +3 -0
  208. data/pkgs/tile-0.8.2/progress.o +0 -0
  209. data/pkgs/tile-0.8.2/scale.o +0 -0
  210. data/pkgs/tile-0.8.2/scroll.o +0 -0
  211. data/pkgs/tile-0.8.2/scrollbar.o +0 -0
  212. data/pkgs/tile-0.8.2/separator.o +0 -0
  213. data/pkgs/tile-0.8.2/tagset.o +0 -0
  214. data/pkgs/tile-0.8.2/tclconfig/install-sh +119 -0
  215. data/pkgs/tile-0.8.2/tclconfig/tcl.m4 +4069 -0
  216. data/pkgs/tile-0.8.2/tclconfig/teax.m4 +109 -0
  217. data/pkgs/tile-0.8.2/tests/all.tcl +18 -0
  218. data/pkgs/tile-0.8.2/tests/bwidget.test +103 -0
  219. data/pkgs/tile-0.8.2/tests/cbtest.tcl +125 -0
  220. data/pkgs/tile-0.8.2/tests/combobox.test +51 -0
  221. data/pkgs/tile-0.8.2/tests/compound.tcl +92 -0
  222. data/pkgs/tile-0.8.2/tests/entry.test +285 -0
  223. data/pkgs/tile-0.8.2/tests/entrytest.tcl +78 -0
  224. data/pkgs/tile-0.8.2/tests/image.test +94 -0
  225. data/pkgs/tile-0.8.2/tests/labelframe.tcl +41 -0
  226. data/pkgs/tile-0.8.2/tests/labelframe.test +137 -0
  227. data/pkgs/tile-0.8.2/tests/layout.test +33 -0
  228. data/pkgs/tile-0.8.2/tests/misc.test +35 -0
  229. data/pkgs/tile-0.8.2/tests/nbtest.tcl +66 -0
  230. data/pkgs/tile-0.8.2/tests/notebook.test +500 -0
  231. data/pkgs/tile-0.8.2/tests/paned.test +298 -0
  232. data/pkgs/tile-0.8.2/tests/progress.test +92 -0
  233. data/pkgs/tile-0.8.2/tests/pwtest.tcl +90 -0
  234. data/pkgs/tile-0.8.2/tests/sbtest.tcl +79 -0
  235. data/pkgs/tile-0.8.2/tests/scrollbar.test +77 -0
  236. data/pkgs/tile-0.8.2/tests/sgtest.tcl +52 -0
  237. data/pkgs/tile-0.8.2/tests/testutils.tcl +20 -0
  238. data/pkgs/tile-0.8.2/tests/tile.test +674 -0
  239. data/pkgs/tile-0.8.2/tests/treetags.test +78 -0
  240. data/pkgs/tile-0.8.2/tests/treeview.test +563 -0
  241. data/pkgs/tile-0.8.2/tests/tvtest.tcl +332 -0
  242. data/pkgs/tile-0.8.2/tests/validate.test +278 -0
  243. data/pkgs/tile-0.8.2/tile.o +0 -0
  244. data/pkgs/tile-0.8.2/tkElements.o +0 -0
  245. data/pkgs/tile-0.8.2/tkTheme.o +0 -0
  246. data/pkgs/tile-0.8.2/tkstate.o +0 -0
  247. data/pkgs/tile-0.8.2/tools/genStubs.tcl +861 -0
  248. data/pkgs/tile-0.8.2/trace.o +0 -0
  249. data/pkgs/tile-0.8.2/track.o +0 -0
  250. data/pkgs/tile-0.8.2/treeview.o +0 -0
  251. data/pkgs/tile-0.8.2/ttkStubInit.o +0 -0
  252. data/pkgs/tile-0.8.2/ttkStubLib.o +0 -0
  253. data/pkgs/tile-0.8.2/widget.o +0 -0
  254. data/pkgs/tile-0.8.2/win/Tile.dsp +261 -0
  255. data/pkgs/tile-0.8.2/win/makefile.vc +527 -0
  256. data/pkgs/tile-0.8.2/win/monitor.c +164 -0
  257. data/pkgs/tile-0.8.2/win/nmakehlp.c +483 -0
  258. data/pkgs/tile-0.8.2/win/rules.vc +512 -0
  259. data/pkgs/tile-0.8.2/win/tile.rc +40 -0
  260. data/pkgs/tile-0.8.2/win/winTheme.c +734 -0
  261. data/pkgs/tile-0.8.2/win/xpTheme.c +1029 -0
  262. data/spec/app_spec.rb +48 -0
  263. data/spec/customer_spec.rb +31 -0
  264. data/spec/fixtures/graph.expectation +18 -0
  265. data/spec/payment_spec.rb +19 -0
  266. data/spec/pratt_spec.rb +148 -0
  267. data/spec/project_spec.rb +163 -0
  268. data/spec/rcov.opts +0 -0
  269. data/spec/spec.opts +1 -0
  270. data/spec/spec_helper.rb +21 -0
  271. data/spec/whence_spec.rb +54 -0
  272. data/tasks/pratt.rb +84 -0
  273. data/templates/model.eruby +12 -0
  274. data/templates/spec.eruby +8 -0
  275. data/views/env.rb +22 -0
  276. data/views/graph.eruby +20 -0
  277. data/views/invoice.eruby +148 -0
  278. data/views/main.rb +92 -0
  279. data/views/pid.eruby +3 -0
  280. data/views/pop.rb +94 -0
  281. data/views/pop2.rb +75 -0
  282. data/views/raw.eruby +11 -0
  283. metadata +390 -0
@@ -0,0 +1,1215 @@
1
+ /*
2
+ * ttkLayout.c --
3
+ *
4
+ * Generic layout processing.
5
+ *
6
+ * Copyright (c) 2003 Joe English. Freely redistributable.
7
+ *
8
+ * layout.c,v 1.76 2007/12/02 04:34:30 jenglish Exp
9
+ */
10
+
11
+ #include <string.h>
12
+ #include <tk.h>
13
+ #include "tkThemeInt.h"
14
+
15
+ #define MAX(a,b) (a > b ? a : b)
16
+ #define MIN(a,b) (a < b ? a : b)
17
+
18
+ /*------------------------------------------------------------------------
19
+ * +++ Ttk_Box and Ttk_Padding utilities:
20
+ */
21
+
22
+ Ttk_Box Ttk_MakeBox(int x, int y, int width, int height)
23
+ {
24
+ Ttk_Box b;
25
+ b.x = x; b.y = y; b.width = width; b.height = height;
26
+ return b;
27
+ }
28
+
29
+ int Ttk_BoxContains(Ttk_Box box, int x, int y)
30
+ {
31
+ return box.x <= x && x < box.x + box.width
32
+ && box.y <= y && y < box.y + box.height;
33
+ }
34
+
35
+ Tcl_Obj *Ttk_NewBoxObj(Ttk_Box box)
36
+ {
37
+ Tcl_Obj *result[4];
38
+
39
+ result[0] = Tcl_NewIntObj(box.x);
40
+ result[1] = Tcl_NewIntObj(box.y);
41
+ result[2] = Tcl_NewIntObj(box.width);
42
+ result[3] = Tcl_NewIntObj(box.height);
43
+
44
+ return Tcl_NewListObj(4, result);
45
+ }
46
+
47
+
48
+
49
+ /*
50
+ * packTop, packBottom, packLeft, packRight --
51
+ * Carve out a parcel of the specified height (resp width)
52
+ * from the specified cavity.
53
+ *
54
+ * Returns:
55
+ * The new parcel.
56
+ *
57
+ * Side effects:
58
+ * Adjust the cavity.
59
+ */
60
+
61
+ static Ttk_Box packTop(Ttk_Box *cavity, int height)
62
+ {
63
+ Ttk_Box parcel;
64
+ height = MIN(height, cavity->height);
65
+ parcel = Ttk_MakeBox(cavity->x, cavity->y, cavity->width, height);
66
+ cavity->y += height;
67
+ cavity->height -= height;
68
+ return parcel;
69
+ }
70
+
71
+ static Ttk_Box packBottom(Ttk_Box *cavity, int height)
72
+ {
73
+ height = MIN(height, cavity->height);
74
+ cavity->height -= height;
75
+ return Ttk_MakeBox(
76
+ cavity->x, cavity->y + cavity->height,
77
+ cavity->width, height);
78
+ }
79
+
80
+ static Ttk_Box packLeft(Ttk_Box *cavity, int width)
81
+ {
82
+ Ttk_Box parcel;
83
+ width = MIN(width, cavity->width);
84
+ parcel = Ttk_MakeBox(cavity->x, cavity->y, width,cavity->height);
85
+ cavity->x += width;
86
+ cavity->width -= width;
87
+ return parcel;
88
+ }
89
+
90
+ static Ttk_Box packRight(Ttk_Box *cavity, int width)
91
+ {
92
+ width = MIN(width, cavity->width);
93
+ cavity->width -= width;
94
+ return Ttk_MakeBox(cavity->x + cavity->width,
95
+ cavity->y, width, cavity->height);
96
+ }
97
+
98
+ /*
99
+ * Ttk_PackBox --
100
+ * Carve out a parcel of the specified size on the specified side
101
+ * in the specified cavity.
102
+ *
103
+ * Returns:
104
+ * The new parcel.
105
+ *
106
+ * Side effects:
107
+ * Adjust the cavity.
108
+ */
109
+
110
+ Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int width, int height, Ttk_Side side)
111
+ {
112
+ switch (side) {
113
+ default:
114
+ case TTK_SIDE_TOP: return packTop(cavity, height);
115
+ case TTK_SIDE_BOTTOM: return packBottom(cavity, height);
116
+ case TTK_SIDE_LEFT: return packLeft(cavity, width);
117
+ case TTK_SIDE_RIGHT: return packRight(cavity, width);
118
+ }
119
+ }
120
+
121
+ /*
122
+ * Ttk_PadBox --
123
+ * Shrink a box by the specified padding amount.
124
+ */
125
+ Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p)
126
+ {
127
+ b.x += p.left;
128
+ b.y += p.top;
129
+ b.width -= (p.left + p.right);
130
+ b.height -= (p.top + p.bottom);
131
+ if (b.width <= 0) b.width = 1;
132
+ if (b.height <= 0) b.height = 1;
133
+ return b;
134
+ }
135
+
136
+ /*
137
+ * Ttk_ExpandBox --
138
+ * Grow a box by the specified padding amount.
139
+ */
140
+ Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p)
141
+ {
142
+ b.x -= p.left;
143
+ b.y -= p.top;
144
+ b.width += (p.left + p.right);
145
+ b.height += (p.top + p.bottom);
146
+ return b;
147
+ }
148
+
149
+ /*
150
+ * Ttk_StickBox --
151
+ * Place a box of size w * h in the specified parcel,
152
+ * according to the specified sticky bits.
153
+ */
154
+ Ttk_Box Ttk_StickBox(Ttk_Box parcel, int width, int height, unsigned sticky)
155
+ {
156
+ int dx, dy;
157
+
158
+ if (width > parcel.width) width = parcel.width;
159
+ if (height > parcel.height) height = parcel.height;
160
+
161
+ dx = parcel.width - width;
162
+ dy = parcel.height - height;
163
+
164
+ /*
165
+ * X coordinate adjustment:
166
+ */
167
+ switch (sticky & (TTK_STICK_W | TTK_STICK_E))
168
+ {
169
+ case TTK_STICK_W | TTK_STICK_E:
170
+ /* no-op -- use entire parcel width */
171
+ break;
172
+ case TTK_STICK_W:
173
+ parcel.width = width;
174
+ break;
175
+ case TTK_STICK_E:
176
+ parcel.x += dx;
177
+ parcel.width = width;
178
+ break;
179
+ default :
180
+ parcel.x += dx / 2;
181
+ parcel.width = width;
182
+ break;
183
+ }
184
+
185
+ /*
186
+ * Y coordinate adjustment:
187
+ */
188
+ switch (sticky & (TTK_STICK_N | TTK_STICK_S))
189
+ {
190
+ case TTK_STICK_N | TTK_STICK_S:
191
+ /* use entire parcel height */
192
+ break;
193
+ case TTK_STICK_N:
194
+ parcel.height = height;
195
+ break;
196
+ case TTK_STICK_S:
197
+ parcel.y += dy;
198
+ parcel.height = height;
199
+ break;
200
+ default :
201
+ parcel.y += dy / 2;
202
+ parcel.height = height;
203
+ break;
204
+ }
205
+
206
+ return parcel;
207
+ }
208
+
209
+ /*
210
+ * AnchorToSticky --
211
+ * Convert a Tk_Anchor enum to a TTK_STICKY bitmask.
212
+ */
213
+ static Ttk_Sticky AnchorToSticky(Tk_Anchor anchor)
214
+ {
215
+ switch (anchor)
216
+ {
217
+ case TK_ANCHOR_N: return TTK_STICK_N;
218
+ case TK_ANCHOR_NE: return TTK_STICK_N | TTK_STICK_E;
219
+ case TK_ANCHOR_E: return TTK_STICK_E;
220
+ case TK_ANCHOR_SE: return TTK_STICK_S | TTK_STICK_E;
221
+ case TK_ANCHOR_S: return TTK_STICK_S;
222
+ case TK_ANCHOR_SW: return TTK_STICK_S | TTK_STICK_W;
223
+ case TK_ANCHOR_W: return TTK_STICK_W;
224
+ case TK_ANCHOR_NW: return TTK_STICK_N | TTK_STICK_W;
225
+ default:
226
+ case TK_ANCHOR_CENTER: return 0;
227
+ }
228
+ }
229
+
230
+ /*
231
+ * Ttk_AnchorBox --
232
+ * Place a box of size w * h in the specified parcel,
233
+ * according to the specified anchor.
234
+ */
235
+ Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int width, int height, Tk_Anchor anchor)
236
+ {
237
+ return Ttk_StickBox(parcel, width, height, AnchorToSticky(anchor));
238
+ }
239
+
240
+ /*
241
+ * Ttk_PlaceBox --
242
+ * Combine Ttk_PackBox() and Ttk_StickBox().
243
+ */
244
+ Ttk_Box Ttk_PlaceBox(
245
+ Ttk_Box *cavity, int width, int height, Ttk_Side side, unsigned sticky)
246
+ {
247
+ return Ttk_StickBox(
248
+ Ttk_PackBox(cavity, width, height, side), width, height, sticky);
249
+ }
250
+
251
+ /*
252
+ * Ttk_PositionBox --
253
+ * Pack and stick a box according to PositionSpec flags.
254
+ */
255
+ TTKAPI Ttk_Box
256
+ Ttk_PositionBox(Ttk_Box *cavity, int width, int height, Ttk_PositionSpec flags)
257
+ {
258
+ Ttk_Box parcel;
259
+
260
+ if (flags & TTK_EXPAND) parcel = *cavity;
261
+ else if (flags & TTK_PACK_TOP) parcel = packTop(cavity, height);
262
+ else if (flags & TTK_PACK_LEFT) parcel = packLeft(cavity, width);
263
+ else if (flags & TTK_PACK_BOTTOM) parcel = packBottom(cavity, height);
264
+ else if (flags & TTK_PACK_RIGHT) parcel = packRight(cavity, width);
265
+ else parcel = *cavity;
266
+
267
+ return Ttk_StickBox(parcel, width, height, flags);
268
+ }
269
+
270
+ /*
271
+ * TTKInitPadding --
272
+ * Common factor of Ttk_GetPaddingFromObj and Ttk_GetBorderFromObj.
273
+ * Initializes Ttk_Padding record, supplying default values
274
+ * for missing entries.
275
+ */
276
+ static void TTKInitPadding(int padc, int pixels[4], Ttk_Padding *pad)
277
+ {
278
+ switch (padc)
279
+ {
280
+ case 0: pixels[0] = 0; /*FALLTHRU*/
281
+ case 1: pixels[1] = pixels[0]; /*FALLTHRU*/
282
+ case 2: pixels[2] = pixels[0]; /*FALLTHRU*/
283
+ case 3: pixels[3] = pixels[1]; /*FALLTHRU*/
284
+ }
285
+
286
+ pad->left = (short)pixels[0];
287
+ pad->top = (short)pixels[1];
288
+ pad->right = (short)pixels[2];
289
+ pad->bottom = (short)pixels[3];
290
+ }
291
+
292
+ /*
293
+ * Ttk_GetPaddingFromObj --
294
+ *
295
+ * Extract a padding specification from a Tcl_Obj * scaled
296
+ * to work with a particular Tk_Window.
297
+ *
298
+ * The string representation of a Ttk_Padding is a list
299
+ * of one to four Tk_Pixel specifications, corresponding
300
+ * to the left, top, right, and bottom padding.
301
+ *
302
+ * If the 'bottom' (fourth) element is missing, it defaults to 'top'.
303
+ * If the 'right' (third) element is missing, it defaults to 'left'.
304
+ * If the 'top' (second) element is missing, it defaults to 'left'.
305
+ *
306
+ * The internal representation is a Tcl_ListObj containing
307
+ * one to four Tk_PixelObj objects.
308
+ *
309
+ * Returns:
310
+ * TCL_OK or TCL_ERROR. In the latter case an error message is
311
+ * left in 'interp' and '*paddingPtr' is set to all-zeros.
312
+ * Otherwise, *paddingPtr is filled in with the padding specification.
313
+ *
314
+ */
315
+ int Ttk_GetPaddingFromObj(
316
+ Tcl_Interp *interp,
317
+ Tk_Window tkwin,
318
+ Tcl_Obj *objPtr,
319
+ Ttk_Padding *pad)
320
+ {
321
+ Tcl_Obj **padv;
322
+ int i, padc, pixels[4];
323
+
324
+ if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {
325
+ goto error;
326
+ }
327
+
328
+ if (padc > 4) {
329
+ if (interp) {
330
+ Tcl_ResetResult(interp);
331
+ Tcl_AppendResult(interp, "Wrong #elements in padding spec", NULL);
332
+ }
333
+ goto error;
334
+ }
335
+
336
+ for (i=0; i < padc; ++i) {
337
+ if (Tk_GetPixelsFromObj(interp, tkwin, padv[i], &pixels[i]) != TCL_OK) {
338
+ goto error;
339
+ }
340
+ }
341
+
342
+ TTKInitPadding(padc, pixels, pad);
343
+ return TCL_OK;
344
+
345
+ error:
346
+ pad->left = pad->top = pad->right = pad->bottom = 0;
347
+ return TCL_ERROR;
348
+ }
349
+
350
+ /* Ttk_GetBorderFromObj --
351
+ * Same as Ttk_GetPaddingFromObj, except padding is a list of integers
352
+ * instead of Tk_Pixel specifications. Does not require a Tk_Window
353
+ * parameter.
354
+ *
355
+ */
356
+ int Ttk_GetBorderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad)
357
+ {
358
+ Tcl_Obj **padv;
359
+ int i, padc, pixels[4];
360
+
361
+ if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {
362
+ goto error;
363
+ }
364
+
365
+ if (padc > 4) {
366
+ if (interp) {
367
+ Tcl_ResetResult(interp);
368
+ Tcl_AppendResult(interp, "Wrong #elements in border spec", NULL);
369
+ }
370
+ goto error;
371
+ }
372
+
373
+ for (i=0; i < padc; ++i) {
374
+ if (Tcl_GetIntFromObj(interp, padv[i], &pixels[i]) != TCL_OK) {
375
+ goto error;
376
+ }
377
+ }
378
+
379
+ TTKInitPadding(padc, pixels, pad);
380
+ return TCL_OK;
381
+
382
+ error:
383
+ pad->left = pad->top = pad->right = pad->bottom = 0;
384
+ return TCL_ERROR;
385
+ }
386
+
387
+ /*
388
+ * Ttk_MakePadding --
389
+ * Return an initialized Ttk_Padding structure.
390
+ */
391
+ Ttk_Padding Ttk_MakePadding(short left, short top, short right, short bottom)
392
+ {
393
+ Ttk_Padding pad;
394
+ pad.left = left;
395
+ pad.top = top;
396
+ pad.right = right;
397
+ pad.bottom = bottom;
398
+ return pad;
399
+ }
400
+
401
+ /*
402
+ * Ttk_UniformPadding --
403
+ * Returns a uniform Ttk_Padding structure, with the same
404
+ * border width on all sides.
405
+ */
406
+ Ttk_Padding Ttk_UniformPadding(short borderWidth)
407
+ {
408
+ Ttk_Padding pad;
409
+ pad.left = pad.top = pad.right = pad.bottom = borderWidth;
410
+ return pad;
411
+ }
412
+
413
+ /*
414
+ * Ttk_AddPadding --
415
+ * Combine two padding records.
416
+ */
417
+ Ttk_Padding Ttk_AddPadding(Ttk_Padding p1, Ttk_Padding p2)
418
+ {
419
+ p1.left += p2.left;
420
+ p1.top += p2.top;
421
+ p1.right += p2.right;
422
+ p1.bottom += p2.bottom;
423
+ return p1;
424
+ }
425
+
426
+ /* Ttk_RelievePadding --
427
+ * Add an extra n pixels of padding according to specified relief.
428
+ * This may be used in element geometry procedures to simulate
429
+ * a "pressed-in" look for pushbuttons.
430
+ */
431
+ Ttk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief, int n)
432
+ {
433
+ switch (relief)
434
+ {
435
+ case TK_RELIEF_RAISED:
436
+ padding.right += n;
437
+ padding.bottom += n;
438
+ break;
439
+ case TK_RELIEF_SUNKEN: /* shift */
440
+ padding.left += n;
441
+ padding.top += n;
442
+ break;
443
+ default:
444
+ {
445
+ int h1 = n/2, h2 = h1 + n % 2;
446
+ padding.left += h1;
447
+ padding.top += h1;
448
+ padding.right += h2;
449
+ padding.bottom += h2;
450
+ break;
451
+ }
452
+ }
453
+ return padding;
454
+ }
455
+
456
+ /*
457
+ * Ttk_GetStickyFromObj --
458
+ * Returns a stickiness specification from the specified Tcl_Obj*,
459
+ * consisting of any combination of n, s, e, and w.
460
+ *
461
+ * Returns: TCL_OK if objPtr holds a valid stickiness specification,
462
+ * otherwise TCL_ERROR. interp is used for error reporting if non-NULL.
463
+ *
464
+ */
465
+ int Ttk_GetStickyFromObj(
466
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *result)
467
+ {
468
+ const char *string = Tcl_GetString(objPtr);
469
+ Ttk_Sticky sticky = 0;
470
+ char c;
471
+
472
+ while ((c = *string++) != '\0') {
473
+ switch (c) {
474
+ case 'w': case 'W': sticky |= TTK_STICK_W; break;
475
+ case 'e': case 'E': sticky |= TTK_STICK_E; break;
476
+ case 'n': case 'N': sticky |= TTK_STICK_N; break;
477
+ case 's': case 'S': sticky |= TTK_STICK_S; break;
478
+ default:
479
+ if (interp) {
480
+ Tcl_ResetResult(interp);
481
+ Tcl_AppendResult(interp,
482
+ "Bad -sticky specification ",
483
+ Tcl_GetString(objPtr),
484
+ NULL);
485
+ }
486
+ return TCL_ERROR;
487
+ }
488
+ }
489
+
490
+ *result = sticky;
491
+ return TCL_OK;
492
+ }
493
+
494
+ /* Ttk_NewStickyObj --
495
+ * Construct a new Tcl_Obj * containing a stickiness specification.
496
+ */
497
+ Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky sticky)
498
+ {
499
+ char buf[5];
500
+ char *p = buf;
501
+
502
+ if (sticky & TTK_STICK_N) *p++ = 'n';
503
+ if (sticky & TTK_STICK_S) *p++ = 's';
504
+ if (sticky & TTK_STICK_W) *p++ = 'w';
505
+ if (sticky & TTK_STICK_E) *p++ = 'e';
506
+
507
+ *p = '\0';
508
+ return Tcl_NewStringObj(buf, p - buf);
509
+ }
510
+
511
+ /*------------------------------------------------------------------------
512
+ * +++ Layout nodes.
513
+ */
514
+ struct Ttk_LayoutNode_
515
+ {
516
+ unsigned flags; /* Packing and sticky flags */
517
+ Ttk_ElementImpl element; /* Element implementation */
518
+ Ttk_State state; /* Current state */
519
+ Ttk_Box parcel; /* allocated parcel */
520
+ Ttk_LayoutNode *next, *child;
521
+ };
522
+
523
+ static Ttk_LayoutNode *Ttk_NewLayoutNode(unsigned flags, Ttk_ElementImpl element)
524
+ {
525
+ Ttk_LayoutNode *node = (Ttk_LayoutNode*)ckalloc(sizeof(Ttk_LayoutNode));
526
+
527
+ node->flags = flags;
528
+ node->element = element;
529
+ node->state = 0u;
530
+ node->next = node->child = 0;
531
+ /* parcel uninitialized */
532
+
533
+ return node;
534
+ }
535
+
536
+ static void Ttk_FreeLayoutNode(Ttk_LayoutNode *node)
537
+ {
538
+ while (node) {
539
+ Ttk_LayoutNode *next = node->next;
540
+ Ttk_FreeLayoutNode(node->child);
541
+ ckfree((ClientData)node);
542
+ node = next;
543
+ }
544
+ }
545
+
546
+ /*------------------------------------------------------------------------
547
+ * +++ Layout templates.
548
+ */
549
+
550
+ struct Ttk_TemplateNode_ {
551
+ char *name;
552
+ unsigned flags;
553
+ struct Ttk_TemplateNode_ *next, *child;
554
+ };
555
+
556
+ static Ttk_TemplateNode *Ttk_NewTemplateNode(const char *name, unsigned flags)
557
+ {
558
+ Ttk_TemplateNode *op = (Ttk_TemplateNode*)ckalloc(sizeof(*op));
559
+ op->name = ckalloc(strlen(name) + 1); strcpy(op->name, name);
560
+ op->flags = flags;
561
+ op->next = op->child = 0;
562
+ return op;
563
+ }
564
+
565
+ void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate op)
566
+ {
567
+ while (op) {
568
+ Ttk_LayoutTemplate next = op->next;
569
+ Ttk_FreeLayoutTemplate(op->child);
570
+ ckfree(op->name);
571
+ ckfree((ClientData)op);
572
+ op = next;
573
+ }
574
+ }
575
+
576
+ /* InstantiateLayout --
577
+ * Create a layout tree from a template.
578
+ */
579
+ static Ttk_LayoutNode *
580
+ Ttk_InstantiateLayout(Ttk_Theme theme, Ttk_TemplateNode *op)
581
+ {
582
+ Ttk_ElementImpl elementImpl = Ttk_GetElement(theme, op->name);
583
+ Ttk_LayoutNode *node = Ttk_NewLayoutNode(op->flags, elementImpl);
584
+
585
+ if (op->next) {
586
+ node->next = Ttk_InstantiateLayout(theme,op->next);
587
+ }
588
+ if (op->child) {
589
+ node->child = Ttk_InstantiateLayout(theme,op->child);
590
+ }
591
+
592
+ return node;
593
+ }
594
+
595
+ /*
596
+ * Ttk_ParseLayoutTemplate --
597
+ * Convert a Tcl list into a layout template.
598
+ *
599
+ * Syntax:
600
+ * layoutSpec ::= { elementName ?-option value ...? }+
601
+ */
602
+
603
+ /* NB: This must match bit definitions TTK_PACK_LEFT etc. */
604
+ static const char *packSideStrings[] =
605
+ { "left", "right", "top", "bottom", NULL };
606
+
607
+ Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr)
608
+ {
609
+ enum { OP_SIDE, OP_STICKY, OP_EXPAND, OP_BORDER, OP_UNIT, OP_CHILDREN };
610
+ static const char *optStrings[] = {
611
+ "-side", "-sticky", "-expand", "-border", "-unit", "-children", 0 };
612
+
613
+ int i = 0, objc;
614
+ Tcl_Obj **objv;
615
+ Ttk_TemplateNode *head = 0, *tail = 0;
616
+
617
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK)
618
+ return 0;
619
+
620
+ while (i < objc) {
621
+ char *elementName = Tcl_GetString(objv[i]);
622
+ unsigned flags = 0x0, sticky = TTK_FILL_BOTH;
623
+ Tcl_Obj *childSpec = 0;
624
+
625
+ /*
626
+ * Parse options:
627
+ */
628
+ ++i;
629
+ while (i < objc) {
630
+ const char *optName = Tcl_GetString(objv[i]);
631
+ int option, value;
632
+
633
+ if (optName[0] != '-')
634
+ break;
635
+
636
+ if (Tcl_GetIndexFromObj(
637
+ interp, objv[i], optStrings, "option", 0, &option)
638
+ != TCL_OK)
639
+ {
640
+ goto error;
641
+ }
642
+
643
+ if (++i >= objc) {
644
+ Tcl_ResetResult(interp);
645
+ Tcl_AppendResult(interp,
646
+ "Missing value for option ",Tcl_GetString(objv[i-1]),
647
+ NULL);
648
+ goto error;
649
+ }
650
+
651
+ switch (option) {
652
+ case OP_SIDE: /* <<NOTE-PACKSIDE>> */
653
+ if (Tcl_GetIndexFromObj(interp, objv[i], packSideStrings,
654
+ "side", 0, &value) != TCL_OK)
655
+ {
656
+ goto error;
657
+ }
658
+ flags |= (TTK_PACK_LEFT << value);
659
+
660
+ break;
661
+ case OP_STICKY:
662
+ if (Ttk_GetStickyFromObj(interp,objv[i],&sticky) != TCL_OK)
663
+ goto error;
664
+ break;
665
+ case OP_EXPAND:
666
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
667
+ goto error;
668
+ if (value)
669
+ flags |= TTK_EXPAND;
670
+ break;
671
+ case OP_BORDER:
672
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
673
+ goto error;
674
+ if (value)
675
+ flags |= TTK_BORDER;
676
+ break;
677
+ case OP_UNIT:
678
+ if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK)
679
+ goto error;
680
+ if (value)
681
+ flags |= TTK_UNIT;
682
+ break;
683
+ case OP_CHILDREN:
684
+ childSpec = objv[i];
685
+ break;
686
+ }
687
+ ++i;
688
+ }
689
+
690
+ /*
691
+ * Build new node:
692
+ */
693
+ if (tail) {
694
+ tail->next = Ttk_NewTemplateNode(elementName, flags | sticky);
695
+ tail = tail->next;
696
+ } else {
697
+ head = tail = Ttk_NewTemplateNode(elementName, flags | sticky);
698
+ }
699
+ if (childSpec) {
700
+ tail->child = Ttk_ParseLayoutTemplate(interp, childSpec);
701
+ if (!tail->child) {
702
+ goto error;
703
+ }
704
+ }
705
+ }
706
+
707
+ return head;
708
+
709
+ error:
710
+ Ttk_FreeLayoutTemplate(head);
711
+ return 0;
712
+ }
713
+
714
+ /* Ttk_BuildLayoutTemplate --
715
+ * Build a layout template tree from a statically defined
716
+ * Ttk_LayoutSpec array.
717
+ */
718
+ Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec spec)
719
+ {
720
+ Ttk_TemplateNode *first = 0, *last = 0;
721
+
722
+ for ( ; !(spec->opcode & _TTK_LAYOUT_END) ; ++spec) {
723
+ if (spec->elementName) {
724
+ Ttk_TemplateNode *node =
725
+ Ttk_NewTemplateNode(spec->elementName, spec->opcode);
726
+
727
+ if (last) {
728
+ last->next = node;
729
+ } else {
730
+ first = node;
731
+ }
732
+ last = node;
733
+ }
734
+
735
+ if (spec->opcode & _TTK_CHILDREN) {
736
+ int depth = 1;
737
+ last->child = Ttk_BuildLayoutTemplate(spec+1);
738
+
739
+ /* Skip to end of group:
740
+ */
741
+ while (depth) {
742
+ ++spec;
743
+ if (spec->opcode & _TTK_CHILDREN) {
744
+ ++depth;
745
+ }
746
+ if (spec->opcode & _TTK_LAYOUT_END) {
747
+ --depth;
748
+ }
749
+ }
750
+ }
751
+
752
+ } /* for */
753
+
754
+ return first;
755
+ }
756
+
757
+ void Ttk_RegisterLayouts(Ttk_Theme theme, Ttk_LayoutSpec spec)
758
+ {
759
+ while (!(spec->opcode & _TTK_LAYOUT_END)) {
760
+ Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(spec+1);
761
+ Ttk_RegisterLayoutTemplate(theme, spec->elementName, layoutTemplate);
762
+ do {
763
+ ++spec;
764
+ } while (!(spec->opcode & _TTK_LAYOUT));
765
+ }
766
+ }
767
+
768
+ Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)
769
+ {
770
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
771
+
772
+ # define APPENDOBJ(obj) Tcl_ListObjAppendElement(NULL, result, obj)
773
+ # define APPENDSTR(str) APPENDOBJ(Tcl_NewStringObj(str,-1))
774
+
775
+ while (node) {
776
+ unsigned flags = node->flags;
777
+
778
+ APPENDSTR(node->name);
779
+
780
+ /* Back-compute -side. <<NOTE-PACKSIDE>>
781
+ * @@@ NOTES: Ick.
782
+ */
783
+ if (flags & TTK_EXPAND) {
784
+ APPENDSTR("-expand");
785
+ APPENDSTR("1");
786
+ } else {
787
+ if (flags & _TTK_MASK_PACK) {
788
+ int side = 0;
789
+ unsigned sideFlags = flags & _TTK_MASK_PACK;
790
+
791
+ while ((sideFlags & TTK_PACK_LEFT) == 0) {
792
+ ++side;
793
+ sideFlags >>= 1;
794
+ }
795
+ APPENDSTR("-side");
796
+ APPENDSTR(packSideStrings[side]);
797
+ }
798
+ }
799
+
800
+ /* In Ttk_ParseLayoutTemplate, default -sticky is "nsew",
801
+ * so always include this even if no sticky bits are set.
802
+ */
803
+ APPENDSTR("-sticky");
804
+ APPENDOBJ(Ttk_NewStickyObj(flags & _TTK_MASK_STICK));
805
+
806
+ /* @@@ Check again: are these necessary? */
807
+ if (flags & TTK_BORDER) { APPENDSTR("-border"); APPENDSTR("1"); }
808
+ if (flags & TTK_UNIT) { APPENDSTR("-unit"); APPENDSTR("1"); }
809
+
810
+ if (node->child) {
811
+ APPENDSTR("-children");
812
+ APPENDOBJ(Ttk_UnparseLayoutTemplate(node->child));
813
+ }
814
+ node = node->next;
815
+ }
816
+
817
+ # undef APPENDOBJ
818
+ # undef APPENDSTR
819
+
820
+ return result;
821
+ }
822
+
823
+ /*------------------------------------------------------------------------
824
+ * +++ Layouts.
825
+ */
826
+ struct Ttk_Layout_
827
+ {
828
+ Ttk_Style style;
829
+ void *recordPtr;
830
+ Tk_OptionTable optionTable;
831
+ Tk_Window tkwin;
832
+ Ttk_LayoutNode *root;
833
+ };
834
+
835
+ static Ttk_Layout TTKNewLayout(
836
+ Ttk_Style style,
837
+ void *recordPtr,Tk_OptionTable optionTable, Tk_Window tkwin,
838
+ Ttk_LayoutNode *root)
839
+ {
840
+ Ttk_Layout layout = (Ttk_Layout)ckalloc(sizeof(*layout));
841
+ layout->style = style;
842
+ layout->recordPtr = recordPtr;
843
+ layout->optionTable = optionTable;
844
+ layout->tkwin = tkwin;
845
+ layout->root = root;
846
+ return layout;
847
+ }
848
+
849
+ void Ttk_FreeLayout(Ttk_Layout layout)
850
+ {
851
+ Ttk_FreeLayoutNode(layout->root);
852
+ ckfree((ClientData)layout);
853
+ }
854
+
855
+ /*
856
+ * Ttk_CreateLayout --
857
+ * Create a layout from the specified theme and style name.
858
+ * Returns: New layout, 0 on error.
859
+ * Leaves an error message in interp's result if there is an error.
860
+ */
861
+ Ttk_Layout Ttk_CreateLayout(
862
+ Tcl_Interp *interp, /* where to leave error messages */
863
+ Ttk_Theme themePtr,
864
+ const char *styleName,
865
+ void *recordPtr,
866
+ Tk_OptionTable optionTable,
867
+ Tk_Window tkwin)
868
+ {
869
+ Ttk_Style style = Ttk_GetStyle(themePtr, styleName);
870
+ Ttk_LayoutTemplate layoutTemplate =
871
+ Ttk_FindLayoutTemplate(themePtr,styleName);
872
+ Ttk_ElementImpl bgelement = Ttk_GetElement(themePtr, "background");
873
+ Ttk_LayoutNode *bgnode;
874
+
875
+ if (!layoutTemplate) {
876
+ Tcl_ResetResult(interp);
877
+ Tcl_AppendResult(interp, "Layout ", styleName, " not found", NULL);
878
+ return 0;
879
+ }
880
+
881
+ bgnode = Ttk_NewLayoutNode(TTK_FILL_BOTH, bgelement);
882
+ bgnode->next = Ttk_InstantiateLayout(themePtr, layoutTemplate);
883
+
884
+ return TTKNewLayout(style, recordPtr, optionTable, tkwin, bgnode);
885
+ }
886
+
887
+ /* Ttk_CreateSublayout --
888
+ * Creates a new sublayout.
889
+ *
890
+ * Sublayouts are used to draw subparts of a compound widget.
891
+ * They use the same Tk_Window, but a different option table
892
+ * and data record.
893
+ */
894
+ Ttk_Layout
895
+ Ttk_CreateSublayout(
896
+ Tcl_Interp *interp,
897
+ Ttk_Theme themePtr,
898
+ Ttk_Layout parentLayout,
899
+ const char *baseName,
900
+ Tk_OptionTable optionTable)
901
+ {
902
+ Tcl_DString buf;
903
+ const char *styleName;
904
+ Ttk_Style style;
905
+ Ttk_LayoutTemplate layoutTemplate;
906
+
907
+ Tcl_DStringInit(&buf);
908
+ Tcl_DStringAppend(&buf, Ttk_StyleName(parentLayout->style), -1);
909
+ Tcl_DStringAppend(&buf, baseName, -1);
910
+ styleName = Tcl_DStringValue(&buf);
911
+
912
+ style = Ttk_GetStyle(themePtr, styleName);
913
+ layoutTemplate = Ttk_FindLayoutTemplate(themePtr, styleName);
914
+
915
+ if (!layoutTemplate) {
916
+ Tcl_ResetResult(interp);
917
+ Tcl_AppendResult(interp, "Layout ", styleName, " not found", NULL);
918
+ return 0;
919
+ }
920
+
921
+ Tcl_DStringFree(&buf);
922
+
923
+ return TTKNewLayout(
924
+ style, 0, optionTable, parentLayout->tkwin,
925
+ Ttk_InstantiateLayout(themePtr, layoutTemplate));
926
+ }
927
+
928
+ /* Ttk_RebindSublayout --
929
+ * Bind sublayout to new data source.
930
+ */
931
+ void Ttk_RebindSublayout(Ttk_Layout layout, void *recordPtr)
932
+ {
933
+ layout->recordPtr = recordPtr;
934
+ }
935
+
936
+ /*
937
+ * Ttk_QueryOption --
938
+ * Look up an option from a layout's associated option.
939
+ */
940
+ Tcl_Obj *Ttk_QueryOption(
941
+ Ttk_Layout layout, const char *optionName, Ttk_State state)
942
+ {
943
+ return Ttk_QueryStyle(
944
+ layout->style,layout->recordPtr,layout->optionTable,optionName,state);
945
+ }
946
+
947
+ /*------------------------------------------------------------------------
948
+ * +++ Size computation.
949
+ */
950
+ static void Ttk_NodeListSize(
951
+ Ttk_Layout layout, Ttk_LayoutNode *node,
952
+ Ttk_State state, int *widthPtr, int *heightPtr); /* Forward */
953
+
954
+ static void Ttk_NodeSize(
955
+ Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state,
956
+ int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
957
+ {
958
+ int elementWidth, elementHeight, subWidth, subHeight;
959
+ Ttk_Padding elementPadding;
960
+
961
+ Ttk_ElementSize(node->element,
962
+ layout->style, layout->recordPtr,layout->optionTable, layout->tkwin,
963
+ state|node->state,
964
+ &elementWidth, &elementHeight, &elementPadding);
965
+
966
+ Ttk_NodeListSize(layout,node->child,state,&subWidth,&subHeight);
967
+ subWidth += Ttk_PaddingWidth(elementPadding);
968
+ subHeight += Ttk_PaddingHeight(elementPadding);
969
+
970
+ *widthPtr = MAX(elementWidth, subWidth);
971
+ *heightPtr = MAX(elementHeight, subHeight);
972
+ *paddingPtr = elementPadding;
973
+ }
974
+
975
+ static void Ttk_NodeListSize(
976
+ Ttk_Layout layout, Ttk_LayoutNode *node,
977
+ Ttk_State state, int *widthPtr, int *heightPtr)
978
+ {
979
+ if (!node) {
980
+ *widthPtr = *heightPtr = 0;
981
+ } else {
982
+ int width, height, restWidth, restHeight;
983
+ Ttk_Padding unused;
984
+
985
+ Ttk_NodeSize(layout, node, state, &width, &height, &unused);
986
+ Ttk_NodeListSize(layout, node->next, state, &restWidth, &restHeight);
987
+
988
+ if (node->flags & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) {
989
+ *widthPtr = width + restWidth;
990
+ } else {
991
+ *widthPtr = MAX(width, restWidth);
992
+ }
993
+
994
+ if (node->flags & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
995
+ *heightPtr = height + restHeight;
996
+ } else {
997
+ *heightPtr = MAX(height, restHeight);
998
+ }
999
+ }
1000
+ }
1001
+
1002
+ /*
1003
+ * Ttk_LayoutNodeInternalPadding --
1004
+ * Returns the internal padding of a layout node.
1005
+ */
1006
+ Ttk_Padding Ttk_LayoutNodeInternalPadding(
1007
+ Ttk_Layout layout, Ttk_LayoutNode *node)
1008
+ {
1009
+ int unused;
1010
+ Ttk_Padding padding;
1011
+ Ttk_ElementSize(node->element,
1012
+ layout->style, layout->recordPtr, layout->optionTable, layout->tkwin,
1013
+ 0/*state*/, &unused, &unused, &padding);
1014
+ return padding;
1015
+ }
1016
+
1017
+ /*
1018
+ * Ttk_LayoutNodeInternalParcel --
1019
+ * Returns the inner area of a specified layout node,
1020
+ * based on current parcel and element's internal padding.
1021
+ */
1022
+ Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout layout, Ttk_LayoutNode *node)
1023
+ {
1024
+ Ttk_Padding padding = Ttk_LayoutNodeInternalPadding(layout, node);
1025
+ return Ttk_PadBox(node->parcel, padding);
1026
+ }
1027
+
1028
+ /* Ttk_LayoutSize --
1029
+ * Compute requested size of a layout.
1030
+ */
1031
+ void Ttk_LayoutSize(
1032
+ Ttk_Layout layout, Ttk_State state, int *widthPtr, int *heightPtr)
1033
+ {
1034
+ Ttk_NodeListSize(layout, layout->root, state, widthPtr, heightPtr);
1035
+ }
1036
+
1037
+ void Ttk_LayoutNodeReqSize( /* @@@ Rename this */
1038
+ Ttk_Layout layout, Ttk_LayoutNode *node, int *widthPtr, int *heightPtr)
1039
+ {
1040
+ Ttk_Padding unused;
1041
+ Ttk_NodeSize(layout, node, 0/*state*/, widthPtr, heightPtr, &unused);
1042
+ }
1043
+
1044
+ /*------------------------------------------------------------------------
1045
+ * +++ Layout placement.
1046
+ */
1047
+
1048
+ /* Ttk_PlaceNodeList --
1049
+ * Compute parcel for each node in a layout tree
1050
+ * according to position specification and overall size.
1051
+ */
1052
+ static void Ttk_PlaceNodeList(
1053
+ Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state, Ttk_Box cavity)
1054
+ {
1055
+ for (; node; node = node->next)
1056
+ {
1057
+ int width, height;
1058
+ Ttk_Padding padding;
1059
+
1060
+ /* Compute node size: (@@@ cache this instead?)
1061
+ */
1062
+ Ttk_NodeSize(layout, node, state, &width, &height, &padding);
1063
+
1064
+ /* Compute parcel:
1065
+ */
1066
+ node->parcel = Ttk_PositionBox(&cavity, width, height, node->flags);
1067
+
1068
+ /* Place child nodes:
1069
+ */
1070
+ if (node->child) {
1071
+ Ttk_Box childBox = Ttk_PadBox(node->parcel, padding);
1072
+ Ttk_PlaceNodeList(layout,node->child, state, childBox);
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ void Ttk_PlaceLayout(Ttk_Layout layout, Ttk_State state, Ttk_Box b)
1078
+ {
1079
+ Ttk_PlaceNodeList(layout, layout->root, state, b);
1080
+ }
1081
+
1082
+ /*------------------------------------------------------------------------
1083
+ * +++ Layout drawing.
1084
+ */
1085
+
1086
+ /*
1087
+ * Ttk_DrawLayout --
1088
+ * Draw a layout tree.
1089
+ */
1090
+ static void Ttk_DrawNodeList(
1091
+ Ttk_Layout layout, Ttk_State state, Ttk_LayoutNode *node, Drawable d)
1092
+ {
1093
+ for (; node; node = node->next)
1094
+ {
1095
+ int border = node->flags & TTK_BORDER;
1096
+ int substate = state;
1097
+
1098
+ if (node->flags & TTK_UNIT)
1099
+ substate |= node->state;
1100
+
1101
+ if (node->child && border)
1102
+ Ttk_DrawNodeList(layout, substate, node->child, d);
1103
+
1104
+ Ttk_DrawElement(
1105
+ node->element,
1106
+ layout->style,layout->recordPtr,layout->optionTable,layout->tkwin,
1107
+ d, node->parcel, state | node->state);
1108
+
1109
+ if (node->child && !border)
1110
+ Ttk_DrawNodeList(layout, substate, node->child, d);
1111
+ }
1112
+ }
1113
+
1114
+ void Ttk_DrawLayout(Ttk_Layout layout, Ttk_State state, Drawable d)
1115
+ {
1116
+ Ttk_DrawNodeList(layout, state, layout->root, d);
1117
+ }
1118
+
1119
+ /*------------------------------------------------------------------------
1120
+ * +++ Inquiry and modification.
1121
+ */
1122
+
1123
+ /*
1124
+ * Ttk_LayoutIdentify --
1125
+ * Find the layout node at the specified x,y coordinate.
1126
+ */
1127
+ static Ttk_LayoutNode *
1128
+ Ttk_LayoutNodeIdentify(Ttk_LayoutNode *node, int x, int y)
1129
+ {
1130
+ Ttk_LayoutNode *closest = NULL;
1131
+
1132
+ for (; node; node = node->next) {
1133
+ if (Ttk_BoxContains(node->parcel, x, y)) {
1134
+ closest = node;
1135
+ if (node->child && !(node->flags & TTK_UNIT)) {
1136
+ Ttk_LayoutNode *childNode =
1137
+ Ttk_LayoutNodeIdentify(node->child, x,y);
1138
+ if (childNode) {
1139
+ closest = childNode;
1140
+ }
1141
+ }
1142
+ }
1143
+ }
1144
+ return closest;
1145
+ }
1146
+
1147
+ Ttk_LayoutNode *Ttk_LayoutIdentify(Ttk_Layout layout, int x, int y)
1148
+ {
1149
+ return Ttk_LayoutNodeIdentify(layout->root, x, y);
1150
+ }
1151
+
1152
+ /*
1153
+ * tail --
1154
+ * Return the last component of an element name, e.g.,
1155
+ * "Scrollbar.thumb" => "thumb"
1156
+ */
1157
+ static const char *tail(const char *elementName)
1158
+ {
1159
+ const char *dot;
1160
+ while ((dot=strchr(elementName,'.')) != NULL)
1161
+ elementName = dot + 1;
1162
+ return elementName;
1163
+ }
1164
+
1165
+ /*
1166
+ * Ttk_LayoutFindNode --
1167
+ * Look up a layout node by name.
1168
+ */
1169
+ static Ttk_LayoutNode *
1170
+ Ttk_LayoutNodeFind(Ttk_LayoutNode *node, const char *nodeName)
1171
+ {
1172
+ for (; node ; node = node->next) {
1173
+ if (!strcmp(tail(Ttk_LayoutNodeName(node)), nodeName))
1174
+ return node;
1175
+
1176
+ if (node->child) {
1177
+ Ttk_LayoutNode *childNode =
1178
+ Ttk_LayoutNodeFind(node->child, nodeName);
1179
+ if (childNode)
1180
+ return childNode;
1181
+ }
1182
+ }
1183
+ return 0;
1184
+ }
1185
+
1186
+ Ttk_LayoutNode *Ttk_LayoutFindNode(Ttk_Layout layout, const char *nodeName)
1187
+ {
1188
+ return Ttk_LayoutNodeFind(layout->root, nodeName);
1189
+ }
1190
+
1191
+ const char *Ttk_LayoutNodeName(Ttk_LayoutNode *node)
1192
+ {
1193
+ return Ttk_ElementName(node->element);
1194
+ }
1195
+
1196
+ Ttk_Box Ttk_LayoutNodeParcel(Ttk_LayoutNode *node)
1197
+ {
1198
+ return node->parcel;
1199
+ }
1200
+
1201
+ void Ttk_PlaceLayoutNode(Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_Box b)
1202
+ {
1203
+ node->parcel = b;
1204
+ if (node->child) {
1205
+ Ttk_PlaceNodeList(layout, node->child, 0,
1206
+ Ttk_PadBox(b, Ttk_LayoutNodeInternalPadding(layout, node)));
1207
+ }
1208
+ }
1209
+
1210
+ void Ttk_ChangeElementState(Ttk_LayoutNode *node,unsigned set,unsigned clr)
1211
+ {
1212
+ node->state = (node->state | set) & ~clr;
1213
+ }
1214
+
1215
+ /*EOF*/