| PUMA 219 Portable University Model of the Atmosphere

- Main Page
- Data Types List
- Files

- File List
- File Members

/Users/home/WC/puma/src/pumax.c
Go to the documentation of this file.

    00001 /*
    00002     pumax - a GUI for PUMA & PLASIM
    00003     (c) 2007 Edilbert Kirk (E.Kirk@gmx.de)
    00004
    00005     This program is free software; you can redistribute it and/or modify
    00006     it under the terms of the GNU General Public License as published by
    00007     the Free Software Foundation; either version 2 of the License, or
    00008     (at your option) any later version.
    00009
    00010     This program is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013     GNU General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with this program; if not, write to the Free Software
    00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00018 */
    00019
    00020 int Debug = 0; // set in initgui
    00021
    00022 #include <ctype.h>
    00023 #include <stdio.h>
    00024 #include <string.h>
    00025 #include <stdlib.h>
    00026 #include <math.h>
    00027 #include <sys/time.h>
    00028 #include <sys/resource.h>
    00029 #include <X11/Xlib.h>
    00030 #include <X11/Xutil.h>
    00031 #include <X11/Xos.h>
    00032 #include <X11/Xatom.h>
    00033 #include <X11/keysym.h>
    00034
    00035 #define INT int
    00036 #define REAL float
    00037 #define INTXU unsigned int
    00038 #define INTXS int
    00039
    00040 #ifndef MIN
    00041 #define MIN(a,b) ((a) < (b) ? (a) : (b))
    00042 #endif
    00043
    00044 #ifndef MAX
    00045 #define MAX(a,b) ((a) > (b) ? (a) : (b))
    00046 #endif
    00047
    00048 #define ROTATE_LEFT  (XK_Left)
    00049 #define ROTATE_RIGHT (XK_Right)
    00050
    00051 #define TOLELO 0x0001
    00052 #define TOLEHI 0x0002
    00053 #define TORILO 0x0004
    00054 #define TORIHI 0x0008
    00055 #define BOLELO 0x0010
    00056 #define BOLEHI 0x0020
    00057 #define BORILO 0x0040
    00058 #define BORIHI 0x0080
    00059 #define TOLEIN 0x0100
    00060 #define TOREIN 0x0200
    00061 #define BOLEIN 0x0400
    00062 #define BOREIN 0x0800
    00063
    00064 #define IPX(l,m,h) (VGAX * (x + (l-m) / (l-h)))
    00065 #define IPY(l,m,h) (VGAY * (y + (l-m) / (l-h)))
    00066
    00067 #define NUMWIN 9
    00068 #define NUMPAL 13
    00069
    00070 /* Picture types */
    00071
    00072 #define ISOHOR  0
    00073 #define ISOCS   1
    00074 #define ISOHOV  2
    00075 #define ISOTS   3
    00076 #define ISOTAB  4
    00077 #define ISOSH   5
    00078 #define ISOLON  6
    00079 #define ISOTRA  7
    00080 #define ISOCOL  8
    00081 #define ISOROT  9
    00082 #define MAPHOR 10
    00083 #define MAPTRA 11
    00084
    00085 /* Models */
    00086
    00087 #define PUMA   0
    00088
    00089 char *IsoNames[] =
    00090 {
    00091    "ISOHOR",
    00092    "ISOCS",
    00093    "ISOHOV",
    00094    "ISOTS",
    00095    "ISOTAB",
    00096    "ISOSH",
    00097    "ISOLON",
    00098    "ISOTRA",
    00099    "ISOCOL",
    00100    "ISOROT",
    00101    "MAPHOR",
    00102    "MAPTRA"
    00103 };
    00104
    00105 int IsoTypes = sizeof(IsoNames) / sizeof(char *);
    00106
    00107 char *PalNames[] =
    00108 {
    00109    "AUTO",
    00110    "U",
    00111    "V",
    00112    "T",
    00113    "P",
    00114    "Q",
    00115    "MARST",
    00116    "AMPLI",
    00117    "VEG",
    00118    "OCET",
    00119    "OCES",
    00120    "DCC",
    00121    "DTDT"
    00122 };
    00123
    00124 int PalTypes = sizeof(PalNames) / sizeof(char *);
    00125
    00126 /* Map projections */
    00127
    00128 #define CYLINDRICAL 0
    00129 #define POLAR       1
    00130 #define AZIMUTHAL   2
    00131
    00132 #define MAXMAPS     3
    00133
    00134 char *ProNames[] =
    00135 {
    00136    "CYLINDRICAL",
    00137    "POLAR",
    00138    "AZIMUTHAL"
    00139 };
    00140
    00141
    00142 /* Coordinates of button areas */
    00143
    00144 int ShowQueue = 0;
    00145 int ShowOnce  = 1;
    00146 int OffsetY = 20;
    00147
    00148 int Stop_XL;
    00149 int Stop_XH;
    00150 int Stop_YL;
    00151 int Stop_YH;
    00152
    00153 int Start_XL;
    00154 int Start_XH;
    00155 int Start_YL;
    00156 int Start_YH;
    00157
    00158 int Pause_XL;
    00159 int Pause_XH;
    00160 int Pause_YL;
    00161 int Pause_YH;
    00162
    00163 int Help_XL;
    00164 int Help_XH;
    00165 int Help_YL;
    00166 int Help_YH;
    00167
    00168 int Minus_XL;
    00169 int Minus_XH;
    00170 int Minus_YL;
    00171 int Minus_YH;
    00172
    00173 int FBWD_XL;
    00174 int FBWD_XH;
    00175 int FBWD_YL;
    00176 int FBWD_YH;
    00177
    00178 int Plus_XL;
    00179 int Plus_XH;
    00180 int Plus_YL;
    00181 int Plus_YH;
    00182
    00183 int FFWD_XL;
    00184 int FFWD_XH;
    00185 int FFWD_YL;
    00186 int FFWD_YH;
    00187
    00188 int Parc_XL;
    00189 int Parc_XH;
    00190 int Parc_XD;
    00191 int Parc_YL;
    00192 int Parc_YH;
    00193 int Parc_YD;
    00194
    00195 int Wbox_XL;
    00196 int Wbox_XH;
    00197 int Wbox_YL;
    00198 int Wbox_YH;
    00199
    00200 int Grid_XL;
    00201 int Grid_XH;
    00202 int Grid_YL;
    00203 int Grid_YH;
    00204
    00205 XPoint StopButton[4] = {{10,10},{40,10},{40,40},{10,40}};
    00206 XPoint StartButton[3] = {{50,10},{80,25},{50,40}};
    00207 XPoint PauseButton1[4] = {{95,10},{102,10},{102,40},{95,40}};
    00208 XPoint PauseButton2[4] = {{108,10},{115,10},{115,40},{108,40}};
    00209
    00210 #define PARCS 100
    00211
    00212 struct ParcStruct
    00213 {
    00214    char Name[8];
    00215    float Inc;
    00216    float Min;
    00217    float Max;
    00218    float Val;
    00219 };
    00220
    00221 int Parcs;
    00222 int cpi = 1;
    00223
    00224 struct ParcStruct Parc[PARCS];
    00225
    00226 int screen_num;
    00227
    00228 Display *display;
    00229 unsigned int ScreenW,ScreenH,ScreenBot;
    00230 int SmallScreen;
    00231
    00232 static char *progname = "PUMA";
    00233
    00234 int BigEndian;
    00235 int ScreenOffset;
    00236 int Model;
    00237 int CowX = -1;
    00238 int CowY = -1;
    00239 int CowW;
    00240 int CowH;
    00241 int NumWin = NUMWIN;
    00242 int WinCols = 3;
    00243 int WinRows = 3;
    00244 int DimT = 100; // Default length of time axis
    00245 int DimX;
    00246 int DimY;
    00247 int DimZ;
    00248 int DimXY;
    00249 int Uindex = -1;
    00250 int Vindex = -1;
    00251 int ScreenD;
    00252 int OffX;
    00253 int OffY = 0;
    00254 INTXU WinXSize;
    00255 INTXU WinYSize;
    00256 int InXSize;
    00257 int InYSize;
    00258 int Latitudes;
    00259 int Lines;
    00260 int SizeChanged;
    00261 int Shutdown;
    00262 int Grid = 1;
    00263 int GridLabel = 1;
    00264 int WhitePix;
    00265 int BlackPix;
    00266 int *Flag;
    00267 int FlagSize;
    00268 int nstep;
    00269 int MRpid;
    00270 int MRnum;
    00271 int wto;
    00272 int FirstKey;
    00273 int LastKey;
    00274 int SymsPerKey;
    00275
    00276 KeySym *KeyMap;
    00277
    00278 char wtrun[8];
    00279
    00280 unsigned Seed;
    00281
    00282 float RotInc = 0.2;
    00283 int LineCo[NUMPAL];
    00284 int MapPro[NUMWIN];
    00285 int HovInx[NUMWIN];
    00286 int Indez[NUMWIN];
    00287 int MaxZ[NUMWIN];
    00288 int RedrawFlag[NUMWIN];
    00289 int LevelChanged[NUMWIN];
    00290 int RotLon[NUMWIN];
    00291 double AutoDelta[NUMWIN];
    00292 double AutoXdelt[NUMWIN];
    00293 double AutoLo[NUMWIN];
    00294 REAL *TSdata[NUMWIN];
    00295 REAL *Dmin[NUMWIN];
    00296 REAL *Dmax[NUMWIN];
    00297 REAL *SpeedScale;
    00298 XPoint *TSxp[NUMWIN];
    00299
    00300
    00301 #define MAXPAR 16384
    00302 float pax[MAXPAR];
    00303 float pay[MAXPAR];
    00304 long  pal[MAXPAR];
    00305
    00306 int Delpar = 8; /* Interval for particle injection */
    00307 int ParInd = 0;
    00308 int ColInd = 0;
    00309 long TracerColor;
    00310
    00311 #define NUMSCALARS 9
    00312
    00313 char TSName[NUMSCALARS][80];
    00314 char TSubsc[NUMSCALARS][80];
    00315 char TSUnit[NUMSCALARS][80];
    00316 char TScale[NUMSCALARS][80];
    00317
    00318 struct PixStruct
    00319 {
    00320    int DimX;
    00321    int DimY;
    00322    Pixmap Pix;
    00323 } WinPixMap[NUMWIN];
    00324
    00325 Pixmap pix;
    00326
    00327 #define NUMARRAYS 100
    00328
    00329 struct ArrayStruct
    00330 {
    00331    char Name[80];
    00332    float *Data;
    00333    int DimX;
    00334    int DimY;
    00335    int DimZ;
    00336    int Flag;
    00337 } Array[NUMARRAYS];
    00338
    00339 int NumArrays;
    00340
    00341 struct WinAttStruct
    00342 {
    00343    unsigned int x;
    00344    unsigned int y;
    00345    unsigned int w;
    00346    unsigned int h;
    00347    int active;
    00348    char array_name[80];
    00349    int Plot;
    00350    int Palette;
    00351 } WinAtt[NUMWIN];
    00352
    00353 int BorderWidth =  0;
    00354 int WM_top_area =  0; // Window manager top    area
    00355 int WinLM       =  0;
    00356 int WinRM       =  0;
    00357 int WinTM       = 24;
    00358 int WinBM       =  0;
    00359
    00360 struct ColorStrip
    00361 {
    00362    double  Lo;
    00363    double  Hi;
    00364    char *Name;
    00365    unsigned long pixel;
    00366 };
    00367
    00368 #define AUTOCOLORS 14
    00369 struct ColorStrip Autostrip[AUTOCOLORS+1] =
    00370 {
    00371    {0.0,0.0,"red"},
    00372    {0.0,0.0,"OrangeRed"},
    00373    {0.0,0.0,"Orange"},
    00374    {0.0,0.0,"yellow"},
    00375    {0.0,0.0,"GreenYellow"},
    00376    {0.0,0.0,"green"},
    00377    {0.0,0.0,"aquamarine"},
    00378    {0.0,0.0,"cyan"},
    00379    {0.0,0.0,"SkyBlue"},
    00380    {0.0,0.0,"blue"},
    00381    {0.0,0.0,"orchid"},
    00382    {0.0,0.0,"magenta"},
    00383    {0.0,0.0,"violet"},
    00384    {0.0,0.0,"DarkViolet"},
    00385    {0.0,0.0,NULL}
    00386 };
    00387
    00388 struct ColorStrip Ustrip[] =
    00389 {
    00390    {-99.0,-10.0,"red"},
    00391    {-10.0, -5.0,"OrangeRed"},
    00392    { -5.0,  0.0,"Orange"},
    00393    {  0.0,  5.0,"yellow"},
    00394    {  5.0, 10.0,"GreenYellow"},
    00395    { 10.0, 15.0,"green"},
    00396    { 15.0, 20.0,"aquamarine"},
    00397    { 20.0, 25.0,"cyan"},
    00398    { 25.0, 30.0,"SkyBlue"},
    00399    { 30.0, 35.0,"blue"},
    00400    { 35.0, 40.0,"orchid"},
    00401    { 40.0, 45.0,"magenta"},
    00402    { 45.0, 50.0,"violet"},
    00403    { 50.0, 99.0,"DarkViolet"},
    00404    {  0.0,  0.0,NULL}
    00405 };
    00406
    00407 struct ColorStrip Qstrip[] =
    00408 {
    00409    {-99.0,  0.0,"black"},
    00410    {  0.0,  5.0,"OrangeRed"},
    00411    {  5.0, 10.0,"Orange"},
    00412    { 10.0, 15.0,"yellow"},
    00413    { 15.0, 20.0,"GreenYellow"},
    00414    { 20.0, 25.0,"green"},
    00415    { 25.0, 30.0,"aquamarine"},
    00416    { 30.0, 35.0,"cyan"},
    00417    { 35.0, 40.0,"SkyBlue"},
    00418    { 40.0, 45.0,"blue"},
    00419    { 45.0, 50.0,"orchid"},
    00420    { 50.0, 55.0,"magenta"},
    00421    { 55.0, 60.0,"violet"},
    00422    { 60.0, 99.0,"DarkViolet"},
    00423    {  0.0,  0.0,NULL}
    00424 };
    00425
    00426 struct ColorStrip Vstrip[] =
    00427 {
    00428    {-99.0,-10.0,"brown"},
    00429    {-10.0, -8.0,"gold"},
    00430    { -8.0, -6.0,"purple"},
    00431    { -6.0, -4.0,"red"},
    00432    { -4.0, -2.0,"OrangeRed"},
    00433    { -2.0,  0.0,"Orange"},
    00434    {  0.0,  2.0,"yellow"},
    00435    {  2.0,  4.0,"GreenYellow"},
    00436    {  4.0,  6.0,"green"},
    00437    {  6.0,  8.0,"aquamarine"},
    00438    {  8.0, 10.0,"cyan"},
    00439    { 10.0, 99.0,"blue"},
    00440    {  0.0,  0.0,NULL}
    00441 };
    00442
    00443 struct ColorStrip Tstrip[] =
    00444 {
    00445    {-99.0,-50.0,"MidnightBlue"},
    00446    {-50.0,-40.0,"RoyalBlue4"},
    00447    {-40.0,-30.0,"RoyalBlue3"},
    00448    {-30.0,-20.0,"RoyalBlue2"},
    00449    {-20.0,-10.0,"RoyalBlue1"},
    00450    {-10.0,  0.0,"violet"},
    00451    {  0.0, 10.0,"IndianRed1"},
    00452    { 10.0, 20.0,"IndianRed2"},
    00453    { 20.0, 30.0,"IndianRed3"},
    00454    { 30.0, 40.0,"IndianRed4"},
    00455    { 40.0, 50.0,"red"},
    00456    {  0.0,  0.0,NULL}
    00457 };
    00458
    00459 struct ColorStrip Kstrip[] =
    00460 {
    00461    {100.0,210.0,"RoyalBlue4"},
    00462    {210.0,220.0,"RoyalBlue3"},
    00463    {220.0,230.0,"RoyalBlue2"},
    00464    {230.0,240.0,"RoyalBlue1"},
    00465    {240.0,250.0,"violet"},
    00466    {250.0,260.0,"IndianRed1"},
    00467    {260.0,270.0,"IndianRed2"},
    00468    {270.0,280.0,"IndianRed3"},
    00469    {280.0,290.0,"IndianRed4"},
    00470    {290.0,400.0,"red"},
    00471    {  0.0,  0.0,NULL}
    00472 };
    00473
    00474 struct ColorStrip Pstrip[] =
    00475 {
    00476    {  00.0, 985.0,"RoyalBlue4"},
    00477    { 985.0, 990.0,"RoyalBlue3"},
    00478    { 990.0, 995.0,"RoyalBlue2"},
    00479    { 995.0,1000.0,"RoyalBlue1"},
    00480    {1000.0,1005.0,"violet"},
    00481    {1005.0,1010.0,"IndianRed1"},
    00482    {1010.0,1015.0,"IndianRed2"},
    00483    {1015.0,1020.0,"IndianRed3"},
    00484    {1020.0,1025.0,"IndianRed4"},
    00485    {1025.0,9990.0,"red"},
    00486    {  0.0,  0.0,NULL}
    00487 };
    00488
    00489 struct ColorStrip MarsTStrip[] =
    00490 {
    00491    {-200.0,-90.0,"RoyalBlue4"},
    00492    { -90.0,-80.0,"RoyalBlue3"},
    00493    { -80.0,-70.0,"RoyalBlue2"},
    00494    { -70.0,-60.0,"RoyalBlue1"},
    00495    { -60.0,-50.0,"violet"},
    00496    { -50.0,-40.0,"IndianRed1"},
    00497    { -40.0,-30.0,"IndianRed2"},
    00498    { -30.0,-20.0,"IndianRed3"},
    00499    { -20.0,  0.0,"IndianRed4"},
    00500    {   0.0,100.0,"red"},
    00501    {   0.0,  0.0,NULL}
    00502 };
    00503
    00504 struct ColorStrip AmpliStrip[] =
    00505 {
    00506    {   0.0,  1.0,"DarkBlue"},
    00507    {   8.0,  9.0,"blue"},
    00508    {   8.0,  9.0,"DarkGreen"},
    00509    {   8.0,  9.0,"green"},
    00510    {   8.0,  9.0,"yellow"},
    00511    {   9.0, 10.0,"Orange"},
    00512    {  10.0, 11.0,"OrangeRed"},
    00513    {  11.0, 12.0,"red"},
    00514    {   0.0,  0.0,NULL}
    00515 };
    00516
    00517 struct ColorStrip Vegstrip[] =
    00518 {
    00519    {-999.9,0.001,"DarkBlue"},
    00520    { 0.001, 10.0,"brown"},
    00521    {  10.0, 20.0,"SeaGreen4"},
    00522    {  20.0, 30.0,"SeaGreen3"},
    00523    {  30.0, 40.0,"SeaGreen2"},
    00524    {  40.0, 50.0,"SeaGreen1"},
    00525    {  50.0, 60.0,"YellowGreen"},
    00526    {  60.0, 70.0,"green4"},
    00527    {  70.0, 80.0,"green3"},
    00528    {  80.0, 90.0,"green2"},
    00529    {  90.0,999.0,"green1"},
    00530    {   0.0,  0.0,NULL}
    00531 };
    00532
    00533 struct ColorStrip Tstripoce[] =
    00534 {
    00535    {-99.0, 0.00001,"Black"},
    00536    { 0.00001, 4.0 ,"RoyalBlue4"},
    00537    { 4.0 ,8.0,"RoyalBlue3"},
    00538    { 8.0, 12.0,"RoyalBlue2"},
    00539    { 12.0, 16.0,"RoyalBlue1"},
    00540    { 16.0, 20.0,"violet"},
    00541    { 20.0, 24.0,"IndianRed1"},
    00542    { 24.0, 28.0,"IndianRed2"},
    00543    { 28.0, 32.0,"IndianRed3"},
    00544    { 32.0, 36.0,"IndianRed4"},
    00545    { 36.0, 40.0,"red"},
    00546    {  0.0,  0.0,NULL}
    00547 };
    00548
    00549 struct ColorStrip Sstripoce[] =
    00550 {
    00551    {-99.0, 30.0,"Black"},
    00552    { 30.0, 32.0 ,"RoyalBlue4"},
    00553    { 32.0 ,32.5,"RoyalBlue3"},
    00554    { 32.5, 33.0,"RoyalBlue2"},
    00555    { 33.0, 34.0,"SeaGreen"},
    00556    { 34.0, 34.5,"YellowGreen"},
    00557    { 34.5, 35.0,"LightGreen"},
    00558    { 35.0, 35.5,"Orange"},
    00559    { 35.5, 36.0,"DarkOrange"},
    00560    { 36.0, 36.5,"OrangeRed"},
    00561    { 36.5, 40.0,"red"},
    00562    {  0.0,  0.0,NULL}
    00563 };
    00564
    00565 struct ColorStrip DCCstrip[] =
    00566 {
    00567    {-99.0, 0.0, "Black"},
    00568    {  0.0, 10.0,"Yellow"},
    00569    { 10.0, 20.0,"YellowGreen"},
    00570    { 20.0, 30.0,"Green"},
    00571    { 30.0, 40.0,"Aquamarine"},
    00572    { 40.0, 50.0,"Cyan"},
    00573    { 50.0, 60.0,"SkyBlue"},
    00574    { 60.0, 70.0,"Blue"},
    00575    { 70.0, 80.0,"Orchid"},
    00576    { 80.0, 90.0,"Magenta"},
    00577    { 90.0,100.0,"DarkViolet"},
    00578    { 0.0, 0.0,NULL}
    00579 };
    00580
    00581 struct ColorStrip DTDTstrip[] =
    00582 {
    00583    {-99.0,  -5.0,"brown"},
    00584    {- 5.0,  -3.0,"gold"},
    00585    { -3.0,  -1.5,"purple"},
    00586    { -1.5,  -0.5,"red"},
    00587    { -0.5,  -0.25,"OrangeRed"},
    00588    { -0.25,  0.0,"Orange"},
    00589    {  0.0,   0.25,"yellow"},
    00590    {  0.25,  0.5,"GreenYellow"},
    00591    {  0.5,   1.5,"green"},
    00592    {  1.5,   3.0,"aquamarine"},
    00593    {  3.0,   5.0,"cyan"},
    00594    {  5.0, 99.0,"blue"},
    00595    {  0.0,  0.0,NULL}
    00596 };
    00597
    00598 #define AMPLI_COLS 8
    00599
    00600 struct ColorStrip *Cstrip;
    00601 struct ColorStrip *Pallet[NUMPAL] =
    00602 { Autostrip, Ustrip, Vstrip, Tstrip, Pstrip, Qstrip,MarsTStrip,AmpliStrip,
    00603   Vegstrip, Tstripoce, Sstripoce, DCCstrip, DTDTstrip};
    00604
    00605 REAL VGAX;
    00606 REAL VGAY;
    00607 REAL CurVal;
    00608
    00609 REAL *Field;  // Pointer for ISO data
    00610 REAL *Ampli;  // Amplitudes of spherical harmonics
    00611 XColor *Acol; // Amplitude colors
    00612
    00613 Colormap colormap;
    00614
    00615 XColor xcolor1,xcolor2;
    00616 XColor Red,Green,Blue,Yellow,Grey,LightRed,DarkRed,LightBlue,DarkBlue;
    00617 XColor LightGreen,DarkGreen,Dummy;
    00618
    00619 unsigned long TSColor[10];
    00620
    00621 Window Win[NUMWIN];
    00622 int    win; // Current window
    00623 Window Cow; // Control bar
    00624 Window HelpWindow;
    00625
    00626 XTextProperty WinconName1;
    00627 XTextProperty WinconName3;
    00628 XTextProperty WinconPause;
    00629 XTextProperty WinconReady;
    00630 char *PauseTitle = "Run Paused";
    00631 char *ReadyTitle = "Press Start Button";
    00632
    00633 XEvent CowEvent;
    00634
    00635 XSizeHints WinSizeHints;
    00636 XSizeHints CowSizeHints;
    00637 int OutXSize,OutYSize;
    00638 int count;
    00639 XEvent report;
    00640 GC gc;
    00641
    00642 /*
    00643 char BigFontName[80] = "10x20";
    00644 char FixFontName[80] = "9x15bold";
    00645 char SubFontName[80] = "6x10";
    00646 */
    00647 char BigFontName[80] = "9x15bold";
    00648 char FixFontName[80] = "8x13";
    00649 char SubFontName[80] = "6x10";
    00650
    00651 XFontStruct *FixFont;
    00652 XFontStruct *SubFont;
    00653 XFontStruct *BigFont;
    00654 int FixFontHeight;
    00655 int SubFontHeight;
    00656 int BigFontHeight;
    00657 int FixFontWidth;
    00658 int SubFontWidth;
    00659 int BigFontWidth;
    00660 int Paused = 0;
    00661
    00662 char *display_name = NULL;
    00663 XWMHints wm_hints;
    00664 XClassHint class_hints;
    00665 Atom Delwin;
    00666
    00667 char *WindowTitle[NUMWIN];
    00668 XTextProperty WindowName[NUMWIN];
    00669 XTextProperty HelpName;
    00670
    00671 char *mona[12] =
    00672 {
    00673    "Jan","Feb","Mar",
    00674    "Apr","May","Jun",
    00675    "Jul","Aug","Sep",
    00676    "Oct","Nov","Dec"
    00677 };
    00678
    00679 char *wena[7] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
    00680
    00681 char datch[64];
    00682 char PlanetName[32] = "Earth";
    00683
    00684 char GUI_default[80] = "GUI.cfg";
    00685 char GUI_config[80] = "GUI_last_used.cfg";
    00686
    00687
    00688 #define PSDIM 30
    00689 char *pixelstar[PSDIM]  = {
    00690 "..............................",
    00691 "..............................",
    00692 "..............................",
    00693 "...**....**....**....**.......",
    00694 "...**....**....**....**.......",
    00695 "...**....**....**....**.......",
    00696 "...**....**....**....**.......",
    00697 "...**....**************.......",
    00698 "...**....**************.......",
    00699 "...**....**....**....**.......",
    00700 "...***...**....**....**.......",
    00701 "....******.....**....**.......",
    00702 ".....****......**....**.......",
    00703 "..............................",
    00704 "..............................",
    00705 "..............................",
    00706 "..............................",
    00707 "..............................",
    00708 "..............................",
    00709 "..............................",
    00710 "..............................",
    00711 "..............................",
    00712 ".......................*......",
    00713 "......................***.....",
    00714 "...................**.***.**..",
    00715 "...................**.***.**..",
    00716 "...................**.***.**..",
    00717 "...................****.****..",
    00718 "...................***...***..",
    00719 "...................***...***.."};
    00720
    00721 // Variables used for calculating "frames per second"
    00722
    00723 int fps;
    00724 int rmuf = 20;  // Rotating map update frequency [1/sec]
    00725 int rmui =  1;  // Rotating map update interval  [steps]
    00726 int SkipFreq;
    00727 int ThisSecond;
    00728 int LastSecond;
    00729 int LastStep;
    00730 int SecEvent;
    00731
    00732 int ndatim[6];  /* year, month, day, hour, minute, weekday */
    00733 int LastMinute; /* Last value of ndatim(4)                 */
    00734 int DeltaTime ; /* Computed timestep interval [min]        */
    00735
    00736 struct BMIstruct
    00737 {
    00738    int   Size;
    00739    int   Width;
    00740    int   Height;
    00741    short Planes;
    00742    short Count;
    00743    int   Compression;
    00744    int   SizeImage;
    00745    int   XPelsPerMeter;
    00746    int   YPelsPerMeter;
    00747    int   ClrUsed;
    00748    int   ClrImportant;
    00749 };
    00750
    00751 struct BMIstruct ImageBMI;
    00752
    00753 struct MapImageStruct
    00754 {
    00755    char   *d; // Bitmap data
    00756    int     w; // Image width
    00757    int     h; // Image height
    00758    int     f; // Rotation factor
    00759    float   l; // Reference longitude
    00760    float   r; // Rotation speed [deg/step]
    00761    XImage *X; // XImage structure
    00762 };
    00763
    00764 // Convert an RGB value to an X11 Pixel
    00765
    00766 unsigned long create_pixel(long red, long green, long blue)
    00767 {
    00768    if (ScreenD == 24)       // 24 bit true color
    00769    {
    00770        return red | green << 8 | blue << 16;
    00771    }
    00772    else if (ScreenD == 16)  // 16 bit RGB 565
    00773    {
    00774       return red >> 3 | (green >> 2) << 5 | (blue >> 3) << 11;
    00775    }
    00776    else return 0;
    00777 }
    00778
    00779 struct MapImageStruct MapHR; // Hires (2560x1280) Earth image
    00780 struct MapImageStruct MapLR[NUMWIN];
    00781
    00782 void ScaleImage(struct MapImageStruct *s, struct MapImageStruct *d)
    00783 {
    00784    int a,b,x,y;
    00785    unsigned long px;
    00786    unsigned long h,w;
    00787    double f,g;
    00788
    00789    if (d->X) XDestroyImage(d->X);
    00790    w = (d->w + 7) & 0xFFF8;
    00791    h =  d->h;
    00792    d->d = malloc(4 * w * h);
    00793    d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0,
    00794                   d->d,w,h,8,0);
    00795
    00796    f = (double)s->w / (double)d->w;
    00797    g = (double)s->h / (double)d->h;
    00798
    00799    for (y = 0 ; y < d->h ; ++y)
    00800    for (x = 0 ; x < d->w ; ++x)
    00801    {
    00802        a = x * f;
    00803        b = y * g;
    00804        XPutPixel(d->X,x,y,XGetPixel(s->X,a,b));
    00805    }
    00806 }
    00807
    00808
    00809 void PolarImage(struct MapImageStruct *s, struct MapImageStruct *d)
    00810 {
    00811    int a,b,x,y;
    00812    unsigned long h,w;
    00813    double f,lfa,xnp,ynp,xsp,ysp,dx,dy;
    00814
    00815    if (d->X) XDestroyImage(d->X);
    00816    w = (d->w + 7) & 0xFFF8;
    00817    h =  d->h;
    00818    d->d = malloc(4 * w * h);
    00819    d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0,
    00820                   d->d,w,h,8,0);
    00821
    00822    f   = (double)s->h / (double)d->h;
    00823    lfa = (s->w-1) / (2.0 * M_PI);
    00824    xnp = (d->w) * 0.25;
    00825    ynp = (d->h) * 0.50;
    00826    xsp = (d->w) * 0.75;
    00827    ysp = ynp;
    00828
    00829    for (y = 0 ; y < d->h   ; ++y)
    00830    {
    00831       dy = ynp - y;
    00832       for (x = 0 ; x < d->w/2 ; ++x) /* Northern hemisphere */
    00833       {
    00834          dx = xnp - x;
    00835          a = atan2(dx,dy) * lfa;
    00836          b = sqrt(dx * dx + dy * dy) * f;
    00837          if (a < 0.0) a += (s->w);
    00838          if (a >= 0 && a < s->w && b >= 0 && b <= s->h/2)
    00839               XPutPixel(d->X,x,y,XGetPixel(s->X,a,b));
    00840          else XPutPixel(d->X,x,y,BlackPix);
    00841       }
    00842       dy = ysp - y;
    00843       for (x = d->w/2 ; x < d->w ; ++x) /* Southern hemisphere */
    00844       {
    00845          dx = x - xsp;
    00846          a = atan2(dx,dy) * lfa;
    00847          b = s->h - f * sqrt(dx * dx + dy * dy);
    00848          if (a < 0.0) a += (s->w);
    00849          if (a >= 0 && a < s->w && b >= 0 && b >= s->h/2 && b <= s->h)
    00850               XPutPixel(d->X,x,y,XGetPixel(s->X,a,b));
    00851          else XPutPixel(d->X,x,y,BlackPix);
    00852       }
    00853    }
    00854 }
    00855
    00856
    00857 void RevOrtho(double R, double lam0, double phi0, int xx, int yy, double *lam, double *phi)
    00858 {
    00859    double rho,c,rhoq,x,y;
    00860
    00861    x = xx;
    00862    y = yy;
    00863
    00864    rhoq = x*x + y*y;
    00865    rho  = sqrt(rhoq);
    00866    if (rho > R)
    00867    {
    00868       *phi = 999.9;
    00869       *lam = 999.9;
    00870    }
    00871    else if (rho > R / 100000.0)
    00872    {
    00873       c   = asin(rho / R);
    00874       *phi = asin(cos(c) * sin(phi0) + y * sin(c) * cos(phi0) / rho);
    00875       *lam = lam0 + atan2(x * sin(c) , rho * cos(phi0) * cos(c) - y * sin(phi0) * sin(c));
    00876    }
    00877    else
    00878    {
    00879       *phi = phi0;
    00880       *lam = lam0;
    00881    }
    00882    // printf("[%6.1lf / %6.1lf] --> (%6.1lf / %6.1lf)\n",x,y,*lam,*phi);
    00883 }
    00884
    00885 /* ==================================================== */
    00886 /* AzimuthalImage - Display map in azimuthal projection */
    00887 /* ==================================================== */
    00888
    00889 void AzimuthalImage(struct MapImageStruct *s, struct MapImageStruct *d)
    00890 {
    00891    int lam;           // lambda pixel coordinate in source image
    00892    int phi;           // phi    pixel coordinate in source image
    00893    int x  ;           // x      pixel coordinate in destination image
    00894    int y  ;           // y      pixel coordinate in destination image
    00895    int dxc;           // pixel coordinate of centre     position
    00896    int dxl;           // pixel coordinate of left  most position
    00897    int dxr;           // pixel coordinate of right most position
    00898    int dx ;           // centre relative x position
    00899    int dy ;           // centre relative y position
    00900    int p00;           // euqator
    00901    int l00;           // reference longitude
    00902
    00903    unsigned int dih;  // destination image height
    00904    unsigned int diw;  // destination image width
    00905    unsigned int dpw;  // destination image padded width
    00906
    00907    double rad;        // pixel radius of new image
    00908    double ysc;        // yscale = source height / destination height
    00909    double rho;        // distance from centre
    00910    double xpi;        // x scale factor = 2 * PI / width
    00911    double ypi;        // y scale factor =     PI / height
    00912    double xrf;
    00913    double yrf;
    00914
    00915    XImage *sX;        // source      image
    00916    XImage *dX;        // destination image
    00917
    00918
    00919    // Destroy old image structure inclusive data storage
    00920
    00921    if (d->X) XDestroyImage(d->X);
    00922
    00923    // Set width of new image
    00924
    00925    diw = d->w;
    00926
    00927    // Pad width of new image to a multiple of 8
    00928
    00929    dpw = (diw + 7) & 0xFFF8;
    00930
    00931    // Set height of new image
    00932
    00933    dih =  d->h;
    00934
    00935    // Allocate space for image data
    00936
    00937    d->d = calloc(dpw * dih,4);
    00938
    00939    // Create image structure
    00940
    00941    dX = d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0,d->d,dpw,dih,8,0);
    00942    sX = s->X;
    00943
    00944    p00 = s->h >> 1;
    00945    rad = dih  >> 1;
    00946    dxc = diw  >> 1;
    00947    dxl = MAX(dxc - rad,   0);
    00948    dxr = MIN(dxc + rad, diw);
    00949    xpi = s->w / M_PI * 0.5;
    00950    ypi = s->h / M_PI;
    00951    ysc = (double)s->h / (double)dih;
    00952    l00 = (int)((d->l * s->w) / 360 + s->w/2) % s->w;
    00953    xrf = (double)diw / pow(2.0,31),
    00954    yrf = (double)dih / pow(2.0,31);
    00955
    00956    // Paint some stars on the sky
    00957
    00958    srandom(Seed);
    00959    for (y = 0 ; y < (diw * dih) >> 8  ; ++y)
    00960       XPutPixel(dX,xrf*random(),yrf*random(),WhitePix);
    00961
    00962    for (y = 0 ; y < dih ; ++y)
    00963    {
    00964       dy  = y - rad;
    00965       phi = y * ysc;
    00966       for (x = dxl ; x < dxr ; ++x)
    00967       {
    00968          dx = x - dxc;
    00969          rho = sqrt(dx * dx + dy * dy);
    00970          if (rho < rad)
    00971          {
    00972             lam = l00 + xpi * atan2(dx / rad, cos(asin(rho / rad)));
    00973             phi = p00 + ypi *  asin(dy / rad);
    00974             XPutPixel(dX,x,y,XGetPixel(sX,lam,phi));
    00975          }
    00976       }
    00977    }
    00978 }
    00979
    00980
    00981 void SwapIEEE16(char W[2])
    00982 {
    00983    char B;
    00984
    00985    B = W[0]; W[0] = W[1]; W[1] = B;
    00986 }
    00987
    00988 void SwapIEEE32(char W[4])
    00989 {
    00990    char B;
    00991
    00992    B = W[0]; W[0] = W[3]; W[3] = B;
    00993    B = W[1]; W[1] = W[2]; W[2] = B;
    00994 }
    00995
    00996 int ReadINT(FILE *fpi)
    00997 {
    00998    int k;
    00999    fread(&k,sizeof(k),1,fpi);
    01000    if (BigEndian) SwapIEEE32((char *)&k);
    01001    return k;
    01002 }
    01003
    01004 short ReadSHORT(FILE *fpi)
    01005 {
    01006    short k;
    01007    fread(&k,sizeof(k),1,fpi);
    01008    if (BigEndian) SwapIEEE16((char *)&k);
    01009    return k;
    01010 }
    01011
    01012 void ReadImage(struct MapImageStruct *ei, char *filename)
    01013 {
    01014    char ch;
    01015    int i,n,x,y,z;
    01016    long r,g,b;
    01017    int FileSize;
    01018    int Reserved;
    01019    int OffBits;
    01020    int PicBytes;
    01021    int ImgBytes;
    01022    int PadWidth;
    01023    int PadBytes;
    01024    int bpp;
    01025    int byr;
    01026    FILE *fp;
    01027    unsigned char *BuffImageData;
    01028
    01029    if (!(fp = fopen(filename,"r"))) return;
    01030    ch = fgetc(fp);
    01031    if (ch != 'B') return;
    01032    ch = fgetc(fp);
    01033    if (ch != 'M') return;
    01034    FileSize = ReadINT(fp);
    01035    Reserved = ReadINT(fp);
    01036    OffBits  = ReadINT(fp);
    01037
    01038    if (Debug)
    01039    {
    01040       printf("Properties of %s:\n",filename);
    01041       printf("FileSize   = %d\n",FileSize);
    01042       printf("FileOffset = %d\n",OffBits);
    01043    }
    01044
    01045    ImageBMI.Size          = ReadINT(fp);
    01046    ImageBMI.Width         = ReadINT(fp);
    01047    ImageBMI.Height        = ReadINT(fp);
    01048    ImageBMI.Planes        = ReadSHORT(fp);
    01049    ImageBMI.Count         = ReadSHORT(fp);
    01050    ImageBMI.Compression   = ReadINT(fp);
    01051    ImageBMI.SizeImage     = ReadINT(fp);
    01052    ImageBMI.XPelsPerMeter = ReadINT(fp);
    01053    ImageBMI.YPelsPerMeter = ReadINT(fp);
    01054    ImageBMI.ClrUsed       = ReadINT(fp);
    01055    ImageBMI.ClrImportant  = ReadINT(fp);
    01056
    01057    PadWidth = (ImageBMI.Width + 7) & 0xFFF8;
    01058    bpp      =  ImageBMI.Count >> 3;
    01059    PadBytes = (4 - ((ImageBMI.Width * bpp) % 4)) % 4 ;
    01060
    01061    if (Debug)
    01062    {
    01063       printf("BMI Size     = %d\n",ImageBMI.Size);
    01064       printf("BMI Width    = %d\n",ImageBMI.Width);
    01065       printf("BMI Height   = %d\n",ImageBMI.Height);
    01066       printf("BMI Planes   = %d\n",ImageBMI.Planes);
    01067       printf("BMI Count    = %d\n",ImageBMI.Count);
    01068       printf("BMI ClrUsed  = %d\n",ImageBMI.ClrUsed);
    01069       printf("Pad Bytes    = %d\n",PadBytes);
    01070       printf("ScreenD= %d\n",ScreenD);
    01071    }
    01072
    01073    PicBytes = (bpp * ImageBMI.Width + PadBytes) * ImageBMI.Height;
    01074    ImgBytes = 4 * PadWidth * ImageBMI.Height;
    01075    ei->d = calloc(ImgBytes,1);
    01076    BuffImageData = malloc(PicBytes);
    01077    n = fread(BuffImageData,PicBytes,1,fp);
    01078    fclose(fp);
    01079
    01080    ei->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0,
    01081                   ei->d,PadWidth,ImageBMI.Height,8,0);
    01082
    01083    for (y = 0 ; y < ImageBMI.Height ; ++y)
    01084    for (x = 0 ; x < ImageBMI.Width  ; ++x)
    01085    {
    01086        i = bpp * x + (ImageBMI.Height - 1 - y) * (ImageBMI.Width*bpp+PadBytes);
    01087        r = BuffImageData[i  ];
    01088        g = BuffImageData[i+1];
    01089        b = BuffImageData[i+2];
    01090        XPutPixel(ei->X, x, y, create_pixel(r,g,b));
    01091    }
    01092    free(BuffImageData);
    01093    ei->w = ImageBMI.Width;
    01094    ei->h = ImageBMI.Height;
    01095 }
    01096
    01097
    01098 void ntocdat(void)
    01099 {
    01100    if (ndatim[1] > 0)
    01101    {
    01102       if (ndatim[5] >= 0)
    01103          sprintf(datch,"%s %2d-%s-%04d %2d:%02d",wena[ndatim[5]],ndatim[2],mona[ndatim[1]-1],
    01104            ndatim[0],ndatim[3],ndatim[4]);
    01105       else
    01106       sprintf(datch,"%2d-%s-%04d %2d:%02d",ndatim[2],mona[ndatim[1]-1],
    01107            ndatim[0],ndatim[3],ndatim[4]);
    01108    }
    01109 }
    01110
    01111 /* ============================================== */
    01112 /* CharAlloc - Allocate space for character array */
    01113 /* ============================================== */
    01114
    01115 char *CharAlloc(int bytes,char *array_name)
    01116 {
    01117    char *result = NULL;
    01118    if (bytes > 0)
    01119    {
    01120       result = (char *)calloc(bytes, sizeof(char));
    01121       if (!result || Debug)
    01122       {
    01123          if (!result) printf("*** Out of Memory *** on ");
    01124          printf("CharAlloc:  at%10p %6d char for %-30.30s\n",
    01125                 result,bytes,array_name);
    01126       }
    01127    }
    01128    return(result);
    01129 }
    01130
    01131 /* ======================================= */
    01132 /* IntAlloc - Allocate space for int array */
    01133 /* ======================================= */
    01134
    01135 int *IntAlloc(int words,char *array_name)
    01136 {
    01137    int *result = NULL;
    01138    if (words > 0)
    01139    {
    01140       result = (int *) calloc(words, sizeof(int));
    01141       if (!result || Debug)
    01142       {
    01143          if (!result) printf("*** Out of Memory *** on ");
    01144          printf("IntAlloc:   at%10p %6d int for %s\n",
    01145                result,words,array_name);
    01146       }
    01147    }
    01148    return(result);
    01149 }
    01150
    01151 /* =========================================== */
    01152 /* FloatAlloc - Allocate space for float array */
    01153 /* =========================================== */
    01154
    01155 float *FloatAlloc(int words, char *array_name)
    01156 {
    01157    float *result = NULL;
    01158    if (words > 0)
    01159    {
    01160       result = (float *) calloc(words, sizeof(float));
    01161       if (!result || Debug)
    01162       {
    01163          if (!result) printf("*** Out of Memory *** on ");
    01164          printf("FloatAlloc: at%10p %6d float for %s\n",
    01165                result,words,array_name);
    01166       }
    01167    }
    01168    return(result);
    01169 }
    01170
    01171 /* ========================================== */
    01172 /* SizeAlloc - Allocate space for sized array */
    01173 /* ========================================== */
    01174
    01175 void *SizeAlloc(int words, int Size, char *array_name)
    01176 {
    01177    void *result = NULL;
    01178    if (words > 0)
    01179    {
    01180       result = (void *) calloc(words, Size);
    01181       if (!result || Debug)
    01182       {
    01183          if (!result) printf("*** Out of Memory *** on ");
    01184          printf("SizeAlloc:  at%10p %6d void for %s\n",
    01185                result,words,array_name);
    01186       }
    01187    }
    01188    return(result);
    01189 }
    01190
    01191 void LoadFonts(void)
    01192 {
    01193    if ((FixFont = XLoadQueryFont(display,FixFontName)) == NULL)
    01194    {
    01195       printf("%s: Cannot open %s font\n",progname,FixFontName);
    01196       exit(-1);
    01197    }
    01198    if ((SubFont = XLoadQueryFont(display,SubFontName)) == NULL)
    01199    {
    01200       SubFont = FixFont;
    01201    }
    01202    if ((BigFont = XLoadQueryFont(display,BigFontName)) == NULL)
    01203    {
    01204       if ((BigFont = XLoadQueryFont(display,"10x20")) == NULL)
    01205       {
    01206          printf("%s: Cannot open %s font\n",progname,BigFontName);
    01207          exit(-1);
    01208       }
    01209    }
    01210    FixFontWidth  = XTextWidth(FixFont,"X",1);
    01211    SubFontWidth  = XTextWidth(SubFont,"X",1);
    01212    BigFontWidth  = XTextWidth(BigFont,"X",1);
    01213    FixFontHeight = FixFont->ascent + FixFont->descent;
    01214    SubFontHeight = SubFont->ascent + SubFont->descent;
    01215    BigFontHeight = BigFont->ascent + BigFont->descent;
    01216 }
    01217
    01218 int AllocateColorCells(struct ColorStrip cs[])
    01219 {
    01220    int i = 0;
    01221    XColor xcolor1,xcolor2;
    01222
    01223    while (cs[i].Name)
    01224    {
    01225       XAllocNamedColor(display,colormap,cs[i].Name,&xcolor1,&xcolor2);
    01226       cs[i].pixel = xcolor1.pixel;
    01227       ++i;
    01228    }
    01229    return i;
    01230 }
    01231
    01232 void CalcButtonAreas(void)
    01233 {
    01234    int of,ds,bh,fh,fw,j;
    01235
    01236    of = OffsetY;
    01237    ds = 10;
    01238    bh = 30;
    01239    fh = BigFontHeight;
    01240    fw = BigFontWidth;
    01241
    01242    /* 1. Stop Button */
    01243
    01244    StopButton[0].y += OffsetY;
    01245    StopButton[1].y += OffsetY;
    01246    StopButton[2].y += OffsetY;
    01247    StopButton[3].y += OffsetY;
    01248
    01249    Stop_XL = ds;
    01250    Stop_XH = Stop_XL + bh;
    01251    Stop_YL = of + ds;
    01252    Stop_YH = Stop_YL + bh;
    01253
    01254    /* 2. Start Button */
    01255
    01256    Start_XL = Stop_XH  + ds;
    01257    Start_XH = Start_XL + bh;
    01258    Start_YL = Stop_YL;
    01259    Start_YH = Stop_YH;
    01260
    01261    StartButton[0].y += OffsetY;
    01262    StartButton[1].y += OffsetY;
    01263    StartButton[2].y += OffsetY;
    01264
    01265    /* 3. Pause Button */
    01266
    01267    Pause_XL = Start_XH + 15;
    01268    Pause_XH = Start_XH + 35;
    01269    Pause_YL = Start_YL;
    01270    Pause_YH = Start_YH;
    01271
    01272    PauseButton1[0].y += OffsetY;
    01273    PauseButton1[1].y += OffsetY;
    01274    PauseButton1[2].y += OffsetY;
    01275    PauseButton1[3].y += OffsetY;
    01276
    01277    PauseButton2[0].y += OffsetY;
    01278    PauseButton2[1].y += OffsetY;
    01279    PauseButton2[2].y += OffsetY;
    01280    PauseButton2[3].y += OffsetY;
    01281
    01282    /* 4. Help  Button */
    01283
    01284    Help_XL = 200;
    01285    Help_XH = Help_XL + 5 * fw;
    01286    Help_YL = Pause_YL;
    01287    Help_YH = Pause_YH;
    01288
    01289    /* 5. Minus & FBWD Button */
    01290
    01291    Minus_XL = 300;
    01292    Minus_XH = Minus_XL + fh;
    01293    Minus_YL = Pause_YL + (bh - fh) / 2;
    01294    Minus_YH = Minus_YL + fh;
    01295
    01296    FBWD_XH = Minus_XL - ds/2;
    01297    FBWD_XL = FBWD_XH - fh;
    01298    FBWD_YL = Minus_YL;
    01299    FBWD_YH = Minus_YH;
    01300
    01301    /* 6. Parameter Change Area */
    01302
    01303    Parc_XL = Minus_XH + ds;
    01304    Parc_XH = Parc_XL  + fw * 14;
    01305    Parc_YL = Minus_YL;
    01306    Parc_YH = Minus_YH;
    01307    Parc_XD = Parc_XH - Parc_XL;
    01308    Parc_YD = Parc_YH - Parc_YL;
    01309
    01310    /* 7. Plus & FFWD Button */
    01311
    01312    Plus_XL = Parc_XH + ds;
    01313    Plus_XH = Plus_XL + fh;
    01314    Plus_YL = Minus_YL;
    01315    Plus_YH = Minus_YH;
    01316
    01317    FFWD_XL = Plus_XH + ds/2;
    01318    FFWD_XH = FFWD_XL + fh;
    01319    FFWD_YL = Plus_YL;
    01320    FFWD_YH = Plus_YH;
    01321
    01322    /* 8. Grid on/off box */
    01323
    01324    Grid_XL = Stop_XL;
    01325    Grid_XH = Grid_XL + FixFontHeight;
    01326    Grid_YL = Stop_YH + 3 * BigFontHeight / 2;
    01327    Grid_YH = Grid_YL + FixFontHeight;
    01328
    01329    /* Window status and select boxes */
    01330
    01331    Wbox_XL = 580;
    01332    Wbox_XH = Wbox_XL + FixFontHeight;
    01333    Wbox_YL =   0;
    01334    Wbox_YH = NumWin  * FixFontHeight;
    01335 }
    01336
    01337
    01338 /* Hack for getting information of window decoration  */
    01339 /* especially borderwidth and titleheight             */
    01340 /* These are properties of the window manager and are */
    01341 /* usually adjustable by the user                     */
    01342
    01343 void TestWindow(int xx, int yy, int wi, int he, int *x, int *y,
    01344                 int *X, int *Y, unsigned int *W, unsigned int *H)
    01345 {
    01346    unsigned int DepthReturn  = 0;
    01347    unsigned int BorderReturn = 0;
    01348    Window TW,Parent,Child;
    01349
    01350    TW = XCreateWindow(display,RootWindow(display,screen_num),
    01351         xx,yy,wi,he,                   // x,y,w,h
    01352         0,CopyFromParent,InputOutput,  // border, depth, class
    01353           CopyFromParent,0,NULL);      // visual, valuemask, attributes
    01354    XSelectInput(display,TW,ExposureMask);
    01355    XMapWindow(display,TW);
    01356    XMoveWindow(display,TW,xx,yy);
    01357    XNextEvent(display,&CowEvent);            // Wait until WM mapped it
    01358    XGetGeometry(display,TW,&Parent,x,y,W,H,&BorderReturn,&DepthReturn);
    01359    XTranslateCoordinates(display,TW,Parent,0,0,X,Y,&Child);
    01360    XDestroyWindow(display,TW);
    01361
    01362    if (Debug)
    01363    {
    01364       printf("TW[%x][%x]: %4d / %4d   %4d x %4d x %2d [%2d:%2d]\n",
    01365               (int)TW,(int)Parent,*x,*y,*W,*H,DepthReturn,*X,*Y);
    01366    }
    01367 }
    01368
    01369
    01370 void CreateTestWindow(void)
    01371 {
    01372    int X,Y,xp,yp;
    01373    unsigned int W,H;
    01374
    01375    // Open a test window with displacement x = 100 and y = 100
    01376    // Test the returned coordinates for upper left corner
    01377    // and compute left margin (border) and top margin (title bar)
    01378
    01379    TestWindow(100,100,100,100,&xp,&yp,&X,&Y,&W,&H);
    01380
    01381    // Left margin
    01382
    01383    if (X >= 100 && X < 110) WinLM = X - 100;
    01384
    01385    // Right margin
    01386
    01387    WinRM = WinLM;
    01388
    01389    // Top margin
    01390
    01391         if (Y >= 100 && Y < 150) WinTM = Y - 100;
    01392    else if (Y >    0 && Y <  50) WinTM = Y;
    01393
    01394    // Bottom margin
    01395
    01396    WinBM = WinLM;
    01397
    01398    // Open a full screen test window
    01399    // Test the returned coordinates for upper left corner
    01400    // the y displacement should be WinTM plus Windowmanager menu bar
    01401
    01402    TestWindow(0,0,ScreenW,ScreenH,&xp,&yp,&X,&Y,&W,&H);
    01403
    01404    // Window manager menu bar on top
    01405
    01406    if (yp > WinTM) WM_top_area = yp - WinTM;
    01407
    01408
    01409    // Last usable scan line
    01410
    01411    ScreenBot = WM_top_area + WinTM + H;
    01412    if (ScreenBot > ScreenH) ScreenBot = ScreenH;
    01413
    01414    // Are we running on a 27" iMac :-)
    01415
    01416    if (ScreenW == 2560 && ScreenH > 1400) ScreenBot -= 100;
    01417
    01418    if (Debug)
    01419    {
    01420       printf("Screen       = %4d x %4d x %2d\n",ScreenW,ScreenH,ScreenD);
    01421       printf("ScreenBot    = %4d\n",ScreenBot);
    01422       printf("Top reserved = %4d\n",WM_top_area);
    01423       printf("Bot reserved = %4d\n",ScreenH-ScreenBot);
    01424       printf("Left  margin = %4d\n",WinLM);
    01425       printf("Right margin = %4d\n",WinRM);
    01426       printf("Top   margin = %4d\n",WinTM);
    01427       printf("Bot   margin = %4d\n",WinBM);
    01428    }
    01429 }
    01430
    01431
    01432 void TrimCopy(char *Trim, char *Line, int n)
    01433 {
    01434    int l;
    01435    char *s;
    01436
    01437    l = strlen(Line);
    01438    Line[--l] = 0;                          // Remove linefeed
    01439    while (Line[l-1] == ' ') Line[--l] = 0; // Remove trailing blanks
    01440    s = Line;
    01441    while (*s == ' ') ++s;                  // Remove leading blanks
    01442    strncpy(Trim,s,n);
    01443 }
    01444
    01445
    01446 int ReadConfig(char *filename)
    01447 {
    01448    FILE *fp;
    01449    int i,w,l,s,p;
    01450    char Line[256];
    01451    char Plot[80];
    01452    char Palette[80];
    01453    char Projection[80];
    01454    char Rotation[80];
    01455    char *t;
    01456
    01457    fp = fopen(filename,"r");
    01458    if (!fp) return 1;
    01459
    01460    w = -2;
    01461    s = -1;
    01462    p = -1;
    01463    while (!feof(fp))
    01464    {
    01465       t = fgets(Line,256,fp);
    01466       if (Line[0] == '#') continue;
    01467       if (strncmp(Line,"[Window "    , 8) == 0) w = atoi(Line+8);
    01468       if (strncmp(Line,"[Control"    , 8) == 0) w = -1;
    01469       if (strncmp(Line,"[Scalar "    , 8) == 0) s = atoi(Line+8);
    01470       if (strncmp(Line,"WinRows ="   , 9) == 0)
    01471       {
    01472          WinRows = atoi(Line+9);
    01473          if (WinRows < 1) WinRows = 1;
    01474          if (WinRows > 3) WinRows = 3;
    01475          NumWin = WinCols * WinRows;
    01476       }
    01477       if (strncmp(Line,"WinCols ="   , 9) == 0)
    01478       {
    01479          WinCols = atoi(Line+9);
    01480          if (WinCols < 1) WinCols = 1;
    01481          if (WinCols > 3) WinCols = 3;
    01482          NumWin = WinCols * WinRows;
    01483       }
    01484       if (strncmp(Line,"[Parameter " ,11) == 0)
    01485       {
    01486          p = atoi(Line+11);
    01487          if (p >= Parcs) Parcs = p+1;
    01488       }
    01489       if (strncmp(Line,"Geometry:",9) == 0 && w >= 0 && w < NUMWIN)
    01490       {
    01491          sscanf(Line+9,"%d %d %d %d",&WinAtt[w].w,&WinAtt[w].h,
    01492                                      &WinAtt[w].x,&WinAtt[w].y);
    01493          WinAtt[w].active = 1;
    01494       }
    01495       if (strncmp(Line,"Inactive:",9) == 0 && w >= 0 && w < NUMWIN)
    01496       {
    01497          sscanf(Line+9,"%d %d %d %d",&WinAtt[w].w,&WinAtt[w].h,
    01498                                      &WinAtt[w].x,&WinAtt[w].y);
    01499          WinAtt[w].active = 0;
    01500       }
    01501       if (strncmp(Line,"Geometry:",9) == 0 && w == -1)
    01502       {
    01503          sscanf(Line+9,"%d %d %d %d",&CowW,&CowH,&CowX,&CowY);
    01504       }
    01505       if (strncmp(Line,"Title:",6) == 0 && w >= -1 && w < NUMWIN)
    01506       {
    01507          if (w == -1) TrimCopy(PlanetName,Line+6,sizeof(PlanetName)-1);
    01508          else         TrimCopy(WindowTitle[w]+wto,Line+6,79-wto);
    01509       }
    01510       if (strncmp(Line,"Array:",6) == 0 && w >= 0 && w < NUMWIN)
    01511          TrimCopy(WinAtt[w].array_name,Line+6,79);
    01512       if (strncmp(Line,"Plot:",5) == 0 && w >= 0 && w < NUMWIN)
    01513       {
    01514          TrimCopy(Plot,Line+5,79);
    01515          for (i=0 ; i < IsoTypes ; ++i)
    01516             if (!strcmp(Plot,IsoNames[i])) WinAtt[w].Plot = i;
    01517       }
    01518       if (strncmp(Line,"Projection:",11) == 0 && w >= 0 && w < NUMWIN)
    01519       {
    01520          TrimCopy(Projection,Line+11,79);
    01521          for (i=0 ; i < MAXMAPS ; ++i)
    01522             if (!strcmp(Projection,ProNames[i])) MapPro[w] = i;
    01523       }
    01524       if (strncmp(Line,"Rotation factor:",15) == 0 && w >= 0 && w < NUMWIN)
    01525       {
    01526          TrimCopy(Rotation,Line+15,79);
    01527          MapLR[w].f = atoi(Rotation);
    01528       }
    01529       if (strncmp(Line,"Palette:",8) == 0 && w >= 0 && w < NUMWIN)
    01530       {
    01531          TrimCopy(Palette,Line+8,79);
    01532          for (i=0 ; i < PalTypes ; ++i)
    01533             if (!strcmp(Palette,PalNames[i])) WinAtt[w].Palette = i;
    01534       }
    01535
    01536       // Dimension for time axis
    01537
    01538       if (strncmp(Line,"DimT:" ,5) == 0) DimT = atoi(Line+5);
    01539
    01540       // Attributes of scalars for timeseries windows
    01541
    01542       if (strncmp(Line,"Name:" ,5) == 0 && s >= 0 && s < NUMSCALARS)
    01543          TrimCopy(TSName[s],Line+5,79);
    01544       if (strncmp(Line,"Sub:"  ,4) == 0 && s >= 0 && s < NUMSCALARS)
    01545          TrimCopy(TSubsc[s],Line+4,79);
    01546       if (strncmp(Line,"Unit:" ,5) == 0 && s >= 0 && s < NUMSCALARS)
    01547          TrimCopy(TSUnit[s],Line+5,79);
    01548       if (strncmp(Line,"Scale:",6) == 0 && s >= 0 && s < NUMSCALARS)
    01549          TrimCopy(TScale[s],Line+6,79);
    01550
    01551       // Attributes of parameter in change menu
    01552
    01553       if (strncmp(Line,"ParName:",8) == 0 && p >= 0 && p < PARCS)
    01554          TrimCopy(Parc[p].Name,Line+8,6);
    01555       if (strncmp(Line,"ParInc:" ,7) == 0 && p >= 0 && p < PARCS)
    01556          Parc[p].Inc = atof(Line+7);
    01557       if (strncmp(Line,"ParMin:" ,7) == 0 && p >= 0 && p < PARCS)
    01558          Parc[p].Min = atof(Line+7);
    01559       if (strncmp(Line,"ParMax:" ,7) == 0 && p >= 0 && p < PARCS)
    01560          Parc[p].Max = atof(Line+7);
    01561       if (strcmp(Parc[p].Name,"SELLON") == 0) Parc[p].Inc = 360.0 / (2.0 * Latitudes);
    01562    }
    01563    fclose(fp);
    01564    return 0;
    01565 }
    01566
    01567
    01568 void CreateControlWindow(void)
    01569 {
    01570    int X,Y,W,H,B,D,x,y;
    01571    char Title1[256];
    01572    char *WinconTitle1;
    01573    char *WinconTitle3 = {"RUN finished - click on red stop button"};
    01574    Window Rootwin;
    01575    Window Child;
    01576
    01577    strcpy(Title1,"Unknown model");
    01578    if (Model == 0) // PUMA
    01579    {
    01580       if (MRpid < 0)
    01581          strcpy(Title1,"PUMA - KlimaCampus Hamburg");
    01582       else
    01583          sprintf(Title1,"Run %d: PUMA - KlimaCampus Hamburg",MRpid);
    01584    }
    01585    else if (Model == 1) sprintf(Title1,"SAM - KlimaCampus");
    01586    else if (Model == 2)
    01587    {
    01588        if (MRpid < 0)
    01589        sprintf(Title1,"Planet Simulator (%s) - KlimaCampus",PlanetName);
    01590        else
    01591        sprintf(Title1,"Run %d: Planet Simulator (%s) - KlimaCampus",MRpid,PlanetName);
    01592    }
    01593    else if (Model == 3) sprintf(Title1,"Planet Simulator / LSG - KlimaCampus");
    01594    else printf("*** unknown model number %d in pumax ***\n",Model);
    01595    WinconTitle1 = Title1;
    01596    if (CowW < 920 || CowW > ScreenW) CowW = 920;
    01597    if (NumWin < 5) CowH = 6 * FixFontHeight + 5;
    01598    else            CowH = NumWin * FixFontHeight + 5;
    01599    if (CowX < 0 || CowX > ScreenW - CowW) CowX = (ScreenW - CowW) / 2;
    01600    if (CowY < 0 || CowY > ScreenBot - CowH - WinTM - WinBM) CowY = ScreenBot - CowH - WinTM - WinBM;
    01601    CowSizeHints.flags      = PPosition | PSize | PMinSize | PMaxSize;
    01602    CowSizeHints.min_width  = CowW;
    01603    CowSizeHints.min_height = CowH;
    01604    CowSizeHints.max_width  = ScreenW - WinLM - WinRM;
    01605    CowSizeHints.max_height = CowH;
    01606    if (MRnum == 2 && MRpid == 1) CowX += ScreenW;
    01607    if (Debug) printf("Control Window %d/%d %dx%d\n",CowX,CowY,CowW,CowH);
    01608    Cow = XCreateWindow(display,RootWindow(display,screen_num), // display, parent
    01609                CowX,CowY,CowW,CowH,
    01610                BorderWidth,CopyFromParent,InputOutput,         // border, depth, class
    01611                CopyFromParent,0,NULL);                         // visual, valuemask, attributes
    01612    XStringListToTextProperty(&WinconTitle1,1,&WinconName1);
    01613    XStringListToTextProperty(&WinconTitle3,1,&WinconName3);
    01614    XStringListToTextProperty(&PauseTitle,1,&WinconPause);
    01615    XStringListToTextProperty(&ReadyTitle,1,&WinconReady);
    01616    XSetWMProtocols(display,Cow,&Delwin,1);
    01617    XSetWMProperties(display,Cow,&WinconName1,NULL,
    01618                 NULL,0,&CowSizeHints,&wm_hints,&class_hints);
    01619    XSelectInput(display,Cow,ButtonPressMask | KeyPressMask | ExposureMask);
    01620    XMapWindow(display,Cow);
    01621 }
    01622
    01623
    01624 void ShowStep(void)
    01625 {
    01626    char Text[80];
    01627    XSetFont(display, gc, BigFont->fid);
    01628    XSetForeground(display,gc,BlackPix);
    01629    XSetBackground(display,gc,Grey.pixel);
    01630    ntocdat();
    01631    if (ndatim[5] == 6) XSetForeground(display,gc,Red.pixel); // sunday
    01632    XDrawImageString(display,Cow,gc,10,BigFontHeight,datch,strlen(datch));
    01633    XSetForeground(display,gc,BlackPix);
    01634    if (ShowQueue)
    01635    {
    01636       sprintf(Text,"%8d Events   ",XPending(display));
    01637       XDrawImageString(display,Cow,gc,10,60 + BigFontHeight,Text,strlen(Text));
    01638    }
    01639    else if (fps > 1)
    01640    {
    01641       if (SkipFreq < 2) sprintf(Text,"%5d fps",fps);
    01642       else sprintf(Text,"%5d fps [%d]",fps,SkipFreq);
    01643       XDrawImageString(display,Cow,gc,10,60 + BigFontHeight,Text,strlen(Text));
    01644    }
    01645 }
    01646
    01647
    01648 int FormatVal(char *Name, float V, char *Text)
    01649 {
    01650    char Format[80];
    01651
    01652    if (V > 9999.9 || V < -999.9)
    01653    {
    01654       sprintf(Text,"%6.6s = *****",Name);
    01655       return strlen(Text);
    01656    }
    01657    else if (V > 999.99  ) strcpy(Format,"%6.6s =%6.1f");
    01658    else if (V >  99.999 ) strcpy(Format,"%6.6s =%6.2f");
    01659    else if (V >   9.9999) strcpy(Format,"%6.6s =%6.3f");
    01660    else if (V >   0.0   ) strcpy(Format,"%6.6s =%6.4f");
    01661    else if (V >  -9.9   ) strcpy(Format,"%6.6s =%6.3f");
    01662    else if (V > -99.9   ) strcpy(Format,"%6.6s =%6.2f");
    01663    else                   strcpy(Format,"%6.6s =%6.1f");
    01664
    01665    sprintf(Text,Format,Name,V);
    01666    return strlen(Text);
    01667 }
    01668
    01669
    01670 void ShowParcs(void)
    01671 {
    01672    char Text[80];
    01673    int len;
    01674    float V;
    01675
    01676    XSetFont(display, gc, BigFont->fid);
    01677    len = FormatVal(Parc[cpi].Name,Parc[cpi].Val,Text);
    01678
    01679    XSetBackground(display,gc,WhitePix);
    01680    XSetForeground(display,gc,Red.pixel);
    01681    XFillRectangle(display,Cow,gc,Minus_XL,Minus_YL,Minus_XH-Minus_XL,Minus_YH-Minus_YL);
    01682    XFillRectangle(display,Cow,gc,FBWD_XL,FBWD_YL,FBWD_XH-FBWD_XL,FBWD_YH-FBWD_YL);
    01683    XSetForeground(display,gc,WhitePix);
    01684    XFillRectangle(display,Cow,gc,Minus_XL+3,(Minus_YH+Minus_YL)/2-1,Minus_XH-Minus_XL-5,3);
    01685    XFillRectangle(display,Cow,gc,FBWD_XL+3,(FBWD_YH+FBWD_YL)/2-1,FBWD_XH-FBWD_XL-5,3);
    01686    XSetForeground(display,gc,BlackPix);
    01687    XDrawImageString(display,Cow,gc,Parc_XL,Parc_YH-3,Text,len);
    01688    XSetForeground(display,gc,Green.pixel);
    01689    XFillRectangle(display,Cow,gc,Plus_XL,Plus_YL,Plus_XH-Plus_XL,Plus_YH-Plus_YL);
    01690    XFillRectangle(display,Cow,gc,FFWD_XL,FFWD_YL,FFWD_XH-FFWD_XL,FFWD_YH-FFWD_YL);
    01691    XSetForeground(display,gc,WhitePix);
    01692    XFillRectangle(display,Cow,gc,Plus_XL+3,(Plus_YH+Plus_YL)/2-1,Plus_XH-Plus_XL-5,3);
    01693    XFillRectangle(display,Cow,gc,FFWD_XL+3,(FFWD_YH+FFWD_YL)/2-1,FFWD_XH-FFWD_XL-5,3);
    01694    XFillRectangle(display,Cow,gc,(Plus_XH+Plus_XL)/2-1,Plus_YL+3,3,Plus_YH-Plus_YL-5);
    01695    XFillRectangle(display,Cow,gc,(FFWD_XH+FFWD_XL)/2-1,FFWD_YL+3,3,FFWD_YH-FFWD_YL-5);
    01696    XSetForeground(display,gc,BlackPix);
    01697    XDrawRectangle(display,Cow,gc,Minus_XL,Minus_YL,Minus_XH-Minus_XL,Minus_YH-Minus_YL);
    01698    XDrawRectangle(display,Cow,gc,FBWD_XL,FBWD_YL,FBWD_XH-FBWD_XL,FBWD_YH-FBWD_YL);
    01699    XDrawRectangle(display,Cow,gc,Parc_XL-1,Parc_YL-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL);
    01700    XDrawRectangle(display,Cow,gc,Plus_XL,Plus_YL,Plus_XH-Plus_XL,Plus_YH-Plus_YL);
    01701    XDrawRectangle(display,Cow,gc,FFWD_XL,FFWD_YL,FFWD_XH-FFWD_XL,FFWD_YH-FFWD_YL);
    01702
    01703    /* Show next parameter */
    01704
    01705    strcpy(Text,"              ");
    01706    if (cpi < Parcs-1) FormatVal(Parc[cpi+1].Name,Parc[cpi+1].Val,Text);
    01707    len = strlen(Text);
    01708
    01709    XSetBackground(display,gc,WhitePix);
    01710    XSetForeground(display,gc,BlackPix);
    01711    XDrawImageString(display,Cow,gc,Parc_XL,2*Parc_YH-Parc_YL-3,Text,len);
    01712    XDrawRectangle(display,Cow,gc,Parc_XL-1,Parc_YH-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL);
    01713
    01714    /* Show previous parameter */
    01715
    01716    strcpy(Text,"              ");
    01717    if (cpi > 0) FormatVal(Parc[cpi-1].Name,Parc[cpi-1].Val,Text);
    01718    len = strlen(Text);
    01719
    01720    XSetBackground(display,gc,WhitePix);
    01721    XSetForeground(display,gc,BlackPix);
    01722    XDrawImageString(display,Cow,gc,Parc_XL,Parc_YL-3,Text,len);
    01723    XDrawRectangle(display,Cow,gc,Parc_XL-1,2*Parc_YL-Parc_YH-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL);
    01724    XSetFont(display, gc, FixFont->fid);
    01725
    01726 }
    01727
    01728
    01729 void CheckMark(int x, int y, int d)
    01730 {
    01731    XDrawLine(display,Cow,gc,x+2,y+2,x+d-1,y+d-1);
    01732    XDrawLine(display,Cow,gc,x+3,y+2,x+d-1,y+d-2);
    01733    XDrawLine(display,Cow,gc,x+2,y+3,x+d-2,y+d-1);
    01734
    01735    XDrawLine(display,Cow,gc,x+d-1,y+1,x+2,y+d-2);
    01736    XDrawLine(display,Cow,gc,x+d-2,y+1,x+2,y+d-3);
    01737    XDrawLine(display,Cow,gc,x+d-1,y+2,x+3,y+d-2);
    01738 }
    01739
    01740
    01741 void ShowWindowStatus(void)
    01742 {
    01743    char *cp;
    01744    char Text[80];
    01745    int len,w,x,d;
    01746
    01747    XSetFont(display, gc, FixFont->fid);
    01748    XSetForeground(display,gc,BlackPix);
    01749    XSetBackground(display,gc,Grey.pixel);
    01750    x = Wbox_XL;
    01751    d = FixFontHeight;
    01752    for (w=0 ; w < NumWin ; ++w)
    01753    {
    01754       strncpy(Text,WindowTitle[w]+wto,40);
    01755       Text[40] = 0;
    01756       cp = strstr(Text,"Level");
    01757       if (cp) *cp = 0;
    01758       cp = strstr(Text,"Latitude");
    01759       if (cp) *cp = 0;
    01760       len = strlen(Text);
    01761       XDrawImageString(display,Cow,gc,x+20,(w+1) * d,Text,len);
    01762    }
    01763    XSetForeground(display,gc,WhitePix);
    01764    for (w=0 ; w < NumWin ; ++w)
    01765    {
    01766       XFillRectangle(display,Cow,gc,x,w*d,d,d);
    01767    }
    01768    XSetForeground(display,gc,BlackPix);
    01769    for (w=0 ; w < NumWin ; ++w)
    01770    {
    01771       XDrawRectangle(display,Cow,gc,x,w*d,d,d);
    01772    }
    01773    for (w=0 ; w < NumWin ; ++w)
    01774    if (Win[w]) CheckMark(x,w*d,d);
    01775 }
    01776
    01777
    01778 void ShowGridStatus(void)
    01779 {
    01780    int x,y,d;
    01781
    01782    d = FixFontHeight;
    01783    x = Grid_XL;
    01784    y = Grid_YL;
    01785    XSetFont(display, gc, FixFont->fid);
    01786    XSetForeground(display,gc,BlackPix);
    01787    XSetBackground(display,gc,Grey.pixel);
    01788    XDrawImageString(display,Cow,gc,Grid_XH+FixFontWidth,Grid_YH,"Grid",4);
    01789    XSetForeground(display,gc,WhitePix);
    01790    XFillRectangle(display,Cow,gc,x,Grid_YL,d,d);
    01791    XSetForeground(display,gc,BlackPix);
    01792    XDrawRectangle(display,Cow,gc,x,Grid_YL,d,d);
    01793
    01794    if (Grid) CheckMark(x,y,d);
    01795 }
    01796
    01797
    01798 int RedrawControlWindow(void)
    01799 {
    01800    char Text[80];
    01801    int status,WinXSize,WinYSize,font_height,width,len;
    01802    int i,j,x1,x2,y1,y2,y3;
    01803    XWindowAttributes CurAtt;
    01804
    01805    status = XGetWindowAttributes(display,Cow,&CurAtt);
    01806    WinXSize = CurAtt.width;
    01807    WinYSize = CurAtt.height;
    01808
    01809    XSetForeground(display,gc,BlackPix);
    01810    XSetBackground(display,gc,WhitePix);
    01811
    01812    XSetWindowBackground(display,Cow,Grey.pixel);
    01813    XClearWindow(display,Cow);
    01814
    01815    /* Red stop button */
    01816
    01817    XSetForeground(display,gc,Red.pixel);
    01818    XFillPolygon(display,Cow,gc,StopButton,4,Convex,CoordModeOrigin);
    01819    XSetForeground(display,gc,WhitePix);
    01820    x1 = StopButton[0].x ;
    01821    y1 = StopButton[0].y ;
    01822    for (j=0 ; j < PSDIM ; ++j)
    01823    for (i=0 ; i < PSDIM ; ++i)
    01824    if (pixelstar[j][i] == '*')
    01825       XDrawPoint(display,Cow,gc,i+x1,j+y1);
    01826
    01827    XSetForeground(display,gc,LightRed.pixel);
    01828    x1 = 10; x2 = 40 ; y1 = OffsetY + 10 ; y2 = OffsetY + 40;
    01829    XDrawLine(display,Cow,gc,x2  ,y1-1,x2  ,y2  );
    01830    XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1);
    01831    XDrawLine(display,Cow,gc,x1-1,y1-1,x2  ,y1-1);
    01832    XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2);
    01833    XSetForeground(display,gc,DarkRed.pixel);
    01834    XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2  );
    01835    XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1);
    01836    XDrawLine(display,Cow,gc,x1-1,y2  ,x2  ,y2  );
    01837    XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1);
    01838
    01839    // Green <play> button
    01840
    01841    XSetForeground(display,gc,Green.pixel);
    01842    XFillPolygon(display,Cow,gc,StartButton,3,Convex,CoordModeOrigin);
    01843    x1 = 50; x2 = 80 ; y1 = OffsetY + 10 ; y2 = OffsetY + 25; y3 = OffsetY + 40;
    01844    XSetForeground(display,gc,LightGreen.pixel);
    01845    XDrawLine(display,Cow,gc,x1  ,y1-1,x2  ,y2  );
    01846    XDrawLine(display,Cow,gc,x1  ,y1-2,x2+1,y2  );
    01847    XSetForeground(display,gc,DarkGreen.pixel);
    01848    XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y3+1);
    01849    XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y3+2);
    01850
    01851    // Blue <pause> button
    01852
    01853    XSetForeground(display,gc,Blue.pixel);
    01854    XFillPolygon(display,Cow,gc,PauseButton1,4,Convex,CoordModeOrigin);
    01855    XFillPolygon(display,Cow,gc,PauseButton2,4,Convex,CoordModeOrigin);
    01856
    01857    x1 = 95; x2 = 102; y1 = OffsetY + 10; y2 = OffsetY + 40;
    01858    XSetForeground(display,gc,DarkBlue.pixel);
    01859    XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2  );
    01860    XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1);
    01861    XDrawLine(display,Cow,gc,x1-1,y2  ,x2  ,y2  );
    01862    XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1);
    01863    XSetForeground(display,gc,LightBlue.pixel);
    01864    XDrawLine(display,Cow,gc,x2  ,y1-1,x2  ,y2  );
    01865    XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1);
    01866    XDrawLine(display,Cow,gc,x1-1,y1-1,x2  ,y1-1);
    01867    XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2);
    01868
    01869    x1 = 108; x2 = 115; y1 = OffsetY + 10; y2 = OffsetY + 40;
    01870    XSetForeground(display,gc,DarkBlue.pixel);
    01871    XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2  );
    01872    XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1);
    01873    XDrawLine(display,Cow,gc,x1-1,y2  ,x2  ,y2  );
    01874    XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1);
    01875    XSetForeground(display,gc,LightBlue.pixel);
    01876    XDrawLine(display,Cow,gc,x2  ,y1-1,x2  ,y2  );
    01877    XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1);
    01878    XDrawLine(display,Cow,gc,x1-1,y1-1,x2  ,y1-1);
    01879    XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2);
    01880
    01881    // Help button
    01882
    01883    x1 = 200; x2 = x1 + 5 * BigFontWidth; y1 = OffsetY + 10; y2 = y1 + 30;
    01884    XSetForeground(display,gc,Red.pixel);
    01885    XFillRectangle(display,Cow,gc,x1,y1,x2-x1,y2-y1);
    01886    XSetForeground(display,gc,BlackPix);
    01887    XDrawRectangle(display,Cow,gc,x1-1,y1-1,x2-x1+1,y2-y1+1);
    01888    XSetFont(display,gc,BigFont->fid);
    01889    XSetForeground(display,gc,Yellow.pixel);
    01890    XSetBackground(display,gc,Red.pixel);
    01891    XDrawImageString(display,Cow,gc,x1+BigFontWidth/2,(y1+y2)/2+BigFont->ascent/2,"HELP",4);
    01892
    01893    ShowStep();
    01894    ShowParcs();
    01895    ShowWindowStatus();
    01896    ShowGridStatus();
    01897    return 0;
    01898 }
    01899
    01900
    01901 void ClearTracer(void)
    01902 {
    01903    int j;
    01904    for (j=0 ; j < MAXPAR ; ++j)
    01905    {
    01906       pax[j] = -1.0;
    01907       pay[j] = -1.0;
    01908    }
    01909 }
    01910
    01911
    01912 int CheckEndianess(void)
    01913 {
    01914    union EndianCheck
    01915    {
    01916       char b[sizeof(int)];
    01917       int  i;
    01918    } ec;
    01919
    01920    ec.i = 8;
    01921    return (ec.b[0] == 0);
    01922 }
    01923
    01924
    01925 void initgui_(int *model, int *debug, int *lats, int *mrpid, int *mrnum)
    01926 {
    01927    int x,y,w,h;
    01928    int argc = 1;
    01929    int i,j;
    01930    unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
    01931    XGCValues values;
    01932    XEvent Event;
    01933    struct timeval TimeVal;
    01934
    01935    // Check for big endian computer
    01936    // The bitmap format ".bmp" ist little endian
    01937
    01938    BigEndian = CheckEndianess();
    01939
    01940    // Set seed for random number generator from clock
    01941
    01942    gettimeofday(&TimeVal,NULL);
    01943    Seed = TimeVal.tv_sec;
    01944
    01945    Model = *model;
    01946    Debug = *debug;
    01947    Latitudes = *lats;
    01948    MRpid = *mrpid;
    01949    MRnum = *mrnum;
    01950
    01951    if (MRpid >= 0)
    01952    {
    01953       sprintf(wtrun,"[%d] ",MRpid);
    01954       wto = strlen(wtrun);
    01955    }
    01956
    01957    if (Debug) printf("initgui(%d,%d)\n",Model,Debug);
    01958    if ((display=XOpenDisplay(display_name)) == NULL)
    01959    {
    01960       fprintf(stderr,"%s: cannot connect to X server %s\n",
    01961               progname, XDisplayName(display_name));
    01962       exit(1);
    01963    }
    01964    screen_num = DefaultScreen(display);
    01965    ScreenD  = XDefaultDepth(display,screen_num);
    01966    ScreenW  = DisplayWidth (display,screen_num);
    01967    ScreenH  = DisplayHeight(display,screen_num);
    01968    BlackPix = BlackPixel(display,screen_num);
    01969    WhitePix = WhitePixel(display,screen_num);
    01970    SmallScreen = ScreenH <= 768;
    01971    if (SmallScreen)
    01972    {
    01973       WinRows = 2;
    01974       NumWin  = WinCols * WinRows;
    01975       Grid = 0;
    01976    }
    01977
    01978    if (MRnum == 2) ScreenW /= 2; /* Run with two GUI's */
    01979
    01980    /* Fix defaults for multihead displays */
    01981
    01982    if (ScreenH > ScreenW && ScreenH > 1200) ScreenH = 1200;
    01983    if (ScreenW > 2 * ScreenH && ScreenW >= 2048) ScreenW /= 2;
    01984
    01985    for (i = 0 ; i < NUMWIN ; ++i)
    01986    {
    01987       WindowTitle[i] = CharAlloc(256,"WindowTitle");
    01988       if (wto == 0) sprintf(WindowTitle[i],"Window %d",i+1);
    01989       else          sprintf(WindowTitle[i],"%sWindow %d",wtrun,i+1);
    01990       WinAtt[i].x = -1;
    01991       WinAtt[i].y = -1;
    01992       WinAtt[i].w = -1;
    01993       WinAtt[i].h = -1;
    01994       WinAtt[i].active = 1;
    01995    }
    01996
    01997    CreateTestWindow();
    01998
    01999    if (MRpid >= 0) sprintf(GUI_default,"GUI_%2.2d.cfg",MRpid);
    02000    ReadConfig(GUI_default);
    02001    if (MRpid >= 0) sprintf(GUI_config,"GUI_last_used_%2.2d.cfg",MRpid);
    02002    ReadConfig(GUI_config);
    02003
    02004    LoadFonts();
    02005    CreateControlWindow();
    02006
    02007    OutXSize = (ScreenW-ScreenOffset) / WinCols;
    02008    OutYSize = (CowY-ScreenOffset-1-WM_top_area)  / WinRows;
    02009    WinXSize = OutXSize - WinLM - WinRM;
    02010    WinYSize = OutYSize - WinTM - WinBM;
    02011    WinSizeHints.flags      = PPosition | PSize | PMinSize;
    02012    WinSizeHints.min_width  = 200;
    02013    WinSizeHints.min_height = 100;
    02014    if (Debug)
    02015    {
    02016       printf("Outer windowsize = %dx%d\n",OutXSize,OutYSize);
    02017       printf("Inner windowsize = %dx%d\n",WinXSize,WinYSize);
    02018    }
    02019
    02020    wm_hints.initial_state = NormalState;
    02021    wm_hints.input = True;
    02022    wm_hints.flags = StateHint | InputHint;
    02023
    02024    class_hints.res_name = progname;
    02025    class_hints.res_class = "PUMA";
    02026
    02027    Delwin = XInternAtom(display,"WM_DELETE_WINDOW",0);
    02028
    02029    ReadImage(&MapHR,"map.bmp");
    02030
    02031    for (i = 0 ; i < NumWin ; ++i)
    02032    {
    02033       x = WinAtt[i].x;
    02034       y = WinAtt[i].y;
    02035       w = WinAtt[i].w;
    02036       h = WinAtt[i].h;
    02037
    02038       if (x < ScreenOffset || x >= ScreenW) x = ScreenOffset+(i%WinCols)*OutXSize;
    02039       if (y < ScreenOffset || y >= ScreenH) y = ScreenOffset+(i/WinCols)*OutYSize+WM_top_area;
    02040       if (w <  WinSizeHints.min_width ) w = WinXSize;
    02041       if (h <  WinSizeHints.min_height) h = WinYSize;
    02042       XStringListToTextProperty(&WindowTitle[i],1,WindowName+i);
    02043       if (WinAtt[i].active)
    02044       {
    02045          if (MRnum == 2 && MRpid == 1) x += ScreenW;
    02046          Win[i] = XCreateWindow(display,RootWindow(display,screen_num), // display, parent
    02047                   x,y,w,h,
    02048                   BorderWidth,CopyFromParent,InputOutput,         // border, depth, class
    02049                   CopyFromParent,0,NULL);                         // visual, valuemask, attributes
    02050          XSetWMProtocols(display,Win[i],&Delwin,1);
    02051          XSetWMProperties(display,Win[i],WindowName+i,NULL,
    02052                 NULL,0,&WinSizeHints,&wm_hints,&class_hints);
    02053          XSelectInput(display,Win[i],ButtonPressMask | KeyPressMask | ExposureMask);
    02054          XMapWindow(display,Win[i]);
    02055       }
    02056    }
    02057
    02058    /* Prepare GC */
    02059
    02060    gc = XCreateGC(display, Cow, valuemask, &values);
    02061    XSetFont(display, gc, FixFont->fid);
    02062    colormap = XDefaultColormap(display,screen_num);
    02063    XSetForeground(display,gc,BlackPix);
    02064    XSetBackground(display,gc,WhitePix);
    02065
    02066    /* Get keyboard information */
    02067
    02068    XDisplayKeycodes(display,&FirstKey,&LastKey);
    02069    KeyMap = XGetKeyboardMapping(display,FirstKey,LastKey-FirstKey+1,&SymsPerKey);
    02070
    02071    /* Allocate color cells */
    02072
    02073    for (i=0 ; i < NUMPAL ; ++i)
    02074       LineCo[i] = AllocateColorCells(Pallet[i]);
    02075
    02076    /* Color cells for control window */
    02077
    02078    XAllocNamedColor(display,colormap,"red"        ,&Red       ,&Dummy);
    02079    XAllocNamedColor(display,colormap,"green"      ,&Green     ,&Dummy);
    02080    XAllocNamedColor(display,colormap,"blue"       ,&Blue      ,&Dummy);
    02081    XAllocNamedColor(display,colormap,"grey"       ,&Grey      ,&Dummy);
    02082    XAllocNamedColor(display,colormap,"yellow"     ,&Yellow    ,&Dummy);
    02083    XAllocNamedColor(display,colormap,"hot pink"   ,&LightRed  ,&Dummy);
    02084    XAllocNamedColor(display,colormap,"dark red"   ,&DarkRed   ,&Dummy);
    02085    XAllocNamedColor(display,colormap,"light blue" ,&LightBlue ,&Dummy);
    02086    XAllocNamedColor(display,colormap,"dark blue"  ,&DarkBlue  ,&Dummy);
    02087    XAllocNamedColor(display,colormap,"light green",&LightGreen,&Dummy);
    02088    XAllocNamedColor(display,colormap,"dark green" ,&DarkGreen ,&Dummy);
    02089
    02090    TSColor[0] = Red.pixel;
    02091    TSColor[1] = Green.pixel;
    02092    TSColor[2] = Blue.pixel;
    02093    TSColor[3] = WhitePix;
    02094    TSColor[4] = LightRed.pixel;
    02095    TSColor[5] = Grey.pixel;
    02096    TSColor[6] = Yellow.pixel;
    02097    TSColor[7] = LightBlue.pixel;
    02098    TSColor[8] = LightGreen.pixel;
    02099
    02100    ClearTracer();
    02101    CalcButtonAreas();
    02102    RedrawControlWindow();
    02103    XSync(display,0);
    02104 }
    02105
    02106 void FillPoly(int n, REAL Poly[])
    02107 {
    02108    int i;
    02109    XPoint xpol[8];
    02110    for (i=0; i < n ; ++i)
    02111    {
    02112       xpol[i].x = OffX + Poly[i+i  ] + 0.5;
    02113       xpol[i].y = OffY + Poly[i+i+1] + 0.5;
    02114    }
    02115    XFillPolygon(display,pix,gc,xpol,n,Convex,CoordModeOrigin);
    02116 }
    02117
    02118 /* ======= */
    02119 /* IsoArea */
    02120 /* ======= */
    02121
    02122 void IsoArea(INT y, REAL vl, REAL vh, REAL Top[], REAL Bot[], INT Dim)
    02123 {
    02124    INT  f,x,p;
    02125    REAL xl,xr,yt,yb;
    02126    REAL Poly[16];
    02127
    02128    // if (Debug) printf("IsoArea %d %10.2f %10.2f %10.2f %10.2f %d\n",y,vl,vh,Top[0],Bot[0],Dim);
    02129    for (x=0 ; x < Dim-1 ; x++)
    02130    {
    02131       Flag[x] = 0;
    02132       if (Top[x  ] <  vl) Flag[x] |= TOLELO;
    02133       if (Top[x  ] >= vh) Flag[x] |= TOLEHI;
    02134       if (Top[x+1] <  vl) Flag[x] |= TORILO;
    02135       if (Top[x+1] >= vh) Flag[x] |= TORIHI;
    02136       if (Bot[x  ] <  vl) Flag[x] |= BOLELO;
    02137       if (Bot[x  ] >= vh) Flag[x] |= BOLEHI;
    02138       if (Bot[x+1] <  vl) Flag[x] |= BORILO;
    02139       if (Bot[x+1] >= vh) Flag[x] |= BORIHI;
    02140    }
    02141
    02142    x = 0;
    02143
    02144    while (x < Dim-1)
    02145    {
    02146       xl = VGAX *  x   ;
    02147       xr = VGAX * (x+1);
    02148       yt = VGAY *  y   ;
    02149       yb = VGAY * (y+1);
    02150       f  = Flag[x];
    02151
    02152       if (f == 0)
    02153       {
    02154          x++;
    02155          while (x < Dim-1 && Flag[x] == 0)
    02156          {
    02157             x++;
    02158             xr = VGAX * x;
    02159          }
    02160          Poly[0] = Poly[6] = xl;
    02161          Poly[1] = Poly[3] = yt;
    02162          Poly[2] = Poly[4] = xr;
    02163          Poly[5] = Poly[7] = yb;
    02164
    02165          FillPoly(4,Poly);
    02166
    02167       }
    02168       else if (f == (TOLELO | TORILO | BOLELO | BORILO) ||
    02169                f == (TOLEHI | TORIHI | BOLEHI | BORIHI))   x++;
    02170       else if (Top[x] < vl && Top[x+1] >= vl && Bot[x] >= vl && Bot[x+1] < vl)
    02171       {
    02172          Poly[1] = Poly[3] = yt;
    02173          Poly[2] = Poly[4] = xr;
    02174          Poly[0] = IPX(Top[x  ],vl,Top[x+1]);
    02175          Poly[5] = IPY(Top[x+1],vl,Bot[x+1]);
    02176          FillPoly(3,Poly);
    02177          Poly[1] = Poly[3] = yb;
    02178          Poly[2] = Poly[4] = xl;
    02179          Poly[0] = IPX(Bot[x  ],vl,Bot[x+1]);
    02180          Poly[5] = IPY(Top[x  ],vl,Bot[x  ]);
    02181          FillPoly(3,Poly);
    02182          ++x;
    02183       }
    02184       else if (Top[x] >= vl && Top[x+1] < vl && Bot[x] < vl && Bot[x+1] >= vl)
    02185       {
    02186          Poly[0] = Poly[4] = xl;
    02187          Poly[1] = Poly[3] = yt;
    02188          Poly[2] = IPX(Top[x  ],vl,Top[x+1]);
    02189          Poly[5] = IPY(Top[x  ],vl,Bot[x  ]);
    02190          FillPoly(3,Poly);
    02191          Poly[0] = Poly[2] = xr;
    02192          Poly[3] = Poly[5] = yb;
    02193          Poly[1] = IPY(Top[x+1],vl,Bot[x+1]);
    02194          Poly[4] = IPX(Bot[x  ],vl,Bot[x+1]);
    02195          FillPoly(3,Poly);
    02196          ++x;
    02197       }
    02198       else
    02199       {
    02200          p = 0;
    02201
    02202          if (Top[x] < vl)
    02203          {
    02204             if (Top[x+1] >= vl)
    02205             {
    02206                Poly[p++] = IPX(Top[x],vl,Top[x+1]);
    02207                Poly[p++] = yt;
    02208             }
    02209
    02210             if (Top[x+1] >= vh)
    02211             {
    02212                Poly[p++] = IPX(Top[x],vh,Top[x+1]);
    02213                Poly[p++] = yt;
    02214             }
    02215          }
    02216          else if (Top[x] >= vh)
    02217          {
    02218             if (Top[x+1] < vh)
    02219             {
    02220                Poly[p++] = IPX(Top[x],vh,Top[x+1]);
    02221                Poly[p++] = yt;
    02222             }
    02223             if (Top[x+1] < vl)
    02224             {
    02225                Poly[p++] = IPX(Top[x],vl,Top[x+1]);
    02226                Poly[p++] = yt;
    02227             }
    02228          }
    02229          else
    02230          {
    02231             Poly[p++] = xl;
    02232             Poly[p++] = yt;
    02233             if (Top[x+1] < vl)
    02234             {
    02235                Poly[p++] = IPX(Top[x],vl,Top[x+1]);
    02236                Poly[p++] = yt;
    02237             }
    02238             if (Top[x+1] >= vh)
    02239             {
    02240                Poly[p++] = IPX(Top[x],vh,Top[x+1]);
    02241                Poly[p++] = yt;
    02242             }
    02243          }
    02244
    02245          if (Top[x+1] < vl)
    02246          {
    02247             if (Bot[x+1] >= vl)
    02248             {
    02249                Poly[p++] = xr;
    02250                Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]);
    02251             }
    02252
    02253             if (Bot[x+1] >= vh)
    02254             {
    02255                Poly[p++] = xr;
    02256                Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]);
    02257             }
    02258          }
    02259          else if (Top[x+1] >= vh)
    02260          {
    02261             if (Bot[x+1] < vh)
    02262             {
    02263                Poly[p++] = xr;
    02264                Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]);
    02265             }
    02266             if (Bot[x+1] < vl)
    02267             {
    02268                Poly[p++] = xr;
    02269                Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]);
    02270             }
    02271          }
    02272          else
    02273          {
    02274             Poly[p++] = xr;
    02275             Poly[p++] = yt;
    02276             if (Bot[x+1] < vl)
    02277             {
    02278                Poly[p++] = xr;
    02279                Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]);
    02280             }
    02281             if (Bot[x+1] >= vh)
    02282             {
    02283                Poly[p++] = xr;
    02284                Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]);
    02285             }
    02286          }
    02287
    02288          if (Bot[x+1] < vl)
    02289          {
    02290             if (Bot[x] >= vl)
    02291             {
    02292                Poly[p++] = IPX(Bot[x],vl,Bot[x+1]);
    02293                Poly[p++] = yb;
    02294             }
    02295             if (Bot[x] >= vh)
    02296             {
    02297                Poly[p++] = IPX(Bot[x],vh,Bot[x+1]);
    02298                Poly[p++] = yb;
    02299             }
    02300          }
    02301          else if (Bot[x+1] >= vh)
    02302          {
    02303             if (Bot[x] < vh)
    02304             {
    02305                Poly[p++] = IPX(Bot[x],vh,Bot[x+1]);
    02306                Poly[p++] = yb;
    02307             }
    02308             if (Bot[x] < vl)
    02309             {
    02310                Poly[p++] = IPX(Bot[x],vl,Bot[x+1]);
    02311                Poly[p++] = yb;
    02312             }
    02313          }
    02314          else
    02315          {
    02316             Poly[p++] = xr;
    02317             Poly[p++] = yb;
    02318             if (Bot[x] < vl)
    02319             {
    02320                Poly[p++] = IPX(Bot[x],vl,Bot[x+1]);
    02321                Poly[p++] = yb;
    02322             }
    02323             if (Bot[x] >= vh)
    02324             {
    02325                Poly[p++] = IPX(Bot[x],vh,Bot[x+1]);
    02326                Poly[p++] = yb;
    02327             }
    02328          }
    02329
    02330          if (Bot[x] < vl)
    02331          {
    02332             if (Top[x] >= vl)
    02333             {
    02334                Poly[p++] = xl;
    02335                Poly[p++] = IPY(Top[x],vl,Bot[x]);
    02336             }
    02337
    02338             if (Top[x] >= vh)
    02339             {
    02340                Poly[p++] = xl;
    02341                Poly[p++] = IPY(Top[x],vh,Bot[x]);
    02342             }
    02343          }
    02344          else if (Bot[x] >= vh)
    02345          {
    02346             if (Top[x] < vh)
    02347             {
    02348                Poly[p++] = xl;
    02349                Poly[p++] = IPY(Top[x],vh,Bot[x]);
    02350             }
    02351             if (Top[x] < vl)
    02352             {
    02353                Poly[p++] = xl;
    02354                Poly[p++] = IPY(Top[x],vl,Bot[x]);
    02355             }
    02356          }
    02357          else
    02358          {
    02359             Poly[p++] = xl;
    02360             Poly[p++] = yb;
    02361             if (Top[x] < vl)
    02362             {
    02363                Poly[p++] = xl;
    02364                Poly[p++] = IPY(Top[x],vl,Bot[x]);
    02365             }
    02366             if (Top[x] >= vh)
    02367             {
    02368                Poly[p++] = xl;
    02369                Poly[p++] = IPY(Top[x],vh,Bot[x]);
    02370             }
    02371          }
    02372          FillPoly(p>>1,Poly);
    02373          x++;
    02374       }
    02375    }
    02376 }
    02377
    02378
    02379 /* ======= */
    02380 /* isoarea */
    02381 /* ======= */
    02382
    02383 void IsoAreas(struct ColorStrip Strip[])
    02384 {
    02385    INT  i;
    02386    INT  y;
    02387    REAL *Top;
    02388    REAL *Bot;
    02389
    02390    i = 0;
    02391    while (Strip[i].Name)
    02392    {
    02393       Top = Field;
    02394       Bot = Field + DimX;
    02395       XSetForeground(display,gc,Strip[i].pixel);
    02396       for (y = 0 ; y < DimY-1 ; y++)
    02397       {
    02398          IsoArea(y,Strip[i].Lo,Strip[i].Hi,Top,Bot,DimX);
    02399          Top += DimX;
    02400          Bot += DimX;
    02401       }
    02402       ++i;
    02403    }
    02404 }
    02405
    02406 /* ======= */
    02407 /* IsoLine */
    02408 /* ======= */
    02409
    02410 void IsoLine(INT y, REAL v, REAL Top[], REAL Bot[], INT Dim)
    02411 {
    02412    INT  f,x;
    02413    REAL xl,xr,yt,yb;
    02414    REAL x1,yo,x2,y2,x3,y3,x4,y4;
    02415
    02416    for (x=0 ; x < Dim-1 ; x++)
    02417    {
    02418       Flag[x] = 0;
    02419       if (Top[x  ] <  v) Flag[x] |= TOLELO;
    02420       else               Flag[x] |= TOLEHI;
    02421       if (Top[x+1] <  v) Flag[x] |= TORILO;
    02422       else               Flag[x] |= TORIHI;
    02423       if (Bot[x  ] <  v) Flag[x] |= BOLELO;
    02424       else               Flag[x] |= BOLEHI;
    02425       if (Bot[x+1] <  v) Flag[x] |= BORILO;
    02426       else               Flag[x] |= BORIHI;
    02427    }
    02428
    02429    x = 0;
    02430
    02431    while (x < Dim-1)
    02432    {
    02433       xl = VGAX *  x   ;
    02434       xr = VGAX * (x+1);
    02435       yt = VGAY *  y   ;
    02436       yb = VGAY * (y+1);
    02437       f  = Flag[x];
    02438
    02439       if (f == 0 || f == (TOLELO | TORILO | BOLELO | BORILO) ||
    02440                     f == (TOLEHI | TORIHI | BOLEHI | BORIHI))   x++;
    02441       else if (f == (TOLELO | BORILO | TORIHI | BOLEHI))
    02442       {
    02443          x1 = IPX(Top[x  ],v,Top[x+1]);
    02444          yo = yt;
    02445          x2 = xr;
    02446          y2 = IPY(Top[x+1],v,Bot[x+1]);
    02447          x3 = IPX(Bot[x  ],v,Bot[x+1]);
    02448          y3 = yb;
    02449          x4 = xl;
    02450          y4 = IPY(Top[x  ],v,Bot[x  ]);
    02451          XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2);
    02452          XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4);
    02453          ++x;
    02454       }
    02455       else if (f == (TORILO | BOLELO | TOLEHI | BORIHI))
    02456       {
    02457          x1 = xl;
    02458          yo = IPY(Top[x  ],v,Bot[x  ]);
    02459          x2 = IPX(Top[x  ],v,Top[x+1]);
    02460          y2 = yt;
    02461          x3 = xr;
    02462          y3 = IPY(Top[x+1],v,Bot[x+1]);
    02463          x4 = IPX(Bot[x  ],v,Bot[x+1]);
    02464          y4 = yb;
    02465          XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2);
    02466          XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4);
    02467          ++x;
    02468       }
    02469       else
    02470       {
    02471          x1 = x2 = x3 = x4 = -1;
    02472
    02473          if (Top[x  ] < v && Top[x+1] >= v || Top[x  ] >= v && Top[x+1] < v)
    02474          {
    02475             x1 = IPX(Top[x  ],v,Top[x+1]);
    02476             yo = yt;
    02477          }
    02478          if (Top[x+1] < v && Bot[x+1] >= v || Top[x+1] >= v && Bot[x+1] < v)
    02479          {
    02480             x2 = xr;
    02481             y2 = IPY(Top[x+1],v,Bot[x+1]);
    02482          }
    02483          if (Bot[x+1] < v && Bot[x  ] >= v || Bot[x+1] >= v && Bot[x  ] < v)
    02484          {
    02485             x3 = IPX(Bot[x  ],v,Bot[x+1]);
    02486             y3 = yb;
    02487          }
    02488          if (Bot[x  ] < v && Top[x  ] >= v || Bot[x  ] >= v && Top[x  ] < v)
    02489          {
    02490             x4 = xl;
    02491             y4 = IPY(Top[x  ],v,Bot[x  ]);
    02492          }
    02493
    02494          if (x1 >= 0 && x2 >= 0 && x3 >= 0 && x4 >= 0)
    02495          {
    02496             XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2);
    02497             XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4);
    02498          }
    02499          else if (x1 >= 0)
    02500          {
    02501             if      (x2 >= 0) XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2);
    02502             else if (x3 >= 0) XDrawLine(display,pix,gc,x1,OffY+yo,x3,OffY+y3);
    02503             else              XDrawLine(display,pix,gc,x1,OffY+yo,x4,OffY+y4);
    02504          }
    02505          else if (x2 >= 0)
    02506          {
    02507             if (x3 >= 0) XDrawLine(display,pix,gc,x2,OffY+y2,x3,OffY+y3);
    02508             else         XDrawLine(display,pix,gc,x2,OffY+y2,x4,OffY+y4);
    02509          }
    02510          else XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4);
    02511
    02512          x++;
    02513       }
    02514    }
    02515 }
    02516
    02517
    02518 /* ======== */
    02519 /* IsoLines */
    02520 /* ======== */
    02521
    02522 void IsoLines(struct ColorStrip Strip[],int Colored)
    02523 {
    02524    INT  i;
    02525    INT  y;
    02526    REAL *Top;
    02527    REAL *Bot;
    02528
    02529    XSetForeground(display,gc,BlackPix);
    02530    i = 0;
    02531    while (Strip[i].Name)
    02532    {
    02533       Top = Field;
    02534       Bot = Field + DimX;
    02535       if (Colored) XSetForeground(display,gc,Strip[i].pixel);
    02536       for (y = 0 ; y < DimY-1 ; y++)
    02537       {
    02538          IsoLine(y,Strip[i].Lo,Top,Bot,DimX);
    02539          Top += DimX;
    02540          Bot += DimX;
    02541       }
    02542       ++i;
    02543    }
    02544 }
    02545
    02546 int AziPoint(int fpx, int fpy, int *x2, int *y2)
    02547 {
    02548    int xc,yc;
    02549    double flam,fsin,fcos,roa,pil,piy;
    02550
    02551    xc  = InXSize >> 1;
    02552    yc  = InYSize >> 1;
    02553    roa = MapLR[win].l * InXSize / 360.0;
    02554    pil = 2.0 * M_PI / InXSize;
    02555    piy = M_PI / InYSize;
    02556
    02557    flam = (fpx - xc - roa) * pil;
    02558    if (flam < -M_PI) flam += 2.0 * M_PI;
    02559    if (flam >  M_PI) flam -= 2.0 * M_PI;
    02560    if (flam < -M_PI_2 || flam > M_PI_2) return 1;
    02561    fsin = sin(flam);
    02562    fcos = cos((fpy-yc) * piy);
    02563    *x2  = xc + InYSize/2 * fcos * fsin;
    02564    *y2  = yc + InYSize/2 * sin((fpy-yc) * piy);
    02565    return 0;
    02566 }
    02567
    02568 void AziLine(int x1, int y1, int x2, int y2)
    02569 {
    02570    int a1,b1,a2,b2;
    02571
    02572    if (AziPoint(x1,y1,&a1,&b1)) return;
    02573    if (AziPoint(x2,y2,&a2,&b2)) return;
    02574    XDrawLine(display,pix,gc,a1,b1,a2,b2);
    02575 }
    02576
    02577
    02578 /* ======= */
    02579 /* MapLine */
    02580 /* ======= */
    02581
    02582 void MapLine(INT y, REAL v, REAL Top[], REAL Bot[], INT Dim)
    02583 {
    02584    INT  f,x;
    02585    REAL xl,xr,yt,yb;
    02586    REAL x1,yo,x2,y2,x3,y3,x4,y4;
    02587
    02588    for (x=0 ; x < Dim-1 ; x++)
    02589    {
    02590       Flag[x] = 0;
    02591       if (Top[x  ] <  v) Flag[x] |= TOLELO;
    02592       else               Flag[x] |= TOLEHI;
    02593       if (Top[x+1] <  v) Flag[x] |= TORILO;
    02594       else               Flag[x] |= TORIHI;
    02595       if (Bot[x  ] <  v) Flag[x] |= BOLELO;
    02596       else               Flag[x] |= BOLEHI;
    02597       if (Bot[x+1] <  v) Flag[x] |= BORILO;
    02598       else               Flag[x] |= BORIHI;
    02599    }
    02600
    02601    x = 0;
    02602
    02603    while (x < Dim-1)
    02604    {
    02605       xl = VGAX *  x   ;
    02606       xr = VGAX * (x+1);
    02607       yt = VGAY *  y   ;
    02608       yb = VGAY * (y+1);
    02609       f  = Flag[x];
    02610
    02611       if (f == 0 || f == (TOLELO | TORILO | BOLELO | BORILO) ||
    02612                     f == (TOLEHI | TORIHI | BOLEHI | BORIHI))   x++;
    02613       else if (f == (TOLELO | BORILO | TORIHI | BOLEHI))
    02614       {
    02615          x1 = IPX(Top[x  ],v,Top[x+1]);
    02616          yo = yt;
    02617          x2 = xr;
    02618          y2 = IPY(Top[x+1],v,Bot[x+1]);
    02619          x3 = IPX(Bot[x  ],v,Bot[x+1]);
    02620          y3 = yb;
    02621          x4 = xl;
    02622          y4 = IPY(Top[x  ],v,Bot[x  ]);
    02623          AziLine(x1,OffY+yo,x2,OffY+y2);
    02624          AziLine(x3,OffY+y3,x4,OffY+y4);
    02625          ++x;
    02626       }
    02627       else if (f == (TORILO | BOLELO | TOLEHI | BORIHI))
    02628       {
    02629          x1 = xl;
    02630          yo = IPY(Top[x  ],v,Bot[x  ]);
    02631          x2 = IPX(Top[x  ],v,Top[x+1]);
    02632          y2 = yt;
    02633          x3 = xr;
    02634          y3 = IPY(Top[x+1],v,Bot[x+1]);
    02635          x4 = IPX(Bot[x  ],v,Bot[x+1]);
    02636          y4 = yb;
    02637          AziLine(x1,OffY+yo,x2,OffY+y2);
    02638          AziLine(x3,OffY+y3,x4,OffY+y4);
    02639          ++x;
    02640       }
    02641       else
    02642       {
    02643          x1 = x2 = x3 = x4 = -1;
    02644
    02645          if (Top[x  ] < v && Top[x+1] >= v || Top[x  ] >= v && Top[x+1] < v)
    02646          {
    02647             x1 = IPX(Top[x  ],v,Top[x+1]);
    02648             yo = yt;
    02649          }
    02650          if (Top[x+1] < v && Bot[x+1] >= v || Top[x+1] >= v && Bot[x+1] < v)
    02651          {
    02652             x2 = xr;
    02653             y2 = IPY(Top[x+1],v,Bot[x+1]);
    02654          }
    02655          if (Bot[x+1] < v && Bot[x  ] >= v || Bot[x+1] >= v && Bot[x  ] < v)
    02656          {
    02657             x3 = IPX(Bot[x  ],v,Bot[x+1]);
    02658             y3 = yb;
    02659          }
    02660          if (Bot[x  ] < v && Top[x  ] >= v || Bot[x  ] >= v && Top[x  ] < v)
    02661          {
    02662             x4 = xl;
    02663             y4 = IPY(Top[x  ],v,Bot[x  ]);
    02664          }
    02665
    02666          if (x1 >= 0 && x2 >= 0 && x3 >= 0 && x4 >= 0)
    02667          {
    02668             AziLine(x1,OffY+yo,x2,OffY+y2);
    02669             AziLine(x3,OffY+y3,x4,OffY+y4);
    02670          }
    02671          else if (x1 >= 0)
    02672          {
    02673             if      (x2 >= 0) AziLine(x1,OffY+yo,x2,OffY+y2);
    02674             else if (x3 >= 0) AziLine(x1,OffY+yo,x3,OffY+y3);
    02675             else              AziLine(x1,OffY+yo,x4,OffY+y4);
    02676          }
    02677          else if (x2 >= 0)
    02678          {
    02679             if (x3 >= 0) AziLine(x2,OffY+y2,x3,OffY+y3);
    02680             else         AziLine(x2,OffY+y2,x4,OffY+y4);
    02681          }
    02682          else AziLine(x3,OffY+y3,x4,OffY+y4);
    02683
    02684          x++;
    02685       }
    02686    }
    02687 }
    02688
    02689
    02690 /* ======== */
    02691 /* MapLines */
    02692 /* ======== */
    02693
    02694 void MapLines(struct ColorStrip Strip[],int Colored)
    02695 {
    02696    INT  i;
    02697    INT  y;
    02698    REAL *Top;
    02699    REAL *Bot;
    02700
    02701    XSetForeground(display,gc,BlackPix);
    02702    i = 0;
    02703    while (Strip[i].Name)
    02704    {
    02705       Top = Field;
    02706       Bot = Field + DimX;
    02707       if (Colored) XSetForeground(display,gc,Strip[i].pixel);
    02708       for (y = 0 ; y < DimY-1 ; y++)
    02709       {
    02710          MapLine(y,Strip[i].Lo,Top,Bot,DimX);
    02711          Top += DimX;
    02712          Bot += DimX;
    02713       }
    02714       ++i;
    02715    }
    02716 }
    02717
    02718 int polco = 0;
    02719
    02720 void poltra(float lam, float phi, float *x, float *y)
    02721 {
    02722    REAL xnp,ynp,xsp,ysp,lfa;
    02723
    02724    lfa = (2.0 * M_PI) / (InXSize-1) ;
    02725    xnp = (InXSize-1) * 0.25;
    02726    ynp = (InYSize-1) * 0.50;
    02727    xsp = (InXSize-1) * 0.75;
    02728    ysp = ynp;
    02729
    02730    /* Northern hemisphere */
    02731
    02732    if (phi < ynp)
    02733    {
    02734       *x = xnp + sin(lam * lfa) * phi;
    02735       *y = ynp + cos(lam * lfa) * phi;
    02736    }
    02737
    02738    /* Souhern hemisphere */
    02739
    02740    else
    02741    {
    02742       *x = xsp - sin(lam * lfa) * (phi-ysp);
    02743       *y = ysp + cos(lam * lfa) * (phi-ysp);
    02744    }
    02745 }
    02746
    02747
    02748 /* ========== */
    02749 /* TracerPlot */
    02750 /* ========== */
    02751
    02752 void TracerPlot(int w)
    02753 {
    02754    int j,ipx,ipy,lpy,lpx,jx,jy,ic,ix,iy,ipr;
    02755    int xnp,ynp,xsp,ysp,xc,yc;
    02756    float *u;
    02757    float *v;
    02758    float fpx,fpy,du,dv,ppx,ppy,rx,ry,spfac;
    02759    float lfa,lam,phi,hpy,fcos,fsin;
    02760    float pil,piy;
    02761    float roa;
    02762    float flam;
    02763    float dpx,dpy;
    02764
    02765    if (Uindex < 0 || Vindex < 0) return; // Data missing
    02766
    02767    Delpar = (8 * 60) / DeltaTime; // Injection interval
    02768    if (LevelChanged[w]) ClearTracer();
    02769    LevelChanged[w] = 0;
    02770    if (!SpeedScale) SpeedScale = FloatAlloc(DimY,"SpeedScale");
    02771    u = Array[Uindex].Data + Indez[w] * DimXY;
    02772    v = Array[Vindex].Data + Indez[w] * DimXY;
    02773
    02774    TracerColor = Yellow.pixel;
    02775    if (nstep % (8*Delpar) == 0) ColInd++;
    02776    if (ColInd >= AUTOCOLORS) ColInd = 0;
    02777    TracerColor = Autostrip[ColInd].pixel;
    02778
    02779    dpx = (float)(InXSize-1) / (float)(DimX-1);
    02780    dpy = (float)(InYSize-1) / (float)(DimY-1);
    02781    lpx = InXSize;
    02782    lpy = InYSize;
    02783    hpy = 0.5 * dpy;
    02784    xc  = lpx / 2;
    02785    yc  = lpy / 2;
    02786    ipr = InXSize / 400;
    02787    pil = 2.0 * M_PI / lpx;
    02788    piy = M_PI / lpy;
    02789    roa = MapLR[w].l * lpx / 360.0;
    02790
    02791    // Compute scale factors
    02792
    02793    if (SizeChanged || nstep < 10)
    02794    {
    02795       for (j=0 ; j < DimY; ++j)
    02796       {
    02797          SpeedScale[j] = InXSize * DeltaTime * 60.0 / 40000000.0
    02798                        / cos((j-0.5*(DimY-1)) * (M_PI/DimY));
    02799       }
    02800       SpeedScale[DimY-1] = SpeedScale[0] = SpeedScale[1];
    02801    }
    02802
    02803    // Insert new particles
    02804
    02805    if (nstep % Delpar == 0)
    02806    {
    02807       fpx = dpx * (DimX-1) / 2.0;
    02808       for (ipy = 0 ; ipy < lpy ; ipy += dpy)
    02809       {
    02810          ParInd = (ParInd+1) & (MAXPAR-1);
    02811          pax[ParInd] = fpx;
    02812          pay[ParInd] = ipy + hpy;
    02813          pal[ParInd] = TracerColor;
    02814       }
    02815    }
    02816
    02817   // Move particles
    02818
    02819   for (j=0 ; j < MAXPAR ; ++j)
    02820   if (pax[j] >= 0.0 && pay[j] >= 0.0)
    02821   {
    02822      jx = rx = pax[j] / dpx;
    02823      jy = ry = pay[j] / dpy;
    02824      ic = jx + DimX * jy;
    02825      ix = ic + 1;
    02826      if (jx >= DimX-1) ix -= DimX;
    02827      iy = ic + DimX;
    02828      if (iy >= DimX * DimY) iy -= DimX;
    02829      rx -= jx;
    02830      ry -= jy;
    02831
    02832      du = u[ic]+(u[ix]-u[ic])*rx+(u[iy]-u[ic])*ry;
    02833      dv = v[ic]+(v[ix]-v[ic])*rx+(v[iy]-v[ic])*ry;
    02834      spfac = SpeedScale[jy] + (SpeedScale[jy+1]-SpeedScale[jy]) * ry;
    02835      du *= spfac;
    02836      dv *= spfac;
    02837      fpx = pax[j] + du;
    02838      fpy = pay[j] + dv;
    02839      if (fpx <  0.0) fpx += lpx;
    02840      if (fpx >= lpx) fpx -= lpx;
    02841      if (fpy < 0.0 || fpy > lpy-1)
    02842      {
    02843         pay[j] = -1.0;
    02844         continue;
    02845      }
    02846      pax[j] = fpx;
    02847      pay[j] = fpy;
    02848      ipx    =  -1;
    02849      if (MapPro[w] == POLAR)
    02850      {
    02851        lfa = (2.0 * M_PI) / lpx;
    02852        xnp = (InXSize-1) * 0.25;
    02853        ynp = (InYSize-1) * 0.50;
    02854        xsp = (InXSize-1) * 0.75;
    02855        ysp = ynp;
    02856        lam = fpx;
    02857        phi = fpy;
    02858        if (phi < 0.5 * lpy) /* Northern hemisphere */
    02859        {
    02860           fpx = xnp - sin(lam * lfa) * (phi + hpy);
    02861           fpy = ynp - cos(lam * lfa) * (phi + hpy);
    02862        }
    02863        else                 /* Souhern hemisphere */
    02864        {
    02865           fpx = xsp + sin(lam * lfa) * (lpy - phi + hpy);
    02866           fpy = ysp - cos(lam * lfa) * (lpy - phi + hpy);
    02867        }
    02868        ipx = rintf(fpx);
    02869        ipy = rintf(fpy);
    02870      }
    02871      else if (MapPro[w] == AZIMUTHAL)
    02872      {
    02873         flam = (fpx - xc - roa) * pil;
    02874         if (flam < -M_PI) flam += 2.0 * M_PI;
    02875         if (flam >  M_PI) flam -= 2.0 * M_PI;
    02876         if (flam < -M_PI_2 || flam > M_PI_2) continue;
    02877         fsin = sin(flam);
    02878         fcos = cos((fpy-yc) * piy);
    02879         fpx  = xc + lpy/2 * fcos * fsin;
    02880         fpy  = yc + lpy/2 * sin((fpy-yc) * piy);
    02881         ipx  = rintf(fpx);
    02882         ipy  = rintf(fpy);
    02883      }
    02884      else
    02885      {
    02886         ipx = rintf(fpx);
    02887         ipy = rintf(fpy);
    02888      }
    02889      if (ipx >= 0)
    02890      {
    02891         XSetForeground(display,gc,pal[j]);
    02892         if (ipr < 2) XDrawPoint(display,pix,gc,ipx,ipy);
    02893         else if (ipr == 2) XFillRectangle(display,pix,gc,ipx,ipy,2,2);
    02894         else XFillArc(display,pix,gc,ipx,ipy,ipr,ipr,0,360*64);
    02895      }
    02896   }
    02897 }
    02898
    02899
    02900 /* ============= */
    02901 /* AmplitudePlot */
    02902 /* ============= */
    02903
    02904 void AmplitudePlot(void)
    02905 {
    02906    int i,j,m,n;
    02907    int x,y;
    02908    int r,dx,dy;
    02909    int mmax;
    02910    int imax;
    02911    REAL Amax,Fac;
    02912
    02913    if (!Ampli) Ampli = FloatAlloc(DimX,"Ampli");
    02914    if (!Acol ) Acol  = SizeAlloc(DimX,sizeof(XColor),"Acol");
    02915
    02916    Amax = 0.0;
    02917    imax = 0;
    02918    for (i=0 ; i < DimX ; ++i)
    02919    {
    02920       Ampli[i] = log (1.0 + sqrt(Field[2*i]*Field[2*i]+Field[2*i+1]*Field[2*i+1]));
    02921       Acol[i].pixel = WhitePix;
    02922       if (Ampli[i] > Amax && i > DimY)
    02923       {
    02924          Amax = Ampli[i];
    02925          imax = i;
    02926       }
    02927    }
    02928
    02929    Fac = 0.0;
    02930    if (Amax > 1.e-20) Fac = 1.0 / Amax;
    02931    for (i=0 ; i < DimX ; ++i)
    02932    {
    02933       j = AMPLI_COLS * Ampli[i] * Fac;
    02934       if (j >= AMPLI_COLS) j = AMPLI_COLS-1;
    02935       Acol[i].pixel = AmpliStrip[j].pixel;
    02936    }
    02937
    02938    dx = WinXSize / 23;
    02939    r  = (dx+dx) / 3;
    02940    mmax = (InYSize / dx) - 1;
    02941    XSetForeground(display,gc,BlackPix);
    02942    for (m=0,i=0 ; m < mmax ; ++m)
    02943    {
    02944       y = FixFontHeight + 4 + m * dx;
    02945       for (n=m ; n < DimY ; ++n,++i)
    02946       if (n < 22)
    02947       {
    02948          x = dx/2 + n * dx;
    02949          XSetForeground(display,gc,Acol[i].pixel);
    02950          XFillArc(display,pix,gc,x,y,r,r,0,360*64);
    02951       }
    02952    }
    02953 }
    02954
    02955
    02956 void RedrawIsoWindow(int w)
    02957 {
    02958    if (WinPixMap[w].Pix)
    02959    XCopyArea(display,WinPixMap[w].Pix,Win[w],gc,0,0,WinPixMap[w].DimX,WinPixMap[w].DimY,0,0);
    02960 }
    02961
    02962
    02963 void CloseWindow(int i)
    02964 {
    02965    INTXS X,Y,xp,yp;
    02966    unsigned int border,depth;
    02967    Window Rootwin,Child;
    02968
    02969    if (Win[i])
    02970    {
    02971        XGetGeometry(display,Win[i],&Rootwin,&xp,&yp,&WinAtt[i].w,&WinAtt[i].h,&border,&depth);
    02972        XTranslateCoordinates(display,Win[i],Rootwin,0,0,&X,&Y,&Child);
    02973        WinAtt[i].x =  X - WinLM;
    02974        WinAtt[i].y =  Y - WinTM;
    02975        XDestroyWindow(display,Win[i]);
    02976        Win[i] = 0;
    02977        ShowWindowStatus();
    02978    }
    02979 }
    02980
    02981 void ReopenWindow(int i)
    02982 {
    02983    if (Win[i] == 0)
    02984    {
    02985       if (WinAtt[i].x < ScreenOffset) WinAtt[i].x = ScreenOffset + OutXSize * (i % WinCols);
    02986       if (WinAtt[i].y < ScreenOffset) WinAtt[i].y = ScreenOffset + OutYSize * (i / WinCols);
    02987       Win[i] = XCreateSimpleWindow(display,RootWindow(display,screen_num),
    02988                WinAtt[i].x,WinAtt[i].y,WinAtt[i].w,WinAtt[i].h,
    02989                BorderWidth,BlackPix,WhitePix);
    02990       XSetWMProtocols(display,Win[i],&Delwin,1);
    02991       XSetWMProperties(display,Win[i],WindowName+i,NULL,
    02992                 NULL,0,&WinSizeHints,&wm_hints,&class_hints);
    02993       XSelectInput(display,Win[i],ButtonPressMask | KeyPressMask | ExposureMask);
    02994       XMapWindow(display,Win[i]);
    02995       ShowWindowStatus();
    02996    }
    02997 }
    02998
    02999 char *HelpText[] =
    03000 {
    03001    "Key assignment for azimuthal projection     ",
    03002    "--------------------------------------------",
    03003    "<- cursor left  : increase westward rotation",
    03004    "-> cursor right : increase eastward rotation",
    03005    "============================================",
    03006    "Key assignment for 3D variables             ",
    03007    "--------------------------------------------",
    03008    "^  cursor up    : display next upper level  ",
    03009    "v  cursor down  : display next lower level  ",
    03010    "============================================",
    03011    "Key assignment for Lon/Lev or Hovmoeller    ",
    03012    "--------------------------------------------",
    03013    "^  cursor up    : switch latitude northwards",
    03014    "v  cursor down  : switch latitude southwards",
    03015    "============================================",
    03016    "Mouse button assignment                     ",
    03017    "--------------------------------------------",
    03018    "Left   button   : decrease level or latitude",
    03019    "Right  button   : increase level or latitude",
    03020    "Middle button   : cycle through projections "
    03021 };
    03022
    03023 int HelpLines = sizeof(HelpText) / sizeof(char *);
    03024
    03025 void DrawHelpWindow(void)
    03026 {
    03027    int x,y,j,l;
    03028
    03029    XSetForeground(display,gc,Yellow.pixel);
    03030    XSetBackground(display,gc,DarkBlue.pixel);
    03031    XSetFont(display,gc,BigFont->fid);
    03032
    03033    x = BigFontWidth / 2;
    03034    for (j=0 ; j < HelpLines ; ++j)
    03035    {
    03036       y = BigFontHeight / 2 + BigFont->ascent + j * BigFontHeight;
    03037       l = strlen(HelpText[j]);
    03038       XDrawImageString(display,HelpWindow,gc,x,y,HelpText[j],l);
    03039    }
    03040 }
    03041
    03042 void DisplayHelpWindow(void)
    03043 {
    03044    int x,y,w,h;
    03045    char *HelpTitle = "Help";
    03046
    03047    w = BigFontWidth  * (strlen(HelpText[0])+1);
    03048    h = BigFontHeight * (HelpLines + 1);
    03049    x = (ScreenW - w) / 2;
    03050    y = (ScreenH - h) / 2;
    03051    HelpWindow = XCreateSimpleWindow(display,RootWindow(display,screen_num),
    03052                 x,y,w,h,BorderWidth,Yellow.pixel,DarkBlue.pixel);
    03053    XStringListToTextProperty(&HelpTitle,1,&HelpName);
    03054    XSetWMProtocols(display,HelpWindow,&Delwin,1);
    03055    XSetWMProperties(display,HelpWindow,&HelpName,NULL,NULL,0,NULL,NULL,NULL);
    03056    XSelectInput(display,HelpWindow,ButtonPressMask | ExposureMask);
    03057    XMapWindow(display,HelpWindow);
    03058    XMoveWindow(display,HelpWindow,x,y);
    03059    DrawHelpWindow();
    03060 }
    03061
    03062 int HitGridButton(XEvent* xe)
    03063 {
    03064    return (
    03065    (xe->xbutton.button == Button1) &&
    03066    (xe->xbutton.x >= Grid_XL  ) &&
    03067    (xe->xbutton.x <= Grid_XH  ) &&
    03068    (xe->xbutton.y >= Grid_YL  ) &&
    03069    (xe->xbutton.y <= Grid_YH  ));
    03070 }
    03071
    03072 int HitPauseButton(XEvent* xe)
    03073 {
    03074    return (
    03075    (xe->xbutton.button == Button1) &&
    03076    (xe->xbutton.x >= Pause_XL-2  ) &&
    03077    (xe->xbutton.x <= Pause_XH+2  ) &&
    03078    (xe->xbutton.y >= Pause_YL-2  ) &&
    03079    (xe->xbutton.y <= Pause_YH+2  ));
    03080 }
    03081
    03082 int HitStartButton(XEvent* xe)
    03083 {
    03084    return (
    03085    (xe->xbutton.button == Button1) &&
    03086    (xe->xbutton.x >= Start_XL-2  ) &&
    03087    (xe->xbutton.x <= Start_XH+2  ) &&
    03088    (xe->xbutton.y >= Start_YL-2  ) &&
    03089    (xe->xbutton.y <= Start_YH+2  ));
    03090 }
    03091
    03092 int HitStopButton(XEvent* xe)
    03093 {
    03094    return (
    03095    (xe->xbutton.button == Button1) &&
    03096    (xe->xbutton.x >= Stop_XL-2   ) &&
    03097    (xe->xbutton.x <= Stop_XH+2   ) &&
    03098    (xe->xbutton.y >= Stop_YL-2   ) &&
    03099    (xe->xbutton.y <= Stop_YH+2   ));
    03100 }
    03101
    03102 int HitHelpButton(XEvent* xe)
    03103 {
    03104    return (
    03105    (xe->xbutton.button == Button1) &&
    03106    (xe->xbutton.x >= Help_XL-2   ) &&
    03107    (xe->xbutton.x <= Help_XH+2   ) &&
    03108    (xe->xbutton.y >= Help_YL-2   ) &&
    03109    (xe->xbutton.y <= Help_YH+2   ));
    03110 }
    03111
    03112 int HitPlusButton(XEvent* xe)
    03113 {
    03114    return (
    03115    (xe->xbutton.button == Button1) &&
    03116    (xe->xbutton.x >= Plus_XL  ) &&
    03117    (xe->xbutton.x <= Plus_XH  ) &&
    03118    (xe->xbutton.y >= Plus_YL  ) &&
    03119    (xe->xbutton.y <= Plus_YH  ));
    03120 }
    03121
    03122 int HitFFWDButton(XEvent* xe)
    03123 {
    03124    return (
    03125    (xe->xbutton.button == Button1) &&
    03126    (xe->xbutton.x >= FFWD_XL  ) &&
    03127    (xe->xbutton.x <= FFWD_XH  ) &&
    03128    (xe->xbutton.y >= FFWD_YL  ) &&
    03129    (xe->xbutton.y <= FFWD_YH  ));
    03130 }
    03131
    03132 int HitMinusButton(XEvent* xe)
    03133 {
    03134    return (
    03135    (xe->xbutton.button == Button1) &&
    03136    (xe->xbutton.x >= Minus_XL  ) &&
    03137    (xe->xbutton.x <= Minus_XH  ) &&
    03138    (xe->xbutton.y >= Minus_YL  ) &&
    03139    (xe->xbutton.y <= Minus_YH  ));
    03140 }
    03141
    03142 int HitFBWDButton(XEvent* xe)
    03143 {
    03144    return (
    03145    (xe->xbutton.button == Button1) &&
    03146    (xe->xbutton.x >= FBWD_XL  ) &&
    03147    (xe->xbutton.x <= FBWD_XH  ) &&
    03148    (xe->xbutton.y >= FBWD_YL  ) &&
    03149    (xe->xbutton.y <= FBWD_YH  ));
    03150 }
    03151
    03152 int HitUpperPanel(XEvent* xe)
    03153 {
    03154    return (
    03155    (xe->xbutton.button == Button1) &&
    03156    (xe->xbutton.x >= Parc_XL  ) &&
    03157    (xe->xbutton.x <= Parc_XH  ) &&
    03158    (xe->xbutton.y >= Parc_YL-Parc_YD  ) &&
    03159    (xe->xbutton.y <= Parc_YL  ));
    03160 }
    03161
    03162 int HitLowerPanel(XEvent* xe)
    03163 {
    03164    return (
    03165    (xe->xbutton.button == Button1) &&
    03166    (xe->xbutton.x >= Parc_XL  ) &&
    03167    (xe->xbutton.x <= Parc_XH  ) &&
    03168    (xe->xbutton.y >= Parc_YH  ) &&
    03169    (xe->xbutton.y <= Parc_YH+Parc_YD));
    03170 }
    03171
    03172 int HitWindowSelect(XEvent* xe)
    03173 {
    03174    if (
    03175    (xe->xbutton.button == Button1) &&
    03176    (xe->xbutton.x >= Wbox_XL) &&
    03177    (xe->xbutton.x <= Wbox_XH) &&
    03178    (xe->xbutton.y >= Wbox_YL) &&
    03179    (xe->xbutton.y <= Wbox_YH))
    03180       return (xe->xbutton.y / FixFontHeight); /* Window number */
    03181    else return -1;
    03182 }
    03183
    03184 void OnMouseClick(void)
    03185 {
    03186    int w;
    03187
    03188    if (HitStopButton(&CowEvent))
    03189    {
    03190       Shutdown = 1;
    03191    }
    03192    else if (HitStartButton(&CowEvent))
    03193    {
    03194       Paused = 0;
    03195       XSetWMName(display,Cow,&WinconName1);
    03196    }
    03197    else if (HitGridButton(&CowEvent))
    03198    {
    03199       Grid = !Grid;
    03200       ShowGridStatus();
    03201       for (w=0 ; w < NUMWIN ; ++w) RedrawFlag[w] = 1;
    03202    }
    03203    else if (HitPauseButton(&CowEvent))
    03204    {
    03205       if (Paused)
    03206       {
    03207          Paused = 0;
    03208          XSetWMName(display,Cow,&WinconName1);
    03209       }
    03210       else
    03211       {
    03212          Paused = 1;
    03213          XSetWMName(display,Cow,&WinconPause);
    03214       }
    03215    }
    03216    else if (HitHelpButton(&CowEvent))
    03217    {
    03218       if (!HelpWindow) DisplayHelpWindow();
    03219    }
    03220    else if ((w = HitWindowSelect(&CowEvent)) >= 0)
    03221    {
    03222       if (Win[w]) CloseWindow(w);
    03223       else        ReopenWindow(w);
    03224    }
    03225    else if (HitPlusButton(&CowEvent))
    03226    {
    03227       Parc[cpi].Val += Parc[cpi].Inc;
    03228       if (Parc[cpi].Val > Parc[cpi].Max) Parc[cpi].Val = Parc[cpi].Max;
    03229    }
    03230    else if (HitFFWDButton(&CowEvent))
    03231    {
    03232       Parc[cpi].Val += 10.0 * Parc[cpi].Inc;
    03233       if (Parc[cpi].Val > Parc[cpi].Max) Parc[cpi].Val = Parc[cpi].Max;
    03234    }
    03235    else if (HitMinusButton(&CowEvent))
    03236    {
    03237        Parc[cpi].Val -= Parc[cpi].Inc;
    03238       if (Parc[cpi].Val < Parc[cpi].Min) Parc[cpi].Val = Parc[cpi].Min;
    03239    }
    03240    else if (HitFBWDButton(&CowEvent))
    03241    {
    03242        Parc[cpi].Val -= 10.0 * Parc[cpi].Inc;
    03243       if (Parc[cpi].Val < Parc[cpi].Min) Parc[cpi].Val = Parc[cpi].Min;
    03244    }
    03245    else if (HitUpperPanel(&CowEvent) && cpi > 0) --cpi;
    03246    else if (HitLowerPanel(&CowEvent) && cpi < Parcs-1) ++cpi;
    03247 }
    03248
    03249
    03250 void SwitchIndez(int w, int d)
    03251 {
    03252    int jlat;
    03253    REAL delphi;
    03254    char *lpt;
    03255    char levstr[20];
    03256
    03257    if (Indez[w] < 0 || Indez[w] >= MaxZ[w])
    03258    {
    03259       if (Debug) printf("### Indez[%d] = %d\n",w,Indez[w]);
    03260       if (Debug) printf("###  MaxZ[%d] = %d\n",w, MaxZ[w]);
    03261       Indez[w] = 0;
    03262    }
    03263    if (Indez[w]+d <  0      ) return;
    03264    if (Indez[w]+d >= MaxZ[w]) return;
    03265    Indez[w] += d;
    03266    lpt = strstr(WindowTitle[w],"Level");
    03267    if (lpt)
    03268    {
    03269       sprintf(levstr," %d",Indez[w]+1);
    03270       strcpy(lpt+5,levstr);
    03271       XStringListToTextProperty(&WindowTitle[w],1,WindowName+w);
    03272       XSetWMProperties(display,Win[w],WindowName+w,NULL,
    03273                 NULL,0,&WinSizeHints,&wm_hints,&class_hints);
    03274       LevelChanged[w] = 1;
    03275       return;
    03276    }
    03277    lpt = strstr(WindowTitle[w],"Latitude");
    03278    if (lpt)
    03279    {
    03280       delphi = 180.0 / MaxZ[w];
    03281       jlat = 90.0 -Indez[w] * delphi - delphi * 0.5;
    03282       if (jlat > 0) sprintf(levstr," %dN", jlat);
    03283       else          sprintf(levstr," %dS",-jlat);
    03284       strcpy(lpt+8,levstr);
    03285       XStringListToTextProperty(&WindowTitle[w],1,WindowName+w);
    03286       XSetWMProperties(display,Win[w],WindowName+w,NULL,
    03287                 NULL,0,&WinSizeHints,&wm_hints,&class_hints);
    03288       return;
    03289    }
    03290 }
    03291
    03292
    03293 void HandleEvents(void)
    03294 {
    03295    int w,Key,KeyIndex;
    03296    XEvent WinEvent;
    03297
    03298    if (nstep == 1)
    03299    {
    03300       RedrawControlWindow();
    03301       Paused = 1; /* Start in pause mode */
    03302    }
    03303
    03304
    03305    do
    03306    {
    03307       /* Check for Termination */
    03308
    03309       if (XCheckTypedWindowEvent(display,Cow,ClientMessage,&WinEvent))
    03310       {
    03311          /* printf("delwin %d\n",WinEvent.xclient.data.l[0]); */
    03312          Shutdown = 1;
    03313          return;
    03314       }
    03315
    03316       /* Check for user request to close windows */
    03317
    03318       for (w=0 ; w < NumWin ; ++w)
    03319       if (Win[w])
    03320       {
    03321          if (XCheckTypedWindowEvent(display,Win[w],ClientMessage,&WinEvent))
    03322          CloseWindow(w);
    03323       }
    03324
    03325       /* Check for user request to close help window */
    03326
    03327       if (HelpWindow && XCheckTypedWindowEvent(display,HelpWindow,ClientMessage,&WinEvent))
    03328       {
    03329          XDestroyWindow(display,HelpWindow);
    03330          HelpWindow = 0;
    03331       }
    03332
    03333       /* Check for mouse click */
    03334
    03335       if (XCheckTypedWindowEvent(display,Cow,ButtonPress,&CowEvent))
    03336       {
    03337          OnMouseClick();
    03338          RedrawControlWindow();
    03339       }
    03340
    03341       /* Check for mouseclicks and expose events */
    03342
    03343       for (w=0 ; w < NumWin ; ++w)
    03344       if (Win[w])
    03345       {
    03346          if (XCheckTypedWindowEvent(display,Win[w],ButtonPress,&CowEvent))
    03347          {
    03348            if (CowEvent.xbutton.button == Button1) SwitchIndez(w,-1);
    03349            if (CowEvent.xbutton.button == Button3) SwitchIndez(w, 1);
    03350            if (CowEvent.xbutton.button == Button2)
    03351            {
    03352               if (++MapPro[w] >= MAXMAPS) MapPro[w] = 0;
    03353               if (MapPro[w] == AZIMUTHAL &&
    03354                  (WinAtt[w].Plot != MAPHOR && WinAtt[w].Plot != MAPTRA))
    03355                  MapPro[w] = 0;
    03356            }
    03357            RedrawFlag[w] = 1;
    03358          }
    03359          if (XCheckTypedWindowEvent(display,Win[w],KeyPress,&CowEvent))
    03360          {
    03361             KeyIndex = (CowEvent.xkey.keycode - FirstKey) * SymsPerKey;
    03362             Key = KeyMap[KeyIndex];
    03363             if (Debug) printf("Windows %d got keyindex %d with symbol %x\n",w,KeyIndex,Key);
    03364             if (Key == ROTATE_LEFT  && MapLR[w].f <  5) MapLR[w].f++;
    03365             if (Key == ROTATE_RIGHT && MapLR[w].f > -5) MapLR[w].f--;
    03366             MapLR[w].r = MapLR[w].f * RotInc;
    03367             if (Key == XK_Up  ) SwitchIndez(w,-1);
    03368             if (Key == XK_Down) SwitchIndez(w, 1);
    03369          }
    03370          if (Paused)
    03371          if (XCheckTypedWindowEvent(display,Win[w],Expose,&CowEvent))
    03372                      RedrawIsoWindow(w);
    03373       }
    03374
    03375       if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent))
    03376          RedrawControlWindow();
    03377
    03378       if (HelpWindow && XCheckTypedWindowEvent(display,HelpWindow,Expose,&CowEvent))
    03379          DrawHelpWindow();
    03380
    03381    } while (Paused && !Shutdown);
    03382 }
    03383
    03384 void guiclose_(void)
    03385 {
    03386    int w;
    03387
    03388    if (MRpid >= 0) return; // Don't wait if multiple instances
    03389    XSetWMName(display,Cow,&WinconName3);
    03390
    03391    do
    03392    {
    03393       for (w=0 ; w < NumWin ; ++w)
    03394       if (Win[w])
    03395       {
    03396          if (XCheckTypedWindowEvent(display,Win[w],Expose,&CowEvent))
    03397                      RedrawIsoWindow(w);
    03398       }
    03399
    03400       if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent))
    03401          RedrawControlWindow();
    03402    }
    03403    while (!(XCheckTypedWindowEvent(display,Cow,ButtonPress,&CowEvent) &&
    03404             HitStopButton(&CowEvent)));
    03405
    03406 // XCloseDisplay(display); // segmentation fault on sun compiler!
    03407 }
    03408
    03409 void SaveConfig(void)
    03410 {
    03411    int i;
    03412    FILE *scp;
    03413    INTXS X,Y,xp,yp;
    03414    unsigned int w,W,H,border,depth;
    03415    Window Rootwin,Child;
    03416    XWindowAttributes RootAtt;
    03417
    03418    scp = fopen(GUI_config,"w");
    03419    if (scp == NULL) return;
    03420
    03421    /* Save window properties */
    03422
    03423    fprintf(scp,"Hamburg GUI Config File Version 16\n");
    03424    fprintf(scp,"Screen: %dx%d\n\n",ScreenW,ScreenH);
    03425    fprintf(scp,"WinRows = %d\n",WinRows);
    03426    fprintf(scp,"WinCols = %d\n",WinCols);
    03427    for (w=0 ; w < NumWin ; ++w)
    03428    {
    03429       fprintf(scp,"\n[Window %02d]\n",w);
    03430       fprintf(scp,"Array:%s\n",WinAtt[w].array_name);
    03431       fprintf(scp,"Plot:%s\n",IsoNames[WinAtt[w].Plot]);
    03432       if (WinAtt[w].Plot == ISOHOR || WinAtt[w].Plot == MAPHOR ||
    03433           WinAtt[w].Plot == ISOTRA || WinAtt[w].Plot == MAPTRA)
    03434       {
    03435          fprintf(scp,"Projection:%s\n",ProNames[MapPro[w]]);
    03436          fprintf(scp,"Rotation factor:%d\n",MapLR[w].f);
    03437       }
    03438       fprintf(scp,"Palette:%s\n",PalNames[WinAtt[w].Palette]);
    03439       fprintf(scp,"Title:%s\n",WindowTitle[w]+wto);
    03440       if (Win[w])
    03441       {
    03442          XGetGeometry(display,Win[w],&Rootwin,&xp,&yp,&W,&H,&border,&depth);
    03443          XTranslateCoordinates(display,Win[w],Rootwin,0,0,&X,&Y,&Child);
    03444          fprintf(scp,"Geometry: %4d %4d %4d %4d\n",W,H,X-WinLM,Y-WinTM);
    03445          if (Debug)
    03446          {
    03447             printf("Geometry Window %d   [%8x]: %4d / %4d   %4d x %4d x %2d | %d\n",
    03448                   w,(int)Win[w],xp,yp,W,H,depth,border);
    03449             printf("Translated UL corner: %4d / %4d\n",X,Y);
    03450          }
    03451       }
    03452       else
    03453          fprintf(scp,"Inactive: %4d %4d %4d %4d\n",
    03454                  WinAtt[w].w,WinAtt[w].h,WinAtt[w].x,WinAtt[w].y);
    03455    }
    03456    XGetGeometry(display,Cow,&Rootwin,&xp,&yp,&W,&H,&border,&depth);
    03457    XTranslateCoordinates(display,Cow,Rootwin,0,0,&X,&Y,&Child);
    03458    fprintf(scp,"\n[Control Window]\n");
    03459    fprintf(scp,"Geometry: %4d %4d %4d %4d\n",W,H,X-WinLM,Y-WinTM);
    03460
    03461    /* Scalar attributes for timeseries and tables */
    03462
    03463    fprintf(scp,"\n# Scalar attributes for timeseries and table window\n");
    03464
    03465    for (i=0 ; i < Parcs ; ++i)
    03466    {
    03467       fprintf(scp,"\n[Scalar %02d]\n",i);
    03468       fprintf(scp,"Name:%s\n",TSName[i]);
    03469       fprintf(scp,"Sub:%s\n",TSubsc[i]);
    03470       fprintf(scp,"Unit:%s\n",TSUnit[i]);
    03471       fprintf(scp,"Scale:%s\n",TScale[i]);
    03472    }
    03473
    03474    /* Scalar attributes for timeseries and tables */
    03475
    03476     fprintf(scp,"\n# Parameter attributes for change menu\n");
    03477
    03478    for (i=0 ; i < NUMSCALARS ; ++i)
    03479    {
    03480       if (strlen(Parc[i].Name) == 0) break;
    03481       fprintf(scp,"\n[Parameter %02d]\n",i);
    03482       fprintf(scp,"ParName:%s\n",Parc[i].Name);
    03483       fprintf(scp,"ParInc:%10.4f\n",Parc[i].Inc);
    03484       fprintf(scp,"ParMin:%10.4f\n",Parc[i].Min);
    03485       fprintf(scp,"ParMax:%10.4f\n",Parc[i].Max);
    03486    }
    03487
    03488    fclose(scp);
    03489 }
    03490
    03491
    03492 void lp2ps(REAL *a, REAL *b)
    03493 {
    03494    int i,j,k,l,k1,l1;
    03495    REAL xnp,ynp,xsp,ysp,dx,dy,x,y,lfa,ua,ub;
    03496
    03497    lfa = (DimX-1) / (2.0 * M_PI);
    03498    xnp = (DimX-1) * 0.25;
    03499    ynp = (DimY-1) * 0.50;
    03500    xsp = (DimX-1) * 0.75;
    03501    ysp = ynp;
    03502
    03503    /* Northern hemisphere */
    03504
    03505    for (j = 0 ; j <  DimY   ; ++j)
    03506    for (i = 0 ; i <= DimX/2 ; ++i)
    03507    {
    03508       dx = xnp - i;
    03509       dy = ynp - j;
    03510       x = atan2(dx,dy) * lfa;
    03511       y = sqrt(dx * dx + dy * dy);
    03512       if (x < 0.0) x += (DimX-1);
    03513       k = x;
    03514       l = y;
    03515       k1 = k + 1;
    03516       if (k1 >= DimX) k1 = 0;
    03517       if (l <= DimY/2+1)
    03518       {
    03519          ua = (k+1-x) *  a[k+l*DimX] + (x-k) * a[k1+l*DimX];
    03520          ub = (k+1-x) * a[k+(l+1)*DimX] + (x-k) * a[k+1+(l+1)*DimX];
    03521          b[i+j*DimX] = (l+1-y) * ua + (y-l) * ub;
    03522       }
    03523       else b[i+j*DimX] = - 99999.0;
    03524    }
    03525
    03526    /* Souhern hemisphere */
    03527
    03528    for (j = 0        ; j < DimY ; ++j)
    03529    for (i = DimX/2+1 ; i < DimX ; ++i)
    03530    {
    03531       dx = i - xsp;
    03532       dy = ysp - j;
    03533       x = atan2(dx,dy) * lfa;
    03534       y = (DimY-1) - sqrt(dx * dx + dy * dy);
    03535       if (x < 0.0) x += (DimX-1);
    03536       k = x;
    03537       l = y;
    03538       k1 = k + 1;
    03539       if (k1 >= DimX) k1 = 0;
    03540       if (l >= DimY/2-3)
    03541       {
    03542          ua = (k+1-x) *  a[k+l*DimX] + (x-k) * a[k1+l*DimX];
    03543          ub = (k+1-x) * a[k+(l+1)*DimX] + (x-k) * a[k+1+(l+1)*DimX];
    03544          b[i+j*DimX] = (l+1-y) * ua + (y-l) * ub;
    03545       }
    03546       else b[i+j*DimX] = - 99999.0;
    03547    }
    03548 }
    03549
    03550
    03551 /* ======================================================= */
    03552 /* lp2az - transform lon/lat array to azimuthal projection */
    03553 /* ======================================================= */
    03554
    03555 void lp2az(REAL *a, REAL *b, float laz)
    03556 {
    03557    int x,y,dxc,k,k1,l;
    03558    REAL dx,dy,lam,rho,rad,phi,ua,ub,l00,p00,xpi,ypi;
    03559
    03560    rad = DimY >> 1;
    03561    dxc = DimX >> 1;
    03562    xpi = DimX / M_PI * 0.5;
    03563    ypi = DimY / M_PI;
    03564    l00 =  (int)((laz * DimX) / 360 + dxc) % DimX;
    03565    p00 = DimY / 2;
    03566
    03567    for (y = 0 ; y < DimY ; ++y)
    03568    {
    03569       dy  = y - rad;
    03570       phi = y;
    03571       for (x = 0 ; x < DimX ; ++x)
    03572       {
    03573          dx = x - dxc;
    03574          rho = sqrt(dx * dx + dy * dy);
    03575          if (rho < rad)
    03576          {
    03577             lam = l00 + xpi * atan2(dx / rad, cos(asin(rho / rad)));
    03578             phi = p00 + ypi *  asin(dy / rad);
    03579             k = lam;
    03580             k1 = k + 1;
    03581             if (k1 >= DimX) k1 = 0;
    03582             l = phi;
    03583             ua = (k+1-lam) * a[k+ l   *DimX] + (lam-k) * a[k1 + l   *DimX];
    03584             ub = (k+1-lam) * a[k+(l+1)*DimX] + (lam-k) * a[k+1+(l+1)*DimX];
    03585             b[x+y*DimX] = (l+1-y) * ua + (y-l) * ub;
    03586          }
    03587          else b[x+y*DimX] = - 99999.0;
    03588       }
    03589    }
    03590 }
    03591
    03592 void ShowGridCS(void)
    03593 {
    03594    int jlev,jlat,x,y,len;
    03595    float dx,dy;
    03596    char Text[80];
    03597
    03598    /* Grid for zonal mean cross sections */
    03599
    03600    XSetForeground(display,gc,WhitePix);
    03601    XSetBackground(display,gc,BlackPix);
    03602    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03603    dy = (InYSize - OffY) / (DimY - 1.0);
    03604    for (jlev = 1 ; jlev < DimY-1 ; ++jlev)
    03605    {
    03606       y = OffY + jlev * dy;
    03607       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03608    }
    03609    dx = (InXSize - OffX) / 6.0; /* Every 30 degrees */
    03610    for (jlat = 1 ; jlat < 6 ; ++jlat)
    03611    {
    03612       x = OffX + jlat * dx;
    03613       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03614    }
    03615    if (GridLabel)
    03616    {
    03617       XDrawImageString(display,pix,gc,InXSize/2-FixFontWidth,InYSize-FixFont->descent,"EQ",2);
    03618       XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"N",1);
    03619       XDrawImageString(display,pix,gc,InXSize-FixFontWidth,InYSize-FixFont->descent,"S",1);
    03620    }
    03621    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03622 }
    03623
    03624 void ShowGridCol(void)
    03625 {
    03626    int jlev,jtim,x,y,len;
    03627    float dx,dy;
    03628    char Text[80];
    03629
    03630    /* Grid for column time series */
    03631
    03632    XSetForeground(display,gc,WhitePix);
    03633    XSetBackground(display,gc,BlackPix);
    03634    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03635    dy = (InYSize - OffY) / (DimY - 1.0);
    03636    for (jlev = 1 ; jlev < DimY-1 ; ++jlev)
    03637    {
    03638       y = OffY + jlev * dy;
    03639       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03640    }
    03641    dx = (InXSize - OffX) / 4.0; /* 4 slices */
    03642    for (jtim = 1 ; jtim < 4 ; ++jtim)
    03643    {
    03644       x = OffX + jtim * dx;
    03645       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03646    }
    03647    if (GridLabel)
    03648    {
    03649       XDrawImageString(display,pix,gc,InXSize/2-3*FixFontWidth/2,InYSize-FixFont->descent,"t-2",3);
    03650       XDrawImageString(display,pix,gc,InXSize/4-3*FixFontWidth/2,InYSize-FixFont->descent,"t-3",3);
    03651       XDrawImageString(display,pix,gc,3*InXSize/4-3*FixFontWidth/2,InYSize-FixFont->descent,"t-1",3);
    03652    }
    03653    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03654 }
    03655
    03656 void ShowGridLonsi(void)
    03657 {
    03658    int jlev,jlat,x,y,len;
    03659    float dx,dy;
    03660    char Text[80];
    03661
    03662    /* Grid for Longitude Sigma section */
    03663
    03664    XSetForeground(display,gc,WhitePix);
    03665    XSetBackground(display,gc,BlackPix);
    03666    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03667    dy = (InYSize - OffY) / (DimY - 1.0);
    03668    for (jlev = 1 ; jlev < DimY-1 ; ++jlev)
    03669    {
    03670       y = OffY + jlev * dy;
    03671       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03672    }
    03673    dx = (InXSize - OffX) / 6.0; /* Every 60 degrees */
    03674    for (jlat = 1 ; jlat < 6 ; ++jlat)
    03675    {
    03676       x = OffX + jlat * dx;
    03677       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03678    }
    03679    if (GridLabel)
    03680    {
    03681       XDrawImageString(display,pix,gc,InXSize/2-3*FixFontWidth/2,InYSize-FixFont->descent,"180",3);
    03682       XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"0",1);
    03683       XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"360",3);
    03684    }
    03685    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03686 }
    03687
    03688 void ShowGridCyl(void)
    03689 {
    03690    int jlon,jlat,x,y;
    03691    float dx,dy;
    03692
    03693    /* Grid for cylinder projection */
    03694
    03695    XSetForeground(display,gc,WhitePix);
    03696    XSetBackground(display,gc,BlackPix);
    03697    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03698    dy = (InYSize - OffY) / 6.0;
    03699    for (jlat = 1 ; jlat < 6 ; ++jlat)
    03700    {
    03701       y = OffY + jlat * dy;
    03702       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03703    }
    03704    dx = (InXSize - OffX) / 6.0; /* Every 30 degrees */
    03705    for (jlon = 1 ; jlon < 6 ; ++jlon)
    03706    {
    03707       x = OffX + jlon * dx;
    03708       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03709    }
    03710    if (GridLabel)
    03711    {
    03712       XDrawImageString(display,pix,gc,OffX,OffY+(InYSize-OffY)/2+FixFontHeight/2-FixFont->descent,"EQ",2);
    03713       XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"N",1);
    03714       XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"-180",4);
    03715       XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"180",3);
    03716       XDrawImageString(display,pix,gc,OffX+(InXSize-OffX)/2-3*FixFontWidth/2,InYSize-FixFont->descent,"0",1);
    03717    }
    03718    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03719 }
    03720
    03721 void ShowGridHov(void)
    03722 {
    03723    int jlon,jlat,x,y,len;
    03724    float dx,dy;
    03725    char Text[80];
    03726
    03727    /* Grid for Hovmoeller */
    03728
    03729    XSetForeground(display,gc,WhitePix);
    03730    XSetBackground(display,gc,BlackPix);
    03731    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03732    dx = (InXSize - OffX) / 6.0;
    03733    for (jlon = 1 ; jlon < 6 ; ++jlon)
    03734    {
    03735       x = OffX + jlon * dx;
    03736       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03737    }
    03738    dy = (InYSize - OffY) / 5.0; /* Every 5 days */
    03739    for (jlat = 1 ; jlat < 5 ; ++jlat)
    03740    {
    03741       y = OffY + jlat * dy;
    03742       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03743    }
    03744    if (GridLabel)
    03745    {
    03746       XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"0",1);
    03747       XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"360",3);
    03748       XDrawImageString(display,pix,gc,OffX+(InXSize-OffX)/2-3*FixFontWidth/2,InYSize-FixFont->descent,"180",3);
    03749       XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"t0",2);
    03750       XDrawImageString(display,pix,gc,OffX,OffY+2*InYSize/5+FixFontHeight/2-FixFont->descent,"t-2",3);
    03751       XDrawImageString(display,pix,gc,OffX,OffY+4*InYSize/5+FixFontHeight/2-FixFont->descent,"t-4",3);
    03752    }
    03753    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03754 }
    03755
    03756 void ShowGridHovT(void)
    03757 {
    03758    int jlon,jlat,x,y,len;
    03759    float dx,dy;
    03760    char Text[80];
    03761
    03762    /* Grid for Hovmoeller */
    03763
    03764    XSetForeground(display,gc,WhitePix);
    03765    XSetBackground(display,gc,BlackPix);
    03766    XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03767    dy = (InYSize - OffY) / 6.0;
    03768    for (jlat = 1 ; jlat < 6 ; ++jlat)
    03769    {
    03770       y = OffY + jlat * dy;
    03771       XDrawLine(display,pix,gc,OffX,y,InXSize-1,y);
    03772    }
    03773    dx = (InXSize - OffX) / 5.0; /* Every 5 days */
    03774    for (jlat = 1 ; jlat < 5 ; ++jlat)
    03775    {
    03776       x = OffX + jlat * dx;
    03777       XDrawLine(display,pix,gc,x,OffY,x,InYSize-1);
    03778    }
    03779    if (GridLabel)
    03780    {
    03781       XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"0",1);
    03782       XDrawImageString(display,pix,gc,OffX,OffY+(InYSize-OffY)/2+FixFontHeight/2-FixFont->descent,"180",3);
    03783       XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"360",3);
    03784       XDrawImageString(display,pix,gc,InXSize-2*FixFontWidth,InYSize-FixFont->descent,"t0",2);
    03785       XDrawImageString(display,pix,gc,3*InXSize/5-3*FixFontWidth/2,InYSize-FixFont->descent,"t-2",3);
    03786       XDrawImageString(display,pix,gc,  InXSize/5-3*FixFontWidth/2,InYSize-FixFont->descent,"t-4",3);
    03787    }
    03788    XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03789 }
    03790
    03791 void ShowGridPolar(void)
    03792 {
    03793    int dx,dy,x,y,xh,yh,ox,oy;
    03794    XPoint pxy[3];
    03795
    03796    /* Grid for polar projection */
    03797
    03798    dx = (InXSize - OffX) / 2;
    03799    dy = (InYSize - OffY);
    03800    xh = dx / 2;
    03801    yh = dy / 2;
    03802    ox = dx / 3.414;
    03803    oy = dy / 3.414;
    03804
    03805    if (Grid)
    03806    {
    03807       XSetForeground(display,gc,WhitePix);
    03808       XSetBackground(display,gc,BlackPix);
    03809       XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound);
    03810
    03811       /* Northern Hemisphere */
    03812
    03813       XDrawArc(display,pix,gc,OffX+dx/6,OffY+dy/6,2*dx/3,2*dy/3,0,360*64);
    03814       XDrawArc(display,pix,gc,OffX+dx/3,OffY+dy/3,dx/3,dy/3,0,360*64);
    03815
    03816       XDrawLine(display,pix,gc,OffX,yh,InXSize,yh);
    03817       XDrawLine(display,pix,gc,OffX+xh,OffY,OffX+xh,InYSize);
    03818
    03819       /* Southern Hemisphere */
    03820
    03821       XDrawArc(display,pix,gc,OffX+7*dx/6,OffY+dy/6,2*dx/3,2*dy/3,0,360*64);
    03822       XDrawArc(display,pix,gc,OffX+4*dx/3,OffY+dy/3,dx/3,dy/3,0,360*64);
    03823
    03824       x = OffX + dx + xh;
    03825       XDrawLine(display,pix,gc,x,OffY,x,InYSize);
    03826
    03827       if (GridLabel)
    03828       {
    03829          x  = OffX + xh - FixFontWidth/2;
    03830          y  = OffY + yh + FixFontHeight/2 - FixFont->descent;
    03831          XDrawImageString(display,pix,gc,x,y,"N",1);
    03832          XDrawImageString(display,pix,gc,x+dx,y,"S",1);
    03833       }
    03834       XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound);
    03835    }
    03836
    03837    /* Octagon mask */
    03838
    03839    XSetForeground(display,gc,BlackPix);
    03840    pxy[0].x = pxy[1].x = OffX;
    03841    pxy[0].y = pxy[2].y = OffY;
    03842    pxy[1].y = OffY + oy;
    03843    pxy[2].x = OffX + ox;
    03844    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03845    pxy[0].x = OffX + dx - ox;
    03846    pxy[1].x = OffX + dx;
    03847    pxy[2].x = OffX + dx + ox;
    03848    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03849    pxy[0].x = InXSize - ox;
    03850    pxy[1].x = InXSize;
    03851    pxy[2].x = InXSize;
    03852    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03853
    03854    pxy[0].x = pxy[1].x = OffX;
    03855    pxy[0].y = pxy[2].y = InYSize;
    03856    pxy[1].y = InYSize - oy;
    03857    pxy[2].x = OffX + ox;
    03858    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03859    pxy[0].x = OffX + dx - ox;
    03860    pxy[1].x = OffX + dx;
    03861    pxy[2].x = OffX + dx + ox;
    03862    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03863    pxy[0].x = InXSize - ox;
    03864    pxy[1].x = InXSize;
    03865    pxy[2].x = InXSize;
    03866    XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin);
    03867 }
    03868
    03869
    03870 void AutoPalette(int w, struct ColorStrip Strip[], REAL f[], int Dim)
    03871 {
    03872    int i,nbands;
    03873    double fmin, fmax, frange, delta, fdelta, xdelta, Lo;
    03874
    03875    fmin = fmax = f[0];
    03876    for (i=0; i < Dim ; ++i)
    03877    {
    03878       if (fmin > f[i]) fmin = f[i];
    03879       if (fmax < f[i]) fmax = f[i];
    03880    }
    03881    frange = fmax - fmin;
    03882    Lo     = 0.0;
    03883    xdelta = 0.1;
    03884    if (frange > 1.0e-10)
    03885    {
    03886        delta  = frange / AUTOCOLORS;
    03887        if (delta > AutoDelta[w] / 1.4 && delta < 1.4 * AutoDelta[w])
    03888        {
    03889           xdelta = AutoXdelt[w];
    03890           delta  = AutoDelta[w];
    03891           Lo     = AutoLo[w];
    03892        }
    03893        else
    03894        {
    03895           fdelta = pow(10.0,rint(log10(delta)));
    03896           xdelta = fdelta;
    03897           nbands = frange / xdelta;
    03898           if (nbands < AUTOCOLORS / 2) xdelta = 0.5 * fdelta;
    03899           if (nbands > AUTOCOLORS    ) xdelta = 2.0 * fdelta;
    03900           nbands = frange / xdelta;
    03901           if (nbands > AUTOCOLORS    ) xdelta = 5.0 * fdelta;
    03902           Lo = xdelta * floor(fmin / xdelta);
    03903           AutoDelta[w] = delta;
    03904           AutoXdelt[w] = xdelta;
    03905           AutoLo[w]    = Lo;
    03906 /*
    03907           if (Debug)
    03908           {
    03909              printf("Autopalette\n");
    03910              printf(" Range: %14.6e\n",frange);
    03911              printf(" delta: %14.6e\n",delta);
    03912              printf("fdelta: %14.6e\n",fdelta);
    03913              printf("xdelta: %14.6e\n",xdelta);
    03914           }
    03915 */
    03916        }
    03917    }
    03918    Strip[0].Lo = Lo;
    03919    for (i=0 ; i < AUTOCOLORS ; ++i)
    03920    {
    03921        Strip[i+1].Lo = Strip[i].Hi = Strip[i].Lo + xdelta;
    03922        // if (Debug) printf("Auto[%2d] = %10.4f - %10.4f\n",i,Strip[i].Lo,Strip[i].Hi);
    03923    }
    03924    return;
    03925 }
    03926
    03927
    03928 // Interface routine to model code in FORTRAN
    03929
    03930 void guiput_(char *aname, float *array, int *dimx, int *dimy, int *dimz)
    03931 {
    03932    int i,nb,nf;
    03933
    03934    if (Debug) printf("guiput(%s,%12.4e,%d,%d,%d)\n",
    03935                      aname,*array,*dimx,*dimy,*dimz);
    03936    nf = (*dimx) * (*dimz);
    03937    if (*dimy > 0) nf *= (*dimy);
    03938    else           nf *= 2;
    03939    nb = nf * sizeof(float);
    03940    for (i=0 ; i < NumArrays ; ++i)
    03941       if (!strcmp(aname,Array[i].Name)) break;
    03942    if (i == NumArrays)
    03943    {
    03944       ++NumArrays;
    03945       strcpy(Array[i].Name,aname);
    03946       Array[i].Data = FloatAlloc(nf,aname);
    03947       Array[i].DimX = *dimx;
    03948       Array[i].DimY = *dimy;
    03949       Array[i].DimZ = *dimz;
    03950       if (strcmp(aname,"GU") == 0) Uindex = i;
    03951       if (strcmp(aname,"GV") == 0) Vindex = i;
    03952    }
    03953    if (Array[i].Data) memcpy(Array[i].Data,array,nb);
    03954    Array[i].Flag = 1; // Data have changed
    03955 }
    03956
    03957
    03958 void guisend_(char *aname, float *array, int *dimx, int *dimy, int *dimz)
    03959 {
    03960    int i,nb,nf;
    03961
    03962    nf = (*dimx) * (*dimz);
    03963    if (*dimy > 0) nf *= (*dimy);
    03964    else           nf *= 2;
    03965    nb = nf * sizeof(float);
    03966    for (i=0 ; i < NumArrays ; ++i)
    03967       if (!strcmp(aname,Array[i].Name)) break;
    03968    if (i == NumArrays)
    03969    {
    03970       ++NumArrays;
    03971       strcpy(Array[i].Name,aname);
    03972       Array[i].DimX = *dimx;
    03973       Array[i].DimY = *dimy;
    03974       Array[i].DimZ = *dimz;
    03975    }
    03976    Array[i].Data = array;
    03977    Array[i].Flag = 1; // Data have changed
    03978 }
    03979
    03980
    03981 // Do the plot
    03982
    03983 void iso(int w,int PicType,REAL *field,int dimx,int dimy,int dimz,int pal)
    03984 {
    03985    char Text[128];
    03986
    03987    int i,j,k,len,lens,xp,yp,status,x;
    03988    int y,dx,r,width,height;
    03989    INTXU border,depth;
    03990    REAL f,o,ra,rb;
    03991    int CapLines;
    03992    float *tspt;
    03993    XEvent WinEvent;
    03994    Window Rootwin,Child;
    03995
    03996    // if (Debug) printf("iso(%d,%s,%12.4e,%d,%d,%d,%d)\n",w,IsoNames[PicType],*field,dimx,dimy,dimz,pal);
    03997    if (Win[w] == 0) return;
    03998    win = w;
    03999    if (SkipFreq > 1 && (nstep % SkipFreq) != 0 &&
    04000       (PicType == ISOCS || PicType == ISOHOR || PicType == MAPHOR || PicType == ISOCOL)) return;
    04001    XGetGeometry(display,Win[w],&Rootwin,&xp,&yp,&WinXSize,&WinYSize,
    04002                 &border,&depth);
    04003    WinAtt[w].w = WinXSize;
    04004    WinAtt[w].h = WinYSize;
    04005    InXSize = WinXSize - OffX;
    04006    InYSize = WinYSize - OffY;
    04007    if (PicType != ISOTRA && PicType != MAPTRA) InYSize -= 20; // Room for colorbar
    04008    DimX  = dimx;
    04009    DimY  = dimy;
    04010    DimZ  = dimz;
    04011    if (DimY < 0) DimY = -DimY; // Get NTP1 for ISOSH
    04012    DimXY = DimX * DimY;
    04013    VGAX  = (InXSize-1.0) / (DimX-1.0);
    04014    if (DimY > 1) VGAY  = (InYSize-1.0) / (DimY-1.0);
    04015    else          VGAY  = 1.0;
    04016    Field = field;
    04017
    04018    if (PicType == ISOTRA || PicType == MAPTRA)
    04019    {
    04020       DimX  = dimx; // NLON
    04021       DimY  = dimy; // NLAT
    04022       DimZ  = dimz; // NLEV
    04023       DimXY = DimX * DimY;
    04024       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04025       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04026       if (MaxZ[w] < DimZ)
    04027       {
    04028          MaxZ[w]   = DimZ;
    04029          Indez[w]  = DimZ / 4;
    04030          SwitchIndez(w,0); // Initialize title
    04031       }
    04032    }
    04033
    04034    if (PicType == ISOHOR || PicType == MAPHOR)
    04035    {
    04036       DimX  = dimx; // NLON
    04037       DimY  = dimy; // NLAT
    04038       DimZ  = dimz; // NLEV
    04039       DimXY = DimX * DimY;
    04040       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04041       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04042       if (MaxZ[w] < DimZ)
    04043       {
    04044          MaxZ[w]   = DimZ;
    04045          Indez[w]  = DimZ / 4;
    04046          SwitchIndez(w,0); // Initialize title
    04047          TSdata[w] = FloatAlloc(DimXY,"ISOLON");
    04048       }
    04049       if (MapPro[w] == POLAR)
    04050       {
    04051          Field = TSdata[w];
    04052          lp2ps(field + Indez[w] * DimXY,Field);
    04053       }
    04054 /*
    04055       else if (MapPro[w] == AZIMUTHAL)
    04056       {
    04057          Field = TSdata[w];
    04058          lp2az(field + Indez[w] * DimXY,Field,MapLR[w].l);
    04059       }
    04060 */
    04061       else Field = field + Indez[w] * DimXY;
    04062    }
    04063
    04064    if (PicType == ISOLON)
    04065    {
    04066       DimX  = dimx; // NLON
    04067       DimY  = dimz; // NLEV
    04068       DimZ  = dimy; // NLAT
    04069       DimXY = DimX * DimY;
    04070       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04071       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04072       if (!TSdata[w])
    04073       {
    04074          TSdata[w] = FloatAlloc(DimXY,"ISOLON");
    04075          MaxZ[w]   = DimZ;
    04076          Indez[w]  = DimZ / 4;
    04077          SwitchIndez(w,0); // Initialize title
    04078       }
    04079       Field = TSdata[w];
    04080       for (j=0,i=0,k=DimX*Indez[w] ; j < DimY ; ++j,i+=DimX,k+=DimX*DimZ)
    04081       {
    04082          memcpy(Field+i,field+k,DimX * sizeof(REAL)); // copy latitude
    04083       }
    04084    }
    04085
    04086    if (PicType == ISOHOV)
    04087    {
    04088       DimX  = dimx; // NLON
    04089       DimY  = DimT; // time
    04090       DimZ  = dimy; // NLAT
    04091       DimXY = DimX * DimY;
    04092       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04093       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04094       if (!TSdata[w])
    04095       {
    04096          TSdata[w] = FloatAlloc(DimXY,"ISOHOV");
    04097          MaxZ[w]   = DimZ;
    04098          Indez[w]  = DimZ / 4;
    04099          SwitchIndez(w,0); // Initialize title
    04100       }
    04101       Field = TSdata[w];
    04102       memmove(Field+DimX,Field,(DimXY-DimX) * sizeof(REAL)); // scroll array
    04103       memcpy(Field,field+Indez[w]*DimX,DimX * sizeof(REAL)); // add line
    04104    }
    04105
    04106    // Advance write pointer HovInx until end of DimX
    04107    // then scroll array and reset pointer
    04108
    04109    if (PicType == ISOTS)
    04110    {
    04111       DimX  = DimT; // time
    04112       DimY  = dimx; // # of variables
    04113       DimZ  = dimz;
    04114       DimXY = DimX * DimY;
    04115       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04116       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04117       if (!TSdata[w])
    04118       {
    04119          TSdata[w] = FloatAlloc(DimXY+DimX,"ISOTS");
    04120       }
    04121       tspt  = TSdata[w];
    04122       ++HovInx[w];
    04123       if (HovInx[w] >= DimX)
    04124       {
    04125           HovInx[w] = 0;
    04126           memmove(tspt,tspt+DimX,DimXY * sizeof(REAL)); // scroll array
    04127       }
    04128       for (i=HovInx[w]+DimX-1,j=0 ; j < DimY ; i+=DimX,++j)
    04129          tspt[i] = field[j];                                  // add column
    04130       Field = tspt+HovInx[w];
    04131    }
    04132
    04133    if (PicType == ISOCOL)
    04134    {
    04135       DimX  = DimT; // time
    04136       DimY  = dimx; // level
    04137       DimZ  = dimy; // clickable index
    04138       DimXY = DimX * DimY;
    04139       VGAX  = (InXSize-1.0) / (DimX-1.0);
    04140       VGAY  = (InYSize-1.0) / (DimY-1.0);
    04141       if (!TSdata[w])
    04142       {
    04143          TSdata[w] = FloatAlloc(DimXY+DimX,"ISOCOL");
    04144          MaxZ[w]   = DimZ;
    04145          Indez[w]  = DimZ / 2;
    04146          SwitchIndez(w,0); // Initialize title
    04147       }
    04148       tspt  = TSdata[w];
    04149       ++HovInx[w];
    04150       if (HovInx[w] >= DimX)
    04151       {
    04152           HovInx[w] = 0;
    04153           memmove(tspt,tspt+DimX,DimXY * sizeof(REAL)); // scroll array
    04154       }
    04155       for (i=HovInx[w]+DimX-1,j=0 ; j < DimY ; i+=DimX,++j)
    04156          tspt[i] = field[j+Indez[w]*DimY];                                  // add column
    04157       Field = tspt+HovInx[w];
    04158    }
    04159
    04160    if (DimX > FlagSize)
    04161    {
    04162       if (Flag) free(Flag);
    04163       Flag = IntAlloc(DimX,"Flag");
    04164       FlagSize = DimX;
    04165    }
    04166
    04167    if (PicType == ISOSH) pal = 1; // ISOSH has its own palette
    04168    if (pal < 1 || pal >= NUMPAL)
    04169    {
    04170       Cstrip = Autostrip;
    04171       AutoPalette(w,Cstrip,Field,DimXY);
    04172       Lines  = AUTOCOLORS;
    04173       // printf("Autopalette %d for Win %d\n",pal,w);
    04174    }
    04175    else
    04176    {
    04177       Cstrip = Pallet[pal];
    04178       Lines  = LineCo[pal];
    04179    }
    04180
    04181    SizeChanged = (WinPixMap[w].DimX != WinXSize || WinPixMap[w].DimY != WinYSize);
    04182    if (SizeChanged)
    04183    {
    04184       if (WinPixMap[w].Pix) XFreePixmap(display,WinPixMap[w].Pix);
    04185       WinPixMap[w].Pix = XCreatePixmap(display,Win[w],WinXSize,WinYSize,ScreenD);
    04186       if (Debug)
    04187          printf("CreatePixmap  %10x %6d bytes\n",
    04188                (unsigned int)WinPixMap[w].Pix,WinXSize*WinYSize);
    04189       WinPixMap[w].DimX = WinXSize;
    04190       WinPixMap[w].DimY = WinYSize;
    04191    }
    04192    pix = WinPixMap[w].Pix; /* Set current pixmap */
    04193
    04194    /* Draw colour bar */
    04195
    04196    if ((SizeChanged || Cstrip == Autostrip) &&
    04197        (PicType == ISOCS  || PicType == ISOHOR ||
    04198         PicType == ISOHOV || PicType == ISOLON ||
    04199         PicType == ISOCOL || PicType == MAPHOR ))
    04200    {
    04201       XSetForeground(display,gc,BlackPix);
    04202       XFillRectangle(display,pix,gc,0,InYSize,WinXSize,WinYSize);
    04203
    04204       CapLines = WinXSize / (20 + 3 * FixFontWidth);
    04205       if (CapLines > Lines) CapLines = Lines;
    04206       for (i=0 ; i < CapLines ; ++i)
    04207       {
    04208          XSetForeground(display,gc,Cstrip[i].pixel);
    04209          XFillRectangle(display,pix,gc,OffX+5+i*(WinXSize-20)/(CapLines-1),
    04210                         OffY+InYSize+5,10,10);
    04211          XSetForeground(display,gc,BlackPix);
    04212          XDrawRectangle(display,pix,gc,OffX+5+i*(WinXSize-20)/(CapLines-1),
    04213                         OffY+InYSize+5,10,10);
    04214       }
    04215       XSetForeground(display,gc,WhitePix);
    04216       XSetBackground(display,gc,BlackPix);
    04217       rb = Cstrip[CapLines-2].Hi - Cstrip[0].Hi;
    04218       for (i=0 ; i < CapLines-1 ; ++i)
    04219       {
    04220          Text[0] = 0;
    04221          ra = Cstrip[i].Hi;
    04222          j = ra;
    04223          if (j > -1000 && j < 10000) sprintf(Text,"%d",j);
    04224          if (ra < 100.0 && ra > -9.99)
    04225          {
    04226             sprintf(Text,"%4.1f",ra);
    04227             if (!strcmp(Text+2,".0")) Text[2] = 0;
    04228          }
    04229          if (ra < 10.0 && ra >= 0.0)
    04230          {
    04231             sprintf(Text,"%4.2f",ra);
    04232             if (!strcmp(Text+1,".00")) Text[1] = 0;
    04233          }
    04234          len    = strlen(Text);
    04235          if (len)
    04236          {
    04237             width  = XTextWidth(FixFont,Text,len);
    04238             height = FixFont->ascent + FixFont->descent;
    04239             xp     = OffX + 10 + (i+0.5) * (WinXSize-20)/(CapLines-1) - width/2;
    04240             yp     = WinYSize - height + 10;
    04241             XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04242          }
    04243       }
    04244    }
    04245
    04246    /* Draw mode legend */
    04247
    04248    if (SizeChanged && PicType == ISOSH)
    04249    {
    04250       dx = WinXSize / 23;
    04251       XSetForeground(display,gc,BlackPix);
    04252       XFillRectangle(display,pix,gc,0,0,WinXSize,WinYSize);
    04253
    04254       XSetForeground(display,gc,LightGreen.pixel);
    04255       XSetBackground(display,gc,BlackPix);
    04256       for (i=0 ; i < 21 ; i+=2)
    04257       {
    04258          sprintf(Text,"%d",i);
    04259          len    = strlen(Text);
    04260          width  = XTextWidth(FixFont,Text,len);
    04261          height = FixFont->ascent + FixFont->descent;
    04262          xp     = dx + i * dx - width/2 - FixFontWidth/2 + 1;
    04263          yp     = FixFontHeight;
    04264          XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04265       }
    04266       XSetForeground(display,gc,LightBlue.pixel);
    04267       for (i=0 ; i < 21 ; i+=2)
    04268       {
    04269          sprintf(Text,"%d",i);
    04270          len    = strlen(Text);
    04271          width  = XTextWidth(FixFont,Text,len);
    04272          height = FixFont->ascent + FixFont->descent;
    04273          xp     = WinXSize - width - 2;
    04274          yp     = 2 * FixFontHeight + i * dx;
    04275          if (yp+FixFont->descent > InYSize) break;
    04276          XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04277       }
    04278       strcpy(Text,"n/m");
    04279       len    = strlen(Text);
    04280       width  = XTextWidth(FixFont,Text,len);
    04281       xp     = WinXSize - width - 2;
    04282       yp     = FixFontHeight;
    04283       XSetForeground(display,gc,WhitePix);
    04284       XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04285       strcpy(Text,"High ");
    04286       len    = strlen(Text);
    04287       width  = XTextWidth(FixFont,Text,len);
    04288       xp     = WinXSize/2 - AMPLI_COLS * 10 - width;
    04289       yp     = WinYSize - FixFontHeight + 10;
    04290       r      = FixFontHeight-2;
    04291       XSetForeground(display,gc,WhitePix);
    04292       if (xp > 0) XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04293       strcpy(Text," Low");
    04294       len    = strlen(Text);
    04295       width  = XTextWidth(FixFont,Text,len);
    04296       xp     = WinXSize/2 + AMPLI_COLS * 10;
    04297       if (xp + width < WinXSize) XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04298       yp     = InYSize;
    04299       XDrawLine(display,pix,gc,OffX,yp,WinXSize,yp);
    04300       yp     = WinYSize - r -  FixFont->descent;
    04301
    04302       for (i=0 ; i < AMPLI_COLS ; ++i)
    04303       {
    04304          xp = WinXSize/2 - AMPLI_COLS * 10 + i * 20;
    04305          XSetForeground(display,gc,AmpliStrip[AMPLI_COLS-i-1].pixel);
    04306          XFillArc(display,pix,gc,xp,yp,r,r,0,360*64);
    04307       }
    04308    }
    04309
    04310    if (SizeChanged && PicType == ISOTS) /* Timeseries Caption */
    04311    {
    04312       XSetForeground(display,gc,BlackPix);
    04313       XFillRectangle(display,pix,gc,0,InYSize,WinXSize,WinYSize);
    04314       XSetBackground(display,gc,BlackPix);
    04315
    04316       xp = FixFontWidth;
    04317       yp = WinYSize - FixFontHeight + 10;
    04318       for (j=0 ; j < DimY ; ++j)
    04319       {
    04320          if (TSName[j][0])
    04321          {
    04322             strcpy(Text,TSName[j]);
    04323             len    = strlen(Text);
    04324             width  = XTextWidth(FixFont,Text,len);
    04325             XSetForeground(display,gc,TSColor[j]);
    04326             XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04327             xp += width;
    04328          }
    04329          if (TSubsc[j][0])
    04330          {
    04331             XSetFont(display, gc, SubFont->fid);
    04332             strcpy(Text,TSubsc[j]);
    04333             len    = strlen(Text);
    04334             width  = XTextWidth(SubFont,Text,len);
    04335             XSetForeground(display,gc,TSColor[j]);
    04336             XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04337             xp += width;
    04338             XSetFont(display, gc, FixFont->fid);
    04339          }
    04340          xp += FixFontWidth;
    04341       }
    04342    }
    04343
    04344    if (SizeChanged && PicType == ISOTAB) /* Table Caption */
    04345    {
    04346       XSetForeground(display,gc,BlackPix);
    04347       XFillRectangle(display,pix,gc,0,0,WinXSize,WinYSize);
    04348       XSetBackground(display,gc,BlackPix);
    04349    }
    04350
    04351    if (PicType == ISOTS)
    04352    {
    04353       if (TSxp[w] == NULL) TSxp[w] = SizeAlloc(DimX * DimY , sizeof(XPoint),"TSxp");
    04354       if (Dmin[w] == NULL) Dmin[w] = FloatAlloc(DimY ,"Dmin");
    04355       if (Dmax[w] == NULL) Dmax[w] = FloatAlloc(DimY ,"Dmax");
    04356       XSetForeground(display,gc,BlackPix);
    04357       XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04358
    04359       for (j=0 ; j < DimY ; ++j) Dmin[w][j] = Dmax[w][j] = field[j];
    04360       if (nstep > 2)
    04361       {
    04362          for (j=0 ; j < DimY ; ++j)
    04363          {
    04364             for (i=1 ; i < DimX ; ++i)
    04365             {
    04366                Dmin[w][j] = MIN(Dmin[w][j],Field[i+j*DimX]);
    04367                Dmax[w][j] = MAX(Dmax[w][j],Field[i+j*DimX]);
    04368             }
    04369          }
    04370       }
    04371
    04372       if (nstep > 2)
    04373       for (j=0 ; j < DimY ; ++j)
    04374       {
    04375          XSetForeground(display,gc,TSColor[j]);
    04376          o = Dmin[w][j];
    04377          if ((Dmax[w][j] - Dmin[w][j]) > 1.0e-20) f = (InYSize-2) / (Dmax[w][j] - Dmin[w][j]);
    04378          else f = 1.0;
    04379
    04380          for (i=1 ; i < DimX ; ++i)
    04381          {
    04382             TSxp[w][i].x = VGAX * i;
    04383             TSxp[w][i].y = InYSize - 1 - f * (Field[i+j*DimX] - o);
    04384          }
    04385          XDrawLines(display,pix,gc,TSxp[w]+1,DimX-1,CoordModeOrigin);
    04386       }
    04387    }
    04388
    04389    if (PicType == ISOTAB)
    04390    {
    04391       XSetForeground(display,gc,BlackPix);
    04392       XSetBackground(display,gc,BlackPix);
    04393       XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04394       XSetFont(display, gc, BigFont->fid);
    04395       yp = BigFontHeight;
    04396       for (j=0 ; j < DimX ; ++j)
    04397       if (TSName[j][0])
    04398       {
    04399          XSetForeground(display,gc,TSColor[j]);
    04400          xp = BigFontWidth;
    04401          strcpy(Text,TSName[j]);
    04402          len = strlen(Text);
    04403          XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04404          xp += XTextWidth(BigFont,Text,len);
    04405          if (TSubsc[j][0])
    04406          {
    04407             XSetFont(display, gc, FixFont->fid);
    04408             XDrawImageString(display,pix,gc,xp,yp,TSubsc[j],strlen(TSubsc[j]));
    04409             XSetFont(display, gc, BigFont->fid);
    04410          }
    04411          xp = 8 * BigFontWidth;
    04412          if (TSUnit[j][0])
    04413          {
    04414             sprintf(Text,"= %7.3f [%s]",field[j],TSUnit[j]);
    04415             if (TScale[j][0]) strcat(Text," 10");
    04416             len = strlen(Text);
    04417             XDrawImageString(display,pix,gc,xp,yp,Text,len);
    04418             if (TScale[j][0] > ' ')
    04419             {
    04420                lens = strlen(TScale[j]);
    04421                XSetFont(display, gc, FixFont->fid);
    04422                XDrawImageString(display,pix,gc,xp+len*BigFontWidth,yp-BigFontHeight+FixFontHeight,TScale[j],lens);
    04423                XSetFont(display, gc, BigFont->fid);
    04424             }
    04425          }
    04426          yp += BigFontHeight;
    04427       }
    04428       XSetFont(display, gc, FixFont->fid);
    04429    }
    04430
    04431    if (PicType == ISOTRA)
    04432    {
    04433       XSetForeground(display,gc,BlackPix);
    04434       XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04435       if (SizeChanged) ClearTracer();
    04436       TracerPlot(w);
    04437    }
    04438    if (PicType == MAPTRA)
    04439    {
    04440       if (SizeChanged) ClearTracer();
    04441       if (MapHR.X)
    04442       {
    04443          if (MapPro[w] == AZIMUTHAL)
    04444          {
    04445             if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize ||
    04446                (nstep % rmui == 0 && MapLR[w].f != 0))
    04447             {
    04448                RedrawFlag[w] = 0;
    04449                MapLR[w].w    = WinXSize;
    04450                MapLR[w].h    = InYSize;
    04451                MapLR[w].l   += MapLR[w].r;
    04452                if (MapLR[w].l < -180.0) MapLR[w].l += 360.0;
    04453                if (MapLR[w].l >  180.0) MapLR[w].l -= 360.0;
    04454                AzimuthalImage(&MapHR,&MapLR[w]);
    04455             }
    04456          }
    04457          else
    04458          {
    04459             if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize)
    04460             {
    04461                RedrawFlag[w] = 0;
    04462                MapLR[w].w  = WinXSize;
    04463                MapLR[w].h  = InYSize;
    04464                if (MapPro[w] == 1) PolarImage(&MapHR,&MapLR[w]);
    04465                else                ScaleImage(&MapHR,&MapLR[w]);
    04466             }
    04467          }
    04468          XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h);
    04469       }
    04470       else
    04471       {
    04472          XSetForeground(display,gc,BlackPix);
    04473          XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04474       }
    04475       TracerPlot(w);
    04476    }
    04477    if (PicType == ISOCS || PicType == ISOHOR || PicType == ISOLON || PicType == ISOCOL)
    04478    {
    04479       XSetForeground(display,gc,BlackPix);
    04480       XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04481       IsoAreas(Cstrip);
    04482       IsoLines(Cstrip,0);
    04483    }
    04484    if (PicType == MAPHOR)
    04485    {
    04486       if (MapHR.X)
    04487       {
    04488          if (MapPro[w] == AZIMUTHAL)
    04489          {
    04490             if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize ||
    04491                (nstep % rmui == 0 && MapLR[w].f != 0))
    04492             {
    04493                RedrawFlag[w] = 0;
    04494                MapLR[w].w    = WinXSize;
    04495                MapLR[w].h    = InYSize;
    04496                MapLR[w].l   += MapLR[w].r;
    04497                if (MapLR[w].l < -180.0) MapLR[w].l += 360.0;
    04498                if (MapLR[w].l >  180.0) MapLR[w].l -= 360.0;
    04499                AzimuthalImage(&MapHR,&MapLR[w]);
    04500             }
    04501             XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h);
    04502             MapLines(Cstrip,1);
    04503          }
    04504          else
    04505          {
    04506             if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize)
    04507             {
    04508                RedrawFlag[w] = 0;
    04509                MapLR[w].w  = WinXSize;
    04510                MapLR[w].h  = InYSize;
    04511                if (MapPro[w] == 1) PolarImage(&MapHR,&MapLR[w]);
    04512                else                ScaleImage(&MapHR,&MapLR[w]);
    04513             }
    04514             XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h);
    04515             IsoLines(Cstrip,1);
    04516          }
    04517       }
    04518       else
    04519       {
    04520          XSetForeground(display,gc,BlackPix);
    04521          XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize);
    04522          IsoLines(Cstrip,1);
    04523       }
    04524    }
    04525    if (PicType == ISOHOV)
    04526    {
    04527       IsoAreas(Cstrip);
    04528    }
    04529
    04530    if (PicType == ISOSH)
    04531    {
    04532       AmplitudePlot();
    04533    }
    04534
    04535    if (Grid && PicType == ISOCS) ShowGridCS();
    04536    if (Grid && PicType == ISOLON) ShowGridLonsi();
    04537    if (Grid && PicType == ISOHOV && MapPro[w] == 0) ShowGridHov();
    04538    if (Grid && PicType == ISOHOV && MapPro[w] == 1) ShowGridHovT();
    04539    if (PicType == ISOHOR &&  MapPro[w] == 1) ShowGridPolar();
    04540    if (Grid && PicType == ISOHOR && MapPro[w] == 0) ShowGridCyl();
    04541    if (Grid && PicType == ISOCOL) ShowGridCol();
    04542
    04543    XCopyArea(display,pix,Win[w],gc,0,0,WinXSize,WinYSize,0,0);
    04544 }
    04545
    04546
    04547 /* ==================================================================== */
    04548 /* iguistep - this function is called from the model for every timestep */
    04549 /* ==================================================================== */
    04550
    04551 int iguistep_(float pparcs[],int kdatim[])
    04552 {
    04553    int i,j,w;               // Loop indices
    04554    struct timeval TimeVal;  // Retrieve time info
    04555
    04556    if (Debug) printf("iguistep(%12.2e,%d-%d-%d)\n",
    04557                      pparcs[0],kdatim[0],kdatim[1],kdatim[2]);
    04558    nstep++;
    04559    memcpy(ndatim,kdatim,sizeof(ndatim));
    04560    DeltaTime = ndatim[4] - LastMinute;
    04561    if (DeltaTime < 0) DeltaTime += 60;
    04562    if (DeltaTime ==0) DeltaTime  = 60;
    04563    LastMinute = ndatim[4];
    04564
    04565    // Compute frames per second every 20 calls
    04566
    04567    gettimeofday(&TimeVal,NULL);
    04568    LastSecond = ThisSecond;
    04569    ThisSecond = TimeVal.tv_sec;
    04570
    04571    if (SecEvent = ThisSecond > LastSecond)
    04572    {
    04573       fps      = nstep - LastStep;
    04574       LastStep = nstep;
    04575       rmui     = fps / rmuf;
    04576       if (rmui < 1) rmui = 1;
    04577    }
    04578
    04579    SkipFreq = 1 + fps / 30; // Reduce plot rate on fast cpu's
    04580    if (SkipFreq < 0 || SkipFreq > 10) SkipFreq = 0;
    04581
    04582    for (w=0 ; w < NumWin ; ++w)
    04583    {
    04584       for (j=0 ; j < NumArrays ; ++j)
    04585       {
    04586          if (!strcmp(WinAtt[w].array_name,Array[j].Name))
    04587          {
    04588             if (Array[j].Flag || RedrawFlag[w])
    04589             iso(w,WinAtt[w].Plot,Array[j].Data,Array[j].DimX,Array[j].DimY,
    04590                                  Array[j].DimZ,WinAtt[w].Palette);
    04591          }
    04592       }
    04593    }
    04594
    04595    for (i=0 ; i < Parcs ; ++i) Parc[i].Val = pparcs[i];
    04596    ShowStep();
    04597    ShowParcs();
    04598    HandleEvents();
    04599    if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent))
    04600       RedrawControlWindow();
    04601    for (i=0 ; i < Parcs ; ++i) pparcs[i] = Parc[i].Val;
    04602
    04603    XSync(display,1);
    04604    if (Shutdown && MRpid < 1) SaveConfig();
    04605    if (Debug) printf("iguistep returns %d\n",Shutdown);
    04606    return Shutdown;
    04607 }
    04608
    04609 int nresources_(double *ut, double *st, long *mem, long *par, long *paf,
    04610                long *swa, long *dr, long *dw)
    04611 {
    04612    struct rusage ru;
    04613    getrusage(RUSAGE_SELF,&ru);
    04614    *ut = ru.ru_utime.tv_sec + 0.000001 * ru.ru_utime.tv_usec;
    04615    *st = ru.ru_stime.tv_sec + 0.000001 * ru.ru_stime.tv_usec;
    04616    *mem = ru.ru_maxrss;
    04617    *par = ru.ru_minflt;
    04618    *paf = ru.ru_majflt;
    04619    *swa = ru.ru_nswap;
    04620    *dr  = ru.ru_inblock;
    04621    *dw  = ru.ru_oublock;
    04622    return 1;
    04623 }
    04624
    04625 /* ------------------------------------------------ */
    04626 /* Stub routines for Absoft Compiler and others,    */
    04627 /* which require, that FORTRAN callable C-functions */
    04628 /* are written in uppercase letters only            */
    04629 /* ------------------------------------------------ */
    04630
    04631
    04632 void INITGUI(int *model, int *debug, int *lats, int *mrpid, int *mrnum)
    04633 {
    04634    initgui_(model,debug,lats,mrpid,mrnum);
    04635 }
    04636
    04637 void GUICLOSE(void)
    04638 {
    04639    guiclose_();
    04640 }
    04641
    04642 int IGUISTEP(float pparcs[], int kdatim[])
    04643 {
    04644    return iguistep_(pparcs,kdatim);
    04645 }
    04646
    04647 void GUIPUT(char *aname, float *array, int *dimx, int *dimy, int *dimz)
    04648 {
    04649    guiput_(aname, array, dimx, dimy, dimz);
    04650 }
    04651
    04652 int NRESOURCES(double *ut, double *st, long *mem, long *par, long *paf,
    04653                long *swa, long *dr, long *dw)
    04654 {
    04655    return nresources_(ut,st,mem,par,paf,swa,dr,dw);
    04656 }
    04657
    04658 /* ------------------------------------------------ */
    04659 /* Stub routines for IBM Compiler and others,       */
    04660 /* which require, that FORTRAN callable C-functions */
    04661 /* are written in lowercase without underscore      */
    04662 /* ------------------------------------------------ */
    04663
    04664
    04665 void initgui(int *model, int *debug, int *lats, int *mrpid, int *mrnum)
    04666 {
    04667    initgui_(model,debug,lats,mrpid,mrnum);
    04668 }
    04669
    04670 void guiclose(void)
    04671 {
    04672    guiclose_();
    04673 }
    04674
    04675 int iguistep(float pparcs[], int kdatim[])
    04676 {
    04677    return iguistep_(pparcs,kdatim);
    04678 }
    04679
    04680 void guiput(char *aname, float *array, int *dimx, int *dimy, int *dimz)
    04681 {
    04682    guiput_(aname, array, dimx, dimy, dimz);
    04683 }
    04684
    04685 int iguinan_(double *p)
    04686 {
    04687    return isnan(*p);
    04688 }
    04689
    04690 int nresources(double *ut, double *st, long *mem, long *par, long *paf,
    04691               long *swa, long *dr, long *dw)
    04692 {
    04693    return nresources_(ut,st,mem,par,paf,swa,dr,dw);
    04694 }