EditorM.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #ifndef _EditorM_h_
  2. #define _EditorM_h_
  3. /* EditorM.h
  4. *
  5. * Copyright (C) 1992-2013,2015-2018 Paul Boersma
  6. *
  7. * This code is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * This code is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #undef REAL
  21. #undef REAL_OR_UNDEFINED
  22. #undef POSITIVE
  23. #undef INTEGER
  24. #undef NATURAL
  25. #undef WORD
  26. #undef SENTENCE
  27. #undef COLOUR
  28. #undef CHANNEL
  29. #undef BOOLEAN
  30. #undef LABEL
  31. #undef MUTABLE_LABEL
  32. #undef TEXTFIELD
  33. #undef RADIO
  34. #undef RADIOSTR
  35. #undef RADIOBUTTON
  36. #undef OPTIONMENU
  37. #undef OPTIONMENUSTR
  38. #undef OPTION
  39. #undef RADIO_ENUM
  40. #undef OPTIONMENU_ENUM
  41. #undef LIST
  42. #undef SET_REAL
  43. #undef SET_INTEGER
  44. #undef SET_BOOLEAN
  45. #undef SET_STRING
  46. #undef SET_ENUM
  47. #define EDITOR_ARGS_FORM EditorCommand cmd, UiForm _sendingForm_, integer _narg_, Stackel _args_, conststring32 _sendingString_, Interpreter interpreter
  48. #define EDITOR_ARGS_CMD EditorCommand cmd, UiForm, integer, Stackel, conststring32, Interpreter
  49. #define EDITOR_ARGS_DIRECT EditorCommand, UiForm, integer, Stackel, conststring32, Interpreter
  50. #define EDITOR_FORM(title, helpTitle) \
  51. UiField _radio_ = nullptr; \
  52. (void) _radio_; \
  53. if (cmd -> d_uiform) goto _form_inited_; \
  54. cmd -> d_uiform = UiForm_createE (cmd, title, cmd -> itemTitle.get(), helpTitle);
  55. #define EDITOR_OK \
  56. UiForm_finish (cmd -> d_uiform.get()); \
  57. _form_inited_: \
  58. if (! _args_ && ! _sendingForm_ && ! _sendingString_) {
  59. #define EDITOR_DO \
  60. UiForm_do (cmd -> d_uiform.get(), false); \
  61. } else if (! _sendingForm_) { \
  62. UiForm_parseStringE (cmd, _narg_, _args_, _sendingString_, interpreter); \
  63. } else {
  64. #define EDITOR_END \
  65. }
  66. /*
  67. Functions to define the fields in a form on the basis of the label text
  68. and factory default value.
  69. They are to be called between EDITOR_FORM and EDITOR_OK.
  70. */
  71. #define REAL_VARIABLE(realVariable) \
  72. static double realVariable;
  73. #define REAL_FIELD(realVariable, labelText, defaultStringValue) \
  74. UiForm_addReal (cmd -> d_uiform.get(), & realVariable, nullptr, labelText, defaultStringValue);
  75. #define REAL(realVariable, labelText, defaultStringValue) \
  76. REAL_VARIABLE (realVariable) \
  77. REAL_FIELD (realVariable, labelText, defaultStringValue)
  78. #define REAL_OR_UNDEFINED_VARIABLE(realVariable) \
  79. static double realVariable;
  80. #define REAL_OR_UNDEFINED_FIELD(realVariable, labelText, defaultStringValue) \
  81. UiForm_addRealOrUndefined (cmd -> d_uiform.get(), & realVariable, nullptr, labelText, defaultStringValue);
  82. #define REAL_OR_UNDEFINED(realVariable, labelText, defaultStringValue) \
  83. REAL_OR_UNDEFINED_VARIABLE (realVariable) \
  84. REAL_OR_UNDEFINED_FIELD (realVariable, labelText, defaultStringValue)
  85. #define POSITIVE_VARIABLE(realVariable) \
  86. static double realVariable;
  87. #define POSITIVE_FIELD(realVariable, labelText, defaultStringValue) \
  88. UiForm_addPositive (cmd -> d_uiform.get(), & realVariable, nullptr, labelText, defaultStringValue);
  89. #define POSITIVE(realVariable, labelText, defaultStringValue) \
  90. POSITIVE_VARIABLE (realVariable) \
  91. POSITIVE_FIELD (realVariable, labelText, defaultStringValue)
  92. #define INTEGER_VARIABLE(integerVariable) \
  93. static integer integerVariable;
  94. #define INTEGER_FIELD(integerVariable, labelText, defaultStringValue) \
  95. UiForm_addInteger (cmd -> d_uiform.get(), & integerVariable, nullptr, labelText, defaultStringValue);
  96. #define INTEGER(integerVariable, labelText, defaultStringValue) \
  97. INTEGER_VARIABLE (integerVariable) \
  98. INTEGER_FIELD (integerVariable, labelText, defaultStringValue)
  99. #define NATURAL_VARIABLE(integerVariable) \
  100. static integer integerVariable;
  101. #define NATURAL_FIELD(integerVariable, labelText, defaultStringValue) \
  102. UiForm_addNatural (cmd -> d_uiform.get(), & integerVariable, nullptr, labelText, defaultStringValue);
  103. #define NATURAL(integerVariable, labelText, defaultStringValue) \
  104. NATURAL_VARIABLE (integerVariable) \
  105. NATURAL_FIELD (integerVariable, labelText, defaultStringValue)
  106. #define WORD_VARIABLE(stringVariable) \
  107. static conststring32 stringVariable;
  108. #define WORD_FIELD(stringVariable, labelText, defaultStringValue) \
  109. UiForm_addWord (cmd -> d_uiform.get(), & stringVariable, nullptr, labelText, defaultStringValue);
  110. #define WORD(stringVariable, labelText, defaultStringValue) \
  111. WORD_VARIABLE (stringVariable) \
  112. WORD_FIELD (stringVariable, labelText, defaultStringValue)
  113. #define SENTENCE_VARIABLE(stringVariable) \
  114. static conststring32 stringVariable;
  115. #define SENTENCE_FIELD(stringVariable, labelText, defaultStringValue) \
  116. UiForm_addSentence (cmd -> d_uiform.get(), & stringVariable, nullptr, labelText, defaultStringValue);
  117. #define SENTENCE(stringVariable, labelText, defaultStringValue) \
  118. SENTENCE_VARIABLE (stringVariable) \
  119. SENTENCE_FIELD (stringVariable, labelText, defaultStringValue)
  120. #define COLOUR_VARIABLE(colourVariable) \
  121. static Graphics_Colour colourVariable;
  122. #define COLOUR_FIELD(colourVariable, labelText, defaultStringValue) \
  123. UiForm_addColour (cmd -> d_uiform.get(), & colourVariable, nullptr, labelText, defaultStringValue);
  124. #define COLOUR(colourVariable, labelText, defaultStringValue) \
  125. COLOUR_VARIABLE (colourVariable) \
  126. COLOUR_FIELD (colourVariable, labelText, defaultStringValue)
  127. #define CHANNEL_VARIABLE(integerVariable) \
  128. static integer integerVariable;
  129. #define CHANNEL_FIELD(integerVariable, labelText, defaultStringValue) \
  130. UiForm_addChannel (cmd -> d_uiform.get(), & integerVariable, nullptr, labelText, defaultStringValue);
  131. #define CHANNEL(integerVariable, labelText, defaultStringValue) \
  132. CHANNEL_VARIABLE (integerVariable) \
  133. CHANNEL_FIELD (integerVariable, labelText, defaultStringValue)
  134. #define BOOLEAN_VARIABLE(booleanVariable) \
  135. static bool booleanVariable;
  136. #define BOOLEAN_FIELD(booleanVariable, labelText, defaultBooleanValue) \
  137. UiForm_addBoolean (cmd -> d_uiform.get(), & booleanVariable, nullptr, labelText, defaultBooleanValue);
  138. #define BOOLEAN(booleanVariable, labelText, defaultBooleanValue) \
  139. BOOLEAN_VARIABLE (booleanVariable) \
  140. BOOLEAN_FIELD (booleanVariable, labelText, defaultBooleanValue)
  141. #define LABEL(labelText) \
  142. UiForm_addLabel (cmd -> d_uiform.get(), nullptr, labelText);
  143. #define MUTABLE_LABEL_VARIABLE(stringVariable) \
  144. static conststring32 stringVariable;
  145. #define MUTABLE_LABEL_FIELD(stringVariable, labelText) \
  146. UiForm_addLabel (cmd -> d_uiform.get(), & stringVariable, labelText);
  147. #define MUTABLE_LABEL(stringVariable, labelText) \
  148. MUTABLE_LABEL_VARIABLE (stringVariable) \
  149. MUTABLE_LABEL_FIELD (stringVariable, labelText)
  150. #define TEXTFIELD_VARIABLE(stringVariable) \
  151. static conststring32 stringVariable;
  152. #define TEXTFIELD_FIELD(stringVariable, labelText, defaultValue) \
  153. if (labelText != nullptr) UiForm_addLabel (cmd -> d_uiform.get(), nullptr, labelText); \
  154. UiForm_addText (cmd -> d_uiform.get(), & stringVariable, nullptr, U"", defaultValue);
  155. #define TEXTFIELD(stringVariable, labelText, defaultValue) \
  156. TEXTFIELD_VARIABLE (stringVariable) \
  157. TEXTFIELD_FIELD (stringVariable, labelText, defaultValue)
  158. #define RADIO_VARIABLE(optionVariable) \
  159. static int optionVariable;
  160. #define RADIO_FIELD(optionVariable, labelText, defaultValue) \
  161. _radio_ = UiForm_addRadio (cmd -> d_uiform.get(), & optionVariable, nullptr, nullptr, labelText, defaultValue, 1);
  162. #define RADIO(optionVariable, labelText, defaultValue) \
  163. RADIO_VARIABLE (optionVariable) \
  164. RADIO_FIELD (optionVariable, labelText, defaultValue)
  165. #define RADIOSTR(stringVariable, labelText, defaultValue) \
  166. static conststring32 stringVariable; \
  167. _radio_ = UiForm_addRadio (cmd -> d_uiform.get(), nullptr, & stringVariable, nullptr, labelText, defaultValue, 1);
  168. #define RADIOBUTTON(labelText) \
  169. UiRadio_addButton (_radio_, labelText);
  170. #define OPTIONMENU_VARIABLE(optionVariable) \
  171. static int optionVariable;
  172. #define OPTIONMENU_FIELD(optionVariable, labelText, defaultValue) \
  173. _radio_ = UiForm_addOptionMenu (cmd -> d_uiform.get(), & optionVariable, nullptr, nullptr, labelText, defaultValue, 1);
  174. #define OPTIONMENU(optionVariable, labelText, defaultValue) \
  175. OPTIONMENU_VARIABLE (optionVariable) \
  176. OPTIONMENU_FIELD(optionVariable, labelText, defaultValue)
  177. #define OPTIONMENUSTR(stringVariable, labelText, defaultValue) \
  178. static conststring32 stringVariable; \
  179. _radio_ = UiForm_addOptionMenu (cmd -> d_uiform.get(), nullptr, & stringVariable, nullptr, labelText, defaultValue, 1);
  180. #define OPTION(labelText) \
  181. UiOptionMenu_addButton (_radio_, labelText);
  182. #define RADIO_ENUM_VARIABLE(EnumeratedType, enumeratedVariable) \
  183. static enum EnumeratedType enumeratedVariable; \
  184. #define RADIO_ENUM_FIELD(EnumeratedType, enumeratedVariable, labelText, defaultValue) \
  185. {/* type checks */ \
  186. enum EnumeratedType _compilerTypeCheckDummy = defaultValue; \
  187. _compilerTypeCheckDummy = enumeratedVariable; \
  188. (void) _compilerTypeCheckDummy; \
  189. } \
  190. {/* scope */ \
  191. UiField _radio = UiForm_addRadio (cmd -> d_uiform.get(), (int *) & enumeratedVariable, nullptr, nullptr, labelText, \
  192. (int) defaultValue - (int) EnumeratedType::MIN + 1, (int) EnumeratedType::MIN); \
  193. for (int _ienum = (int) EnumeratedType::MIN; _ienum <= (int) EnumeratedType::MAX; _ienum ++) \
  194. UiRadio_addButton (_radio, EnumeratedType##_getText ((enum EnumeratedType) _ienum)); \
  195. }
  196. #define RADIO_ENUM(EnumeratedType, enumeratedVariable, labelText, defaultValue) \
  197. RADIO_ENUM_VARIABLE (EnumeratedType, enumeratedVariable) \
  198. RADIO_ENUM_FIELD (EnumeratedType, enumeratedVariable, labelText, defaultValue)
  199. #define OPTIONMENU_ENUM_VARIABLE(EnumeratedType, enumeratedVariable) \
  200. static enum EnumeratedType enumeratedVariable; \
  201. #define OPTIONMENU_ENUM_FIELD(EnumeratedType, enumeratedVariable, labelText, defaultValue) \
  202. {/* type checks */ \
  203. enum EnumeratedType _compilerTypeCheckDummy = defaultValue; \
  204. _compilerTypeCheckDummy = enumeratedVariable; \
  205. (void) _compilerTypeCheckDummy; \
  206. } \
  207. {/* scope */ \
  208. UiField _radio = UiForm_addOptionMenu (cmd -> d_uiform.get(), (int *) & enumeratedVariable, nullptr, nullptr, labelText, \
  209. (int) defaultValue - (int) EnumeratedType::MIN + 1, (int) EnumeratedType::MIN); \
  210. for (int _ienum = (int) EnumeratedType::MIN; _ienum <= (int) EnumeratedType::MAX; _ienum ++) \
  211. UiOptionMenu_addButton (_radio, EnumeratedType##_getText ((enum EnumeratedType) _ienum)); \
  212. }
  213. #define OPTIONMENU_ENUM(EnumeratedType, enumeratedVariable, labelText, defaultValue) \
  214. OPTIONMENU_ENUM_VARIABLE (EnumeratedType, enumeratedVariable) \
  215. OPTIONMENU_ENUM_FIELD (EnumeratedType, enumeratedVariable, labelText, defaultValue)
  216. #define LIST(integerVariable, labelText, strings, defaultValue) \
  217. static integer integerVariable; \
  218. UiForm_addList (cmd -> d_uiform.get(), & integerVariable, nullptr, nullptr, labelText, strings, defaultValue);
  219. /*
  220. Seven optional functions to change the content of a field on the basis of the current
  221. editor setting rather than on the basis of the factory default.
  222. They are to be called between EDITOR_OK and EDITOR_DO.
  223. */
  224. #define SET_REAL(realVariable, realValue) \
  225. UiForm_setReal (cmd -> d_uiform.get(), & realVariable, realValue);
  226. #define SET_INTEGER(integerVariable, integerValue) \
  227. UiForm_setInteger (cmd -> d_uiform.get(), & integerVariable, integerValue);
  228. #define SET_INTEGER_AS_STRING(integerVariable, stringValue) \
  229. UiForm_setIntegerAsString (cmd -> d_uiform.get(), & integerVariable, stringValue);
  230. #define SET_BOOLEAN(booleanVariable, booleanValue) \
  231. UiForm_setBoolean (cmd -> d_uiform.get(), & booleanVariable, booleanValue);
  232. #define SET_OPTION(optionVariable, optionValue) \
  233. UiForm_setOption (cmd -> d_uiform.get(), & optionVariable, optionValue);
  234. #define SET_STRING(stringVariable, stringValue) \
  235. UiForm_setString (cmd -> d_uiform.get(), & stringVariable, stringValue);
  236. #define SET_ENUM(enumeratedVariable, EnumeratedType, enumeratedValue) \
  237. enumeratedVariable = enumeratedValue /* type check */; \
  238. UiForm_setOption (cmd -> d_uiform.get(), (int *) & enumeratedVariable, (int) enumeratedValue - (int) EnumeratedType::MIN + 1);
  239. #define DIALOG cmd -> d_uiform
  240. #define EDITOR_FORM_SAVE(title, helpTitle) \
  241. if (! cmd -> d_uiform) { \
  242. cmd -> d_uiform = UiOutfile_createE (cmd, title, cmd -> itemTitle.get(), helpTitle); \
  243. } if (! _args_ && ! _sendingForm_ && ! _sendingString_) { char32 defaultName [300]; defaultName [0] = U'\0';
  244. #define EDITOR_DO_SAVE \
  245. (void) interpreter; \
  246. UiOutfile_do (cmd -> d_uiform.get(), defaultName); } else { MelderFile file; structMelderFile _file2 { }; \
  247. if (_args_) { \
  248. Melder_require (_narg_ == 1, \
  249. U"Command requires exactly 1 argument, the name of the file to write, instead of the given ", _narg_, U" arguments."); \
  250. Melder_require (_args_ [1]. which == Stackel_STRING, \
  251. U"The file name argument should be a string, not ", _args_ [1]. whichText(), U"."); \
  252. Melder_relativePathToFile (_args_ [1]. getString(), & _file2); \
  253. file = & _file2; \
  254. } else if (_sendingString_) { \
  255. Melder_relativePathToFile (_sendingString_, & _file2); \
  256. file = & _file2; \
  257. } else { \
  258. file = UiFile_getFile (cmd -> d_uiform.get()); \
  259. }
  260. #define EDITOR_FORM_READ(title, helpTitle) \
  261. if (! cmd -> d_uiform) { \
  262. cmd -> d_uiform = UiInfile_createE (cmd, title, cmd -> itemTitle.get(), helpTitle); \
  263. } if (! _args_ && ! _sendingForm_ && ! _sendingString_) {
  264. #define EDITOR_DO_READ \
  265. (void) interpreter; \
  266. UiInfile_do (cmd -> d_uiform.get()); } else { MelderFile file; structMelderFile _file2 { }; \
  267. if (_args_) { \
  268. Melder_require (_narg_ == 1, \
  269. U"Command requires exactly 1 argument, the name of the file to read, instead of the given ", _narg_, U" arguments."); \
  270. Melder_require (_args_ [1]. which == Stackel_STRING, \
  271. U"The file name argument should be a string, not ", _args_ [1]. whichText(), U"."); \
  272. Melder_relativePathToFile (_args_ [1]. getString(), & _file2); \
  273. file = & _file2; \
  274. } else if (_sendingString_) { \
  275. Melder_relativePathToFile (_sendingString_, & _file2); \
  276. file = & _file2; \
  277. } else { \
  278. file = UiFile_getFile (cmd -> d_uiform.get()); \
  279. }
  280. /* End of file EditorM.h */
  281. #endif