Non reinvents the DAW. Powerful enough to form a complete studio, fast and light enough to run on low-end hardware like the eeePC or Raspberry Pi, and so reliable that it can be used live https://non.tuxfamily.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
8.4KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2008 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include "Fl_Menu_Settings.H"
  19. #include <string.h>
  20. /* code to dump and restore (portions of) an Fl_Menu_ */
  21. #define MAX_PATH 1024
  22. void
  23. Fl_Menu_Settings::remove_ampersands ( char *str, int n )
  24. {
  25. char *d = str;
  26. char *s = str;
  27. while ( n-- )
  28. {
  29. if ( *s == '&' )
  30. {
  31. ++s;
  32. continue;
  33. }
  34. *(d++) = *(s++);
  35. }
  36. *d = '\0';
  37. }
  38. void
  39. Fl_Menu_Settings::indent ( FILE *fp, int n )
  40. {
  41. while ( n-- )
  42. fprintf( fp, "\t" );
  43. }
  44. int
  45. Fl_Menu_Settings::item_pathname_x ( char *path, int n, const Fl_Menu_Item *item )
  46. {
  47. int r = Fl_Menu_::item_pathname( path, n, item );
  48. remove_ampersands( path, n );
  49. return r;
  50. }
  51. /** dump options from submenu /menu/ of menubar /bar/ to file /fp/ */
  52. const Fl_Menu_Item *
  53. Fl_Menu_Settings::dump ( Fl_Menu_ *bar, const Fl_Menu_Item *menu, FILE *fp, int depth )
  54. {
  55. static char path[256];
  56. const Fl_Menu_Item *m = menu;
  57. for ( ; m->text; ++m )
  58. {
  59. bool is_radio = false;
  60. if ( m->flags & FL_SUBMENU )
  61. // if ( m->submenu() )
  62. {
  63. strcpy( path, m->text );
  64. remove_ampersands( path, strlen( path ) );
  65. indent( fp, depth );
  66. fprintf( fp, "%s\n", path );
  67. /* recurse */
  68. m = dump( bar, ++m, fp, depth + 1 );
  69. // ++m;
  70. // m = dump( bar, m->flags & FL_SUBMENU_POINTER ? (Fl_Menu_Item*) m->user_data() : m, fp, depth + 1 );
  71. if ( ! depth )
  72. break;
  73. else
  74. continue;
  75. }
  76. if ( m->radio() )
  77. is_radio = true;
  78. // bar->item_pathname( path, sizeof( path ) - 1, m );
  79. item_pathname_x( path, sizeof( path ) - 1, m );
  80. if ( m->flags & FL_MENU_TOGGLE || m->flags & FL_MENU_RADIO )
  81. {
  82. if ( ! is_radio )
  83. {
  84. indent( fp, depth );
  85. fprintf( fp, "%s\n", rindex( path, '/' ) + 1 );
  86. indent( fp, depth + 1 );
  87. fprintf( fp, "%s\n", m->flags & FL_MENU_VALUE ? "true" : "false" );
  88. }
  89. else if ( m->flags & FL_MENU_VALUE )
  90. {
  91. *rindex( path, '/' ) = '\0';
  92. indent( fp, depth );
  93. fprintf( fp, "%s\n", path + strlen( path ) + 1 );
  94. }
  95. }
  96. }
  97. return m;
  98. }
  99. /** dump menu to file /name/ starting at /item. */
  100. int
  101. Fl_Menu_Settings::dump ( const Fl_Menu_Item *item, const char *name )
  102. {
  103. FILE *fp = fopen( name, "w" );
  104. if ( ! fp )
  105. return false;
  106. dump( this, item, fp, 0 );
  107. fclose( fp );
  108. return true;
  109. }
  110. #define strlcat strncat
  111. /* taken from Fl_Menu_.cxx and modified to ignore hotkeys and case */
  112. const Fl_Menu_Item *
  113. Fl_Menu_Settings::find_item_x ( const char *name, const Fl_Menu_Item *item )
  114. {
  115. char menupath [ MAX_PATH ] = ""; // File/Export
  116. const Fl_Menu_Item *m = item ? item : menu();
  117. int depth = 0;
  118. while ( depth >= 0 )
  119. for ( ;m ; ++m )
  120. {
  121. if ( m->flags & FL_SUBMENU )
  122. {
  123. // IT'S A SUBMENU
  124. // we do not support searches through FL_SUBMENU_POINTER links
  125. if ( menupath[0] )
  126. strlcat( menupath, "/", sizeof( menupath ) );
  127. strlcat( menupath, m->label(), sizeof( menupath ) );
  128. remove_ampersands( menupath, strlen( menupath ) );
  129. if ( ! strcasecmp( menupath, name ) )
  130. return m;
  131. else
  132. {
  133. ++depth;
  134. continue;
  135. }
  136. }
  137. else
  138. {
  139. if ( ! m->label() )
  140. {
  141. // END OF SUBMENU? Pop back one level.
  142. char *ss = strrchr( menupath, '/' );
  143. if ( ss )
  144. *ss = 0;
  145. else
  146. menupath[0] = '\0';
  147. --depth;
  148. ++m;
  149. break;
  150. }
  151. // IT'S A MENU ITEM
  152. char itempath[ MAX_PATH ]; // eg. Edit/Copy
  153. strcpy( itempath, menupath );
  154. if ( itempath[0] )
  155. strlcat( itempath, "/", sizeof( itempath ) );
  156. strlcat( itempath, m->label(), sizeof( itempath ) );
  157. remove_ampersands( itempath, strlen( itempath ) );
  158. if ( !strcasecmp( itempath, name ) )
  159. return m;
  160. }
  161. }
  162. return ( Fl_Menu_Item * )0;
  163. }
  164. static void
  165. path_push ( char *path, const char *s )
  166. {
  167. strcat( path, s );
  168. strcat( path, "/" );
  169. }
  170. static void
  171. path_pop ( char *path )
  172. {
  173. char *s;
  174. int l = strlen( path );
  175. if ( ! l )
  176. return;
  177. if ( path[ l - 1 ] == '/' )
  178. path[ l - 1 ] = '\0';
  179. s = rindex( path, '/' );
  180. if ( s )
  181. *(s + 1) = '\0';
  182. else
  183. *path = '\0';
  184. }
  185. void
  186. Fl_Menu_Settings::load ( Fl_Menu_ *bar, const Fl_Menu_Item *item, FILE *fp, int depth, char *path, int pmax )
  187. {
  188. char line[256];
  189. while ( ! feof( fp ) )
  190. {
  191. *line = '\0';
  192. fgets( line, sizeof( line ), fp );
  193. if ( *line == '#' )
  194. continue;
  195. line[ strlen( line ) - 1 ] = '\0';
  196. int ld = strspn( line, "\t" );
  197. if ( ld > depth )
  198. {
  199. path_push( path, line + ld );
  200. ++depth;
  201. // load( bar, item, fp, depth + 1, path, pmax );
  202. /* */;
  203. }
  204. else if ( ld < depth )
  205. {
  206. /* we should know the path and the value now */
  207. // path_pop( path );
  208. *rindex( path, '/' ) = '\0';
  209. // printf( "%s = %s\n", path, path + strlen( path ) + 1 );
  210. const Fl_Menu_Item *it = find_item_x( path, item + 1 );
  211. if ( it && it->radio() ) /* radio button */
  212. {
  213. bar->picked( it );
  214. path_pop( path );
  215. }
  216. else /* toggle */
  217. {
  218. *rindex( path, '/' ) = '\0';
  219. if ( ( it = find_item_x( path, item + 1 ) ) && it->checkbox() )
  220. {
  221. int v = 0 == strcasecmp( "true", (path + strlen( path ) + 1 ) );
  222. if ( v != ( it->value() != 0 ) /* grr, FLTK */ )
  223. bar->picked( it );
  224. }
  225. }
  226. while ( ld < depth )
  227. {
  228. path_pop( path );
  229. depth--;
  230. }
  231. path_push( path, line + ld );
  232. }
  233. else /* d == depth */
  234. {
  235. /* doesn't apply? */
  236. }
  237. }
  238. }
  239. /** load settings from file /name/ into menu starting at /item */
  240. int
  241. Fl_Menu_Settings::load ( const Fl_Menu_Item *item, const char *name )
  242. {
  243. FILE *fp = fopen( name, "r" );
  244. if ( ! fp )
  245. return false;
  246. char path[ MAX_PATH ];
  247. path[0] = '\0';
  248. load( this, item, fp, 0, path, sizeof( path ) );
  249. fclose( fp );
  250. return true;
  251. }