open-axiom repository from github
/*1Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2011, Gabriel Dos Reis.4All rights reserved.56Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions are8met:910- Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.1213- Redistributions in binary form must reproduce the above copyright14notice, this list of conditions and the following disclaimer in15the documentation and/or other materials provided with the16distribution.1718- Neither the name of The Numerical Algorithms Group Ltd. nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS23IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED24TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A25PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER26OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,27EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,28PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR29PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/3435#define _PROCESS2D_C36#include "openaxiom-c-macros.h"3738#include <string.h>39#include <stdio.h>40#include <stdlib.h>41#include <unistd.h>42#include <sys/types.h>43#include <sys/time.h>44#ifdef RIOSplatform45#include <sys/select.h>46#endif4748#include "cfuns.h"49#include "header2.h"50#include "all_2d.H1"51#include "util.H1"52#include "Gfun.H1"53#include "XSpadFill.h"5455using namespace OpenAxiom;565758static int doit=0; /* globish variable for picking/dropping/clearing - all sorts of592 button sequence events (command & graph #). */606162void63doPick (int i,int bKey)64{65int vCommand=pick2D;6667picking = no;68/* reset indicator so that we're not in pick/drop/query mode anymore */69doit = 0;70if (graphArray[currentGraph].key) {71check(write(Socket,&vCommand,intSize));72check(write(Socket,&(graphArray[currentGraph].key),intSize));73check(write(Socket,&(graphStateArray[currentGraph]),74sizeof(graphStateStruct)));75sprintf(control->message,"%s%d","Picked up graph ",currentGraph+1);76} else77sprintf(control->message,"%s","This graph is empty!");78writeControlMessage();798081}828384void85doDrop (int i,int bKey)86{87int vCommand=drop2D;88int viewGoAhead;8990dropping = no;91/* reset indicator so that we're not in pick/drop/query mode anymore */92doit = 0;93check(write(Socket,&(vCommand),intSize));94readViewman(&viewGoAhead,intSize);95if (viewGoAhead < 0) {96sprintf(control->message,"%s%d","Couldn't drop to graph ",currentGraph+1);97writeControlMessage();98} else {99sprintf(control->message,"%s%d","Dropped onto graph ",currentGraph+1);100writeControlMessage();101freeGraph(currentGraph);102readViewman(&(graphArray[currentGraph].key),intSize);103getGraphFromViewman(currentGraph);104/* simulate a button press to turn display number on and select on */105/* need !yes since it will be inverted */106graphStateArray[currentGraph].selected = no;107graphStateArray[currentGraph].showing =108!(graphStateArray[currentGraph].showing);109clickedOnGraph(currentGraph,currentGraph+graphStart);110clickedOnGraphSelect(currentGraph,currentGraph+graphSelectStart);111}112}113114void115clickedOnGraphSelect (int i,int bKey)116{117int strlength;118119switch (doit) {120case pick2D:121currentGraph = i;122doPick(i,bKey);123break;124case drop2D:125currentGraph = i;126doDrop(i,bKey);127break;128case query2D:129queriedGraph = i;130makeMessageFromData(queriedGraph);131writeControlMessage();132/* reset indicator so that we're not in pick/drop/query mode anymore */133doit = 0;134break;135default:136graphStateArray[i].selected = !(graphStateArray[i].selected);137if (graphStateArray[i].selected) {138GSetForeground(graphGC,(float)graphBarSelectColor,Xoption);139strcpy(control->buttonQueue[bKey].text,"^");140strlength = strlen(control->buttonQueue[bKey].text);141} else {142GSetForeground(graphGC,(float)graphBarNotSelectColor,Xoption);143strcpy(control->buttonQueue[bKey].text,"-");144strlength = strlen(control->buttonQueue[bKey].text);145}146/* just to make sure the background is reset from clickedOnGraph */147if (mono) {148GSetForeground(graphGC,(float)foregroundColor,Xoption);149GSetBackground(graphGC,(float)backgroundColor,Xoption);150}151152GDrawImageString(graphGC,control->controlWindow,153control->buttonQueue[bKey].buttonX +154centerX(graphGC,155control->buttonQueue[bKey].text,strlength,156control->buttonQueue[bKey].buttonWidth),157control->buttonQueue[bKey].buttonY +158centerY(graphGC,159control->buttonQueue[bKey].buttonHeight),160control->buttonQueue[bKey].text,strlength,Xoption);161GSetForeground(trashGC,(float)foregroundColor,Xoption);162GSetLineAttributes(trashGC,2,LineSolid,CapButt,JoinMiter,Xoption);163GDrawLine(trashGC,control->controlWindow,0,286,controlWidth,286,Xoption);164break;165} /* switch doit */166167}168169170static void171drawControlPushButton(int isOn, int index)172{173GDrawPushButton(dsply, processGC, processGC, processGC,174control->controlWindow,175(control->buttonQueue[index]).buttonX,176(control->buttonQueue[index]).buttonY,177(control->buttonQueue[index]).buttonWidth,178(control->buttonQueue[index]).buttonHeight,179isOn,180(control->buttonQueue[index]).text,181buttonColor,182monoColor((control->buttonQueue[index]).textColor), Xoption);183XSync(dsply,False);184}185186187188void189buttonAction (int bKey)190{191int i;192193switch (bKey) {194195case pick2D:196if (viewAloned) {197sprintf(control->message,"%s","Cannot pick without OpenAxiom!");198writeControlMessage();199XSync(dsply,False);200}201else {202doit = pick2D;203sprintf(control->message,"%s","Click on the graph to pick");204writeControlMessage();205XSync(dsply,False);206}207break;208209case drop2D:210if (viewAloned) {211sprintf(control->message,"%s","Cannot drop without OpenAxiom!");212writeControlMessage();213XSync(dsply,False);214} else {215doit = drop2D;216sprintf(control->message,"%s","Click on the graph to drop");217writeControlMessage();218XSync(dsply,False);219}220break;221222case query2D:223doit = query2D;224sprintf(control->message,"%s","Click on the graph to query");225writeControlMessage();226XSync(dsply,False);227break;228229230case zoom2Dx:231if (zoomXON)232strcpy((control->buttonQueue[zoom2Dx]).text ,233"X Off");234else235strcpy((control->buttonQueue[zoom2Dx]).text ,236"X On ");237zoomXON = !zoomXON;238239drawControlPushButton(zoomXON, zoom2Dx);240XSync(dsply,False);241break;242243case zoom2Dy:244if (zoomYON) strcpy((control->buttonQueue[zoom2Dy]).text,245"Y Off");246else strcpy((control->buttonQueue[zoom2Dy]).text ,247"Y On ");248zoomYON = !zoomYON;249drawControlPushButton(zoomYON, zoom2Dy);250XSync(dsply,False);251break;252253254case translate2Dx:255if (transXON) strcpy((control->buttonQueue[translate2Dx]).text,256"X Off");257else strcpy( (control->buttonQueue[translate2Dx]).text,258"X On ");259transXON = !transXON;260drawControlPushButton(transXON, translate2Dx);261XSync(dsply,False);262break;263264case translate2Dy:265if (transYON) strcpy((control->buttonQueue[translate2Dy]).text,266"Y Off");267else strcpy( (control->buttonQueue[translate2Dy]).text,268"Y On");269transYON = !transYON;270drawControlPushButton(transYON, translate2Dy);271XSync(dsply,False);272break;273274case pointsOnOff:275if (pointsON) strcpy((control->buttonQueue[pointsOnOff]).text,276"Pts Off");277else strcpy( (control->buttonQueue[pointsOnOff]).text,278"Pts On ");279pointsON = !pointsON;280for (i=0; i<maxGraphs; i++)281if (graphStateArray[i].showing && graphStateArray[i].selected)282graphStateArray[i].pointsOn = pointsON;283284drawControlPushButton(pointsON, pointsOnOff);285drawViewport(Xoption);286break;287288case connectOnOff:289if (connectON) strcpy((control->buttonQueue[connectOnOff]).text,290"Lines Off");291else strcpy( (control->buttonQueue[connectOnOff]).text,292"Lines On ");293connectON = !connectON;294for (i=0; i<maxGraphs; i++)295if (graphStateArray[i].showing && graphStateArray[i].selected)296graphStateArray[i].connectOn = connectON;297298drawControlPushButton(connectON, connectOnOff);299drawViewport(Xoption);300break;301302case spline2D:303if (splineON) strcpy((control->buttonQueue[spline2D]).text,304"Box Off");305else strcpy ((control->buttonQueue[spline2D]).text ,306"Box On ");307splineON = !splineON;308for (i=0; i<maxGraphs; i++)309if (graphStateArray[i].showing && graphStateArray[i].selected)310graphStateArray[i].splineOn = splineON;311312drawControlPushButton(splineON, spline2D);313drawViewport(Xoption);314break;315316case axesOnOff2D:317if (axesON)318strcpy ((control->buttonQueue[axesOnOff2D]).text,319"Axes Off");320else321strcpy ((control->buttonQueue[axesOnOff2D]).text ,322"Axes On ");323axesON = !axesON;324for (i=0; i<maxGraphs; i++)325if (graphStateArray[i].showing && graphStateArray[i].selected)326graphStateArray[i].axesOn = axesON;327328drawControlPushButton(axesON, axesOnOff2D);329drawViewport(Xoption);330break;331332case unitsOnOff2D:333if (unitsON)334strcpy( (control->buttonQueue[unitsOnOff2D]).text,335"Units Off");336else337strcpy ((control->buttonQueue[unitsOnOff2D]).text,338"Units On ");339unitsON = !unitsON;340for (i=0; i<maxGraphs; i++)341if (graphStateArray[i].showing && graphStateArray[i].selected)342graphStateArray[i].unitsOn = unitsON;343344drawControlPushButton(unitsON, unitsOnOff2D);345drawViewport(Xoption);346break;347348case ps2D:349strcpy(control->message,"Creating postscript now ...");350writeControlMessage();351drawControlPushButton(1, ps2D);352353if (PSInit(viewport->viewWindow, viewport->titleWindow) == psError) {354strcpy(control->message,"Aborted: PSInit error.");355writeControlMessage();356drawControlPushButton(0, ps2D);357XSync(dsply,False);358return; /* make new temp name for new file */359}360361drawViewport(PSoption); /* draw picture in PS; create ps script file */362363if (PSCreateFile(viewBorderWidth,364viewport->viewWindow,365viewport->titleWindow,366viewport->title) == psError) {367strcpy(control->message,"Aborted: PSCreateFile error.");368writeControlMessage();369drawControlPushButton(0, ps2D);370XSync(dsply,False);371return;372}373374clearControlMessage();375strcpy(control->message,PSfilename);376strcat(control->message," in working dir ");377writeControlMessage();378drawControlPushButton(0, ps2D);379XSync(dsply,False);380break;381382case hideControl2D:383if (viewport->haveControl) {384viewport->haveControl = no;385XUnmapWindow(dsply,control->controlWindow);386XSync(dsply,False);387}388break;389390case reset2D:391/* reset view */392for (i=0; i<maxGraphs; i++)393if (graphStateArray[i].showing && graphStateArray[i].selected)394graphStateArray[i] = graphStateBackupArray[i];395396unitsON = no;397strcpy( (control->buttonQueue[unitsOnOff2D]).text,s = "Units Off");398for (i=0; i<maxGraphs; i++)399if (graphStateArray[i].showing && graphStateArray[i].selected)400graphStateArray[i].unitsOn = no;401drawControlPushButton(unitsON, unitsOnOff2D);402403pointsON = yes;404strcpy ((control->buttonQueue[pointsOnOff]).text ,"Pts On ");405for (i=0; i<maxGraphs; i++)406if (graphStateArray[i].showing && graphStateArray[i].selected)407graphStateArray[i].pointsOn = yes;408drawControlPushButton(pointsON, pointsOnOff);409410axesON = yes;411strcpy ((control->buttonQueue[axesOnOff2D]).text,"Axes On ");412for (i=0; i<maxGraphs; i++)413if (graphStateArray[i].showing && graphStateArray[i].selected)414graphStateArray[i].axesOn = yes;415drawControlPushButton(axesON, axesOnOff2D);416417connectON = yes;418strcpy((control->buttonQueue[connectOnOff]).text,"Lines On ");419for (i=0; i<maxGraphs; i++)420if (graphStateArray[i].showing && graphStateArray[i].selected)421graphStateArray[i].connectOn = yes;422drawControlPushButton(connectON, connectOnOff);423424splineON = no;425strcpy( (control->buttonQueue[connectOnOff]).text ,"Box Off");426for (i=0; i<maxGraphs; i++)427if (graphStateArray[i].showing && graphStateArray[i].selected)428graphStateArray[i].splineOn = splineON;429drawControlPushButton(splineON, spline2D);430drawViewport(Xoption);431432break;433434case closeAll2D:435strcpy(control->message," Click again to confirm ");436writeControlMessage();437drawControlPushButton(1, closeAll2D);438XSync(dsply,False);439viewport->closing = yes;440break;441442case clear2D:443for (i=0; i<maxGraphs; i++) graphStateArray[i].selected = 1;444clickedOnGraphSelect(0,graphSelect1);445clickedOnGraphSelect(1,graphSelect2);446clickedOnGraphSelect(2,graphSelect3);447clickedOnGraphSelect(3,graphSelect4);448clickedOnGraphSelect(4,graphSelect5);449clickedOnGraphSelect(5,graphSelect6);450clickedOnGraphSelect(6,graphSelect7);451clickedOnGraphSelect(7,graphSelect8);452clickedOnGraphSelect(8,graphSelect9);453XSync(dsply,False);454break;455456case graph1:457case graph2:458case graph3:459case graph4:460case graph5:461case graph6:462case graph7:463case graph8:464case graph9:465clickedOnGraph(bKey-graphStart,bKey);466XSync(dsply,False);467break;468469case graphSelect1:470case graphSelect2:471case graphSelect3:472case graphSelect4:473case graphSelect5:474case graphSelect6:475case graphSelect7:476case graphSelect8:477case graphSelect9:478clickedOnGraphSelect(bKey-graphSelectStart,bKey);479XSync(dsply,False);480break;481482} /* switch (action) */483}484485/*********************** X Event Processing ***************************/486void487processEvents(void)488{489490XEvent *event,491tempEvent;492Window whichWindow;493XWindowAttributes graphWindowAttrib;494buttonStruct *controlButton;495mouseCoord mouseXY;496int i,497someInt,498mouseW4,499mouseH4,500toggleReady,501gotToggle = no,502checkButton = no,503firstTime = yes,504gotEvent = 0,505buttonTablePtr,506Xcon,507len,508externalControl;509fd_set rd;510511512externalControl=0;513Xcon = ConnectionNumber(dsply);514515516if (!(event = (XEvent *)malloc(sizeof(XEvent)))) {517fprintf(stderr,"Ran out of memory initializing event processing.\n");518exitWithAck(RootWindow(dsply,scrn),Window,-1);519}520521controlButton = control->buttonQueue;522523while(1) {524525len=0;526while(len<=0) {527FD_ZERO(&rd);528if (externalControl==0) FD_SET(0, &rd);529FD_SET(Xcon,&rd);530531if (XEventsQueued(dsply, QueuedAlready)) {532len=1;533break;534}535if (!followMouse)536len=select(FD_SETSIZE, &rd,0,0,0);537else538len=1;539}540if (FD_ISSET(Xcon,&rd)||541XEventsQueued(dsply, QueuedAfterFlush) ||542followMouse) {543544if (followMouse) {545if (XPending(dsply))546XNextEvent(dsply,event);547gotEvent++;548} else {549XNextEvent(dsply,event);550gotEvent++;551}552553if (gotToggle || !followMouse)554checkButton = no;555556if (gotEvent) {557whichWindow = ((XButtonEvent *)event)->window;558firstTime = no;559560switch(((XEvent *)event)->type) {561562case ClientMessage:563if (event->xclient.data.l[0] == wm_delete_window) {564goodbye(-1);565}566else {567fprintf(stderr,"Unknown Client Message ...\n");568}569break;570case Expose:571if (whichWindow == viewport->titleWindow) {572/* get rid of redundant events */573XCheckWindowEvent(dsply,574viewport->titleWindow,575ExposureMask,576&tempEvent);577writeTitle();578XGetWindowAttributes(dsply,579whichWindow,580&graphWindowAttrib);581XResizeWindow(dsply,582viewport->viewWindow,583graphWindowAttrib.width,584graphWindowAttrib.height-titleHeight);585XSync(dsply,False);586break;587} else if (whichWindow == viewport->viewWindow) {588XCheckWindowEvent(dsply,589viewport->viewWindow,590ExposureMask,591&tempEvent);592XGetWindowAttributes(dsply,593viewport->titleWindow,594&graphWindowAttrib);595XResizeWindow(dsply,596viewport->viewWindow,597graphWindowAttrib.width,598graphWindowAttrib.height-titleHeight);599drawViewport(Xoption);600XMapWindow(dsply,whichWindow);601XSync(dsply,False);602break;603} else { /* it's gotta be the control panel */604XGetWindowAttributes(dsply,605control->controlWindow,606&graphWindowAttrib);607/* do not allow resizing of control panel */608if ((graphWindowAttrib.width != controlWidth) ||609(graphWindowAttrib.height != controlHeight)) {610XResizeWindow(dsply,611control->controlWindow,612controlWidth,613controlHeight);614}615drawControlPanel();616XSync(dsply,False);617break;618}619break;620621case MotionNotify:622if (followMouse) {623while (XCheckMaskEvent(dsply,624ButtonMotionMask,625event));626mouseXY = getPotValue(((XButtonEvent *)event)->x,627((XButtonEvent *)event)->y,628controlButton->xHalf,629controlButton->yHalf);630}631if (controlButton->pot) {632gotToggle = no;633checkButton = yes;634}635break;636637case ButtonRelease:638if (followMouse==yes) {639followMouse = no;640toggleReady = yes;641checkButton = no;642drawViewport(Xoption);643} else {644followMouse = no;645toggleReady = yes;646checkButton = no;647}648break;649650case LeaveNotify:651/*652We still follow the mouse when we leave the pots.653*/654/*655followMouse = no;656toggleReady = yes;657checkButton = no;658*/659660break;661662case ButtonPress:663if (whichWindow == viewport->viewWindow) {664665/* mouse clicked on viewport */666667switch (((XButtonEvent *)event)->button) {668case Button3:669670/* print out (x,y) object-space coordinates in message area */671672XGetWindowAttributes(dsply,whichWindow,&graphWindowAttrib);673sprintf(viewport->controlPanel->message,674" >%d<: [%6.2f,%6.2f] ",675queriedGraph+1,676projX((((XButtonEvent *)event)->x),677graphWindowAttrib.width,queriedGraph),678projY((((XButtonEvent *)event)->y),679graphWindowAttrib.height,queriedGraph));680writeControlMessage();681XFlush(dsply);682break;683default:684685/* Find where mouse is on the viewport => where to put the CP */686687XGetWindowAttributes(dsply,688whichWindow,689&graphWindowAttrib);690mouseW4 = graphWindowAttrib.width/4;691if (((XButtonEvent *)event)->x >692(graphWindowAttrib.width - mouseW4))693someInt = 1;694else {695mouseH4 = graphWindowAttrib.height/4;696if (((XButtonEvent *)event)->y >697(graphWindowAttrib.height - mouseH4))698someInt = 2;699else if (((XButtonEvent *)event)->x < mouseW4)700someInt = 3;701else if (((XButtonEvent *)event)->y < mouseH4)702someInt = 4;703else someInt = 0;704}705if (viewport->haveControl) {706XUnmapWindow(dsply,control->controlWindow);707}708putControlPanelSomewhere(someInt);709XMapWindow(dsply,control->controlWindow);710XSync(dsply,False);711break;712} /* switch on mouse button */713} else if (whichWindow == control->colormapWindow) {714715/* mouse clicked on colormap */716717followMouse = yes;718gotToggle = no;719checkButton = yes;720firstTime = yes;721} else if (whichWindow != control->controlWindow) {722723/* mouse clicked on control window (not colormap) */724725if (controlButton->self != whichWindow) {726buttonTablePtr = *((int *)XLookUpAssoc(dsply,table,whichWindow));727controlButton = &(control->buttonQueue[buttonTablePtr]);728}729730if (controlButton->pot) {731/* figure out [x,y] for this button in the range [-1..1,-1..1] */732mouseXY = getPotValue(((XButtonEvent *)event)->x,733((XButtonEvent *)event)->y,734controlButton->xHalf,735controlButton->yHalf);736followMouse = yes;737gotToggle = no;738} else {739followMouse = no;740gotToggle = yes; /* auto-repeat on toggle buttons not allowed */741if (toggleReady) {742toggleReady = no;743}744}745checkButton = yes;746firstTime = yes;747}748break;749750} /* switch */751gotEvent--;752} /* if gotEvent */753754755/* Allow repeat polling when mouse button clicked on a potentiometer. */756757if (followMouse && !firstTime && (followMouse++ > mouseWait)) {758followMouse = yes; /* reset for next timing loop */759checkButton = yes;760}761if (checkButton) {762if (viewport->closing && (controlButton->buttonKey == closeAll2D)) {763goodbye(-1);764} else {765clearControlMessage();766viewport->closing = no;767drawControlPushButton(0, closeAll2D);768if ((doit) &&769((controlButton->buttonKey < graphStart) &&770(controlButton->buttonKey > (graphSelectStart + maxGraphs))))771doit = 0;772773switch(controlButton->buttonKey) {774775case translate2D:776for (i=0; i<maxGraphs; i++) {777if (graphStateArray[i].showing && graphStateArray[i].selected) {778if (transXON) {779graphStateArray[i].centerX -= mouseXY.x * 0.1;780if (graphStateArray[i].centerX > maxDelta)781graphStateArray[i].centerX = maxDelta;782else if (graphStateArray[i].centerX < -maxDelta)783graphStateArray[i].centerX = maxDelta;784}785if (transYON) {786graphStateArray[i].centerY -= mouseXY.y * 0.1;787if (graphStateArray[i].centerY > maxDelta)788graphStateArray[i].centerY = maxDelta;789else if (graphStateArray[i].centerY < -maxDelta)790graphStateArray[i].centerY = maxDelta;791}792} /* graph showing or selected */793} /* for graphs */794drawViewport(Xoption);795break;796797case scale2D:798for (i=0; i<maxGraphs; i++) {799if (graphStateArray[i].showing && graphStateArray[i].selected) {800if (zoomXON) {801graphStateArray[i].scaleX *= (1 - mouseXY.y * 0.3);802if (graphStateArray[i].scaleX > maxScale)803graphStateArray[i].scaleX = maxScale;804else if (graphStateArray[i].scaleX < minScale)805graphStateArray[i].scaleX = minScale;806}807if (zoomYON) {808graphStateArray[i].scaleY *= (1 - mouseXY.y * 0.3);809if (graphStateArray[i].scaleY > maxScale)810graphStateArray[i].scaleY = maxScale;811else if (graphStateArray[i].scaleY < minScale)812graphStateArray[i].scaleY = minScale;813}814} /* graph showing or selected */815} /* for graphs */816drawViewport(Xoption);817break;818819default:820buttonAction(controlButton->buttonKey);821} /* switch on buttonKey */822} /* else - not closing */823} /* if checkButton */824} /* if FD_ISSET(Xcon.... */825else if (FD_ISSET(0,&rd)) {826externalControl=spadAction(); /* returns (-1) if broken ,0 if success */827if (spadDraw && (externalControl==0)) drawViewport(Xoption);828}829} /* while */830} /* processEvents() */831832833834835836837void838clickedOnGraph (int i,int bKey)839{840841switch (doit) {842case pick2D:843currentGraph = queriedGraph = i;844doPick(i,bKey);845break;846case drop2D:847currentGraph = queriedGraph = i;848doDrop(i,bKey);849break;850case query2D:851queriedGraph = i;852makeMessageFromData(queriedGraph);853writeControlMessage();854/* reset indicator so that we're not in pick/drop/query mode anymore */855doit = 0;856break;857default:858graphStateArray[i].showing = !(graphStateArray[i].showing);859if (mono) {860if (graphStateArray[i].showing) {861GSetForeground(graphGC,(float)backgroundColor,Xoption);862GSetBackground(graphGC,(float)foregroundColor,Xoption);863} else {864GSetForeground(graphGC,(float)foregroundColor,Xoption);865GSetBackground(graphGC,(float)backgroundColor,Xoption);866}867GDrawImageString(graphGC,868control->controlWindow,869(control->buttonQueue[bKey]).buttonX +870centerX(graphGC,(control->buttonQueue[bKey]).text,1,871(control->buttonQueue[bKey]).buttonWidth),872(control->buttonQueue[bKey]).buttonY +873centerY(graphGC,(control->buttonQueue[bKey]).buttonHeight),874(control->buttonQueue[bKey]).text,8751,876Xoption);877} else {878if (graphStateArray[i].showing)879GSetForeground(graphGC,(float)graphBarShowingColor,Xoption);880else881GSetForeground(graphGC,(float)graphBarHiddenColor,Xoption);882GDrawString(graphGC,883control->controlWindow,884(control->buttonQueue[bKey]).buttonX +885centerX(graphGC,(control->buttonQueue[bKey]).text,1,886(control->buttonQueue[bKey]).buttonWidth),887(control->buttonQueue[bKey]).buttonY +888centerY(graphGC,(control->buttonQueue[bKey]).buttonHeight),889(control->buttonQueue[bKey]).text,1,Xoption);890}891drawViewport(Xoption);892break;893} /* switch doit */894895}896897898899900901902903904905906907