/* * $Id$ */ #include #include #include #include #include #include #include #include #include #include #include /* Some silly AIX stuff: */ #if defined(_AIX) #define _NO_PROTO /* signal definition is wrong: void (*signal(int, void (*)(int)))(int) */ #else #include #endif #include #include "gr.h" #include "xpomp_graphic.h" static int is_shm = 0; static int pc_depth[20] = {0}; static int pc_no_graphic = 0; static char *display_name = 0; static struct sh_header *sh_h[20]; static int _NO_PROC; static int fildeftab[] = { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, }; enum wm { NONE, SUNVIEW, X11 }; /* The color range when automatic color scaling in XPOMP_show: */ enum { min_scale_color = 1, max_scale_color = 254 }; static XPOMP_display currentdisplay = -1; /* In XPOMP graphic, there is no runtime synchronization or broadcast since it is already done by the HPFC compiler: */ static void pc_synchro(void) { } static void pc_broadcast(void * variable, int size) { } static enum wm identify_wm() { if(getenv("NODISPLAY")) return NONE; if(getenv("WINDOW_ME")) return SUNVIEW; if(getenv("DISPLAY")) return X11; pc_no_graphic = 1; return NONE; } #if defined(_AIX) static void sigusr2(int sig, int code, struct sigcontext * scp) #elif defined(__linux) static void sigusr2(int sig) #else static void sigusr2(int sig, int code, struct sigcontext * scp, char * addr) #endif { } static int get_tab_entry() { int i; for(i=0;i < 20;i++) { if(fildeftab[i] == 0) { fildeftab[i] = 1; return i; } } return -1; } static int pc_setcurrentdisplay(int d) { int old_d; old_d = currentdisplay; currentdisplay = d; return old_d; } static int pc_getcurrentdisplay(void) { return currentdisplay; } /* returns the directory name for the executable: * "${XPOMP_RUNTIME}/${PIPS_ARCH:-.}" * "${PIPS_ROOT}/Runtime/xpomp/${PIPS_ARCH:-.}" * PATH chosen => "" */ #define NAME_MAX_LENGTH 300 /* environment variables */ #define XPOMP "XPOMP_RUNTIME" #define PIPS_ROOT "PIPS_ROOT" #define PIPS_ARCH "PIPS_ARCH" #define XPOMP_DIR "Runtime/xpomp" static char * path_of(char * binary) { static char name[NAME_MAX_LENGTH]; int len; char *xpomp = getenv(XPOMP), *pipsr = getenv(PIPS_ROOT), *pipsa = getenv(PIPS_ARCH); /* checks for no "name" buffer overflow */ len = (xpomp? strlen(xpomp)+1: pipsr? strlen(pipsr)+strlen(XPOMP_DIR)+2: 0) + (pipsa? strlen(pipsa)+1: 0) + strlen(binary) + 1; if (len>NAME_MAX_LENGTH) { fprintf(stderr, "[path_of] %s path name length too large (%d)\n", binary, len); exit(1); } /* builds the path from the environment variables */ if (xpomp) if (pipsa) sprintf(name, "%s/%s/%s", xpomp, pipsa, binary); else sprintf(name, "%s/%s", xpomp, binary); else if (pipsr) if (pipsa) sprintf(name, "%s/" XPOMP_DIR "/%s/%s", pipsr, pipsa, binary); else sprintf(name, "%s/" XPOMP_DIR "/%s", pipsr, binary); else sprintf(name, "%s", binary); return name; } int pc_basic_opendisplay(int X, int Y, int dbx) { int i,size,id,shmid; static char *argv[20] = {0,"-m",0,0,0,0,0}; char sx[10]; char sy[10]; int argc; enum wm w; w = identify_wm(); switch(w) { case SUNVIEW : argv[0] = path_of("pompview"); break; case X11 : argv[0] = path_of("xpomp"); break; case NONE : default : fprintf(stderr,"no window manager is running!\n"); return -1; } i = get_tab_entry(); if(i == -1) return -1; size = X * Y; if(!_NO_PROC) { shmid = shmget(IPC_PRIVATE,size+sizeof(*sh_h),IPC_CREAT | 0600); } pc_broadcast(&shmid,sizeof(int)); if(shmid == -1) { is_shm = 0; } else is_shm = 1; if(is_shm) { sh_h[i] = (struct sh_header *) shmat(shmid,0,0); if(sh_h[i] == (struct sh_header *) -1) { perror("shmat"); exit(-1); } } else { sh_h[i] = (struct sh_header *) malloc(sizeof(**sh_h)); } if(!_NO_PROC) { sh_h[i]->buf1 = ((char *) (sh_h[i]+1)); sh_h[i]->buf2 = sh_h[i]->buf1 + size; sh_h[i]->lock = 1; sh_h[i]->flag = GR_START; sh_h[i]->bufsize = size; { char * shmid_number = malloc(12); sprintf(shmid_number,"%d",shmid); argv[2] = shmid_number; } argc = 3; if(dbx) argv[argc++] = "-d"; sprintf(sx,"%d",X); sprintf(sy,"%d",Y); argv[argc++] = "-w"; argv[argc++] = sx; argv[argc++] = sy; if(display_name) { argv[argc++] = "-D"; argv[argc++] = display_name; } argv[argc++] = 0; (void) signal(SIGUSR2, sigusr2); /* fork! */ switch(id = fork()) { case -1 : fprintf(stderr,"unsuccessfull fork!\n"); return 0; case 0 : /* child's subprocess */ fprintf(stderr, "executing %s\n", argv[0]); execvp(argv[0],argv); perror("Exec failed"); exit(0); } while(sh_h[i]->lock) sigpause(0); pc_depth[i] = sh_h[i]->p1; sh_h[i]->id = id; } if(pc_getcurrentdisplay() == -1) { pc_setcurrentdisplay(i); } return i; } int is_good_desc(int * i) { if(pc_no_graphic) return 0; if(*i == -1) { *i = pc_getcurrentdisplay(); if(*i == -1) { *i = pc_basic_opendisplay(512,512,0); pc_setcurrentdisplay(*i); } } if(*i <0 || *i >= 20) return 0; return fildeftab[*i]; } static void pc_basic_flush(sh) struct sh_header *sh; { if(!_NO_PROC) { sh->lock = 1; kill(sh->id,SIGUSR2); } } static void pc_basic_wait_lock(screen) { struct sh_header *sh; if(!is_good_desc(&screen)) return; sh = sh_h[screen]; while(sh->lock) sigpause(0); } static void pc_basic_buf_clip(screen,X,Y,PX,PY,dx,dy,zoomx,zoomy,SIZEY,SIZEX,flag) { struct sh_header *sh; if(!is_good_desc(&screen)) return; sh = sh_h[screen]; pc_synchro(); if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_BUF; sh->p1 = X; sh->p2 = Y; sh->p3 = dx; sh->p4 = dy; sh->p5 = zoomx; sh->p6 = zoomy; sh->p7 = PX; sh->p8 = PY; sh->p9 = SIZEX; sh->p10 = SIZEY; sh->activite = flag; sh->lock = 1; pc_basic_flush(sh); } } static void pc_basic_buf(screen,X,Y,PX,PY,dx,dy,zoomx,zoomy,flag) { struct sh_header *sh; if(!is_good_desc(&screen)) return; sh = sh_h[screen]; pc_synchro(); if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_BUF; sh->p1 = X; sh->p2 = Y; sh->p3 = dx; sh->p4 = dy; sh->p5 = zoomx; sh->p6 = zoomy; sh->p7 = PX; sh->p8 = PY; sh->p9 = X; sh->p10 = Y; sh->activite = flag; sh->lock = 1; pc_basic_flush(sh); } } char *pc_basic_get_buf(screen,n) { if(!is_good_desc(&screen)) return NULL; if(!_NO_PROC) pc_basic_wait_lock(screen); pc_synchro(); if(_NO_PROC) { if(!n) return (char *)(sh_h[screen] + 1); return (char *)(sh_h[screen] + 1) + sh_h[screen]->bufsize; } else { if(!n) return sh_h[screen]->buf1; return sh_h[screen]->buf2; } } static void new_pc_basic_buf(XPOMP_display screen, unsigned char * data_array, int X_data_array_size, int Y_data_array_size, int X_offset, int Y_offset, int X_zoom_ratio, int Y_zoom_ratio) { struct sh_header *sh; if(!is_good_desc(&screen)) return; sh = sh_h[screen]; pc_basic_wait_lock(screen); sh->flag = GR_BUF; sh->p1 = X_data_array_size; sh->p2 = Y_data_array_size; sh->p3 = X_offset; sh->p4 = Y_offset; sh->p5 = X_zoom_ratio; sh->p6 = Y_zoom_ratio; sh->lock = 1; pc_basic_flush(sh); } /************************************************************************/ int pc_basic_closedisplay(XPOMP_display screen) { struct sh_header *sh; if(!is_good_desc(&screen)) return -1; sh = sh_h[screen]; if(!_NO_PROC) { sh->flag = GR_CLOSE; pc_basic_flush(sh); } fildeftab[screen] = 0; return 0; } static int pc_basic_scroll(XPOMP_display screen, int y) { struct sh_header *sh; if(!is_good_desc(&screen)) return -1; sh = sh_h[screen]; if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_SCROLL; sh->p1 = y; pc_basic_flush(sh); } return 0; } int pc_basic_setcolor(screen,red,green,blue) int screen; unsigned char *red, *green, *blue; { struct sh_header *sh; char *p; if(!is_good_desc(&screen)) return -1; sh = sh_h[screen]; if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_SET_COLOR; p = (char *) (sh+1); memcpy(p, (char *) red, 256); memcpy(p+256, (char *) green, 256); memcpy(p+512, (char *) blue, 256); pc_basic_flush(sh); } return 0; } static int pc_basic_mouse(XPOMP_display screen, int * X, int * Y, int * state) { struct sh_header *sh; int B = -1; /* Default values: */ *X = 32; *Y = 48; if(is_good_desc(&screen)) { sh = sh_h[screen]; if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_MOUSE; pc_basic_flush(sh); pc_basic_wait_lock(screen); *X = sh->p1; *Y = sh->p2; B = sh->p3; *state = sh->p4; } } return B; } static int pc_basic_ismouse(XPOMP_display screen, int * X, int * Y, int * state) { struct sh_header *sh; int res = -1; /* Default values: */ *X = 32; *Y = 48; if(is_good_desc(&screen)) { sh = sh_h[screen]; if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_ISMOUSE; pc_basic_flush(sh); pc_basic_wait_lock(screen); *X = sh->p1; *Y = sh->p2; *state = sh->p4; res = sh->p3; } } return res; } int pc_basicgetdepth(screen) int screen; { if(!is_good_desc(&screen)) return -1; return pc_depth[screen]; } /* The user function to open a new display window: */ XPOMP_display XPOMP_open_display(int X_window_size, int Y_window_size) { return pc_basic_opendisplay(X_window_size, Y_window_size, 0); } /* Get the number of bit per pixel of the screen: */ void XPOMP_close_display(XPOMP_display screen) { pc_basic_closedisplay(screen); } /* Get the current default XPOMP display: */ int XPOMP_get_current_default_display() { return pc_getcurrentdisplay(); } /* Set the current default XPOMP display and return the old one: */ int XPOMP_set_current_default_display(XPOMP_display screen) { return pc_setcurrentdisplay(screen); } /* Get the pixel bit width of a display window: */ int XPOMP_get_depth(XPOMP_display screen) { return pc_basicgetdepth(screen); } /* Select the color map: */ int XPOMP_set_color_map(XPOMP_display screen, int pal, int cycle, int start, int clip) { struct sh_header *sh; if(!is_good_desc(&screen)) return -1; sh = sh_h[screen]; if(!_NO_PROC) { sh->flag = GR_CMAP; sh->p1 = pal; sh->p2 = cycle; sh->p3 = start; sh->p4 = clip; pc_basic_flush(sh); } return 0; } /* Load a user defined colormap and select it: */ int XPOMP_set_user_color_map(XPOMP_display screen, unsigned char * red, unsigned char * green, unsigned char * blue) { return pc_basic_setcolor(screen, red, green, blue); } /* Wait for a mouse click: */ int XPOMP_wait_mouse(XPOMP_display screen, int * X, int * Y, int * state) { return pc_basic_mouse(screen, X, Y, state); } /* Just test for a mouse click: */ int XPOMP_is_mouse(XPOMP_display screen, int * X, int * Y, int * state) { return pc_basic_ismouse(screen, X, Y, state); } /* The user interface to show something uncooked. Return -1 if it fails, 0 if not: */ int XPOMP_flash(XPOMP_display screen, unsigned char * data_array, int X_data_array_size, int Y_data_array_size, int X_offset, int Y_offset, int X_zoom_ratio, int Y_zoom_ratio) { char *p; if (!is_good_desc(&screen)) return -1; p = pc_basic_get_buf(screen,0); memcpy(p, (char *) data_array, X_data_array_size*Y_data_array_size); new_pc_basic_buf(screen, data_array, X_data_array_size, Y_data_array_size, X_offset, Y_offset, X_zoom_ratio, Y_zoom_ratio); return 0; } /* Show something: */ #define XPOMP_SHOW(TYPE) \ int \ XPOMP_show_##TYPE(XPOMP_display screen, \ const TYPE * data_array, \ const int X_data_array_size, \ const int Y_data_array_size, \ const int X_offset, \ const int Y_offset, \ const int X_zoom_ratio, \ const int Y_zoom_ratio, \ double min_value, \ double max_value) \ { \ int i; \ \ unsigned char * flash_data = \ (unsigned char *) alloca(X_data_array_size*X_data_array_size); \ \ if (!is_good_desc(&screen)) \ return -1; \ \ if (min_value == 0 && max_value == 0) { \ /* Automatic color scaling: */ \ min_value = HUGE_VAL; \ max_value = -HUGE_VAL; \ for(i = 0; i <= X_data_array_size*X_data_array_size; i++) { \ if (data_array[i] > max_value) \ max_value = data_array[i]; \ else if (data_array[i] < min_value) \ min_value = data_array[i]; \ } \ } \ \ if (!(min_value == 0 && max_value == 0)) \ for(i = 0; i <= X_data_array_size*X_data_array_size; i++) \ flash_data[i] = (data_array[i] - min_value) \ *(max_scale_color - min_scale_color)/ \ (max_value - min_value) + min_scale_color; \ else \ /* All the array is 0, so display a big 0... */ \ for(i = 0; i <= X_data_array_size*X_data_array_size; i++) \ flash_data[i] = 0; \ \ return XPOMP_flash(screen, flash_data, X_data_array_size, \ Y_data_array_size, \ X_offset, Y_offset, X_zoom_ratio, Y_zoom_ratio); \ } /* Show a float array and interpolate color between min_value to max_value. If min_value = max_value = 0, automatically scale the colors: */ XPOMP_SHOW(float) /* Show a double array and interpolate color between min_value to max_value. If min_value = max_value = 0, automatically scale the colors: */ XPOMP_SHOW(double) /* Scroll a window: */ int XPOMP_scroll(XPOMP_display screen, int delta_Y) { return pc_basic_scroll(screen, delta_Y); } /* Draw a frame from corner (X0,Y0) to corner (X1,Y1) and add a title: */ int XPOMP_draw_frame(XPOMP_display screen, char * title, int title_color, int background_color, int X0, int Y0, int X1, int Y1, int color) { struct sh_header *sh; if(!is_good_desc(&screen)) return -1; sh = sh_h[screen]; if(!_NO_PROC) { pc_basic_wait_lock(screen); sh->flag = GR_PUT_FRAME; sh->p1 = X0; sh->p2 = Y0; sh->p3 = X1; sh->p4 = Y1; sh->p5 = color; sh->p6 = title_color; sh->p7 = background_color; strcpy(sh->buf1, title); sh->lock = 1; pc_basic_flush(sh); } return 0; } /* Print out a small help about keyboard usage in xPOMP: */ void XPOMP_show_usage() { fprintf(stderr, "xPOMP library keyboard usage:\n" "\tColor Map typeselection:\n" "1: grey scale\n" "2: rainbow color\n" "3: rainbow color with alternating half-tone\n" "4: color centered\n" "0: application defined\n" "\tColor Map parameters:\n" "- or _: decrease cycling\n" "+ or =: increase cycling\n" "h: increase start value\n" "l: decrease start value\n" "j: decrease clipping level value\n" "k: increase clipping level value\n" "H: combination of 'h' and 'j' keys\n" "L: combination of 'k' and 'l' keys\n" "?: print out the actual color map parameters\n" "\n" "q or ^D: quit.\n"); } /* The Fortran 77 wrappers: */ void FUNCTION(xpompfopendisplay)(int * X_window_size, int * Y_window_size, XPOMP_display * d) { *d = XPOMP_open_display(*X_window_size, *Y_window_size); } void FUNCTION(xpompfclosedisplay)(XPOMP_display * screen) { XPOMP_close_display(*screen); } void FUNCTION(xpompfgetcurrentdefaultdisplay)(int * d) { *d = XPOMP_get_current_default_display(); } void FUNCTION(xpompfsetcurrentdefaultdisplay)(XPOMP_display * screen, int * d) { *d = XPOMP_set_current_default_display(*screen); } void FUNCTION(xpompfgetdepth)(XPOMP_display * screen, int * d) { *d = XPOMP_get_depth(*screen); } void FUNCTION(xpompfsetcolormap)(XPOMP_display * screen, int * pal, int * cycle, int * start, int * clip, int * d) { *d = XPOMP_set_color_map(*screen, *pal, *cycle, *start, *clip); } void FUNCTION(xpompfsetusercolormap)(XPOMP_display * screen, unsigned char * red, unsigned char * green, unsigned char * blue, int * d) { *d = XPOMP_set_user_color_map(*screen, red, green, blue); } void FUNCTION(xpompfwaitmouse)(XPOMP_display * screen, int * X, int * Y, int * state, int * d) { *d = XPOMP_wait_mouse(*screen, X, Y, state); } void FUNCTION(xpompfismouse)(XPOMP_display * screen, int * X, int * Y, int * state, int * d) { *d = XPOMP_is_mouse(*screen, X, Y, state); } void FUNCTION(xpompfflash)(XPOMP_display * screen, unsigned char * data_array, int * X_data_array_size, int * Y_data_array_size, int * X_offset, int * Y_offset, int * X_zoom_ratio, int * Y_zoom_ratio, int * d) { *d = XPOMP_flash(*screen, data_array, *X_data_array_size, *Y_data_array_size, *X_offset, *Y_offset, *X_zoom_ratio, *Y_zoom_ratio); } void FUNCTION(xpompfshowreal4)(XPOMP_display * screen, float * data_array, int * X_data_array_size, int * Y_data_array_size, int * X_offset, int * Y_offset, int * X_zoom_ratio, int * Y_zoom_ratio, double * min_value, double * max_value, int * d) { *d = XPOMP_show_float(*screen, data_array, *X_data_array_size, *Y_data_array_size, *X_offset, *Y_offset, *X_zoom_ratio, *Y_zoom_ratio, *min_value, *max_value); } void FUNCTION(xpompfshowreal8)(XPOMP_display * screen, double * data_array, int * X_data_array_size, int * Y_data_array_size, int * X_offset, int * Y_offset, int * X_zoom_ratio, int * Y_zoom_ratio, double * min_value, double * max_value, int * d) { *d = XPOMP_show_double(*screen, data_array, *X_data_array_size, *Y_data_array_size, *X_offset, *Y_offset, *X_zoom_ratio, *Y_zoom_ratio, *min_value, *max_value); } void FUNCTION(xpompfscroll)(XPOMP_display * screen, int * delta_Y, int * return_value) { *return_value = XPOMP_scroll(*screen, *delta_Y); } /* Deal with nasty conventions with strings between Fortran and C. null title is represented in Fortran by ' ' (1 blank string) instead of "": */ void FUNCTION(xpompfdrawframe) ARGS(`screen, STRING_ARG(title), title_color, background_color, X0, Y0, X1, Y1, color, return_value') XPOMP_display * screen; STRING_ARG_DECL(title); int * title_color; int * background_color; int * X0; int * Y0; int * X1; int * Y1; int * color; int * return_value; { char * the_title; char * c_title = malloc(STRING_LEN(title) + 1); (void) memcpy(c_title, STRING_PTR(title), STRING_LEN(title)); c_title[STRING_LEN(title)] = '\0'; /* printf("'%s'->'%s' %d\n", STRING_PTR(title), c_title, STRING_LEN(title)); */ /* Note this is a string with one blank character in Fortran~77 because the Fortran~77 does not allow a string with no character in it... */ if (strcmp(c_title, " ") == 0) the_title = ""; else the_title = c_title; *return_value = XPOMP_draw_frame(*screen, the_title, *title_color, *background_color, *X0, *Y0, *X1, *Y1, *color); free(c_title); } void FUNCTION(xpompfshowusage)() { XPOMP_show_usage(); }