Change sprintf to snprintf for buffer overflow protection
[snark14.git] / tools / Display / SnarkDisplay.cpp
1 /** @file SnarkDisplay.cpp
2     @package snark14Display
3     @author Bruno M. Carvalho and Deniz Sarioz
4     licensed under (open-source) QPL v1.0
5     which accompanies this distribution in the file QPL
6     
7     modification: Joanna Klukowska 1/13/2009
8             added choice of grayScale display for plot
9             in addition to color display
10 // 
11  */
12
13 // sd headers
14 #include "SnarkDisplay.hpp"
15 #include "displaylines.hpp"
16 #include "displayprojection.hpp"
17 #include "eval_helper.hpp"
18 #include "lines.hpp"
19 #include "line_real_t.hpp"
20 #include "plot_t.hpp"
21 #include "linesimages.hpp"
22 #include "proj.hpp"
23 #include "displaywindow.hpp"
24 #include "selectEvalExecutions.hpp"
25 #include "variables.hpp"
26 #include "range.hpp"
27 #include "openimages.hpp"
28
29 // C++ headers
30 #include <iostream>
31
32 // C-like headers
33 #include <cstdio>
34 #include <ctype.h>
35 #include <malloc.h>
36
37 // Qt headers
38 #include <qapplication.h>
39 #include <qdialog.h>
40 #include <qfiledialog.h>
41 #include <qframe.h>
42 #include <qpushbutton.h>
43 #include <qlayout.h>
44 #include <qpainter.h>
45 #include <qpen.h>
46 #include <qvariant.h>
47 #include <qtooltip.h>
48 #include <qwhatsthis.h>
49 #include <qmessagebox.h>
50 #include <qregexp.h> 
51
52 const char *myTag = "sd140707";
53
54 /* 
55  *  Constructs a SnarkDisplay which is a child of 'parent', with the 
56  *  name 'name' and widget flags set to 'fl'
57  */
58 SnarkDisplay::SnarkDisplay(QWidget* parent, const char* name, WFlags fl)
59 : QWidget(parent, name, fl) {
60     std::cout << "Executing snark14Display - " << myTag << std::endl;
61     numimages = 0;
62     desk = QApplication::desktop();
63     maxSizex = desk->size().width();
64     maxSizey = desk->size().height();
65     if (!name)
66         setName("snark14Display");
67     resize(250, 400);
68     setSizePolicy(QSizePolicy((QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, sizePolicy().hasHeightForWidth()));
69     setMinimumSize(QSize(250, 400));
70     setMaximumSize(QSize(250, 400));
71     setCaption(tr("snark14Display"));
72
73     recfilbutton = new QPushButton(this, "recfilbutton");
74     recfilbutton->setGeometry(QRect(40, 25, 170, 40));
75     recfilbutton->setText(tr("Open Recfil File"));
76     QObject::connect(recfilbutton, SIGNAL(clicked()), this, SLOT(openRecfilFile()));
77
78     imagesbutton = new QPushButton(this, "imagesbutton");
79     imagesbutton->setGeometry(QRect(40, 75, 170, 40));
80     imagesbutton->setText(tr("Open Images"));
81     QObject::connect(imagesbutton, SIGNAL(clicked()), this, SLOT(callOpenImages()));
82
83     rangebutton = new QPushButton(this, "rangebutton");
84     rangebutton->setGeometry(QRect(40, 125, 170, 40));
85     rangebutton->setText(tr("Set Global Features"));
86     QObject::connect(rangebutton, SIGNAL(clicked()), this, SLOT(callRange()));
87
88     linesbutton = new QPushButton(this, "linesbutton");
89     linesbutton->setGeometry(QRect(40, 175, 170, 40));
90     linesbutton->setText(tr("Display Lines"));
91     QObject::connect(linesbutton, SIGNAL(clicked()), this, SLOT(callLines()));
92
93     projfilbutton = new QPushButton(this, "projfilbutton");
94     projfilbutton->setGeometry(QRect(40, 225, 170, 40));
95     projfilbutton->setText(tr("Open Prjfil File"));
96     QObject::connect(projfilbutton, SIGNAL(clicked()), this, SLOT(openPrjfilFile()));
97
98     evalbutton = new QPushButton(this, "evalbutton");
99     evalbutton->setGeometry(QRect(40, 275, 170, 40));
100     evalbutton->setText(tr("Open Eval File"));
101     QObject::connect(evalbutton, SIGNAL(clicked()), this, SLOT(openEvalFile()));
102
103     Line1 = new QFrame(this, "Line1");
104     Line1->setGeometry(QRect(0, 325, 260, 16));
105     Line1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
106
107     quitbutton = new QPushButton(this, "quitbutton");
108     quitbutton->setGeometry(QRect(10, 350, 100, 40));
109     quitbutton->setText(tr("Quit"));
110     QObject::connect(quitbutton, SIGNAL(clicked()), qApp, SLOT(quit()));
111
112     helpbutton = new QPushButton(this, "helpbutton");
113     helpbutton->setGeometry(QRect(140, 350, 100, 40));
114     helpbutton->setText(tr("About"));
115     QObject::connect(helpbutton, SIGNAL(clicked()), this, SLOT(about()));
116
117     allocSnarkimages(numimages);
118     //  allocDisplaywindows(numimages);
119     displaywindowset = 0;
120     displaywindowactive = 0;
121     myRangeWinP = 0;
122     myOpenImagesWinP = 0;
123 } // --SnarkDisplay ctor
124
125 /** Destroys the object and frees any allocated resources
126  */
127 SnarkDisplay::~SnarkDisplay() {
128     // no need to delete child widgets, Qt does it all for us
129 }
130
131 /** Calls file dialog and opens recfil file
132 @param void
133 @author Bruno M. Carvalho
134 @version 1.0 */
135 void SnarkDisplay::openRecfilFile() {
136     unsigned int asn, an;
137     int i, j, ni, widthproj, widthexec;
138     char name[256], oldname[256], nameexecution[13], namephantom[41];
139     char namealg[5], nameprojection[13];
140     const char *na;
141     const DIGDimensions* Dimensions;
142     QString itname, recfilfilename, s;
143     QFileDialog fd(QString::null, "Recfil files (*recfil*)\n All files (*)", this, "Open Recfil File", true);
144     fd.setCaption("Open Recfil File");
145     fd.setSelection(QDir::currentDirPath());
146     if (fd.exec() == QDialog::Accepted)
147         recfilfilename = fd.selectedFile();
148     else
149         recfilfilename = "";
150     if (openrecfil) {
151         digrecfil.Close();
152         free(settitles);
153         for (i = 0; i < numimages; i++) {
154             if (imageindexes[i]) {
155                 free(imageindexes[i]);
156                 imageindexes[i] = 0;
157             }
158             imagetitles[i] = 0;
159         }
160         if (myRangeWinP) {
161             myRangeWinP->closeWindow();
162             myRangeWinP = 0;
163         }
164         if (myOpenImagesWinP) {
165             delete myOpenImagesWinP;
166             myOpenImagesWinP = 0;
167         }
168         free(imageindexes);
169         freeSnarkimages(numimages);
170         freeDisplaywindows(numimages);
171     }
172     if (!recfilfilename.isEmpty()) {
173         snprintf(name, sizeof(name)-1, "%s", recfilfilename.latin1());
174         if (digrecfil.Open(name) != 0) {
175             s.sprintf("Error!\nUnable to open file:\n%s\n", recfilfilename.latin1());
176             QMessageBox::information(this, "SnarkDisplay", s);
177             digrecfil.Close();
178             return;
179         } else {
180           snprintf(oldname, sizeof(oldname)-1, "%s", name);
181             phantomexists = false;
182             if (digrecfil.GetDimensions(&Dimensions) != 0) {
183                 s.sprintf("%s is not a snark14 recfil\n", recfilfilename.latin1());
184                 QMessageBox::information(this, "SnarkDisplay", s);
185                 return;
186             }
187             if ((Dimensions->x != 1) && (Dimensions->y != 1) && (Dimensions->z != 1)) {
188                 s.sprintf("%s is not a snark14 recfil\n", recfilfilename.latin1());
189                 QMessageBox::information(this, "SnarkDisplay", s);
190                 return;
191             }
192             if (Dimensions->z == 1) {
193                 Sizex = Dimensions->x;
194                 Sizey = Dimensions->y;
195             } else {
196                 if (Dimensions->y == 1) {
197                     Sizex = Dimensions->x;
198                     Sizey = Dimensions->z;
199                 } else {
200                     Sizex = Dimensions->y;
201                     Sizey = Dimensions->z;
202                 }
203             }
204             digrecfil.GetDataFormat(&dataformat);
205             nameproj = (const char *) malloc(sizeof (const char) *81);
206             digrecfil.GetTitle(&nameproj);
207             strncpy(nameprojection, nameproj, 12);
208             nameprojection[12] = 0;
209             widthproj = 12;
210             for (j = 11; j >= 0; j--) {
211                 if (nameprojection[j] == ' ' || nameprojection[j] == 0 || nameprojection[j] == 10) {
212                     nameprojection[j] = 0;
213                     widthproj--;
214                 } else
215                     break;
216             }
217             digrecfil.GetNoOfArraySets(&asn);
218             settitles = (const char **) malloc(sizeof (const char *) * asn);
219             numimages = 0;
220             for (i = 0; i < (static_cast<int> (asn)); i++) {
221                 digrecfil.SelectArraySet(i);
222                 digrecfil.GetArraySetTitle(&settitles[i]);
223                 digrecfil.GetNoOfArrays(&an);
224                 numimages += an;
225             }
226             imagetitles = (char **) malloc(sizeof (char *) * numimages);
227             for (i = 0; i < numimages; i++) {
228                 imagetitles[i] = (char *) malloc(sizeof (char) *41);
229             }
230             imageindexes = (unsigned int **) malloc(sizeof (unsigned int *) * numimages);
231             for (i = 0; i < numimages; i++) {
232                 imageindexes[i] = (unsigned int *) malloc(sizeof (unsigned int *) *2);
233             }
234             ni = 0;
235             for (i = 0; i < (static_cast<int> (asn)); i++) {
236                 widthexec = 12;
237                 digrecfil.SelectArraySet(i);
238                 digrecfil.GetNoOfArrays(&an);
239                 digrecfil.GetArraySetType(&na);
240                 strncpy(namealg, na, 4);
241                 namealg[4] = 0;
242                 for (j = 0; j < 4; j++)
243                     namealg[j] = toupper(namealg[j]);
244                 if (!strcmp(namealg, "PHAN")) {
245                     phantomexists = true;
246                     strncpy(namephantom, settitles[i], 40);
247                     namephantom[40] = 0;
248                     if (!strcmp(namephantom, ""))
249                         itname.sprintf("_");
250                     else
251                         itname.sprintf("%-40s", namephantom);
252                     snprintf(imagetitles[ni], sizeof(imagetitles[ni])-1, "%s", itname.latin1());
253                     imageindexes[ni][0] = i;
254                     imageindexes[ni][1] = 0;
255                     ni++;
256                 } else {
257                     strncpy(nameexecution, settitles[i], 12);
258                     nameexecution[12] = 0;
259                     widthexec = 12;
260                     for (j = 11; j >= 0; j--) {
261                         if (nameexecution[j] == ' ' || nameexecution[j] == 0) {
262                             nameexecution[j] = 0;
263                             widthexec--;
264                         } else
265                             break;
266                     }
267                     for (j = 0; j < (static_cast<int> (an)); j++) {
268                         if (strcmp(nameprojection, ""))
269                             itname.sprintf("%-*s_%-*s_%s_%04d_r_a", widthproj, nameprojection, widthexec, nameexecution, namealg, j + 1);
270                         else
271                             itname.sprintf("__%-*s_%4s_%04d_r_a", widthexec, nameexecution, namealg, j + 1);
272                         snprintf(imagetitles[ni], sizeof(imagetitles[ni])-1, "%s", itname.latin1());
273                         imageindexes[ni][0] = i;
274                         imageindexes[ni][1] = j;
275                         ni++;
276                     }
277                 }
278             } // --for on asn
279             allocSnarkimages(numimages);
280             allocDisplaywindows(numimages);
281             if (openrecfil) {
282                 if (myOpenImagesWinP) {
283                     myOpenImagesWinP->setImagesNames();
284                 }
285             } else
286                 openrecfil = true;
287         }
288     }
289 } //--SnarkDisplay::openRecfilFile()
290
291 /** Starts a window for selecting images to be shown
292 @param void
293 @author Bruno M. Carvalho
294 @version 1.0 */
295 void SnarkDisplay::callOpenImages() {
296     QPoint topleft;
297     topleft = this->pos();
298     if (!openrecfil) {
299         QMessageBox::information(this, "SnarkDisplay", "Error!\n"
300                 "No recfil file is open.");
301     } else {
302         //  noiw=new openimageswindow(desk,"Open Images",false,0,topleft.x()+30,topleft.y()+30);
303         if (!myOpenImagesWinP) {
304             myOpenImagesWinP = new openimageswindow(displaywindowset, desk, "Open Images", false, 0, topleft.x() + 30, topleft.y() + 30);
305             //      myOpenImagesWinP = new openimageswindow(displaywindowset,this,"Open Images",false,0,topleft.x()+30,topleft.y()+30);
306         }
307         myOpenImagesWinP->hide(); // hack to give focus, setFocus() didn't work
308         myOpenImagesWinP->show();
309     }
310 } // --SnarkDisplay::callOpenImages()
311
312 /** Starts a lines window
313 @param void
314 @author Bruno M. Carvalho, deniz
315 @version 1.4
316 @comments majorly shortened due to new (Deniz'04) classes
317  */
318 void SnarkDisplay::callLines() {
319     if (std::verbose >= 2) {
320         std::cout << "++SnarkDisplay::callLines()" << std::endl;
321     }
322     int l[4];
323     int linetype, c, i, j, k, minx, maxx;
324     int *siarray;
325     int topleftx, toplefty;
326     double **img;
327     double miny, maxy;
328     QString title, xaxis, yaxis, temp;
329     QFont f;
330     QPoint topleft;
331     if (!openrecfil)
332         QMessageBox::information(this, "SnarkDisplay", "Error!\n"
333             "No recfil file is open.");
334     else {
335         if (!imageset[0]->isLoaded())
336             imageset[0]->readImage(0, dataformat);
337         linesimageswindow* nw = new linesimageswindow(this, "Multiple Images' Lines", true);
338         c = nw->exec();
339         if (c == QDialog::Accepted) {
340             linetype = nw->getLinetype(); // row or column.  0 for row, 1 for column.
341             l[0] = nw->getLine1();
342             l[1] = nw->getLine2();
343             l[2] = nw->getLine3();
344             l[3] = nw->getLine4();
345             title = ((nw->getTitle()).simplifyWhiteSpace());
346             xaxis = nw->getXAxis();
347             yaxis = nw->getYAxis();
348             minx = nw->getMinX();
349             maxx = nw->getMaxX();
350             miny = nw->getMinY();
351             maxy = nw->getMaxY();
352             topleft = this->pos();
353             topleftx = topleft.x();
354             toplefty = topleft.y();
355             siarray = nw->getSelectedImages();
356             // (linetype==0) ==> show for suchandsuch row(s) all column values based on xrange
357             // (linetype==1) ==> show for suchandsuch col(s) all row    values based on xrange
358             QString rowOrColumn = ((linetype) ? ("Column ") : ("Row "));
359             QString vs = ((linetype) ? ("Rows") : ("Columns"));
360             for (k = 1; k <= siarray[0]; k++) {
361                 if (!imageset[siarray[k]]->isLoaded())
362                     imageset[siarray[k]]->readImage(k, DIGDataFormat_ASCII);
363             }
364             // j is index for user-selected (keyed in) rows or columns
365             for (j = 0; j < 4; j++) {
366                 // l[j] is the user-selected (keyed in) row or column "at position j"
367                 if (l[j] >= 0 && l[j] < Sizex) { // plot only if within range.
368                     line_real_set_t myLRS(minx, maxx, miny, maxy); // create a brand new LRS for brand new plot
369                     myLRS.clear(); // and be sure of it!
370                     QString whichRowOrCol;
371                     whichRowOrCol.setNum(l[j]);
372                     QString plotName = title.simplifyWhiteSpace();
373 //                    plotName += " ::multiple images':: ";
374                     plotName += " :: ";
375                     plotName += (rowOrColumn + whichRowOrCol);
376                     topleftx += 30;
377                     toplefty += 30;
378                     QPainter picasso;
379                     QPixmap* pmp = new QPixmap(sd_line_t::WIDTH, sd_line_t::HEIGHT);
380                     pmp->fill(Qt::white);
381                     picasso.begin(pmp);
382                     picasso.setBackgroundColor(Qt::white);
383                     for (k = 1; k <= siarray[0]; k++) { // k is array index for the image within recfil
384                         QString LRName = imagetitles[siarray[k]]; // something like "brainscan_ART_iter_5"
385                         line_real_t myLR(LRName);
386                         if (!(imageset[siarray[k]]->isLoaded())) {
387                             imageset[siarray[k]]->readImage(k, DIGDataFormat_ASCII);
388                         }
389                         img = imageset[siarray[k]]->getImage();
390                         int& row = ((linetype) ? (i) : (l[j])); // not assignment, but rather, unification.
391                         int& col = ((linetype) ? (l[j]) : (i)); // (linetype==1) means l[j] is col, else l[j] is row
392                         for (i = 0; i < Sizey; i++) { // recfils are Sizey by Sizey
393                             myLR.add(i, img[row][col]); // x is independent i, y is dependent img[row][col]
394                         }
395                         myLRS.add(myLR); // add my LineReal due to selected row/col in this (k) image to my LRS
396                     } // --for each image k (plot all of them on the same thing.)
397                     plot_t myPlot(myLRS); // plot myLRS due to single selection of row/col (up to 4)
398                     myPlot.setName(plotName);
399                     myPlot.setXAxisName(xaxis);
400                     myPlot.setYAxisName(yaxis);
401                     // jk 1/13/2009 adding grayScale option for graphs
402                     if (nw->isGrayScaleChecked()) { // picasso paints on QPixmap pointed to by pmp
403                         myPlot.plotGray(picasso);
404                     } else {
405                         myPlot.plot(picasso);
406                     }
407
408                     if (toplefty > (maxSizey - 100))
409                         toplefty = 30;
410                     // spawn a display for each row/col plot, each plot potentially due to many images
411                     displaylineswindow* nieuwDLWp = new displaylineswindow(desk, plotName, pmp, false, 0, topleftx, toplefty);
412                     nieuwDLWp->show();
413                 } // --if of chosen row or column being within the appropriate range (i think)
414             } // --for each chosen row or column (max. 4 of them)
415         } // --"if" of Accepted QDialog
416     } // --"else" of "no recfil is open"
417 } // --SnarkDisplay::callLines()
418
419 /** Starts a range window
420 @param void
421 @author Bruno M. Carvalho
422 @version 1.0 */
423 void SnarkDisplay::callRange() {
424     bool imageopened = false;
425     int i;
426     if (!openrecfil)
427         QMessageBox::information(desk, "SnarkDisplay", "Error!\n"
428             "No recfil file is open.");
429     else {
430         for (i = 0; i < numimages; i++) {
431             if (displaywindowactive[i]) {
432                 imageopened = true;
433             }
434         }
435         if (imageopened) {
436             //      rangewindow* nw=new rangewindow(this,"Set Range",false,Qt::WType_TopLevel);
437             if (myRangeWinP) {
438                 myRangeWinP->closeWindow();
439                 myRangeWinP = 0;
440             }
441             myRangeWinP = new rangewindow(this, "Set Range", false, Qt::WType_TopLevel);
442             myRangeWinP->show();
443         } else
444             QMessageBox::information(desk, "SnarkDisplay", "Error!\n"
445                 "No image is open.");
446     }
447 } // --SnarkDisplay::callRange()
448
449 /** Calls file dialog and opens PROJECTION file
450     @param void
451     @author Bruno M. Carvalho
452     @version 1.0 */
453 void SnarkDisplay::openPrjfilFile() {
454     QString projfilfilename, s;
455     QPoint topleft;
456     //  const DIGDimensions* Dimensions;
457     char name[256];
458
459     QFileDialog fd(QString::null, "Projfil files (*prjfil*)\n All files (*)", this, "Open Prjfil File", TRUE);
460     fd.setCaption("Open Projfil File");
461     fd.setSelection(QDir::currentDirPath());
462     if (fd.exec() == QDialog::Accepted) {
463         projfilfilename = fd.selectedFile();
464         snprintf(name, sizeof(name)-1, "%s", projfilfilename.latin1());
465         if (openprojfil) //*(JD 1/28/04)
466             digprojfil.Close(); //(JD 1/28/04)
467         if (digprojfil.Open(name) != 0) {
468             s.sprintf("Error!\nUnable to open file:\n%s\nMaybe it is not a snark14 prjfil file!", projfilfilename.latin1());
469             QMessageBox::information(this, "SnarkDisplay", s);
470         } else {
471             //      digprojfil.GetDataFormat(&projformat);
472             projname = (const char *) malloc(sizeof (const char) *81);
473             digprojfil.GetTitle(&projname);
474             //      digprojfil.GetNoOfArraySets(&prjnum);
475             digprojfil.GetNoOfProjs(&prjnum);
476             //      digprojfil.GetDimensions(&Dimensions);
477             //      usrays = Dimensions->x;
478             digprojfil.GetDimensions(&usrays);
479             projfil = new Snarkproj();
480             // open prjfil in displaywindow
481             topleft = this->pos();
482             projwin = new displayprojection(desk, projname, false, 0, topleft.x(), topleft.y());
483             projwin->show();
484             projwin->resetscroll();
485         }
486         digprojfil.Open(name);
487         openprojfil = true; //*(JD 1/28/04)
488     }
489 }
490
491 /** Calls file dialog and opens eval file, throwing all information into global myEES
492 @param void
493 @author Bruno M. Carvalho for version 1.0, Deniz Sarioz after
494 @version 2.0 */
495 void SnarkDisplay::openEvalFile() {
496     // myEES stands for "my eval_execution_set" defined in variables.h
497     // eval_execution_set is defined in eval_helper.hpp and fleshed out in eval_helper.cpp
498     myEES.clear(); // just in case
499     // opening new eval file: get rid of ALL previous eval-related information
500     QString evalfilename, s;
501     FILE *fp;
502     const unsigned maxlinelength = 512;
503     const unsigned maxnamelength = 512;
504     char line[maxlinelength]; // buffer for reading in lines
505     char name[maxnamelength]; // buffer for reading in name
506     memset(&(line[0]), 0, maxlinelength); // init line with null terminator
507     memset(&(name[0]), 0, maxnamelength); // init name with null terminator
508     int tmpint; // complete dummy
509     QFileDialog fd(QString::null, "Eval files (*eval*)\n All files (*)", this, "Open Eval File", TRUE);
510     fd.setCaption("Open Eval File");
511     fd.setSelection(QDir::currentDirPath());
512     if (fd.exec() == QDialog::Accepted) {
513         evalfilename = fd.selectedFile();
514         snprintf(name, sizeof(name)-1, "%s", evalfilename.latin1());
515         if (std::verbose >= 2) printf("\nname of eval file is:\n%s\n", name);
516         if ((fp = fopen(name, "r")) == NULL) {
517             s.sprintf("Error!\nUnable to open file:\n%s\n", evalfilename.latin1());
518             QMessageBox::information(this, "SnarkDisplay", s);
519         } else {
520
521             enum status_t {
522                 JUSTBEGAN, NEWEVALUATE, GLOBAL, POINT
523             };
524             status_t status = JUSTBEGAN;
525
526             /* if end in JUSTBEGAN or NEWEVALUATE, raise red flag
527              *  graph of possible status transitions
528              *                             ____________
529              *                            /            \
530              *                            |            |
531              *                            V            |
532              * JUSTBEGAN ---------> NEWEVALUATE ---> POINT
533              *                      |  ^               ^
534              *                      |  |               |
535              *                      V  |               |
536              *                      GLOBAL-------------/
537              */
538             enum global_status_t {
539                 GLOBEGAN, TOREADPHAN, TOREADGLOB
540             };
541             // this is assigned based on the string parsed
542             global_status_t globalstatus = GLOBEGAN;
543             bool ADD_POINTMEAS = false;
544             typedef char* inputline_t;
545             inputline_t myline;
546             measline_t mymeasline;
547             execname_t myexecname;
548             bool ignoredonce = false;
549             myline = (&(line[0])); // myline permanently points to line[0]
550             mymeasline = (&(line[0]));
551             myexecname = (&(line[0]));
552             while (fgets(line, maxlinelength, fp)) {
553                 ////    if(isspace(mymeasline)) continue;
554                 char *p;
555                 p = myline;
556                 while ((' ' == *p) || ('\t' == *p)) p++;
557                 if (('\n' == *p) || ('\r' == *p) || ('\0' == *p)) continue;
558                 switch (status) {
559                     case JUSTBEGAN:
560                         // first line does not have to start with evaluation name: allow comments
561                         if (strstr(myline, "evaluation name:")) {
562                             status = NEWEVALUATE;
563                             try {
564                                 myEES.new_exec(myexecname); // READ IN evaluation name!
565                             } catch (std::exception &e) {
566                                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
567                             }
568                         } else {
569                             if (!ignoredonce) {
570                                 std::cout << "stuff in eval file before first 'evaluation name:' ignored!!!" << std::endl;
571                                 ignoredonce = true;
572                             }
573                         }
574                         break; // the switch, not the while
575                     case NEWEVALUATE:
576                         if (strstr(myline, "global resolution measures")) {
577                             status = GLOBAL;
578                         } else {
579                             if (strstr(myline, "point by point resolution measures")) {
580                                 status = POINT;
581                             }
582                         }
583                         break; // out of switch
584                     case GLOBAL:
585                         if (strstr(myline, "evaluation name:")) { // can happen at any time
586                             globalstatus = GLOBEGAN;
587                             status = NEWEVALUATE;
588                             try {
589                                 myEES.new_exec(myexecname); // READ IN evaluation name!
590                             } catch (std::exception &e) {
591                                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
592                             }
593                         } else {
594                             switch (globalstatus) {
595                                 case GLOBEGAN:
596                                     if (strstr(myline, "hantom name")) {
597                                         // read the name of phantom! (necessary?)
598                                     } else if (strstr(myline, "etrics for test phantom")) {
599                                         globalstatus = TOREADPHAN;
600                                     }
601                                     break; // out of inner switch
602                                 case TOREADPHAN: // read exactly one line of phantom data
603                                     if (sscanf(myline, "%d", &tmpint) == 1) { // if line starts with an integer
604                                         try {
605                                             myEES.set_phantomeas(mymeasline);
606                                         } catch (std::exception &e) {
607                                             std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
608                                         }
609                                         globalstatus = TOREADGLOB; // next, should try to read an execution
610                                     }
611                                     break; // out of inner switch
612                                 case TOREADGLOB:
613                                     if (sscanf(myline, "%d", &tmpint) == 1) {
614                                         try {
615                                             myEES.add_to_globmeaset(mymeasline);
616                                         } catch (std::exception &e) {
617                                             std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
618                                         }
619                                     } else if (strstr(myline, "execution name")) {
620                                         // parse in execution name (necessary?)
621                                         try {
622                                             myEES.new_globmeaset(myexecname);
623                                         } catch (std::exception &e) {
624                                             std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
625                                         }
626                                     } else if (strstr(myline, "etrics for algorithm")) {
627                                         // parse in ALGO name! (maybe?)
628                                     } else if (strstr(myline, "point by point resolution measures")) {
629                                         globalstatus = GLOBEGAN;
630                                         status = POINT;
631                                     }
632                                     break; // out of inner switch (optional here, defensive)
633                             }
634                         } // else
635                         break; // out of switch
636                     case POINT:
637                         if (strstr(myline, "evaluation name")) {
638                             // parse evaluation name!
639                             ADD_POINTMEAS = false;
640                             status = NEWEVALUATE;
641                             try {
642                                 myEES.new_exec(myexecname); // READ IN evaluation name!
643                             } catch (std::exception &e) {
644                                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
645                             }
646                         } else if (strstr(myline, "execution name")) {
647                             ADD_POINTMEAS = false;
648                             try {
649                                 myEES.new_PBPmeaset(myexecname); // name gets assigned as we go along, but still parse in name
650                             } catch (std::exception &e) {
651                                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
652                             }
653                         } else if (strstr(myline, "algn")) { // need a line with this
654                             ADD_POINTMEAS = true;
655                         } else if (ADD_POINTMEAS) {
656                             // NOW we can go ahead with this, since whitespace-lines are skipped
657                             try {
658                                 myEES.add_to_PBPmeaset(mymeasline);
659                             } catch (std::exception &e) {
660                                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
661                             }
662                         }
663                         break; // out of switch (optional here, defensive)
664                 } // status switch
665                 memset(myline, 0, maxlinelength); // reinit line to null terminator
666             } // while can keep reading lines
667             if ((status == JUSTBEGAN) || (status == NEWEVALUATE)) {
668                 //maybe throw std::runtime_error("malformed eval file: no measurements");
669                 std::cerr << "malformed eval file: no measurements... please open a valid eval file." << std::endl;
670                 myEES.clear();
671                 return;
672             }
673             try {
674                 myEES.complete();
675             } catch (std::exception &e) {
676                 std::cerr << "This badness happened:" << std::endl << e.what() << std::endl;
677                 myEES.clear();
678                 return;
679             }
680             /// Call Eval Window
681             //   new version: first, user should select executions!
682             QPoint topleft;
683             topleft = this->pos();
684             selectEvalExecutionsWindow* selectEvalExecsWin;
685             selectEvalExecsWin = new selectEvalExecutionsWindow(desk, "Open Evaluate Executions", false, 0, topleft.x() + 30, topleft.y() + 30);
686             selectEvalExecsWin->show();
687         } // --if was able to open the file ("else" of failure, failure already handled)
688     } // --if QDialog accepted
689     // else?
690 } // --SnarkDisplay::openEvalFile()
691
692 /** Updates low and high thresholds for image windows having the button Global Thresholds checked
693 @param void
694 @author Bruno M. Carvalho
695 @version 1.0 */
696 void SnarkDisplay::updateGlobalThreshs() {
697     // the new way: do it for all of them!
698     for (int i = 0; i < numimages; i++)
699         if (imageset[i]->isLoaded() && displaywindowset[i]) {
700             displaywindowset[i]->setGlobalthreshs();
701         }
702 }
703
704 /** tells all windows to be activated by the global thresholds
705 @param void
706 @author Bruno M. Carvalho
707 @version 1.0 */
708 void SnarkDisplay::signalAllGlobals(bool on) {
709     allglobal = on;
710     if (myRangeWinP) {
711         myRangeWinP->signalAllGlobals(allglobal);
712     }
713     for (int i = 0; i < numimages; i++) {
714         if (alldifference && (i == 0)) continue;
715         if (imageset[i]->isLoaded() && displaywindowset[i]) {
716             displaywindowset[i]->setGlobal(on);
717         }
718     }
719     updateGlobalThreshs(); // refresh immediately
720 }
721
722 void SnarkDisplay::signalAllDifference(bool on) {
723     alldifference = on;
724     if (myRangeWinP) {
725         myRangeWinP->signalAllDifference(alldifference);
726     }
727     if (allglobal) {
728         if (imageset[0]->isLoaded() && displaywindowset[0]) {
729             if (alldifference) {
730                 displaywindowset[0]->setGlobal(false);
731             } else {
732                 displaywindowset[0]->setGlobal(true);
733             }
734         }
735     }
736     for (int i = 1; i < numimages; i++) {
737         if (imageset[i]->isLoaded() && displaywindowset[i]) {
738             displaywindowset[i]->setDifference(on);
739         }
740     }
741 }
742
743 void SnarkDisplay::signalAllIntensity(bool on) {
744     for (int i = 0; i < numimages; i++) {
745         if (displaywindowset[i]) {
746             displaywindowset[i]->setIntensity(on);
747         }
748     }
749 }
750
751 /** Calls about window
752 @param void
753 @author Bruno M. Carvalho & Deniz Sarioz
754 @version 2.0 */
755 void SnarkDisplay::about() {
756     QMessageBox::information(this, "snark14Display",
757             "snark14Display was developed by\n"
758             "Bruno M. Carvalho and Deniz Sarioz\n"
759             "2003--2008\n"
760             "copyright (QPL) by CUNY-GC-CS-DIG\n"
761             "http://www.dig.cs.gc.cuny.edu");
762 }
763
764 /** Allocates space for a vector of Snarkimages
765 @param ni number of images
766 @author Bruno M. Carvalho
767 @version 1.0 */
768 void SnarkDisplay::allocSnarkimages(int ni) {
769     int i;
770     imageset = (Snarkimage **) malloc((unsigned) (ni) * sizeof (Snarkimage*));
771     if (!imageset) {
772         QMessageBox::information(this, "SnarkDisplay", "Error!\n"
773                 "Allocation failure in allocSnarkimages()\n");
774     } else {
775         for (i = 0; i < ni; i++) {
776             imageset[i] = new Snarkimage();
777             if (!imageset[i]) {
778                 QMessageBox::information(this, "SnarkDisplay", "Error!\n"
779                         "Allocation failure in allocSnarkimages()\n");
780             }
781         }
782     }
783 }
784
785 /** Allocates space for a vector of displaywindow POINTERS
786 @param ni number of images
787 @author Bruno M. Carvalho
788 @version 1.0 */
789 void SnarkDisplay::allocDisplaywindows(int ni) {
790     allglobal = false;
791     alldifference = false;
792     globalmax = globaldiffmax = -100000;
793     globalmin = globaldiffmin = 100000;
794     // forget everything we did before!
795     if (ni == 0) return;
796     //  displaywindowset = (displaywindow **) malloc((unsigned) (ni)*sizeof(displaywindow*));
797     displaywindowset = new displaywindow* [ni];
798     if (!displaywindowset) {
799         QMessageBox::information(this, "SnarkDisplay", "Error!\n"
800                 "Allocation failure in allocDisplaywindows()\n");
801     }
802     displaywindowactive = (bool *) malloc((unsigned) (ni) * sizeof (bool));
803     for (int i = 0; i < ni; i++) {
804         displaywindowactive[i] = false;
805         displaywindowset[i] = 0; // NULL
806     }
807 }
808
809 /** Frees space of a vector of Snarkimages
810 @param ni number of images
811 @author Bruno M. Carvalho
812 @version 1.0 */
813 void SnarkDisplay::freeSnarkimages(int ni) {
814     int i;
815
816     if (imageset) {
817         for (i = 0; i < ni; i++) {
818             if (imageset[i]) {
819                 imageset[i]->~Snarkimage();
820                 imageset[i] = 0;
821             }
822         }
823         free(imageset);
824     }
825 } // --SnarkDisplay::freeSnarkimages()
826
827 /** Frees space of a vector of Displaywindows
828 @param void
829 @author Bruno M. Carvalho
830 @version 1.0 */
831 void SnarkDisplay::freeDisplaywindows(int ni) {
832     int i;
833     if (displaywindowset) {
834         for (i = 0; i < ni; i++) {
835             if (displaywindowset[i]) {
836                 delete displaywindowset[i];
837             }
838         }
839         delete [] displaywindowset;
840     }
841 } // --SnarkDisplay::freeDisplaywindows()
842
843 /** Starts the application
844 @param void
845 @author Bruno M. Carvalho, parametrized by deniz
846 @version 1.2 */
847 int main(int argc, char* argv[]) {
848     QApplication snarkapp(argc, argv);
849
850     if (argc == 3) {
851         int wid = atoi(argv[1]);
852         int hei = atoi(argv[2]);
853         int minwid = 3 * sd_line_t::XWINPAD;
854         int minhei = 3 * sd_line_t::YWINPAD;
855         if ((wid >= minwid) && (hei >= minhei)) {
856             std::cout << "For plots, accepted window WIDTH=" << wid << ", HEIGHT=" << hei << std::endl;
857             sd_line_t::WIDTH = wid;
858             sd_line_t::HEIGHT = hei;
859         } else {
860             std::cout << "Minimum width: " << minwid << ", minimum height: " << minhei << std::endl;
861             std::cout << "Aborting " << argv[0] << std::endl;
862             return 1;
863         }
864     }
865     //  SnarkDisplay* mw=new SnarkDisplay();
866     SnarkDisplay mw;
867     //  snarkapp.setMainWidget(mw);
868     snarkapp.setMainWidget(&mw);
869     //  mw->show();
870     mw.show();
871
872     return snarkapp.exec();
873 } // --main()