1 /* praat_objectMenus.cpp
2 *
3 * Copyright (C) 1992-2021 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
19 #include "praatP.h"
20 #include "praatM.h"
21 #include "praat_script.h"
22 #include "ScriptEditor.h"
23 #include "ButtonEditor.h"
24 #include "DataEditor.h"
25 #include "site.h"
26 #include "GraphicsP.h"
27
28 #define EDITOR theCurrentPraatObjects -> list [IOBJECT]. editors
29
30 /********** Callbacks of the fixed buttons. **********/
31
DIRECT(PRAAT_Remove)32 DIRECT (PRAAT_Remove) {
33 WHERE_DOWN (SELECTED)
34 praat_removeObject (IOBJECT);
35 praat_show ();
36 END_NO_NEW_DATA
37 }
38
39 FORM (MODIFY_Rename, U"Rename object", U"Rename...") {
40 TEXTFIELD (newName, U"New name", U"", 3)
41 OK
42 WHERE (SELECTED) SET_STRING (newName, NAME)
43 DO
44 if (theCurrentPraatObjects -> totalSelection == 0)
45 Melder_throw (U"Selection changed!\nNo object selected. Cannot rename.");
46 if (theCurrentPraatObjects -> totalSelection > 1)
47 Melder_throw (U"Selection changed!\nCannot rename more than one object at a time.");
48 WHERE (SELECTED) break;
49 static MelderString string;
50 MelderString_copy (& string, newName);
51 praat_cleanUpName (string.string);
52 static MelderString fullName;
53 MelderString_copy (& fullName, Thing_className (OBJECT), U" ", string.string);
54 if (! str32equ (fullName.string, FULL_NAME)) {
55 theCurrentPraatObjects -> list [IOBJECT]. name = Melder_dup_f (fullName.string);
56 autoMelderString listName;
57 MelderString_append (& listName, ID, U". ", fullName.string);
58 praat_list_renameAndSelect (IOBJECT, listName.string);
59 for (int ieditor = 0; ieditor < praat_MAXNUM_EDITORS; ieditor ++)
60 if (EDITOR [ieditor]) Thing_setName (EDITOR [ieditor], fullName.string);
61 Thing_setName (OBJECT, string.string);
62 }
63 END_NO_NEW_DATA
64 }
65
66 FORM (NEW1_Copy, U"Copy object", U"Copy...") {
67 TEXTFIELD (newName, U"Name of new object", U"", 3)
68 OK
69 WHERE (SELECTED) SET_STRING (newName, NAME)
70 DO
71 if (theCurrentPraatObjects -> totalSelection == 0)
72 Melder_throw (U"Selection changed!\nNo object selected. Cannot copy.");
73 if (theCurrentPraatObjects -> totalSelection > 1)
74 Melder_throw (U"Selection changed!\nCannot copy more than one object at a time.");
75 if (interpreter)
76 interpreter -> returnType = kInterpreter_ReturnType::OBJECT_;
77 WHERE (SELECTED)
78 praat_new (Data_copy ((Daata) OBJECT), newName);
79 END_WITH_NEW_DATA
80 }
81
DIRECT(INFO_Info)82 DIRECT (INFO_Info) {
83 INFO_NONE
84 if (theCurrentPraatObjects -> totalSelection == 0)
85 Melder_throw (U"Selection changed!\nNo object selected. Cannot query.");
86 if (theCurrentPraatObjects -> totalSelection > 1)
87 Melder_throw (U"Selection changed!\nCannot query more than one object at a time.");
88 WHERE (SELECTED) Thing_infoWithIdAndFile (OBJECT, ID, & theCurrentPraatObjects -> list [IOBJECT]. file);
89 INFO_NONE_END
90 }
91
DIRECT(PRAAT__Inspect)92 DIRECT (PRAAT__Inspect) {
93 PRAAT
94 if (theCurrentPraatObjects -> totalSelection == 0)
95 Melder_throw (U"Selection changed!\nNo object selected. Cannot inspect.");
96 if (theCurrentPraatApplication -> batch) {
97 Melder_throw (U"Cannot inspect data from batch.");
98 } else {
99 WHERE (SELECTED) {
100 autoDataEditor editor = DataEditor_create (ID_AND_FULL_NAME, OBJECT);
101 praat_installEditor (editor.get(), IOBJECT);
102 editor.releaseToUser();
103 }
104 }
105 PRAAT_END
106 }
107
108 /********** The fixed menus. **********/
109
110 static GuiMenu praatMenu, editMenu, windowMenu, newMenu, readMenu, goodiesMenu, preferencesMenu, technicalMenu, applicationHelpMenu, helpMenu;
111
praat_objects_resolveMenu(conststring32 menu)112 GuiMenu praat_objects_resolveMenu (conststring32 menu) {
113 return
114 str32equ (menu, U"Praat") || str32equ (menu, U"Control") ? praatMenu :
115 #if cocoa
116 str32equ (menu, U"Edit") ? editMenu :
117 str32equ (menu, U"Window") ? windowMenu :
118 #endif
119 str32equ (menu, U"New") || str32equ (menu, U"Create") ? newMenu :
120 str32equ (menu, U"Open") || str32equ (menu, U"Read") ? readMenu :
121 str32equ (menu, U"Help") ? helpMenu :
122 str32equ (menu, U"Goodies") ? goodiesMenu :
123 str32equ (menu, U"Preferences") ? preferencesMenu :
124 str32equ (menu, U"Technical") ? technicalMenu :
125 #ifdef macintosh
126 str32equ (menu, U"ApplicationHelp") ? applicationHelpMenu :
127 #else
128 str32equ (menu, U"ApplicationHelp") ? helpMenu :
129 #endif
130 newMenu; // default
131 }
132
133 /********** Callbacks of the Praat menu. **********/
134
DIRECT(PRAAT__About)135 DIRECT (PRAAT__About) {
136 PRAAT
137 praat_showLogo ();
138 PRAAT_END
139 }
140
DIRECT(PRAAT__newScript)141 DIRECT (PRAAT__newScript) {
142 PRAAT
143 autoScriptEditor editor = ScriptEditor_createFromText (nullptr, nullptr);
144 editor.releaseToUser();
145 PRAAT_END
146 }
147
DIRECT(PRAAT__openScript)148 DIRECT (PRAAT__openScript) {
149 PRAAT
150 autoScriptEditor editor = ScriptEditor_createFromText (nullptr, nullptr);
151 TextEditor_showOpen (editor.get());
152 editor.releaseToUser();
153 PRAAT_END
154 }
155
156 static ButtonEditor theReferenceToTheOnlyButtonEditor;
157
cb_ButtonEditor_destruction(Editor)158 static void cb_ButtonEditor_destruction (Editor /* editor */) {
159 theReferenceToTheOnlyButtonEditor = nullptr;
160 }
161
DIRECT(PRAAT__editButtons)162 DIRECT (PRAAT__editButtons) {
163 PRAAT
164 if (theReferenceToTheOnlyButtonEditor) {
165 Editor_raise (theReferenceToTheOnlyButtonEditor);
166 } else {
167 autoButtonEditor editor = ButtonEditor_create ();
168 Editor_setDestructionCallback (editor.get(), cb_ButtonEditor_destruction);
169 theReferenceToTheOnlyButtonEditor = editor.get();
170 editor.releaseToUser();
171 }
172 PRAAT_END
173 }
174
175 FORM (PRAAT__addMenuCommand, U"Add menu command", U"Add menu command...") {
176 WORD (window, U"Window", U"Objects")
177 WORD (menu, U"Menu", U"New")
178 SENTENCE (command, U"Command", U"Hallo...")
179 SENTENCE (afterCommand, U"After command", U"")
180 INTEGER (depth, U"Depth", U"0")
181 INFILE (script, U"Script file", U"/u/miep/hallo.praat")
182 OK
183 DO
184 PRAAT
185 praat_addMenuCommandScript (window, menu, command, afterCommand, depth, script);
186 PRAAT_END
187 }
188
189 FORM (PRAAT__hideMenuCommand, U"Hide menu command", U"Hide menu command...") {
190 WORD (window, U"Window", U"Objects")
191 WORD (menu, U"Menu", U"New")
192 SENTENCE (command, U"Command", U"Hallo...")
193 OK
194 DO
195 PRAAT
196 praat_hideMenuCommand (window, menu, command);
197 PRAAT_END
198 }
199
200 FORM (PRAAT__showMenuCommand, U"Show menu command", U"Show menu command...") {
201 WORD (window, U"Window", U"Objects")
202 WORD (menu, U"Menu", U"New")
203 SENTENCE (command, U"Command", U"Hallo...")
204 OK
205 DO
206 PRAAT
207 praat_showMenuCommand (window, menu, command);
208 PRAAT_END
209 }
210
211 FORM (PRAAT__addAction, U"Add action command", U"Add action command...") {
212 WORD (class1, U"Class 1", U"Sound")
213 INTEGER (number1, U"Number 1", U"0")
214 WORD (class2, U"Class 2", U"")
215 INTEGER (number2, U"Number 2", U"0")
216 WORD (class3, U"Class 3", U"")
217 INTEGER (number3, U"Number 3", U"0")
218 SENTENCE (command, U"Command", U"Play reverse")
219 SENTENCE (afterCommand, U"After command", U"Play")
220 INTEGER (depth, U"Depth", U"0")
221 INFILE (script, U"Script file", U"/u/miep/playReverse.praat")
222 OK
223 DO
224 PRAAT
225 praat_addActionScript (class1, number1, class2, number2, class3, number3, command, afterCommand, depth, script);
226 PRAAT_END
227 }
228
229 FORM (PRAAT__hideAction, U"Hide action command", U"Hide action command...") {
230 WORD (class1, U"Class 1", U"Sound")
231 WORD (class2, U"Class 2", U"")
232 WORD (class3, U"Class 3", U"")
233 SENTENCE (command, U"Command", U"Play")
234 OK
235 DO
236 PRAAT
237 praat_hideAction_classNames (class1, class2, class3, command);
238 PRAAT_END
239 }
240
241 FORM (PRAAT__showAction, U"Show action command", U"Show action command...") {
242 WORD (class1, U"Class 1", U"Sound")
243 WORD (class2, U"Class 2", U"")
244 WORD (class3, U"Class 3", U"")
245 SENTENCE (command, U"Command", U"Play")
246 OK
247 DO
248 PRAAT
249 praat_showAction_classNames (class1, class2, class3, command);
250 PRAAT_END
251 }
252
253 /********** Callbacks of the Preferences menu. **********/
254
255 FORM (PREFS__TextInputEncodingSettings, U"Text reading preferences", U"Unicode") {
256 RADIO_ENUM (kMelder_textInputEncoding, encodingOf8BitTextFiles,
257 U"Encoding of 8-bit text files", kMelder_textInputEncoding::DEFAULT)
258 OK
259 SET_ENUM (encodingOf8BitTextFiles, kMelder_textInputEncoding, Melder_getInputEncoding ())
260 DO
261 PREFS
262 Melder_setInputEncoding (encodingOf8BitTextFiles);
263 PREFS_END
264 }
265
266 FORM (PREFS__TextOutputEncodingSettings, U"Text writing preferences", U"Unicode") {
267 RADIO_ENUM (kMelder_textOutputEncoding, outputEncoding,
268 U"Output encoding", kMelder_textOutputEncoding::DEFAULT)
269 OK
270 SET_ENUM (outputEncoding, kMelder_textOutputEncoding, Melder_getOutputEncoding ())
271 DO
272 PREFS
273 Melder_setOutputEncoding (outputEncoding);
274 PREFS_END
275 }
276
277 FORM (PREFS__GraphicsCjkFontStyleSettings, U"CJK font style preferences", nullptr) {
278 OPTIONMENU_ENUM (kGraphics_cjkFontStyle, cjkFontStyle,
279 U"CJK font style", kGraphics_cjkFontStyle::DEFAULT)
280 OK
281 SET_ENUM (cjkFontStyle, kGraphics_cjkFontStyle, theGraphicsCjkFontStyle)
282 DO
283 PREFS
284 theGraphicsCjkFontStyle = cjkFontStyle;
285 PREFS_END
286 }
287
288 /********** Callbacks of the Goodies menu. **********/
289
290 FORM (INFO_NONE__praat_calculator, U"Calculator", U"Calculator") {
291 TEXTFIELD (expression, U"Type any numeric formula or string formula", U"5*5", 5)
292 LABEL (U"Note that you can include many special functions in your formula,")
293 LABEL (U"including statistical functions and acoustics-auditory conversions.")
294 LABEL (U"For details, click Help.")
295 OK
296 DO
297 INFO_NONE
298 Formula_Result result;
299 if (! interpreter) {
300 autoInterpreter tempInterpreter = Interpreter_create (nullptr, nullptr);
301 Interpreter_anyExpression (tempInterpreter.get(), expression, & result);
302 } else {
303 Interpreter_anyExpression (interpreter, expression, & result);
304 }
305 switch (result. expressionType) {
306 case kFormula_EXPRESSION_TYPE_NUMERIC:
307 Melder_information (result. numericResult);
308 break; case kFormula_EXPRESSION_TYPE_STRING:
309 Melder_information (result. stringResult.get());
310 break; case kFormula_EXPRESSION_TYPE_NUMERIC_VECTOR:
311 Melder_information (constVECVU (result. numericVectorResult));
312 break; case kFormula_EXPRESSION_TYPE_NUMERIC_MATRIX:
313 Melder_information (constMATVU (result. numericMatrixResult));
314 break; case kFormula_EXPRESSION_TYPE_STRING_ARRAY:
315 Melder_information (result. stringArrayResult);
316 }
317 INFO_NONE_END
318 }
319
320 FORM (INFO_reportDifferenceOfTwoProportions, U"Report difference of two proportions", U"Difference of two proportions") {
321 INTEGER (a_int, U"left Row 1", U"71")
322 INTEGER (b_int, U"right Row 1", U"39")
323 INTEGER (c_int, U"left Row 2", U"93")
324 INTEGER (d_int, U"right Row 2", U"27")
325 OK
326 DO
327 INFO_NONE
328 double a = a_int, b = b_int, c = c_int, d = d_int;
329 double n = a + b + c + d;
330 if (a < 0 || b < 0 || c < 0 || d < 0)
331 Melder_throw (U"The numbers should not be negative.");
332 if (a + b <= 0 || c + d <= 0)
333 Melder_throw (U"The row totals should be positive.");
334 if (a + c <= 0 || b + d <= 0)
335 Melder_throw (U"The column totals should be positive.");
336 MelderInfo_open ();
337 MelderInfo_writeLine (U"Observed row 1 = ", Melder_iround (a), U" ", Melder_iround (b));
338 MelderInfo_writeLine (U"Observed row 2 = ", Melder_iround (c), U" ", Melder_iround (d));
339 double aexp = (a + b) * (a + c) / n;
340 double bexp = (a + b) * (b + d) / n;
341 double cexp = (a + c) * (c + d) / n;
342 double dexp = (b + d) * (c + d) / n;
343 MelderInfo_writeLine (U"");
344 MelderInfo_writeLine (U"Expected row 1 = ", aexp, U" ", bexp);
345 MelderInfo_writeLine (U"Expected row 2 = ", cexp, U" ", dexp);
346 /*
347 Continuity correction:
348 bring the observed numbers closer to the expected numbers by 0.5 (if possible).
349 */
350 Melder_moveCloserToBy (& a, aexp, 0.5);
351 Melder_moveCloserToBy (& b, bexp, 0.5);
352 Melder_moveCloserToBy (& c, cexp, 0.5);
353 Melder_moveCloserToBy (& d, dexp, 0.5);
354 MelderInfo_writeLine (U"");
355 MelderInfo_writeLine (U"Corrected observed row 1 = ", a, U" ", b);
356 MelderInfo_writeLine (U"Corrected observed row 2 = ", c, U" ", d);
357
358 n = a + b + c + d;
359 double crossDifference = a * d - b * c;
360 double x2 = n * crossDifference * crossDifference / (a + b) / (c + d) / (a + c) / (b + d);
361 MelderInfo_writeLine (U"");
362 MelderInfo_writeLine (U"Chi-square = ", x2);
363 MelderInfo_writeLine (U"Two-tailed p = ", NUMchiSquareQ (x2, 1));
364 MelderInfo_close ();
365 INFO_NONE_END
366 }
367
368 /********** Callbacks of the Technical menu. **********/
369
370 FORM (PREFS__debug, U"Set debugging options", nullptr) {
371 LABEL (U"If you switch Tracing on, Praat will write lots of detailed ")
372 LABEL (U"information about what goes on in Praat")
373 structMelderDir dir;
374 Melder_getPrefDir (& dir);
375 structMelderFile file;
376 #ifdef UNIX
377 MelderDir_getFile (& dir, U"tracing", & file);
378 #else
379 MelderDir_getFile (& dir, U"Tracing.txt", & file);
380 #endif
381 LABEL (Melder_cat (U"to ", Melder_fileToPath (& file), U"."))
382 BOOLEAN (tracing, U"Tracing", false)
383 LABEL (U"Setting the following to anything other than zero")
384 LABEL (U"will alter the behaviour of Praat")
385 LABEL (U"in unpredictable ways.")
386 INTEGER (debugOption, U"Debug option", U"0")
387 OK
388 SET_BOOLEAN (tracing, Melder_isTracing)
389 SET_INTEGER (debugOption, Melder_debug)
390 DO
391 PREFS
392 Melder_setTracing (tracing);
393 Melder_debug = debugOption;
394 PREFS_END
395 }
396
DIRECT(INFO_NONE__listReadableTypesOfObjects)397 DIRECT (INFO_NONE__listReadableTypesOfObjects) {
398 INFO_NONE
399 Thing_listReadableClasses ();
400 INFO_NONE_END
401 }
402
403 FORM (INFO_praat_library_createC, U"PraatLib: Create C header or file", nullptr) {
404 BOOLEAN (isInHeader, U"Is in header", true)
405 BOOLEAN (includeCreateAPI, U"Include \"Create\" API", true)
406 BOOLEAN (includeReadAPI, U"Include \"Read\" API", true)
407 BOOLEAN (includeSaveAPI, U"Include \"Save\" API", true)
408 BOOLEAN (includeQueryAPI, U"Include \"Query\" API", true)
409 BOOLEAN (includeModifyAPI, U"Include \"Modify\" API", true)
410 BOOLEAN (includeToAPI, U"Include \"To\" API", true)
411 BOOLEAN (includeRecordAPI, U"Include \"Record\" API", true)
412 BOOLEAN (includePlayAPI, U"Include \"Play\" API", true)
413 BOOLEAN (includeDrawAPI, U"Include \"Draw\" API", true)
414 BOOLEAN (includeHelpAPI, U"Include \"Help\" API", false)
415 BOOLEAN (includeWindowAPI, U"Include \"Window\" API", false)
416 BOOLEAN (includeDemoAPI, U"Include \"Demo\" API", false)
417 OK
418 DO
419 praat_library_createC (isInHeader, includeCreateAPI, includeReadAPI, includeSaveAPI,
420 includeQueryAPI, includeModifyAPI, includeToAPI, includeRecordAPI, includePlayAPI,
421 includeDrawAPI, includeHelpAPI, includeWindowAPI, includeDemoAPI);
422 END_NO_NEW_DATA
423 }
424
DIRECT(INFO_NONE__reportSystemProperties)425 DIRECT (INFO_NONE__reportSystemProperties) {
426 INFO_NONE
427 praat_reportSystemProperties ();
428 INFO_NONE_END
429 }
430
DIRECT(INFO_NONE__reportGraphicalProperties)431 DIRECT (INFO_NONE__reportGraphicalProperties) {
432 INFO_NONE
433 praat_reportGraphicalProperties ();
434 INFO_NONE_END
435 }
436
DIRECT(INFO_NONE__reportIntegerProperties)437 DIRECT (INFO_NONE__reportIntegerProperties) {
438 INFO_NONE
439 praat_reportIntegerProperties ();
440 INFO_NONE_END
441 }
442
DIRECT(INFO_NONE__reportMemoryUse)443 DIRECT (INFO_NONE__reportMemoryUse) {
444 INFO_NONE
445 praat_reportMemoryUse ();
446 INFO_NONE_END
447 }
448
DIRECT(INFO_NONE__reportTextProperties)449 DIRECT (INFO_NONE__reportTextProperties) {
450 INFO_NONE
451 praat_reportTextProperties ();
452 INFO_NONE_END
453 }
454
DIRECT(INFO_NONE__reportFontProperties)455 DIRECT (INFO_NONE__reportFontProperties) {
456 INFO_NONE
457 praat_reportFontProperties ();
458 INFO_NONE_END
459 }
460
461 /********** Callbacks of the Open menu. **********/
462
463 /*
464 Note: readFromFile should not call praat_updateSelection(),
465 because praat_updateSelection() should be called after all files have been read,
466 not just the current one.
467 */
readFromFile(MelderFile file)468 static void readFromFile (MelderFile file) {
469 autoDaata object = Data_readFromFile (file);
470 if (! object)
471 return; // this can happen with Picture_readFromPraatPictureFile (file recognized, but no data)
472 if (Thing_isa (object.get(), classManPages) && ! Melder_batch) {
473 ManPages manPages = (ManPages) object.get();
474 ManPage firstPage = manPages -> pages.at [1];
475 autoManual manual = Manual_create (firstPage -> title.get(), object.releaseToAmbiguousOwner(), true);
476 if (manPages -> executable)
477 Melder_warning (U"These manual pages contain links to executable scripts.\n"
478 "Only navigate these pages if you trust their author!");
479 manual.releaseToUser();
480 return;
481 }
482 if (Thing_isa (object.get(), classScript) && ! Melder_batch) {
483 autoScriptEditor editor = ScriptEditor_createFromScript_canBeNull (nullptr, (Script) object.get());
484 if (! editor) {
485 (void) 0; // the script was already open, and the user has been notified of that
486 } else {
487 editor.releaseToUser();
488 }
489 return;
490 }
491 praat_newWithFile (object.move(), file, MelderFile_name (file));
492 }
493
494 FORM_READ (READMANY_Data_readFromFile, U"Read Object(s) from file", 0, true) {
495 readFromFile (file);
496 if (interpreter)
497 interpreter -> returnType = kInterpreter_ReturnType::OBJECT_;
498 END_WITH_NEW_DATA // this calls praat_updateSelection(), after reading a single file; see also cb_openDocument
499 }
500
501 /********** Callbacks of the Save menu. **********/
502
503 FORM_SAVE (SAVE_Data_writeToTextFile, U"Save Object(s) as one text file", nullptr, nullptr) {
504 if (theCurrentPraatObjects -> totalSelection == 1) {
505 LOOP {
506 iam_LOOP (Daata);
507 Data_writeToTextFile (me, file);
508 }
509 } else {
510 autoCollection set = praat_getSelectedObjects ();
511 Data_writeToTextFile (set.get(), file);
512 }
513 END_NO_NEW_DATA
514 }
515
516 FORM_SAVE (SAVE_Data_writeToShortTextFile, U"Save Object(s) as one short text file", nullptr, nullptr) {
517 if (theCurrentPraatObjects -> totalSelection == 1) {
518 LOOP {
519 iam_LOOP (Daata);
520 Data_writeToShortTextFile (me, file);
521 }
522 } else {
523 autoCollection set = praat_getSelectedObjects ();
524 Data_writeToShortTextFile (set.get(), file);
525 }
526 END_NO_NEW_DATA
527 }
528
529 FORM_SAVE (SAVE_Data_writeToBinaryFile, U"Save Object(s) as one binary file", nullptr, nullptr) {
530 if (theCurrentPraatObjects -> totalSelection == 1) {
531 LOOP {
532 iam_LOOP (Daata);
533 Data_writeToBinaryFile (me, file);
534 }
535 } else {
536 autoCollection set = praat_getSelectedObjects ();
537 Data_writeToBinaryFile (set.get(), file);
538 }
539 END_NO_NEW_DATA
540 }
541
542 FORM (PRAAT_ManPages_saveToHtmlFolder, U"Save all pages as HTML files", nullptr) {
543 FOLDER (folder, U"Folder", U"")
544 OK
545 LOOP {
546 iam_LOOP (ManPages);
547 SET_STRING (folder, Melder_dirToPath (& my rootDirectory))
548 }
549 DO
550 LOOP {
551 iam_LOOP (ManPages);
552 ManPages_writeAllToHtmlDir (me, folder);
553 }
554 END_NO_NEW_DATA
555 }
556
DIRECT(WINDOW_ManPages_view)557 DIRECT (WINDOW_ManPages_view) {
558 LOOP {
559 iam_LOOP (ManPages);
560 ManPage firstPage = my pages.at [1];
561 autoManual manual = Manual_create (firstPage -> title.get(), me, false);
562 if (my executable)
563 Melder_warning (U"These manual pages contain links to executable scripts.\n"
564 "Only navigate these pages if you trust their author!");
565 praat_installEditor (manual.get(), IOBJECT);
566 manual.releaseToUser();
567 }
568 END_NO_NEW_DATA
569 }
570
571 /********** Callbacks of the Help menu. **********/
572
573 FORM (PRAAT__SearchManual, U"Search manual", U"Manual") {
574 TEXTFIELD (query, U"Search for strings (separate with spaces)", U"", 3)
575 OK
576 DO
577 PRAAT
578 if (theCurrentPraatApplication -> batch)
579 Melder_throw (U"Cannot view a manual from batch.");
580 autoManual manual = Manual_create (U"Intro", theCurrentPraatApplication -> manPages, false);
581 Manual_search (manual.get(), query);
582 manual.releaseToUser();
583 PRAAT_END
584 }
585
586 FORM (PRAAT__GoToManualPage, U"Go to manual page", nullptr) {
587 static constSTRVEC pages;
588 pages = ManPages_getTitles (theCurrentPraatApplication -> manPages);
589 LIST (goToPageNumber, U"Page", pages, 1)
590 OK
591 DO
592 PRAAT
593 if (theCurrentPraatApplication -> batch)
594 Melder_throw (U"Cannot view a manual from batch.");
595 autoManual manual = Manual_create (U"Intro", theCurrentPraatApplication -> manPages, false);
596 HyperPage_goToPage_number (manual.get(), goToPageNumber);
597 manual.releaseToUser();
598 PRAAT_END
599 }
600
601 FORM (HELP_SaveManualToHtmlFolder, U"Save all pages as HTML files", nullptr) {
602 FOLDER (folder, U"Folder", U"")
603 OK
604 structMelderDir currentDirectory { };
605 Melder_getDefaultDir (& currentDirectory);
606 SET_STRING (folder, Melder_dirToPath (& currentDirectory))
607 DO
608 ManPages_writeAllToHtmlDir (theCurrentPraatApplication -> manPages, folder);
609 END_NO_NEW_DATA
610 }
611
612 /********** Menu descriptions. **********/
613
praat_show()614 void praat_show () {
615 /*
616 (De)sensitivize the fixed buttons as appropriate for the current selection.
617 */
618 praat_sensitivizeFixedButtonCommand (U"Remove", theCurrentPraatObjects -> totalSelection != 0);
619 praat_sensitivizeFixedButtonCommand (U"Rename...", theCurrentPraatObjects -> totalSelection == 1);
620 praat_sensitivizeFixedButtonCommand (U"Copy...", theCurrentPraatObjects -> totalSelection == 1);
621 praat_sensitivizeFixedButtonCommand (U"Info", theCurrentPraatObjects -> totalSelection == 1);
622 praat_sensitivizeFixedButtonCommand (U"Inspect", theCurrentPraatObjects -> totalSelection != 0);
623 praat_actions_show ();
624 if (theCurrentPraatApplication == & theForegroundPraatApplication && theReferenceToTheOnlyButtonEditor)
625 Editor_dataChanged (theReferenceToTheOnlyButtonEditor);
626 }
627
628 /********** Menu descriptions. **********/
629
praat_addFixedButtons(GuiWindow window)630 void praat_addFixedButtons (GuiWindow window) {
631 praat_addFixedButtonCommand (window, U"Rename...", MODIFY_Rename, 8, 70);
632 praat_addFixedButtonCommand (window, U"Copy...", NEW1_Copy, 98, 70);
633 praat_addFixedButtonCommand (window, U"Inspect",
634 PRAAT__Inspect, 8, 40);
635 praat_addFixedButtonCommand (window, U"Info", INFO_Info, 98, 40);
636 praat_addFixedButtonCommand (window, U"Remove", PRAAT_Remove, 8, 10);
637 }
638
searchProc()639 static void searchProc () {
640 PRAAT__SearchManual (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
641 }
642
643 static MelderString itemTitle_about;
644
scriptRecognizer(integer nread,const char * header,MelderFile file)645 static autoDaata scriptRecognizer (integer nread, const char *header, MelderFile file) {
646 conststring32 name = MelderFile_name (file);
647 if (nread < 2)
648 return autoDaata ();
649 if ((header [0] == '#' && header [1] == '!')
650 || Melder_stringMatchesCriterion (name, kMelder_string::ENDS_WITH, U".praat", false)
651 || Melder_stringMatchesCriterion (name, kMelder_string::ENDS_WITH, U".html", false)
652 ) {
653 return Script_createFromFile (file);
654 }
655 return autoDaata ();
656 }
657
cb_openDocument(MelderFile file)658 static void cb_openDocument (MelderFile file) {
659 try {
660 readFromFile (file); // read a single file without calling praat_updateSelection()
661 } catch (MelderError) {
662 Melder_flushError ();
663 }
664 }
cb_finishedOpeningDocuments()665 static void cb_finishedOpeningDocuments () {
666 try {
667 praat_updateSelection (); // this finally calls praat_updateSelection(), after each separate file has been read
668 } catch (MelderError) {
669 Melder_flushError ();
670 }
671 }
672
673 #if cocoa
DIRECT(PRAAT__cut)674 DIRECT (PRAAT__cut) {
675 PRAAT
676 [[[NSApp keyWindow] firstResponder] cut: nil];
677 PRAAT_END
678 }
DIRECT(PRAAT__copy)679 DIRECT (PRAAT__copy) {
680 PRAAT
681 [[[NSApp keyWindow] firstResponder] copy: nil];
682 PRAAT_END
683 }
DIRECT(PRAAT__paste)684 DIRECT (PRAAT__paste) {
685 PRAAT
686 [[[NSApp keyWindow] firstResponder] pasteAsPlainText: nil];
687 PRAAT_END
688 }
DIRECT(PRAAT__minimize)689 DIRECT (PRAAT__minimize) {
690 PRAAT
691 [[NSApp keyWindow] performMiniaturize: nil];
692 PRAAT_END
693 }
DIRECT(PRAAT__zoom)694 DIRECT (PRAAT__zoom) {
695 PRAAT
696 [[NSApp keyWindow] performZoom: nil];
697 PRAAT_END
698 }
DIRECT(PRAAT__close)699 DIRECT (PRAAT__close) {
700 PRAAT
701 [[NSApp keyWindow] performClose: nil];
702 PRAAT_END
703 }
704 #endif
705
praat_addMenus(GuiWindow window)706 void praat_addMenus (GuiWindow window) {
707 Melder_setSearchProc (searchProc);
708
709 Data_recognizeFileType (scriptRecognizer);
710
711 /*
712 Create the menu titles in the bar.
713 */
714 if (! theCurrentPraatApplication -> batch) {
715 #ifdef macintosh
716 praatMenu = GuiMenu_createInWindow (nullptr, U"\024", 0);
717 #if cocoa
718 editMenu = GuiMenu_createInWindow (nullptr, U"Edit", 0);
719 windowMenu = GuiMenu_createInWindow (nullptr, U"Window", 0);
720 #endif
721 #else
722 praatMenu = GuiMenu_createInWindow (window, U"Praat", 0);
723 #endif
724 newMenu = GuiMenu_createInWindow (window, U"New", 0);
725 readMenu = GuiMenu_createInWindow (window, U"Open", 0);
726 praat_actions_createWriteMenu (window);
727 #ifdef macintosh
728 applicationHelpMenu = GuiMenu_createInWindow (nullptr, U"Help", 0);
729 #endif
730 helpMenu = GuiMenu_createInWindow (window, U"Help", 0);
731 }
732
733 MelderString_append (& itemTitle_about, U"About ", praatP.title.get());
734 praat_addMenuCommand (U"Objects", U"Praat", itemTitle_about.string, nullptr, praat_UNHIDABLE,
735 PRAAT__About);
736 #ifdef macintosh
737 #if cocoa
738 /*
739 HACK: give the following commands weird names,
740 because otherwise they may be called from a script.
741 (we add three alt-spaces)
742 */
743 praat_addMenuCommand (U"Objects", U"Edit", U"Cut ", nullptr, praat_UNHIDABLE | 'X' | praat_NO_API,
744 PRAAT__cut);
745 praat_addMenuCommand (U"Objects", U"Edit", U"Copy ", nullptr, praat_UNHIDABLE | 'C' | praat_NO_API,
746 PRAAT__copy);
747 praat_addMenuCommand (U"Objects", U"Edit", U"Paste ", nullptr, praat_UNHIDABLE | 'V' | praat_NO_API,
748 PRAAT__paste);
749 praat_addMenuCommand (U"Objects", U"Window", U"Minimize ", nullptr, praat_UNHIDABLE | praat_NO_API,
750 PRAAT__minimize);
751 praat_addMenuCommand (U"Objects", U"Window", U"Zoom ", nullptr, praat_UNHIDABLE | praat_NO_API,
752 PRAAT__zoom);
753 praat_addMenuCommand (U"Objects", U"Window", U"Close ", nullptr, 'W' | praat_NO_API,
754 PRAAT__close);
755 #endif
756 #endif
757 praat_addMenuCommand (U"Objects", U"Praat", U"-- script --", nullptr, 0, nullptr);
758 praat_addMenuCommand (U"Objects", U"Praat", U"New Praat script", nullptr, praat_NO_API,
759 PRAAT__newScript);
760 praat_addMenuCommand (U"Objects", U"Praat", U"Open Praat script...", nullptr, praat_NO_API,
761 PRAAT__openScript);
762 praat_addMenuCommand (U"Objects", U"Praat", U"-- buttons --", nullptr, 0, nullptr);
763 praat_addMenuCommand (U"Objects", U"Praat", U"Add menu command...", nullptr, praat_HIDDEN | praat_NO_API,
764 PRAAT__addMenuCommand);
765 praat_addMenuCommand (U"Objects", U"Praat", U"Hide menu command...", nullptr, praat_HIDDEN | praat_NO_API,
766 PRAAT__hideMenuCommand);
767 praat_addMenuCommand (U"Objects", U"Praat", U"Show menu command...", nullptr, praat_HIDDEN | praat_NO_API,
768 PRAAT__showMenuCommand);
769 praat_addMenuCommand (U"Objects", U"Praat", U"Add action command...", nullptr, praat_HIDDEN | praat_NO_API,
770 PRAAT__addAction);
771 praat_addMenuCommand (U"Objects", U"Praat", U"Hide action command...", nullptr, praat_HIDDEN | praat_NO_API,
772 PRAAT__hideAction);
773 praat_addMenuCommand (U"Objects", U"Praat", U"Show action command...", nullptr, praat_HIDDEN | praat_NO_API,
774 PRAAT__showAction);
775
776 GuiMenuItem menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Goodies", nullptr, praat_UNHIDABLE, nullptr);
777 goodiesMenu = menuItem ? menuItem -> d_menu : nullptr;
778 praat_addMenuCommand (U"Objects", U"Goodies", U"Calculator...", nullptr, 'U',
779 INFO_NONE__praat_calculator);
780 praat_addMenuCommand (U"Objects", U"Goodies", U"Report difference of two proportions...", nullptr, 0, INFO_reportDifferenceOfTwoProportions);
781
782 menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Preferences", nullptr, praat_UNHIDABLE, nullptr);
783 preferencesMenu = menuItem ? menuItem -> d_menu : nullptr;
784 praat_addMenuCommand (U"Objects", U"Preferences", U"Buttons...", nullptr, praat_UNHIDABLE,
785 PRAAT__editButtons);
786 praat_addMenuCommand (U"Objects", U"Preferences", U"-- encoding prefs --", nullptr, 0, nullptr);
787 praat_addMenuCommand (U"Objects", U"Preferences", U"Text reading preferences...", nullptr, 0,
788 PREFS__TextInputEncodingSettings);
789 praat_addMenuCommand (U"Objects", U"Preferences", U"Text writing preferences...", nullptr, 0,
790 PREFS__TextOutputEncodingSettings);
791 praat_addMenuCommand (U"Objects", U"Preferences", U"CJK font style preferences...", nullptr, 0,
792 PREFS__GraphicsCjkFontStyleSettings);
793
794 menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Technical", nullptr, praat_UNHIDABLE, nullptr);
795 technicalMenu = menuItem ? menuItem -> d_menu : nullptr;
796 praat_addMenuCommand (U"Objects", U"Technical", U"Report memory use", nullptr, 0,
797 INFO_NONE__reportMemoryUse);
798 praat_addMenuCommand (U"Objects", U"Technical", U"Report integer properties", nullptr, 0,
799 INFO_NONE__reportIntegerProperties);
800 praat_addMenuCommand (U"Objects", U"Technical", U"Report system properties", nullptr, 0,
801 INFO_NONE__reportSystemProperties);
802 praat_addMenuCommand (U"Objects", U"Technical", U"Report graphical properties", nullptr, 0,
803 INFO_NONE__reportGraphicalProperties);
804 praat_addMenuCommand (U"Objects", U"Technical", U"Report text properties", nullptr, 0,
805 INFO_NONE__reportTextProperties);
806 praat_addMenuCommand (U"Objects", U"Technical", U"Report font properties", nullptr, 0,
807 INFO_NONE__reportFontProperties);
808 praat_addMenuCommand (U"Objects", U"Technical", U"Debug...", nullptr, 0,
809 PREFS__debug);
810 praat_addMenuCommand (U"Objects", U"Technical", U"-- api --", nullptr, 0, nullptr);
811 praat_addMenuCommand (U"Objects", U"Technical", U"List readable types of objects", nullptr, 0,
812 INFO_NONE__listReadableTypesOfObjects);
813 praat_addMenuCommand (U"Objects", U"Technical", U"Create C interface...", nullptr, 0, INFO_praat_library_createC);
814
815 praat_addMenuCommand (U"Objects", U"Open", U"Read from file...", nullptr, praat_ATTRACTIVE | 'O', READMANY_Data_readFromFile);
816
817 praat_addAction1 (classDaata, 0, U"Save as text file...", nullptr, 0, SAVE_Data_writeToTextFile);
818 praat_addAction1 (classDaata, 0, U"Write to text file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToTextFile);
819 praat_addAction1 (classDaata, 0, U"Save as short text file...", nullptr, 0, SAVE_Data_writeToShortTextFile);
820 praat_addAction1 (classDaata, 0, U"Write to short text file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToShortTextFile);
821 praat_addAction1 (classDaata, 0, U"Save as binary file...", nullptr, 0, SAVE_Data_writeToBinaryFile);
822 praat_addAction1 (classDaata, 0, U"Write to binary file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToBinaryFile);
823
824 praat_addAction1 (classManPages, 1, U"Save to HTML folder...", nullptr, 0, PRAAT_ManPages_saveToHtmlFolder);
825 praat_addAction1 (classManPages, 1, U"Save to HTML directory...", nullptr, praat_DEPRECATED_2020, PRAAT_ManPages_saveToHtmlFolder);
826 praat_addAction1 (classManPages, 1, U"View", nullptr, 0, WINDOW_ManPages_view);
827 }
828
praat_addMenus2()829 void praat_addMenus2 () {
830 praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"-- manual --", nullptr, 0, nullptr);
831 praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Go to manual page...", nullptr, 0,
832 PRAAT__GoToManualPage);
833 praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Save manual to HTML folder...", nullptr, praat_HIDDEN, HELP_SaveManualToHtmlFolder);
834 praat_addMenuCommand (U"Objects", U"ApplicationHelp", Melder_cat (U"Search ", praatP.title.get(), U" manual..."), nullptr, 'M' | praat_NO_API,
835 PRAAT__SearchManual);
836 praat_addMenuCommand (U"Objects", U"ApplicationHelp", itemTitle_about.string, nullptr, praat_UNHIDABLE,
837 PRAAT__About);
838
839 #if defined (macintosh) || defined (_WIN32)
840 Gui_setOpenDocumentCallback (cb_openDocument, cb_finishedOpeningDocuments);
841 #endif
842 }
843
844 /* End of file praat_objectMenus.cpp */
845