
/****************************************************************************
 *
 * MODULE:       d.rast.edit
 * AUTHOR(S):    Chris Rewerts, Agricultural Engineering, Purdue University 
 *                    (original contributor)
 *               Roberto Flor <flor itc.it>, 
 *               Markus Neteler <neteler itc.it>, 
 *               Bernhard Reiter <bernhard intevation.de>, 
 *               Huidae Cho <grass4u gmail.com>, 
 *               Eric G. Miller <egm2 jps.net>, 
 *               Hamish Bowman <hamish_b yahoo.com>
 * PURPOSE:      interactive editing of cell values
 * COPYRIGHT:    (C) 1999-2007 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the file COPYING that comes with GRASS
 *               for details.
 *
 *****************************************************************************/
/*
 * Pre-CVS edit comments:
 * April 1991 Update:
 * March 1992 (add vector overlay, misc touchups) Update: May 1992   (removed
 * parser routine to ask about grid color, since that can be changed easily
 * enough with the menu. added a lookup of cell value ranges, and ability to
 * edit negative cell values. also more misc touchups)
 * 
 * d.rast.edit is a graphically interactive cell editor which allows the user
 * to display a cell layer on the graphics monitor and use the mouse cursor
 * to indicate which cell values to edit by pointing to cells displayed.
 * 
 * d.rast.edit determines the name and mapset of the cell layer displayed on the
 * monitor, then makes a copy of the layer's values in a temporary file.
 * Note: current window settings and masks are ignored when making the copy,
 * so that the view on the screen can be various "zoom" views to allow the
 * user to find individual cells. After editing, a new cell layer is created.
 * 
 */
#include <stdlib.h>
#include <string.h>
#define GLOBAL
#include <grass/glocale.h>
#include "edit.h"


int main(int argc, char **argv)
{
    struct GModule *module;
    struct Option *outmap;
    char temp[128], line[128];
    char *m;
    struct FPRange fp_range;

    /* Initialize the GIS calls */
    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("display, raster");
    module->description =
	_("Interactively edit cell values in a raster map.");

    outmap = G_define_standard_option(G_OPT_R_OUTPUT);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    /*
     * note: grid color used to be an option set with the help of the
     * parser, but it was more bother than worth. if black is not what
     * the user wants, they can reset it with the menu
     */

    strcpy(grid_color_name, DEFAULT_FG_COLOR);
    grid_color = D_translate_color(grid_color_name);

    if (R_open_driver() != 0)
	G_fatal_error("No graphics device selected");
    /*
     * if the monitor is divided into more than one window, find which is
     * the chosen, current one being used
     */

    if (D_get_cur_wind(temp))
	error(1, "No current graphics window");

    if (D_set_cur_wind(temp))
	error(1, "Current graphics window not available");

    /*
     * now that we have established what monitor window we are to work
     * with, find out the name of the cell layer currently displayed
     * there
     */

    D_get_cell_name(temp);
    if (*temp == 0 || strcmp(temp, "full_screen") == 0)
	error(1, "no map displayed in monitor.");

    m = G_find_cell2(temp, "");
    if (m == NULL) {
	sprintf(line, " %s - raster map not found\n", temp);
	error(1, line);
    }
    sscanf(m, "%s", orig_mapset);
    sscanf(temp, "%s", orig_name);

    fprintf(stderr, "\n\nName of original raster layer: [%s] in [%s]\n",
	    orig_name, orig_mapset);

    G_read_fp_range(orig_name, orig_mapset, &fp_range);
    G_get_fp_range_min_max(&fp_range, &min_value, &max_value);

    /* get the name for the new raster map to be created (the one we will edit) */
    strncpy(new_name, outmap->answer, 39);
    new_name[39] = '\0';

    /* get names straight  */
    sscanf(m, "%s", user_mapset);
    strcpy(current_name, orig_name);
    strcpy(current_mapset, orig_mapset);

    /*
     * we are not in the business of resampling the old file to a new
     * raster map with a different window setting, so when we make a copy
     * of the raster map to be edited, we will ignor the current window
     * and find out what the cell_head window is (and call that
     * "real_window")(the current_window could be anything, since the
     * user will probably have to use zoom to get a detailed view of what
     * they are editing).
     */

    G_get_cellhd(orig_name, orig_mapset, &real_window);

    real_nrows = real_window.rows;
    real_ncols = real_window.cols;

    main_menu();

    ext();
}

/*---------------------------------------------------------------*/
int do_edit(
	       /*
	        * called by the edit() routine. given a row and col location a value for the
	        * cell at that location, find that location in the temporary file and write
	        * in the new value
	        */
	       int c_row, int c_col, double new_value)
{

    int fd;
    long offset;
    DCELL c;

    fd = open(tempfile, 2);
    if (c_row > real_nrows - 1)
	error(0, "bad row number\n");
    if (c_col > real_ncols - 1)
	error(0, "bad col number\n");

    /* how many bytes into the temporary file will this value be? */
    offset = ((c_row * real_ncols) + c_col) * cellsize;

    lseek(fd, offset, 0);
    read(fd, &c, cellsize);

    lseek(fd, offset, 0);
    G_set_raster_value_d((void *)&c, new_value, map_type);
    if (write(fd, &c, cellsize) != cellsize)
	error(0, "was not able to write new value");

    close(fd);

    return 0;
}

/*------------------------------------------------------------------*/
int error(
	     /*
	      * some sort of function to deal with errors. code 0: print warning and
	      * continue code 1: print error message, close things down, and die
	      */
	     int code, char message[128]
    )
{

    /* int cellfd; */

    if (code == 0)
	fprintf(stderr, "\n\7WARNING: %s\n", message);
    else if (code == 1)
	fprintf(stderr, "\n\7ERROR: %s\n", message);
    if (code == 1) {
	/* G_unopen_cell(cellfd); */
	unlink(tempfile);
	R_close_driver();
	fprintf(stderr,
		"\n     +-------------------------------------------+\n");
	fprintf(stderr,
		"     |                d.rast.edit aborts         |\n");
	fprintf(stderr,
		"     +-------------------------------------------+\n\n");
	exit(-1);
    }

    return 0;
}

/*-------------------------------------------------------------*/

int ext(void)
{
    R_close_driver();
    fprintf(stderr, "\n     +-------------------------------------------+\n");
    fprintf(stderr, "     |                 d.rast.edit exits         |\n");
    fprintf(stderr, "     +-------------------------------------------+\n\n");
    exit(0);
}
