Editor.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /* Editor.cpp
  2. *
  3. * Copyright (C) 1992-2018 Paul Boersma, 2008 Stefan de Konink, 2010 Franz Brausse
  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 <time.h>
  19. #include "ScriptEditor.h"
  20. #include "machine.h"
  21. #include "EditorM.h"
  22. #include "praat_script.h"
  23. #include "sendsocket.h"
  24. #include "enums_getText.h"
  25. #include "Editor_enums.h"
  26. #include "enums_getValue.h"
  27. #include "Editor_enums.h"
  28. Thing_implement (Editor, Thing, 0);
  29. #include "prefs_define.h"
  30. #include "Editor_prefs.h"
  31. #include "prefs_install.h"
  32. #include "Editor_prefs.h"
  33. #include "prefs_copyToInstance.h"
  34. #include "Editor_prefs.h"
  35. /********** class EditorCommand **********/
  36. Thing_implement (EditorCommand, Thing, 0);
  37. /********** class EditorMenu **********/
  38. Thing_implement (EditorMenu, Thing, 0);
  39. /********** functions **********/
  40. static void commonCallback (EditorCommand me, GuiMenuItemEvent /* event */) {
  41. if (my d_editor && my d_editor -> v_scriptable () && ! str32str (my itemTitle.get(), U"...")) {
  42. UiHistory_write (U"\n");
  43. UiHistory_write_colonize (my itemTitle.get());
  44. }
  45. try {
  46. my commandCallback (my d_editor, me, nullptr, 0, nullptr, nullptr, nullptr);
  47. } catch (MelderError) {
  48. if (! Melder_hasError (U"Script exited.")) {
  49. Melder_appendError (U"Menu command \"", my itemTitle.get(), U"\" not completed.");
  50. }
  51. Melder_flushError ();
  52. }
  53. }
  54. GuiMenuItem EditorMenu_addCommand (EditorMenu me, conststring32 itemTitle /* cattable */, uint32 flags, EditorCommandCallback commandCallback)
  55. {
  56. autoEditorCommand thee = Thing_new (EditorCommand);
  57. thy d_editor = my d_editor;
  58. thy menu = me;
  59. thy itemTitle = Melder_dup (itemTitle);
  60. thy itemWidget =
  61. ! commandCallback ? GuiMenu_addSeparator (my menuWidget) :
  62. flags & Editor_HIDDEN ? nullptr :
  63. GuiMenu_addItem (my menuWidget, itemTitle, flags, commonCallback, thee.get()); // DANGLE BUG: me can be killed by Collection_addItem(), but EditorCommand::destroy doesn't remove the item
  64. thy commandCallback = commandCallback;
  65. GuiMenuItem result = thy itemWidget;
  66. my commands. addItem_move (thee.move());
  67. return result;
  68. }
  69. /*GuiObject EditorCommand_getItemWidget (EditorCommand me) { return my itemWidget; }*/
  70. EditorMenu Editor_addMenu (Editor me, conststring32 menuTitle, uint32 flags) {
  71. autoEditorMenu thee = Thing_new (EditorMenu);
  72. thy d_editor = me;
  73. thy menuTitle = Melder_dup (menuTitle);
  74. thy menuWidget = GuiMenu_createInWindow (my windowForm, menuTitle, flags);
  75. return my menus. addItem_move (thee.move());
  76. }
  77. /*GuiObject EditorMenu_getMenuWidget (EditorMenu me) { return my menuWidget; }*/
  78. GuiMenuItem Editor_addCommand (Editor me, conststring32 menuTitle, conststring32 itemTitle, uint32 flags, EditorCommandCallback commandCallback)
  79. {
  80. try {
  81. integer numberOfMenus = my menus.size;
  82. for (integer imenu = 1; imenu <= numberOfMenus; imenu ++) {
  83. EditorMenu menu = my menus.at [imenu];
  84. if (str32equ (menuTitle, menu -> menuTitle.get()))
  85. return EditorMenu_addCommand (menu, itemTitle, flags, commandCallback);
  86. }
  87. Melder_throw (U"Menu \"", menuTitle, U"\" does not exist.");
  88. } catch (MelderError) {
  89. Melder_throw (U"Command \"", itemTitle, U"\" not inserted in menu \"", menuTitle, U".");
  90. }
  91. }
  92. static void Editor_scriptCallback (Editor me, EditorCommand cmd, UiForm /* sendingForm */,
  93. integer /* narg */, Stackel /* args */, conststring32 /* sendingString */, Interpreter /* interpreter */)
  94. {
  95. DO_RunTheScriptFromAnyAddedEditorCommand (me, cmd -> script.get());
  96. }
  97. GuiMenuItem Editor_addCommandScript (Editor me, conststring32 menuTitle, conststring32 itemTitle, uint32 flags,
  98. conststring32 script)
  99. {
  100. integer numberOfMenus = my menus.size;
  101. for (integer imenu = 1; imenu <= numberOfMenus; imenu ++) {
  102. EditorMenu menu = my menus.at [imenu];
  103. if (str32equ (menuTitle, menu -> menuTitle.get())) {
  104. autoEditorCommand cmd = Thing_new (EditorCommand);
  105. cmd -> d_editor = me;
  106. cmd -> menu = menu;
  107. cmd -> itemTitle = Melder_dup (itemTitle);
  108. cmd -> itemWidget = script == nullptr ? GuiMenu_addSeparator (menu -> menuWidget) :
  109. GuiMenu_addItem (menu -> menuWidget, itemTitle, flags, commonCallback, cmd.get()); // DANGLE BUG
  110. cmd -> commandCallback = Editor_scriptCallback;
  111. if (script [0] == U'\0') {
  112. cmd -> script = Melder_dup (U"");
  113. } else {
  114. structMelderFile file { };
  115. Melder_relativePathToFile (script, & file);
  116. cmd -> script = Melder_dup (Melder_fileToPath (& file));
  117. }
  118. GuiMenuItem result = cmd -> itemWidget;
  119. menu -> commands. addItem_move (cmd.move());
  120. return result;
  121. }
  122. }
  123. Melder_warning (
  124. U"Menu \"", menuTitle, U"\" does not exist.\n"
  125. U"Command \"", itemTitle, U"\" not inserted in menu \"", menuTitle, U".\n"
  126. U"To fix this, go to Praat->Preferences->Buttons->Editors, and remove the script from this menu.\n"
  127. U"You may want to install the script in a different menu.");
  128. return nullptr;
  129. }
  130. void Editor_setMenuSensitive (Editor me, conststring32 menuTitle, bool sensitive) {
  131. integer numberOfMenus = my menus.size;
  132. for (integer imenu = 1; imenu <= numberOfMenus; imenu ++) {
  133. EditorMenu menu = my menus.at [imenu];
  134. if (str32equ (menuTitle, menu -> menuTitle.get())) {
  135. GuiThing_setSensitive (menu -> menuWidget, sensitive);
  136. return;
  137. }
  138. }
  139. }
  140. EditorCommand Editor_getMenuCommand (Editor me, conststring32 menuTitle, conststring32 itemTitle) {
  141. integer numberOfMenus = my menus.size;
  142. for (int imenu = 1; imenu <= numberOfMenus; imenu ++) {
  143. EditorMenu menu = my menus.at [imenu];
  144. if (str32equ (menuTitle, menu -> menuTitle.get())) {
  145. integer numberOfCommands = menu -> commands.size, icommand;
  146. for (icommand = 1; icommand <= numberOfCommands; icommand ++) {
  147. EditorCommand command = menu -> commands.at [icommand];
  148. if (str32equ (itemTitle, command -> itemTitle.get()))
  149. return command;
  150. }
  151. }
  152. }
  153. Melder_throw (U"Command \"", itemTitle, U"\" not found in menu \"", menuTitle, U"\".");
  154. }
  155. void Editor_doMenuCommand (Editor me, conststring32 commandTitle, integer narg, Stackel args, conststring32 arguments, Interpreter interpreter) {
  156. integer numberOfMenus = my menus.size;
  157. for (int imenu = 1; imenu <= numberOfMenus; imenu ++) {
  158. EditorMenu menu = my menus.at [imenu];
  159. integer numberOfCommands = menu -> commands.size;
  160. for (integer icommand = 1; icommand <= numberOfCommands; icommand ++) {
  161. EditorCommand command = menu -> commands.at [icommand];
  162. if (str32equ (commandTitle, command -> itemTitle.get())) {
  163. command -> commandCallback (me, command, nullptr, narg, args, arguments, interpreter);
  164. return;
  165. }
  166. }
  167. }
  168. Melder_throw (U"Command not available in ", my classInfo -> className, U".");
  169. }
  170. /********** class Editor **********/
  171. void structEditor :: v_destroy () noexcept {
  172. trace (U"enter");
  173. MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
  174. /*
  175. * The following command must be performed before the shell is destroyed.
  176. * Otherwise, we would be forgetting dangling command dialogs here.
  177. */
  178. our menus.removeAllItems();
  179. Editor_broadcastDestruction (this);
  180. if (our windowForm) {
  181. #if gtk
  182. if (our windowForm -> d_gtkWindow) {
  183. Melder_assert (GTK_IS_WIDGET (our windowForm -> d_gtkWindow));
  184. gtk_widget_destroy (GTK_WIDGET (our windowForm -> d_gtkWindow));
  185. }
  186. #elif motif
  187. if (our windowForm -> d_xmShell) {
  188. XtDestroyWidget (our windowForm -> d_xmShell);
  189. }
  190. #elif cocoa
  191. if (our windowForm -> d_cocoaShell) {
  192. NSWindow *cocoaWindow = our windowForm -> d_cocoaShell;
  193. //our windowForm -> d_cocoaShell = nullptr;
  194. [cocoaWindow close];
  195. }
  196. #endif
  197. }
  198. if (our ownData) forget (our data);
  199. Melder_free (our callbackSocket);
  200. Editor_Parent :: v_destroy ();
  201. }
  202. void structEditor :: v_info () {
  203. MelderInfo_writeLine (U"Editor type: ", Thing_className (this));
  204. MelderInfo_writeLine (U"Editor name: ", our name ? our name.get() : U"<no name>");
  205. time_t today = time (nullptr);
  206. MelderInfo_writeLine (U"Date: ", Melder_peek8to32 (ctime (& today))); // includes a newline
  207. if (our data) {
  208. MelderInfo_writeLine (U"Data type: ", our data -> classInfo -> className);
  209. MelderInfo_writeLine (U"Data name: ", our data -> name.get());
  210. }
  211. }
  212. void structEditor :: v_nameChanged () {
  213. if (our name)
  214. GuiShell_setTitle (our windowForm, our name.get());
  215. }
  216. void structEditor :: v_saveData () {
  217. if (! our data) return;
  218. our previousData = Data_copy (our data);
  219. }
  220. void structEditor :: v_restoreData () {
  221. if (our data && our previousData)
  222. Thing_swap (our data, our previousData.get());
  223. }
  224. static void menu_cb_sendBackToCallingProgram (Editor me, EDITOR_ARGS_DIRECT) {
  225. if (my data) {
  226. extern structMelderDir praatDir;
  227. structMelderFile file { };
  228. MelderDir_getFile (& praatDir, U"praat_backToCaller.Data", & file);
  229. Data_writeToTextFile (my data, & file);
  230. sendsocket (my callbackSocket, Melder_peek32to8 (my data -> name.get()));
  231. }
  232. my v_goAway ();
  233. }
  234. static void menu_cb_close (Editor me, EDITOR_ARGS_DIRECT) {
  235. my v_goAway ();
  236. }
  237. static void menu_cb_undo (Editor me, EDITOR_ARGS_DIRECT) {
  238. my v_restoreData ();
  239. if (str32nequ (my undoText, U"Undo", 4)) my undoText [0] = U'R', my undoText [1] = U'e';
  240. else if (str32nequ (my undoText, U"Redo", 4)) my undoText [0] = U'U', my undoText [1] = U'n';
  241. else str32cpy (my undoText, U"Undo?");
  242. #if gtk
  243. gtk_label_set_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (my undoButton -> d_widget))), Melder_peek32to8 (my undoText));
  244. #elif motif
  245. conststring8 text_utf8 = Melder_peek32to8 (my undoText);
  246. XtVaSetValues (my undoButton -> d_widget, XmNlabelString, text_utf8, nullptr);
  247. #elif cocoa
  248. [(GuiCocoaMenuItem *) my undoButton -> d_widget setTitle: (NSString *) Melder_peek32toCfstring (my undoText)];
  249. #endif
  250. /*
  251. * Send a message to myself (e.g., I will redraw myself).
  252. */
  253. my v_dataChanged ();
  254. /*
  255. * Send a message to my boss (e.g., she will notify the others that depend on me).
  256. */
  257. Editor_broadcastDataChanged (me);
  258. }
  259. static void menu_cb_searchManual (Editor /* me */, EDITOR_ARGS_DIRECT) {
  260. Melder_search ();
  261. }
  262. static void menu_cb_newScript (Editor me, EDITOR_ARGS_DIRECT) {
  263. autoScriptEditor scriptEditor = ScriptEditor_createFromText (me, nullptr);
  264. scriptEditor.releaseToUser();
  265. }
  266. static void menu_cb_openScript (Editor me, EDITOR_ARGS_DIRECT) {
  267. autoScriptEditor scriptEditor = ScriptEditor_createFromText (me, nullptr);
  268. TextEditor_showOpen (scriptEditor.get());
  269. scriptEditor.releaseToUser();
  270. }
  271. void structEditor :: v_createMenuItems_file (EditorMenu /* menu */) {
  272. }
  273. void structEditor :: v_createMenuItems_edit (EditorMenu menu) {
  274. if (our data)
  275. our undoButton = EditorMenu_addCommand (menu, U"Cannot undo", GuiMenu_INSENSITIVE + 'Z', menu_cb_undo);
  276. }
  277. static void menu_cb_settingsReport (Editor me, EDITOR_ARGS_DIRECT) {
  278. Thing_info (me);
  279. }
  280. static void menu_cb_info (Editor me, EDITOR_ARGS_DIRECT) {
  281. if (my data) Thing_info (my data);
  282. }
  283. void structEditor :: v_createMenuItems_query (EditorMenu menu) {
  284. v_createMenuItems_query_info (menu);
  285. }
  286. void structEditor :: v_createMenuItems_query_info (EditorMenu menu) {
  287. EditorMenu_addCommand (menu, U"Editor info", 0, menu_cb_settingsReport);
  288. EditorMenu_addCommand (menu, U"Settings report", Editor_HIDDEN, menu_cb_settingsReport);
  289. if (data) {
  290. EditorMenu_addCommand (menu, Melder_cat (Thing_className (data), U" info"), 0, menu_cb_info);
  291. }
  292. }
  293. void structEditor :: v_createMenus () {
  294. EditorMenu menu = Editor_addMenu (this, U"File", 0);
  295. v_createMenuItems_file (menu);
  296. if (v_editable ()) {
  297. menu = Editor_addMenu (this, U"Edit", 0);
  298. v_createMenuItems_edit (menu);
  299. }
  300. if (v_hasQueryMenu ()) {
  301. menu = Editor_addMenu (this, U"Query", 0);
  302. v_createMenuItems_query (menu);
  303. }
  304. }
  305. BOOLEAN_VARIABLE (v_form_pictureWindow_eraseFirst)
  306. void structEditor :: v_form_pictureWindow (EditorCommand cmd) {
  307. LABEL (U"Picture window:")
  308. BOOLEAN_FIELD (v_form_pictureWindow_eraseFirst, U"Erase first", true)
  309. }
  310. void structEditor :: v_ok_pictureWindow (EditorCommand cmd) {
  311. SET_BOOLEAN (v_form_pictureWindow_eraseFirst, our pref_picture_eraseFirst ())
  312. }
  313. void structEditor :: v_do_pictureWindow (EditorCommand /* cmd */) {
  314. our pref_picture_eraseFirst () = v_form_pictureWindow_eraseFirst;
  315. }
  316. OPTIONMENU_ENUM_VARIABLE (kEditor_writeNameAtTop, v_form_pictureMargins_writeNameAtTop)
  317. void structEditor :: v_form_pictureMargins (EditorCommand cmd) {
  318. LABEL (U"Margins:")
  319. OPTIONMENU_ENUM_FIELD (kEditor_writeNameAtTop, v_form_pictureMargins_writeNameAtTop,
  320. U"Write name at top", kEditor_writeNameAtTop::DEFAULT)
  321. }
  322. void structEditor :: v_ok_pictureMargins (EditorCommand cmd) {
  323. SET_ENUM (v_form_pictureMargins_writeNameAtTop, kEditor_writeNameAtTop, pref_picture_writeNameAtTop ())
  324. }
  325. void structEditor :: v_do_pictureMargins (EditorCommand /* cmd */) {
  326. pref_picture_writeNameAtTop () = v_form_pictureMargins_writeNameAtTop;
  327. }
  328. static void gui_window_cb_goAway (Editor me) {
  329. Melder_assert (me);
  330. Melder_assert (Thing_isa (me, classEditor));
  331. my v_goAway ();
  332. }
  333. void praat_addCommandsToEditor (Editor me);
  334. void Editor_init (Editor me, int x, int y, int width, int height, conststring32 title, Daata data) {
  335. double xmin, ymin, widthmax, heightmax;
  336. Gui_getWindowPositioningBounds (& xmin, & ymin, & widthmax, & heightmax);
  337. /*
  338. * Negative widths are relative to the whole screen.
  339. */
  340. if (width < 0) width += (int) widthmax;
  341. if (height < 0) height += (int) heightmax;
  342. /*
  343. * Don't start with a maximized window, because then the user doesn't know what a click on the maximize button means.
  344. */
  345. if (width > (int) widthmax - 100) width = (int) widthmax - 100;
  346. if (height > (int) heightmax - 100) height = (int) heightmax - 100;
  347. /*
  348. * Make sure that the window has at least a sane size.
  349. * Just in case the user made the previous window very small (Praat's FunctionEditor saves the last size),
  350. * or the user edited the preferences file (which might save a window size).
  351. */
  352. if (width < 200) width = 200;
  353. if (height < 150) height = 150;
  354. /*
  355. * Now that the size is right, establish the position.
  356. */
  357. int left, right, top, bottom;
  358. if (x > 0) {
  359. /*
  360. * Positive x: relative to the left edge of the screen.
  361. */
  362. left = (int) xmin + x;
  363. right = left + width;
  364. } else if (x < 0) {
  365. /*
  366. * Negative x: relative to the right edge of the screen.
  367. */
  368. right = (int) xmin + (int) widthmax + x;
  369. left = right - width;
  370. } else {
  371. /*
  372. * Zero x: randomize between the left and right edge of the screen.
  373. */
  374. left = (int) NUMrandomInteger ((int) xmin + 4, (int) xmin + (int) widthmax - width - 4);
  375. right = left + width;
  376. }
  377. if (y > 0) {
  378. /*
  379. * Positive y: relative to the top of the screen.
  380. */
  381. top = (int) ymin + y;
  382. bottom = top + height;
  383. } else if (y < 0) {
  384. /*
  385. * Negative y: relative to the bottom of the screen.
  386. */
  387. bottom = (int) ymin + (int) heightmax + y;
  388. top = bottom - height;
  389. } else {
  390. /*
  391. * Zero y: randomize between the top and bottom of the screen.
  392. */
  393. top = (int) NUMrandomInteger ((int) ymin + 4, (int) ymin + (int) heightmax - height - 4);
  394. //Melder_casual (ymin, U" ", heightmax, U" ", height, U" ", top);
  395. bottom = top + height;
  396. }
  397. #if defined (macintoshXXX) || gtk
  398. top += Machine_getTitleBarHeight ();
  399. bottom += Machine_getTitleBarHeight ();
  400. #endif
  401. my windowForm = GuiWindow_create (left, top, width, height, 450, 250, title, gui_window_cb_goAway, me, my v_canFullScreen () ? GuiWindow_FULLSCREEN : 0);
  402. Thing_setName (me, title);
  403. my data = data;
  404. my v_copyPreferencesToInstance ();
  405. /* Create menus. */
  406. if (my v_hasMenuBar ()) {
  407. GuiWindow_addMenuBar (my windowForm);
  408. }
  409. my v_createChildren ();
  410. if (my v_hasMenuBar ()) {
  411. my v_createMenus ();
  412. EditorMenu helpMenu = Editor_addMenu (me, U"Help", 0);
  413. my v_createHelpMenuItems (helpMenu);
  414. EditorMenu_addCommand (helpMenu, U"-- search --", 0, nullptr);
  415. my searchButton = EditorMenu_addCommand (helpMenu, U"Search manual...", 'M', menu_cb_searchManual);
  416. if (my v_scriptable ()) {
  417. Editor_addCommand (me, U"File", U"New editor script", 0, menu_cb_newScript);
  418. Editor_addCommand (me, U"File", U"Open editor script...", 0, menu_cb_openScript);
  419. Editor_addCommand (me, U"File", U"-- after script --", 0, 0);
  420. }
  421. /*
  422. * Add the scripted commands.
  423. */
  424. praat_addCommandsToEditor (me);
  425. if (my callbackSocket)
  426. Editor_addCommand (me, U"File", U"Send back to calling program", 0, menu_cb_sendBackToCallingProgram);
  427. Editor_addCommand (me, U"File", U"Close", 'W', menu_cb_close);
  428. }
  429. GuiThing_show (my windowForm);
  430. }
  431. void Editor_save (Editor me, conststring32 text) {
  432. my v_saveData ();
  433. if (! my undoButton) return;
  434. GuiThing_setSensitive (my undoButton, true);
  435. Melder_sprint (my undoText,100, U"Undo ", text);
  436. #if gtk
  437. gtk_label_set_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (my undoButton -> d_widget))), Melder_peek32to8 (my undoText));
  438. #elif motif
  439. conststring8 text_utf8 = Melder_peek32to8 (my undoText);
  440. XtVaSetValues (my undoButton -> d_widget, XmNlabelString, text_utf8, nullptr);
  441. #elif cocoa
  442. [(GuiCocoaMenuItem *) my undoButton -> d_widget setTitle: (NSString *) Melder_peek32toCfstring (my undoText)];
  443. #endif
  444. }
  445. void Editor_openPraatPicture (Editor me) {
  446. my pictureGraphics = praat_picture_editor_open (my pref_picture_eraseFirst ());
  447. }
  448. void Editor_closePraatPicture (Editor me) {
  449. if (my data && my pref_picture_writeNameAtTop () != kEditor_writeNameAtTop::NO_) {
  450. Graphics_setNumberSignIsBold (my pictureGraphics, false);
  451. Graphics_setPercentSignIsItalic (my pictureGraphics, false);
  452. Graphics_setCircumflexIsSuperscript (my pictureGraphics, false);
  453. Graphics_setUnderscoreIsSubscript (my pictureGraphics, false);
  454. Graphics_textTop (my pictureGraphics,
  455. my pref_picture_writeNameAtTop () == kEditor_writeNameAtTop::FAR_,
  456. my data -> name.get());
  457. Graphics_setNumberSignIsBold (my pictureGraphics, true);
  458. Graphics_setPercentSignIsItalic (my pictureGraphics, true);
  459. Graphics_setCircumflexIsSuperscript (my pictureGraphics, true);
  460. Graphics_setUnderscoreIsSubscript (my pictureGraphics, true);
  461. }
  462. praat_picture_editor_close ();
  463. }
  464. /* End of file Editor.cpp */