GRASS Programmer's Manual
6.4.2(2012)
|
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 }