PageRenderTime 133ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.10/extensions/src/medm3_1_4/medm/SciPlot.c

http://atf2flightsim.googlecode.com/
C | 2367 lines | 2009 code | 254 blank | 104 comment | 263 complexity | 3feafe23b91cab39f429457029134f13 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*----------------------------------------------------------------------------
  2. * SciPlot A generalized plotting widget
  3. *
  4. * Copyright (c) 1996 Robert W. McMullen
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public
  17. * License along with this library; if not, write to the Free
  18. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. *
  20. *
  21. * Author: Rob McMullen <rwmcm@mail.ae.utexas.edu>
  22. * http://www.ae.utexas.edu/~rwmcm
  23. */
  24. #define DEBUG_SCIPLOT 0
  25. #define DEBUG_SCIPLOT_VTEXT 0
  26. #define DEBUG_SCIPLOT_TEXT 0
  27. #define DEBUG_SCIPLOT_LINE 0
  28. #define DEBUG_SCIPLOT_AXIS 0
  29. #define DEBUG_SCIPLOT_ALLOC 0
  30. #define DEBUG_SCIPLOT_MLK 0
  31. /* KE: Use SCIPLOT_EPS to avoid roundoff in floor and ceil */
  32. #define SCIPLOT_EPS .0001
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include <X11/IntrinsicP.h>
  37. #include <X11/StringDefs.h>
  38. #ifdef MOTIF
  39. #include <Xm/Xm.h>
  40. #endif
  41. #ifdef _MSC_VER
  42. /* Eliminate Microsoft C++ warnings about converting to float */
  43. #pragma warning (disable: 4244 4305)
  44. #endif
  45. #ifdef WIN32
  46. /* Hummingbird extra functions including lprintf
  47. * Needs to be included after Intrinsic.h for Exceed 5 */
  48. # include <X11/XlibXtra.h>
  49. /* The following is done in Exceed 6 but not in Exceed 5
  50. * Need it to define printf as lprintf for Windows
  51. * (as opposed to Console) apps */
  52. # ifdef _WINDOWS
  53. # ifndef printf
  54. # define printf lprintf
  55. # endif
  56. # endif
  57. #endif /* #ifdef WIN32 */
  58. #include "SciPlotP.h"
  59. enum sci_drag_states {NOT_DRAGGING,
  60. DRAGGING_NOTHING,
  61. DRAGGING_TOP, DRAGGING_BOTTOM,
  62. DRAGGING_BOTTOM_AND_LEFT,
  63. DRAGGING_LEFT, DRAGGING_RIGHT, DRAGGING_DATA
  64. };
  65. enum sci_draw_axis_type {DRAW_ALL,
  66. DRAW_AXIS_ONLY,
  67. DRAW_NO_LABELS
  68. };
  69. #define SCIPLOT_ZOOM_FACTOR 0.25
  70. #define offset(field) XtOffsetOf(SciPlotRec, plot.field)
  71. static XtResource resources[] =
  72. {
  73. {XtNchartType, XtCMargin, XtRInt, sizeof(int),
  74. offset(ChartType), XtRImmediate, (XtPointer) XtCARTESIAN},
  75. {XtNdegrees, XtCBoolean, XtRBoolean, sizeof(Boolean),
  76. offset(Degrees), XtRImmediate, (XtPointer) True},
  77. {XtNdrawMajor, XtCBoolean, XtRBoolean, sizeof(Boolean),
  78. offset(DrawMajor), XtRImmediate, (XtPointer) True},
  79. {XtNdrawMajorTics, XtCBoolean, XtRBoolean, sizeof(Boolean),
  80. offset(DrawMajorTics), XtRImmediate, (XtPointer) True},
  81. {XtNdrawMinor, XtCBoolean, XtRBoolean, sizeof(Boolean),
  82. offset(DrawMinor), XtRImmediate, (XtPointer) True},
  83. {XtNdrawMinorTics, XtCBoolean, XtRBoolean, sizeof(Boolean),
  84. offset(DrawMinorTics), XtRImmediate, (XtPointer) True},
  85. {XtNmonochrome, XtCBoolean, XtRBoolean, sizeof(Boolean),
  86. offset(Monochrome), XtRImmediate, (XtPointer) False},
  87. {XtNshowLegend, XtCBoolean, XtRBoolean, sizeof(Boolean),
  88. offset(ShowLegend), XtRImmediate, (XtPointer) True},
  89. {XtNshowTitle, XtCBoolean, XtRBoolean, sizeof(Boolean),
  90. offset(ShowTitle), XtRImmediate, (XtPointer) True},
  91. {XtNshowXLabel, XtCBoolean, XtRBoolean, sizeof(Boolean),
  92. offset(ShowXLabel), XtRImmediate, (XtPointer) True},
  93. {XtNshowYLabel, XtCBoolean, XtRBoolean, sizeof(Boolean),
  94. offset(ShowYLabel), XtRImmediate, (XtPointer) True},
  95. {XtNxLabel, XtCString, XtRString, sizeof(String),
  96. offset(TransientXLabel), XtRString, "X Axis"},
  97. {XtNyLabel, XtCString, XtRString, sizeof(String),
  98. offset(TransientYLabel), XtRString, "Y Axis"},
  99. {XtNplotTitle, XtCString, XtRString, sizeof(String),
  100. offset(TransientPlotTitle), XtRString, "Plot"},
  101. {XtNmargin, XtCMargin, XtRInt, sizeof(int),
  102. offset(Margin), XtRImmediate, (XtPointer) 5},
  103. {XtNtitleMargin, XtCMargin, XtRInt, sizeof(int),
  104. offset(TitleMargin), XtRImmediate, (XtPointer) 16},
  105. {XtNlegendLineSize, XtCMargin, XtRInt, sizeof(int),
  106. offset(LegendLineSize), XtRImmediate, (XtPointer) 16},
  107. {XtNdefaultMarkerSize, XtCMargin, XtRInt, sizeof(int),
  108. offset(DefaultMarkerSize), XtRImmediate, (XtPointer) 3},
  109. {XtNlegendMargin, XtCMargin, XtRInt, sizeof(int),
  110. offset(LegendMargin), XtRImmediate, (XtPointer) 3},
  111. {XtNlegendThroughPlot, XtCBoolean, XtRBoolean, sizeof(Boolean),
  112. offset(LegendThroughPlot), XtRImmediate, (XtPointer) False},
  113. {XtNtitleFont, XtCMargin, XtRInt, sizeof(int),
  114. offset(TitleFont), XtRImmediate, (XtPointer) (XtFONT_HELVETICA | 24)},
  115. {XtNlabelFont, XtCMargin, XtRInt, sizeof(int),
  116. offset(LabelFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 18)},
  117. {XtNaxisFont, XtCMargin, XtRInt, sizeof(int),
  118. offset(AxisFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 10)},
  119. {XtNxAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean),
  120. offset(XAutoScale), XtRImmediate, (XtPointer) True},
  121. {XtNyAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean),
  122. offset(YAutoScale), XtRImmediate, (XtPointer) True},
  123. {XtNxAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean),
  124. offset(XAxisNumbers), XtRImmediate, (XtPointer) True},
  125. {XtNyAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean),
  126. offset(YAxisNumbers), XtRImmediate, (XtPointer) True},
  127. {XtNxLog, XtCBoolean, XtRBoolean, sizeof(Boolean),
  128. offset(XLog), XtRImmediate, (XtPointer) False},
  129. {XtNyLog, XtCBoolean, XtRBoolean, sizeof(Boolean),
  130. offset(YLog), XtRImmediate, (XtPointer) False},
  131. {XtNxOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean),
  132. offset(XOrigin), XtRImmediate, (XtPointer) False},
  133. {XtNyOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean),
  134. offset(YOrigin), XtRImmediate, (XtPointer) False},
  135. {XtNyNumbersHorizontal, XtCBoolean, XtRBoolean, sizeof(Boolean),
  136. offset(YNumHorz), XtRImmediate, (XtPointer) True},
  137. {XtNdragX, XtCBoolean, XtRBoolean, sizeof(Boolean),
  138. offset(DragX), XtRImmediate, (XtPointer) True},
  139. {XtNdragY, XtCBoolean, XtRBoolean, sizeof(Boolean),
  140. offset(DragY), XtRImmediate, (XtPointer) False},
  141. {XtNtrackPointer, XtCBoolean, XtRBoolean, sizeof(Boolean),
  142. offset(TrackPointer), XtRImmediate, (XtPointer) False},
  143. {XtNxNoCompMinMax, XtCBoolean, XtRBoolean, sizeof(Boolean),
  144. offset(XNoCompMinMax), XtRImmediate, (XtPointer) False},
  145. {XtNdragXCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  146. offset(drag_x_callback), XtRCallback, NULL},
  147. {XtNdragYCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  148. offset(drag_y_callback), XtRCallback, NULL},
  149. {XtNpointerValCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  150. offset(pointer_val_callback), XtRCallback, NULL},
  151. {XtNbtn1ClickCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  152. offset(btn1_callback), XtRCallback, NULL},
  153. {XtNxFixedLeftRight, XtCBoolean, XtRBoolean, sizeof(Boolean),
  154. offset(XFixedLR), XtRImmediate, (XtPointer) False},
  155. {XtNxLeftSpace, XtCMargin, XtRInt, sizeof(int),
  156. offset(XLeftSpace), XtRImmediate, (XtPointer) (100)},
  157. {XtNxRightSpace, XtCMargin, XtRInt, sizeof(int),
  158. offset(XRightSpace), XtRImmediate, (XtPointer) (100)},
  159. /* KE: (From XmFrame.c) */
  160. #ifdef MOTIF
  161. {XmNshadowType, XmCShadowType, XmRShadowType, sizeof(unsigned char),
  162. offset(ShadowType), XmRImmediate, (XtPointer)XmINVALID_DIMENSION},
  163. #endif
  164. };
  165. static SciPlotFontDesc font_desc_table[] =
  166. {
  167. {XtFONT_TIMES, "Times", "times", False, True},
  168. {XtFONT_COURIER, "Courier", "courier", True, False},
  169. {XtFONT_HELVETICA, "Helvetica", "helvetica", True, False},
  170. {XtFONT_LUCIDA, "Lucida", "lucidabright", False, False},
  171. {XtFONT_LUCIDASANS, "LucidaSans", "lucida", False, False},
  172. {XtFONT_NCSCHOOLBOOK, "NewCenturySchlbk",
  173. "new century schoolbook", False, True},
  174. {-1, NULL, NULL, False, False},
  175. };
  176. /*
  177. * Private function declarations
  178. */
  179. static void Redisplay (Widget w, XEvent *event, Region region);
  180. static void Resize (Widget w);
  181. static Boolean SetValues (Widget current,
  182. Widget request, Widget new,
  183. ArgList args, Cardinal *nargs);
  184. static void GetValuesHook (Widget w, ArgList args,
  185. Cardinal *num_args);
  186. static void Initialize (Widget treq, Widget tnew,
  187. ArgList args, Cardinal *num);
  188. static void Realize (Widget aw, XtValueMask * value_mask,
  189. XSetWindowAttributes * attributes);
  190. static void Destroy (Widget w);
  191. static void ComputeAll (SciPlotWidget w, int type);
  192. static void ComputeAllDimensions (SciPlotWidget w, int type);
  193. static void DrawAll (SciPlotWidget w);
  194. static void ItemDrawAll (SciPlotWidget w);
  195. static void ItemDraw (SciPlotWidget w, SciPlotItem *item);
  196. static void EraseAll (SciPlotWidget w);
  197. static void FontInit (SciPlotWidget w, SciPlotFont *pf);
  198. static int ColorStore (SciPlotWidget w, Pixel color);
  199. static int FontStore (SciPlotWidget w, int flag);
  200. static int FontnumReplace (SciPlotWidget w, int fontnum, int flag);
  201. static void SciPlotPrintf(const char *fmt, ...);
  202. /* translation manager routines */
  203. static void sciPlotMotionAP (SciPlotWidget w,
  204. XEvent *event, char *args, int n_args);
  205. static void sciPlotBtnUpAP (SciPlotWidget w,
  206. XEvent *event, char *args, int n_args);
  207. static void sciPlotClick (SciPlotWidget w,
  208. XEvent *event, char *args, int n_args);
  209. static void sciPlotTrackPointer (SciPlotWidget w,
  210. XEvent *event, char *args, int n_args);
  211. /* KE: */
  212. #ifdef MOTIF
  213. static void DrawShadow (SciPlotWidget w, Boolean raised, real x, real y,
  214. real width, real height);
  215. #endif
  216. static char sciPlotTranslations[] =
  217. #ifndef _MEDM
  218. "<Btn2Motion>: Motion()\n\
  219. <Btn2Down>: Motion()\n\
  220. <Btn2Up>: BtnUp()\n\
  221. <Btn1Up>: Btn1Up()\n\
  222. <Motion>: TrackPointer()";
  223. #else
  224. "Shift<Btn1Motion>: Motion()\n\
  225. Shift<Btn2Motion>: Motion()\n\
  226. Shift<Btn1Down>: Motion()\n\
  227. Shift<Btn1Up>: BtnUp()\n\
  228. Shift<Btn2Down>: Motion()\n\
  229. Shift<Btn2Up>: BtnUp()\n\
  230. <Btn1Up>: Btn1Up()\n\
  231. <Motion>: TrackPointer()";
  232. #endif
  233. static XtActionsRec sciPlotActionsList[] = {
  234. {"Motion", (XtActionProc)sciPlotMotionAP},
  235. {"BtnUp", (XtActionProc)sciPlotBtnUpAP},
  236. {"Btn1Up", (XtActionProc)sciPlotClick},
  237. {"TrackPointer", (XtActionProc)sciPlotTrackPointer}
  238. };
  239. SciPlotClassRec sciplotClassRec =
  240. {
  241. {
  242. /* core_class fields */
  243. #ifdef MOTIF
  244. /* superclass */ (WidgetClass) & xmPrimitiveClassRec,
  245. #else
  246. /* superclass */ (WidgetClass) & widgetClassRec,
  247. #endif
  248. /* class_name */ "SciPlot",
  249. /* widget_size */ sizeof(SciPlotRec),
  250. /* class_initialize */ NULL,
  251. /* class_part_initialize */ NULL,
  252. /* class_inited */ False,
  253. /* initialize */ Initialize,
  254. /* initialize_hook */ NULL,
  255. /* realize */ Realize,
  256. /* actions */ sciPlotActionsList,
  257. /* num_actions */ XtNumber (sciPlotActionsList),
  258. /* resources */ resources,
  259. /* num_resources */ XtNumber(resources),
  260. /* xrm_class */ NULLQUARK,
  261. /* compress_motion */ True,
  262. /* compress_exposure */ XtExposeCompressMultiple,
  263. /* compress_enterleave */ True,
  264. /* visible_interest */ True,
  265. /* destroy */ Destroy,
  266. /* resize */ Resize,
  267. /* expose */ Redisplay,
  268. /* set_values */ SetValues,
  269. /* set_values_hook */ NULL,
  270. /* set_values_almost */ XtInheritSetValuesAlmost,
  271. /* get_values_hook */ GetValuesHook,
  272. /* accept_focus */ NULL,
  273. /* version */ XtVersion,
  274. /* callback_private */ NULL,
  275. /* tm_table */ sciPlotTranslations,
  276. /* query_geometry */ NULL,
  277. /* display_accelerator */ XtInheritDisplayAccelerator,
  278. /* extension */ NULL
  279. },
  280. #ifdef MOTIF
  281. {
  282. /* primitive_class fields */
  283. /* border_highlight */ (XtWidgetProc)_XtInherit,
  284. /* border_unhighligh */ (XtWidgetProc)_XtInherit,
  285. /* translations */ XtInheritTranslations,
  286. /* arm_and_activate */ (XtActionProc)_XtInherit,
  287. /* syn_resources */ NULL,
  288. /* num_syn_resources */ 0,
  289. /* extension */ NULL
  290. },
  291. #endif
  292. {
  293. /* plot_class fields */
  294. /* dummy */ 0
  295. /* (some stupid compilers barf on empty structures) */
  296. }
  297. };
  298. WidgetClass sciplotWidgetClass = (WidgetClass) & sciplotClassRec;
  299. static void
  300. Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num)
  301. {
  302. SciPlotWidget new;
  303. new = (SciPlotWidget) tnew;
  304. new->plot.plotlist = NULL;
  305. new->plot.alloc_plotlist = 0;
  306. new->plot.num_plotlist = 0;
  307. new->plot.alloc_drawlist = NUMPLOTITEMALLOC;
  308. new->plot.drawlist = (SciPlotItem *) XtCalloc(new->plot.alloc_drawlist,
  309. sizeof(SciPlotItem));
  310. new->plot.num_drawlist = 0;
  311. new->plot.cmap = DefaultColormap(XtDisplay(new),
  312. DefaultScreen(XtDisplay(new)));
  313. new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1);
  314. strcpy(new->plot.xlabel, new->plot.TransientXLabel);
  315. new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1);
  316. strcpy(new->plot.ylabel, new->plot.TransientYLabel);
  317. new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1);
  318. strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle);
  319. new->plot.TransientXLabel=NULL;
  320. new->plot.TransientYLabel=NULL;
  321. new->plot.TransientPlotTitle=NULL;
  322. new->plot.colors = NULL;
  323. new->plot.num_colors = 0;
  324. new->plot.fonts = NULL;
  325. new->plot.num_fonts = 0;
  326. new->plot.update = FALSE;
  327. new->plot.UserMin.x = new->plot.UserMin.y = 0.0;
  328. new->plot.UserMax.x = new->plot.UserMax.y = 10.0;
  329. new->plot.titleFont = FontStore(new, new->plot.TitleFont);
  330. new->plot.labelFont = FontStore(new, new->plot.LabelFont);
  331. new->plot.axisFont = FontStore(new, new->plot.AxisFont);
  332. /* set initial drag state to drag_none */
  333. new->plot.drag_state = NOT_DRAGGING;
  334. new->plot.drag_start.x = 0.0;
  335. new->plot.drag_start.y = 0.0;
  336. new->plot.startx = 0.0;
  337. new->plot.endx = 0.0;
  338. new->plot.starty = 0.0;
  339. new->plot.endy = 0.0;
  340. new->plot.reach_limit = 0;
  341. }
  342. static void
  343. GCInitialize(SciPlotWidget new)
  344. {
  345. XGCValues values;
  346. XtGCMask mask;
  347. long colorsave;
  348. values.line_style = LineSolid;
  349. values.line_width = 0;
  350. values.fill_style = FillSolid;
  351. values.background = WhitePixelOfScreen(XtScreen(new));
  352. values.background = new->core.background_pixel;
  353. new->plot.BackgroundColor = ColorStore(new, values.background);
  354. /* KE: Moved this up here 1-11-01 so 1 would be the foreground color
  355. as in the documentation */
  356. values.foreground = colorsave = BlackPixelOfScreen(XtScreen(new));
  357. new->plot.ForegroundColor = ColorStore(new, values.foreground);
  358. #ifdef MOTIF
  359. /* KE: Primitive should keep track of colors and GC. We don't need to
  360. * do that. */
  361. new->core.background_pixel = values.background;
  362. {
  363. Pixel fg, select, shade1, shade2;
  364. XmGetColors(XtScreen(new), new->core.colormap,
  365. new->core.background_pixel, &fg, &shade1, &shade2, &select);
  366. new->plot.ShadowColor1 = ColorStore(new, shade1);
  367. new->plot.ShadowColor2 = ColorStore(new, shade2);
  368. new->primitive.top_shadow_color = shade1;
  369. new->primitive.bottom_shadow_color = shade2;
  370. }
  371. #endif
  372. mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground | GCBackground;
  373. new->plot.defaultGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values);
  374. /* Eliminate events that we do not handle anyway */
  375. XSetGraphicsExposures(XtDisplay(new), new->plot.defaultGC, False);
  376. values.foreground = colorsave;
  377. values.line_style = LineOnOffDash;
  378. new->plot.dashGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values);
  379. /* Eliminate events that we do not handle anyway */
  380. XSetGraphicsExposures(XtDisplay(new), new->plot.dashGC, False);
  381. }
  382. static void
  383. Realize(Widget aw, XtValueMask * value_mask, XSetWindowAttributes * attributes)
  384. {
  385. SciPlotWidget w = (SciPlotWidget) aw;
  386. #define superclass (&widgetClassRec)
  387. (*superclass->core_class.realize) (aw, value_mask, attributes);
  388. #undef superclass
  389. GCInitialize(w);
  390. }
  391. static void
  392. Destroy(Widget ws)
  393. {
  394. SciPlotWidget w = (SciPlotWidget)ws;
  395. int i, j;
  396. SciPlotFont *pf;
  397. SciPlotList *p;
  398. XFreeGC(XtDisplay(w), w->plot.defaultGC);
  399. XFreeGC(XtDisplay(w), w->plot.dashGC);
  400. XtFree((char *) w->plot.xlabel);
  401. XtFree((char *) w->plot.ylabel);
  402. XtFree((char *) w->plot.plotTitle);
  403. for (i = 0; i < w->plot.num_fonts; i++) {
  404. pf = &w->plot.fonts[i];
  405. XFreeFont(XtDisplay((Widget) w), pf->font);
  406. }
  407. XtFree((char *) w->plot.fonts);
  408. XtFree((char *) w->plot.colors);
  409. #if DEBUG_SCIPLOT_ALLOC
  410. SciPlotPrintf("Destroy: alloc_plotlist=%d num_plotlist=%d\n",
  411. w->plot.alloc_plotlist,w->plot.num_plotlist);
  412. for (i = 0; i < w->plot.alloc_plotlist; i++) {
  413. p = w->plot.plotlist + i;
  414. SciPlotPrintf(" List %d: allocated=%d legend=%x markertext=%x\n",
  415. i, p->allocated, p->legend, p->markertext);
  416. }
  417. #endif
  418. for (i = 0; i < w->plot.alloc_plotlist; i++) {
  419. p = w->plot.plotlist + i;
  420. if (p->allocated > 0)
  421. XtFree((char *) p->data);
  422. if (p->legend)
  423. XtFree(p->legend);
  424. if (p->markertext) {
  425. for (j = 0; j < p->number; j++) {
  426. if (p->markertext[j])
  427. XtFree (p->markertext[j]);
  428. }
  429. }
  430. }
  431. if (w->plot.alloc_plotlist > 0)
  432. XtFree((char *) w->plot.plotlist);
  433. EraseAll(w);
  434. XtFree((char *) w->plot.drawlist);
  435. }
  436. static Boolean
  437. SetValues(Widget currents, Widget requests, Widget news,
  438. ArgList args, Cardinal *nargs)
  439. /* KE: requests, args, nargs are not used */
  440. {
  441. SciPlotWidget current = (SciPlotWidget)currents;
  442. SciPlotWidget new = (SciPlotWidget)news;
  443. Boolean redisplay = FALSE;
  444. if (current->plot.XLog != new->plot.XLog)
  445. redisplay = TRUE;
  446. else if (current->plot.YLog != new->plot.YLog)
  447. redisplay = TRUE;
  448. else if (current->plot.XOrigin != new->plot.XOrigin)
  449. redisplay = TRUE;
  450. else if (current->plot.YOrigin != new->plot.YOrigin)
  451. redisplay = TRUE;
  452. else if (current->plot.XAxisNumbers != new->plot.XAxisNumbers)
  453. redisplay = TRUE;
  454. else if (current->plot.YAxisNumbers != new->plot.YAxisNumbers)
  455. redisplay = TRUE;
  456. else if (current->plot.DrawMajor != new->plot.DrawMajor)
  457. redisplay = TRUE;
  458. else if (current->plot.DrawMajorTics != new->plot.DrawMajorTics)
  459. redisplay = TRUE;
  460. else if (current->plot.DrawMinor != new->plot.DrawMinor)
  461. redisplay = TRUE;
  462. else if (current->plot.DrawMinorTics != new->plot.DrawMinorTics)
  463. redisplay = TRUE;
  464. else if (current->plot.ChartType != new->plot.ChartType)
  465. redisplay = TRUE;
  466. else if (current->plot.Degrees != new->plot.Degrees)
  467. redisplay = TRUE;
  468. else if (current->plot.ShowLegend != new->plot.ShowLegend)
  469. redisplay = TRUE;
  470. else if (current->plot.ShowTitle != new->plot.ShowTitle)
  471. redisplay = TRUE;
  472. else if (current->plot.ShowXLabel != new->plot.ShowXLabel)
  473. redisplay = TRUE;
  474. else if (current->plot.ShowYLabel != new->plot.ShowYLabel)
  475. redisplay = TRUE;
  476. else if (current->plot.ShowTitle != new->plot.ShowTitle)
  477. redisplay = TRUE;
  478. else if (current->plot.Monochrome != new->plot.Monochrome)
  479. redisplay = TRUE;
  480. else if (current->plot.XFixedLR != new->plot.XFixedLR)
  481. redisplay = TRUE;
  482. else if ((current->plot.XLeftSpace != new->plot.XLeftSpace ||
  483. current->plot.XRightSpace != new->plot.XRightSpace) &&
  484. new->plot.XFixedLR)
  485. redisplay = TRUE;
  486. if (new->plot.TransientXLabel) {
  487. if (current->plot.TransientXLabel != new->plot.TransientXLabel ||
  488. strcmp(new->plot.TransientXLabel,current->plot.xlabel)!=0) {
  489. redisplay = TRUE;
  490. XtFree(current->plot.xlabel);
  491. new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1);
  492. strcpy(new->plot.xlabel, new->plot.TransientXLabel);
  493. new->plot.TransientXLabel=NULL;
  494. }
  495. }
  496. if (new->plot.TransientYLabel) {
  497. if (current->plot.TransientYLabel != new->plot.TransientYLabel ||
  498. strcmp(new->plot.TransientYLabel,current->plot.ylabel)!=0) {
  499. redisplay = TRUE;
  500. XtFree(current->plot.ylabel);
  501. new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1);
  502. strcpy(new->plot.ylabel, new->plot.TransientYLabel);
  503. new->plot.TransientYLabel=NULL;
  504. }
  505. }
  506. if (new->plot.TransientPlotTitle) {
  507. if (current->plot.TransientPlotTitle != new->plot.TransientPlotTitle ||
  508. strcmp(new->plot.TransientPlotTitle,current->plot.plotTitle)!=0) {
  509. redisplay = TRUE;
  510. XtFree(current->plot.plotTitle);
  511. new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1);
  512. strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle);
  513. new->plot.TransientPlotTitle=NULL;
  514. }
  515. }
  516. if (current->plot.AxisFont != new->plot.AxisFont) {
  517. redisplay = TRUE;
  518. FontnumReplace(new, new->plot.axisFont, new->plot.AxisFont);
  519. }
  520. if (current->plot.TitleFont != new->plot.TitleFont) {
  521. redisplay = TRUE;
  522. FontnumReplace(new, new->plot.titleFont, new->plot.TitleFont);
  523. }
  524. if (current->plot.LabelFont != new->plot.LabelFont) {
  525. redisplay = TRUE;
  526. FontnumReplace(new, new->plot.labelFont, new->plot.LabelFont);
  527. }
  528. new->plot.update = redisplay;
  529. return redisplay;
  530. }
  531. static void
  532. GetValuesHook(Widget ws, ArgList args, Cardinal *num_args)
  533. {
  534. SciPlotWidget w = (SciPlotWidget)ws;
  535. int i;
  536. char **loc;
  537. for (i=0; i < (int)*num_args; i++) {
  538. loc=(char **)args[i].value;
  539. if (strcmp(args[i].name,XtNplotTitle)==0)
  540. *loc=w->plot.plotTitle;
  541. else if (strcmp(args[i].name,XtNxLabel)==0)
  542. *loc=w->plot.xlabel;
  543. else if (strcmp(args[i].name,XtNyLabel)==0)
  544. *loc=w->plot.ylabel;
  545. }
  546. }
  547. static void
  548. Redisplay(Widget ws, XEvent *event, Region region)
  549. /* KE: event, region not used */
  550. {
  551. SciPlotWidget w = (SciPlotWidget)ws;
  552. if (!XtIsRealized((Widget)w))
  553. return;
  554. if (w->plot.update) {
  555. Resize(ws);
  556. w->plot.update = FALSE;
  557. }
  558. else {
  559. ItemDrawAll(w);
  560. }
  561. }
  562. static void
  563. Resize(Widget ws)
  564. {
  565. SciPlotWidget w = (SciPlotWidget)ws;
  566. if (!XtIsRealized((Widget)w))
  567. return;
  568. EraseAll(w);
  569. if (w->plot.XNoCompMinMax)
  570. ComputeAll(w, NO_COMPUTE_MIN_MAX_X);
  571. else
  572. ComputeAll(w, COMPUTE_MIN_MAX);
  573. DrawAll(w);
  574. }
  575. /*
  576. * Private SciPlot utility functions
  577. */
  578. static int
  579. ColorStore (SciPlotWidget w, Pixel color)
  580. {
  581. int i;
  582. /* Check if it is there */
  583. for(i=0; i < w->plot.num_colors; i++) {
  584. if(w->plot.colors[i] == color) return i;
  585. }
  586. /* Not found, add it */
  587. w->plot.num_colors++;
  588. w->plot.colors = (Pixel *) XtRealloc((char *) w->plot.colors,
  589. sizeof(Pixel) * w->plot.num_colors);
  590. w->plot.colors[w->plot.num_colors - 1] = color;
  591. return w->plot.num_colors - 1;
  592. }
  593. static void
  594. FontnumStore (SciPlotWidget w, int fontnum, int flag)
  595. {
  596. SciPlotFont *pf;
  597. int fontflag, sizeflag, attrflag;
  598. pf = &w->plot.fonts[fontnum];
  599. fontflag = flag & XtFONT_NAME_MASK;
  600. sizeflag = flag & XtFONT_SIZE_MASK;
  601. attrflag = flag & XtFONT_ATTRIBUTE_MASK;
  602. switch (fontflag) {
  603. case XtFONT_TIMES:
  604. case XtFONT_COURIER:
  605. case XtFONT_HELVETICA:
  606. case XtFONT_LUCIDA:
  607. case XtFONT_LUCIDASANS:
  608. case XtFONT_NCSCHOOLBOOK:
  609. break;
  610. default:
  611. fontflag = XtFONT_NAME_DEFAULT;
  612. break;
  613. }
  614. if (sizeflag < 1)
  615. sizeflag = XtFONT_SIZE_DEFAULT;
  616. switch (attrflag) {
  617. case XtFONT_BOLD:
  618. case XtFONT_ITALIC:
  619. case XtFONT_BOLD_ITALIC:
  620. break;
  621. default:
  622. attrflag = XtFONT_ATTRIBUTE_DEFAULT;
  623. break;
  624. }
  625. pf->id = flag;
  626. FontInit(w, pf);
  627. }
  628. static int
  629. FontnumReplace (SciPlotWidget w, int fontnum, int flag)
  630. {
  631. SciPlotFont *pf;
  632. pf = &w->plot.fonts[fontnum];
  633. XFreeFont(XtDisplay(w), pf->font);
  634. FontnumStore(w, fontnum, flag);
  635. return fontnum;
  636. }
  637. static int
  638. FontStore (SciPlotWidget w, int flag)
  639. {
  640. int fontnum;
  641. w->plot.num_fonts++;
  642. w->plot.fonts = (SciPlotFont *) XtRealloc((char *) w->plot.fonts,
  643. sizeof(SciPlotFont) * w->plot.num_fonts);
  644. fontnum = w->plot.num_fonts - 1;
  645. FontnumStore(w, fontnum, flag);
  646. return fontnum;
  647. }
  648. static SciPlotFontDesc *
  649. FontDescLookup (int flag)
  650. {
  651. SciPlotFontDesc *pfd;
  652. pfd = font_desc_table;
  653. while (pfd->flag >= 0) {
  654. #if DEBUG_SCIPLOT
  655. SciPlotPrintf("FontDescLookup: checking if %d == %d (font %s)\n",
  656. flag & XtFONT_NAME_MASK, pfd->flag, pfd->PostScript);
  657. #endif
  658. if ((flag & XtFONT_NAME_MASK) == pfd->flag)
  659. return pfd;
  660. pfd++;
  661. }
  662. return NULL;
  663. }
  664. static void
  665. FontnumPostScriptString (SciPlotWidget w, int fontnum, char *str)
  666. {
  667. char temp[128];
  668. int flag, bold, italic;
  669. SciPlotFontDesc *pfd;
  670. flag = w->plot.fonts[fontnum].id;
  671. pfd = FontDescLookup(flag);
  672. if (pfd) {
  673. strcpy(temp, pfd->PostScript);
  674. bold = False;
  675. italic = False;
  676. if (flag & XtFONT_BOLD) {
  677. bold = True;
  678. strcat(temp, "-Bold");
  679. }
  680. if (flag & XtFONT_ITALIC) {
  681. italic = True;
  682. if (!bold)
  683. strcat(temp, "-");
  684. if (pfd->PSUsesOblique)
  685. strcat(temp, "Oblique");
  686. else
  687. strcat(temp, "Italic");
  688. }
  689. if (!bold && !italic && pfd->PSUsesRoman) {
  690. strcat(temp, "-Roman");
  691. }
  692. sprintf(str, "/%s findfont %d scalefont",
  693. temp,
  694. (flag & XtFONT_SIZE_MASK));
  695. }
  696. else
  697. sprintf(str, "/Courier findfont 10 scalefont");
  698. }
  699. static void
  700. FontX11String (int flag, char *str)
  701. {
  702. SciPlotFontDesc *pfd;
  703. pfd = FontDescLookup(flag);
  704. if (pfd) {
  705. sprintf(str, "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-*-*",
  706. pfd->X11,
  707. (flag & XtFONT_BOLD ? "bold" : "medium"),
  708. (flag & XtFONT_ITALIC ? (pfd->PSUsesOblique ? "o" : "i") : "r"),
  709. (flag & XtFONT_SIZE_MASK));
  710. }
  711. else
  712. sprintf(str, "fixed");
  713. #if DEBUG_SCIPLOT
  714. SciPlotPrintf("FontX11String: font string=%s\n", str);
  715. #endif
  716. }
  717. static void
  718. FontInit (SciPlotWidget w, SciPlotFont *pf)
  719. {
  720. char str[256], **list;
  721. int num;
  722. FontX11String(pf->id, str);
  723. list = XListFonts(XtDisplay(w), str, 100, &num);
  724. #if DEBUG_SCIPLOT
  725. if (1) {
  726. int i;
  727. i = 0;
  728. while (i < num) {
  729. SciPlotPrintf("FontInit: Found font: %s\n", list[i]);
  730. i++;
  731. }
  732. }
  733. #endif
  734. if (num <= 0) {
  735. pf->id &= ~XtFONT_ATTRIBUTE_MASK;
  736. pf->id |= XtFONT_ATTRIBUTE_DEFAULT;
  737. FontX11String(pf->id, str);
  738. list = XListFonts(XtDisplay(w), str, 100, &num);
  739. #if DEBUG_SCIPLOT
  740. if (1) {
  741. int i;
  742. i = 0;
  743. while (i < num) {
  744. SciPlotPrintf("FontInit: Attr reset: found: %s\n", list[i]);
  745. i++;
  746. }
  747. }
  748. #endif
  749. }
  750. if (num <= 0) {
  751. pf->id &= ~XtFONT_NAME_MASK;
  752. pf->id |= XtFONT_NAME_DEFAULT;
  753. FontX11String(pf->id, str);
  754. list = XListFonts(XtDisplay(w), str, 100, &num);
  755. #if DEBUG_SCIPLOT
  756. if (1) {
  757. int i;
  758. i = 0;
  759. while (i < num) {
  760. SciPlotPrintf("FontInit: Name reset: found: %s\n", list[i]);
  761. i++;
  762. }
  763. }
  764. #endif
  765. }
  766. if (num <= 0) {
  767. pf->id &= ~XtFONT_SIZE_MASK;
  768. pf->id |= XtFONT_SIZE_DEFAULT;
  769. FontX11String(pf->id, str);
  770. list = XListFonts(XtDisplay(w), str, 100, &num);
  771. #if DEBUG_SCIPLOT
  772. if (1) {
  773. int i;
  774. i = 0;
  775. while (i < num) {
  776. SciPlotPrintf("FontInit: Size reset: found: %s\n", list[i]);
  777. i++;
  778. }
  779. }
  780. #endif
  781. }
  782. #if DEBUG_SCIPLOT
  783. if (1) {
  784. XFontStruct *f;
  785. int i;
  786. i = 0;
  787. while (i < num) {
  788. SciPlotPrintf("FontInit: Properties for: %s\n", list[i]);
  789. f = XLoadQueryFont(XtDisplay(w), list[i]);
  790. SciPlotPrintf(" Height: %3d Ascent: %d Descent: %d\n",
  791. f->max_bounds.ascent + f->max_bounds.descent,
  792. f->max_bounds.ascent, f->max_bounds.descent);
  793. XFreeFont(XtDisplay(w), f);
  794. i++;
  795. }
  796. }
  797. #endif
  798. if (num > 0) {
  799. /* Use the first one in the list */
  800. /* KE: Used to use str instead of list[0] but this failed on Linux
  801. * Enterprise for some unknown reason */
  802. pf->font = XLoadQueryFont(XtDisplay(w), list[0]);
  803. XFreeFontNames(list);
  804. } else {
  805. /* Use fixed */
  806. pf->font = XLoadQueryFont(XtDisplay(w), "fixed");
  807. }
  808. #if DEBUG_SCIPLOT
  809. SciPlotPrintf("FontInit: Finally ran XLoadQueryFont using: %s\n", str);
  810. SciPlotPrintf(" Height: %3d Ascent: %d Descent: %d\n",
  811. pf->font->max_bounds.ascent + pf->font->max_bounds.descent,
  812. pf->font->max_bounds.ascent, pf->font->max_bounds.descent);
  813. #endif
  814. }
  815. static XFontStruct *
  816. FontFromFontnum (SciPlotWidget w, int fontnum)
  817. {
  818. XFontStruct *f;
  819. if (fontnum >= w->plot.num_fonts)
  820. fontnum = 0;
  821. f = w->plot.fonts[fontnum].font;
  822. return f;
  823. }
  824. static real
  825. FontHeight(XFontStruct *f)
  826. {
  827. return (real) (f->max_bounds.ascent + f->max_bounds.descent);
  828. }
  829. static real
  830. FontnumHeight(SciPlotWidget w, int fontnum)
  831. {
  832. XFontStruct *f;
  833. f = FontFromFontnum(w, fontnum);
  834. return FontHeight(f);
  835. }
  836. static real
  837. FontDescent(XFontStruct *f)
  838. {
  839. return (real) (f->max_bounds.descent);
  840. }
  841. static real
  842. FontnumDescent(SciPlotWidget w, int fontnum)
  843. {
  844. XFontStruct *f;
  845. f = FontFromFontnum(w, fontnum);
  846. return FontDescent(f);
  847. }
  848. static real
  849. FontAscent(XFontStruct *f)
  850. {
  851. return (real) (f->max_bounds.ascent);
  852. }
  853. static real
  854. FontnumAscent(SciPlotWidget w, int fontnum)
  855. {
  856. XFontStruct *f;
  857. f = FontFromFontnum(w, fontnum);
  858. return FontAscent(f);
  859. }
  860. static real
  861. FontTextWidth(XFontStruct *f, char *c)
  862. {
  863. return (real) XTextWidth(f, c, strlen(c));
  864. }
  865. static real
  866. FontnumTextWidth(SciPlotWidget w, int fontnum, char *c)
  867. {
  868. XFontStruct *f;
  869. f = FontFromFontnum(w, fontnum);
  870. return FontTextWidth(f, c);
  871. }
  872. /*
  873. * Private List functions
  874. */
  875. static int
  876. _ListNew (SciPlotWidget w)
  877. {
  878. int index;
  879. SciPlotList *p;
  880. Boolean found;
  881. /* First check to see if there is any free space in the index */
  882. found = FALSE;
  883. for (index = 0; index < w->plot.num_plotlist; index++) {
  884. p = w->plot.plotlist + index;
  885. if (!p->used) {
  886. found = TRUE;
  887. break;
  888. }
  889. }
  890. /* If no space is found, increase the size of the index */
  891. if (!found) {
  892. w->plot.num_plotlist++;
  893. if (w->plot.alloc_plotlist == 0) {
  894. w->plot.alloc_plotlist = NUMPLOTLINEALLOC;
  895. w->plot.plotlist = (SciPlotList *) XtCalloc(w->plot.alloc_plotlist, sizeof(SciPlotList));
  896. if (!w->plot.plotlist) {
  897. SciPlotPrintf("Can't calloc memory for SciPlotList\n");
  898. exit(1);
  899. }
  900. w->plot.alloc_plotlist = NUMPLOTLINEALLOC;
  901. }
  902. else if (w->plot.num_plotlist > w->plot.alloc_plotlist) {
  903. w->plot.alloc_plotlist += NUMPLOTLINEALLOC;
  904. w->plot.plotlist = (SciPlotList *) XtRealloc((char *) w->plot.plotlist,
  905. w->plot.alloc_plotlist * sizeof(SciPlotList));
  906. if (!w->plot.plotlist) {
  907. SciPlotPrintf("Can't realloc memory for SciPlotList\n");
  908. exit(1);
  909. }
  910. /* KE: XtRealloc does not zero memory as does the original XtCalloc
  911. * This will cause problems in Destroy for data, legend, markertest, etc.*/
  912. p = w->plot.plotlist + w->plot.alloc_plotlist - NUMPLOTLINEALLOC;
  913. memset(p, '\0', NUMPLOTLINEALLOC * sizeof(SciPlotList));
  914. }
  915. index = w->plot.num_plotlist - 1;
  916. p = w->plot.plotlist + index;
  917. }
  918. /* KE: Since the lists have been zeroed, only the non-zero ones
  919. * really need to be set */
  920. p->LineStyle = p->LineColor = p->PointStyle = p->PointColor = 0;
  921. p->number = p->allocated = 0;
  922. p->data = NULL;
  923. p->legend = NULL;
  924. p->draw = p->used = TRUE;
  925. p->markersize = (real) w->plot.DefaultMarkerSize;
  926. p->markertext = NULL;
  927. #if DEBUG_SCIPLOT_ALLOC
  928. SciPlotPrintf("_ListNew: alloc_plotlist=%d num_plotlist=%d\n",
  929. w->plot.alloc_plotlist,w->plot.num_plotlist);
  930. #endif
  931. return index;
  932. }
  933. static void
  934. _ListDelete (SciPlotList *p)
  935. {
  936. int i;
  937. if (p->markertext) {
  938. for (i = 0; i < p->number; i++) {
  939. if (p->markertext[i]) {
  940. XtFree (p->markertext[i]);
  941. p->markertext[i] = NULL;
  942. }
  943. }
  944. XtFree ((char *)p->markertext);
  945. p->markertext = NULL;
  946. }
  947. p->draw = p->used = FALSE;
  948. p->number = p->allocated = 0;
  949. if (p->data)
  950. XtFree((char *) p->data);
  951. p->data = NULL;
  952. if (p->legend)
  953. XtFree((char *) p->legend);
  954. p->legend = NULL;
  955. #if DEBUG_SCIPLOT_ALLOC
  956. SciPlotPrintf("_ListDelete:\n");
  957. #endif
  958. }
  959. static SciPlotList *
  960. _ListFind (SciPlotWidget w, int id)
  961. {
  962. SciPlotList *p;
  963. if ((id >= 0) && (id < w->plot.num_plotlist)) {
  964. p = w->plot.plotlist + id;
  965. if (p->used)
  966. return p;
  967. }
  968. return NULL;
  969. }
  970. static void
  971. _ListSetStyle (SciPlotList *p, int pcolor, int pstyle, int lcolor, int lstyle)
  972. {
  973. /* Note! Do checks in here later on... */
  974. if (lstyle >= 0)
  975. p->LineStyle = lstyle;
  976. if (lcolor >= 0)
  977. p->LineColor = lcolor;
  978. if (pstyle >= 0)
  979. p->PointStyle = pstyle;
  980. if (pcolor >= 0)
  981. p->PointColor = pcolor;
  982. }
  983. static void
  984. _ListSetLegend (SciPlotList *p, char *legend)
  985. {
  986. /* Note! Do checks in here later on... */
  987. p->legend = (char *) XtMalloc(strlen(legend) + 1);
  988. strcpy(p->legend, legend);
  989. }
  990. static void
  991. _ListAllocData (SciPlotList *p, int num)
  992. {
  993. if (p->data) {
  994. XtFree((char *) p->data);
  995. p->allocated = 0;
  996. }
  997. p->allocated = num + NUMPLOTDATAEXTRA;
  998. p->data = (realpair *) XtCalloc(p->allocated, sizeof(realpair));
  999. if (!p->data) {
  1000. p->number = p->allocated = 0;
  1001. }
  1002. }
  1003. static void
  1004. _ListReallocData (SciPlotList *p, int more)
  1005. {
  1006. if (!p->data) {
  1007. _ListAllocData(p, more);
  1008. }
  1009. else if (p->number + more > p->allocated) {
  1010. p->allocated += more + NUMPLOTDATAEXTRA;
  1011. p->data = (realpair *) XtRealloc((char *) p->data, p->allocated * sizeof(realpair));
  1012. if (!p->data) {
  1013. p->number = p->allocated = 0;
  1014. }
  1015. }
  1016. }
  1017. static void
  1018. _ListAddReal (SciPlotList *p, int num, real *xlist, real *ylist)
  1019. {
  1020. int i;
  1021. _ListReallocData(p, num);
  1022. if (p->data) {
  1023. for (i = 0; i < num; i++) {
  1024. p->data[i + p->number].x = xlist[i];
  1025. p->data[i + p->number].y = ylist[i];
  1026. }
  1027. p->number += num;
  1028. }
  1029. }
  1030. static void
  1031. _ListAddFloat (SciPlotList *p, int num, float *xlist, float *ylist)
  1032. {
  1033. int i;
  1034. _ListReallocData(p, num);
  1035. if (p->data) {
  1036. for (i = 0; i < num; i++) {
  1037. p->data[i + p->number].x = xlist[i];
  1038. p->data[i + p->number].y = ylist[i];
  1039. }
  1040. p->number += num;
  1041. }
  1042. }
  1043. static void
  1044. _ListAddDouble (SciPlotList *p, int num, double *xlist, double *ylist)
  1045. {
  1046. int i;
  1047. _ListReallocData(p, num);
  1048. if (p->data) {
  1049. for (i = 0; i < num; i++) {
  1050. p->data[i + p->number].x = xlist[i];
  1051. p->data[i + p->number].y = ylist[i];
  1052. }
  1053. p->number += num;
  1054. }
  1055. }
  1056. static void
  1057. _ListSetReal(SciPlotList *p, int num, real *xlist, real *ylist)
  1058. {
  1059. if ((!p->data) || (p->allocated < num))
  1060. _ListAllocData(p, num);
  1061. p->number = 0;
  1062. _ListAddReal(p, num, xlist, ylist);
  1063. }
  1064. static void
  1065. _ListSetFloat (SciPlotList *p, int num, float *xlist, float *ylist)
  1066. {
  1067. if ((!p->data) || (p->allocated < num))
  1068. _ListAllocData(p, num);
  1069. p->number = 0;
  1070. _ListAddFloat(p, num, xlist, ylist);
  1071. }
  1072. static void
  1073. _ListSetDouble (SciPlotList *p, int num, double *xlist, double *ylist)
  1074. {
  1075. if ((!p->data) || (p->allocated < num))
  1076. _ListAllocData(p, num);
  1077. p->number = 0;
  1078. _ListAddDouble(p, num, xlist, ylist);
  1079. }
  1080. /*
  1081. * Private SciPlot functions
  1082. */
  1083. /*
  1084. * The following vertical text drawing routine uses the "Fill Stippled" idea
  1085. * found in xvertext-5.0, by Alan Richardson (mppa3@syma.sussex.ac.uk).
  1086. *
  1087. * The following code is my interpretation of his idea, including some
  1088. * hacked together excerpts from his source. The credit for the clever bits
  1089. * belongs to him.
  1090. *
  1091. * To be complete, portions of the subroutine XDrawVString are
  1092. * Copyright (c) 1993 Alan Richardson (mppa3@syma.sussex.ac.uk)
  1093. */
  1094. static void
  1095. XDrawVString (Display *display, Window win, GC gc, int x, int y, char *str, int len, XFontStruct *f)
  1096. {
  1097. XImage *before, *after;
  1098. char *dest, *source, *source0, *source1;
  1099. int xloop, yloop, xdest, ydest;
  1100. Pixmap pix, rotpix;
  1101. int width, height;
  1102. GC drawGC;
  1103. width = (int) FontTextWidth(f, str);
  1104. height = (int) FontHeight(f);
  1105. pix = XCreatePixmap(display, win, width, height, 1);
  1106. rotpix = XCreatePixmap(display, win, height, width, 1);
  1107. drawGC = XCreateGC(display, pix, 0L, NULL);
  1108. XSetBackground(display, drawGC, 0);
  1109. XSetFont(display, drawGC, f->fid);
  1110. XSetForeground(display, drawGC, 0);
  1111. XFillRectangle(display, pix, drawGC, 0, 0, width, height);
  1112. XFillRectangle(display, rotpix, drawGC, 0, 0, height, width);
  1113. XSetForeground(display, drawGC, 1);
  1114. /* Eliminate events that we do not handle anyway */
  1115. XSetGraphicsExposures(display, drawGC, False);
  1116. XDrawImageString(display, pix, drawGC, 0, (int) FontAscent(f),
  1117. str, strlen(str));
  1118. source0 = (char *) calloc((((width + 7) / 8) * height), 1);
  1119. before = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)),
  1120. 1, XYPixmap, 0, source0, width, height, 8, 0);
  1121. before->byte_order = before->bitmap_bit_order = MSBFirst;
  1122. XGetSubImage(display, pix, 0, 0, width, height, 1L, XYPixmap, before, 0, 0);
  1123. source1 = (char *) calloc((((height + 7) / 8) * width), 1);
  1124. after = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)),
  1125. 1, XYPixmap, 0, source1, height, width, 8, 0);
  1126. after->byte_order = after->bitmap_bit_order = MSBFirst;
  1127. for (yloop = 0; yloop < height; yloop++) {
  1128. for (xloop = 0; xloop < width; xloop++) {
  1129. source = before->data + (xloop / 8) +
  1130. (yloop * before->bytes_per_line);
  1131. if (*source & (128 >> (xloop % 8))) {
  1132. dest = after->data + (yloop / 8) +
  1133. ((width - 1 - xloop) * after->bytes_per_line);
  1134. *dest |= (128 >> (yloop % 8));
  1135. }
  1136. }
  1137. }
  1138. #if DEBUG_SCIPLOT_VTEXT
  1139. if (1) {
  1140. char sourcebit;
  1141. for (yloop = 0; yloop < before->height; yloop++) {
  1142. for (xloop = 0; xloop < before->width; xloop++) {
  1143. source = before->data + (xloop / 8) +
  1144. (yloop * before->bytes_per_line);
  1145. sourcebit = *source & (128 >> (xloop % 8));
  1146. if (sourcebit)
  1147. putchar('X');
  1148. else
  1149. putchar('.');
  1150. }
  1151. putchar('\n');
  1152. }
  1153. for (yloop = 0; yloop < after->height; yloop++) {
  1154. for (xloop = 0; xloop < after->width; xloop++) {
  1155. source = after->data + (xloop / 8) +
  1156. (yloop * after->bytes_per_line);
  1157. sourcebit = *source & (128 >> (xloop % 8));
  1158. if (sourcebit)
  1159. putchar('X');
  1160. else
  1161. putchar('.');
  1162. }
  1163. putchar('\n');
  1164. }
  1165. }
  1166. #endif
  1167. xdest = x - (int) FontAscent(f);
  1168. if (xdest < 0)
  1169. xdest = 0;
  1170. ydest = y - width;
  1171. XPutImage(display, rotpix, drawGC, after, 0, 0, 0, 0,
  1172. after->width, after->height);
  1173. XSetFillStyle(display, gc, FillStippled);
  1174. XSetStipple(display, gc, rotpix);
  1175. XSetTSOrigin(display, gc, xdest, ydest);
  1176. XFillRectangle(display, win, gc, xdest, ydest, after->width, after->height);
  1177. XSetFillStyle(display, gc, FillSolid);
  1178. XFreeGC(display, drawGC);
  1179. /* Free image data ourselves and mark it as null in the XImage */
  1180. free(source0);
  1181. free(source1);
  1182. before->data = 0;
  1183. after->data = 0;
  1184. XDestroyImage(before);
  1185. XDestroyImage(after);
  1186. XFreePixmap(display, pix);
  1187. XFreePixmap(display, rotpix);
  1188. }
  1189. static char dots[] =
  1190. {2, 1, 1};
  1191. static char widedots[] =
  1192. {2, 1, 4};
  1193. static GC
  1194. ItemGetGC (SciPlotWidget w, SciPlotItem *item)
  1195. {
  1196. GC gc;
  1197. short color;
  1198. switch (item->kind.any.style) {
  1199. case XtLINE_SOLID:
  1200. gc = w->plot.defaultGC;
  1201. break;
  1202. case XtLINE_DOTTED:
  1203. XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &dots[1],
  1204. (int) dots[0]);
  1205. gc = w->plot.dashGC;
  1206. break;
  1207. case XtLINE_WIDEDOT:
  1208. XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &widedots[1],
  1209. (int) widedots[0]);
  1210. gc = w->plot.dashGC;
  1211. break;
  1212. default:
  1213. return NULL;
  1214. }
  1215. if (w->plot.Monochrome)
  1216. if (item->kind.any.color > 0)
  1217. color = w->plot.ForegroundColor;
  1218. else
  1219. color = w->plot.BackgroundColor;
  1220. else if (item->kind.any.color >= w->plot.num_colors)
  1221. color = w->plot.ForegroundColor;
  1222. else if (item->kind.any.color <= 0)
  1223. color = w->plot.BackgroundColor;
  1224. else
  1225. color = item->kind.any.color;
  1226. XSetForeground(XtDisplay(w), gc, w->plot.colors[color]);
  1227. return gc;
  1228. }
  1229. static GC
  1230. ItemGetFontGC (SciPlotWidget w, SciPlotItem *item)
  1231. {
  1232. GC gc;
  1233. short color, fontnum;
  1234. gc = w->plot.dashGC;
  1235. if (w->plot.Monochrome)
  1236. if (item->kind.any.color > 0)
  1237. color = w->plot.ForegroundColor;
  1238. else
  1239. color = w->plot.BackgroundColor;
  1240. else if (item->kind.any.color >= w->plot.num_colors)
  1241. color = w->plot.ForegroundColor;
  1242. else if (item->kind.any.color <= 0)
  1243. color = w->plot.BackgroundColor;
  1244. else
  1245. color = item->kind.any.color;
  1246. XSetForeground(XtDisplay(w), gc, w->plot.colors[color]);
  1247. if (item->kind.text.font >= w->plot.num_fonts)
  1248. fontnum = 0;
  1249. else
  1250. fontnum = item->kind.text.font;
  1251. /*
  1252. * fontnum==0 hack: 0 is supposed to be the default font, but the program
  1253. * can't seem to get the default font ID from the GC for some reason. So,
  1254. * use a different GC where the default font still exists.
  1255. */
  1256. XSetFont(XtDisplay(w), gc, w->plot.fonts[fontnum].font->fid);
  1257. return gc;
  1258. }
  1259. static void
  1260. ItemDraw (SciPlotWidget w, SciPlotItem *item)
  1261. {
  1262. XPoint point[8];
  1263. XSegment seg;
  1264. XRectangle rect;
  1265. int i;
  1266. GC gc;
  1267. if (!XtIsRealized((Widget) w))
  1268. return;
  1269. if ((item->type > SciPlotStartTextTypes) && (item->type < SciPlotEndTextTypes))
  1270. gc = ItemGetFontGC(w, item);
  1271. else
  1272. gc = ItemGetGC(w, item);
  1273. if (!gc)
  1274. return;
  1275. #if DEBUG_SCIPLOT_LINE
  1276. SciPlotPrintf("ItemDraw: item->type=%d\n"
  1277. " SciPlotFALSE=%d SciPlotPoint=%d SciPlotLine=%d \n",
  1278. item->type,SciPlotFALSE,SciPlotPoint,SciPlotLine);
  1279. #endif
  1280. switch (item->type) {
  1281. case SciPlotLine:
  1282. seg.x1 = (short) item->kind.line.x1;
  1283. seg.y1 = (short) item->kind.line.y1;
  1284. seg.x2 = (short) item->kind.line.x2;
  1285. seg.y2 = (short) item->kind.line.y2;
  1286. XDrawSegments(XtDisplay(w), XtWindow(w), gc,
  1287. &seg, 1);
  1288. break;
  1289. case SciPlotRect:
  1290. XDrawRectangle(XtDisplay(w), XtWindow(w), gc,
  1291. (int) (item->kind.rect.x),
  1292. (int) (item->kind.rect.y),
  1293. (unsigned int) (item->kind.rect.w),
  1294. (unsigned int) (item->kind.rect.h));
  1295. break;
  1296. case SciPlotFRect:
  1297. XFillRectangle(XtDisplay(w), XtWindow(w), gc,
  1298. (int) (item->kind.rect.x),
  1299. (int) (item->kind.rect.y),
  1300. (unsigned int) (item->kind.rect.w),
  1301. (unsigned int) (item->kind.rect.h));
  1302. XDrawRectangle(XtDisplay(w), XtWindow(w), gc,
  1303. (int) (item->kind.rect.x),
  1304. (int) (item->kind.rect.y),
  1305. (unsigned int) (item->kind.rect.w),
  1306. (unsigned int) (item->kind.rect.h));
  1307. break;
  1308. case SciPlotPoly:
  1309. i = 0;
  1310. while (i < item->kind.poly.count) {
  1311. point[i].x = (int) item->kind.poly.x[i];
  1312. point[i].y = (int) item->kind.poly.y[i];
  1313. i++;
  1314. }
  1315. point[i].x = (int) item->kind.poly.x[0];
  1316. point[i].y = (int) item->kind.poly.y[0];
  1317. XDrawLines(XtDisplay(w), XtWindow(w), gc,
  1318. point, i + 1, CoordModeOrigin);
  1319. break;
  1320. case SciPlotFPoly:
  1321. i = 0;
  1322. while (i < item->kind.poly.count) {
  1323. point[i].x = (int) item->kind.poly.x[i];
  1324. point[i].y = (int) item->kind.poly.y[i];
  1325. i++;
  1326. }
  1327. point[i].x = (int) item->kind.poly.x[0];
  1328. point[i].y = (int) item->kind.poly.y[0];
  1329. XFillPolygon(XtDisplay(w), XtWindow(w), gc,
  1330. point, i + 1, Complex, CoordModeOrigin);
  1331. XDrawLines(XtDisplay(w), XtWindow(w), gc,
  1332. point, i + 1, CoordModeOrigin);
  1333. break;
  1334. case SciPlotCircle:
  1335. XDrawArc(XtDisplay(w), XtWindow(w), gc,
  1336. (int) (item->kind.circ.x - item->kind.circ.r),
  1337. (int) (item->kind.circ.y - item->kind.circ.r),
  1338. (unsigned int) (item->kind.circ.r * 2),
  1339. (unsigned int) (item->kind.circ.r * 2),
  1340. 0 * 64, 360 * 64);
  1341. break;
  1342. case SciPlotFCircle:
  1343. XFillArc(XtDisplay(w), XtWindow(w), gc,
  1344. (int) (item->kind.circ.x - item->kind.circ.r),
  1345. (int) (item->kind.circ.y - item->kind.circ.r),
  1346. (unsigned int) (item->kind.circ.r * 2),
  1347. (unsigned int) (item->kind.circ.r * 2),
  1348. 0 * 64, 360 * 64);
  1349. break;
  1350. case SciPlotText:
  1351. XDrawString(XtDisplay(w), XtWindow(w), gc,
  1352. (int) (item->kind.text.x), (int) (item->kind.text.y),
  1353. item->kind.text.text,
  1354. (int) item->kind.text.length);
  1355. break;
  1356. case SciPlotVText:
  1357. XDrawVString(XtDisplay(w), XtWindow(w), gc,
  1358. (int) (item->kind.text.x), (int) (item->kind.text.y),
  1359. item->kind.text.text,
  1360. (int) item->kind.text.length,
  1361. FontFromFontnum(w, item->kind.text.font));
  1362. break;
  1363. case SciPlotClipRegion:
  1364. rect.x = (short) item->kind.line.x1;
  1365. rect.y = (short) item->kind.line.y1;
  1366. rect.width = (short) item->kind.line.x2;
  1367. rect.height = (short) item->kind.line.y2;
  1368. XSetClipRectangles(XtDisplay(w), w->plot.dashGC, 0, 0, &rect, 1, Unsorted);
  1369. XSetClipRectangles(XtDisplay(w), w->plot.defaultGC, 0, 0, &rect, 1, Unsorted);
  1370. break;
  1371. case SciPlotClipClear:
  1372. XSetClipMask(XtDisplay(w), w->plot.dashGC, None);
  1373. XSetClipMask(XtDisplay(w), w->plot.defaultGC, None);
  1374. break;
  1375. default:
  1376. #if DEBUG_SCIPLOT_LINE
  1377. SciPlotPrintf("ItemDraw: default case\n");
  1378. #endif
  1379. break;
  1380. }
  1381. }
  1382. static void
  1383. ItemDrawAll (SciPlotWidget w)
  1384. {
  1385. SciPlotItem *item;
  1386. int i;
  1387. if (!XtIsRealized((Widget) w))
  1388. return;
  1389. item = w->plot.drawlist;
  1390. i = 0;
  1391. while (i < w->plot.num_drawlist) {
  1392. ItemDraw(w, item);
  1393. i++;
  1394. item++;
  1395. }
  1396. }
  1397. /*
  1398. * PostScript (r) functions ------------------------------------------------
  1399. *
  1400. */
  1401. typedef struct {
  1402. char *command;
  1403. char *prolog;
  1404. } PScommands;
  1405. static PScommands psc[] =
  1406. {
  1407. {"ma", "moveto"},
  1408. {"da", "lineto stroke newpath"},
  1409. {"la", "lineto"},
  1410. {"poly", "closepath stroke newpath"},
  1411. {"fpoly", "closepath fill newpath"},
  1412. {"box", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath stroke newpath"},
  1413. {"fbox", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill newpath"},
  1414. {"clipbox", "gsave 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath clip newpath"},
  1415. {"unclip", "grestore newpath"},
  1416. {"cr", "0 360 arc stroke newpath"},
  1417. {"fcr", "0 360 arc fill newpath"},
  1418. {"vma", "gsave moveto 90 rotate"},
  1419. {"norm", "grestore"},
  1420. {"solid", "[] 0 setdash"},
  1421. {"dot", "[.25 2] 0 setdash"},
  1422. {"widedot", "[.25 8] 0 setdash"},
  1423. {"rgb", "setrgbcolor"},
  1424. {NULL, NULL}
  1425. };
  1426. enum PSenums {
  1427. PSmoveto, PSlineto,
  1428. PSpolyline, PSendpoly, PSendfill,
  1429. PSbox, PSfbox,
  1430. PSclipbox, PSunclip,
  1431. PScircle, PSfcircle,
  1432. PSvmoveto, PSnormal,
  1433. PSsolid, PSdot, PSwidedot,
  1434. PSrgb
  1435. };
  1436. static void
  1437. ItemPSDrawAll (SciPlotWidget w, FILE *fd, float yflip, int usecolor)
  1438. {
  1439. int i, loopcount;
  1440. SciPlotItem *item;
  1441. XcmsColor currentcolor;
  1442. int previousfont, previousline, currentfont, currentline, previouscolor;
  1443. item = w->plot.drawlist;
  1444. loopcount = 0;
  1445. previousfont = 0;
  1446. previouscolor = -1;
  1447. previousline = XtLINE_SOLID;
  1448. while (loopcount < w->plot.num_drawlist) {
  1449. /* 2 switch blocks: 1st sets up defaults, 2nd actually draws things. */
  1450. currentline = previousline;
  1451. currentfont = previousfont;
  1452. switch (item->type) {
  1453. case SciPlotLine:
  1454. case SciPlotCircle:
  1455. currentline = item->kind.any.style;
  1456. break;
  1457. default:
  1458. break;
  1459. }
  1460. if (currentline != XtLINE_NONE) {
  1461. if (currentline != previousline) {
  1462. switch (item->kind.any.style) {
  1463. case XtLINE_SOLID:
  1464. fprintf(fd, "%s ", psc[PSsolid].command);
  1465. break;
  1466. case XtLINE_DOTTED:
  1467. fprintf(fd, "%s ", psc[PSdot].command);
  1468. break;
  1469. case XtLINE_WIDEDOT:
  1470. fprintf(fd, "%s ", psc[PSwidedot].command);
  1471. break;
  1472. }
  1473. previousline = currentline;
  1474. }
  1475. if (usecolor && item->kind.any.color != previouscolor) {
  1476. /* Get Pixel index */
  1477. currentcolor.pixel = w->plot.colors[item->kind.any.color];
  1478. #ifdef WIN32
  1479. /* Exceed 5 does not have Xcms routines
  1480. * Only want to get colors as XcmsFloat=double in range [0.0,1.0]
  1481. * So use XQueryColors and convert */
  1482. {
  1483. XColor xcolor;
  1484. XQueryColor( XtDisplay(w), w->plot.cmap, &xcolor);
  1485. currentcolor.spec.RGBi.red = (double)xcolor.red/65535.;
  1486. currentcolor.spec.RGBi.green = (double)xcolor.green/65535.;
  1487. currentcolor.spec.RGBi.blue = (double)xcolor.blue/65535.;
  1488. currentcolor.format = XcmsRGBiFormat;
  1489. }
  1490. #else
  1491. /* Get RGBi components [0.0,1.0] */
  1492. XcmsQueryColor( XtDisplay(w), w->plot.cmap, &currentcolor,
  1493. XcmsRGBiFormat );
  1494. #endif
  1495. /* output PostScript command */
  1496. fprintf(fd, "%f %f %f %s ", currentcolor.spec.RGBi.red,
  1497. currentcolor.spec.RGBi.green, currentcolor.spec.RGBi.blue,
  1498. psc[PSrgb].command);
  1499. previouscolor=item->kind.any.color;
  1500. }
  1501. switch (item->type) {
  1502. case SciPlotLine:
  1503. fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
  1504. item->kind.line.x1, yflip - item->kind.line.y1,
  1505. psc[PSmoveto].command,
  1506. item->kind.line.x2, yflip - item->kind.line.y2,
  1507. psc[PSlineto].command);
  1508. break;
  1509. case SciPlotRect:
  1510. fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
  1511. item->kind.rect.x,
  1512. yflip - item->kind.rect.y - (item->kind.rect.h - 1.0),
  1513. psc[PSmoveto].command,
  1514. item->kind.rect.w - 1.0, item->kind.rect.h - 1.0,
  1515. psc[PSbox].command);
  1516. break;
  1517. case SciPlotFRect:
  1518. fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
  1519. item->kind.rect.x,
  1520. yflip - item->kind.rect.y - (item->kind.rect.h - 1.0),
  1521. psc[PSmoveto].command,
  1522. item->kind.rect.w - 1.0, item->kind.rect.h - 1.0,
  1523. psc[PSfbox].command);
  1524. break;
  1525. case SciPlotPoly:
  1526. fprintf(fd, "%.2f %.2f %s ",
  1527. item->kind.poly.x[0], yflip - item->kind.poly.y[0],
  1528. psc[PSmoveto].command);
  1529. for (i = 1; i < item->kind.poly.count; i++) {
  1530. fprintf(fd, "%.2f %.2f %s ",
  1531. item->kind.poly.x[i],
  1532. yflip - item->kind.poly.y[i],
  1533. psc[PSpolyline].command);
  1534. }
  1535. fprintf(fd, "%s\n", psc[PSendpoly].command);
  1536. break;
  1537. case SciPlotFPoly:
  1538. fprintf(fd, "%.2f %.2f %s ",
  1539. item->kind.poly.x[0], yflip - item->kind.poly.y[0],
  1540. psc[PSmoveto].command);
  1541. for (i = 1; i < item->kind.poly.count; i++) {
  1542. fprintf(fd, "%.2f %.2f %s ",
  1543. item->kind.poly.x[i],
  1544. yflip - item->kind.poly.y[i],
  1545. psc[PSpolyline].command);
  1546. }
  1547. fprintf(fd, "%s\n", psc[PSendfill].command);
  1548. break;
  1549. case SciPlotCircle:
  1550. fprintf(fd, "%.2f %.2f %.2f %s\n",
  1551. item->kind.circ.x, yflip - item->kind.circ.y,
  1552. item->kind.circ.r,
  1553. psc[PScircle].command);
  1554. break;
  1555. case SciPlotFCircle:
  1556. fprintf(fd, "%.2f %.2f %.2f %s\n",
  1557. item->kind.circ.x, yflip - item->kind.circ.y,
  1558. item->kind.circ.r,
  1559. psc[PSfcircle].command);
  1560. break;
  1561. case Sci

Large files files are truncated, but you can click here to view the full file