GRASS Programmer's Manual  6.4.2(2012)
command.c
Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003  *
00004  * MODULE:       driver
00005  * AUTHOR(S):    Glynn Clements <glynn gclements.plus.com> (original contributor)
00006  *               Jachym Cepicky <jachym les-ejk.cz>
00007  * PURPOSE:      
00008  * COPYRIGHT:    (C) 2006-2007 by the GRASS Development Team
00009  *
00010  *               This program is free software under the GNU General Public
00011  *               License (>=v2). Read the file COPYING that comes with GRASS
00012  *               for details.
00013  *
00014  *****************************************************************************/
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <stdlib.h>
00018 #include <signal.h>
00019 #include <setjmp.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022 #include <sys/time.h>
00023 #include <sys/types.h>
00024 
00025 #include <grass/gis.h>
00026 #include <grass/graphics.h>
00027 #include "driverlib.h"
00028 #include "driver.h"
00029 #include "pad.h"
00030 #include <grass/glocale.h>
00031 
00032 #define REC(a,b)    if ((ateof=rec((a),(b)))) break
00033 #define RECTEXT(x,s)  if ((ateof=rectext(&x,&s))) break
00034 #define SEND(a,b)   _send((a),(b))
00035 #define SENDTEXT(x)  sendtext((x))
00036 
00037 static int rec(void *, int);
00038 static int rectext(char **, int *);
00039 static int _send(const void *, int);
00040 static int sendtext(const char *);
00041 static int RESULT(int);
00042 
00043 static int _wfd;
00044 static int _rfd;
00045 
00046 static char inbuf[4096];
00047 static int n_read;
00048 static int atbuf;
00049 
00050 static char current_command;
00051 
00052 static int ateof;
00053 
00054 static PAD *curpad;             /* current selected pad */
00055 
00056 static unsigned char *blua;
00057 static unsigned char *grna;
00058 static unsigned char *reda;
00059 static unsigned char *nula;
00060 static int blu_alloc;
00061 static int grn_alloc;
00062 static int red_alloc;
00063 static int nul_alloc;
00064 
00065 static int *xarray;
00066 static int *yarray;
00067 static int n_xarray;
00068 static int n_yarray;
00069 
00070 static char lc;
00071 
00072 static void *xalloc(void *buf, int *cur, int new, int len)
00073 {
00074     if (*cur < new) {
00075         buf = G_realloc(buf, (size_t) new * len);
00076         *cur = new;
00077     }
00078 
00079     return buf;
00080 }
00081 
00082 void command_init(int rfd, int wfd)
00083 {
00084     _rfd = rfd;
00085     _wfd = wfd;
00086 
00087     atbuf = n_read = 0;
00088     current_command = 0;
00089 
00090     ateof = 0;
00091 }
00092 
00093 int LIB_command_get_input(void)
00094 {
00095     return _rfd;
00096 }
00097 
00098 static void send_fonts(void (*func) (char ***, int *))
00099 {
00100     char **fonts;
00101     int num_fonts;
00102     int i;
00103 
00104     (*func) (&fonts, &num_fonts);
00105     SEND(&num_fonts, sizeof num_fonts);
00106     for (i = 0; i < num_fonts; i++)
00107         SENDTEXT(fonts[i]);
00108     free_font_list(fonts, num_fonts);
00109 }
00110 
00111 int process_command(int c)
00112 {
00113     static char *name;
00114     static int name_size;
00115     static char *text;
00116     static int text_size;
00117 
00118     int t, b, l, r, ret;
00119     int x, y;
00120     unsigned char red, grn, blu;
00121     int number;
00122     int index;
00123     int button;
00124     float wx;
00125     ITEM *item;
00126     LIST *list;
00127     PAD *pad;
00128     unsigned char ch;
00129     int src[2][2], dst[2][2];
00130 
00131     switch (c) {
00132     case BEGIN:
00133         ch = 0;
00134         for (index = -10; index < BEGIN_SYNC_COUNT; index++)
00135             SEND(&ch, 1);
00136         ch = COMMAND_ESC;
00137         SEND(&ch, 1);
00138         break;
00139     case RESPOND:
00140         COM_Respond();
00141         SEND(&ch, 1);
00142         break;
00143     case GET_NUM_COLORS:
00144         COM_Number_of_colors(&index);
00145         SEND(&index, sizeof index);
00146         break;
00147     case STANDARD_COLOR:
00148         REC(&index, sizeof index);
00149         COM_Standard_color(index);
00150         break;
00151     case RGB_COLOR:
00152         REC(&red, sizeof red);
00153         REC(&grn, sizeof grn);
00154         REC(&blu, sizeof blu);
00155         COM_Color_RGB(red, grn, blu);
00156         break;
00157     case LINE_WIDTH:
00158         REC(&number, sizeof number);
00159         COM_Line_width(number);
00160         break;
00161     case CONT_ABS:
00162         REC(&x, sizeof x);
00163         REC(&y, sizeof y);
00164         COM_Cont_abs(x, y);
00165         break;
00166     case CONT_REL:
00167         REC(&x, sizeof x);
00168         REC(&y, sizeof y);
00169         COM_Cont_rel(x, y);
00170         break;
00171     case BOX_ABS:
00172         REC(&l, sizeof l);
00173         REC(&t, sizeof t);
00174         REC(&r, sizeof r);
00175         REC(&b, sizeof b);
00176         COM_Box_abs(l, t, r, b);
00177         break;
00178     case BOX_REL:
00179         REC(&l, sizeof l);
00180         REC(&t, sizeof t);
00181         COM_Box_rel(l, t);
00182         break;
00183     case ERASE:
00184         COM_Erase();
00185         break;
00186     case GET_LOCATION_WITH_BOX:
00187         REC(&t, sizeof t);
00188         REC(&b, sizeof b);
00189         REC(&x, sizeof x);
00190         REC(&y, sizeof y);
00191         COM_Get_location_with_box(t, b, &x, &y, &button);
00192         SEND(&x, sizeof x);
00193         SEND(&y, sizeof y);
00194         SEND(&button, sizeof button);
00195         break;
00196     case GET_LOCATION_WITH_LINE:
00197         REC(&t, sizeof t);
00198         REC(&b, sizeof b);
00199         REC(&x, sizeof x);
00200         REC(&y, sizeof y);
00201         COM_Get_location_with_line(t, b, &x, &y, &button);
00202         SEND(&x, sizeof x);
00203         SEND(&y, sizeof y);
00204         SEND(&button, sizeof button);
00205         break;
00206     case GET_LOCATION_WITH_POINTER:
00207         REC(&x, sizeof x);
00208         REC(&y, sizeof y);
00209         REC(&button, sizeof button);
00210         COM_Get_location_with_pointer(&x, &y, &button);
00211         SEND(&x, sizeof x);
00212         SEND(&y, sizeof y);
00213         SEND(&button, sizeof button);
00214         break;
00215     case GRAPH_CLOSE:
00216         COM_Graph_close();
00217         exit(0);
00218     case MOVE_ABS:
00219         REC(&x, sizeof x);
00220         REC(&y, sizeof y);
00221         COM_Move_abs(x, y);
00222         break;
00223     case MOVE_REL:
00224         REC(&x, sizeof x);
00225         REC(&y, sizeof y);
00226         COM_Move_rel(x, y);
00227         break;
00228     case BITMAP:
00229         REC(&x, sizeof x);
00230         REC(&y, sizeof y);
00231         REC(&index, sizeof index);
00232         blua =
00233             (unsigned char *)xalloc(blua, &blu_alloc, x * y, sizeof(*blua));
00234         REC(blua, x * y * sizeof(char));
00235         COM_Bitmap(x, y, index, blua);
00236         break;
00237     case BEGIN_SCALED_RASTER:
00238         REC(&index, sizeof(int));
00239         REC(&src[0][0], 4 * sizeof(int));
00240         REC(&dst[0][0], 4 * sizeof(int));
00241         COM_begin_scaled_raster(index, src, dst);
00242         break;
00243     case SCALED_RASTER:
00244         REC(&x, sizeof x);
00245         REC(&y, sizeof y);
00246         reda = (unsigned char *)xalloc(reda, &red_alloc, x, sizeof(*reda));
00247         grna = (unsigned char *)xalloc(grna, &grn_alloc, x, sizeof(*grna));
00248         blua = (unsigned char *)xalloc(blua, &blu_alloc, x, sizeof(*blua));
00249         nula = (unsigned char *)xalloc(nula, &nul_alloc, x, sizeof(*nula));
00250         REC(reda, x * sizeof(char));
00251         REC(grna, x * sizeof(char));
00252         REC(blua, x * sizeof(char));
00253         REC(nula, x * sizeof(char));
00254         REC(&t, sizeof t);
00255         ret = COM_scaled_raster(x, y, reda, grna, blua, t ? nula : NULL);
00256         SEND(&ret, sizeof ret);
00257         break;
00258     case END_SCALED_RASTER:
00259         COM_end_scaled_raster();
00260         break;
00261     case POLYGON_ABS:
00262         REC(&number, sizeof number);
00263         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00264         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00265         REC(xarray, number * sizeof(xarray[0]));
00266         REC(yarray, number * sizeof(yarray[0]));
00267         COM_Polygon_abs(xarray, yarray, number);
00268         break;
00269     case POLYGON_REL:
00270         REC(&number, sizeof number);
00271         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00272         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00273         REC(xarray, number * sizeof(xarray[0]));
00274         REC(yarray, number * sizeof(yarray[0]));
00275         COM_Polygon_rel(xarray, yarray, number);
00276         break;
00277     case POLYLINE_ABS:
00278         REC(&number, sizeof number);
00279         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00280         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00281         REC(xarray, number * sizeof(xarray[0]));
00282         REC(yarray, number * sizeof(yarray[0]));
00283         COM_Polyline_abs(xarray, yarray, number);
00284         break;
00285     case POLYLINE_REL:
00286         REC(&number, sizeof number);
00287         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00288         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00289         REC(xarray, number * sizeof(xarray[0]));
00290         REC(yarray, number * sizeof(yarray[0]));
00291         COM_Polyline_rel(xarray, yarray, number);
00292         break;
00293     case POLYDOTS_ABS:
00294         REC(&number, sizeof number);
00295         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00296         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00297         REC(xarray, number * sizeof(xarray[0]));
00298         REC(yarray, number * sizeof(yarray[0]));
00299         COM_Polydots_abs(xarray, yarray, number);
00300         break;
00301     case POLYDOTS_REL:
00302         REC(&number, sizeof number);
00303         xarray = (int *)xalloc(xarray, &n_xarray, number, sizeof(*xarray));
00304         yarray = (int *)xalloc(yarray, &n_yarray, number, sizeof(*yarray));
00305         REC(xarray, number * sizeof(xarray[0]));
00306         REC(yarray, number * sizeof(yarray[0]));
00307         COM_Polydots_rel(xarray, yarray, number);
00308         break;
00309     case SCREEN_LEFT:
00310         COM_Screen_left(&index);
00311         SEND(&index, sizeof index);
00312         break;
00313     case SCREEN_RITE:
00314         COM_Screen_rite(&index);
00315         SEND(&index, sizeof index);
00316         break;
00317     case SCREEN_BOT:
00318         COM_Screen_bot(&index);
00319         SEND(&index, sizeof index);
00320         break;
00321     case SCREEN_TOP:
00322         COM_Screen_top(&index);
00323         SEND(&index, sizeof index);
00324         break;
00325     case SET_WINDOW:
00326         REC(&t, sizeof t);
00327         REC(&b, sizeof b);
00328         REC(&l, sizeof l);
00329         REC(&r, sizeof r);
00330         COM_Set_window(t, b, l, r);
00331         break;
00332     case GET_TEXT_BOX:
00333         RECTEXT(text, text_size);
00334         COM_Get_text_box(text, &t, &b, &l, &r);
00335         SEND(&t, sizeof t);
00336         SEND(&b, sizeof b);
00337         SEND(&l, sizeof l);
00338         SEND(&r, sizeof r);
00339         break;
00340     case FONT:
00341         RECTEXT(text, text_size);
00342         COM_Font_get(text);
00343         break;
00344     case CHARSET:
00345         RECTEXT(text, text_size);
00346         COM_Font_init_charset(text);
00347         break;
00348     case FONT_LIST:
00349         send_fonts(COM_Font_list);
00350         break;
00351     case FONT_INFO:
00352         send_fonts(COM_Font_info);
00353         break;
00354     case TEXT:
00355         RECTEXT(text, text_size);
00356         COM_Text(text);
00357         break;
00358     case TEXT_SIZE:
00359         REC(&x, sizeof x);
00360         REC(&y, sizeof y);
00361         COM_Text_size(x, y);
00362         break;
00363     case TEXT_ROTATION:
00364         REC(&wx, sizeof wx);
00365         COM_Text_rotation(wx);
00366         break;
00367     case PANEL_SAVE:
00368         RECTEXT(text, text_size);
00369         REC(&t, sizeof t);
00370         REC(&b, sizeof b);
00371         REC(&l, sizeof l);
00372         REC(&r, sizeof r);
00373         COM_Panel_save(text, t, b, l, r);
00374         break;
00375     case PANEL_RESTORE:
00376         RECTEXT(text, text_size);
00377         COM_Panel_restore(text);
00378         break;
00379     case PANEL_DELETE:
00380         RECTEXT(text, text_size);
00381         COM_Panel_delete(text);
00382         break;
00383     case PAD_CREATE:
00384         RECTEXT(text, text_size);
00385         if (*text == 0)         /* this is scratch pad */
00386             RESULT(OK);
00387         else if (find_pad(text) != NULL)
00388             RESULT(DUPLICATE);  /* duplicate pad */
00389         else if (create_pad(text))
00390             RESULT(OK);
00391         else
00392             RESULT(NO_MEMORY);
00393         break;
00394 
00395     case PAD_CURRENT:
00396         if (curpad == NULL) {
00397             RESULT(NO_CUR_PAD);
00398             SENDTEXT("");
00399         }
00400         else {
00401             RESULT(OK);
00402             SENDTEXT(curpad->name);
00403         }
00404         break;
00405 
00406     case PAD_DELETE:
00407         if (curpad == NULL)
00408             RESULT(NO_CUR_PAD);
00409         else if (*curpad->name == 0)
00410             RESULT(ILLEGAL);
00411         else {
00412             delete_pad(curpad);
00413             curpad = NULL;
00414             RESULT(OK);
00415         }
00416         break;
00417 
00418     case PAD_INVENT:
00419         invent_pad(text);
00420         SENDTEXT(text);
00421         break;
00422 
00423     case PAD_LIST:
00424         for (pad = pad_list(); pad != NULL; pad = pad->next)
00425             if (*pad->name)
00426                 SENDTEXT(pad->name);
00427         SENDTEXT("");
00428         break;
00429 
00430     case PAD_SELECT:
00431         RECTEXT(text, text_size);       /* pad name */
00432         curpad = find_pad(text);
00433         if (curpad == NULL)
00434             RESULT(NO_PAD);
00435         else
00436             RESULT(OK);
00437         break;
00438 
00439     case PAD_GET_ITEM:
00440         RECTEXT(text, text_size);       /* item name */
00441         if (curpad == NULL) {
00442             RESULT(NO_CUR_PAD);
00443             break;
00444         }
00445         item = find_item(curpad, text);
00446         if (item == NULL) {
00447             RESULT(NO_ITEM);
00448             break;
00449         }
00450         RESULT(OK);
00451         for (list = item->list; list != NULL; list = list->next)
00452             if (*list->value)
00453                 SENDTEXT(list->value);
00454         SENDTEXT("");
00455         break;
00456 
00457     case PAD_SET_ITEM:
00458         RECTEXT(name, name_size);       /* item name */
00459         RECTEXT(text, text_size);       /* item value */
00460         if (curpad == NULL) {
00461             RESULT(NO_CUR_PAD);
00462             break;
00463         }
00464         delete_item(curpad, name);
00465         if (append_item(curpad, name, text, 0))
00466             RESULT(OK);
00467         else
00468             RESULT(NO_MEMORY);
00469         break;
00470 
00471     case PAD_APPEND_ITEM:
00472         RECTEXT(name, name_size);       /* item name */
00473         RECTEXT(text, text_size);       /* item value */
00474         REC(&index, sizeof index);      /* replace flag */
00475         if (curpad == NULL) {
00476             RESULT(NO_CUR_PAD);
00477             break;
00478         }
00479         if (append_item(curpad, name, text, index))
00480             RESULT(OK);
00481         else
00482             RESULT(NO_MEMORY);
00483         break;
00484 
00485     case PAD_DELETE_ITEM:
00486         RECTEXT(text, text_size);       /* item name */
00487         if (curpad == NULL) {
00488             RESULT(NO_CUR_PAD);
00489             break;
00490         }
00491         delete_item(curpad, text);
00492         RESULT(OK);
00493         break;
00494 
00495     case PAD_LIST_ITEMS:
00496         if (curpad == NULL) {
00497             RESULT(NO_CUR_PAD);
00498             break;
00499         }
00500         RESULT(OK);
00501         for (item = curpad->items; item != NULL; item = item->next)
00502             if (*item->name)
00503                 SENDTEXT(item->name);
00504         SENDTEXT("");
00505         break;
00506 
00507     default:
00508         G_warning(_("Unknown command: %d last: %d"), c, lc);
00509         break;
00510     }
00511     lc = c;
00512 
00513     return ateof;
00514 }
00515 
00516 static int read1(char *c)
00517 {
00518     if (atbuf == n_read) {
00519         atbuf = 0;
00520         n_read = read(_rfd, inbuf, sizeof inbuf);
00521         if (n_read < 0)
00522             perror("Monitor: read1: Error reading input");
00523         if (n_read <= 0)
00524             return 1;           /* EOF */
00525     }
00526     *c = inbuf[atbuf++];
00527     return 0;
00528 }
00529 
00530 int get_command(char *c)
00531 {
00532     /* is there a command char pending? */
00533     if ((*c = current_command)) {
00534         current_command = 0;
00535         return 0;
00536     }
00537 
00538     /*
00539      * look for 1 (or more) COMMAND_ESC chars
00540      * followed by a non-zero comamnd token char
00541      */
00542     while (read1(c) == 0) {     /* while !EOF */
00543         if (*c != COMMAND_ESC)
00544             continue;
00545         while (*c == COMMAND_ESC)
00546             if (read1(c) != 0) {
00547                 G_warning(_("Monitor: get_command: Premature EOF"));
00548                 return 1;       /* EOF */
00549             }
00550         if (*c)
00551             return 0;           /* got the command token */
00552     }
00553     return 1;                   /* EOF */
00554 }
00555 
00556 static int get1(char *c)
00557 {
00558     if (read1(c) != 0)
00559         return 1;               /* EOF */
00560     if (*c != COMMAND_ESC)
00561         return 0;               /* OK */
00562     if (read1(c) != 0)
00563         return 1;               /* EOF */
00564     if (*c) {
00565         current_command = *c;
00566         return -1;              /* Got command within data */
00567     }
00568     *c = COMMAND_ESC;           /* sequence COMMAND_ESC,0 becomes data COMMAND_ESC */
00569     return 0;                   /* OK */
00570 }
00571 
00572 static int rec(void *buf, int n)
00573 {
00574     char *cbuf = buf;
00575     int stat;
00576 
00577     while (n-- > 0) {
00578         if ((stat = get1(cbuf++)) != 0)
00579             return stat;        /* EOF or COMMAND_ESC */
00580     }
00581     return 0;
00582 }
00583 
00584 static int rectext(char **buff_p, int *size_p)
00585 {
00586     char *buff = *buff_p;
00587     int size = *size_p;
00588     int i, stat;
00589 
00590     for (i = 0;; i++) {
00591         char c;
00592 
00593         stat = get1(&c);
00594         if (stat != 0)
00595             return stat;        /* EOF or COMMAND_ESC */
00596 
00597         if (i >= size) {
00598             *size_p = size = size ? size * 2 : 1000;
00599             *buff_p = buff = G_realloc(buff, size);
00600         }
00601 
00602         buff[i] = c;
00603 
00604         if (!c)
00605             return 0;
00606     }
00607 }
00608 
00609 static int _send(const void *buf, int n)
00610 {
00611     int r = write(_wfd, buf, n);
00612 
00613     if (r < 0) {
00614         perror("Monitor: _send: write");
00615         return 1;
00616     }
00617     if (r < n) {
00618         G_warning("Monitor: _send: write returned short count: %d of %d",
00619                   r, n);
00620         return 1;
00621     }
00622     return 0;
00623 }
00624 
00625 static int sendtext(const char *s)
00626 {
00627     SEND(s, strlen(s) + 1);
00628     return 0;
00629 }
00630 
00631 static int RESULT(int n)
00632 {
00633     unsigned char c;
00634 
00635     c = n;
00636     SEND(&c, 1);
00637 
00638     return 0;
00639 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines