source: tags/arb_5.5/PGT/plot.cxx

Last change on this file was 3960, checked in by baderk, 19 years ago

Removed gcc-warnings.
Removed some memory leaks in the PGT code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.1 KB
Line 
1// Copyright (c) 2004 - 2005 Kai Bader <baderk@in.tum.de>
2//
3// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
6// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
7// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
8// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
10// CVS REVISION TAG  --  $Revision: 3960 $
11
12
13#include "plot.hxx"
14#include <locale.h>
15
16
17#define GNUPLOT_WINDOW_WIDTH  321
18#define GNUPLOT_WINDOW_HEIGHT 123
19
20
21/****************************************************************************
22*  PLOT - CONSTRUCTOR
23****************************************************************************/
24Plot::Plot(Display *d, Window w)
25{
26    // SET PARENT WINDOW (WHERE THE GNUPLOT WINDOW WILL BE EMBEDDED)
27    m_parent_display= d;
28    // m_parent_shell= s;
29    m_parent_window= w;
30
31    // RESERVE SPACE FOR THE GNUPLOT WINDOW TITLE
32    m_title= (char *)malloc(64*sizeof(char));
33
34    // INITIALIZE THE PIPE VARIABLES
35    m_command_pipe= NULL;
36    m_has_command_pipe= false;
37    m_data_pipe= NULL;
38    m_has_data_pipe= false;
39    m_temp_name= NULL;
40}
41
42
43/****************************************************************************
44*  PLOT - DESTRUCTOR
45****************************************************************************/
46Plot::~Plot()
47{
48    // CLOSE COMMAND PIPE (IF NEEDED)
49    if(m_has_command_pipe) close_command_pipe();
50
51    // FREE ALLOCATED SPACE
52    free(m_title);
53}
54
55
56/****************************************************************************
57*  PLOT - SET THE PARENT WINDOW
58****************************************************************************/
59void Plot::setParentWindow(Window w) { m_parent_window= w; }
60
61
62/****************************************************************************
63*  PLOT - EMBED GNUPLOT X11 WINDOW INTO ANOTHER WINDOW
64****************************************************************************/
65void Plot::embed()
66{
67    // DO NOT EMBED IF THE PARENT WINDOW ID IS NULL OR NO DISPLAY IS SET
68    if(!m_parent_window || !m_parent_display) return;
69
70    // CREATE AND INIT LOCAL VARIABLES
71    int countdown= 100;
72    XEvent event;
73    char *window_name;
74    m_gnuplot_window= 0;
75
76    // SET THE EVENT MASK TO 'SubstructureNotifyMask'
77    XSelectInput(m_parent_display, DefaultRootWindow(m_parent_display), SubstructureNotifyMask);
78
79    // LOOP WHILE COUNTDOWN > 0 (AVOIDS INFINITE LOOPS)
80    while(countdown)
81    {
82        // CAUTION:
83        // XNEXTEVENT BELOW ALSO CATCHES OTHER EVENTS AND REMOVES THEM FROM
84        // THE QUEUE. THIS MAY CAUSE PROBLEMS WITH OTHER WINDOWS/WIDGETS,
85        // I.E. FALSE REDRAWN WINDOWS OR LOST SIGNALS FROM WINDOWS/WIDGETS.
86
87        // WAIT FOR AN EVENT TO OCCUR
88        XNextEvent(m_parent_display, &event);
89
90        // IS IT A CREATENOTIFY EVENT?
91        if(event.type == CreateNotify)
92        {
93            // FETCH THE CREATEWINDOWEVENT STRUCT
94            XCreateWindowEvent cwe= event.xcreatewindow;
95
96            // FETCH THE NAME OF THE WINDOW WHICH THREW THE EVENT (POSSIBLY NULL)
97            XFetchName(m_parent_display, cwe.window, &window_name);
98
99            // IF THE NAME MATCHES OUR GNUPLOT WINDOW OR THE SIZE IS RIGHT
100            // MARK IT AND EXIT THE LOOP
101            if((window_name && (strcmp(window_name, m_title) == 0)) ||
102               ((cwe.width == GNUPLOT_WINDOW_WIDTH) && (cwe.height == GNUPLOT_WINDOW_HEIGHT)))
103            {
104                // GET THE WINDOW ID OF THE NEW GNUPLOT WINDOW
105                m_gnuplot_window= cwe.window;
106
107                // SET BORDER WIDTH TO 0 IF NECESSARY
108                if(cwe.border_width) XSetWindowBorderWidth(m_parent_display, m_gnuplot_window, 0);
109
110                // SET COUNTDOWN= 0 TO EXIT LOOP
111                countdown= 0;
112            }
113            else countdown--; // DECREASE LOOP COUNTER
114        }
115        else
116        {
117            // IF THE EVENT IS NOT OF INTEREST FOR US RETURN IT TO THE QUEUE
118            // XPutBackEvent(m_parent_display, &event);
119
120            // DECREASE LOOP COUNTER
121            countdown--;
122        }
123
124        // THIS XSYNC ERASES THE EVENT QUEUE (ALSO MAKES XPUTBACKEVENT OBSOLETE)
125        // XSync(m_parent_display, true);
126    }
127
128    // EXIT, IF WE WERE NOT ABLE TO FIND THE GNUPLOT WINDOW
129    if (!m_gnuplot_window) return;
130
131    // SYNC AND WITHDRAW THE ORIGINAL WINDOW
132    XSync(m_parent_display, false);
133    XWithdrawWindow(m_parent_display, m_gnuplot_window, 0);
134
135    // THE REPARENTING MUST BE TRIED MULTIPLE TIMES TO WORK.
136    // DONT ASK ME WHY...
137    for(int c= 0; c < 100; c++)
138    {
139        XReparentWindow(m_parent_display, m_gnuplot_window, m_parent_window, 0, 0);
140        XSync(m_parent_display, false);
141    }
142
143    // SYNC AND MAP THE NEW GNUPLOT WINDOW
144    XMapWindow(m_parent_display, m_gnuplot_window);
145    XSync(m_parent_display, false);
146}
147
148
149/****************************************************************************
150*  PLOT - RESIZE THE GNUPLOT WINDOW
151****************************************************************************/
152void Plot::resizeWindow(int x, int y, int width, int height)
153{
154    // RETURN IF NO WINDOW IS VISIBLE
155    if(!m_has_command_pipe) return;
156
157    // RESIZE THE GNUPLOT WINDOW
158    XMoveResizeWindow(m_parent_display, m_gnuplot_window, x, y, width, height);
159    XSync(m_parent_display, false);
160}
161
162
163/****************************************************************************
164*  PLOT - OPEN/INIT THE COMMAND PIPE
165****************************************************************************/
166FILE *Plot::open_command_pipe()
167{
168    // LOCAL GNUPLOT WINDOW ID (INCREMENTED BY EACH CALL TO MAKE IT UNIQUE)
169    static int m_local_ID= 0;
170
171    char *buf= (char *)malloc(1024*sizeof(char));
172
173    // CREATE GNUPLOT TITLE (NEEDED FOR LATER RECOGNITION)
174    // m_local_ID++;
175    sprintf(m_title, "plot%dclient%d", getpid(), ++m_local_ID);
176    sprintf(buf, "gnuplot -geometry %dx%d -title '%s'",
177            GNUPLOT_WINDOW_WIDTH, GNUPLOT_WINDOW_HEIGHT, m_title);
178
179    // CREATE A TEMPORARY FILENAME (WARNING: TMPNAM() IS DEPRECATED)
180    // if((m_temp_name= tmpnam(NULL)) == NULL) return NULL;
181
182    // CREATE A TEMPORARY FILENAME (USING MKSTEMP)
183    m_temp_name= (char *)malloc(17 * sizeof(char));
184    strcpy(m_temp_name, "/tmp/plot_XXXXXX");
185        if((mkstemp(m_temp_name)) == -1) return NULL;
186
187    // AS MKTEMP ALSO CREATES THE FILE ITSELF (WHAT WE DONT WANT) REMOVE IT
188    // RIGHT AFTER ITS CREATION FOR FURTHER USE AS A PIPE
189    unlink(m_temp_name);
190
191    // CREATE A FIFO PIPE
192    if(mkfifo(m_temp_name, S_IRUSR | S_IWUSR) != 0) return NULL;
193    m_command_pipe= popen(buf, "w");
194
195    m_has_command_pipe= true;
196
197    free(buf);
198
199    return m_command_pipe;
200}
201
202
203/****************************************************************************
204*  PLOT - CLOSE THE COMMAND PIPE
205****************************************************************************/
206void Plot::close_command_pipe()
207{
208    // CLOSE DATA PIPE (IF NEEDED)
209    if(m_has_data_pipe) close_data_pipe();
210
211    // CLOSE DATA PIPE
212    pclose(m_command_pipe);
213
214    // REMOVE TEMP FILE (WHICH WAS USED AS A PIPE)
215    unlink(m_temp_name);
216
217    if(m_temp_name) free(m_temp_name);
218    m_temp_name= NULL;
219
220    // SET COMMAND PIPE FLAG TO FALSE
221    m_has_command_pipe= false;
222}
223
224
225/****************************************************************************
226*  PLOT - OPEN THE DATA PIPE
227****************************************************************************/
228FILE *Plot::open_data_pipe()
229{
230    if(!m_has_command_pipe) return NULL;
231
232    // fprintf(m_command_pipe, "plot \"%s\" with lines\n", m_temp_name);
233    fprintf(m_command_pipe, "plot \"%s\" with linespoints\n", m_temp_name);
234
235    fflush(m_command_pipe);
236    m_data_pipe= fopen(m_temp_name, "w");
237
238    // SET DATA PIPE FLAG TO TRUE
239    m_has_data_pipe= true;
240
241    return m_data_pipe;
242}
243
244
245/****************************************************************************
246*  PLOT - CLOSE THE DATA PIPE
247****************************************************************************/
248void Plot::close_data_pipe()
249{
250    if(!m_has_data_pipe) return;
251
252    // CLOSE DATA PIPE
253    fclose(m_data_pipe);
254
255    // SET DATA PIPE FLAG TO FALSE
256    m_has_data_pipe= false;
257}
258
259
260/****************************************************************************
261*  PLOT - SEND A STRING TO THE COMMAND PIPE
262****************************************************************************/
263void Plot::send_command_pipe(char *s)
264{
265    // RETURN, IF THERE IS NO OPEN COMMAND PIPE
266    if(!m_has_command_pipe) return;
267
268    // WRITE THE STRING S TO THE DATA PIPE
269    fputs(s, m_command_pipe);
270}
271
272
273/****************************************************************************
274*  PLOT - SEND A STRING TO THE DATA PIPE
275****************************************************************************/
276void Plot::send_data_pipe(char *s)
277{
278    // RETURN, IF THERE IS NO OPEN DATA PIPE
279    if(!m_has_data_pipe) return;
280
281    // WRITE THE STRING S TO THE DATA PIPE
282    fputs(s, m_data_pipe);
283}
284
285
286/****************************************************************************
287*  PLOT - CREATE A DEMO PLOT (FOR TESTING PURPOSES ONLY)
288****************************************************************************/
289void Plot::demo()
290{
291    // AVOID WRONG FLOAT OUTPUT DUE TO GERMAN LOCALES ( ',' -> '.')
292    setlocale(LC_ALL, "C");
293
294    if(!open_command_pipe()) return;
295
296    send_command_pipe(const_cast<char*>("set title \"Überschrift - Proteomdaten\"\n"));
297    send_command_pipe(const_cast<char*>("set xlabel \"Protein\"\n"));
298    send_command_pipe(const_cast<char*>("set ylabel \"Abweichung\"\n"));
299
300    if(!open_data_pipe()) return;
301
302    double a, b;
303
304    // FIRST DATASET
305    for (int i= 1; i < 20; i++)
306    {
307        a= i / 10.0;
308        b= cos(a);
309
310        fprintf(m_data_pipe, "%f %f\n", a, b);
311    }
312
313    // EMPTY LINE (SEPARATOR BETWEEN DATASETS)
314    fprintf(m_data_pipe, "\n");
315
316    // SECOND DATASET
317    for (int i= 1; i < 20; i++)
318    {
319        a= i / 10.0;
320        b= (double)(rand()%10);
321
322        fprintf(m_data_pipe, "%f %f\n", a, b);
323    }
324
325    close_data_pipe();
326    // close_command_pipe();
327
328    // RESET LOCALES
329    setlocale(LC_ALL, "");
330
331    // DEBUG
332    embed();
333    // DEBUG
334}
335
Note: See TracBrowser for help on using the repository browser.