gimpconfigwriter.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /* LIBGIMP - The GIMP Library
  2. * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3. *
  4. * GimpConfigWriter
  5. * Copyright (C) 2003 Sven Neumann <sven@gimp.org>
  6. *
  7. * This library is free software: you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 3 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library. If not, see
  19. * <https://www.gnu.org/licenses/>.
  20. */
  21. #include "config.h"
  22. #include <string.h>
  23. #include <gio/gio.h>
  24. #ifdef G_OS_WIN32
  25. #include <gio/gwin32outputstream.h>
  26. #else
  27. #include <gio/gunixoutputstream.h>
  28. #endif
  29. #include "libgimpbase/gimpbase.h"
  30. #include "gimpconfigtypes.h"
  31. #include "gimpconfigwriter.h"
  32. #include "gimpconfig-iface.h"
  33. #include "gimpconfig-error.h"
  34. #include "gimpconfig-serialize.h"
  35. #include "gimpconfig-utils.h"
  36. #include "libgimp/libgimp-intl.h"
  37. /**
  38. * SECTION: gimpconfigwriter
  39. * @title: GimpConfigWriter
  40. * @short_description: Functions for writing config info to a file for
  41. * libgimpconfig.
  42. *
  43. * Functions for writing config info to a file for libgimpconfig.
  44. **/
  45. struct _GimpConfigWriter
  46. {
  47. gint ref_count;
  48. gboolean finished;
  49. GOutputStream *output;
  50. GFile *file;
  51. GError *error;
  52. GString *buffer;
  53. gboolean comment;
  54. gint depth;
  55. gint marker;
  56. };
  57. G_DEFINE_BOXED_TYPE (GimpConfigWriter, gimp_config_writer,
  58. gimp_config_writer_ref, gimp_config_writer_unref)
  59. static inline void gimp_config_writer_flush (GimpConfigWriter *writer);
  60. static inline void gimp_config_writer_newline (GimpConfigWriter *writer);
  61. static gboolean gimp_config_writer_close_output (GimpConfigWriter *writer,
  62. GError **error);
  63. static inline void
  64. gimp_config_writer_flush (GimpConfigWriter *writer)
  65. {
  66. GError *error = NULL;
  67. if (! writer->output)
  68. return;
  69. if (! g_output_stream_write_all (writer->output,
  70. writer->buffer->str,
  71. writer->buffer->len,
  72. NULL, NULL, &error))
  73. {
  74. g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
  75. _("Error writing to '%s': %s"),
  76. writer->file ?
  77. gimp_file_get_utf8_name (writer->file) : "output stream",
  78. error->message);
  79. g_clear_error (&error);
  80. }
  81. g_string_truncate (writer->buffer, 0);
  82. }
  83. static inline void
  84. gimp_config_writer_newline (GimpConfigWriter *writer)
  85. {
  86. gint i;
  87. g_string_append_c (writer->buffer, '\n');
  88. if (writer->comment)
  89. g_string_append_len (writer->buffer, "# ", 2);
  90. for (i = 0; i < writer->depth; i++)
  91. g_string_append_len (writer->buffer, " ", 4);
  92. }
  93. /**
  94. * gimp_config_writer_new_from_file:
  95. * @file: a #GFile
  96. * @atomic: if %TRUE the file is written atomically
  97. * @header: text to include as comment at the top of the file
  98. * @error: return location for errors
  99. *
  100. * Creates a new #GimpConfigWriter and sets it up to write to
  101. * @file. If @atomic is %TRUE, a temporary file is used to avoid
  102. * possible race conditions. The temporary file is then moved to @file
  103. * when the writer is closed.
  104. *
  105. * Returns: (nullable): a new #GimpConfigWriter or %NULL in case of an error
  106. *
  107. * Since: 2.10
  108. **/
  109. GimpConfigWriter *
  110. gimp_config_writer_new_from_file (GFile *file,
  111. gboolean atomic,
  112. const gchar *header,
  113. GError **error)
  114. {
  115. GimpConfigWriter *writer;
  116. GOutputStream *output;
  117. GFile *dir;
  118. g_return_val_if_fail (G_IS_FILE (file), NULL);
  119. g_return_val_if_fail (error == NULL || *error == NULL, NULL);
  120. dir = g_file_get_parent (file);
  121. if (dir && ! g_file_query_exists (dir, NULL))
  122. {
  123. if (! g_file_make_directory_with_parents (dir, NULL, error))
  124. g_prefix_error (error,
  125. _("Could not create directory '%s' for '%s': "),
  126. gimp_file_get_utf8_name (dir),
  127. gimp_file_get_utf8_name (file));
  128. }
  129. g_object_unref (dir);
  130. if (error && *error)
  131. return NULL;
  132. if (atomic)
  133. {
  134. output = G_OUTPUT_STREAM (g_file_replace (file,
  135. NULL, FALSE, G_FILE_CREATE_NONE,
  136. NULL, error));
  137. if (! output)
  138. g_prefix_error (error,
  139. _("Could not create temporary file for '%s': "),
  140. gimp_file_get_utf8_name (file));
  141. }
  142. else
  143. {
  144. output = G_OUTPUT_STREAM (g_file_replace (file,
  145. NULL, FALSE,
  146. G_FILE_CREATE_REPLACE_DESTINATION,
  147. NULL, error));
  148. }
  149. if (! output)
  150. return NULL;
  151. writer = g_slice_new0 (GimpConfigWriter);
  152. writer->ref_count = 1;
  153. writer->output = output;
  154. writer->file = g_object_ref (file);
  155. writer->buffer = g_string_new (NULL);
  156. if (header)
  157. {
  158. gimp_config_writer_comment (writer, header);
  159. gimp_config_writer_linefeed (writer);
  160. }
  161. return writer;
  162. }
  163. /**
  164. * gimp_config_writer_new_from_stream:
  165. * @output: a #GOutputStream
  166. * @header: text to include as comment at the top of the file
  167. * @error: return location for errors
  168. *
  169. * Creates a new #GimpConfigWriter and sets it up to write to
  170. * @output.
  171. *
  172. * Returns: (nullable): a new #GimpConfigWriter or %NULL in case of an error
  173. *
  174. * Since: 2.10
  175. **/
  176. GimpConfigWriter *
  177. gimp_config_writer_new_from_stream (GOutputStream *output,
  178. const gchar *header,
  179. GError **error)
  180. {
  181. GimpConfigWriter *writer;
  182. g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL);
  183. g_return_val_if_fail (error == NULL || *error == NULL, NULL);
  184. writer = g_slice_new0 (GimpConfigWriter);
  185. writer->ref_count = 1;
  186. writer->output = g_object_ref (output);
  187. writer->buffer = g_string_new (NULL);
  188. if (header)
  189. {
  190. gimp_config_writer_comment (writer, header);
  191. gimp_config_writer_linefeed (writer);
  192. }
  193. return writer;
  194. }
  195. /**
  196. * gimp_config_writer_new_from_fd:
  197. * @fd:
  198. *
  199. * Returns: (nullable): a new #GimpConfigWriter or %NULL in case of an error
  200. *
  201. * Since: 2.4
  202. **/
  203. GimpConfigWriter *
  204. gimp_config_writer_new_from_fd (gint fd)
  205. {
  206. GimpConfigWriter *writer;
  207. g_return_val_if_fail (fd > 0, NULL);
  208. writer = g_slice_new0 (GimpConfigWriter);
  209. writer->ref_count = 1;
  210. #ifdef G_OS_WIN32
  211. writer->output = g_win32_output_stream_new ((gpointer) fd, FALSE);
  212. #else
  213. writer->output = g_unix_output_stream_new (fd, FALSE);
  214. #endif
  215. writer->buffer = g_string_new (NULL);
  216. return writer;
  217. }
  218. /**
  219. * gimp_config_writer_new_from_string:
  220. * @string:
  221. *
  222. * Returns: (nullable): a new #GimpConfigWriter or %NULL in case of an error
  223. *
  224. * Since: 2.4
  225. **/
  226. GimpConfigWriter *
  227. gimp_config_writer_new_from_string (GString *string)
  228. {
  229. GimpConfigWriter *writer;
  230. g_return_val_if_fail (string != NULL, NULL);
  231. writer = g_slice_new0 (GimpConfigWriter);
  232. writer->ref_count = 1;
  233. writer->buffer = string;
  234. return writer;
  235. }
  236. /**
  237. * gimp_config_writer_ref:
  238. * @writer: #GimpConfigWriter to ref
  239. *
  240. * Adds a reference to a #GimpConfigWriter.
  241. *
  242. * Returns: the same @writer.
  243. *
  244. * Since: 3.0
  245. */
  246. GimpConfigWriter *
  247. gimp_config_writer_ref (GimpConfigWriter *writer)
  248. {
  249. g_return_val_if_fail (writer != NULL, NULL);
  250. writer->ref_count++;
  251. return writer;
  252. }
  253. /**
  254. * gimp_config_writer_unref:
  255. * @writer: #GimpConfigWriter to unref
  256. *
  257. * Unref a #GimpConfigWriter. If the reference count drops to zero, the
  258. * writer is freed.
  259. *
  260. * Note that at least one of the references has to be dropped using
  261. * gimp_config_writer_finish().
  262. *
  263. * Since: 3.0
  264. */
  265. void
  266. gimp_config_writer_unref (GimpConfigWriter *writer)
  267. {
  268. g_return_if_fail (writer != NULL);
  269. writer->ref_count--;
  270. if (writer->ref_count < 1)
  271. {
  272. if (! writer->finished)
  273. {
  274. GError *error = NULL;
  275. g_printerr ("%s: dropping last reference via unref(), you should "
  276. "call gimp_config_writer_finish()\n", G_STRFUNC);
  277. if (! gimp_config_writer_finish (writer, NULL, &error))
  278. {
  279. g_printerr ("%s: error on finishing writer: %s\n",
  280. G_STRFUNC, error->message);
  281. }
  282. }
  283. else
  284. {
  285. g_slice_free (GimpConfigWriter, writer);
  286. }
  287. }
  288. }
  289. /**
  290. * gimp_config_writer_comment_mode:
  291. * @writer: a #GimpConfigWriter
  292. * @enable: %TRUE to enable comment mode, %FALSE to disable it
  293. *
  294. * This function toggles whether the @writer should create commented
  295. * or uncommented output. This feature is used to generate the
  296. * system-wide installed gimprc that documents the default settings.
  297. *
  298. * Since comments have to start at the beginning of a line, this
  299. * function will insert a newline if necessary.
  300. *
  301. * Since: 2.4
  302. **/
  303. void
  304. gimp_config_writer_comment_mode (GimpConfigWriter *writer,
  305. gboolean enable)
  306. {
  307. g_return_if_fail (writer != NULL);
  308. g_return_if_fail (writer->finished == FALSE);
  309. if (writer->error)
  310. return;
  311. enable = (enable ? TRUE : FALSE);
  312. if (writer->comment == enable)
  313. return;
  314. writer->comment = enable;
  315. if (enable)
  316. {
  317. if (writer->buffer->len == 0)
  318. g_string_append_len (writer->buffer, "# ", 2);
  319. else
  320. gimp_config_writer_newline (writer);
  321. }
  322. }
  323. /**
  324. * gimp_config_writer_open:
  325. * @writer: a #GimpConfigWriter
  326. * @name: name of the element to open
  327. *
  328. * This function writes the opening parenthesis followed by @name.
  329. * It also increases the indentation level and sets a mark that
  330. * can be used by gimp_config_writer_revert().
  331. *
  332. * Since: 2.4
  333. **/
  334. void
  335. gimp_config_writer_open (GimpConfigWriter *writer,
  336. const gchar *name)
  337. {
  338. g_return_if_fail (writer != NULL);
  339. g_return_if_fail (writer->finished == FALSE);
  340. g_return_if_fail (name != NULL);
  341. if (writer->error)
  342. return;
  343. /* store the current buffer length so we can revert to this state */
  344. writer->marker = writer->buffer->len;
  345. if (writer->depth > 0)
  346. gimp_config_writer_newline (writer);
  347. writer->depth++;
  348. g_string_append_printf (writer->buffer, "(%s", name);
  349. }
  350. /**
  351. * gimp_config_writer_print:
  352. * @writer: a #GimpConfigWriter
  353. * @string: a string to write
  354. * @len: number of bytes from @string or -1 if @string is NUL-terminated.
  355. *
  356. * Appends a space followed by @string to the @writer. Note that string
  357. * must not contain any special characters that might need to be escaped.
  358. *
  359. * Since: 2.4
  360. **/
  361. void
  362. gimp_config_writer_print (GimpConfigWriter *writer,
  363. const gchar *string,
  364. gint len)
  365. {
  366. g_return_if_fail (writer != NULL);
  367. g_return_if_fail (writer->finished == FALSE);
  368. g_return_if_fail (len == 0 || string != NULL);
  369. if (writer->error)
  370. return;
  371. if (len < 0)
  372. len = strlen (string);
  373. if (len)
  374. {
  375. g_string_append_c (writer->buffer, ' ');
  376. g_string_append_len (writer->buffer, string, len);
  377. }
  378. }
  379. /**
  380. * gimp_config_writer_printf: (skip)
  381. * @writer: a #GimpConfigWriter
  382. * @format: a format string as described for g_strdup_printf().
  383. * @...: list of arguments according to @format
  384. *
  385. * A printf-like function for #GimpConfigWriter.
  386. *
  387. * Since: 2.4
  388. **/
  389. void
  390. gimp_config_writer_printf (GimpConfigWriter *writer,
  391. const gchar *format,
  392. ...)
  393. {
  394. gchar *buffer;
  395. va_list args;
  396. g_return_if_fail (writer != NULL);
  397. g_return_if_fail (writer->finished == FALSE);
  398. g_return_if_fail (format != NULL);
  399. if (writer->error)
  400. return;
  401. va_start (args, format);
  402. buffer = g_strdup_vprintf (format, args);
  403. va_end (args);
  404. g_string_append_c (writer->buffer, ' ');
  405. g_string_append (writer->buffer, buffer);
  406. g_free (buffer);
  407. }
  408. /**
  409. * gimp_config_writer_string:
  410. * @writer: a #GimpConfigWriter
  411. * @string: a NUL-terminated string
  412. *
  413. * Writes a string value to @writer. The @string is quoted and special
  414. * characters are escaped.
  415. *
  416. * Since: 2.4
  417. **/
  418. void
  419. gimp_config_writer_string (GimpConfigWriter *writer,
  420. const gchar *string)
  421. {
  422. g_return_if_fail (writer != NULL);
  423. g_return_if_fail (writer->finished == FALSE);
  424. if (writer->error)
  425. return;
  426. g_string_append_c (writer->buffer, ' ');
  427. gimp_config_string_append_escaped (writer->buffer, string);
  428. }
  429. /**
  430. * gimp_config_writer_identifier:
  431. * @writer: a #GimpConfigWriter
  432. * @identifier: a NUL-terminated string
  433. *
  434. * Writes an identifier to @writer. The @string is *not* quoted and special
  435. * characters are *not* escaped.
  436. *
  437. * Since: 2.4
  438. **/
  439. void
  440. gimp_config_writer_identifier (GimpConfigWriter *writer,
  441. const gchar *identifier)
  442. {
  443. g_return_if_fail (writer != NULL);
  444. g_return_if_fail (writer->finished == FALSE);
  445. g_return_if_fail (identifier != NULL);
  446. if (writer->error)
  447. return;
  448. g_string_append_printf (writer->buffer, " %s", identifier);
  449. }
  450. /**
  451. * gimp_config_writer_data:
  452. * @writer: a #GimpConfigWriter
  453. * @length:
  454. * @data:
  455. *
  456. * Since: 2.4
  457. **/
  458. void
  459. gimp_config_writer_data (GimpConfigWriter *writer,
  460. gint length,
  461. const guint8 *data)
  462. {
  463. gint i;
  464. g_return_if_fail (writer != NULL);
  465. g_return_if_fail (writer->finished == FALSE);
  466. g_return_if_fail (length >= 0);
  467. g_return_if_fail (data != NULL || length == 0);
  468. if (writer->error)
  469. return;
  470. g_string_append (writer->buffer, " \"");
  471. for (i = 0; i < length; i++)
  472. {
  473. if (g_ascii_isalpha (data[i]))
  474. g_string_append_c (writer->buffer, data[i]);
  475. else
  476. g_string_append_printf (writer->buffer, "\\%o", data[i]);
  477. }
  478. g_string_append (writer->buffer, "\"");
  479. }
  480. /**
  481. * gimp_config_writer_revert:
  482. * @writer: a #GimpConfigWriter
  483. *
  484. * Reverts all changes to @writer that were done since the last call
  485. * to gimp_config_writer_open(). This can only work if you didn't call
  486. * gimp_config_writer_close() yet.
  487. *
  488. * Since: 2.4
  489. **/
  490. void
  491. gimp_config_writer_revert (GimpConfigWriter *writer)
  492. {
  493. g_return_if_fail (writer != NULL);
  494. g_return_if_fail (writer->finished == FALSE);
  495. if (writer->error)
  496. return;
  497. g_return_if_fail (writer->depth > 0);
  498. g_return_if_fail (writer->marker != -1);
  499. g_string_truncate (writer->buffer, writer->marker);
  500. writer->depth--;
  501. writer->marker = -1;
  502. }
  503. /**
  504. * gimp_config_writer_close:
  505. * @writer: a #GimpConfigWriter
  506. *
  507. * Closes an element opened with gimp_config_writer_open().
  508. *
  509. * Since: 2.4
  510. **/
  511. void
  512. gimp_config_writer_close (GimpConfigWriter *writer)
  513. {
  514. g_return_if_fail (writer != NULL);
  515. g_return_if_fail (writer->finished == FALSE);
  516. if (writer->error)
  517. return;
  518. g_return_if_fail (writer->depth > 0);
  519. g_string_append_c (writer->buffer, ')');
  520. if (--writer->depth == 0)
  521. {
  522. g_string_append_c (writer->buffer, '\n');
  523. gimp_config_writer_flush (writer);
  524. }
  525. }
  526. /**
  527. * gimp_config_writer_finish:
  528. * @writer: a #GimpConfigWriter
  529. * @footer: text to include as comment at the bottom of the file
  530. * @error: return location for possible errors
  531. *
  532. * This function finishes the work of @writer and unrefs it
  533. * afterwards. It closes all open elements, appends an optional
  534. * comment and releases all resources allocated by @writer.
  535. *
  536. * Using any function except gimp_config_writer_ref() or
  537. * gimp_config_writer_unref() after this function is forbidden
  538. * and will trigger warnings.
  539. *
  540. * Returns: %TRUE if everything could be successfully written,
  541. * %FALSE otherwise
  542. *
  543. * Since: 2.4
  544. **/
  545. gboolean
  546. gimp_config_writer_finish (GimpConfigWriter *writer,
  547. const gchar *footer,
  548. GError **error)
  549. {
  550. gboolean success = TRUE;
  551. g_return_val_if_fail (writer != NULL, FALSE);
  552. g_return_val_if_fail (writer->finished == FALSE, FALSE);
  553. g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
  554. if (writer->depth < 0)
  555. {
  556. g_warning ("gimp_config_writer_finish: depth < 0 !!");
  557. }
  558. else
  559. {
  560. while (writer->depth)
  561. gimp_config_writer_close (writer);
  562. }
  563. if (footer)
  564. {
  565. gimp_config_writer_linefeed (writer);
  566. gimp_config_writer_comment (writer, footer);
  567. }
  568. if (writer->output)
  569. {
  570. success = gimp_config_writer_close_output (writer, error);
  571. g_clear_object (&writer->file);
  572. g_string_free (writer->buffer, TRUE);
  573. writer->buffer = NULL;
  574. }
  575. if (writer->error)
  576. {
  577. if (error && *error == NULL)
  578. g_propagate_error (error, writer->error);
  579. else
  580. g_clear_error (&writer->error);
  581. success = FALSE;
  582. }
  583. writer->finished = TRUE;
  584. gimp_config_writer_unref (writer);
  585. return success;
  586. }
  587. void
  588. gimp_config_writer_linefeed (GimpConfigWriter *writer)
  589. {
  590. g_return_if_fail (writer != NULL);
  591. g_return_if_fail (writer->finished == FALSE);
  592. if (writer->error)
  593. return;
  594. if (writer->output && writer->buffer->len == 0 && !writer->comment)
  595. {
  596. GError *error = NULL;
  597. if (! g_output_stream_write_all (writer->output, "\n", 1,
  598. NULL, NULL, &error))
  599. {
  600. g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
  601. _("Error writing to '%s': %s"),
  602. writer->file ?
  603. gimp_file_get_utf8_name (writer->file) : "output stream",
  604. error->message);
  605. g_clear_error (&error);
  606. }
  607. }
  608. else
  609. {
  610. gimp_config_writer_newline (writer);
  611. }
  612. }
  613. /**
  614. * gimp_config_writer_comment:
  615. * @writer: a #GimpConfigWriter
  616. * @comment: the comment to write (ASCII only)
  617. *
  618. * Appends the @comment to @str and inserts linebreaks and hash-marks to
  619. * format it as a comment. Note that this function does not handle non-ASCII
  620. * characters.
  621. *
  622. * Since: 2.4
  623. **/
  624. void
  625. gimp_config_writer_comment (GimpConfigWriter *writer,
  626. const gchar *comment)
  627. {
  628. const gchar *s;
  629. gboolean comment_mode;
  630. gint i, len, space;
  631. #define LINE_LENGTH 75
  632. g_return_if_fail (writer != NULL);
  633. g_return_if_fail (writer->finished == FALSE);
  634. if (writer->error)
  635. return;
  636. g_return_if_fail (writer->depth == 0);
  637. if (!comment)
  638. return;
  639. comment_mode = writer->comment;
  640. gimp_config_writer_comment_mode (writer, TRUE);
  641. len = strlen (comment);
  642. while (len > 0)
  643. {
  644. for (s = comment, i = 0, space = 0;
  645. *s != '\n' && (i <= LINE_LENGTH || space == 0) && i < len;
  646. s++, i++)
  647. {
  648. if (g_ascii_isspace (*s))
  649. space = i;
  650. }
  651. if (i > LINE_LENGTH && space && *s != '\n')
  652. i = space;
  653. g_string_append_len (writer->buffer, comment, i);
  654. i++;
  655. comment += i;
  656. len -= i;
  657. if (len > 0)
  658. gimp_config_writer_newline (writer);
  659. }
  660. gimp_config_writer_comment_mode (writer, comment_mode);
  661. gimp_config_writer_newline (writer);
  662. if (writer->depth == 0)
  663. gimp_config_writer_flush (writer);
  664. #undef LINE_LENGTH
  665. }
  666. static gboolean
  667. gimp_config_writer_close_output (GimpConfigWriter *writer,
  668. GError **error)
  669. {
  670. g_return_val_if_fail (writer->output != NULL, FALSE);
  671. if (writer->error)
  672. {
  673. GCancellable *cancellable = g_cancellable_new ();
  674. /* Cancel the overwrite initiated by g_file_replace(). */
  675. g_cancellable_cancel (cancellable);
  676. g_output_stream_close (writer->output, cancellable, NULL);
  677. g_object_unref (cancellable);
  678. g_clear_object (&writer->output);
  679. return FALSE;
  680. }
  681. if (writer->file)
  682. {
  683. GError *my_error = NULL;
  684. if (! g_output_stream_close (writer->output, NULL, &my_error))
  685. {
  686. g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
  687. _("Error writing '%s': %s"),
  688. gimp_file_get_utf8_name (writer->file),
  689. my_error->message);
  690. g_clear_error (&my_error);
  691. g_clear_object (&writer->output);
  692. return FALSE;
  693. }
  694. }
  695. g_clear_object (&writer->output);
  696. return TRUE;
  697. }