HyperPage.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. /* HyperPage.cpp
  2. *
  3. * Copyright (C) 1996-2018 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <ctype.h>
  19. #include "HyperPage.h"
  20. #include "Printer.h"
  21. #include "machine.h"
  22. #include "GuiP.h"
  23. #include "praat.h"
  24. #include "EditorM.h"
  25. Thing_implement (HyperPage, Editor, 0);
  26. #include "prefs_define.h"
  27. #include "HyperPage_prefs.h"
  28. #include "prefs_install.h"
  29. #include "HyperPage_prefs.h"
  30. #include "prefs_copyToInstance.h"
  31. #include "HyperPage_prefs.h"
  32. #define PAGE_HEIGHT 320.0
  33. #define SCREEN_HEIGHT 15.0
  34. #define PAPER_TOP 12.0
  35. #define TOP_MARGIN 0.8
  36. #define PAPER_BOTTOM (13.0 - (double) thePrinter. paperHeight / thePrinter. resolution)
  37. #define BOTTOM_MARGIN 0.5
  38. static double resolution;
  39. /********** class HyperLink **********/
  40. Thing_implement (HyperLink, Daata, 0);
  41. autoHyperLink HyperLink_create (conststring32 name, double x1DC, double x2DC, double y1DC, double y2DC) {
  42. autoHyperLink me = Thing_new (HyperLink);
  43. Thing_setName (me.get(), name);
  44. my x1DC = x1DC, my x2DC = x2DC, my y1DC = y1DC, my y2DC = y2DC;
  45. return me;
  46. }
  47. static void saveHistory (HyperPage me, conststring32 title) {
  48. if (! title) return;
  49. /*
  50. * The page title will be saved at the top. Go there.
  51. */
  52. while (my historyPointer < 19 && my history [my historyPointer]. page)
  53. my historyPointer ++;
  54. /*
  55. * If the page title to be saved is already at the top, ignore it.
  56. */
  57. if (my history [my historyPointer]. page) {
  58. if (str32equ (my history [my historyPointer]. page.get(), title)) return;
  59. } else if (my historyPointer > 0 && str32equ (my history [my historyPointer - 1]. page.get(), title)) {
  60. my historyPointer --;
  61. return;
  62. }
  63. /*
  64. * If the history buffer is full, shift it.
  65. */
  66. if (my historyPointer == 19 && my history [my historyPointer]. page) {
  67. for (int i = 0; i < 19; i ++)
  68. my history [i] = std::move (my history [i + 1]);
  69. my history [19]. page. reset();
  70. }
  71. /*
  72. * Add the page title to the top of the history list.
  73. */
  74. my history [my historyPointer]. page = Melder_dup_f (title);
  75. }
  76. /********************************************************************************
  77. *
  78. * Before drawing or printing.
  79. *
  80. */
  81. static void initScreen (HyperPage me) {
  82. my d_y = PAGE_HEIGHT + my top / 5.0;
  83. my d_x = 0;
  84. my previousBottomSpacing = 0.0;
  85. my links. removeAllItems ();
  86. }
  87. void HyperPage_initSheetOfPaper (HyperPage me) {
  88. int reflect = my mirror && (my d_printingPageNumber & 1) == 0;
  89. conststring32 leftHeader = reflect ? my outsideHeader : my insideHeader;
  90. conststring32 rightHeader = reflect ? my insideHeader : my outsideHeader;
  91. conststring32 leftFooter = reflect ? my outsideFooter : my insideFooter;
  92. conststring32 rightFooter = reflect ? my insideFooter : my outsideFooter;
  93. my d_y = PAPER_TOP - TOP_MARGIN;
  94. my d_x = 0;
  95. my previousBottomSpacing = 0.0;
  96. Graphics_setFont (my ps, kGraphics_font::TIMES);
  97. Graphics_setFontSize (my ps, 12);
  98. Graphics_setFontStyle (my ps, Graphics_ITALIC);
  99. if (leftHeader) {
  100. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_TOP);
  101. Graphics_text (my ps, 0.7, PAPER_TOP, leftHeader);
  102. }
  103. if (my middleHeader) {
  104. Graphics_setTextAlignment (my ps, Graphics_CENTRE, Graphics_TOP);
  105. Graphics_text (my ps, 0.7 + 3, PAPER_TOP, my middleHeader);
  106. }
  107. if (rightHeader) {
  108. Graphics_setTextAlignment (my ps, Graphics_RIGHT, Graphics_TOP);
  109. Graphics_text (my ps, 0.7 + 6, PAPER_TOP, rightHeader);
  110. }
  111. if (leftFooter) {
  112. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
  113. Graphics_text (my ps, 0.7, PAPER_BOTTOM, leftFooter);
  114. }
  115. if (my middleFooter) {
  116. Graphics_setTextAlignment (my ps, Graphics_CENTRE, Graphics_BOTTOM);
  117. Graphics_text (my ps, 0.7 + 3, PAPER_BOTTOM, my middleFooter);
  118. }
  119. if (rightFooter) {
  120. Graphics_setTextAlignment (my ps, Graphics_RIGHT, Graphics_BOTTOM);
  121. Graphics_text (my ps, 0.7 + 6, PAPER_BOTTOM, rightFooter);
  122. }
  123. Graphics_setFontStyle (my ps, Graphics_NORMAL);
  124. if (my d_printingPageNumber)
  125. Graphics_text (my ps, 0.7 + ( reflect ? 0 : 6 ), PAPER_BOTTOM, my d_printingPageNumber);
  126. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
  127. }
  128. static void updateVerticalScrollBar (HyperPage me);
  129. void HyperPage_any (HyperPage me, conststring32 text, kGraphics_font font, int size, int style, double minFooterDistance,
  130. double x, double secondIndent, double topSpacing, double bottomSpacing, uint32 method)
  131. {
  132. if (my rightMargin == 0) return; // no infinite heights please
  133. double heightGuess = size * (1.2/72) * ((integer) size * str32len (text) / (int) (my rightMargin * 150));
  134. if (! my printing) {
  135. Graphics_Link *paragraphLinks;
  136. int numberOfParagraphLinks, ilink;
  137. if (my entryHint && (method & HyperPage_USE_ENTRY_HINT) && str32equ (text, my entryHint.get())) {
  138. my entryPosition = my d_y;
  139. }
  140. my d_y -= ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  141. my d_y -= size * (1.2/72);
  142. my d_x = x;
  143. if (/* my d_y > PAGE_HEIGHT + 2.0 + heightGuess || */ my d_y < PAGE_HEIGHT - SCREEN_HEIGHT) {
  144. my d_y -= heightGuess;
  145. } else {
  146. Graphics_setFont (my graphics.get(), font);
  147. Graphics_setFontSize (my graphics.get(), size);
  148. Graphics_setWrapWidth (my graphics.get(), my rightMargin - x - 0.1);
  149. Graphics_setSecondIndent (my graphics.get(), secondIndent);
  150. Graphics_setFontStyle (my graphics.get(), style);
  151. Graphics_text (my graphics.get(), my d_x, my d_y, text);
  152. numberOfParagraphLinks = Graphics_getLinks (& paragraphLinks);
  153. for (ilink = 1; ilink <= numberOfParagraphLinks; ilink ++) {
  154. autoHyperLink link = HyperLink_create (paragraphLinks [ilink]. name,
  155. paragraphLinks [ilink]. x1, paragraphLinks [ilink]. x2,
  156. paragraphLinks [ilink]. y1, paragraphLinks [ilink]. y2);
  157. my links. addItem_move (link.move());
  158. }
  159. if (method & HyperPage_ADD_BORDER) {
  160. Graphics_setLineWidth (my graphics.get(), 2.0);
  161. Graphics_line (my graphics.get(), 0.0, my d_y, my rightMargin, my d_y);
  162. Graphics_setLineWidth (my graphics.get(), 1.0);
  163. }
  164. /*
  165. * The text may have wrapped.
  166. * Ask the Graphics manager by how much, and update our text position accordingly.
  167. */
  168. my d_y = Graphics_inqTextY (my graphics.get());
  169. }
  170. } else {
  171. Graphics_setFont (my ps, font);
  172. Graphics_setFontSize (my ps, size);
  173. my d_y -= my d_y == PAPER_TOP - TOP_MARGIN ? 0 : ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  174. my d_y -= size * (1.2/72);
  175. if (my d_y < PAPER_BOTTOM + BOTTOM_MARGIN + minFooterDistance + size * (1.2/72) * (str32len (text) / (6.0 * 10))) {
  176. Graphics_nextSheetOfPaper (my ps);
  177. if (my d_printingPageNumber) my d_printingPageNumber ++;
  178. HyperPage_initSheetOfPaper (me);
  179. Graphics_setFont (my ps, font);
  180. Graphics_setFontSize (my ps, size);
  181. my d_y -= size * (1.2/72);
  182. }
  183. my d_x = 0.7 + x;
  184. Graphics_setWrapWidth (my ps, 6.0 - x);
  185. Graphics_setSecondIndent (my ps, secondIndent);
  186. Graphics_setFontStyle (my ps, style);
  187. Graphics_text (my ps, my d_x, my d_y, text);
  188. if (method & HyperPage_ADD_BORDER) {
  189. Graphics_setLineWidth (my ps, 3);
  190. /*Graphics_line (my ps, 0.7, my d_y, 6.7, my d_y);*/
  191. Graphics_line (my ps, 0.7, my d_y + size * (1.2/72) + 0.07, 6.7, my d_y + size * (1.2/72) + 0.07);
  192. Graphics_setLineWidth (my ps, 1);
  193. }
  194. my d_y = Graphics_inqTextY (my ps);
  195. }
  196. my previousBottomSpacing = bottomSpacing;
  197. }
  198. void HyperPage_pageTitle (HyperPage me, conststring32 title) {
  199. HyperPage_any (me, title, my p_font, my p_fontSize * 2, 0,
  200. 2.0, 0.0, 0.0, my printing ? 0.4/2 : 0.2/2, 0.3/2, HyperPage_ADD_BORDER);
  201. }
  202. void HyperPage_intro (HyperPage me, conststring32 text) {
  203. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.03, 0.0, 0.1, 0.1, 0);
  204. }
  205. void HyperPage_entry (HyperPage me, conststring32 title) {
  206. HyperPage_any (me, title, my p_font, my p_fontSize * 1.4, Graphics_BOLD, 0.5, 0.0, 0.0, 0.25/1.4, 0.1/1.4, HyperPage_USE_ENTRY_HINT);
  207. }
  208. void HyperPage_paragraph (HyperPage me, conststring32 text) {
  209. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.03, 0.0, 0.1, 0.1, 0);
  210. }
  211. void HyperPage_listItem (HyperPage me, conststring32 text) {
  212. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.30, 0.2, 0.0, 0.0, 0);
  213. }
  214. void HyperPage_listItem1 (HyperPage me, conststring32 text) {
  215. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.57, 0.2, 0.0, 0.0, 0);
  216. }
  217. void HyperPage_listItem2 (HyperPage me, conststring32 text) {
  218. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.84, 0.2, 0.0, 0.0, 0);
  219. }
  220. void HyperPage_listItem3 (HyperPage me, conststring32 text) {
  221. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 1.11, 0.2, 0.0, 0.0, 0);
  222. }
  223. void HyperPage_listTag (HyperPage me, conststring32 text) {
  224. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.2, 0.03, 0.0, 0.1, 0.03, 0);
  225. }
  226. void HyperPage_listTag1 (HyperPage me, conststring32 text) {
  227. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.2, 0.50, 0.0, 0.05, 0.03, 0);
  228. }
  229. void HyperPage_listTag2 (HyperPage me, conststring32 text) {
  230. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.2, 0.97, 0.0, 0.03, 0.03, 0);
  231. }
  232. void HyperPage_listTag3 (HyperPage me, conststring32 text) {
  233. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.2, 1.44, 0.0, 0.03, 0.03, 0);
  234. }
  235. void HyperPage_definition (HyperPage me, conststring32 text) {
  236. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.5, 0.0, 0.03, 0.1, 0);
  237. }
  238. void HyperPage_definition1 (HyperPage me, conststring32 text) {
  239. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.97, 0.0, 0.03, 0.05, 0);
  240. }
  241. void HyperPage_definition2 (HyperPage me, conststring32 text) {
  242. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 1.44, 0.0, 0.03, 0.03, 0);
  243. }
  244. void HyperPage_definition3 (HyperPage me, conststring32 text) {
  245. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 1.93, 0.0, 0.03, 0.03, 0);
  246. }
  247. void HyperPage_code (HyperPage me, conststring32 text) {
  248. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 0.3, 0.5, 0.0, 0.0, 0);
  249. }
  250. void HyperPage_code1 (HyperPage me, conststring32 text) {
  251. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 0.6, 0.5, 0.0, 0.0, 0);
  252. }
  253. void HyperPage_code2 (HyperPage me, conststring32 text) {
  254. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 0.9, 0.5, 0.0, 0.0, 0);
  255. }
  256. void HyperPage_code3 (HyperPage me, conststring32 text) {
  257. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 1.2, 0.5, 0.0, 0.0, 0);
  258. }
  259. void HyperPage_code4 (HyperPage me, conststring32 text) {
  260. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 1.5, 0.5, 0.0, 0.0, 0);
  261. }
  262. void HyperPage_code5 (HyperPage me, conststring32 text) {
  263. HyperPage_any (me, text, kGraphics_font::COURIER, my p_fontSize * 0.86, 0, 0.0, 1.8, 0.5, 0.0, 0.0, 0);
  264. }
  265. void HyperPage_prototype (HyperPage me, conststring32 text) {
  266. HyperPage_any (me, text, my p_font, my p_fontSize, 0, 0.0, 0.03, 0.5, 0.0, 0.0, 0);
  267. }
  268. void HyperPage_formula (HyperPage me, conststring32 formula) {
  269. double topSpacing = 0.2, bottomSpacing = 0.2, minFooterDistance = 0.0;
  270. kGraphics_font font = my p_font;
  271. int size = my p_fontSize;
  272. if (! my printing) {
  273. my d_y -= ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  274. my d_y -= size * (1.2/72);
  275. if (my d_y > PAGE_HEIGHT + 2.0 || my d_y < PAGE_HEIGHT - SCREEN_HEIGHT) {
  276. } else {
  277. Graphics_setFont (my graphics.get(), font);
  278. Graphics_setFontStyle (my graphics.get(), 0);
  279. Graphics_setFontSize (my graphics.get(), size);
  280. Graphics_setWrapWidth (my graphics.get(), 0.0);
  281. Graphics_setTextAlignment (my graphics.get(), Graphics_CENTRE, Graphics_BOTTOM);
  282. Graphics_text (my graphics.get(), 0.5 * my rightMargin, my d_y, formula);
  283. Graphics_setTextAlignment (my graphics.get(), Graphics_LEFT, Graphics_BOTTOM);
  284. }
  285. } else {
  286. Graphics_setFont (my ps, font);
  287. Graphics_setFontStyle (my ps, 0);
  288. Graphics_setFontSize (my ps, size);
  289. my d_y -= my d_y == PAPER_TOP - TOP_MARGIN ? 0 : ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  290. my d_y -= size * (1.2/72);
  291. if (my d_y < PAPER_BOTTOM + BOTTOM_MARGIN + minFooterDistance) {
  292. Graphics_nextSheetOfPaper (my ps);
  293. if (my d_printingPageNumber) my d_printingPageNumber ++;
  294. HyperPage_initSheetOfPaper (me);
  295. Graphics_setFont (my ps, font);
  296. Graphics_setFontSize (my ps, size);
  297. my d_y -= size * (1.2/72);
  298. }
  299. Graphics_setWrapWidth (my ps, 0);
  300. Graphics_setTextAlignment (my ps, Graphics_CENTRE, Graphics_BOTTOM);
  301. Graphics_text (my ps, 3.7, my d_y, formula);
  302. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
  303. }
  304. my previousBottomSpacing = bottomSpacing;
  305. }
  306. void HyperPage_picture (HyperPage me, double width_inches, double height_inches, void (*draw) (Graphics g)) {
  307. double topSpacing = 0.1, bottomSpacing = 0.1, minFooterDistance = 0.0;
  308. kGraphics_font font = my p_font;
  309. int size = my p_fontSize;
  310. width_inches *= width_inches < 0.0 ? -1.0 : size / 12.0;
  311. height_inches *= height_inches < 0.0 ? -1.0 : size / 12.0;
  312. if (! my printing) {
  313. my d_y -= ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  314. if (my d_y > PAGE_HEIGHT + height_inches || my d_y < PAGE_HEIGHT - SCREEN_HEIGHT) {
  315. my d_y -= height_inches;
  316. } else {
  317. my d_y -= height_inches;
  318. Graphics_setFont (my graphics.get(), font);
  319. Graphics_setFontStyle (my graphics.get(), 0);
  320. Graphics_setFontSize (my graphics.get(), size);
  321. my d_x = width_inches > my rightMargin ? 0.0 : 0.5 * (my rightMargin - width_inches);
  322. Graphics_setWrapWidth (my graphics.get(), 0.0);
  323. Graphics_setViewport (my graphics.get(), my d_x, my d_x + width_inches, my d_y, my d_y + height_inches);
  324. draw (my graphics.get());
  325. Graphics_setViewport (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
  326. Graphics_setWindow (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
  327. Graphics_setTextAlignment (my graphics.get(), Graphics_LEFT, Graphics_BOTTOM);
  328. }
  329. } else {
  330. Graphics_setFont (my ps, font);
  331. Graphics_setFontStyle (my ps, 0);
  332. Graphics_setFontSize (my ps, size);
  333. my d_y -= my d_y == PAPER_TOP - TOP_MARGIN ? 0 : ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  334. my d_y -= height_inches;
  335. if (my d_y < PAPER_BOTTOM + BOTTOM_MARGIN + minFooterDistance) {
  336. Graphics_nextSheetOfPaper (my ps);
  337. if (my d_printingPageNumber) my d_printingPageNumber ++;
  338. HyperPage_initSheetOfPaper (me);
  339. Graphics_setFont (my ps, font);
  340. Graphics_setFontSize (my ps, size);
  341. my d_y -= height_inches;
  342. }
  343. my d_x = 3.7 - 0.5 * width_inches;
  344. if (my d_x < 0) my d_x = 0;
  345. Graphics_setWrapWidth (my ps, 0);
  346. Graphics_setViewport (my ps, my d_x, my d_x + width_inches, my d_y, my d_y + height_inches);
  347. draw (my ps);
  348. Graphics_setViewport (my ps, 0, 1, 0, 1);
  349. Graphics_setWindow (my ps, 0, 1, 0, 1);
  350. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
  351. }
  352. my previousBottomSpacing = bottomSpacing;
  353. }
  354. void HyperPage_script (HyperPage me, double width_inches, double height_inches, conststring32 script) {
  355. autostring32 text = Melder_dup (script);
  356. autoInterpreter interpreter = Interpreter_createFromEnvironment (nullptr);
  357. double topSpacing = 0.1, bottomSpacing = 0.1, minFooterDistance = 0.0;
  358. kGraphics_font font = my p_font;
  359. int size = my p_fontSize;
  360. double true_width_inches = width_inches * ( width_inches < 0.0 ? -1.0 : size / 12.0 );
  361. double true_height_inches = height_inches * ( height_inches < 0.0 ? -1.0 : size / 12.0 );
  362. if (! my printing) {
  363. my d_y -= ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  364. if (my d_y > PAGE_HEIGHT + true_height_inches || my d_y < PAGE_HEIGHT - SCREEN_HEIGHT) {
  365. my d_y -= true_height_inches;
  366. } else {
  367. my d_y -= true_height_inches;
  368. Graphics_setFont (my graphics.get(), font);
  369. Graphics_setFontStyle (my graphics.get(), 0);
  370. Graphics_setFontSize (my graphics.get(), size);
  371. my d_x = true_width_inches > my rightMargin ? 0.0 : 0.5 * (my rightMargin - true_width_inches);
  372. Graphics_setWrapWidth (my graphics.get(), 0.0);
  373. integer x1DCold, x2DCold, y1DCold, y2DCold;
  374. Graphics_inqWsViewport (my graphics.get(), & x1DCold, & x2DCold, & y1DCold, & y2DCold);
  375. double x1NDCold, x2NDCold, y1NDCold, y2NDCold;
  376. Graphics_inqWsWindow (my graphics.get(), & x1NDCold, & x2NDCold, & y1NDCold, & y2NDCold);
  377. {
  378. if (! my praatApplication) my praatApplication = Melder_calloc_f (structPraatApplication, 1);
  379. if (! my praatObjects) my praatObjects = Melder_calloc_f (structPraatObjects, 1);
  380. if (! my praatPicture) my praatPicture = Melder_calloc_f (structPraatPicture, 1);
  381. theCurrentPraatApplication = (PraatApplication) my praatApplication;
  382. theCurrentPraatApplication -> batch = true; // prevent creation of editor windows
  383. theCurrentPraatApplication -> topShell = theForegroundPraatApplication. topShell; // needed for UiForm_create () in dialogs
  384. theCurrentPraatObjects = (PraatObjects) my praatObjects;
  385. theCurrentPraatPicture = (PraatPicture) my praatPicture;
  386. theCurrentPraatPicture -> graphics = my graphics.get(); // has to draw into HyperPage rather than Picture window
  387. theCurrentPraatPicture -> font = (int) font;
  388. theCurrentPraatPicture -> fontSize = size;
  389. theCurrentPraatPicture -> lineType = Graphics_DRAWN;
  390. theCurrentPraatPicture -> colour = Graphics_BLACK;
  391. theCurrentPraatPicture -> lineWidth = 1.0;
  392. theCurrentPraatPicture -> arrowSize = 1.0;
  393. theCurrentPraatPicture -> speckleSize = 1.0;
  394. theCurrentPraatPicture -> x1NDC = my d_x;
  395. theCurrentPraatPicture -> x2NDC = my d_x + true_width_inches;
  396. theCurrentPraatPicture -> y1NDC = my d_y;
  397. theCurrentPraatPicture -> y2NDC = my d_y + true_height_inches;
  398. Graphics_setViewport (my graphics.get(), theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
  399. Graphics_setWindow (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
  400. integer x1DC, y1DC, x2DC, y2DC;
  401. Graphics_WCtoDC (my graphics.get(), 0.0, 0.0, & x1DC, & y2DC);
  402. Graphics_WCtoDC (my graphics.get(), 1.0, 1.0, & x2DC, & y1DC);
  403. Graphics_resetWsViewport (my graphics.get(), x1DC, x2DC, y1DC, y2DC);
  404. Graphics_setWsWindow (my graphics.get(), 0, width_inches, 0, height_inches);
  405. theCurrentPraatPicture -> x1NDC = 0.0;
  406. theCurrentPraatPicture -> x2NDC = width_inches;
  407. theCurrentPraatPicture -> y1NDC = 0.0;
  408. theCurrentPraatPicture -> y2NDC = height_inches;
  409. Graphics_setViewport (my graphics.get(), theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
  410. {// scope
  411. autoMelderProgressOff progress;
  412. autoMelderWarningOff warning;
  413. autoMelderSaveDefaultDir saveDir;
  414. if (! MelderDir_isNull (& my rootDirectory)) {
  415. Melder_setDefaultDir (& my rootDirectory);
  416. }
  417. try {
  418. Interpreter_run (interpreter.get(), text.get());
  419. } catch (MelderError) {
  420. if (my scriptErrorHasBeenNotified) {
  421. Melder_clearError ();
  422. } else {
  423. Melder_flushError ();
  424. my scriptErrorHasBeenNotified = true;
  425. }
  426. }
  427. }
  428. Graphics_setLineType (my graphics.get(), Graphics_DRAWN);
  429. Graphics_setLineWidth (my graphics.get(), 1.0);
  430. Graphics_setArrowSize (my graphics.get(), 1.0);
  431. Graphics_setSpeckleSize (my graphics.get(), 1.0);
  432. Graphics_setColour (my graphics.get(), Graphics_BLACK);
  433. /*Graphics_Link *paragraphLinks;
  434. integer numberOfParagraphLinks = Graphics_getLinks (& paragraphLinks);
  435. if (my links) for (integer ilink = 1; ilink <= numberOfParagraphLinks; ilink ++) {
  436. autoHyperLink link = HyperLink_create (paragraphLinks [ilink]. name,
  437. paragraphLinks [ilink]. x1, paragraphLinks [ilink]. x2,
  438. paragraphLinks [ilink]. y1, paragraphLinks [ilink]. y2);
  439. my links -> addItem_move (link.move());
  440. }*/
  441. theCurrentPraatApplication = & theForegroundPraatApplication;
  442. theCurrentPraatObjects = & theForegroundPraatObjects;
  443. theCurrentPraatPicture = & theForegroundPraatPicture;
  444. }
  445. Graphics_resetWsViewport (my graphics.get(), x1DCold, x2DCold, y1DCold, y2DCold);
  446. Graphics_setWsWindow (my graphics.get(), x1NDCold, x2NDCold, y1NDCold, y2NDCold);
  447. Graphics_setViewport (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
  448. Graphics_setWindow (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
  449. Graphics_setTextAlignment (my graphics.get(), Graphics_LEFT, Graphics_BOTTOM);
  450. }
  451. } else {
  452. Graphics_setFont (my ps, font);
  453. Graphics_setFontStyle (my ps, 0);
  454. Graphics_setFontSize (my ps, size);
  455. my d_y -= my d_y == PAPER_TOP - TOP_MARGIN ? 0 : ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
  456. my d_y -= true_height_inches;
  457. if (my d_y < PAPER_BOTTOM + BOTTOM_MARGIN + minFooterDistance) {
  458. Graphics_nextSheetOfPaper (my ps);
  459. if (my d_printingPageNumber) my d_printingPageNumber ++;
  460. HyperPage_initSheetOfPaper (me);
  461. Graphics_setFont (my ps, font);
  462. Graphics_setFontSize (my ps, size);
  463. my d_y -= true_height_inches;
  464. }
  465. my d_x = 3.7 - 0.5 * true_width_inches;
  466. if (my d_x < 0) my d_x = 0;
  467. Graphics_setWrapWidth (my ps, 0);
  468. integer x1DCold, x2DCold, y1DCold, y2DCold;
  469. Graphics_inqWsViewport (my ps, & x1DCold, & x2DCold, & y1DCold, & y2DCold);
  470. double x1NDCold, x2NDCold, y1NDCold, y2NDCold;
  471. Graphics_inqWsWindow (my ps, & x1NDCold, & x2NDCold, & y1NDCold, & y2NDCold);
  472. {
  473. if (! my praatApplication) my praatApplication = Melder_calloc_f (structPraatApplication, 1);
  474. if (! my praatObjects) my praatObjects = Melder_calloc_f (structPraatObjects, 1);
  475. if (! my praatPicture) my praatPicture = Melder_calloc_f (structPraatPicture, 1);
  476. theCurrentPraatApplication = (PraatApplication) my praatApplication;
  477. theCurrentPraatApplication -> batch = true;
  478. theCurrentPraatApplication -> topShell = theForegroundPraatApplication. topShell; // needed for UiForm_create () in dialogs
  479. theCurrentPraatObjects = (PraatObjects) my praatObjects;
  480. theCurrentPraatPicture = (PraatPicture) my praatPicture;
  481. theCurrentPraatPicture -> graphics = my ps;
  482. theCurrentPraatPicture -> font = (int) font;
  483. theCurrentPraatPicture -> fontSize = size;
  484. theCurrentPraatPicture -> lineType = Graphics_DRAWN;
  485. theCurrentPraatPicture -> colour = Graphics_BLACK;
  486. theCurrentPraatPicture -> lineWidth = 1.0;
  487. theCurrentPraatPicture -> arrowSize = 1.0;
  488. theCurrentPraatPicture -> speckleSize = 1.0;
  489. theCurrentPraatPicture -> x1NDC = my d_x;
  490. theCurrentPraatPicture -> x2NDC = my d_x + true_width_inches;
  491. theCurrentPraatPicture -> y1NDC = my d_y;
  492. theCurrentPraatPicture -> y2NDC = my d_y + true_height_inches;
  493. Graphics_setViewport (my ps, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
  494. Graphics_setWindow (my ps, 0.0, 1.0, 0.0, 1.0);
  495. integer x1DC, y1DC, x2DC, y2DC;
  496. Graphics_WCtoDC (my ps, 0.0, 0.0, & x1DC, & y2DC);
  497. Graphics_WCtoDC (my ps, 1.0, 1.0, & x2DC, & y1DC);
  498. integer shift = (integer) (Graphics_getResolution (my ps) * true_height_inches) + (y1DCold - y2DCold);
  499. #if cocoa
  500. shift = 0; // this is a FIX
  501. #endif
  502. Graphics_resetWsViewport (my ps, x1DC, x2DC, y1DC + shift, y2DC + shift);
  503. Graphics_setWsWindow (my ps, 0, width_inches, 0, height_inches);
  504. theCurrentPraatPicture -> x1NDC = 0;
  505. theCurrentPraatPicture -> x2NDC = width_inches;
  506. theCurrentPraatPicture -> y1NDC = 0;
  507. theCurrentPraatPicture -> y2NDC = height_inches;
  508. Graphics_setViewport (my ps, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
  509. {// scope
  510. autoMelderProgressOff progress;
  511. autoMelderWarningOff warning;
  512. autoMelderSaveDefaultDir saveDir;
  513. if (! MelderDir_isNull (& my rootDirectory)) {
  514. Melder_setDefaultDir (& my rootDirectory);
  515. }
  516. try {
  517. Interpreter_run (interpreter.get(), text.get());
  518. } catch (MelderError) {
  519. Melder_clearError ();
  520. }
  521. }
  522. Graphics_setLineType (my ps, Graphics_DRAWN);
  523. Graphics_setLineWidth (my ps, 1.0);
  524. Graphics_setArrowSize (my ps, 1.0);
  525. Graphics_setSpeckleSize (my ps, 1.0);
  526. Graphics_setColour (my ps, Graphics_BLACK);
  527. theCurrentPraatApplication = & theForegroundPraatApplication;
  528. theCurrentPraatObjects = & theForegroundPraatObjects;
  529. theCurrentPraatPicture = & theForegroundPraatPicture;
  530. }
  531. Graphics_resetWsViewport (my ps, x1DCold, x2DCold, y1DCold, y2DCold);
  532. Graphics_setWsWindow (my ps, x1NDCold, x2NDCold, y1NDCold, y2NDCold);
  533. Graphics_setViewport (my ps, 0, 1, 0, 1);
  534. Graphics_setWindow (my ps, 0, 1, 0, 1);
  535. Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
  536. }
  537. my previousBottomSpacing = bottomSpacing;
  538. }
  539. static void print (void *void_me, Graphics graphics) {
  540. iam (HyperPage);
  541. my ps = graphics;
  542. Graphics_setDollarSignIsCode (graphics, true);
  543. Graphics_setAtSignIsLink (graphics, true);
  544. my printing = true;
  545. HyperPage_initSheetOfPaper (me);
  546. my v_draw ();
  547. my printing = false;
  548. }
  549. /********** class HyperPage **********/
  550. void structHyperPage :: v_destroy () noexcept {
  551. if (our praatApplication) {
  552. for (int iobject = ((PraatObjects) our praatObjects) -> n; iobject >= 1; iobject --) {
  553. ((PraatObjects) our praatObjects) -> list [iobject]. name. reset();
  554. forget (((PraatObjects) our praatObjects) -> list [iobject]. object);
  555. }
  556. Melder_free (our praatApplication);
  557. Melder_free (our praatObjects);
  558. Melder_free (our praatPicture);
  559. }
  560. our HyperPage_Parent :: v_destroy ();
  561. }
  562. static void gui_drawingarea_cb_expose (HyperPage me, GuiDrawingArea_ExposeEvent /* event */) {
  563. if (! my graphics) return; // could be the case in the very beginning
  564. Graphics_clearWs (my graphics.get());
  565. initScreen (me);
  566. trace (U"going to draw");
  567. my v_draw ();
  568. if (my entryHint && my entryPosition != 0.0) {
  569. my entryHint. reset();
  570. my top = (int) floor (5.0 * (PAGE_HEIGHT - my entryPosition));
  571. if (my top < 0) my top = 0;
  572. Graphics_clearWs (my graphics.get());
  573. initScreen (me);
  574. my v_draw ();
  575. updateVerticalScrollBar (me);
  576. }
  577. }
  578. static void gui_drawingarea_cb_click (HyperPage me, GuiDrawingArea_ClickEvent event) {
  579. if (! my graphics) return; // could be the case in the very beginning
  580. for (integer ilink = 1; ilink <= my links.size; ilink ++) {
  581. HyperLink link = my links.at [ilink];
  582. if (! link)
  583. Melder_fatal (U"gui_drawingarea_cb_click: empty link ", ilink, U"/", my links.size, U".");
  584. if (event -> y > link -> y2DC && event -> y < link -> y1DC && event -> x > link -> x1DC && event -> x < link -> x2DC) {
  585. saveHistory (me, my currentPageTitle.get());
  586. try {
  587. HyperPage_goToPage (me, link -> name.get());
  588. } catch (MelderError) {
  589. Melder_flushError ();
  590. }
  591. return;
  592. }
  593. }
  594. }
  595. extern "C" void GRAPHICS_PostScript_settings (UiForm sendingForm, int narg, Stackel args, conststring32 sendingString, Interpreter interpreter, conststring32 invokingButtonTitle, bool modified, void *buttonClosure);
  596. static void menu_cb_postScriptSettings (HyperPage me, EDITOR_ARGS_FORM) {
  597. (void) me;
  598. (void) cmd;
  599. GRAPHICS_PostScript_settings (_sendingForm_, _narg_, _args_, _sendingString_, interpreter, nullptr, false, nullptr);
  600. }
  601. #ifdef macintosh
  602. static void menu_cb_pageSetup (HyperPage me, EDITOR_ARGS_DIRECT) {
  603. (void) me;
  604. Printer_pageSetup ();
  605. }
  606. #endif
  607. static void menu_cb_print (HyperPage me, EDITOR_ARGS_FORM) {
  608. EDITOR_FORM (U"Print", nullptr)
  609. SENTENCE_FIELD (my insideHeader, U"Left or inside header", U"")
  610. SENTENCE_FIELD (my middleHeader, U"Middle header", U"")
  611. TEXTFIELD_FIELD (my outsideHeader, U"Right or outside header", U"")
  612. SENTENCE_FIELD (my insideFooter, U"Left or inside footer", U"")
  613. SENTENCE_FIELD (my middleFooter, U"Middle footer", U"")
  614. SENTENCE_FIELD (my outsideFooter, U"Right or outside footer", U"")
  615. BOOLEAN_FIELD (my mirror, U"Mirror even/odd headers", true)
  616. INTEGER_FIELD (my d_printingPageNumber, U"First page number", U"0 (= no page numbers)")
  617. EDITOR_OK
  618. my v_defaultHeaders (cmd);
  619. if (my d_printingPageNumber != 0) SET_INTEGER (my d_printingPageNumber, my d_printingPageNumber + 1)
  620. EDITOR_DO
  621. Printer_print (print, me);
  622. EDITOR_END
  623. }
  624. static void menu_cb_font (HyperPage me, EDITOR_ARGS_FORM) {
  625. EDITOR_FORM (U"Font", nullptr)
  626. RADIO (font, U"Font", 1)
  627. RADIOBUTTON (U"Times")
  628. RADIOBUTTON (U"Helvetica")
  629. EDITOR_OK
  630. SET_OPTION (font, my p_font == kGraphics_font::TIMES ? 1 :
  631. my p_font == kGraphics_font::HELVETICA ? 2 : my p_font == kGraphics_font::PALATINO ? 3 : 1);
  632. EDITOR_DO
  633. my pref_font () = my p_font = font == 1 ? kGraphics_font::TIMES : kGraphics_font::HELVETICA;
  634. if (my graphics) Graphics_updateWs (my graphics.get());
  635. EDITOR_END
  636. }
  637. static void updateSizeMenu (HyperPage me) {
  638. GuiMenuItem_check (my fontSizeButton_10, my p_fontSize == 10);
  639. GuiMenuItem_check (my fontSizeButton_12, my p_fontSize == 12);
  640. GuiMenuItem_check (my fontSizeButton_14, my p_fontSize == 14);
  641. GuiMenuItem_check (my fontSizeButton_18, my p_fontSize == 18);
  642. GuiMenuItem_check (my fontSizeButton_24, my p_fontSize == 24);
  643. }
  644. static void setFontSize (HyperPage me, int fontSize) {
  645. my pref_fontSize () = my p_fontSize = fontSize;
  646. if (my graphics) Graphics_updateWs (my graphics.get());
  647. updateSizeMenu (me);
  648. }
  649. static void menu_cb_10 (HyperPage me, EDITOR_ARGS_DIRECT) { setFontSize (me, 10); }
  650. static void menu_cb_12 (HyperPage me, EDITOR_ARGS_DIRECT) { setFontSize (me, 12); }
  651. static void menu_cb_14 (HyperPage me, EDITOR_ARGS_DIRECT) { setFontSize (me, 14); }
  652. static void menu_cb_18 (HyperPage me, EDITOR_ARGS_DIRECT) { setFontSize (me, 18); }
  653. static void menu_cb_24 (HyperPage me, EDITOR_ARGS_DIRECT) { setFontSize (me, 24); }
  654. static void menu_cb_fontSize (HyperPage me, EDITOR_ARGS_FORM) {
  655. EDITOR_FORM (U"Font size", nullptr)
  656. NATURAL (fontSize, U"Font size (points)", my default_fontSize ())
  657. EDITOR_OK
  658. SET_INTEGER (fontSize, my p_fontSize)
  659. EDITOR_DO
  660. setFontSize (me, fontSize);
  661. EDITOR_END
  662. }
  663. static void menu_cb_searchForPage (HyperPage me, EDITOR_ARGS_FORM) {
  664. EDITOR_FORM (U"Search for page", nullptr)
  665. TEXTFIELD (page, U"Page:", U"a")
  666. EDITOR_OK
  667. EDITOR_DO
  668. HyperPage_goToPage (me, page);
  669. EDITOR_END
  670. }
  671. /********************************************************************************
  672. *
  673. * The vertical scroll bar controls and/or mirrors
  674. * the position of the viewable area within the page.
  675. * A page can be PAGE_HEIGHT inches high, so 'my top' (and the scroll-bar 'value')
  676. * may take on values between 0 and PAGE_HEIGHT * 5 (fifth inches).
  677. * Hence, the 'minimum' is 0.
  678. * The viewable area shows a certain number of fifth inches;
  679. * hence the 'sliderSize' is height / resolution * 5,
  680. * and the 'maximum' is PAGE_HEIGHT * 5.
  681. * The 'increment' is 1, so the arrows move the page by one fifth of an inch.
  682. * The 'pageIncrement' is sliderSize - 1.
  683. */
  684. static void gui_cb_verticalScroll (HyperPage me, GuiScrollBarEvent event) {
  685. double value = GuiScrollBar_getValue (event -> scrollBar);
  686. if (value != my top) {
  687. trace (U"scroll from ", my top, U" to ", value);
  688. my top = (int) floor (value);
  689. #if cocoa || gtk || motif
  690. Graphics_updateWs (my graphics.get()); // wait for expose event
  691. #else
  692. initScreen (me);
  693. Graphics_clearWs (my graphics.get());
  694. my v_draw (); // do not wait for expose event
  695. #endif
  696. updateVerticalScrollBar (me);
  697. }
  698. }
  699. static void createVerticalScrollBar (HyperPage me, GuiForm parent) {
  700. int height = Machine_getTextHeight ();
  701. my verticalScrollBar = GuiScrollBar_createShown (parent,
  702. - Machine_getScrollBarWidth (), 0,
  703. Machine_getMenuBarHeight () + (my d_hasExtraRowOfTools ? 2 * height + 19 : height + 12), - Machine_getScrollBarWidth (),
  704. 0, PAGE_HEIGHT * 5, 0, 25, 1, 24,
  705. gui_cb_verticalScroll, me, 0);
  706. }
  707. static void updateVerticalScrollBar (HyperPage me)
  708. /* We cannot call this immediately after creation. */
  709. /* This has to be called after changing 'my topParagraph'. */
  710. {
  711. int sliderSize = 25;
  712. GuiScrollBar_set (my verticalScrollBar, undefined, undefined, my top, sliderSize, 1, sliderSize - 1);
  713. my history [my historyPointer]. top = 0/*my top*/;
  714. }
  715. static void menu_cb_pageUp (HyperPage me, EDITOR_ARGS_DIRECT) {
  716. if (! my verticalScrollBar) return;
  717. int value = GuiScrollBar_getValue (my verticalScrollBar) - 24;
  718. if (value < 0) value = 0;
  719. if (value != my top) {
  720. my top = value;
  721. Graphics_clearWs (my graphics.get());
  722. initScreen (me);
  723. my v_draw (); // do not wait for expose event
  724. updateVerticalScrollBar (me);
  725. }
  726. }
  727. static void menu_cb_pageDown (HyperPage me, EDITOR_ARGS_DIRECT) {
  728. if (! my verticalScrollBar) return;
  729. int value = GuiScrollBar_getValue (my verticalScrollBar) + 24;
  730. if (value > (int) (PAGE_HEIGHT * 5) - 25) value = (int) (PAGE_HEIGHT * 5) - 25;
  731. if (value != my top) {
  732. my top = value;
  733. Graphics_clearWs (my graphics.get());
  734. initScreen (me);
  735. my v_draw (); // do not wait for expose event
  736. updateVerticalScrollBar (me);
  737. }
  738. }
  739. /********** **********/
  740. static void do_back (HyperPage me) {
  741. if (my historyPointer <= 0) return;
  742. autostring32 page = Melder_dup_f (my history [-- my historyPointer]. page.get()); // temporary, because pointer will be moved
  743. int top = my history [my historyPointer]. top;
  744. if (my v_goToPage (page.get())) {
  745. my top = top;
  746. HyperPage_clear (me);
  747. updateVerticalScrollBar (me);
  748. }
  749. }
  750. static void menu_cb_back (HyperPage me, EDITOR_ARGS_DIRECT) {
  751. do_back (me);
  752. }
  753. static void gui_button_cb_back (HyperPage me, GuiButtonEvent /* event */) {
  754. do_back (me);
  755. }
  756. static void do_forth (HyperPage me) {
  757. if (my historyPointer >= 19 || ! my history [my historyPointer + 1]. page) return;
  758. autostring32 page = Melder_dup_f (my history [++ my historyPointer]. page.get());
  759. int top = my history [my historyPointer]. top;
  760. if (my v_goToPage (page.get())) {
  761. my top = top;
  762. HyperPage_clear (me);
  763. updateVerticalScrollBar (me);
  764. }
  765. }
  766. static void menu_cb_forth (HyperPage me, EDITOR_ARGS_DIRECT) {
  767. do_forth (me);
  768. }
  769. static void gui_button_cb_forth (HyperPage me, GuiButtonEvent /* event */) {
  770. do_forth (me);
  771. }
  772. void structHyperPage :: v_createMenus () {
  773. HyperPage_Parent :: v_createMenus ();
  774. Editor_addCommand (this, U"File", U"PostScript settings...", 0, menu_cb_postScriptSettings);
  775. #ifdef macintosh
  776. Editor_addCommand (this, U"File", U"Page setup...", 0, menu_cb_pageSetup);
  777. #endif
  778. Editor_addCommand (this, U"File", U"Print page...", 'P', menu_cb_print);
  779. Editor_addCommand (this, U"File", U"-- close --", 0, nullptr);
  780. if (our v_hasHistory ()) {
  781. Editor_addMenu (this, U"Go to", 0);
  782. Editor_addCommand (this, U"Go to", U"Search for page...", 0, menu_cb_searchForPage);
  783. Editor_addCommand (this, U"Go to", U"Back", GuiMenu_OPTION | GuiMenu_LEFT_ARROW, menu_cb_back);
  784. Editor_addCommand (this, U"Go to", U"Forward", GuiMenu_OPTION | GuiMenu_RIGHT_ARROW, menu_cb_forth);
  785. Editor_addCommand (this, U"Go to", U"-- page --", 0, nullptr);
  786. Editor_addCommand (this, U"Go to", U"Page up", GuiMenu_PAGE_UP, menu_cb_pageUp);
  787. Editor_addCommand (this, U"Go to", U"Page down", GuiMenu_PAGE_DOWN, menu_cb_pageDown);
  788. }
  789. Editor_addMenu (this, U"Font", 0);
  790. Editor_addCommand (this, U"Font", U"Font size...", 0, menu_cb_fontSize);
  791. fontSizeButton_10 = Editor_addCommand (this, U"Font", U"10", GuiMenu_CHECKBUTTON, menu_cb_10);
  792. fontSizeButton_12 = Editor_addCommand (this, U"Font", U"12", GuiMenu_CHECKBUTTON, menu_cb_12);
  793. fontSizeButton_14 = Editor_addCommand (this, U"Font", U"14", GuiMenu_CHECKBUTTON, menu_cb_14);
  794. fontSizeButton_18 = Editor_addCommand (this, U"Font", U"18", GuiMenu_CHECKBUTTON, menu_cb_18);
  795. fontSizeButton_24 = Editor_addCommand (this, U"Font", U"24", GuiMenu_CHECKBUTTON, menu_cb_24);
  796. Editor_addCommand (this, U"Font", U"-- font --", 0, nullptr);
  797. Editor_addCommand (this, U"Font", U"Font...", 0, menu_cb_font);
  798. }
  799. /********** **********/
  800. static void gui_drawingarea_cb_resize (HyperPage me, GuiDrawingArea_ResizeEvent event) {
  801. if (! my graphics) return;
  802. Graphics_setWsViewport (my graphics.get(), 0.0, event -> width, 0.0, event -> height);
  803. Graphics_setWsWindow (my graphics.get(), 0.0, my rightMargin = event -> width / resolution,
  804. PAGE_HEIGHT - event -> height / resolution, PAGE_HEIGHT);
  805. Graphics_updateWs (my graphics.get());
  806. updateVerticalScrollBar (me);
  807. }
  808. static void gui_button_cb_previousPage (HyperPage me, GuiButtonEvent /* event */) {
  809. HyperPage_goToPage_i (me, my v_getCurrentPageNumber () > 1 ?
  810. my v_getCurrentPageNumber () - 1 : my v_getNumberOfPages ());
  811. }
  812. static void gui_button_cb_nextPage (HyperPage me, GuiButtonEvent /* event */) {
  813. integer currentPageNumber = my v_getCurrentPageNumber ();
  814. HyperPage_goToPage_i (me, currentPageNumber < my v_getNumberOfPages () ? currentPageNumber + 1 : 1);
  815. }
  816. void structHyperPage :: v_createChildren () {
  817. int height = Machine_getTextHeight ();
  818. int y = Machine_getMenuBarHeight () + 4;
  819. /***** Create navigation buttons. *****/
  820. if (our v_hasHistory ()) {
  821. GuiButton_createShown (our windowForm, 4, 48, y, y + height,
  822. U"<", gui_button_cb_back, this, 0);
  823. GuiButton_createShown (our windowForm, 54, 98, y, y + height,
  824. U">", gui_button_cb_forth, this, 0);
  825. }
  826. if (our v_isOrdered ()) {
  827. GuiButton_createShown (our windowForm, 174, 218, y, y + height,
  828. U"< 1", gui_button_cb_previousPage, this, 0);
  829. GuiButton_createShown (our windowForm, 224, 268, y, y + height,
  830. U"1 >", gui_button_cb_nextPage, this, 0);
  831. }
  832. /***** Create scroll bar. *****/
  833. createVerticalScrollBar (this, our windowForm);
  834. /***** Create drawing area. *****/
  835. drawingArea = GuiDrawingArea_createShown (our windowForm,
  836. 0, - Machine_getScrollBarWidth (),
  837. y + ( our d_hasExtraRowOfTools ? 2 * height + 16 : height + 9 ), - Machine_getScrollBarWidth (),
  838. gui_drawingarea_cb_expose, gui_drawingarea_cb_click, nullptr, gui_drawingarea_cb_resize, this, GuiDrawingArea_BORDER);
  839. GuiDrawingArea_setSwipable (drawingArea, nullptr, our verticalScrollBar);
  840. }
  841. void HyperPage_init (HyperPage me, conststring32 title, Daata data) {
  842. resolution = Gui_getResolution (nullptr);
  843. Editor_init (me, 0, 0, (int) floor (6 * resolution + 30), 800, title, data);
  844. #if motif
  845. Melder_assert (XtWindow (my drawingArea -> d_widget));
  846. #endif
  847. my graphics = Graphics_create_xmdrawingarea (my drawingArea);
  848. Graphics_setAtSignIsLink (my graphics.get(), true);
  849. Graphics_setDollarSignIsCode (my graphics.get(), true);
  850. Graphics_setFont (my graphics.get(), kGraphics_font::TIMES);
  851. if (my p_font != kGraphics_font::TIMES && my p_font != kGraphics_font::HELVETICA)
  852. my pref_font () = my p_font = kGraphics_font::TIMES; // ensure Unicode compatibility
  853. setFontSize (me, my p_fontSize);
  854. struct structGuiDrawingArea_ResizeEvent event { my drawingArea, 0, 0 };
  855. event. width = GuiControl_getWidth (my drawingArea);
  856. event. height = GuiControl_getHeight (my drawingArea);
  857. gui_drawingarea_cb_resize (me, & event);
  858. updateVerticalScrollBar (me); // scroll to the top (my top == 0)
  859. }
  860. void HyperPage_clear (HyperPage me) {
  861. Graphics_updateWs (my graphics.get());
  862. my links. removeAllItems();
  863. }
  864. void structHyperPage :: v_dataChanged () {
  865. bool oldError = Melder_hasError (); // this method can be called during error time
  866. (void) our v_goToPage (our currentPageTitle.get());
  867. if (Melder_hasError () && ! oldError) Melder_flushError ();
  868. HyperPage_clear (this);
  869. updateVerticalScrollBar (this);
  870. }
  871. int HyperPage_goToPage (HyperPage me, conststring32 title) {
  872. switch (my v_goToPage (title)) {
  873. case -1: return 0;
  874. case 0: HyperPage_clear (me); return 0;
  875. }
  876. saveHistory (me, title); // last chance: HyperPage_clear will destroy "title" !!!
  877. my currentPageTitle = Melder_dup_f (title);
  878. my top = 0;
  879. HyperPage_clear (me);
  880. updateVerticalScrollBar (me); // scroll to the top (my top == 0)
  881. return 1;
  882. }
  883. void HyperPage_goToPage_i (HyperPage me, integer i) {
  884. my v_goToPage_i (i); // catch -> HyperPage_clear (me); ?
  885. my top = 0;
  886. HyperPage_clear (me);
  887. updateVerticalScrollBar (me); // scroll to the top (my top == 0)
  888. }
  889. void HyperPage_setEntryHint (HyperPage me, conststring32 hint) {
  890. my entryHint = Melder_dup_f (hint);
  891. }
  892. /* End of file HyperPage.cpp */