123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- /* Manual.cpp
- *
- * Copyright (C) 1996-2018 Paul Boersma
- *
- * This code is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This code is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this work. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <ctype.h>
- #include "Manual.h"
- #include "Printer.h"
- #include "machine.h"
- #include "site.h"
- #include <time.h>
- #include "EditorM.h"
- #include "praat_script.h"
- #include "praatP.h"
- Thing_implement (Manual, HyperPage, 0);
- /* Remaining BUGS: HTML writer does not recognize "\s{". */
- #define SEARCH_PAGE 0
- static const conststring32 month [] =
- { U"", U"January", U"February", U"March", U"April", U"May", U"June",
- U"July", U"August", U"September", U"October", U"November", U"December" };
- static void menu_cb_writeOneToHtmlFile (Manual me, EDITOR_ARGS_FORM) {
- EDITOR_FORM_SAVE (U"Save as HTML file", nullptr)
- ManPages manPages = (ManPages) my data;
- autoMelderString buffer;
- MelderString_copy (& buffer, manPages -> pages.at [my path] -> title.get());
- char32 *p = buffer.string;
- while (*p) { if (! isalnum ((int) *p) && *p != U'_') *p = U'_'; p ++; }
- MelderString_append (& buffer, U".html");
- Melder_sprint (defaultName,300, buffer.string);
- EDITOR_DO_SAVE
- ManPages_writeOneToHtmlFile ((ManPages) my data, my path, file);
- EDITOR_END
- }
- static void menu_cb_writeAllToHtmlDir (Manual me, EDITOR_ARGS_FORM) {
- EDITOR_FORM (U"Save all pages as HTML files", nullptr)
- TEXTFIELD (directory, U"Directory:", U"")
- EDITOR_OK
- SET_STRING (directory, Melder_dirToPath (& my rootDirectory))
- EDITOR_DO
- ManPages_writeAllToHtmlDir ((ManPages) my data, directory);
- EDITOR_END
- }
- static void menu_cb_searchForPageList (Manual me, EDITOR_ARGS_FORM) {
- EDITOR_FORM (U"Search for page", nullptr)
- static ManPages manPages;
- static conststring32vector pages;
- manPages = (ManPages) my data;
- pages = ManPages_getTitles (manPages);
- LIST (page, U"Page", pages, 1)
- EDITOR_OK
- EDITOR_DO
- HyperPage_goToPage_i (me, page);
- EDITOR_END
- }
- void structManual :: v_draw () {
- ManPages manPages = (ManPages) our data;
- ManPage page;
- #if motif
- Graphics_clearWs (our graphics.get());
- #endif
- if (our path == SEARCH_PAGE) {
- HyperPage_pageTitle (this, U"Best matches");
- HyperPage_intro (this, U"The best matches to your query seem to be:");
- for (int i = 1; i <= our numberOfMatches; i ++) {
- char32 link [300];
- page = manPages -> pages.at [matches [i]];
- Melder_sprint (link,300, U"• @@", page -> title.get());
- HyperPage_listItem (this, link);
- }
- return;
- }
- page = manPages -> pages.at [path];
- if (! our paragraphs) return;
- HyperPage_pageTitle (this, page -> title.get());
- for (ManPage_Paragraph paragraph = & page -> paragraphs [0]; (int) paragraph -> type != 0; paragraph ++) {
- switch (paragraph -> type) {
- case kManPage_type::INTRO: HyperPage_intro (this, paragraph -> text); break;
- case kManPage_type::ENTRY: HyperPage_entry (this, paragraph -> text); break;
- case kManPage_type::NORMAL: HyperPage_paragraph (this, paragraph -> text); break;
- case kManPage_type::LIST_ITEM: HyperPage_listItem (this, paragraph -> text); break;
- case kManPage_type::TAG: HyperPage_listTag (this, paragraph -> text); break;
- case kManPage_type::DEFINITION: HyperPage_definition (this, paragraph -> text); break;
- case kManPage_type::CODE: HyperPage_code (this, paragraph -> text); break;
- case kManPage_type::PROTOTYPE: HyperPage_prototype (this, paragraph -> text); break;
- case kManPage_type::FORMULA: HyperPage_formula (this, paragraph -> text); break;
- case kManPage_type::PICTURE: HyperPage_picture (this, paragraph -> width,
- paragraph -> height, paragraph -> draw); break;
- case kManPage_type::SCRIPT: HyperPage_script (this, paragraph -> width,
- paragraph -> height, paragraph -> text); break;
- case kManPage_type::LIST_ITEM1: HyperPage_listItem1 (this, paragraph -> text); break;
- case kManPage_type::LIST_ITEM2: HyperPage_listItem2 (this, paragraph -> text); break;
- case kManPage_type::LIST_ITEM3: HyperPage_listItem3 (this, paragraph -> text); break;
- case kManPage_type::TAG1: HyperPage_listTag1 (this, paragraph -> text); break;
- case kManPage_type::TAG2: HyperPage_listTag2 (this, paragraph -> text); break;
- case kManPage_type::TAG3: HyperPage_listTag3 (this, paragraph -> text); break;
- case kManPage_type::DEFINITION1: HyperPage_definition1 (this, paragraph -> text); break;
- case kManPage_type::DEFINITION2: HyperPage_definition2 (this, paragraph -> text); break;
- case kManPage_type::DEFINITION3: HyperPage_definition3 (this, paragraph -> text); break;
- case kManPage_type::CODE1: HyperPage_code1 (this, paragraph -> text); break;
- case kManPage_type::CODE2: HyperPage_code2 (this, paragraph -> text); break;
- case kManPage_type::CODE3: HyperPage_code3 (this, paragraph -> text); break;
- case kManPage_type::CODE4: HyperPage_code4 (this, paragraph -> text); break;
- case kManPage_type::CODE5: HyperPage_code5 (this, paragraph -> text); break;
- default: break;
- }
- }
- if (ManPages_uniqueLinksHither (manPages, our path)) {
- integer ilink, jlink, lastParagraph = 0;
- bool goAhead = true;
- while ((int) page -> paragraphs [lastParagraph]. type != 0) lastParagraph ++;
- if (lastParagraph > 0) {
- conststring32 text = page -> paragraphs [lastParagraph - 1]. text;
- if (! text || text [0] == U'\0' || text [str32len (text) - 1] != U':') {
- if (our printing && our suppressLinksHither)
- goAhead = false;
- else
- HyperPage_entry (this, U"Links to this page");
- }
- }
- if (goAhead) for (ilink = 1; ilink <= page -> nlinksHither; ilink ++) {
- integer link = page -> linksHither [ilink];
- bool alreadyShown = false;
- for (jlink = 1; jlink <= page -> nlinksThither; jlink ++)
- if (page -> linksThither [jlink] == link)
- alreadyShown = true;
- if (! alreadyShown) {
- conststring32 title = manPages -> pages.at [page -> linksHither [ilink]] -> title.get();
- char32 linkText [304];
- Melder_sprint (linkText, 304, U"@@", title, U"@");
- HyperPage_listItem (this, linkText);
- }
- }
- }
- if (! our printing && page -> date) {
- char32 signature [100];
- integer date = page -> date;
- int imonth = date % 10000 / 100;
- if (imonth < 0 || imonth > 12) imonth = 0;
- Melder_sprint (signature,100,
- U"© ", str32equ (page -> author.get(), U"ppgb") ? U"Paul Boersma" :
- str32equ (page -> author.get(), U"djmw") ? U"David Weenink" : page -> author.get(),
- U", ", date % 100,
- U" ", month [imonth],
- U" ", date / 10000);
- HyperPage_any (this, U"", our p_font, our p_fontSize, 0, 0.0,
- 0.0, 0.0, 0.1, 0.1, HyperPage_ADD_BORDER);
- HyperPage_any (this, signature, our p_font, our p_fontSize, Graphics_ITALIC, 0.0,
- 0.03, 0.0, 0.1, 0.0, 0);
- }
- }
- /********** PRINTING **********/
- static void print (void *void_me, Graphics graphics) {
- iam (Manual);
- ManPages manPages = (ManPages) my data;
- integer numberOfPages = manPages -> pages.size, savePage = my path;
- my ps = graphics;
- Graphics_setDollarSignIsCode (my ps, true);
- Graphics_setAtSignIsLink (my ps, true);
- my printing = true;
- HyperPage_initSheetOfPaper ((HyperPage) me);
- for (integer ipage = 1; ipage <= numberOfPages; ipage ++) {
- ManPage page = manPages -> pages.at [ipage];
- if (my printPagesStartingWith == nullptr ||
- Melder_stringMatchesCriterion (page -> title.get(), kMelder_string::STARTS_WITH, my printPagesStartingWith, true))
- {
- ManPage_Paragraph par;
- my path = ipage;
- my paragraphs = page -> paragraphs;
- my numberOfParagraphs = 0;
- par = my paragraphs;
- while ((int) (par ++) -> type != 0) my numberOfParagraphs ++;
- my currentPageTitle = Melder_dup_f (page -> title.get());
- my v_goToPage_i (ipage);
- my v_draw ();
- my v_goToPage_i (savePage);
- }
- }
- my printing = false;
- my printPagesStartingWith = nullptr;
- }
- static void menu_cb_printRange (Manual me, EDITOR_ARGS_FORM) {
- EDITOR_FORM (U"Print range", nullptr)
- SENTENCE (leftOrInsideHeader, U"Left or inside header", U"")
- SENTENCE (middleHeader, U"Middle header", U"")
- SENTENCE (rightOrOutsideHeader, U"Right or outside header", U"Manual")
- SENTENCE (leftOrInsideFooter, U"Left or inside footer", U"")
- SENTENCE (middleFooter, U"Middle footer", U"")
- SENTENCE (rightOrOutsideFooter, U"Right or outside footer", U"")
- BOOLEAN (mirrorEvenOddHeaders, U"Mirror even/odd headers", true)
- TEXTFIELD (printAllPagesWhoseTitleStartsWith, U"Print all pages whose title starts with:", U"Intro")
- INTEGER (firstPageNumber, U"First page number", U"1")
- BOOLEAN (suppressLinksToThisPage, U"Suppress \"Links to this page\"", false)
- EDITOR_OK
- ManPages manPages = (ManPages) my data;
- time_t today = time (nullptr);
- char dateA [50];
- #ifdef UNIX
- struct tm *tm = localtime (& today);
- strftime (dateA, 50, "%B %e, %Y", tm);
- #else
- strcpy (dateA, ctime (& today));
- #endif
- autostring32 date = Melder_8to32 (dateA);
- char32 *newline = str32chr (date.get(), U'\n');
- if (newline)
- *newline = U'\0';
- SET_STRING (leftOrInsideHeader, date.get())
- SET_STRING (rightOrOutsideHeader, my name.get())
- if (my d_printingPageNumber) SET_INTEGER (firstPageNumber, my d_printingPageNumber + 1)
- if (my path >= 1 && my path <= manPages -> pages.size) {
- ManPage page = manPages -> pages.at [my path];
- SET_STRING (printAllPagesWhoseTitleStartsWith, page -> title.get());
- }
- EDITOR_DO
- my insideHeader = leftOrInsideHeader;
- my middleHeader = middleHeader;
- my outsideHeader = rightOrOutsideHeader;
- my insideFooter = leftOrInsideFooter;
- my middleFooter = middleFooter;
- my outsideFooter = rightOrOutsideFooter;
- my mirror = mirrorEvenOddHeaders;
- my printPagesStartingWith = printAllPagesWhoseTitleStartsWith;
- my d_printingPageNumber = firstPageNumber;
- my suppressLinksHither = suppressLinksToThisPage;
- Printer_print (print, me);
- EDITOR_END
- }
- /********** SEARCHING **********/
- static double *goodnessOfMatch;
- static double searchToken (ManPages me, integer ipage, char32 *token) {
- double goodness = 0.0;
- ManPage page = my pages.at [ipage];
- struct structManPage_Paragraph *par = & page -> paragraphs [0];
- if (! token [0]) return 1.0;
- /*
- * Try to find a match in the title, case-insensitively.
- */
- static MelderString buffer { };
- MelderString_copy (& buffer, page -> title.get());
- for (char32 *p = & buffer.string [0]; *p != U'\0'; p ++) *p = Melder_toLowerCase (*p);
- if (str32str (buffer.string, token)) {
- goodness += 300.0; // lots of points for a match in the title!
- if (str32equ (buffer.string, token))
- goodness += 10000.0; // even more points for an exact match!
- }
- /*
- * Try to find a match in the paragraphs, case-insensitively.
- */
- while ((int) par -> type != 0) {
- if (par -> text) {
- char32 *ptoken;
- MelderString_copy (& buffer, par -> text);
- for (char32 *p = & buffer.string [0]; *p != '\0'; p ++) *p = Melder_toLowerCase (*p);
- ptoken = str32str (buffer.string, token);
- if (ptoken) {
- goodness += 10.0; // ten points for every paragraph with a match!
- if (str32str (ptoken + str32len (token), token)) {
- goodness += 1.0; // one point for every second occurrence in a paragraph!
- }
- }
- }
- par ++;
- }
- return goodness;
- }
- static void search (Manual me, conststring32 query) {
- ManPages manPages = (ManPages) my data;
- integer numberOfPages = manPages -> pages.size;
- static MelderString searchText { };
- MelderString_copy (& searchText, query);
- for (char32 *p = & searchText.string [0]; *p != U'\0'; p ++) {
- if (*p == U'\n') *p = U' ';
- *p = Melder_toLowerCase (*p);
- }
- if (! goodnessOfMatch)
- goodnessOfMatch = NUMvector <double> (1, numberOfPages);
- for (integer ipage = 1; ipage <= numberOfPages; ipage ++) {
- char32 *token = searchText.string;
- goodnessOfMatch [ipage] = 1.0;
- for (;;) {
- char32 *space = str32chr (token, U' ');
- if (space) *space = U'\0';
- goodnessOfMatch [ipage] *= searchToken (manPages, ipage, token);
- if (! space) break;
- *space = U' '; // restore
- token = space + 1;
- }
- }
- /*
- * Find the 20 best matches.
- */
- my numberOfMatches = 0;
- for (integer imatch = 1; imatch <= 20; imatch ++) {
- integer imax = 0;
- double max = 0.0;
- for (integer ipage = 1; ipage <= numberOfPages; ipage ++) {
- if (goodnessOfMatch [ipage] > max) {
- max = goodnessOfMatch [ipage];
- imax = ipage;
- }
- }
- if (! imax) break;
- my matches [++ my numberOfMatches] = imax;
- goodnessOfMatch [imax] = 0.0; // skip next time
- }
- HyperPage_goToPage_i (me, SEARCH_PAGE);
- }
- void Manual_search (Manual me, conststring32 query) {
- GuiText_setString (my searchText, query);
- search (me, query);
- }
- static void gui_button_cb_home (Manual me, GuiButtonEvent /* event */) {
- ManPages pages = (ManPages) my data;
- integer iHome = ManPages_lookUp (pages, U"Intro");
- HyperPage_goToPage_i (me, iHome ? iHome : 1);
- }
-
- static void gui_button_cb_record (Manual me, GuiButtonEvent /* event */) {
- ManPages manPages = (ManPages) my data;
- ManPage manPage = ( my path < 1 ? nullptr : manPages -> pages.at [my path] );
- GuiThing_setSensitive (my recordButton, false);
- GuiThing_setSensitive (my playButton, false);
- GuiThing_setSensitive (my publishButton, false);
- #if defined (_WIN32)
- GdiFlush ();
- #endif
- if (! Melder_record (manPage == nullptr ? 1.0 : manPage -> recordingTime)) Melder_flushError ();
- GuiThing_setSensitive (my recordButton, true);
- GuiThing_setSensitive (my playButton, true);
- GuiThing_setSensitive (my publishButton, true);
- }
- static void gui_button_cb_play (Manual me, GuiButtonEvent /* event */) {
- GuiThing_setSensitive (my recordButton, false);
- GuiThing_setSensitive (my playButton, false);
- GuiThing_setSensitive (my publishButton, false);
- #if defined (_WIN32)
- GdiFlush ();
- #endif
- Melder_play ();
- GuiThing_setSensitive (my recordButton, true);
- GuiThing_setSensitive (my playButton, true);
- GuiThing_setSensitive (my publishButton, true);
- }
- static void gui_button_cb_publish (Manual /* me */, GuiButtonEvent /* event */) {
- Melder_publishPlayed ();
- }
- static void do_search (Manual me) {
- autostring32 query = GuiText_getString (my searchText);
- search (me, query.get());
- }
- static void gui_button_cb_search (Manual me, GuiButtonEvent /* event */) {
- do_search (me);
- }
- void structManual :: v_createChildren () {
- ManPages pages = (ManPages) our data; // has been installed here by Editor_init ()
- our d_hasExtraRowOfTools = pages -> dynamic;
- Manual_Parent :: v_createChildren ();
- #if defined (macintosh)
- #define STRING_SPACING 8
- #else
- #define STRING_SPACING 2
- #endif
- int height = Machine_getTextHeight (), y = Machine_getMenuBarHeight () + 4;
- our homeButton = GuiButton_createShown (our windowForm, 104, 168, y, y + height,
- U"Home", gui_button_cb_home, this, 0);
- if (pages -> dynamic) {
- our recordButton = GuiButton_createShown (our windowForm, 4, 79, y+height+8, y+height+8 + height,
- U"Record", gui_button_cb_record, this, 0);
- our playButton = GuiButton_createShown (our windowForm, 85, 160, y+height+8, y+height+8 + height,
- U"Play", gui_button_cb_play, this, 0);
- our publishButton = GuiButton_createShown (our windowForm, 166, 166 + 175, y+height+8, y+height+8 + height,
- U"Copy last played to list", gui_button_cb_publish, this, 0);
- }
- GuiButton_createShown (our windowForm, 274, 274 + 69, y, y + height,
- U"Search:", gui_button_cb_search, this, GuiButton_DEFAULT);
- our searchText = GuiText_createShown (our windowForm, 274+69 + STRING_SPACING, 452 + STRING_SPACING - 2, y, y + Gui_TEXTFIELD_HEIGHT, 0);
- }
- static void menu_cb_help (Manual me, EDITOR_ARGS_DIRECT) { HyperPage_goToPage (me, U"Manual"); }
- void structManual :: v_createMenus () {
- Manual_Parent :: v_createMenus ();
- Editor_addCommand (this, U"File", U"Print manual...", 0, menu_cb_printRange);
- Editor_addCommand (this, U"File", U"Save page as HTML file...", 0, menu_cb_writeOneToHtmlFile);
- Editor_addCommand (this, U"File", U"Save manual to HTML directory...", 0, menu_cb_writeAllToHtmlDir);
- Editor_addCommand (this, U"File", U"-- close --", 0, nullptr);
- Editor_addCommand (this, U"Go to", U"Search for page (list)...", 0, menu_cb_searchForPageList);
- }
- void structManual :: v_createHelpMenuItems (EditorMenu menu) {
- Manual_Parent :: v_createHelpMenuItems (menu);
- EditorMenu_addCommand (menu, U"Manual help", '?', menu_cb_help);
- }
- void structManual :: v_defaultHeaders (EditorCommand cmd) {
- Manual me = (Manual) cmd -> d_editor;
- ManPages manPages = (ManPages) my data;
- if (my path) {
- char32 string [400];
- static const conststring32 shortMonth [] =
- { U"Jan", U"Feb", U"Mar", U"Apr", U"May", U"Jun", U"Jul", U"Aug", U"Sep", U"Oct", U"Nov", U"Dec" };
- ManPage page = manPages -> pages.at [my path];
- integer date = page -> date;
- SET_STRING (my outsideHeader, page -> title.get())
- SET_STRING (my insideFooter, page -> author.get())
- if (date) {
- Melder_sprint (string,400, shortMonth [date % 10000 / 100 - 1], U" ", date % 100, U", ", date / 10000);
- SET_STRING (my insideHeader, string)
- }
- }
- }
- integer structManual :: v_getNumberOfPages () {
- ManPages manPages = (ManPages) our data;
- return manPages -> pages.size;
- }
- integer structManual :: v_getCurrentPageNumber () {
- return our path ? our path : 1;
- }
- void structManual :: v_goToPage_i (integer pageNumber) {
- ManPages manPages = (ManPages) our data;
- if (pageNumber < 1 || pageNumber > manPages -> pages.size) {
- if (pageNumber == SEARCH_PAGE) {
- our path = SEARCH_PAGE;
- our currentPageTitle. reset();
- return;
- } else Melder_throw (U"Page ", pageNumber, U" not found.");
- }
- our path = pageNumber;
- ManPage page = manPages -> pages.at [path];
- our paragraphs = page -> paragraphs;
- our numberOfParagraphs = 0;
- ManPage_Paragraph par = paragraphs;
- while ((int) (par ++) -> type != 0) our numberOfParagraphs ++;
- our currentPageTitle = Melder_dup_f (page -> title.get());
- }
- int structManual :: v_goToPage (conststring32 title) {
- ManPages manPages = (ManPages) our data;
- if (title [0] == U'\\' && title [1] == U'F' && title [2] == U'I') {
- structMelderFile file { };
- MelderDir_relativePathToFile (& manPages -> rootDirectory, title + 3, & file);
- Melder_recordFromFile (& file);
- return -1;
- } else if (title [0] == U'\\' && title [1] == U'S' && title [2] == U'C') {
- autoMelderSetDefaultDir dir (& manPages -> rootDirectory);
- autoPraatBackground background;
- try {
- autostring32 fileNameWithArguments = Melder_dup (title + 3);
- praat_executeScriptFromFileNameWithArguments (fileNameWithArguments.get());
- } catch (MelderError) {
- Melder_flushError ();
- }
- return 0;
- } else {
- integer i = ManPages_lookUp (manPages, title);
- if (! i)
- Melder_throw (U"Page \"", title, U"\" not found.");
- our v_goToPage_i (i);
- return 1;
- }
- }
- void Manual_init (Manual me, conststring32 title, Daata data, bool ownData) {
- ManPages manPages = (ManPages) data;
- integer i;
- if ((i = ManPages_lookUp (manPages, title)) == 0)
- Melder_throw (U"Page \"", title, U"\" not found.");
- my path = i;
- ManPage page = manPages -> pages.at [i];
- my paragraphs = page -> paragraphs;
- my numberOfParagraphs = 0;
- ManPage_Paragraph par = my paragraphs;
- while ((int) (par ++) -> type != 0) my numberOfParagraphs ++;
- char32 windowTitle [101];
- if (manPages -> pages.at [1] -> title [0] == U'-') {
- Melder_sprint (windowTitle,101, & manPages -> pages.at [1] -> title [1]);
- if (windowTitle [str32len (windowTitle) - 1] == U'-') windowTitle [str32len (windowTitle) - 1] = U'\0';
- } else {
- Melder_sprint (windowTitle,101, U"Manual");
- }
- my ownData = ownData;
- HyperPage_init (me, windowTitle, data);
- MelderDir_copy (& manPages -> rootDirectory, & my rootDirectory);
- my history [0]. page = Melder_dup_f (title); // BAD
- }
- autoManual Manual_create (conststring32 title, Daata data, bool ownData) {
- try {
- autoManual me = Thing_new (Manual);
- Manual_init (me.get(), title, data, ownData);
- return me;
- } catch (MelderError) {
- Melder_throw (U"Manual window not created.");
- }
- }
- /* End of file Manual.cpp */
|