history.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*!
  2. * \file raster/history.c
  3. *
  4. * \brief Raster Library - History management
  5. *
  6. * (C) 2001-2009 GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author Original author CERL
  12. */
  13. #include <string.h>
  14. #include <grass/gis.h>
  15. #include <grass/raster.h>
  16. #include <grass/glocale.h>
  17. static void print_history_error(const char *, const char *, FILE *);
  18. /*!
  19. * \brief Read raster history file
  20. *
  21. * This routine reads the history file for the raster map <i>name</i>
  22. * in <i>mapset</i> into the <i>hist</i> structure.
  23. *
  24. * A diagnostic message is printed and -1 is returned if there is an
  25. * error reading the history file. Otherwise, 0 is returned.
  26. *
  27. * \param name map name
  28. * \param mapset mapset name
  29. * \param hist pointer to History structure which holds history info
  30. *
  31. * \return -1 on error
  32. * \return 0 on success
  33. */
  34. int Rast_read_history(const char *name, const char *mapset, struct History *hist)
  35. {
  36. FILE *fd;
  37. G_zero(hist, sizeof(struct History));
  38. fd = G_fopen_old("hist", name, mapset);
  39. if (!fd) {
  40. print_history_error(name, mapset, fd);
  41. return -1;
  42. }
  43. if (!G_getl(hist->mapid, sizeof(hist->mapid), fd)) {
  44. print_history_error(name, mapset, fd);
  45. return -1;
  46. }
  47. G_ascii_check(hist->mapid);
  48. if (!G_getl(hist->title, sizeof(hist->title), fd)) {
  49. print_history_error(name, mapset, fd);
  50. return -1;
  51. }
  52. G_ascii_check(hist->title);
  53. if (!G_getl(hist->mapset, sizeof(hist->mapset), fd)) {
  54. print_history_error(name, mapset, fd);
  55. return -1;
  56. }
  57. G_ascii_check(hist->mapset);
  58. if (!G_getl(hist->creator, sizeof(hist->creator), fd)) {
  59. print_history_error(name, mapset, fd);
  60. return -1;
  61. }
  62. G_ascii_check(hist->creator);
  63. if (!G_getl(hist->maptype, sizeof(hist->maptype), fd)) {
  64. print_history_error(name, mapset, fd);
  65. return -1;
  66. }
  67. G_ascii_check(hist->maptype);
  68. if (!G_getl(hist->datsrc_1, sizeof(hist->datsrc_1), fd)) {
  69. print_history_error(name, mapset, fd);
  70. return -1;
  71. }
  72. G_ascii_check(hist->datsrc_1);
  73. if (!G_getl(hist->datsrc_2, sizeof(hist->datsrc_2), fd)) {
  74. print_history_error(name, mapset, fd);
  75. return -1;
  76. }
  77. G_ascii_check(hist->datsrc_2);
  78. if (!G_getl(hist->keywrd, sizeof(hist->keywrd), fd)) {
  79. print_history_error(name, mapset, fd);
  80. return -1;
  81. }
  82. G_ascii_check(hist->keywrd);
  83. hist->edlinecnt = 0;
  84. while ((hist->edlinecnt < MAXEDLINES) &&
  85. (G_getl
  86. (hist->edhist[hist->edlinecnt], sizeof(hist->edhist[0]), fd))) {
  87. G_ascii_check(hist->edhist[hist->edlinecnt]);
  88. hist->edlinecnt++;
  89. }
  90. fclose(fd);
  91. return 0;
  92. }
  93. void print_history_error(const char *name, const char *mapset, FILE *fd)
  94. {
  95. if (fd != NULL)
  96. fclose(fd);
  97. if (mapset) {
  98. G_warning(_("Unable to get history information for <%s@%s>"),
  99. name, mapset);
  100. }
  101. else { /* write */
  102. G_warning(_("Unable to write history information for <%s>"), name);
  103. }
  104. }
  105. /*!
  106. * \brief Write raster history file
  107. *
  108. * This routine writes the history file for the raster map
  109. * <i>name</i> in the current mapset from the <i>hist</i> structure.
  110. *
  111. * A diagnostic message is printed and -1 is returned if there is an
  112. * error writing the history file. Otherwise, 0 is returned.
  113. *
  114. * <b>Note:</b> The <i>hist</i> structure should first be initialized
  115. * using Rast_short_history().
  116. *
  117. * \param name map name
  118. * \param[out] hist pointer to History structure which holds history info
  119. *
  120. * \return -1 on error
  121. * \return 0 on success
  122. */
  123. int Rast_write_history(const char *name, struct History *hist)
  124. {
  125. FILE *fd;
  126. int i;
  127. fd = G_fopen_new("hist", name);
  128. if (!fd) {
  129. print_history_error(name, NULL, fd);
  130. return -1;
  131. }
  132. fprintf(fd, "%s\n", hist->mapid);
  133. fprintf(fd, "%s\n", hist->title);
  134. fprintf(fd, "%s\n", hist->mapset);
  135. fprintf(fd, "%s\n", hist->creator);
  136. fprintf(fd, "%s\n", hist->maptype);
  137. fprintf(fd, "%s\n", hist->datsrc_1);
  138. fprintf(fd, "%s\n", hist->datsrc_2);
  139. fprintf(fd, "%s\n", hist->keywrd);
  140. for (i = 0; i < hist->edlinecnt; i++)
  141. fprintf(fd, "%s\n", hist->edhist[i]);
  142. fclose(fd);
  143. return 0;
  144. }
  145. /*!
  146. * \brief Initialize history structure
  147. *
  148. * This routine initializes the <i>hist</i> structure, recording the
  149. * date, user, module name and the raster map <i>name</i>
  150. * structure. The <i>type</i> is an anachronism from earlier versions
  151. * of GRASS and should be specified as "raster".
  152. *
  153. * <b>Note:</b> This routine only initializes the data structure. It
  154. * does not write the history file.
  155. *
  156. * \param name map name
  157. * \param type map type
  158. * \param hist pointer to History structure which holds history info
  159. */
  160. void Rast_short_history(const char *name, const char *type, struct History *hist)
  161. {
  162. strncpy(hist->mapid, G_date(), RECORD_LEN);
  163. strncpy(hist->title, name, RECORD_LEN);
  164. strncpy(hist->mapset, G_mapset(), RECORD_LEN);
  165. strncpy(hist->creator, G_whoami(), RECORD_LEN);
  166. strncpy(hist->maptype, type, RECORD_LEN);
  167. sprintf(hist->keywrd, _("generated by %s"), G_program_name());
  168. strcpy(hist->datsrc_1, "");
  169. strcpy(hist->datsrc_2, "");
  170. hist->edlinecnt = 0;
  171. }
  172. /*!
  173. * \brief Save command line to raster history structure
  174. *
  175. * This routine takes an existing (run Rast_short_history first() history
  176. * structure and adds the command line to the end of the comments
  177. * array, as cleaned & expanded by the parser.
  178. *
  179. * History file is limited to [80]x[50], as defined in include/gis.h
  180. *
  181. * - First version had for loops of [i][j] character assignments and ending
  182. * nulls, but using the string libraries is cleaner and less bug prone.
  183. * - Second version had white space detection, intelligent wrapping, and
  184. * indentation of continued lines, but this proved a pain in the neck for
  185. * things like r.patch which can have long strings without any
  186. * parser-acceptable breaks.
  187. * - This is MK-III, simplified, but that's good: it's cut & paste-able.
  188. *
  189. * Note: use Rast_write_history() to write the structure.
  190. *
  191. * Sample Usage:
  192. * \code
  193. * struct History history;
  194. * Rast_short_history(rasterfile, "raster", &history);
  195. * Rast_command_history(&history);
  196. * Rast_write_history(rasterfile, &history);
  197. * \endcode
  198. *
  199. * \param hist pointer to History structure which holds history info
  200. *
  201. * \return 0 on success
  202. * \return 1 on failure (history file full, no change)
  203. * \return 2 on failure (history file full, added as much as we could)
  204. */
  205. int Rast_command_history(struct History *hist)
  206. {
  207. int j, cmdlen;
  208. char *cmdlin;
  209. cmdlin = G_recreate_command();
  210. cmdlen = strlen(cmdlin);
  211. if (hist->edlinecnt > MAXEDLINES - 2) {
  212. G_warning(_("Not enough room in history file to record command line"));
  213. return 1;
  214. }
  215. if (hist->edlinecnt > 0) { /* add a blank line if preceding history exists */
  216. strcpy(hist->edhist[hist->edlinecnt], "");
  217. hist->edlinecnt++;
  218. }
  219. if (cmdlen < 70) { /* ie if it will fit on a single line */
  220. sprintf(hist->edhist[hist->edlinecnt], G_recreate_command());
  221. hist->edlinecnt++;
  222. }
  223. else { /* multi-line required */
  224. j = 0; /* j is the current position in the command line string */
  225. while ((cmdlen - j) > 70) {
  226. strncpy(hist->edhist[hist->edlinecnt], &cmdlin[j], 68);
  227. hist->edhist[hist->edlinecnt][68] = '\0';
  228. strcat(hist->edhist[hist->edlinecnt], "\\");
  229. j += 68;
  230. hist->edlinecnt++;
  231. if (hist->edlinecnt > MAXEDLINES - 2) {
  232. G_warning(_("Not enough room in history file for command line (truncated)"));
  233. return 2;
  234. }
  235. }
  236. if ((cmdlen - j) > 0) { /* ie anything left */
  237. strcpy(hist->edhist[hist->edlinecnt], &cmdlin[j]);
  238. hist->edlinecnt++;
  239. }
  240. }
  241. return 0;
  242. }