home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xodometr / part04 < prev    next >
Encoding:
Text File  |  1993-04-27  |  48.0 KB  |  1,373 lines

  1. Newsgroups: comp.sources.x
  2. From: lusol@Turkey.CC.Lehigh.EDU (Stephen O. Lidie)
  3. Subject: v19i040:  xodometer - Track pointer and measure distance moved, Part04/04
  4. Message-ID: <1993Mar11.161652.17576@sparky.imd.sterling.com>
  5. X-Md4-Signature: e2da2485ed3544cd5833cbd942e89342
  6. Date: Thu, 11 Mar 1993 16:16:52 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: lusol@Turkey.CC.Lehigh.EDU (Stephen O. Lidie)
  10. Posting-number: Volume 19, Issue 40
  11. Archive-name: xodometer/part04
  12. Environment: X11
  13.  
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 4 (of 4)."
  22. # Contents:  xodo.c
  23. # Wrapped by lusol@Turkey.CC.Lehigh.EDU on Wed Mar 10 19:42:13 1993
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'xodo.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'xodo.c'\"
  27. else
  28. echo shar: Extracting \"'xodo.c'\" \(45761 characters\)
  29. sed "s/^X//" >'xodo.c' <<'END_OF_FILE'
  30. X/*
  31. X
  32. X  xodometer - Track the total distance your pointing device and cursor
  33. X              travel.  The distance can be displayed in various units.
  34. X
  35. X  Inspired by the MacIntosh Mouse Odometer by Sean P. Nolan.          
  36. X
  37. X  Template code from xneko by Masayuki Koba.
  38. X
  39. X  For X11 Release 4.
  40. X
  41. X  Stephen O. Lidie, 93/01/20.  lusol@Lehigh.EDU
  42. X
  43. X
  44. X  Given the number of pixels and the screen dimensions in millimeters
  45. X  we use this distance formula:
  46. X
  47. X  distance = sqrt( (dX * (Xmm/Xpixels))**2 + (dY * (Ymm/Ypixels))**2 )
  48. X
  49. X  Where dX and dY are pixel differentials, and Xmm, Ymm and Xpixels,
  50. X  Ypixels are the screen dimensions in millimeters and pixels,
  51. X  respectively.
  52. X
  53. X  My first X application and my first graphical application too.  Yes,
  54. X  I used Xlib for the experience... never again though!
  55. X  
  56. X*/
  57. X
  58. X
  59. X#include <X11/Xlib.h>
  60. X#include <X11/Xutil.h>
  61. X#include <X11/Xresource.h>
  62. X
  63. X#include <stdio.h>
  64. X#include <signal.h>
  65. X#include <math.h>
  66. X#include <sys/time.h>
  67. X#include <sys/errno.h>
  68. X
  69. X#include "evap/evap.h"
  70. X#include "evap/xodo_pdt.out"
  71. X
  72. X#include "patchlevel.h"
  73. X
  74. X#include "bitmaps/icon.xbm"
  75. X#include "bitmaps/cursor.xbm"
  76. X#include "bitmaps/cur_mask.xbm"
  77. X#include "bitmaps/pulldown.xbm"
  78. X
  79. X#define DEBUG           0    /* 1 IFF debug */
  80. X
  81. X#define CURSOR_S        "Cursor"
  82. X#define POINTER_S       "Pointer"
  83. X
  84. X/*
  85. X  EVENT_MASK1 - Top level window.
  86. X  EVENT_MASK2 - Action windows like About, Quit, Units and trip odometer reset buttons.
  87. X  EVENT_MASK3 - Menu pane windows.
  88. X*/
  89. X
  90. X#define    EVENT_MASK1    ButtonPressMask | ButtonReleaseMask | ExposureMask | StructureNotifyMask
  91. X#define EVENT_MASK2    ButtonPressMask | ButtonReleaseMask | OwnerGrabButtonMask | EnterWindowMask | LeaveWindowMask
  92. X#define EVENT_MASK3     ButtonPressMask | ButtonReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask
  93. X
  94. X/* The ALL_EVENTS_MASK mask is a superset of all possible events that ANY window might need. */
  95. X
  96. X#define ALL_EVENTS_MASK EVENT_MASK1 | EVENT_MASK2 | EVENT_MASK3
  97. X
  98. X/* Action window ordinals. */
  99. X
  100. X#define TRIP1           0
  101. X#define TRIP2           1
  102. X#define QUIT            2
  103. X#define UNITS           3
  104. X#define ABOUT           4
  105. X
  106. X/* Odometer ordinals. */
  107. X
  108. X#define CURSOR          0
  109. X#define POINTER         1
  110. X#define BOTH            2
  111. X
  112. X/* Function prototypes, sorta. */
  113. X
  114. Xvoid                    compute_font_and_resize_data();
  115. Xvoid                    draw_action_windows();
  116. Xvoid                    draw_menu();
  117. Xvoid                    draw_menu_panes();
  118. Xvoid                    draw_misc_info();
  119. Xvoid                    draw_odometers();
  120. Xvoid                    draw_odometer_digit();
  121. Xint                     evap();
  122. Xvoid                    evap_type_conversion();
  123. Xvoid                    finish_xodo();
  124. Xvoid                    highlight_action_window();
  125. Xvoid                    initialize_graphics_contexts();
  126. Xvoid                    initialize_menu();
  127. Xvoid                    initialize_xodo();
  128. XBool                    process_event();
  129. Xvoid                    process_pointer();
  130. Xvoid                    save_xodo();
  131. X
  132. X/* Global variables, more or less alphabetically. */
  133. X
  134. Xchar                    *about[] = {
  135. X                          "         xodometer xxx",
  136. X                          " ",
  137. X                          "The Mac Mouse Odometer, X Style ",
  138. X                          "   Stephen O. Lidie, 93/02/11",
  139. X                          "       lusol@Lehigh.EDU",
  140. X              " ",
  141. X              "   For help:  xodo -full_help",
  142. X            };
  143. Xshort                   about_active = False;
  144. Xint                     about_count = sizeof( about ) / sizeof( *about );
  145. Xint                     about_width, about_height;
  146. Xint                     about_width_old, about_height_old, about_x_old, about_y_old;
  147. Xint                     about_width_x;
  148. Xint                     accel_numerator, accel_denominator;
  149. Xdouble                  acceleration;
  150. Xint                     ascent;
  151. Xfloat                   aspect;
  152. XAtom                    atom_wm_save_yourself;
  153. Xint                     autosave_count, autosave_ticks;
  154. Xunsigned int        BorderWidth = 2;
  155. Xshort                   button_depressed = False;
  156. Xchar                    calibration[] = "2.54 cm/in";
  157. Xint                     calibration_width;
  158. Xint                     coordinates_x, coordinates_y;
  159. X
  160. X#if DEBUG
  161. XFILE                    *d;
  162. X#endif
  163. X
  164. Xint                     descent;
  165. Xint                     direction;
  166. Xunsigned int            display_width, display_height;
  167. Xunsigned int            display_widthmm, display_heightmm;
  168. Xdouble                  distance;
  169. Xstruct distances {
  170. X  char *name;
  171. X  char *abbreviation;
  172. X  Window menu_pane;
  173. X  double value;
  174. X}                       distances[] = {
  175. X                          {"millimeters",        "mm ", None, 1.0},
  176. X                          {"centimeters",        "cm ", None, 0.1},
  177. X                          {"decimeters",         "dm ", None, 0.01},
  178. X                          {"meters",             "m  ", None, 0.001},
  179. X                          {"dekameters",         "dam", None, 0.0001},
  180. X                          {"hectometers",        "hm ", None, 0.00001},
  181. X                          {"kilometers",         "km ", None, 0.000001},
  182. X                          {"myriameters",        "mym", None, 0.0000001},
  183. X                          {"inches",             "in ", None, 0.1/2.54},
  184. X                          {"feet",               "ft ", None, 0.1/2.54/12.0},
  185. X                          {"yards",              "yd ", None, 0.1/2.54/12.0/3.0},
  186. X                          {"rods",               "rd ", None, 0.1/2.54/12.0/3.0/5.5},
  187. X                          {"miles",              "mi ", None, 0.1/2.54/12.0/3.0/1760.0},
  188. X                          {"furlongs",           "fl ", None, 0.1/2.54/12.0/3.0/220.0},
  189. X                          {"fathoms",            "fm ", None, 0.1/2.54/12.0/6.0},
  190. X                          {"light-nanoseconds",  "lns", None, 0.001/299792458.0*1.0E+9},
  191. X              {"marine_leagues",     "mlg", None, 0.001/1852.0/3.0},
  192. X              {"nautical_miles",     "nm ", None, 0.001/1852.0},
  193. X                        };
  194. Xchar                    distances_human[] = "U=lns";
  195. Xint                     distances_ordinal = 0;
  196. Xextern                  errno;
  197. XXFontStruct             *font_info;
  198. XXFontStruct             *font_info2;
  199. Xchar                    *fontname;
  200. Xint                     font_width, font_height;
  201. XGC                      gc;
  202. XGC                      gc2;
  203. XGC                      gc3;
  204. XGC                      gc_reverse;
  205. XGC                      gc2_reverse;
  206. Xint                     label_cursor_x, label_cursor_y;
  207. Xint                     label_pointer_x, label_pointer_y;
  208. Xshort                   menu_active = False;
  209. Xint                     menu_border_width = 4;
  210. Xint                     menu_pane_count = sizeof( distances) / sizeof( struct distances );
  211. Xint                     menu_pane_height;
  212. Xint                     menu_width, menu_height;
  213. Xint                     menu_width_old, menu_height_old, menu_x_old, menu_y_old;
  214. Xunsigned long           motion_buffer_size;
  215. Xint                     odometer_count = BOTH;
  216. XFILE                    *OF;
  217. Xchar                    old_line1[20] = "!!!!!!!!!!!!!!!!!!!";
  218. Xchar                    old_line2[20] = "!!!!!!!!!!!!!!!!!!!";
  219. Xchar                    old_line3[20] = "!!!!!!!!!!!!!!!!!!!";
  220. Xchar                    old_line4[20] = "!!!!!!!!!!!!!!!!!!!";
  221. XXCharStruct             overall;
  222. Xint                     pixels_per_cm_x, pixels_per_cm_y;
  223. Xint                     pixels_per_inch_x, pixels_per_inch_y;
  224. Xint            PointerX;
  225. Xint            PointerY;
  226. Xint            PrevPointerX = 0;
  227. Xint            PrevPointerY = 0;
  228. Xchar            *ProgramName;
  229. XPixmap                  pulldown;
  230. XXRectangle              rectangles[10] = {   3, 25, 20, 20,
  231. X                                            23, 25, 20, 20,
  232. X                        43, 25, 20, 20,
  233. X                        63, 25, 20, 20,
  234. X                        83, 25, 20, 20,
  235. X                       103, 25, 20, 20,
  236. X                       123, 25, 20, 20,
  237. X                       143, 25, 20, 20,
  238. X                       163, 25, 20, 20,
  239. X                       183, 25, 20, 20,
  240. X                                         };
  241. XXRectangle              rectangles2[10];
  242. XXRectangle              rectangles3[10];
  243. XXRectangle              rectangles4[10];
  244. XStatus                  status;
  245. XXColor            theBackgroundColor;
  246. Xunsigned long        theBackgroundPixel;
  247. XXColor                  theBorderColor;
  248. Xunsigned long           theBorderPixel;
  249. XCursor                  theCursor;
  250. Xunsigned int        theDepth;
  251. XDisplay            *theDisplay;
  252. XXColor            theExactColor;
  253. XXColor            theForegroundColor;
  254. Xunsigned long        theForegroundPixel;
  255. XPixmap            theIconPixmap;
  256. XWindow                  theMenu;
  257. XWindow            theRoot;
  258. Xint            theScreen;
  259. XWindow            theWindow;
  260. Xint                     threshold;
  261. Xdouble                  total_cursor_distance, trip_cursor_distance; /* distances in millimeters */
  262. Xdouble                  total_pointer_distance, trip_pointer_distance; /* distances in millimeters */
  263. Xunsigned long           valuemask;
  264. XXGCValues               values;
  265. Xstruct windata{
  266. X  Window window;
  267. X  int color;
  268. X  char *text;
  269. X  int x;
  270. X  int y;
  271. X  int width;
  272. X  int height;
  273. X  int border;
  274. X}                       windata[] = {
  275. X                          {None, 0, "",          0, 0,  8,  3, 2},
  276. X                          {None, 0, "",          0, 0,  8,  3, 2},
  277. X                          {None, 0, "Quit",     40, 2, 25, 10, 2},
  278. X                          {None, 0, "  Units", 205, 2, 45, 10, 2},
  279. X                          {None, 0, "About",     2, 2, 30, 10, 2}, 
  280. X                        };
  281. Xint                     windata_count = sizeof( windata) / sizeof( struct windata );
  282. Xint                     window_width = 1;
  283. Xint                 window_height = 1;
  284. Xunsigned int        WindowHeight = 1;
  285. Xint              WindowPointX = 1;
  286. Xint              WindowPointY = 1;
  287. Xunsigned int        WindowWidth = 1;
  288. Xdouble                  X_mm_per_pixel, Y_mm_per_pixel;
  289. Xchar                    status_line[100];
  290. X
  291. X
  292. X
  293. X
  294. X/* Global procedures; again, alphabetically. */
  295. X
  296. X
  297. X
  298. X
  299. Xvoid
  300. Xcompute_font_and_resize_data( font_info ) /* size rectangles et. al. based on font */
  301. X     XFontStruct                *font_info;
  302. X{
  303. X
  304. X  int                           i, width_incr;
  305. X
  306. X  if ( font_info != NULL ) {
  307. X
  308. X    font_width = font_info->max_bounds.rbearing - font_info->min_bounds.lbearing;
  309. X    font_height = font_info->max_bounds.ascent + font_info->max_bounds.descent;
  310. X
  311. X    for ( i = 0; i < 10; i++ ) {
  312. X      rectangles[i].height = font_height + 5;
  313. X      rectangles[i].width = rectangles[i].height;
  314. X      if ( i > 0 )
  315. X    rectangles[i].x = rectangles[i-1].x + font_height + 5;
  316. X      if ( font_height + 5 > 25 )
  317. X    rectangles[i].y = font_height + 5;
  318. X    }
  319. X
  320. X  }
  321. X
  322. X  width_incr = (int)( aspect * (float)rectangles[0].width - (float)rectangles[0].width );
  323. X
  324. X  for( i = 0; i < 10; i++ ){
  325. X    if ( i >= 5 )
  326. X      rectangles[i].height += 1;
  327. X    rectangles[i].width += width_incr;
  328. X    rectangles[i].x = rectangles[i].x + (i * width_incr);
  329. X    
  330. X    rectangles2[i] = rectangles[i];
  331. X    rectangles2[i].y = rectangles[i].y + (font_height * 2);
  332. X    
  333. X    rectangles3[i] = rectangles[i];
  334. X    rectangles3[i].y = rectangles[i].y + (font_height * 5);
  335. X    
  336. X    rectangles4[i] = rectangles[i];
  337. X    rectangles4[i].y = rectangles[i].y + (font_height * 7);
  338. X  }
  339. X  
  340. X  windata[TRIP1].x = rectangles2[0].x;
  341. X  windata[TRIP1].y = rectangles2[0].y - 7;
  342. X  windata[TRIP2].x = rectangles4[0].x;
  343. X  windata[TRIP2].y = rectangles4[0].y - 7;
  344. X  
  345. X  window_width = rectangles[9].x + rectangles[9].width + 3;
  346. X
  347. X  i = font_info2->max_bounds.ascent + font_info2->max_bounds.descent;
  348. X  if ( font_height > i )
  349. X    window_height = rectangles4[0].y + 7 + (font_height * 2);
  350. X  else
  351. X    window_height = rectangles4[0].y + 7 + (i * 2);
  352. X  if ( odometer_count != BOTH )
  353. X    window_height = window_height + rectangles2[0].y - rectangles4[0].y;
  354. X
  355. X  about_width_x = window_width;
  356. X
  357. X  XTextExtents( font_info, CURSOR_S, strlen( CURSOR_S ), &direction, &ascent, &descent, &overall );
  358. X  label_cursor_x = ( window_width - overall.width ) / 2;
  359. X  label_cursor_y = rectangles[0].y - (font_height/2) + font_info->max_bounds.descent;
  360. X  XTextExtents( font_info, POINTER_S, strlen( POINTER_S ), &direction, &ascent, &descent, &overall );
  361. X  label_pointer_x = ( window_width - overall.width ) / 2;
  362. X  label_pointer_y = rectangles3[0].y - (font_height/2) + font_info->max_bounds.descent;
  363. X
  364. X  if ( font_info != NULL ) {
  365. X    if ( (WindowWidth != window_width) || (WindowHeight != window_height) ) {
  366. X      WindowWidth = window_width;
  367. X      WindowHeight = window_height;
  368. X      XMoveWindow( theDisplay, windata[TRIP1].window, windata[TRIP1].x, windata[TRIP1].y );
  369. X      if ( odometer_count == BOTH )
  370. X    XMoveWindow( theDisplay, windata[TRIP2].window, windata[TRIP2].x, windata[TRIP2].y );
  371. X      XMoveWindow( theDisplay, windata[UNITS].window, window_width-50, windata[UNITS].y );
  372. X      XResizeWindow( theDisplay, theWindow, WindowWidth, WindowHeight );
  373. X    }
  374. X  } /* ifend font_info != NULL */
  375. X
  376. X  coordinates_x = 1;        /* compute Units and absolute coordinates display postion */
  377. X  coordinates_y = rectangles4[0].y + font_height + (font_height / 2) + font_info2->max_bounds.ascent + 2;
  378. X  if ( odometer_count != BOTH ) {
  379. X    coordinates_y += (rectangles2[0].y - rectangles4[0].y);
  380. X  }
  381. X
  382. X} /* end compute_font_and_resize_data */
  383. X
  384. X
  385. X
  386. X
  387. Xvoid
  388. Xdo_distances( refresh_digits )    /* compute and display the distances */
  389. X     short                      refresh_digits;
  390. X{
  391. X
  392. X    Window               QueryRoot, QueryChild;
  393. X    int                    AbsoluteX, AbsoluteY;
  394. X    int                    RelativeX, RelativeY;
  395. X    unsigned int            ModKeyMask;
  396. X    double                dXmm, dYmm;
  397. X    int                         dX, dY;
  398. X    char                        line1[20], line2[20], line3[20], line4[20];
  399. X    double                      units;
  400. X    int                         i, n, x, y;
  401. X    char                        coordinates[13]; /* allows for a 99,999 by 99,999 display */
  402. X    int                         coord_len;
  403. X
  404. X    if ( refresh_digits ) {
  405. X      strcpy( old_line1, "!!!!!!!!!!!!!!!!!!!" );
  406. X      strcpy( old_line2, "!!!!!!!!!!!!!!!!!!!" );
  407. X      strcpy( old_line3, "!!!!!!!!!!!!!!!!!!!" );
  408. X      strcpy( old_line4, "!!!!!!!!!!!!!!!!!!!" );
  409. X    }
  410. X
  411. X    XQueryPointer( theDisplay, theWindow, &QueryRoot, &QueryChild, &AbsoluteX, &AbsoluteY, &RelativeX, &RelativeY, &ModKeyMask );
  412. X
  413. X    PrevPointerX = PointerX;
  414. X    PrevPointerY = PointerY;
  415. X
  416. X    PointerX = AbsoluteX;
  417. X    PointerY = AbsoluteY;
  418. X
  419. X    dX = PointerX - PrevPointerX;
  420. X    dY = PointerY - PrevPointerY;
  421. X
  422. X    if ( dX < 0.0 )
  423. X      dX = -dX;
  424. X    if ( dY < 0.0 )
  425. X      dY = -dY;
  426. X    
  427. X    dXmm = (double)dX * X_mm_per_pixel;
  428. X    dYmm = (double)dY * Y_mm_per_pixel;
  429. X
  430. X    distance = sqrt( (dXmm * dXmm) + (dYmm * dYmm) );
  431. X
  432. X    if ( distance != 0 ) {
  433. X
  434. X      trip_cursor_distance += distance;
  435. X      total_cursor_distance += distance;
  436. X      if ( dX > threshold || dY > threshold ) {
  437. X    distance /= acceleration; /* if cursor was accelerated, we suppose! */
  438. X      }
  439. X      distance /= pvt[P_POINTER_SCALE_FACTOR].value.real_value;
  440. X      trip_pointer_distance += distance;
  441. X      total_pointer_distance += distance;
  442. X    }
  443. X
  444. X    units = distances[distances_ordinal].value;
  445. X
  446. X    if ( odometer_count == CURSOR || odometer_count == BOTH ) {
  447. X      sprintf( line1, "%011.5f", fmod( (total_cursor_distance * units), 100000.0 ) );
  448. X      sprintf( line2, "%011.5f", fmod( (trip_cursor_distance * units), 100000.0 ) );
  449. X    } else if ( odometer_count == POINTER ) {
  450. X      sprintf( line1, "%011.5f", fmod( (total_pointer_distance * units), 100000.0 ) );
  451. X      sprintf( line2, "%011.5f", fmod( (trip_pointer_distance * units), 100000.0 ) );
  452. X    }
  453. X    if ( odometer_count == BOTH ) {
  454. X      sprintf( line3, "%011.5f", fmod( (total_pointer_distance * units), 100000.0 ) );
  455. X      sprintf( line4, "%011.5f", fmod( (trip_pointer_distance * units), 100000.0 ) );
  456. X    }
  457. X
  458. X    for(i = 0, n = 0; i < 11; i++) {
  459. X      if ( i == 5 ) {
  460. X    continue;        /* skip units point */
  461. X      } else if ( i < 5 ) {    /* draw digits to the left of the point */
  462. X    draw_odometer_digit( gc, rectangles[n], line1+i, old_line1+i );
  463. X    draw_odometer_digit( gc, rectangles2[n], line2+i, old_line2+i );
  464. X    if ( odometer_count == BOTH ) {
  465. X      draw_odometer_digit( gc, rectangles3[n], line3+i, old_line3+i );
  466. X      draw_odometer_digit( gc, rectangles4[n], line4+i, old_line4+i );
  467. X    }
  468. X      } else {            /* draw digits to the right of the point */
  469. X    draw_odometer_digit( gc_reverse, rectangles[n], line1+i, old_line1+i );
  470. X    draw_odometer_digit( gc_reverse, rectangles2[n], line2+i, old_line2+i );
  471. X    if ( odometer_count == BOTH ) {
  472. X      draw_odometer_digit( gc_reverse, rectangles3[n], line3+i, old_line3+i );
  473. X      draw_odometer_digit( gc_reverse, rectangles4[n], line4+i, old_line4+i );
  474. X    }
  475. X      }
  476. X      n++;            /* advance to next rectangle */
  477. X    }
  478. X
  479. X    sprintf( coordinates, "(%d,%d)", PointerX, PointerY ); /* draw absolute pointer coordinates */
  480. X                                                                       /* Einstein: 'You said "absolute"?' */
  481. X    coord_len = strlen( coordinates );
  482. X    strncpy( coordinates+coord_len, "             ", 13-coord_len );
  483. X    XDrawImageString( theDisplay, theWindow, gc2, coordinates_x+33, coordinates_y, coordinates, 13 );
  484. X
  485. X} /* end do_distances */
  486. X
  487. X
  488. X
  489. X
  490. Xvoid
  491. Xdraw_action_windows( gc )
  492. X     GC                gc;
  493. X{
  494. X
  495. X  int                           i;
  496. X
  497. X  for ( i = 0; i < windata_count; i++ ) {
  498. X    if ( odometer_count != BOTH && i == TRIP2 )
  499. X      continue;            /* skip second trip odometer if only 1 odometer */
  500. X    XDrawImageString( theDisplay, windata[i].window, gc, font_info2->max_bounds.lbearing-3, font_info2->max_bounds.ascent+1,
  501. X          windata[i].text, strlen(windata[i].text) );
  502. X  } /* forend */
  503. X  XCopyPlane( theDisplay, pulldown, windata[UNITS].window, gc, 0, 0, pulldown_width, pulldown_height, 1, 1, 1 );
  504. X  
  505. X} /* end draw_action_windows */
  506. X
  507. X
  508. X
  509. X
  510. Xvoid
  511. Xdraw_menu()
  512. X{
  513. X
  514. X  int                new_width, new_height;
  515. X
  516. X  menu_active = True;
  517. X  XMapWindow( theDisplay, theMenu );
  518. X  menu_width_old = WindowWidth;
  519. X  menu_height_old = WindowHeight;
  520. X  if ( WindowWidth < menu_width + font_info->max_bounds.width ) 
  521. X    new_width = menu_width + font_info->max_bounds.width;
  522. X  else
  523. X    new_width = WindowWidth;
  524. X  if ( WindowHeight < menu_height + menu_pane_height ) 
  525. X    new_height = menu_height + menu_pane_height;
  526. X  else
  527. X    new_height = WindowHeight;
  528. X  menu_x_old = WindowPointX;
  529. X  menu_y_old = WindowPointY;
  530. X  if ( WindowPointY + new_height > display_height ) {
  531. X    menu_y_old = display_height - new_height;
  532. X  }
  533. X
  534. X  XMoveResizeWindow( theDisplay, theWindow, menu_x_old, menu_y_old, new_width, new_height );
  535. X  menu_y_old = WindowPointY;
  536. X  XGrabPointer( theDisplay, theMenu, True, EVENT_MASK2, GrabModeAsync, GrabModeAsync, None, theCursor, CurrentTime );
  537. X
  538. X} /* end draw_menu */
  539. X
  540. X
  541. X
  542. X
  543. Xvoid
  544. Xdraw_menu_panes( gc, window )
  545. X     GC                gc;
  546. X     Window                     window;
  547. X{
  548. X
  549. X  int                           i, j;
  550. X  char                          units_name[100];
  551. X
  552. X  for ( i = 0; i < menu_pane_count; i++ ) {
  553. X    if ( window  == distances[i].menu_pane ) {
  554. X      strcpy( units_name, distances[i].name );
  555. X      for ( j = 0; j < strlen( units_name ); j++ )
  556. X    if ( units_name[j] == '_' )
  557. X      units_name[j] = ' ';
  558. X      XDrawImageString( theDisplay, distances[i].menu_pane, gc, 1, font_info->max_bounds.ascent, units_name,
  559. X            strlen( units_name ) );
  560. X    } /* ifend */
  561. X  } /* forend */
  562. X  
  563. X} /* end draw_menu_panes */
  564. X
  565. X
  566. X
  567. X
  568. Xvoid
  569. Xdraw_misc_info()
  570. X{
  571. X
  572. X  int                           x, y;
  573. X  int                           i, n;
  574. X
  575. X  /* Draw the Units. */
  576. X
  577. X  XDrawImageString( theDisplay, theWindow, gc2, coordinates_x, coordinates_y, distances_human, strlen( distances_human ) );
  578. X  
  579. X  /* Draw the About information in a (normally) hidden part of the window. */
  580. X  
  581. X  for ( i = 0, n = font_height; i < about_count; i++, n += font_height ) {
  582. X    XDrawImageString( theDisplay, theWindow, gc, about_width_x, n, about[i], strlen( about[i] ) );
  583. X  }
  584. X  XCopyPlane( theDisplay, theIconPixmap, theWindow, gc, 0, 0, icon_width, icon_height, about_width_x,
  585. X         about_height-icon_height, 1 );
  586. X  XDrawImageString( theDisplay, theWindow, gc2, about_width_x+icon_width, about_height-(icon_height/2),
  587. X        status_line, strlen( status_line ) );           
  588. X
  589. X  /* Draw the calibration information in inches and centimeters. */
  590. X
  591. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3, about_height, about_width-3, about_height-pixels_per_inch_y );
  592. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3, about_height-pixels_per_cm_y,
  593. X        about_width-3-8, about_height-pixels_per_cm_y );
  594. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3, about_height-2*pixels_per_cm_y,
  595. X        about_width-3-8, about_height-2*pixels_per_cm_y );
  596. X
  597. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3, about_height, about_width-3-pixels_per_inch_x, about_height );
  598. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3-pixels_per_cm_x, about_height,
  599. X        about_width-3-pixels_per_cm_x, about_height-8 );
  600. X  XDrawLine( theDisplay, theWindow, gc3, about_width-3-2*pixels_per_cm_x, about_height,
  601. X        about_width-3-2*pixels_per_cm_x, about_height-8 );
  602. X  XDrawImageString( theDisplay, theWindow, gc3, about_width-calibration_width-20, about_height-pixels_per_cm_y, calibration,
  603. X        strlen( calibration ) );
  604. X
  605. X} /* end draw_misc_info */
  606. X
  607. X
  608. X
  609. X
  610. Xvoid
  611. Xdraw_odometers()
  612. X{
  613. X  
  614. X  if ( odometer_count == CURSOR || odometer_count == BOTH ) {
  615. X    XDrawImageString( theDisplay, theWindow, gc, label_cursor_x, label_cursor_y, CURSOR_S, strlen( CURSOR_S ) );
  616. X  } else {
  617. X    XDrawImageString( theDisplay, theWindow, gc, label_cursor_x, label_cursor_y,  POINTER_S, strlen( POINTER_S ) );
  618. X  }
  619. X  XDrawRectangles( theDisplay, theWindow, gc, rectangles, 5 );
  620. X  XFillRectangles( theDisplay, theWindow, gc, rectangles+5, 5 );
  621. X  
  622. X  XDrawRectangles( theDisplay, theWindow, gc, rectangles2, 5 );
  623. X  XFillRectangles( theDisplay, theWindow, gc, rectangles2+5, 5 );
  624. X  
  625. X  if ( odometer_count == BOTH ) {
  626. X    XDrawImageString( theDisplay, theWindow, gc, label_pointer_x, label_pointer_y, POINTER_S, strlen( POINTER_S ) );
  627. X    
  628. X    XDrawRectangles( theDisplay, theWindow, gc, rectangles3, 5 );
  629. X    XFillRectangles( theDisplay, theWindow, gc, rectangles3+5, 5 );
  630. X    
  631. X    XDrawRectangles( theDisplay, theWindow, gc, rectangles4, 5 );
  632. X    XFillRectangles( theDisplay, theWindow, gc, rectangles4+5, 5 );
  633. X  }
  634. X
  635. X  do_distances( True );        /* repaint odometer digits */
  636. X  
  637. X} /* end draw_odometers */
  638. X
  639. X
  640. X
  641. X
  642. Xvoid
  643. Xdraw_odometer_digit( gc, rectangle, line, old_line )
  644. X     GC                         gc;
  645. X     XRectangle            rectangle;
  646. X     char                       line[];
  647. X     char                       old_line[];
  648. X{
  649. X
  650. X  if ( line[0] == old_line[0] )
  651. X    return;
  652. X
  653. X  XDrawImageString( theDisplay, theWindow, gc, rectangle.x+(font_info->max_bounds.lbearing),
  654. X        rectangle.y+(font_info->max_bounds.ascent)+1, line+0, 1 );
  655. X
  656. X  old_line[0] = line[0];
  657. X
  658. X} /* end draw_odometer_digit */
  659. X
  660. X
  661. X
  662. X
  663. Xvoid
  664. Xfinish_xodo()            /* finish xodo */
  665. X{
  666. X
  667. X  save_xodo();            /* update state information */
  668. X
  669. X  XUnloadFont( theDisplay, font_info->fid );
  670. X  XUnloadFont( theDisplay, font_info2->fid );
  671. X  XFreeGC( theDisplay, gc);
  672. X  XFreeGC( theDisplay, gc2);
  673. X  XFreeGC( theDisplay, gc3);
  674. X  XFreeGC( theDisplay, gc_reverse);
  675. X  XFreeGC( theDisplay, gc2_reverse);
  676. X  XCloseDisplay( theDisplay );
  677. X
  678. X#if DEBUG
  679. X  fclose( d );
  680. X#endif
  681. X
  682. X  exit( 0 );
  683. X
  684. X} /* end finish_xodo */
  685. X
  686. X
  687. X
  688. X
  689. Xvoid
  690. Xhighlight_action_window( gc, window, border )    /* either normal or highlighted */
  691. X     GC                gc;
  692. X     Window                     window;
  693. X     unsigned long              border;
  694. X{
  695. X
  696. X  int                           i;
  697. X
  698. X  if ( menu_active )
  699. X    return;
  700. X
  701. X  for ( i = 0; i < windata_count; i++ ) {
  702. X    if ( window == windata[i].window ) {
  703. X      XSetWindowBorder( theDisplay, windata[i].window, border );
  704. X      XDrawImageString( theDisplay, windata[i].window, gc, font_info2->max_bounds.lbearing-3, 
  705. X          font_info2->max_bounds.ascent+1, windata[i].text, strlen(windata[i].text) );
  706. X      break;
  707. X    } /* ifend */
  708. X  } /* forend */
  709. X
  710. X  if ( i == UNITS )
  711. X    XCopyPlane( theDisplay, pulldown, windata[UNITS].window, gc, 0, 0, pulldown_width, pulldown_height, 1, 1, 1 );
  712. X
  713. X} /* end highlight_action_window */
  714. X
  715. X
  716. X
  717. X
  718. Xvoid
  719. Xinitialize_graphics_contexts()    /* initialize graphics context */
  720. X{
  721. X
  722. X  unsigned int                  line_width = 1;
  723. X  int                           line_style = LineSolid;
  724. X  int                           cap_style = CapRound;
  725. X  int                           join_style = JoinMiter;
  726. X  
  727. X  fontname = pvt[P_FONTNAME].value.string_value;
  728. X
  729. X  if ( (font_info = XLoadQueryFont( theDisplay, fontname )) == NULL ) {
  730. X    fprintf( stderr, "%s:  cannot open %s font.\n", ProgramName, fontname );
  731. X    exit( 1 );
  732. X  }
  733. X
  734. X  valuemask = GCFunction | GCForeground | GCBackground;
  735. X  values.function = GXcopy;
  736. X  values.foreground = theForegroundPixel;
  737. X  values.background = theBackgroundPixel;
  738. X  gc = XCreateGC( theDisplay, theWindow, valuemask, &values );
  739. X  XSetFont( theDisplay, gc, font_info->fid );
  740. X  XSetLineAttributes( theDisplay, gc, line_width, line_style, cap_style, join_style );
  741. X
  742. X  valuemask = GCFunction | GCForeground | GCBackground;
  743. X  values.function = GXcopy;
  744. X  values.foreground = theBackgroundPixel;
  745. X  values.background = theForegroundPixel;
  746. X  gc_reverse = XCreateGC( theDisplay, theWindow, valuemask, &values );
  747. X  XSetFont( theDisplay, gc_reverse, font_info->fid );
  748. X  XSetLineAttributes( theDisplay, gc_reverse, line_width, line_style, cap_style, join_style );
  749. X
  750. X  fontname = pvt[P_FONTNAME2].value.string_value;
  751. X  if ( (font_info2 = XLoadQueryFont( theDisplay, fontname )) == NULL ) {
  752. X    fprintf( stderr, "%s:  cannot open %s font.\n", ProgramName, fontname );
  753. X    exit( 1 );
  754. X  }
  755. X
  756. X  valuemask = GCFunction | GCForeground | GCBackground;
  757. X  values.function = GXcopy;
  758. X  values.foreground = theForegroundPixel;
  759. X  values.background = theBackgroundPixel;
  760. X  gc2 = XCreateGC( theDisplay, theWindow, valuemask, &values );
  761. X  XSetFont( theDisplay, gc2, font_info2->fid );
  762. X  XSetLineAttributes( theDisplay, gc2, line_width, line_style, cap_style, join_style );
  763. X
  764. X  valuemask = GCFunction | GCForeground | GCBackground;
  765. X  values.function = GXcopy;
  766. X  values.foreground = theBackgroundPixel;
  767. X  values.background = theForegroundPixel;
  768. X  gc2_reverse = XCreateGC( theDisplay, theWindow, valuemask, &values );
  769. X  XSetFont( theDisplay, gc2_reverse, font_info2->fid );
  770. X  XSetLineAttributes( theDisplay, gc2_reverse, line_width, line_style, cap_style, join_style );
  771. X
  772. X  valuemask = GCFunction | GCForeground | GCBackground;
  773. X  values.function = GXcopy;
  774. X  values.foreground = theBorderPixel;
  775. X  values.background = theBackgroundPixel;
  776. X  gc3 = XCreateGC( theDisplay, theWindow, valuemask, &values );
  777. X  XSetFont( theDisplay, gc3, font_info2->fid );
  778. X  XSetLineAttributes( theDisplay, gc3, line_width, line_style, cap_style, join_style );
  779. X
  780. X} /* end initialize_graphics_contexts */
  781. X
  782. X
  783. X
  784. X
  785. Xvoid
  786. Xinitialize_menu()        /* initialize the Units menu */
  787. X{
  788. X
  789. X  char                          *string;
  790. X  int                           i, x, y;
  791. X  Pixmap                        theCursorSource, theCursorMask;
  792. X
  793. X  string = distances[0].name;    /* find longest string */
  794. X  for ( i = 1; i < menu_pane_count; i++ ) {
  795. X    if( strlen( distances[i].name ) > strlen( string ) )
  796. X      string = distances[i].name;
  797. X  }
  798. X  XTextExtents( font_info, string, strlen( string ), &direction, &ascent, &descent, &overall );
  799. X  menu_width = overall.width + 4;
  800. X  menu_pane_height = overall.ascent + overall.descent + 4;
  801. X  menu_height = menu_pane_height * menu_pane_count;
  802. X  x = window_width - menu_width - ( 2 * menu_border_width);
  803. X  y = 0;
  804. X
  805. X  theMenu = XCreateSimpleWindow( theDisplay, theWindow, x, y, menu_width, menu_height, menu_border_width, theBorderPixel,
  806. X        theBackgroundPixel );
  807. X
  808. X  for( i = 0; i < menu_pane_count; i++ ) {
  809. X    distances[i].menu_pane = XCreateSimpleWindow( theDisplay, theMenu, 0, menu_height/menu_pane_count*i, menu_width,
  810. X          menu_pane_height, menu_border_width = 1, theForegroundPixel, theBackgroundPixel );
  811. X    XSelectInput( theDisplay, distances[i].menu_pane, EVENT_MASK3 );
  812. X  }
  813. X
  814. X  theCursorSource = XCreateBitmapFromData( theDisplay, theWindow, cursor_bits, cursor_width, cursor_height );
  815. X  theCursorMask = XCreateBitmapFromData( theDisplay, theWindow, cursor_mask_bits, cursor_mask_width, cursor_mask_height );
  816. X  theCursor = XCreatePixmapCursor( theDisplay, theCursorSource, theCursorMask, &theForegroundColor, &theBackgroundColor,
  817. X        cursor_x_hot, cursor_y_hot );
  818. X  XDefineCursor( theDisplay, theMenu, theCursor );
  819. X
  820. X  XMapSubwindows( theDisplay, theMenu );
  821. X
  822. X} /* end initialize_menu */
  823. X
  824. X
  825. X
  826. X
  827. Xvoid
  828. Xinitialize_xodo()        /* initialize xodometer */
  829. X{
  830. X    int                GeometryStatus;
  831. X    XSetWindowAttributes    theWindowAttributes;
  832. X    XSizeHints            theSizeHints;
  833. X    unsigned long        theWindowMask;
  834. X    XWMHints            theWMHints;
  835. X    Colormap            theColormap;
  836. X    int                         i;
  837. X    Window                    QueryRoot, QueryChild;
  838. X    int                         AbsoluteX, AbsoluteY;
  839. X    int                         RelativeX, RelativeY;
  840. X    unsigned int                ModKeyMask;
  841. X    XVisualInfo                 visual_info;
  842. X    unsigned long               background;
  843. X    char                        units[80];
  844. X    char                        *X_default;
  845. X    static char                 *argv[1] = {"xodo"};
  846. X    int                         argc = 1;
  847. X    long                        max_request_size;
  848. X    struct sigaction            action;
  849. X
  850. X#if DEBUG
  851. X    d = fopen( "debug.log", "w" );
  852. X#endif
  853. X
  854. X    sigemptyset( &action.sa_mask ); /* disable all signals */
  855. X
  856. X    action.sa_flags = 0;
  857. X    action.sa_handler = finish_xodo;
  858. X    if ( sigaction( SIGINT, &action, NULL ) != 0 ) {
  859. X      fprintf( stderr, "Cannot set signal SIGINT!\n" );
  860. X      exit( 1 );
  861. X    }
  862. X    action.sa_flags = 0;
  863. X    action.sa_handler = save_xodo;
  864. X    if ( sigaction( SIGHUP, &action, NULL ) != 0 ) {
  865. X      fprintf( stderr, "Cannot set signal SIGHUP!\n" );
  866. X      exit( 1 );
  867. X    }
  868. X
  869. X    ProgramName = pvt[P_HELP].unconverted_value;
  870. X
  871. X    if ( strlen( pvt[P_DISPLAY].value.string_value ) < 1 ) {
  872. X    pvt[P_DISPLAY].value.string_value = NULL;
  873. X    }
  874. X
  875. X    if ( ( theDisplay = XOpenDisplay( pvt[P_DISPLAY].value.string_value ) ) == NULL ) {
  876. X    fprintf( stderr, "%s: Can't open display", ProgramName );
  877. X    if ( pvt[P_DISPLAY].value.string_value != NULL ) {
  878. X        fprintf( stderr, " %s.\n", pvt[P_DISPLAY].value.string_value );
  879. X    } else {
  880. X        fprintf( stderr, ".\n" );
  881. X    }
  882. X    exit( 1 );
  883. X    }
  884. X
  885. X    if ( strlen( pvt[P_GEOMETRY].value.string_value ) < 1 ) {
  886. X    pvt[P_GEOMETRY].value.string_value = NULL;
  887. X    }
  888. X
  889. X    /* For all unspecified evaluate_parameters command line parameters see if there is an X default value. */
  890. X
  891. X    for ( i = 0 ; i < P_NUMBER_OF_PARAMETERS; i++ ) { /* for all evaluate_parameters parameters */
  892. X      if ( ! pvt[i].specified ) {
  893. X    X_default = XGetDefault( theDisplay, ProgramName, pvt[i].parameter );
  894. X    if ( X_default != NULL ) {
  895. X      pvt[i].unconverted_value = X_default;
  896. X      evap_type_conversion( &pvt[i] ); /* convert string to proper type */
  897. X    } /* ifend non-null X default for this parameter */
  898. X      } /* ifend unspecified parameter */
  899. X    } /* forend all evaluate_parameters parameters */
  900. X
  901. X    max_request_size = XMaxRequestSize( theDisplay );
  902. X    if ( ((max_request_size - 3) / 3) < 10 ) {
  903. X      fprintf( stderr, "XMaxRequestSize is too small for xodo the run!\n");
  904. X      exit( 1 );
  905. X    }
  906. X
  907. X    motion_buffer_size = XDisplayMotionBufferSize( theDisplay );
  908. X
  909. X    if ( strcmp( pvt[P_ODOMETER].value.key_value, "cursor" ) == 0 )
  910. X      odometer_count = CURSOR;
  911. X    else if ( strcmp( pvt[P_ODOMETER].value.key_value, "pointer" ) == 0 )
  912. X      odometer_count = POINTER;
  913. X
  914. X    autosave_ticks = pvt[P_ODOMETER_AUTOSAVE_TIME].value.integer_value * 60 * 1000000 /
  915. X          pvt[P_MICROSECOND_INTERVAL_TIME].value.integer_value;
  916. X    autosave_count = autosave_ticks;
  917. X
  918. X    display_widthmm = pvt[P_DISPLAY_WIDTH_MILLIMETERS].value.integer_value;
  919. X    display_heightmm = pvt[P_DISPLAY_HEIGHT_MILLIMETERS].value.integer_value;
  920. X    display_width = pvt[P_DISPLAY_WIDTH_PIXELS].value.integer_value;
  921. X    display_height = pvt[P_DISPLAY_HEIGHT_PIXELS].value.integer_value;
  922. X    X_mm_per_pixel = (double)display_widthmm / display_width;
  923. X    Y_mm_per_pixel = (double)display_heightmm / display_height;
  924. X    pixels_per_inch_x = (int)( 25.4 / X_mm_per_pixel );
  925. X    pixels_per_inch_y = (int)( 25.4 / Y_mm_per_pixel );
  926. X    pixels_per_cm_x = (int)( 10.0 / X_mm_per_pixel );
  927. X    pixels_per_cm_y = (int)( 10.0 / Y_mm_per_pixel );
  928. X    aspect = (float)(X_mm_per_pixel / Y_mm_per_pixel);
  929. X
  930. X    total_cursor_distance = 0.0;
  931. X    trip_cursor_distance = 0.0;
  932. X    total_pointer_distance = 0.0;
  933. X    trip_pointer_distance = 0.0;
  934. X
  935. X    for( i=0; i < menu_pane_count; i++ ) { /* default units = kilometers */
  936. X      if( strcmp( distances[i].name, "kilometers" ) == 0 )
  937. X    distances_ordinal = i;
  938. X    }
  939. X
  940. X    OF = fopen( pvt[P_ODOMETER_FILE].value.file_value, "r" );
  941. X    if ( OF == NULL && errno != ENOENT ) {
  942. X      perror("Cannot open odometer_file");
  943. X      exit( 1 );
  944. X    } else if ( OF != NULL ) {
  945. X      fscanf( OF, "%lf %lf %s", &total_cursor_distance, &total_pointer_distance, units );
  946. X      for( i=0; i < menu_pane_count; i++ ) {
  947. X    if( strcmp( distances[i].name, units ) == 0 )
  948. X      distances_ordinal = i;
  949. X      }
  950. X      fclose( OF );
  951. X    }
  952. X
  953. X    GeometryStatus = XParseGeometry( pvt[P_GEOMETRY].value.string_value, &WindowPointX, &WindowPointY, &WindowWidth,
  954. X          &WindowHeight );
  955. X
  956. X    if ( !( GeometryStatus & XValue ) ) {
  957. X      WindowPointX = 1;
  958. X    } else if ( GeometryStatus & XNegative ) {
  959. X      WindowPointX = display_width + WindowPointX;
  960. X    }
  961. X    if ( !( GeometryStatus & YValue ) ) {
  962. X      WindowPointY = 1;
  963. X    } else if ( GeometryStatus & YNegative ) {
  964. X      WindowPointY = display_height + WindowPointY;
  965. X    }
  966. X    if ( !( GeometryStatus & WidthValue ) ) {
  967. X      WindowWidth = window_width;
  968. X    }
  969. X    if ( !( GeometryStatus & HeightValue ) ) {
  970. X      WindowHeight = window_height;
  971. X    }
  972. X
  973. X    theScreen = DefaultScreen( theDisplay );
  974. X    theDepth = DefaultDepth( theDisplay, theScreen );
  975. X    theColormap = DefaultColormap( theDisplay, theScreen );
  976. X    theForegroundPixel = BlackPixel( theDisplay, theScreen );
  977. X    theBackgroundPixel = WhitePixel( theDisplay, theScreen );
  978. X    theBorderPixel = theForegroundPixel;
  979. X
  980. X    if ( theDepth > 1 ) {    /* if possible color monitor */
  981. X
  982. X      i = DirectColor;        /* StaticGray, GrayScale, StaticColor, PseudoColor, TrueColor, DirectColor */
  983. X      while ( ! XMatchVisualInfo( theDisplay, theScreen, theDepth, i--, &visual_info ) )
  984. X    ; /* whilend */
  985. X
  986. X      if ( i >= StaticColor ) {
  987. X    if ( ! XAllocNamedColor( theDisplay, theColormap, pvt[P_BACKGROUND].value.name_value, &theBackgroundColor,
  988. X              &theExactColor ) ) {
  989. X      fprintf( stderr, "%s: Can't XAllocNamedColor( \"%s\" ).\n", ProgramName, pvt[P_BACKGROUND].value.name_value );
  990. X      exit( 1 );
  991. X    }
  992. X    if ( ! XAllocNamedColor( theDisplay, theColormap, pvt[P_FOREGROUND].value.name_value, &theForegroundColor,
  993. X              &theExactColor ) ) {
  994. X      fprintf( stderr, "%s: Can't XAllocNamedColor( \"%s\" ).\n", ProgramName, pvt[P_FOREGROUND].value.name_value );
  995. X      exit( 1 );
  996. X    }
  997. X    if ( ! XAllocNamedColor( theDisplay, theColormap, pvt[P_BORDER].value.name_value, &theBorderColor, &theExactColor ) ) {
  998. X      fprintf( stderr, "%s: Can't XAllocNamedColor( \"%s\" ).\n", ProgramName, pvt[P_BORDER].value.name_value );
  999. X      exit( 1 );
  1000. X    }
  1001. X
  1002. X    theForegroundPixel = theForegroundColor.pixel;
  1003. X    theBackgroundPixel = theBackgroundColor.pixel;
  1004. X    theBorderPixel = theBorderColor.pixel;
  1005. X      } /* ifend color visual */
  1006. X
  1007. X    } /* ifend depth > 1 */
  1008. X
  1009. X    theWindowAttributes.border_pixel = theBorderPixel;
  1010. X    theWindowAttributes.background_pixel = theBackgroundPixel;
  1011. X    theWindowAttributes.override_redirect = False;
  1012. X    theWindowAttributes.event_mask = EVENT_MASK1;
  1013. X
  1014. X    theWindowMask = CWBackPixel | CWBorderPixel    | CWEventMask | CWOverrideRedirect;
  1015. X
  1016. X    theWindow = XCreateWindow( theDisplay, RootWindow( theDisplay, theScreen ), WindowPointX, WindowPointY, WindowWidth,
  1017. X          WindowHeight, BorderWidth, theDepth, InputOutput, CopyFromParent, theWindowMask, &theWindowAttributes );
  1018. X
  1019. X    initialize_graphics_contexts(); /* initialize graphics contexts */
  1020. X
  1021. X    theIconPixmap = XCreateBitmapFromData( theDisplay, theWindow, icon_bits, icon_width, icon_height );
  1022. X    pulldown = XCreateBitmapFromData( theDisplay, theWindow, pulldown_bits, pulldown_width, pulldown_height );
  1023. X
  1024. X    theWMHints.icon_pixmap = theIconPixmap;
  1025. X    if ( pvt[P_ICONIC].specified ) {
  1026. X    theWMHints.initial_state = IconicState;
  1027. X    } else {
  1028. X    theWMHints.initial_state = NormalState;
  1029. X    }
  1030. X    theWMHints.flags = IconPixmapHint | StateHint;
  1031. X
  1032. X    XSetWMHints( theDisplay, theWindow, &theWMHints );
  1033. X
  1034. X    theSizeHints.flags = PPosition | PSize; /* PMinSize perhaps */
  1035. X    theSizeHints.x = WindowPointX;
  1036. X    theSizeHints.y = WindowPointY;
  1037. X    theSizeHints.width = WindowWidth;
  1038. X    theSizeHints.height = WindowHeight;
  1039. X    theSizeHints.min_width = window_width;
  1040. X    theSizeHints.min_height = window_height;
  1041. X
  1042. X    XSetNormalHints( theDisplay, theWindow, &theSizeHints );
  1043. X
  1044. X    if ( strlen( pvt[P_TITLE].value.string_value ) >= 1 ) {
  1045. X    XStoreName( theDisplay, theWindow, pvt[P_TITLE].value.string_value );
  1046. X    XSetIconName( theDisplay, theWindow, pvt[P_TITLE].value.string_value );
  1047. X    } else {
  1048. X    XStoreName( theDisplay, theWindow, ProgramName );
  1049. X    XSetIconName( theDisplay, theWindow, ProgramName );
  1050. X    }
  1051. X
  1052. X    XSetCommand( theDisplay, theWindow, argv, argc );
  1053. X    atom_wm_save_yourself = XInternAtom( theDisplay, "WM_SAVE_YOURSELF", False );
  1054. X    status = XSetWMProtocols( theDisplay, theWindow, &atom_wm_save_yourself, 1 );
  1055. X
  1056. X    for( i = 0; i < windata_count; i++ ) { /* make Action buttons */
  1057. X      if ( odometer_count != BOTH && i == TRIP2 )
  1058. X    continue;        /* skip second trip odometer if only 1 odometer */
  1059. X      background = theBackgroundPixel;
  1060. X      if ( i == TRIP1 || i == TRIP2 )
  1061. X    background = theBorderPixel;
  1062. X      windata[i].window = XCreateSimpleWindow( theDisplay, theWindow, windata[i].x, windata[i].y, windata[i].width,
  1063. X            windata[i].height, windata[i].border, theBorderPixel, background );
  1064. X      XSelectInput( theDisplay, windata[i].window, EVENT_MASK2 );
  1065. X    } /* forend */
  1066. X
  1067. X    XQueryPointer( theDisplay, theWindow, &QueryRoot, &QueryChild, &AbsoluteX, &AbsoluteY, &RelativeX, &RelativeY, &ModKeyMask );
  1068. X    PointerX = AbsoluteX;
  1069. X    PointerY = AbsoluteY;
  1070. X
  1071. X    XGetPointerControl( theDisplay, &accel_numerator, &accel_denominator, &threshold);
  1072. X    acceleration = (double)accel_numerator / (double)accel_denominator;
  1073. X
  1074. X    sprintf( status_line, "S=%.1f T=%d A=%.1f", pvt[P_POINTER_SCALE_FACTOR].value.real_value, threshold, acceleration );
  1075. X    strncpy( distances_human+2, distances[distances_ordinal].abbreviation, 3 );
  1076. X
  1077. X    XMapSubwindows( theDisplay, theWindow );
  1078. X
  1079. X    compute_font_and_resize_data( font_info );
  1080. X
  1081. X    XGetGeometry( theDisplay, theWindow, &theRoot, &WindowPointX, &WindowPointY, &WindowWidth, &WindowHeight, &BorderWidth,
  1082. X          &theDepth );
  1083. X
  1084. X    XTextExtents( font_info, about[2], strlen( about[2] ), &direction, &ascent, &descent, &overall );
  1085. X    about_width = overall.width + 4 + about_width_x;
  1086. X    about_height = ( overall.ascent + overall.descent + 4 ) * about_count;
  1087. X    about_height += icon_height + font_height + 1;
  1088. X    i = strlen( about[0] );    /* update version information */
  1089. X    strncpy( about[0]+i-3, VERSION, 3 );
  1090. X
  1091. X    XTextExtents( font_info2, calibration, strlen( calibration ), &direction, &ascent, &descent, &overall );
  1092. X    calibration_width = overall.width + 4;
  1093. X
  1094. X    initialize_menu();        /* initialize the Units menu windows */
  1095. X
  1096. X    XMapWindow( theDisplay, theWindow );
  1097. X    XFlush( theDisplay );
  1098. X
  1099. X} /* end initialize_xodo */
  1100. X
  1101. X
  1102. X
  1103. X
  1104. XBool
  1105. Xprocess_event()            /* handle all X events */
  1106. X{
  1107. X  XEvent                        theEvent;
  1108. X  int                           new_width, new_height;
  1109. X  int                           i;
  1110. X
  1111. X  /* Check for ClientMessage type WM_SAVE_YOURSELF to save state information. */
  1112. X
  1113. X  if ( XCheckTypedEvent( theDisplay, ClientMessage, &theEvent ) == True ) {
  1114. X    if ( theEvent.xclient.data.l[0] == atom_wm_save_yourself )
  1115. X      finish_xodo();        /* save state information and exit */
  1116. X  } /* ifend ClientMessage received */
  1117. X  
  1118. X  while ( XCheckMaskEvent( theDisplay, ALL_EVENTS_MASK, &theEvent ) ) {
  1119. X
  1120. X    switch ( theEvent.type ) {
  1121. X      
  1122. X    case MapNotify:      case MappingNotify:   case GraphicsExpose:   case NoExpose:
  1123. X    case SelectionClear: case SelectionNotify: case SelectionRequest:
  1124. X      
  1125. X      break;            /* misc */
  1126. X      
  1127. X    case ClientMessage:
  1128. X
  1129. X      finish_xodo();        /* will never get here via XCheckMaskEvent! */
  1130. X      
  1131. X      break;            /* ClientMessage */
  1132. X      
  1133. X    case ConfigureNotify:
  1134. X      if ( theEvent.xconfigure.window == theWindow ) {
  1135. X    WindowWidth = theEvent.xconfigure.width;
  1136. X    WindowHeight = theEvent.xconfigure.height;
  1137. X    if ( theEvent.xconfigure.x != 0 )
  1138. X      WindowPointX = theEvent.xconfigure.x;
  1139. X    if ( theEvent.xconfigure.y != 0 )
  1140. X      WindowPointY = theEvent.xconfigure.y;
  1141. X    BorderWidth = theEvent.xconfigure.border_width;
  1142. X      }
  1143. X      
  1144. X      break;            /* ConfigureNotify */
  1145. X    
  1146. X    case Expose:
  1147. X      
  1148. X      if ( theEvent.xexpose.count == 0 ) {
  1149. X    
  1150. X    if ( theEvent.xexpose.window == theWindow ) {
  1151. X      draw_odometers();
  1152. X      draw_misc_info();
  1153. X      draw_action_windows( gc2 );
  1154. X        }
  1155. X    
  1156. X    draw_menu_panes( gc, theEvent.xexpose.window );
  1157. X
  1158. X      } /* ifend event count = 0 */
  1159. X      
  1160. X      break;            /* Expose */
  1161. X      
  1162. X    case EnterNotify:
  1163. X
  1164. X      if ( button_depressed ) {
  1165. X    if (theEvent.xcrossing.window == windata[UNITS].window)
  1166. X      draw_menu();
  1167. X    else
  1168. X      highlight_action_window( gc2_reverse, theEvent.xcrossing.window, theForegroundPixel );
  1169. X      }
  1170. X
  1171. X      draw_menu_panes( gc_reverse, theEvent.xcrossing.window );
  1172. X    
  1173. X      break;            /* EnterNotify */
  1174. X      
  1175. X    case LeaveNotify:
  1176. X
  1177. X      highlight_action_window( gc2, theEvent.xcrossing.window, theBorderPixel );
  1178. X      
  1179. X      draw_menu_panes( gc, theEvent.xcrossing.window );
  1180. X      
  1181. X      break;            /* LeaveNotify */
  1182. X      
  1183. X    case ButtonPress:
  1184. X
  1185. X      button_depressed = True;
  1186. X  
  1187. X      if ( theEvent.xbutton.window == windata[UNITS].window ) {
  1188. X    draw_menu();
  1189. X    break;
  1190. X      }      
  1191. X
  1192. X      highlight_action_window( gc2_reverse, theEvent.xbutton.window, theForegroundPixel );
  1193. X
  1194. X      break;            /* ButtonPress */
  1195. X
  1196. X    case ButtonRelease:
  1197. X
  1198. X      button_depressed = False;
  1199. X
  1200. X      highlight_action_window( gc2, theEvent.xbutton.window, theBorderPixel );
  1201. X
  1202. X      if ( menu_active == True ) {
  1203. X    XUngrabPointer( theDisplay, CurrentTime );
  1204. X    XUnmapWindow( theDisplay, theMenu );
  1205. X    XMoveResizeWindow( theDisplay, theWindow, menu_x_old, menu_y_old, menu_width_old, menu_height_old );
  1206. X    menu_active = False;
  1207. X    for ( i = 0; i < menu_pane_count; i++ ) {
  1208. X      if ( theEvent.xbutton.window == distances[i].menu_pane ) {
  1209. X        distances_ordinal = i;
  1210. X        strncpy( distances_human+2, distances[distances_ordinal].abbreviation, 3 );
  1211. X        draw_misc_info();
  1212. X      } /* ifend button release occurred in a menu pane */
  1213. X    } /* forend */
  1214. X    break; /* case ButtonRelease */
  1215. X      } /* ifend menu_active */
  1216. X
  1217. X      if ( theEvent.xbutton.window == windata[TRIP1].window ) {
  1218. X    if ( odometer_count == CURSOR || odometer_count == BOTH ) {
  1219. X      trip_cursor_distance = 0.0;
  1220. X    } else {
  1221. X      trip_pointer_distance = 0.0;
  1222. X    }
  1223. X      } else if ( theEvent.xbutton.window == windata[TRIP2].window ) {
  1224. X    trip_pointer_distance = 0.0;
  1225. X      } else if ( theEvent.xbutton.window == windata[QUIT].window ) {
  1226. X    finish_xodo();        /* update distance totals */
  1227. X      } else if ( theEvent.xbutton.window == windata[UNITS].window ) {
  1228. X    XUnmapWindow( theDisplay, theMenu );
  1229. X      } else if ( theEvent.xbutton.window == windata[ABOUT].window ) {
  1230. X    if ( about_active ) {
  1231. X      about_active = False;
  1232. X      windata[ABOUT].text = "About";
  1233. X      XMoveResizeWindow( theDisplay, theWindow, about_x_old, about_y_old, about_width_old, about_height_old );
  1234. X    } else {
  1235. X      about_active = True;
  1236. X      about_width_old = WindowWidth;
  1237. X      about_height_old = WindowHeight;
  1238. X      windata[ABOUT].text = " OK! ";
  1239. X      if ( WindowWidth < about_width ) 
  1240. X        new_width = about_width;
  1241. X      else
  1242. X        new_width = WindowWidth;
  1243. X      if ( WindowHeight < about_height ) 
  1244. X        new_height = about_height;
  1245. X      else
  1246. X        new_height = WindowHeight;
  1247. X      about_x_old = WindowPointX;
  1248. X      about_y_old = WindowPointY;
  1249. X      if ( WindowPointX + new_width > display_width )
  1250. X        about_x_old = display_width - new_width - 10;
  1251. X      if ( WindowPointY + new_height > display_height )
  1252. X        about_y_old = display_height - new_height - 10;
  1253. X      XMoveResizeWindow( theDisplay, theWindow, about_x_old, about_y_old, new_width, new_height+5 );
  1254. X      about_x_old = WindowPointX;
  1255. X      about_y_old = WindowPointY;
  1256. X    }
  1257. X      } else if ( theEvent.xbutton.button == Button2 ) {
  1258. X    trip_cursor_distance = 0.0;
  1259. X    trip_pointer_distance = 0.0;
  1260. X      } /* ifend */
  1261. X
  1262. X      break;            /* ButtonRelease */
  1263. X    
  1264. X    default:
  1265. X
  1266. X      break;            /* unknown event */
  1267. X
  1268. X    } /* casend event type */
  1269. X
  1270. X  } /* whilend */
  1271. X
  1272. X  return( True );
  1273. X
  1274. X} /* end process_event */
  1275. X
  1276. X
  1277. X
  1278. X
  1279. Xvoid
  1280. Xprocess_pointer()        /* do stuff every time period */
  1281. X{
  1282. X  struct timeval                timer;
  1283. X  
  1284. X  timer.tv_sec = 0;
  1285. X  timer.tv_usec = pvt[P_MICROSECOND_INTERVAL_TIME].value.integer_value;
  1286. X  
  1287. X  do {
  1288. X    
  1289. X    do_distances( False );
  1290. X    
  1291. X    if ( --autosave_count <= 0 ) {
  1292. X      autosave_count = autosave_ticks;
  1293. X      save_xodo();        /* update state information */
  1294. X    }
  1295. X    
  1296. X    if ( pvt[P_MICROSECOND_INTERVAL_TIME].value.integer_value <= 999999 )
  1297. X      select( 0, NULL, NULL, NULL, &timer );
  1298. X    else
  1299. X      sleep ( (unsigned)pvt[P_MICROSECOND_INTERVAL_TIME].value.integer_value / 1000000 );
  1300. X    
  1301. X  } while ( process_event() );
  1302. X
  1303. X} /* end process_pointer */
  1304. X
  1305. X
  1306. X
  1307. X
  1308. Xvoid
  1309. Xsave_xodo()            /* update xodo distances */
  1310. X{
  1311. X
  1312. X  OF = fopen( pvt[P_ODOMETER_FILE].value.file_value, "w" );
  1313. X  if ( OF == NULL ) {
  1314. X    perror("Cannot open odometer_file for write!");
  1315. X  } else {
  1316. X    fprintf( OF, "%f %f %s\n", total_cursor_distance, total_pointer_distance, distances[distances_ordinal].name );
  1317. X    fclose( OF );
  1318. X  }
  1319. X
  1320. X} /* end save_xodo */
  1321. X
  1322. X
  1323. X
  1324. Xint
  1325. Xmain( argc, argv )
  1326. X    int        argc;
  1327. X    char    *argv[];
  1328. X{
  1329. X  
  1330. X  evap( &argc, &argv, pdt, NULL, pvt ); /* evaluate parameters */
  1331. X  
  1332. X  initialize_xodo();        /* all other xodometer initialization */
  1333. X
  1334. X  process_pointer();        /* watch the pointing device */
  1335. X  
  1336. X  finish_xodo();        /* update distances for next time */
  1337. X
  1338. X  exit( 0 );            /* success, just in case */
  1339. X
  1340. X} /* end xodo main */
  1341. END_OF_FILE
  1342. if test 45761 -ne `wc -c <'xodo.c'`; then
  1343.     echo shar: \"'xodo.c'\" unpacked with wrong size!
  1344. fi
  1345. chmod +x 'xodo.c'
  1346. # end of 'xodo.c'
  1347. fi
  1348. echo shar: End of archive 4 \(of 4\).
  1349. cp /dev/null ark4isdone
  1350. MISSING=""
  1351. for I in 1 2 3 4 ; do
  1352.     if test ! -f ark${I}isdone ; then
  1353.     MISSING="${MISSING} ${I}"
  1354.     fi
  1355. done
  1356. if test "${MISSING}" = "" ; then
  1357.     echo You have unpacked all 4 archives.
  1358.     echo "Read README for installation instructions."
  1359.     rm -f ark[1-9]isdone
  1360. else
  1361.     echo You still need to unpack the following archives:
  1362.     echo "        " ${MISSING}
  1363. fi
  1364. ##  End of shell archive.
  1365. exit 0
  1366.  
  1367. exit 0 # Just in case...
  1368. -- 
  1369.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  1370. \X/  Amiga - The only way to fly!      |
  1371.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  1372.   casual observer..."                  |
  1373.