/* * @(#) xrungekt.c - Differential equation solver (XWindow version). * (c) 1996 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: C * Tested with: BSD GNU CC * Last modified: 1996-05-25 20:40:00 GMT+04:00 */ #define X11R3 /* for XWindow v11 r3 */ #include #include #include #include #include #include #include /* windows geometry & title */ #define WND_WDT 600 #define WND_HGH 400 #define WND_MIN_WDT 480 #define WND_MIN_HGH 360 #define WND_BORDER 5 #define WND_FONT "fixed" #define WND_TITLE "Runge-Kutta diff. equation solver" #define WND_ICON_TITLE "XRungeKutta" /* button size & offset */ #define BUTTON_START 10 /* x-coord of all buttons */ #define BUTTON_SHIFT 160 /* in % of button height */ #define BUTTON_HGH 180 /* in % of text height */ #define BUTTON_SHADOW 25 /* in % of button height */ /* window board default size */ #define BRD_WDT 70 /* in % of window width */ #define BRD_GR_HGH 95 /* in % of window board */ #define BRD_AXIS_L 10 #define BRD_AXIS_W 7 /* text table size & format */ #define TBL_MAX 20 /* max amount of table lines */ #define TBL_HEADER ".....-N-.....-X-.........-Y-.......-Yreal-." #define TBL_FORMAT " %7ld %11.6f %11.6f %11.6f " #define TEXT_INTRLV 10 /* in %, text string interleaving */ /* hot keys definition */ #define XK_Return 90 #define XK_Escape 8 #define XK_Space 41 #define XK_Tab 13 #define XK_Up 99 #define XK_Down 96 #define BELLACTIVITY 3 #define M_PI (3.1415926535) /* diff. equation parameters */ #define X0 (-1.0) #define Y0 (exp(-1.0/2.0)) #define B (3.0) #define PHI(x) (0.0) #define PSI(x) (0.0) #define G(x) (x) #define YFUNC(x) (exp(-(x)*(x)/2.0)) #define F(x,y) (PHI(x)*PSI(x)-G(x)*(y)) #define EPS (1e-3) #define PLEVEL 3 /* method precise level */ /* program state type */ typedef struct { int quit; int activebutton,pressedbutton; int table,graphic,approx; int efunc,afunc,ffunc; } TProgState; /* buttons names */ static char *PButtonNames[]= { "~Table","~Draw","E~rror","", "~Exact","~Auto","~Fixed","", "~Clear","E~xit",0 }; /* help text on usage */ static char *PHelpOnUsage[]= { "Usage:", " xrungekt [-h] [-text] | []\n", "Options:\n", " -h(help) - Display help information", " -text - Text mode", "XWindow options:", " -rv(reverse) - Reverse window context", " -title - Define window title", " -n(name) - Define icon name", " -fn(font) - Use specified font", " -g(geometry) [*][++] - Set window \"geometry\"", " -d(display) :[.] - Use specified display", 0 }; /* help text on equation and method */ static char *PHelpOnMethod[]= { "Method description:", " Runge-Kutta, precise level 3", /* PLEVEL */ "Equation description:", " y'=phi(x)*psi(x)-g(x)*y, ", " where phi(x)=0, psi(x)=0, g(x)=x ", " x0=-1, y0=exp(-1/2), b(xn)=3", /* X0,Y0,B */ " Eps=0.001", /* EPS */ " Result function: y(x)=exp(-x*x/2)", 0 }; /* euler method (precise level 1) */ /* double Euler(double x,double y,double h) { return (F(x,y)*h+y); } */ /* Runge-Kutta method (precise level 3) */ double RungeKutta(double x,double y,double h) { double p=F(x,y)*h/3.0; return ((F(h*2.0/3.0+x,F(h/3.0+x,p+y)*h*2.0/3.0+y)*h+p)*3.0/4.0+y); } /* Runge-Kutta method with automatically selected step */ double RungeKuttaAuto(double x,double y,double *h) { double y1=RungeKutta(x,y,*h); double y2=RungeKutta(x,y,*h/2.0); double dy=fabs(y1-y2)/(1<=EPS) do { *h/=2.0; y1=y2; y2=RungeKutta(x,y,*h/2.0); } while (fabs(y1-y2)>=EPS*(1<*maxy) *maxy=fabs(y); if ((dy=fabs(y-YFUNC(x)))>*maxdy) *maxdy=dy; } } /* prints result (text) table with fixed step length */ void PrintResTable(double h,long step,int afunc) { double x,y; long i; printf(TBL_HEADER "\n"); printf(TBL_FORMAT "\n",0,X0,Y0,YFUNC(X0)); for (x=X0,y=Y0,i=1;xTBL_MAX) ? n/TBL_MAX : 1; printf("\nResult table with fixed-step solution.\n"); PrintResTable((B-X0)/n,step,0); printf("\nResult table with auto-step solution.\n"); PrintResTable((B-X0)/4.0,step,1); } /* finds the string in the table, returns number of string or 0 */ int FindStrInTable(char *table[],char *str) { int n=0; while (table[n]) { if (!strcmp(table[n],str)) return n+1; n++; } return 0; } /* changes one symbol to another in the string */ void ChangeSymbols(char *s,char c,char cn) { while ((s=strchr(s,c))) *(s++)=cn; } /* returns length of the longest string in the table */ int GetMaxLen(char *table[]) { int len,max=0; while (*table) if ((len=strlen(*(table++)))>max) max=len; return (max); } /* searches specified symbol after tile in the table, returns table row number or -1 in case of failure */ int SearchTileSymbol(char *table[],int start,char symbol) { int n=start; char ch,*pc; if (isupper(symbol)) symbol=tolower(symbol); do { if (!(pc=strchr(table[n],'~'))) pc=table[n]; else pc++; ch=isupper(*pc)? tolower(*pc) : *pc; if (ch==symbol) return (n); n++; if (!table[n]) n=0; } while (start!=n); return (-1); } /* creates str without tile symbol and returns tile pos */ char *GetUntiledStr(char *str,int *pos) { char *p,*s; if (!(s=(char *)malloc(strlen(str)+1))) { fprintf(stderr,"No memory!\n"); exit(1); } *pos=0; strcpy(s,str); if ((p=strchr(s,'~'))) strcpy(p,str+(*pos=p-s)+1); return (s); } /* prints help information */ int PrintPoster(char *argv[]) { int i; int NeedHelp=FindStrInTable(argv,"-help") || FindStrInTable(argv,"-h"); printf("XRunge-Kutta diff. solver for XWindow\n" " Run with option -h for help.\n\n"); if (NeedHelp) for (i=0;PHelpOnUsage[i];i++) printf(" %s\n",PHelpOnUsage[i]); printf("\n"); for (i=0;PHelpOnMethod[i];i++) printf(" %s\n",PHelpOnMethod[i]); printf("\n"); return (NeedHelp); } /* opens XWindow display */ Display *ConnectToXServer(char *argv[]) { Display *prDisplay; /* Option -display :[.] */ int Opt=FindStrInTable(argv,"-display"); if (!Opt) Opt=FindStrInTable(argv,"-d"); if (!(prDisplay=XOpenDisplay(Opt ? argv[Opt] : 0))) { fprintf(stderr,"Cannot connect to the X server!\n"); exit(1); } return (prDisplay); } /* loads default or specified in the CMD line font */ XFontStruct *LoadDefaultFont(Display *prDisplay,char *argv[]) { XFontStruct *prFont; char *font; int Opt=FindStrInTable(argv,"-font"); /* option -font */ if (!Opt) Opt=FindStrInTable(argv,"-fn"); if (Opt) { if (!(font=(char *)malloc(strlen(argv[Opt])+3))) { fprintf(stderr,"No memory!\n"); exit(1); } font[0]='\0'; strcat(strcat(strcat(font,"*"),argv[Opt]),"*"); prFont=XLoadQueryFont(prDisplay,font); free((void *)font); } else prFont=XLoadQueryFont(prDisplay,WND_FONT); if (!prFont) { fprintf(stderr,"Font not found!\n"); exit(1); } return (prFont); } /* window properties set procedure */ static void SetWindowManagerHints(Display *prDisplay,char *psPrgClass, char *argv[],int argc,Window nWnd, int x,int y,int nWidth,int nHeight, int nMinWidth,int nMinHeight, char *psTitle,char *psIconTitle, Pixmap nIconPixmap) { XSizeHints rSizeHints; #ifdef X11R3 /* XWindow Version X11R3 or lower */ rSizeHints.flags=PPosition | PSize | PMinSize; rSizeHints.x=x; rSizeHints.y=y; rSizeHints.width=nWidth; rSizeHints.height=nHeight; rSizeHints.min_width=nMinWidth; rSizeHints.min_height=nMinHeight; XSetStandardProperties(prDisplay,nWnd,psTitle,psIconTitle,nIconPixmap, argv,argc,&rSizeHints); #else /* XWindow Version X11R4 or higher */ XWMHints rWMHints; XClassHint rClassHint; XTextProperty prWindowName,prIconName; if (!XStringListToTextProperty(&psTitle,1,&prWindowName) || !XStringListToTextProperty(&psIconTitle,1,&prIconName)) { fprintf(stderr,"No memory!\n"); exit(1); } rSizeHints.flags=PPosition | PSize | PMinSize; rSizeHints.min_width=nMinWidth; rSizeHints.min_height=nMinHeight; rWMHints.flags=StateHint | IconPixmapHint | InputHint; rWMHints.initial_state=NormalState; rWMHints.input=True; rWMHints.icon_pixmap=nIconPixmap; rWMHints.res_name=argv[0]; rWMHints.res_class=psPrgClass; XSetWMProperties(prDisplay,nWnd,&prWindowName,&prIconName, argv,argc,&rSizeHints,&rWMHints,&rClassHint); #endif } /* opens new window */ Window OpenNewWindow(Display *prDisplay,char *Title,char *IconTitle, int x,int y,int w,int h,int b,int min_w,int min_h, int argc,char *argv[],int RvContext) { int nScr=DefaultScreen(prDisplay); Window nWnd=XCreateSimpleWindow( prDisplay,RootWindow(prDisplay,nScr),x,y,w,h,b, RvContext ? WhitePixel(prDisplay,nScr) : BlackPixel(prDisplay,nScr), RvContext ? BlackPixel(prDisplay,nScr) : WhitePixel(prDisplay,nScr)); SetWindowManagerHints(prDisplay,IconTitle,argv,argc,nWnd, x,y,w,h,min_w,min_h,Title,IconTitle,0); XMapWindow(prDisplay,nWnd); return (nWnd); } /* gets window geometry from CMD line */ void GetWindowCMDGeometry(char *argv[], int *x,int *y,int *width,int *height) { char *ptr,*p; int geometry; /* option -geometry [*][++] */ if (!(geometry=FindStrInTable(argv,"-geometry"))) geometry=FindStrInTable(argv,"-g"); if (geometry && (ptr=argv[geometry])) { if (*ptr!='+') { *width=atoi(ptr); if ((p=strchr(ptr,'*'))) *height=atoi(ptr=p+1); } if ((ptr=strchr(ptr,'+'))) { *x=atoi(++ptr); if ((ptr=strchr(ptr,'+'))) *y=atoi(++ptr); } } } /* opens window using parameter specified in the CMD line or default */ Window OpenDefaultWindow(Display *prDisplay, int argc,char *argv[],int *RvContext) { int x=0,y=0,width=0,height=0; int name=FindStrInTable(argv,"-name"); /* option -name */ int title=FindStrInTable(argv,"-title"); /* option -title */ if (!name) name=FindStrInTable(argv,"-n"); if (title) ChangeSymbols(argv[title],'_',' '); *RvContext=FindStrInTable(argv,"-reverse") || FindStrInTable(argv,"-rv"); GetWindowCMDGeometry(argv,&x,&y,&width,&height); if (!width) width=WND_WDT; else if (widthfid); for (i=0;PHelpOnMethod[i];i++) XDrawString(prDisplay,nWnd,prGC, BUTTON_START,y+=prFont->ascent+prFont->descent, PHelpOnMethod[i],strlen(PHelpOnMethod[i])); XFreeGC(prDisplay,prGC); } /* draws push button */ void DrawPushButton(Display *prDisplay,Window nWnd, char *Name,int enabled,int x,int y, int width,int height,int shadow,int sframe, XFontStruct *prFont,int RvGCFlag) { int tilepos; char *RealName=GetUntiledStr(Name,&tilepos); int slen=strlen(RealName); int textx,texty,textwidth,textheight; GC prGC=CreateGrContext(prDisplay,nWnd,RvGCFlag); XSetLineAttributes(prDisplay,prGC,1,LineSolid,CapRound,JoinRound); XDrawRectangle(prDisplay,nWnd,prGC,x,y,width,height); XFillRectangle(prDisplay,nWnd,prGC,x+shadow,y+height,width+1,shadow+1); XFillRectangle(prDisplay,nWnd,prGC,x+width,y+shadow,shadow+1,height+1); textwidth=XTextWidth(prFont,RealName,slen); textheight=prFont->descent+prFont->ascent; textx=x+(width-textwidth)/2; texty=y+textheight; XSetFont(prDisplay,prGC,prFont->fid); XDrawString(prDisplay,nWnd,prGC,textx,texty,RealName,slen); tilepos=textx+tilepos*textwidth/slen; XDrawLine(prDisplay,nWnd,prGC, tilepos,texty+3,tilepos+textwidth/slen-2,texty+3); if (!enabled) { XDrawLine(prDisplay,nWnd,prGC,x,y,x+width-1,y+height-1); XDrawLine(prDisplay,nWnd,prGC,x,y+height-1,x+width-1,y); } if (sframe) { XSetLineAttributes(prDisplay,prGC,1,LineOnOffDash,CapRound,JoinRound); XDrawRectangle(prDisplay,nWnd,prGC, textx-sframe,texty-textheight-sframe+4, textwidth+sframe*2,textheight+sframe*2); } free((void *)RealName); XFreeGC(prDisplay,prGC); } /* gets size and coordinates of window board */ Region GetBoardSize(Display *prDisplay,Window nWnd, int *x,int *y,int *width,int *height) { XPoint prPoint[4]; XWindowAttributes rWinAttr; XGetWindowAttributes(prDisplay,nWnd,&rWinAttr); *width=(rWinAttr.width-5)*BRD_WDT/100; *x=rWinAttr.width-5-*width; *height=rWinAttr.height-5; *y=2; prPoint[0].x=prPoint[3].x=*x-1; prPoint[0].y=prPoint[1].y=*y-1; prPoint[1].x=prPoint[2].x=*x+*width+2; prPoint[2].y=prPoint[3].y=*y+*height+2; return (XPolygonRegion(prPoint,sizeof(prPoint)/sizeof(XPoint), WindingRule)); } /* draws result table */ void DrawTable(Display *prDisplay,Window nWnd,int afunc, XFontStruct *prFont,int RvGCFlag,long Cnt) { long i,step; double h; double x,y; int xpos,ypos; int height,width; char OutStr[256]; GC prGC=CreateGrContext(prDisplay,nWnd,RvGCFlag); Region nRegion=GetBoardSize(prDisplay,nWnd, &xpos,&ypos,&width,&height); XSetRegion(prDisplay,prGC,nRegion); XClearArea(prDisplay,nWnd,xpos,ypos,width,height,False); XSetFont(prDisplay,prGC,prFont->fid); step=height; width=prFont->ascent; height=prFont->descent; xpos+=height*TEXT_INTRLV/100; width+=height*TEXT_INTRLV/100; ypos+=width; height+=width; XDrawString(prDisplay,nWnd,prGC, xpos,ypos,TBL_HEADER,strlen(TBL_HEADER)); step=step/height-2; step=(Cnt>step) ? Cnt/step : 1; h=(B-X0)/((afunc) ? 4.0 : Cnt); for (x=X0,y=Y0,i=0;xascent+prFont->descent)*BUTTON_HGH/100; x=BUTTON_START; y+=button*height*BUTTON_SHIFT/100; XClearArea(prDisplay,nWnd, x,y,width+BUTTON_SHADOW,height+BUTTON_SHADOW,False); DrawPushButton(prDisplay,nWnd,PButtonNames[button],enabled, x,y,width,height, !pressed*height*BUTTON_SHADOW/100, selected*2,prFont,RvGCFlag); return (1); } /* returns 1 if mouse is on the specified button */ int CheckSpecifiedButton(Display *prDisplay,Window nWnd, int button,int mousex,int mousey, XFontStruct *prFont) { int x,y,width,height; XDestroyRegion(GetBoardSize(prDisplay,nWnd,&width,&y,&x,&x)); width-=2*BUTTON_START; height=(prFont->ascent+prFont->descent)*BUTTON_HGH/100; y+=button*height*BUTTON_SHIFT/100; return (mousex>=BUTTON_START && mousey>=y && mousextable); case 1: /* Draw */ return (!prState->graphic); case 2: /* Error */ return (!prState->approx); case 4: /* Exact */ return (prState->graphic && !prState->efunc); case 5: /* Auto */ return ((prState->table || prState->graphic || prState->approx) && !prState->afunc); case 6: /* Fixed */ return ((prState->table || prState->graphic || prState->approx) && !prState->ffunc); default: return (1); } } /* draws all buttons in the DLG */ void DrawButtonDlg(Display *prDisplay,Window nWnd,TProgState *prState, XFontStruct *prFont,int RvGCFlag) { int n=0; while (DrawSpecifiedButton(prDisplay,nWnd,n, prState->pressedbutton==n,prState->activebutton==n, ButtonEnabled(prState,n),prFont,RvGCFlag)) n++; } /* draws all parts of window */ void DrawWindow(Display *prDisplay,Window nWnd,TProgState *prState, XFontStruct *prFont,int RvGCFlag, long Cnt,double MaxY,double MaxDY) { DrawBoard(prDisplay,nWnd,RvGCFlag); DrawButtonDlg(prDisplay,nWnd,prState,prFont,RvGCFlag); if (prState->table) { if (prState->afunc) DrawTable(prDisplay,nWnd,1,prFont,RvGCFlag,Cnt); if (prState->ffunc) DrawTable(prDisplay,nWnd,0,prFont,RvGCFlag,Cnt); } if (prState->graphic) { if (prState->efunc) DrawGraphic(prDisplay,nWnd,0,0,1,RvGCFlag,Cnt,MaxY); if (prState->afunc) DrawGraphic(prDisplay,nWnd,1,0,0,RvGCFlag,Cnt,MaxY); if (prState->ffunc) DrawGraphic(prDisplay,nWnd,0,1,0,RvGCFlag,Cnt,MaxY); } if (prState->approx) { if (prState->afunc) DrawGraphic(prDisplay,nWnd,1,0,1,RvGCFlag,Cnt,MaxDY); if (prState->ffunc) DrawGraphic(prDisplay,nWnd,0,1,1,RvGCFlag,Cnt,MaxDY); } } /* reaction on button press and release */ void ProcessButtonEvent(Display *prDisplay,Window nWnd, TProgState *prState,int button, XFontStruct *prFont,int RvGCFlag, long Cnt,double MaxY,double MaxDY) { switch (button) { case 0: /* Table */ prState->table=1; prState->graphic=0; prState->approx=0; if (prState->afunc) DrawTable(prDisplay,nWnd,1,prFont,RvGCFlag,Cnt); else if (prState->ffunc) DrawTable(prDisplay,nWnd,0,prFont,RvGCFlag,Cnt); break; case 1: /* Draw */ prState->table=0; prState->graphic=1; if (prState->efunc) DrawGraphic(prDisplay,nWnd,0,0,1,RvGCFlag,Cnt,MaxY); if (prState->afunc) DrawGraphic(prDisplay,nWnd,1,0,0,RvGCFlag,Cnt,MaxY); if (prState->ffunc) DrawGraphic(prDisplay,nWnd,0,1,0,RvGCFlag,Cnt,MaxY); break; case 2: /* Error */ prState->table=0; prState->approx=1; if (prState->afunc) DrawGraphic(prDisplay,nWnd,1,0,1,RvGCFlag,Cnt,MaxDY); if (prState->ffunc) DrawGraphic(prDisplay,nWnd,0,1,1,RvGCFlag,Cnt,MaxDY); break; case 4: /* Exact */ prState->efunc=1; if (prState->graphic) DrawGraphic(prDisplay,nWnd,0,0,1,RvGCFlag,Cnt,MaxY); break; case 5: /* Auto */ prState->afunc=1; if (prState->table) prState->ffunc=0; if (prState->table) DrawTable(prDisplay,nWnd,1,prFont,RvGCFlag,Cnt); if (prState->graphic) DrawGraphic(prDisplay,nWnd,1,0,0,RvGCFlag,Cnt,MaxY); if (prState->approx) DrawGraphic(prDisplay,nWnd,1,0,1,RvGCFlag,Cnt,MaxDY); break; case 6: /* Fixed */ prState->ffunc=1; if (prState->table) prState->afunc=0; if (prState->table) DrawTable(prDisplay,nWnd,0,prFont,RvGCFlag,Cnt); if (prState->graphic) DrawGraphic(prDisplay,nWnd,0,1,0,RvGCFlag,Cnt,MaxY); if (prState->approx) DrawGraphic(prDisplay,nWnd,0,1,1,RvGCFlag,Cnt,MaxDY); break; case 8: /* Clear */ prState->table=prState->graphic=prState->approx=0; prState->efunc=prState->afunc=prState->ffunc=0; DrawBoard(prDisplay,nWnd,RvGCFlag); break; case 9: /* Exit */ prState->quit=1; } } /* mouse left button events handler */ int MouseEventHandler(Display *prDisplay,Window nWnd, int mousex,int mousey,XFontStruct *prFont) { int button; for (button=0;PButtonNames[button];button++) if (*PButtonNames[button] && CheckSpecifiedButton(prDisplay,nWnd,button,mousex,mousey,prFont)) return (button); return (-1); } /* keyboard events handler */ int KeyboardEventHandler(XKeyEvent *prKeyEvent,int activebutton) { char skey[2]="\0\0"; XLookupString(prKeyEvent,&skey[0],sizeof(skey),0,0); if (!skey[1]) return (SearchTileSymbol(PButtonNames,activebutton,skey[0])); return (-1); } /* active button selector */ int SelectActiveButton(int keycode,int *button,int pressed) { if (pressed) if (keycode==XK_Tab || keycode==XK_Down) { (*button)++; if (!PButtonNames[*button]) *button=0; while (!*PButtonNames[*button]) (*button)++; return (-2); } else if (keycode==XK_Up) { (*button)--; if (*button<0) while (PButtonNames[*button+1]) (*button)++; while (!*PButtonNames[*button]) (*button)--; return (-2); } if (keycode==XK_Escape) return (SearchTileSymbol(PButtonNames,*button,'x')); /* Exit */ else if (keycode==XK_Space || keycode==XK_Return) return (*button); return (-1); } /* button press-release event handler */ void ButtonEvent(Display *prDisplay,Window nWnd,int Button,int Pressed, TProgState *prState,XFontStruct *prFont,int RvGCFlag, long Cnt,double MaxY,double MaxDY) { if (Button>=0 && *PButtonNames[Button]) if (Pressed) if (ButtonEnabled(prState,Button)) prState->activebutton=prState->pressedbutton=Button; else XBell(prDisplay,BELLACTIVITY); else if (prState->pressedbutton==Button) ProcessButtonEvent(prDisplay,nWnd,prState,Button, prFont,RvGCFlag,Cnt,MaxY,MaxDY); } /* program all-event handler */ void EventHandler(Display *prDisplay,Window nWnd, XEvent *prEvent,TProgState *prState, XFontStruct *prFont,int RvGCFlag, long Cnt,double MaxY,double MaxDY) { switch (prEvent->type) { case KeyPress: case KeyRelease: ButtonEvent(prDisplay,nWnd,SelectActiveButton(prEvent->xkey.keycode, &prState->activebutton,prEvent->type==KeyPress), prEvent->type==KeyPress, prState,prFont,RvGCFlag,Cnt,MaxY,MaxDY); ButtonEvent(prDisplay,nWnd,KeyboardEventHandler(&prEvent->xkey, prState->activebutton),prEvent->type==KeyPress, prState,prFont,RvGCFlag,Cnt,MaxY,MaxDY); if (prEvent->type==KeyRelease) prState->pressedbutton=-1; DrawButtonDlg(prDisplay,nWnd,prState,prFont,RvGCFlag); break; case ButtonPress: case ButtonRelease: if (prEvent->xbutton.button==Button1) ButtonEvent(prDisplay,nWnd,MouseEventHandler(prDisplay,nWnd, prEvent->xbutton.x,prEvent->xbutton.y,prFont), prEvent->type==ButtonPress, prState,prFont,RvGCFlag,Cnt,MaxY,MaxDY); if (prEvent->type==ButtonRelease) prState->pressedbutton=-1; DrawButtonDlg(prDisplay,nWnd,prState,prFont,RvGCFlag); break; case Expose: if (!prEvent->xexpose.count) DrawWindow(prDisplay,nWnd,prState,prFont,RvGCFlag,Cnt,MaxY,MaxDY); } } void main(int argc,char *argv[]) { Display *prDisplay; XFontStruct *prFont; Window nWnd; XEvent rEvent; TProgState rProgState={0,0,-1,0,0,0,0,0,0}; long Cnt; /* amount of steps */ double MaxY,MaxDY; /* maximum of Y and DY absolute values */ int RvContext; if (PrintPoster(argv)) exit(0); printf("Solving equation...\n "); printf(" with %ld steps.\n",Cnt=GetStepsCnt()); if (!FindStrInTable(argv,"-text")) /* Option -text (Text mode) */ { prDisplay=ConnectToXServer(argv); prFont=LoadDefaultFont(prDisplay,argv); nWnd=OpenDefaultWindow(prDisplay,argc,argv,&RvContext); XSelectInput(prDisplay,nWnd,ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); do { XNextEvent(prDisplay,&rEvent); if (rEvent.type==Expose && !rEvent.xexpose.count) DrawPoster(prDisplay,nWnd,prFont,RvContext); } while (rEvent.type==Expose); XClearArea(prDisplay,nWnd,0,0,0,0,True); GetMaxFuncValues(Cnt,&MaxY,&MaxDY); do /* main loop */ { XNextEvent(prDisplay,&rEvent); EventHandler(prDisplay,nWnd,&rEvent,&rProgState, prFont,RvContext,Cnt,MaxY,MaxDY); } while (!rProgState.quit); XFreeFont(prDisplay,prFont); XCloseDisplay(prDisplay); } else PrintTextTables(Cnt); printf("\nDone.\n"); }