home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / fplan-1.3 / part01 next >
Encoding:
Text File  |  1992-06-29  |  54.5 KB  |  1,760 lines

  1. Newsgroups: comp.sources.misc
  2. From: tynor@prism.gatech.edu (STEVE TYNOR)
  3. Subject:  v30i081:  fplan-1.3 - Fplan 1.3 (Flight Planner), Part01/04
  4. Message-ID: <csm-v30i081=fplan-1.3.114503@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: e94f0d086a3e1716b1c9dfa6c54237e9
  6. Date: Sun, 28 Jun 1992 16:50:06 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tynor@prism.gatech.edu (STEVE TYNOR)
  10. Posting-number: Volume 30, Issue 81
  11. Archive-name: fplan-1.3/part01
  12. Environment: K&R C, BSD, MSDOS, Sunview (optional)
  13. Supersedes: fplan: Volume 09, Issue 11-16
  14.  
  15. FPLAN v.1.3 - Flight Plan program.
  16.  
  17.     FPLAN is a flight planner intended for use in general
  18. aviation.  FPLAN reads a planfile consisting of departure and
  19. destination airports, navigation aids, intermediate checkpoints, fuel
  20. consumption rates, winds aloft, and produces a flight plan including
  21. wind corrected heading, fuel consumption for each leg, vor fixes for
  22. each checkpoint, etc.  FPLAN uses NAV format databases for upward
  23. compatibility with those widely distributed databases (see the file
  24. WHERE_DBS for details on how to get them).
  25.  
  26.     How is FPLAN different from NAV? Mainly, it will automatically
  27. compute VOR cross fixes (radial and distance to/from fix) at each
  28. waypoint along the flight and allow you to enter a waypoint as ``15
  29. miles since the previous waypoint along the current heading''. These
  30. features provide a kind of flight plan more useful in VFR / dead
  31. reckoning flight, where frequent checkpoints are necessary.
  32.  
  33.     This program is in the public domain. Permission to copy,
  34. distribute, modify this program is hearby given as long as this header
  35. remains. If you redistribute this program after modifying it, please
  36. document your changes so that I do not take the blame (or credit) for
  37. those changes.  If you fix bugs or add features, please send me a
  38. patch so that I can keep the `official' version up-to-date. Bug
  39. reports are welcome and I'll make an attempt to fix those that are
  40. reported.
  41.  
  42.     USE AT YOUR OWN RISK! I assume no responsibility for any
  43. errors in this program, its databases or documentation. I will make an
  44. effort to fix bugs, but if you crash and burn because, for example,
  45. fuel estimates in this program were inaccurate, it's your own fault
  46. for trusting somebody else's code! Remember, as Pilot in Command, it's
  47. _your_ responsibility to do complete preflight planning. Use this
  48. program as a flight planning aid, but verify its results before using
  49. them.
  50.  
  51. NOTE: Version 1.2 incorporated a number of bug fixes submitted by the
  52. following fine individuals:
  53.  
  54.     Chris Coffin    coffin@xroads.UUCP
  55.     Dave Buck    {amdahl,sun,megatest,plx,ardent,ubvax}!dlb!dave
  56.     Randy Bailey    randy@hpisla.HP.COM
  57.     Dave Lockwood    davel@vision.UUCP (Dave has also submitted SysV 
  58.         patches which have, unfortunately, _not_ been incorporated
  59.         into this distribution). 
  60.     Andy Schneider    ajs@sony.com
  61.  
  62. NOTE: Version 1.3 incorporates a bug fix submitted by:
  63.  
  64.     Tyko Strassen    strassen@iam.unibe.ch
  65.  
  66. NOTE: The NAV databases referred to in the README are somewhat out of date. 
  67. There seems to be some initiative among rec.aviators to update the databases 
  68. from more recent FAA tapes: see discussions in rec.aviation for details. 
  69.   
  70. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  71.     Virtue is its own punishment.
  72.  
  73.     Steve Tynor
  74.  
  75.     Yellow Jacket Flying Club
  76.     and
  77.     Georgia Tech Research Institute
  78.     Artificial Intelligence Branch
  79.     Georgia Institute of Technology
  80.     tynor@prism.gatech.edu
  81.  
  82. ---- cut here ---- cut here ---- cut here ---- cut here ----
  83. #! /bin/sh
  84. # This is a shell archive.  Remove anything before this line, then feed it
  85. # into a shell via "sh file" or similar.  To overwrite existing files,
  86. # type "sh file -c".
  87. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  88. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  89. # Contents:  README compute.c output.c sv_draw.c
  90. # Wrapped by kent@sparky on Sun Jun 28 11:39:10 1992
  91. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  92. echo If this archive is complete, you will see the following message:
  93. echo '          "shar: End of archive 1 (of 4)."'
  94. if test -f 'README' -a "${1}" != "-c" ; then 
  95.   echo shar: Will not clobber existing file \"'README'\"
  96. else
  97.   echo shar: Extracting \"'README'\" \(2671 characters\)
  98.   sed "s/^X//" >'README' <<'END_OF_FILE'
  99. X    FPLAN v.1.3 - Flight Plan program.
  100. X
  101. X    FPLAN is a flight planner intended for use in general
  102. Xaviation.  FPLAN reads a planfile consisting of departure and
  103. Xdestination airports, navigation aids, intermediate checkpoints, fuel
  104. Xconsumption rates, winds aloft, and produces a flight plan including
  105. Xwind corrected heading, fuel consumption for each leg, vor fixes for
  106. Xeach checkpoint, etc.  FPLAN uses NAV format databases for upward
  107. Xcompatibility with those widely distributed databases (see the file
  108. XWHERE_DBS for details on how to get them).
  109. X
  110. X    How is FPLAN different from NAV? Mainly, it will automatically
  111. Xcompute VOR cross fixes (radial and distance to/from fix) at each
  112. Xwaypoint along the flight and allow you to enter a waypoint as ``15
  113. Xmiles since the previous waypoint along the current heading''. These
  114. Xfeatures provide a kind of flight plan more useful in VFR / dead
  115. Xreckoning flight, where frequent checkpoints are necessary.
  116. X
  117. X    This program is in the public domain. Permission to copy,
  118. Xdistribute, modify this program is hearby given as long as this header
  119. Xremains. If you redistribute this program after modifying it, please
  120. Xdocument your changes so that I do not take the blame (or credit) for
  121. Xthose changes.  If you fix bugs or add features, please send me a
  122. Xpatch so that I can keep the `official' version up-to-date. Bug
  123. Xreports are welcome and I'll make an attempt to fix those that are
  124. Xreported.
  125. X
  126. X    USE AT YOUR OWN RISK! I assume no responsibility for any
  127. Xerrors in this program, its databases or documentation. I will make an
  128. Xeffort to fix bugs, but if you crash and burn because, for example,
  129. Xfuel estimates in this program were inaccurate, it's your own fault
  130. Xfor trusting somebody else's code! Remember, as Pilot in Command, it's
  131. X_your_ responsibility to do complete preflight planning. Use this
  132. Xprogram as a flight planning aid, but verify its results before using
  133. Xthem.
  134. X
  135. XNOTE: Version 1.2 incorporated a number of bug fixes submitted by the
  136. Xfollowing fine individuals:
  137. X
  138. X    Chris Coffin    coffin@xroads.UUCP
  139. X    Dave Buck    {amdahl,sun,megatest,plx,ardent,ubvax}!dlb!dave
  140. X    Randy Bailey    randy@hpisla.HP.COM
  141. X    Dave Lockwood    davel@vision.UUCP (Dave has also submitted SysV 
  142. X        patches which have, unfortunately, _not_ been incorporated
  143. X        into this distribution). 
  144. X    Andy Schneider    ajs@sony.com
  145. X
  146. XNOTE: Version 1.3 incorporates a bug fix submitted by:
  147. X
  148. X    Tyko Strassen    strassen@iam.unibe.ch
  149. X
  150. X=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  151. X    Virtue is its own punishment.
  152. X
  153. X    Steve Tynor
  154. X
  155. X    Yellow Jacket Flying Club
  156. X    and
  157. X    Georgia Tech Research Institute
  158. X    Artificial Intelligence Branch
  159. X    Georgia Institute of Technology
  160. X    tynor@prism.gatech.edu
  161. END_OF_FILE
  162.   if test 2671 -ne `wc -c <'README'`; then
  163.     echo shar: \"'README'\" unpacked with wrong size!
  164.   fi
  165.   # end of 'README'
  166. fi
  167. if test -f 'compute.c' -a "${1}" != "-c" ; then 
  168.   echo shar: Will not clobber existing file \"'compute.c'\"
  169. else
  170.   echo shar: Extracting \"'compute.c'\" \(14905 characters\)
  171.   sed "s/^X//" >'compute.c' <<'END_OF_FILE'
  172. X/*
  173. X * $Id: compute.c,v 2.7 90/06/15 21:31:55 tynor Exp $
  174. X *----------------------------------------------------------------------------
  175. X *    FPLAN - Flight Planner
  176. X *    Steve Tynor
  177. X *    tynor@prism.gatech.edu
  178. X *
  179. X *    This program is in the public domain. Permission to copy,
  180. X * distribute, modify this program is hearby given as long as this header
  181. X * remains. If you redistribute this program after modifying it, please
  182. X * document your changes so that I do not take the blame (or credit) for
  183. X * those changes.  If you fix bugs or add features, please send me a
  184. X * patch so that I can keep the 'official' version up-to-date.
  185. X *
  186. X *    Bug reports are welcome and I'll make an attempt to fix those
  187. X * that are reported.
  188. X *
  189. X *    USE AT YOUR OWN RISK! I assume no responsibility for any
  190. X * errors in this program, its database or documentation. I will make an
  191. X * effort to fix bugs, but if you crash and burn because, for example,
  192. X * fuel estimates in this program were inaccurate, it's your own fault
  193. X * for trusting somebody else's code! Remember, as PIC, it's _your_
  194. X * responsibility to do complete preflight planning. Use this program as
  195. X * a flight planning aid, but verify its results before using them.
  196. X *----------------------------------------------------------------------------
  197. X */
  198. X
  199. Xstatic char rcsid[] = "$Id: compute.c,v 2.7 90/06/15 21:31:55 tynor Exp $";
  200. X
  201. X#include "wp_info.h"
  202. X#include <math.h>
  203. X
  204. X/*----------------------------------------------------------------------------*/
  205. Xstatic void wind_correct (true_air_speed, mag_course, 
  206. X              wind_speed, wind_heading,
  207. X              ground_speed, mag_heading)
  208. X     double true_air_speed, mag_course, 
  209. X    wind_speed, wind_heading, 
  210. X    *ground_speed, *mag_heading;
  211. X{
  212. X   double hdiff, tx, ty, wca;
  213. X
  214. X   if (wind_heading <= 180.0)
  215. X      wind_heading += 180.0;
  216. X   else
  217. X      wind_heading -= 180.0;
  218. X   hdiff = DEG2RAD (mag_course - wind_heading);
  219. X   tx = wind_speed * sin (hdiff);
  220. X   ty = wind_speed * cos (hdiff);
  221. X   wca = asin (tx / true_air_speed);
  222. X   *ground_speed = cos (wca) * true_air_speed + ty;
  223. X   *mag_heading = mag_course + RAD2DEG (wca);
  224. X   if (*mag_heading >= 360.0)
  225. X      *mag_heading -= 360.0;
  226. X   else if (*mag_heading <= 0.0)
  227. X      *mag_heading += 360.0;
  228. X}
  229. X
  230. X/*----------------------------------------------------------------------------*/
  231. Xvoid distance_and_heading (lat1, long1, lat2, long2, distance, heading)
  232. X     double lat1, long1, lat2, long2;
  233. X     double *distance, *heading;
  234. X{
  235. X   double tmp;
  236. X
  237. X   lat1  = DEG2RAD (lat1);
  238. X   long1 = DEG2RAD (long1);
  239. X   lat2  = DEG2RAD (lat2);
  240. X   long2 = DEG2RAD (long2);
  241. X
  242. X   if ((lat1 == lat2) && (long1 == long2)) {
  243. X      *distance = 0.0;
  244. X      *heading  = 0.0;
  245. X      return;
  246. X   }
  247. X
  248. X   tmp = atan2 (2.0 * asin (sin ((long1 - long2) / 2.0)),
  249. X        log (tan (PI / 4.0 + lat2 / 2.0)) - 
  250. X        log (tan (PI / 4.0 + lat1 / 2.0)) );
  251. X   if (lat1 == lat2)
  252. X      *distance = 60.0 *
  253. X     fabs (RAD2DEG (2.0 * asin (sin ((long1 - long2) / 2.0)))) *
  254. X        cos (lat1);
  255. X   else
  256. X      *distance = 60.0 * RAD2DEG (lat2 - lat1) / cos (fabs (tmp));
  257. X   
  258. X   if (asin (sin (long1-long2)) >= 0.0)
  259. X      *heading = RAD2DEG (fabs(tmp));
  260. X   else
  261. X      *heading = 360.0 - RAD2DEG (fabs(tmp));
  262. X}
  263. X
  264. X/*----------------------------------------------------------------------------*/
  265. Xstatic int next_non_incremental (start)
  266. X     int start;
  267. X{
  268. X   int i = start;
  269. X
  270. X   for (i = start; i < num_waypoints; i++)
  271. X      if (waypoints[i].db->mode != WP_INCREMENTAL)
  272. X     return i;
  273. X   return -1;
  274. X}
  275. X
  276. X/*----------------------------------------------------------------------------*/
  277. Xstatic void locate_incrementals ()
  278. X{
  279. X   int    j, prev, next;
  280. X   double d, heading;
  281. X
  282. X   for (prev = 0; ((prev >= 0) && (prev < num_waypoints)); ) {
  283. X      next = next_non_incremental (prev+1);
  284. X      if (next >= 0) {
  285. X     distance_and_heading (waypoints[prev].db->latitude,
  286. X                   waypoints[prev].db->longitude, 
  287. X                   waypoints[next].db->latitude, 
  288. X                   waypoints[next].db->longitude, 
  289. X                   &d, &heading);
  290. X     for (j = prev+1; j < next; j++) {
  291. X        if (waypoints[j].db->u.dist_since_last_wp >= 0.0) {
  292. X           waypoints[j].db->latitude =  waypoints[prev].db->latitude +
  293. X          (waypoints[next].db->latitude - waypoints[prev].db->latitude)
  294. X             * waypoints[j].db->u.dist_since_last_wp / d;
  295. X           waypoints[j].db->longitude =  waypoints[prev].db->longitude +
  296. X          (waypoints[next].db->longitude -
  297. X           waypoints[prev].db->longitude) * 
  298. X              waypoints[j].db->u.dist_since_last_wp / d;
  299. X        } else {
  300. X           waypoints[j].db->latitude =  waypoints[next].db->latitude +
  301. X          (waypoints[next].db->latitude - waypoints[prev].db->latitude)
  302. X             * waypoints[j].db->u.dist_since_last_wp / d;
  303. X           waypoints[j].db->longitude =  waypoints[next].db->longitude +
  304. X          (waypoints[next].db->longitude -
  305. X           waypoints[prev].db->longitude) * 
  306. X              waypoints[j].db->u.dist_since_last_wp / d;
  307. X        }
  308. X         waypoints[j].db->mag_variation =
  309. X           waypoints[prev].db->mag_variation + 
  310. X          (waypoints[next].db->mag_variation -
  311. X           waypoints[prev].db->mag_variation) *
  312. X            waypoints[j].db->u.dist_since_last_wp / d;
  313. X     }
  314. X      }
  315. X      prev = next;
  316. X   }
  317. X}
  318. X
  319. X/*----------------------------------------------------------------------------*/
  320. X#define IS_NAVAID(mode) (((mode) == WP_VOR) || ((mode) == WP_NDB) || \
  321. X             ((mode) == WP_DME) || ((mode) == WP_TAC) || \
  322. X             ((mode) == WP_ILS) || ((mode) == WP_LOM) || \
  323. X             ((mode) == WP_LMM))
  324. X
  325. X/*----------------------------------------------------------------------------
  326. X * FUZZ is the number of degrees two points can be apart and still be considered
  327. X * colocated - we let this be fuzzy, since it's often the case that onfield VORs
  328. X * are reported with slightly different lat/long, but we still want to view them
  329. X * as the same point...
  330. X */
  331. X#define FUZZ 0.01
  332. X#define COLOCATED(db1,db2) \
  333. X   ((fabs ((db1)->latitude - (db2)->latitude) <= FUZZ) && \
  334. X    (fabs ((db1)->longitude - (db2)->longitude) <= FUZZ))
  335. X
  336. X/*----------------------------------------------------------------------------*/
  337. Xstatic DATABASE_INFO *get_navaid (wp)
  338. X     WAYPOINT_INFO wp;
  339. X     /*
  340. X      * If the waypoint is a navaid return its db pointer. If it's an airport 
  341. X      * and there's a navaid colocated on the field, return it's db pointer,
  342. X      * else return NULL.
  343. X      */
  344. X{
  345. X   DATABASE_INFO *db;
  346. X   extern BOOLEAN lookup_desig ();
  347. X
  348. X   if (IS_NAVAID (wp.db->mode)) {
  349. X      return (wp.db);
  350. X   } else if ((wp.db->mode == WP_AIRPORT) && 
  351. X          (lookup_desig (WP_VIA, wp.db->desig, &db)) &&
  352. X          IS_NAVAID (db->mode) &&
  353. X          COLOCATED (db, wp.db) ) {
  354. X      return (db);
  355. X   } else {
  356. X      return ((DATABASE_INFO*) 0);
  357. X   }
  358. X}
  359. X
  360. X/*----------------------------------------------------------------------------*/
  361. Xstatic track_nav1 ()
  362. X     /*
  363. X      * for each waypoint, determine what VOR to tune in on NAV1.
  364. X      *
  365. X      * This is tricky - some waypoints are navaids - so we want to track to 
  366. X      * (and sometimes from) them - others are just "distance-since-last-
  367. X      * -waypoint" or "lat/long" waypoints, and we can't track to those. 
  368. X      * From and To Airports also sometimes have VORS on-field, so we need to 
  369. X      * recognize when that happens so that we can track to/from airport 
  370. X      * waypoints. 
  371. X      *
  372. X      * The vor_fix[0] for each waypoint is for the leg _between_ that waypoint
  373. X      * and the next one. If there is no navaid that can be used to track along
  374. X      * that leg, set the .valid falg to FALSE.
  375. X      */
  376. X{
  377. X   int this, to;
  378. X   DATABASE_INFO *db;
  379. X
  380. X   /*
  381. X    * invalidate all the current NAV1 settings
  382. X    */
  383. X   for (this = 0; this < num_waypoints; this++) 
  384. X      waypoints[this].vor_fix[0].valid = FALSE;
  385. X
  386. X   to = 0;
  387. X   for (this = 0; (to != -1) && (this < num_waypoints); this++) {
  388. X      to = next_non_incremental (this+1);
  389. X      if (
  390. X      /*
  391. X       * if the next non-incremental waypoint is a navaid (or if an
  392. X       * airport and there's a navaid colocated on the field) then use that 
  393. X       * as NAV1 for this waypoint and those up to that one
  394. X       */
  395. X      ((to >= 0) && 
  396. X       (db = get_navaid (waypoints[to]))) ||
  397. X      /*
  398. X      * else, if this waypoint is a navaid, use it
  399. X      */
  400. X       (db = get_navaid (waypoints[this])) ) {
  401. X     for (; this < to; this++) {
  402. X        waypoints[this].vor_fix[0].valid = TRUE;
  403. X        waypoints[this].vor_fix[0].db    = db;
  404. X     }
  405. X     this = to - 1;
  406. X      } 
  407. X      /*
  408. X       * else, we're out of luck - leave the fix invalid.
  409. X       */
  410. X   }
  411. X}
  412. X
  413. X/*----------------------------------------------------------------------------*/
  414. Xnormalize_heading (head)
  415. X     double *head;
  416. X{
  417. X   if (*head < 0.0)
  418. X      *head += 360.0;
  419. X   else if (*head > 360.0)
  420. X      *head -= 360.0;
  421. X}
  422. X
  423. X/*----------------------------------------------------------------------------*/
  424. Xstatic BOOLEAN do_fix (plane_heading, latitude, longitude, vor_fix, force_from)
  425. X     double plane_heading;
  426. X     double latitude;
  427. X     double longitude;
  428. X     VOR_FIX *vor_fix;
  429. X     BOOLEAN force_from;
  430. X{
  431. X   double d;
  432. X   double lat_from  = latitude;
  433. X   double long_from = longitude;
  434. X   double lat_to    = vor_fix->db->latitude;
  435. X   double long_to   = vor_fix->db->longitude;
  436. X   
  437. X   if (! vor_fix->db)
  438. X      return FALSE;
  439. X
  440. X   if ((lat_from == lat_to) && (long_from == long_to))
  441. X      return FALSE;
  442. X
  443. X   distance_and_heading (lat_from, long_from, lat_to, long_to,
  444. X             &vor_fix->distance, &vor_fix->heading); 
  445. X   vor_fix->heading += vor_fix->db->mag_variation;
  446. X   normalize_heading (&vor_fix->heading);
  447. X   d = plane_heading - vor_fix->heading;
  448. X   vor_fix->from_to = TO;
  449. X   
  450. X   {
  451. X      double anti;
  452. X      double d1;
  453. X      
  454. X      anti = vor_fix->heading - 180;
  455. X      normalize_heading( &anti );
  456. X      d1 = plane_heading - anti;
  457. X      d1 = ( d1 < 0.0 ) ? -d1 : d1;      /* normalize_heading(&d1); */
  458. X      d  = ( d  < 0.0 ) ? -d  : d ;      /* normalize_heading(&d); */
  459. X      if( force_from || ( d > d1 ) ) {
  460. X     vor_fix->from_to = FROM;
  461. X     vor_fix->heading += 180.0;
  462. X      }
  463. X   }
  464. X   normalize_heading (&vor_fix->heading);
  465. X   return TRUE;
  466. X}
  467. X
  468. X/*----------------------------------------------------------------------------*/
  469. XBOOLEAN compute_plan (auto_nav1)
  470. X     BOOLEAN auto_nav1;
  471. X{
  472. X   int i;
  473. X   int num_pairs = 0;
  474. X#define MAX_NUM_PAIRS 30
  475. X   double total_dist [MAX_NUM_PAIRS];
  476. X   double distance, heading;
  477. X
  478. X   /*
  479. X    * locate the waypoints specified only by distance from last waypoint:
  480. X    */
  481. X   locate_incrementals ();
  482. X
  483. X   /*
  484. X    * accumulate the total distance between each from/to pair
  485. X    */
  486. X   num_pairs = 0;
  487. X   for (i = 0; i < num_waypoints; i++) {
  488. X      if (waypoints[i].wp_kind == WP_FROM) {
  489. X     waypoints[i].eta.valid = TRUE;
  490. X     waypoints[i].eta.value = 0.0;
  491. X     total_dist [num_pairs] = 0.0;
  492. X      }
  493. X      if ((i+1 < num_waypoints) && (waypoints[i].wp_kind != WP_TO)) {
  494. X     distance_and_heading (waypoints[i].db->latitude,
  495. X                   waypoints[i].db->longitude,
  496. X                   waypoints[i+1].db->latitude,
  497. X                   waypoints[i+1].db->longitude,
  498. X                   &distance, &heading);
  499. X     waypoints[i].dist_leg.valid = TRUE;
  500. X     waypoints[i].tc.valid       = TRUE;
  501. X     waypoints[i].mc.valid       = TRUE;
  502. X     waypoints[i].dist_leg.value = distance;
  503. X     waypoints[i].tc.value       = heading;
  504. X     waypoints[i].mc.value       = heading + waypoints[i].db->mag_variation;
  505. X     normalize_heading (&waypoints[i].mc.value);
  506. X     normalize_heading (&waypoints[i].tc.value);
  507. X      } else {
  508. X     waypoints[i].dist_leg.valid = FALSE;
  509. X     waypoints[i].tc.valid       = FALSE;
  510. X     waypoints[i].mc.valid       = FALSE;
  511. X      }
  512. X
  513. X      waypoints[i].dist.valid = TRUE;
  514. X      waypoints[i].dist.value = total_dist [num_pairs];
  515. X
  516. X      total_dist [num_pairs] += waypoints[i].dist_leg.value;
  517. X
  518. X      if (waypoints[i].wp_kind == WP_TO)
  519. X     num_pairs++;
  520. X   }
  521. X
  522. X   /*
  523. X    * now, do the distance remaining:
  524. X    */
  525. X   num_pairs = 0.0;
  526. X   for (i = 0; i < num_waypoints; i++) {
  527. X      waypoints[i].dist_remain.value = 
  528. X     total_dist [num_pairs] - waypoints[i].dist.value;
  529. X      waypoints[i].dist_remain.valid = TRUE;
  530. X      if (waypoints[i].wp_kind == WP_TO)
  531. X     num_pairs++;
  532. X   }
  533. X
  534. X   /*
  535. X    * wind correction (heading, ground speed)
  536. X    */
  537. X   for (i = 0; i < num_waypoints; i++) {
  538. X      if (waypoints[i].tas.valid && 
  539. X      waypoints[i].mc.valid) {
  540. X
  541. X     if (!waypoints[i].wind_speed.valid)
  542. X        waypoints[i].wind_speed.value = 0.0; 
  543. X     if (!waypoints[i].wind_direction.valid)
  544. X        waypoints[i].wind_direction.value = 0.0;
  545. X     wind_correct (waypoints[i].tas.value, 
  546. X               waypoints[i].mc.value, 
  547. X               waypoints[i].wind_speed.value,
  548. X               waypoints[i].wind_direction.value,
  549. X               &waypoints[i].egs.value,
  550. X               &waypoints[i].mh.value);
  551. X
  552. X     waypoints[i].egs.valid  = TRUE;
  553. X     waypoints[i].mh.valid   = TRUE;
  554. X     normalize_heading (&waypoints[i].mh.value);
  555. X
  556. X     /*
  557. X      * time in hours
  558. X      */
  559. X     waypoints[i].eta_leg.valid = waypoints[i].dist_leg.valid;
  560. X     waypoints[i].eta_leg.value = waypoints[i].dist_leg.value / 
  561. X        waypoints[i].egs.value;
  562. X      } else {
  563. X     waypoints[i].egs.valid     = FALSE;
  564. X     waypoints[i].mh.valid      = FALSE;
  565. X     waypoints[i].eta.valid     = FALSE;
  566. X     waypoints[i].eta_leg.valid = FALSE;
  567. X      }
  568. X      waypoints[i].eta.valid     = (BOOLEAN) (waypoints[i].wp_kind != WP_FROM);
  569. X      waypoints[i].eta.value     = (waypoints[i].dist.value == 0.0) ? 0.0 :
  570. X     waypoints[i-1].eta_leg.value + waypoints[i-1].eta.value;
  571. X   }
  572. X
  573. X   /*
  574. X    * fuel burn:
  575. X    */
  576. X   for (i = 0; i < num_waypoints; i++) {
  577. X      waypoints[i].fuel_leg.valid = (BOOLEAN) (waypoints[i].fuel_rate.valid &&
  578. X                           waypoints[i].eta_leg.valid);
  579. X      if (waypoints[i].fuel_leg.valid)
  580. X     waypoints[i].fuel_leg.value = 
  581. X        waypoints[i].fuel_rate.value * waypoints[i].eta_leg.value;
  582. X      if (waypoints[i].refuel) {
  583. X     waypoints[i].fuel_amt.valid = TRUE;
  584. X      } else if (i && (waypoints[i].wp_kind == WP_FROM) &&
  585. X         (!waypoints[i].refuel)) {
  586. X     waypoints[i].fuel_amt.valid = waypoints[i-1].fuel_amt.valid;
  587. X     waypoints[i].fuel_amt.value = waypoints[i-1].fuel_amt.value;
  588. X      } else if (i && waypoints[i-1].fuel_leg.valid &&
  589. X         waypoints[i-1].fuel_amt.valid) {
  590. X     waypoints[i].fuel_amt.value = 
  591. X        waypoints[i-1].fuel_amt.value - waypoints[i-1].fuel_leg.value;
  592. X      }
  593. X      if (waypoints[i].extra_fuel_burn.valid)
  594. X     waypoints[i].fuel_amt.value -= waypoints[i].extra_fuel_burn.value;
  595. X   }
  596. X
  597. X   if (auto_nav1)
  598. X      track_nav1 ();
  599. X
  600. X   /*
  601. X    * VOR cross fixes:
  602. X    */
  603. X   {
  604. X      int vor;
  605. X      for (i = 0; i < num_waypoints; i++) {
  606. X     for (vor = 0; vor < MAX_NUM_VOR_FIXES; vor++) {
  607. X        if (waypoints[i].vor_fix[vor].valid) {
  608. X           if (! do_fix (waypoints[i].mh.value, waypoints[i].db->latitude,
  609. X                 waypoints[i].db->longitude, 
  610. X                 &waypoints[i].vor_fix[vor], FALSE) ) {
  611. X          /*
  612. X           * if we failed to compute an xfix, it could be because we're
  613. X           * right on top of the navaid - pretend we're at the next
  614. X           * waypoint (since that's where we're going...)
  615. X           */
  616. X          if ((i+1) < num_waypoints) {
  617. X             if (!do_fix (waypoints[i].mh.value, 
  618. X                  waypoints[i+1].db->latitude,
  619. X                  waypoints[i+1].db->longitude, 
  620. X                  &waypoints[i].vor_fix[vor], TRUE))
  621. X            waypoints[i].vor_fix[vor].valid = FALSE;
  622. X          } else
  623. X             waypoints[i].vor_fix[vor].valid = FALSE;
  624. X           }
  625. X        }
  626. X     }
  627. X      }
  628. X   }
  629. X   return TRUE;
  630. X}
  631. X
  632. X
  633. END_OF_FILE
  634.   if test 14905 -ne `wc -c <'compute.c'`; then
  635.     echo shar: \"'compute.c'\" unpacked with wrong size!
  636.   fi
  637.   # end of 'compute.c'
  638. fi
  639. if test -f 'output.c' -a "${1}" != "-c" ; then 
  640.   echo shar: Will not clobber existing file \"'output.c'\"
  641. else
  642.   echo shar: Extracting \"'output.c'\" \(21837 characters\)
  643.   sed "s/^X//" >'output.c' <<'END_OF_FILE'
  644. X/*
  645. X * $Id: output.c,v 2.10 89/11/11 19:09:29 tynor Exp $
  646. X *----------------------------------------------------------------------------
  647. X *    FPLAN - Flight Planner
  648. X *    Steve Tynor
  649. X *    tynor@prism.gatech.edu
  650. X *
  651. X *    This program is in the public domain. Permission to copy,
  652. X * distribute, modify this program is hearby given as long as this header
  653. X * remains. If you redistribute this program after modifying it, please
  654. X * document your changes so that I do not take the blame (or credit) for
  655. X * those changes.  If you fix bugs or add features, please send me a
  656. X * patch so that I can keep the 'official' version up-to-date.
  657. X *
  658. X *    Bug reports are welcome and I'll make an attempt to fix those
  659. X * that are reported.
  660. X *
  661. X *    USE AT YOUR OWN RISK! I assume no responsibility for any
  662. X * errors in this program, its database or documentation. I will make an
  663. X * effort to fix bugs, but if you crash and burn because, for example,
  664. X * fuel estimates in this program were inaccurate, it's your own fault
  665. X * for trusting somebody else's code! Remember, as PIC, it's _your_
  666. X * responsibility to do complete preflight planning. Use this program as
  667. X * a flight planning aid, but verify its results before using them.
  668. X *----------------------------------------------------------------------------
  669. X */
  670. X
  671. Xstatic char rcsid[] = "$Id: output.c,v 2.10 89/11/11 19:09:29 tynor Exp $";
  672. X
  673. X#include <math.h>
  674. X#include <stdio.h>
  675. X#include "mystring.h"
  676. X#include "wp_info.h"
  677. X
  678. Xextern double decimal_2_degrees_mins();
  679. X
  680. Xtypedef enum {
  681. X   END_OF_FORMAT,    /* we count on ((int)END_OF_FORMAT == 0) */
  682. X   CITY, NAME, COMMENT, ELEV, FREQ, TYPE, DESIG, 
  683. X   TC, MC, MH, WIND, DIST_LEG, DIST, DIST_REMAIN,
  684. X   ETA_LEG, ETA, ATA, FUEL_AMT, FUEL_RATE, FUEL_LEG, ALT,
  685. X   TAS, EGS, AGS, VOR_DESIG, VOR_FREQ, VOR_RADIAL, LAT_LONG, VOR_DME,
  686. X   IGNORE, EMPTY, FORWARD_ARROW, BACKWARD_ARROW, 
  687. X   SEPARATOR, BAR, CROSS, EOL, END_OF_VOR,
  688. X   } FORMAT_KIND;
  689. X
  690. Xchar *headers[] = 
  691. X{
  692. X   "", "CITY", "CHECKPOINT", "COMMENT", "ELEV", "FREQ", "TYPE", "DESIG", 
  693. X   "TC", "MC", "MH", "WIND", "DIST", "DIS", "REM",
  694. X   "ETE", "ETE", "ATE", "FUEL", "RATE", "FUEL", "ALT",
  695. X   "TAS", "EGS", "AGS", "VOR", "FREQ", "RAD", "LAT/LONG", "DME", "", "",
  696. X};
  697. X
  698. Xtypedef enum {R, L} JUSTIFICATION;
  699. X
  700. Xtypedef enum {U,S} UNSHIFTED_OR_SHIFTED;
  701. X
  702. Xtypedef struct {
  703. X   FORMAT_KIND         kind;
  704. X   int             field_width;
  705. X   JUSTIFICATION     justification;
  706. X   int             arg;    /* which_vor or num_decimal_points */
  707. X   UNSHIFTED_OR_SHIFTED    shifted;
  708. X} FORMAT_SPEC_CELL;
  709. X
  710. X/*
  711. X * default format (for narrow output (e.g. to terminals) the VORs are not 
  712. X * output)
  713. X *
  714. X *                                                            VOR1    VOR2
  715. X *+=========//==============+===+=====+                            +=======+
  716. X *|NAME     //    TYPE DESIG|   | FUEL|                            |    VOR|
  717. X *|CITY     //      ALT FREQ|DIS|  ETE|======+===+====+====+=======|   FREQ|
  718. X *|COMMENT  //      LAT/LONG|REM|  ATE|    MC|TAS|DIST| ALT|    VOR|RAD DME|
  719. X *+=========//==============+===+=====>  WIND|EGS| ETE|RATE|   FREQ<-------+
  720. X *|         //              |   |     |    MH|AGS| ATE|FUEL|RAD DME|       |
  721. X *|         //              |   |     |======+===+====+====+=======|       |
  722. X *|         //              |   |     |      |   |    |    |       |       |
  723. X *+---------//--------------+---+----->      |   |    |    |       <-------+
  724. X *|         //              |   |     |      |   |    |    |       |       |
  725. X *|         //              |   |     |------+---+----+----+-------|       |
  726. X */
  727. X
  728. X#define MAX_NUM_FIELDS 170
  729. X
  730. XFORMAT_SPEC_CELL default_format_wide [] = 
  731. X{
  732. X   /* line 0 */
  733. X   /* WAYPOINT INFO */
  734. X   {CROSS},{SEPARATOR,44,L},{CROSS},
  735. X   {SEPARATOR,3}, {CROSS}, {SEPARATOR,5},{FORWARD_ARROW},
  736. X
  737. X   /* LEG INFO */
  738. X   {WIND,6,R,0,S},{BAR,1,R,0,S},{EGS,3,R,0,S},{BAR,1,R,0,S},
  739. X   {ETA_LEG,4,R,0,S},{BAR,1,R,0,S},{FUEL_RATE,5,R,1,S},{BAR,1,R,0,S},
  740. X   {END_OF_VOR,1,R,0,U},{VOR_FREQ,8,R,0,S},{BACKWARD_ARROW,1,R,0,U},
  741. X   /* WAYPOINT INFO */
  742. X   {END_OF_VOR,1,R,1,U},{SEPARATOR,8,R,1,U},{CROSS},
  743. X   {END_OF_VOR,1,R,2,U},{SEPARATOR,8,R,2,U},{CROSS},
  744. X   {END_OF_VOR,1,R,3,U},{SEPARATOR,8,R,3,U},{CROSS},
  745. X   {END_OF_VOR,1,R,4,U},{SEPARATOR,8,R,4,U},{CROSS},
  746. X   {END_OF_VOR,1,R,5,U},{SEPARATOR,8,R,5,U},{CROSS},
  747. X   {END_OF_VOR,1,R,6,U},{SEPARATOR,8,R,6,U},{CROSS},
  748. X   {END_OF_VOR,1,R,7,U},{SEPARATOR,8,R,7,U},{CROSS},
  749. X   {EOL}, 
  750. X
  751. X   /* line 1 */
  752. X   /* WAYPOINT INFO */
  753. X   {BAR},{NAME,32,L},{ELEV,5},{EMPTY,1},{DESIG,6},{BAR},
  754. X   {EMPTY,3}, {BAR}, {FUEL_AMT,5,R,1},{BAR},
  755. X   /* LEG INFO */
  756. X   {MH,6,R,0,S},{BAR,1,R,0,S},{AGS,3,R,0,S},{BAR,1,R,0,S},
  757. X   {ATA,4,R,0,S},{BAR,1,R,0,S},{FUEL_LEG,5,R,1,S},{BAR,1,R,0,S},
  758. X   {VOR_RADIAL,4,L,0,S},
  759. X   {VOR_DME,4,R,0,S},{BAR,1,R,0,U},
  760. X   /* WAYPOINT INFO */
  761. X   {VOR_DESIG,8,R,1,U},{BAR},
  762. X   {VOR_DESIG,8,R,2,U},{BAR},
  763. X   {VOR_DESIG,8,R,3,U},{BAR},
  764. X   {VOR_DESIG,8,R,4,U},{BAR},
  765. X   {VOR_DESIG,8,R,5,U},{BAR},
  766. X   {VOR_DESIG,8,R,6,U},{BAR},
  767. X   {VOR_DESIG,8,R,7,U},{BAR},
  768. X   {EOL}, 
  769. X
  770. X   /* line 2 */
  771. X   /* WAYPOINT INFO */
  772. X   {BAR},{CITY,29,L},{TYPE,8},{EMPTY,1},{FREQ,6},{BAR},
  773. X   {DIST,3}, {BAR},{ETA,5},{BAR},
  774. X   /* LEG INFO */
  775. X   {SEPARATOR,6,R,0,U},{CROSS,1,R,0,U},{SEPARATOR,3,R,0,U},{CROSS,1,R,0,U},
  776. X   {SEPARATOR,4,R,0,U},{CROSS,1,R,0,U},{SEPARATOR,5,R,0,U},{CROSS,1,R,0,U},
  777. X   {END_OF_VOR,1,R,0,U},{SEPARATOR,8,R,0,U},{BAR,1,R,0,U},
  778. X   /* WAYPOINT INFO */
  779. X   {VOR_FREQ,8,R,1,U},{BAR},
  780. X   {VOR_FREQ,8,R,2,U},{BAR},
  781. X   {VOR_FREQ,8,R,3,U},{BAR},
  782. X   {VOR_FREQ,8,R,4,U},{BAR},
  783. X   {VOR_FREQ,8,R,5,U},{BAR},
  784. X   {VOR_FREQ,8,R,6,U},{BAR},
  785. X   {VOR_FREQ,8,R,7,U},{BAR},
  786. X   {EOL}, 
  787. X
  788. X   /* line 3 */
  789. X   /* WAYPOINT INFO */
  790. X   {BAR},{COMMENT,26,L},{LAT_LONG,18},{BAR},
  791. X   {DIST_REMAIN,3}, {BAR},{ATA,5},{BAR},
  792. X   /* LEG INFO */
  793. X   {MC,6,R,0,S},{BAR,1,R,0,S},{TAS,3,R,0,S},{BAR,1,R,0,S},
  794. X   {DIST_LEG,4,R,0,S},{BAR,1,R,0,S},{ALT,5,R,0,S},{BAR,1,R,0,S},
  795. X   {VOR_DESIG,8,R,0,S},{BAR,1,R,0,U},
  796. X   /* WAYPOINT INFO */
  797. X   {VOR_RADIAL,4,L,1,U}, {VOR_DME,4,R,1,U},{BAR},
  798. X   {VOR_RADIAL,4,L,2,U}, {VOR_DME,4,R,2,U},{BAR},
  799. X   {VOR_RADIAL,4,L,3,U}, {VOR_DME,4,R,3,U},{BAR},
  800. X   {VOR_RADIAL,4,L,4,U}, {VOR_DME,4,R,4,U},{BAR},
  801. X   {VOR_RADIAL,4,L,5,U}, {VOR_DME,4,R,5,U},{BAR},
  802. X   {VOR_RADIAL,4,L,6,U}, {VOR_DME,4,R,6,U},{BAR},
  803. X   {VOR_RADIAL,4,L,7,U}, {VOR_DME,4,R,7,U},{BAR},
  804. X   {EOL}, 
  805. X   {END_OF_FORMAT}
  806. X};
  807. X
  808. X#ifdef OLD_FORMAT
  809. X/*
  810. X * Default wide column format:
  811. X *
  812. X+-------------//--------------+------+---+----+-----+-----+-----+-----+
  813. X|NAME         //    TYPE DESIG|    MC|TAS| LEG|  LEG|  ALT|  VOR|  VOR|
  814. X|CITY         //      ALT FREQ|  WIND|EGS|DIST|  ETA| RATE| FREQ| FREQ|
  815. X|COMMENT      //      LAT/LONG|    MH|AGS| REM|  ATA| FUEL|  RAD|  RAD|
  816. X+-------------//--------------+------+---+----+-----+-----+-----+-----+
  817. X *
  818. X * narrow column format is the same - without the last 2 fields
  819. X */
  820. X
  821. XFORMAT_SPEC_CELL default_format_wide [MAX_NUM_FIELDS] = 
  822. X{
  823. X   {BAR},{NAME,33,L},{TYPE,11},{EMPTY,1},{DESIG,6},{BAR},
  824. X   {MC,6},{BAR},{TAS,3},{BAR},
  825. X   {DIST_LEG,4},{BAR},{ETA_LEG,5},{BAR},{ALT,5},{BAR},
  826. X   {VOR_DESIG,6,R,0},{BAR},{VOR_DESIG,6,R,1},{BAR},
  827. X   {EOL}, 
  828. X
  829. X   {BAR},{CITY,33,L},{ELEV,11},{EMPTY,1},{FREQ,6,R,1},{BAR},
  830. X   {WIND,6},{BAR},{EGS,3},{BAR},
  831. X   {DIST,4},{BAR},{ETA,5},{BAR},{FUEL_RATE,5,R,1},{BAR},
  832. X   {VOR_FREQ,6,R,0},{BAR},{VOR_FREQ,6,R,1},{BAR},
  833. X   {EOL},
  834. X
  835. X   {BAR},{COMMENT,33,L},{LAT_LONG,18},
  836. X   {BAR},{MH,6},{BAR},{AGS,3},{BAR},
  837. X   {DIST_REMAIN,4},{BAR},{ATA,5},{BAR},{FUEL_AMT,5,R,1},{BAR},
  838. X   {VOR_RADIAL,6,R,0},{BAR},{VOR_RADIAL,6,R,1},{BAR},
  839. X   {EOL},
  840. X
  841. X   {END_OF_FORMAT}
  842. X};
  843. X#endif
  844. X
  845. XFORMAT_SPEC_CELL output_format [MAX_NUM_FIELDS];
  846. X
  847. Xint line_num;
  848. X
  849. Xenum {NAUTICAL, STATUTE} output_units = NAUTICAL;
  850. X/*
  851. X * the only things affected by the output_format are:
  852. X * speeds (TAS, GS) and distance (DIST, DIST_LEG, DIST_REMAIN)
  853. X * All are internally stored as knots and km.
  854. X */
  855. X#define NM_OR_MI(a) ((output_units == NAUTICAL) ? (a) : (a) * MI_PER_NM)
  856. X
  857. X#define EPSON_CROSS        197
  858. X#define EPSON_VERTICAL_BAR    179
  859. X#define EPSON_HORIZONTAL_BAR    196
  860. X#define EPSON_FORWARD_ARROW    180
  861. X#define EPSON_BACKWARD_ARROW    195
  862. Xstatic BOOLEAN use_epson_box_chars = FALSE;
  863. X
  864. X/*----------------------------------------------------------------------------*/
  865. Xvoid set_output_units (nautical)
  866. X     int nautical;
  867. X{
  868. X   if (nautical)
  869. X      output_units = NAUTICAL;
  870. X   else
  871. X      output_units = STATUTE;
  872. X}
  873. X
  874. X/*----------------------------------------------------------------------------*/
  875. Xvoid set_format (max_nav, epson)
  876. X     int max_nav;
  877. X     BOOLEAN epson;
  878. X{
  879. X   int i;
  880. X   FORMAT_SPEC_CELL *spec = default_format_wide;
  881. X
  882. X   use_epson_box_chars = epson;
  883. X   for (i = 0; i < MAX_NUM_FIELDS; i++) {
  884. X      if (((spec[i].kind == END_OF_VOR) ||
  885. X       (spec[i].kind == VOR_DESIG) ||
  886. X       (spec[i].kind == VOR_FREQ) ||
  887. X       (spec[i].kind == VOR_DME) ||
  888. X       (spec[i].kind == VOR_RADIAL))
  889. X      && 
  890. X      (max_nav < spec[i].arg)) {
  891. X     for (; (spec[i].kind != EOL) && (i < MAX_NUM_FIELDS); i++) {
  892. X        output_format[i].kind = IGNORE;
  893. X     }
  894. X     i--;
  895. X      } else {
  896. X     output_format[i] = spec[i];
  897. X      }
  898. X   }
  899. X#if 0
  900. X   output_format[i] = spec[i];
  901. X#endif
  902. X}
  903. X
  904. X/*----------------------------------------------------------------------------*/
  905. Xstatic void put_time (out_fp, field_width, hours)
  906. X     FILE   *out_fp;
  907. X     int    field_width;
  908. X     double hours;
  909. X{
  910. X   char   buffer[30];
  911. X   int    h       = (int) hours;
  912. X   double minutes = hours * 60.0;
  913. X
  914. X   if (h > 0) {
  915. X      sprintf (buffer, "%d:%02.0f", h, minutes - h * 60.0);
  916. X      fprintf (out_fp, "%*s", field_width, buffer);
  917. X   } else {
  918. X      fprintf (out_fp, "%*.0f", field_width, minutes);
  919. X   }
  920. X}
  921. X/*----------------------------------------------------------------------------*/
  922. Xstatic void put_string (out_fp, fw, str)
  923. XFILE *out_fp;
  924. Xint fw;
  925. Xchar *str;
  926. X{
  927. X   /*
  928. X    * force a string to fit in the specified field width. if we have to 
  929. X    * truncate, then indicate the truncation with a '>' in the last position
  930. X    */
  931. X
  932. X   char buffer[100];
  933. X
  934. X   strncpy (buffer, str, ABS (fw));
  935. X   if (strlen (str) > ABS(fw))
  936. X      buffer[ABS (fw)-1] = '>';
  937. X   buffer[ABS (fw)] = '\0';
  938. X#ifdef MSDOS
  939. X   /* 
  940. X    * both the Microsoft and Zortech compilers generate incorrect output for
  941. X    * negative field widths.
  942. X    */
  943. X   {
  944. X      int i;
  945. X      int xtra = ABS(fw) - strlen (buffer);
  946. X      
  947. X      if (fw > 0)
  948. X     for (i = 0; i < xtra; i++)
  949. X        fprintf (out_fp, " ");
  950. X      fprintf (out_fp, "%s", buffer);
  951. X      if (fw < 0)
  952. X     for (i = 0; i < xtra; i++)
  953. X        fprintf (out_fp, " ");
  954. X   }
  955. X#else
  956. X   fprintf (out_fp, "%*s", fw, buffer);
  957. X#endif
  958. X}
  959. X
  960. X/*----------------------------------------------------------------------------*/
  961. Xstatic void put_lat_long (out_fp, fw, latitude, longitude)
  962. X     FILE   *out_fp;
  963. X     int    fw;
  964. X     double latitude, longitude;
  965. X{
  966. X   char buffer [100];
  967. X   sprintf (buffer, "[%c%3.3lf,%c%3.3lf]", 
  968. X        (latitude > 0.0) ? 'N' : 'S',
  969. X        fabs ((double) decimal_2_degrees_mins (latitude)),
  970. X        (longitude > 0.0) ? 'W' : 'E',
  971. X        fabs ((double) decimal_2_degrees_mins (longitude)));
  972. X   fprintf (out_fp, "%*s", fw, buffer);
  973. X}
  974. X/*----------------------------------------------------------------------------*/
  975. Xstatic void put_db_mode (out_fp, fw, mode)
  976. X     FILE        *out_fp;
  977. X     int           fw;
  978. X     WAYPOINT_MODE mode;
  979. X{
  980. X   char *str_val;
  981. X
  982. X   switch (mode) {
  983. X   case WP_AIRPORT:
  984. X      str_val = "Airport";
  985. X      break;
  986. X   case WP_VOR:
  987. X      str_val = "VOR";
  988. X      break;
  989. X   case WP_NAMED_INTERSECTION:
  990. X   case WP_INTERSECTION:
  991. X      str_val = "Intersection";
  992. X      break;
  993. X   case WP_INCREMENTAL:
  994. X      str_val = "Incremental";
  995. X      break;
  996. X   case WP_LAT_LONG:
  997. X      str_val = "Lat/Long";
  998. X      break;
  999. X   case WP_NDB:
  1000. X      str_val = "NDB";
  1001. X      break;
  1002. X   case WP_DME:
  1003. X      str_val = "VOR/DME";
  1004. X      break;
  1005. X   case WP_TAC:
  1006. X      str_val = "TACAN";
  1007. X      break;
  1008. X   case WP_ILS:
  1009. X      str_val = "ILS";
  1010. X      break;
  1011. X   case WP_WPT:
  1012. X      str_val = "Waypoint";
  1013. X      break;
  1014. X   case WP_LOM:
  1015. X      str_val = "Outer Mkr";
  1016. X      break;
  1017. X   case WP_LMM:
  1018. X      str_val = "Middle Mkr";
  1019. X      break;
  1020. X   default:
  1021. X      break;
  1022. X   }
  1023. X   put_string (out_fp, fw, str_val);
  1024. X}
  1025. X/*----------------------------------------------------------------------------*/
  1026. Xstatic void put_header_cell (out_fp, cell, force)
  1027. X     FILE *out_fp;
  1028. X     FORMAT_SPEC_CELL cell;
  1029. X     BOOLEAN force;
  1030. X{
  1031. X   int fw = ((cell.justification == R) ? cell.field_width :
  1032. X         -1 * cell.field_width);
  1033. X
  1034. X
  1035. X   if ((cell.kind == IGNORE) || (cell.kind == END_OF_VOR))
  1036. X      return;
  1037. X
  1038. X   if (cell.kind == EOL) {
  1039. X      line_num++;
  1040. X      fprintf (out_fp, "\n");
  1041. X      return;
  1042. X   }
  1043. X
  1044. X   if ((!force) &&(cell.shifted == S) && ((line_num == 0) || (line_num == 1))) {
  1045. X      put_string (out_fp, cell.field_width, "");
  1046. X      return;
  1047. X   }
  1048. X
  1049. X   switch (cell.kind) {
  1050. X   case BAR:
  1051. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_VERTICAL_BAR : '|');
  1052. X      break;
  1053. X   case FORWARD_ARROW:
  1054. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_FORWARD_ARROW : '+');
  1055. X      break;
  1056. X   case BACKWARD_ARROW:
  1057. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_BACKWARD_ARROW : '+');
  1058. X      break;
  1059. X   case CROSS:
  1060. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_CROSS : '+');
  1061. X      break;
  1062. X   case SEPARATOR:
  1063. X      { 
  1064. X     int i;
  1065. X     for (i = 0; i < cell.field_width; i++)
  1066. X        fprintf (out_fp, "%c", 
  1067. X             use_epson_box_chars ? EPSON_HORIZONTAL_BAR : '-');
  1068. X      }
  1069. X      break;
  1070. X   default:
  1071. X      put_string (out_fp, fw, headers[(int) cell.kind]);
  1072. X   }
  1073. X}
  1074. X
  1075. X
  1076. X/*----------------------------------------------------------------------------*/
  1077. Xstatic void put_info_cell (out_fp, cell, prev_wp, curr_wp)
  1078. X     FILE             *out_fp;
  1079. X     FORMAT_SPEC_CELL cell;
  1080. X     WAYPOINT_INFO    *prev_wp, *curr_wp;
  1081. X{ 
  1082. X   WAYPOINT_INFO *wp;
  1083. X
  1084. X   int fw = ((cell.justification == R) ? cell.field_width :
  1085. X         -1 * cell.field_width);
  1086. X   char   *str_val;
  1087. X   double d_val;
  1088. X   char buffer[80];
  1089. X   BOOLEAN valid;
  1090. X   
  1091. X   if ((cell.kind == IGNORE) || (cell.kind == END_OF_VOR))
  1092. X      return;
  1093. X   if ((cell.shifted == S) &&
  1094. X    ((line_num == 0) || (line_num == 1))) {
  1095. X      if (! prev_wp) {
  1096. X     put_header_cell (out_fp, cell, TRUE);
  1097. X     return;
  1098. X      } else
  1099. X     wp = prev_wp;
  1100. X   } else
  1101. X      wp = curr_wp;
  1102. X
  1103. X   if ((cell.shifted == S) && (wp->wp_kind == WP_TO)) {
  1104. X      put_string (out_fp, cell.field_width, "");
  1105. X      return;
  1106. X   }
  1107. X
  1108. X   switch (cell.kind) {
  1109. X   case EOL:
  1110. X      line_num++;
  1111. X      fprintf (out_fp, "\n");
  1112. X      break;
  1113. X   case BAR:
  1114. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_VERTICAL_BAR : '|');
  1115. X      break;
  1116. X   case CROSS:
  1117. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_CROSS : '+');
  1118. X      break;
  1119. X   case FORWARD_ARROW:
  1120. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_FORWARD_ARROW : '>');
  1121. X      break;
  1122. X   case BACKWARD_ARROW:
  1123. X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_BACKWARD_ARROW : '<');
  1124. X      break;
  1125. X   case SEPARATOR:
  1126. X      { 
  1127. X     int i;
  1128. X     for (i = 0; i < cell.field_width; i++)
  1129. X        fprintf (out_fp, "%c", 
  1130. X             use_epson_box_chars ? EPSON_HORIZONTAL_BAR : '-');
  1131. X      }
  1132. X      break;
  1133. X      /*
  1134. X       * strings
  1135. X       */
  1136. X   case NAME:
  1137. X   case CITY:
  1138. X   case COMMENT:
  1139. X   case DESIG:
  1140. X   case VOR_DESIG:
  1141. X      switch (cell.kind) {
  1142. X      case CITY:
  1143. X     valid = TRUE;
  1144. X     str_val = wp->db->city;
  1145. X     break;
  1146. X      case NAME:
  1147. X     valid = TRUE;
  1148. X     str_val = wp->db->name;
  1149. X     break;
  1150. X      case COMMENT:
  1151. X     valid = TRUE;
  1152. X     str_val = wp->db->comment;
  1153. X     break;
  1154. X      case DESIG:
  1155. X     valid = TRUE;
  1156. X     str_val = wp->db->desig;
  1157. X     break;
  1158. X      case VOR_DESIG:
  1159. X     valid   = wp->vor_fix [cell.arg].valid;
  1160. X     if (valid)
  1161. X        str_val = wp->vor_fix [cell.arg].db->desig;
  1162. X     break;
  1163. X      default:
  1164. X     valid   = FALSE;
  1165. X     str_val = NULL;
  1166. X     break;
  1167. X      }
  1168. X      if (! str_val)
  1169. X     valid = FALSE;
  1170. X      if (valid) {
  1171. X     put_string (out_fp, fw, str_val);
  1172. X      } else
  1173. X     fprintf (out_fp, "%*s", fw, "");
  1174. X      break;
  1175. X      /*
  1176. X       * headings
  1177. X       */
  1178. X   case MH:
  1179. X   case MC:
  1180. X   case TC:
  1181. X      switch (cell.kind) {
  1182. X      case MH:
  1183. X     valid = wp->mh.valid;
  1184. X     d_val = wp->mh.value;
  1185. X     break;
  1186. X      case MC:
  1187. X     valid = wp->mc.valid;
  1188. X     d_val = wp->mc.value;
  1189. X     break;
  1190. X      case TC:
  1191. X     valid = wp->tc.valid;
  1192. X     d_val = wp->tc.value;
  1193. X     break;
  1194. X      default:
  1195. X     break;
  1196. X      }
  1197. X      if (valid) {
  1198. X     sprintf (buffer, "%03.*f", cell.arg, d_val);
  1199. X     fprintf (out_fp, "%*s", fw, buffer);
  1200. X      } else {
  1201. X     fprintf (out_fp, "%*s", fw, "");
  1202. X      }
  1203. X      break;
  1204. X      /*
  1205. X       * numbers
  1206. X       */
  1207. X   case FREQ:
  1208. X   case VOR_FREQ:
  1209. X      switch (cell.kind) {
  1210. X      case VOR_FREQ:
  1211. X     valid = wp->vor_fix [cell.arg].valid;
  1212. X     if (valid) 
  1213. X        d_val = wp->vor_fix [cell.arg].db->freq.value;
  1214. X     break;
  1215. X      case FREQ:
  1216. X     valid = wp->db->freq.valid;
  1217. X     d_val = wp->db->freq.value;
  1218. X     break;
  1219. X      default:
  1220. X     valid = FALSE;
  1221. X     break;
  1222. X      }
  1223. X      if (valid) {
  1224. X     fprintf (out_fp, "%*.2f", fw, d_val);
  1225. X      } else
  1226. X     fprintf (out_fp, "%*s", fw, "");
  1227. X      break;
  1228. X   case ELEV:
  1229. X   case TAS:
  1230. X   case EGS:
  1231. X   case FUEL_AMT:
  1232. X   case FUEL_LEG:
  1233. X   case FUEL_RATE:
  1234. X   case DIST_LEG:
  1235. X   case DIST:
  1236. X   case DIST_REMAIN:
  1237. X      switch (cell.kind) {
  1238. X      case ELEV:
  1239. X     valid = wp->db->altitude.valid;
  1240. X     d_val = wp->db->altitude.value;
  1241. X     break;
  1242. X      case TAS:
  1243. X     valid = wp->tas.valid;
  1244. X     d_val = NM_OR_MI (wp->tas.value); 
  1245. X     break;
  1246. X      case EGS:
  1247. X     valid = wp->egs.valid;
  1248. X     d_val = NM_OR_MI (wp->egs.value);
  1249. X     break;
  1250. X      case FUEL_AMT:
  1251. X     valid = wp->fuel_amt.valid;
  1252. X     d_val = wp->fuel_amt.value;
  1253. X     break;
  1254. X      case FUEL_LEG:
  1255. X     valid = wp->fuel_leg.valid;
  1256. X     d_val = wp->fuel_leg.value;
  1257. X     break;
  1258. X      case FUEL_RATE:
  1259. X     valid = wp->fuel_rate.valid;
  1260. X     d_val = wp->fuel_rate.value;
  1261. X     break;
  1262. X      case DIST_LEG:
  1263. X     valid = wp->dist_leg.valid;
  1264. X     d_val = NM_OR_MI (wp->dist_leg.value);
  1265. X     break;
  1266. X      case DIST:
  1267. X     valid = wp->dist.valid;
  1268. X     d_val = NM_OR_MI (wp->dist.value);
  1269. X     break;
  1270. X      case DIST_REMAIN:
  1271. X     valid = wp->dist_remain.valid;
  1272. X     d_val = NM_OR_MI (wp->dist_remain.value);
  1273. X     break;
  1274. X      default:
  1275. X     valid = FALSE;
  1276. X     d_val = 0.0;
  1277. X     break;
  1278. X      }
  1279. X      if (valid) {
  1280. X     fprintf (out_fp, "%*.*f", fw, cell.arg, d_val);
  1281. X      } else
  1282. X     fprintf (out_fp, "%*s", fw, "");
  1283. X      break;
  1284. X      /*
  1285. X       * times:
  1286. X       */
  1287. X   case ETA:
  1288. X   case ETA_LEG:
  1289. X      valid = (cell.kind == ETA) ? wp->eta.valid : wp->eta_leg.valid;
  1290. X      d_val = (cell.kind == ETA) ? wp->eta.value : wp->eta_leg.value;
  1291. X      if (valid)
  1292. X     put_time (out_fp, fw, d_val);
  1293. X      else
  1294. X     fprintf (out_fp, "%*s", fw, "");
  1295. X      break;
  1296. X   case VOR_DME:
  1297. X      if (wp->vor_fix[cell.arg].valid)
  1298. X     fprintf (out_fp, "%*.0lf", fw, wp->vor_fix[cell.arg].distance);
  1299. X      else
  1300. X     fprintf (out_fp, "%*s", fw, "");
  1301. X      break;
  1302. X   case VOR_RADIAL:
  1303. X      if (wp->vor_fix[cell.arg].valid) {
  1304. X     sprintf (buffer, "%03.0f%c", wp->vor_fix[cell.arg].heading, 
  1305. X          (wp->vor_fix[cell.arg].from_to == FROM ? 'F' : 'T') );
  1306. X     fprintf (out_fp, "%*s", fw, buffer);
  1307. X      } else {
  1308. X     fprintf (out_fp, "%*s", fw, "");
  1309. X      }
  1310. X      break;
  1311. X   case LAT_LONG:
  1312. X      put_lat_long (out_fp, fw, wp->db->latitude, wp->db->longitude);
  1313. X      break;
  1314. X   case ALT:
  1315. X      if (! wp->altitude.valid) {
  1316. X     fprintf (out_fp, "%*s", fw, "");
  1317. X#if 0
  1318. X      } else if (wp->altitude.value < 1000.0) {
  1319. X     sprintf (buffer, "FL%g", wp->altitude.value);
  1320. X     fprintf (out_fp, "%*s", fw, buffer);
  1321. X#endif
  1322. X      } else {
  1323. X     fprintf (out_fp, "%*.0f", fw, wp->altitude.value);
  1324. X      }
  1325. X      break;
  1326. X   case WIND:
  1327. X      if (wp->wind_direction.valid && wp->wind_speed.valid) {
  1328. X     sprintf (buffer, "%03.0f@%02.0f", wp->wind_direction.value, 
  1329. X          wp->wind_speed.value);
  1330. X     fprintf (out_fp, "%*s", fw, buffer);
  1331. X      } else {
  1332. X     fprintf (out_fp, "%*s", fw, "");
  1333. X      }
  1334. X      break;
  1335. X   case TYPE:
  1336. X      put_db_mode (out_fp, fw, wp->db->mode);
  1337. X      break;
  1338. X   case EMPTY:
  1339. X   case ATA:
  1340. X   case AGS:
  1341. X   default:
  1342. X      fprintf (out_fp, "%*s", fw, "");
  1343. X      break;
  1344. X   }    
  1345. X}
  1346. X
  1347. X/*----------------------------------------------------------------------------*/
  1348. Xstatic void put_info_cells (out_fp, cells, prev_wp, wp)
  1349. X     FILE             *out_fp;
  1350. X     FORMAT_SPEC_CELL cells[];
  1351. X     WAYPOINT_INFO    *prev_wp, *wp;
  1352. X{
  1353. X   int i;
  1354. X
  1355. X   line_num = 0;
  1356. X   for (i = 0; (cells[i].kind != END_OF_FORMAT); i++) 
  1357. X      put_info_cell (out_fp, cells[i], prev_wp, wp);
  1358. X}
  1359. X
  1360. X/*----------------------------------------------------------------------------*/
  1361. Xstatic void put_header_cells (out_fp, cells, first_line_only)
  1362. X     FILE             *out_fp;
  1363. X     FORMAT_SPEC_CELL cells[];
  1364. X     BOOLEAN first_line_only;
  1365. X{
  1366. X   int i;
  1367. X
  1368. X   line_num = 0;
  1369. X   for (i = 0; (cells[i].kind != END_OF_FORMAT); i++) {
  1370. X      if (first_line_only && line_num)
  1371. X     return;
  1372. X      else
  1373. X     put_header_cell (out_fp, cells[i], FALSE);
  1374. X   }
  1375. X}
  1376. X
  1377. X/*----------------------------------------------------------------------------*/
  1378. Xvoid print_plan ()
  1379. X{
  1380. X   int i;
  1381. X
  1382. X   for (i = 0; i < num_waypoints; i++) {
  1383. X      if (waypoints[i].wp_kind == WP_FROM) {
  1384. X     if (i)
  1385. X        fprintf (stdout, "\f");
  1386. X     printf ("\nSpeeds in %s; Distances in %s miles\n",
  1387. X         (output_units == NAUTICAL) ? "knots" : "mph (wind in knots)",
  1388. X         (output_units == NAUTICAL) ? "nautical" : "statute");
  1389. X     put_header_cells (stdout, output_format, FALSE);
  1390. X      }
  1391. X      put_info_cells (stdout, output_format,
  1392. X              (waypoints[i].wp_kind == WP_FROM) ? 0 : &waypoints[i-1],
  1393. X              &waypoints[i]);
  1394. X      if (waypoints[i].wp_kind == WP_TO)
  1395. X     put_header_cells (stdout, output_format, TRUE);
  1396. X   }
  1397. X}
  1398. X
  1399. X
  1400. X/*----------------------------------------------------------------------------*/
  1401. Xput_db (out_fp, db)
  1402. X     FILE          *out_fp;
  1403. X     DATABASE_INFO *db;
  1404. X{
  1405. X   fprintf (out_fp, "______________________________________________________________________________\n");
  1406. X   fprintf (out_fp, "%s\t", db->desig);
  1407. X   put_db_mode (out_fp, -12, db->mode);
  1408. X   if (db->name)
  1409. X      fprintf (out_fp, "\nNAME   : %s\n", db->name);
  1410. X   if (db->city)
  1411. X      fprintf (out_fp, "CITY   : %s\n", db->city);
  1412. X   if (db->comment)
  1413. X      fprintf (out_fp, "COMMENT: %s\n", db->comment);
  1414. X   fprintf (out_fp, "LAT/LONG: ");
  1415. X   put_lat_long (out_fp, 1, db->latitude, db->longitude);
  1416. X   fprintf (out_fp, " MAG VARIATION: %g ", db->mag_variation);
  1417. X   if (db->freq.valid)
  1418. X      fprintf (out_fp, "FREQ: %7.2f ", db->freq.value);
  1419. X   if (db->altitude.valid)
  1420. X      fprintf (out_fp, "ALTITUDE: %g", db->altitude.value);
  1421. X   fprintf (out_fp, "\n");
  1422. X}
  1423. END_OF_FILE
  1424.   if test 21837 -ne `wc -c <'output.c'`; then
  1425.     echo shar: \"'output.c'\" unpacked with wrong size!
  1426.   fi
  1427.   # end of 'output.c'
  1428. fi
  1429. if test -f 'sv_draw.c' -a "${1}" != "-c" ; then 
  1430.   echo shar: Will not clobber existing file \"'sv_draw.c'\"
  1431. else
  1432.   echo shar: Extracting \"'sv_draw.c'\" \(8895 characters\)
  1433.   sed "s/^X//" >'sv_draw.c' <<'END_OF_FILE'
  1434. X/*
  1435. X * $Id: sv_draw.c,v 1.3 89/11/11 19:43:17 tynor Exp $
  1436. X *----------------------------------------------------------------------------
  1437. X *    FPLAN - Flight Planner
  1438. X *    Steve Tynor
  1439. X *    tynor@prism.gatech.edu
  1440. X *
  1441. X *    This program is in the public domain. Permission to copy,
  1442. X * distribute, modify this program is hearby given as long as this header
  1443. X * remains. If you redistribute this program after modifying it, please
  1444. X * document your changes so that I do not take the blame (or credit) for
  1445. X * those changes.  If you fix bugs or add features, please send me a
  1446. X * patch so that I can keep the 'official' version up-to-date.
  1447. X *
  1448. X *    Bug reports are welcome and I'll make an attempt to fix those
  1449. X * that are reported.
  1450. X *
  1451. X *    USE AT YOUR OWN RISK! I assume no responsibility for any
  1452. X * errors in this program, its database or documentation. I will make an
  1453. X * effort to fix bugs, but if you crash and burn because, for example,
  1454. X * fuel estimates in this program were inaccurate, it's your own fault
  1455. X * for trusting somebody else's code! Remember, as PIC, it's _your_
  1456. X * responsibility to do complete preflight planning. Use this program as
  1457. X * a flight planning aid, but verify its results before using them.
  1458. X *----------------------------------------------------------------------------
  1459. X */
  1460. X
  1461. X#ifdef GFX_SUNVIEW 
  1462. X
  1463. X/*
  1464. X *==============================================================================
  1465. X * Graphics routines for Sunview
  1466. X *==============================================================================
  1467. X */
  1468. X
  1469. X#include "wp_info.h"
  1470. X#include <suntool/sunview.h>
  1471. X#include <suntool/canvas.h>
  1472. X#include <suntool/panel.h>
  1473. X#include <suntool/scrollbar.h>
  1474. X
  1475. Xstatic char rcsid[] = "$Id: sv_draw.c,v 1.3 89/11/11 19:43:17 tynor Exp $";
  1476. X
  1477. Xstatic double min_lat;
  1478. Xstatic double max_lat;
  1479. Xstatic double min_long;
  1480. Xstatic double max_long;
  1481. X
  1482. X#define PIX_OR (PIX_SRC | PIX_DST) /* Rasterop */
  1483. X
  1484. XPixfont *font;
  1485. X#define DEFAULT_SCALE 100 /* pixels per degree */
  1486. X#define SV_MARGIN 40
  1487. X
  1488. XPanel panel;
  1489. XFrame frame;
  1490. XCanvas canvas;
  1491. Xstatic BOOLEAN brief_mode;
  1492. Xint scale = DEFAULT_SCALE;
  1493. XBOOLEAN first_time;
  1494. XScrollbar vert_scroll, horiz_scroll;
  1495. X
  1496. X/*----------------------------------------------------------------------------*/
  1497. Xstatic void sv_draw_pt (canvas, x, y)
  1498. X     Canvas canvas;
  1499. X     int x, y;
  1500. X{
  1501. X   pw_writebackground (canvas_pixwin (canvas), x-1, y-1, 3, 3,
  1502. X               PIX_NOT (PIX_SRC));
  1503. X}
  1504. X
  1505. X/*----------------------------------------------------------------------------*/
  1506. Xstatic void sv_draw_str (canvas, x, y, str)
  1507. X     Canvas canvas;
  1508. X     int x, y;
  1509. X     char *str;
  1510. X{
  1511. X   pw_text (canvas_pixwin (canvas), x+3, y+3, PIX_OR, font, str);
  1512. X}
  1513. X
  1514. X/*----------------------------------------------------------------------------*/
  1515. Xstatic void sv_project (latitude, longitude, x, y)
  1516. Xdouble latitude, longitude;
  1517. Xint *x, *y;
  1518. X{
  1519. X   /*
  1520. X    * NOTE: this is "Tynor's naive projection system" - ignores the curvature
  1521. X    * of the earth:
  1522. X    */
  1523. X
  1524. X   *x = SV_MARGIN + (int) ((max_long - longitude) * (double) scale);
  1525. X   *y = SV_MARGIN + (int) ((max_lat - latitude  ) * (double) scale);
  1526. X}
  1527. X
  1528. X/*----------------------------------------------------------------------------*/
  1529. Xstatic void sv_draw_db (canvas, db)
  1530. X     Canvas canvas;
  1531. X     DATABASE_INFO *db;
  1532. X{
  1533. X   int x, y;
  1534. X
  1535. X   sv_project (db->latitude, db->longitude, &x, &y);
  1536. X   sv_draw_pt (canvas, x, y);
  1537. X   sv_draw_str (canvas, x, y,
  1538. X         (db->mode != WP_INCREMENTAL) ? db->desig : db->name);
  1539. X}
  1540. X
  1541. X/*----------------------------------------------------------------------------*/
  1542. Xstatic void sv_draw_leg (canvas, db1, db2)
  1543. X     Canvas canvas;
  1544. X     DATABASE_INFO *db1, *db2;
  1545. X{
  1546. X   int x1, y1, x2, y2;
  1547. X
  1548. X   sv_project (db1->latitude, db1->longitude, &x1, &y1);
  1549. X   sv_project (db2->latitude, db2->longitude, &x2, &y2);
  1550. X
  1551. X   pw_vector (canvas_pixwin (canvas), x1, y1, x2, y2, PIX_OR, 1);
  1552. X}
  1553. X
  1554. X/*----------------------------------------------------------------------------*/
  1555. Xstatic void sv_scroll_to (db)
  1556. X     DATABASE_INFO *db;
  1557. X{
  1558. X   int x, y;
  1559. X
  1560. X   sv_project (db->latitude, db->longitude, &x, &y);
  1561. X
  1562. X   /*
  1563. X    * try to center the waypoint on the canvas
  1564. X    */
  1565. X   scrollbar_scroll_to (horiz_scroll, 
  1566. X            MIN ((int)window_get (canvas, CANVAS_WIDTH, 0),
  1567. X                 MAX (0, 
  1568. X                  x - (int)window_get (canvas, 
  1569. X                               WIN_WIDTH, 0) / 2)));
  1570. X   scrollbar_scroll_to (vert_scroll, 
  1571. X            MIN ((int)window_get (canvas, CANVAS_HEIGHT, 0),
  1572. X                 MAX (0, 
  1573. X                  y - (int)window_get (canvas, 
  1574. X                               WIN_HEIGHT, 0) / 2)));
  1575. X}
  1576. X
  1577. X/*----------------------------------------------------------------------------*/
  1578. Xstatic void sv_redraw ()
  1579. X{
  1580. X   int width, height, i;
  1581. X
  1582. X#define MIN_WIDTH 400
  1583. X#define XTRA_WIDTH   30 /* frame needs to be this much bigger than the canvas */
  1584. X#define XTRA_HEIGHT 100 /* frame needs to be this much bigger than the canvas */
  1585. X
  1586. X   width  = ABS ((int) ((max_long - min_long) * (double) scale)) + 
  1587. X      2 * SV_MARGIN;
  1588. X   height = ABS ((int) ((max_lat - min_lat)   * (double) scale)) +
  1589. X      2 * SV_MARGIN;
  1590. X
  1591. X   width = MAX (width, MIN_WIDTH);
  1592. X
  1593. X   window_set (canvas, CANVAS_HEIGHT, height, 0);
  1594. X   window_set (canvas, CANVAS_WIDTH, width, 0);
  1595. X
  1596. X   pw_writebackground (canvas_pixwin (canvas), 0, 0, 3000, 3000, PIX_SRC);
  1597. X
  1598. X   for (i = 0; i < num_cached; i++) {
  1599. X      sv_draw_db (canvas, cache[i]);
  1600. X   }
  1601. X
  1602. X   for (i = 0; i < num_waypoints - 1; i++) {
  1603. X      sv_draw_leg (canvas, waypoints[i].db, waypoints[i+1].db);
  1604. X      if ((!brief_mode) && (waypoints[i].db->mode == WP_INCREMENTAL))
  1605. X     sv_draw_db (canvas, waypoints[i].db);
  1606. X   }
  1607. X
  1608. X   if (first_time) {
  1609. X      Pixrect *screen = pr_open ("/dev/fb");
  1610. X
  1611. X      window_set (frame, WIN_WIDTH, MIN (screen->pr_size.x, 
  1612. X                     XTRA_WIDTH + width), 0);
  1613. X      window_set (frame, WIN_HEIGHT, MIN (screen->pr_size.y,
  1614. X                      XTRA_HEIGHT + height), 0);
  1615. X      first_time = FALSE;
  1616. X      sv_scroll_to (waypoints[0].db);
  1617. X   }
  1618. X}
  1619. X
  1620. X/*----------------------------------------------------------------------------*/
  1621. Xsv_quit_event_proc (item, event)
  1622. X     Panel_item item;
  1623. X     Event *event;
  1624. X{
  1625. X   window_destroy (frame);
  1626. X}
  1627. X
  1628. X/*----------------------------------------------------------------------------*/
  1629. Xsv_brief_event_proc (item, event)
  1630. X     Panel_item item;
  1631. X     Event *event;
  1632. X{
  1633. X   brief_mode = (int) panel_get (item, PANEL_VALUE, 0);
  1634. X   sv_redraw ();
  1635. X}
  1636. X
  1637. X/*----------------------------------------------------------------------------*/
  1638. Xsv_tofirst_event_proc (item, event)
  1639. X     Panel_item item;
  1640. X     Event *event;
  1641. X{
  1642. X   sv_scroll_to (waypoints[0].db);
  1643. X}
  1644. X
  1645. X/*----------------------------------------------------------------------------*/
  1646. Xsv_tolast_event_proc (item, event)
  1647. X     Panel_item item;
  1648. X     Event *event;
  1649. X{
  1650. X   sv_scroll_to (waypoints[num_waypoints-1].db);
  1651. X}
  1652. X
  1653. X/*----------------------------------------------------------------------------*/
  1654. Xsv_scale_event_proc (item, event)
  1655. X     Panel_item item;
  1656. X     Event *event;
  1657. X{
  1658. X   scale = (int) panel_get (item, PANEL_VALUE, 0);
  1659. X   sv_redraw ();
  1660. X}
  1661. X
  1662. X/*----------------------------------------------------------------------------*/
  1663. Xvoid sv_draw (brief)
  1664. X     BOOLEAN brief;
  1665. X{
  1666. X
  1667. X   min_max_lat_long (&min_lat, &max_lat, &min_long, &max_long);
  1668. X
  1669. X   brief_mode = brief;
  1670. X   font = pf_open ("/usr/lib/fonts/fixedwidthfonts/screen.r.7");
  1671. X
  1672. X   frame = window_create (NULL, FRAME,
  1673. X              FRAME_LABEL, "FPLAN",
  1674. X              0);
  1675. X
  1676. X   panel = window_create (frame, PANEL,
  1677. X              0);
  1678. X   
  1679. X   panel_create_item (panel, PANEL_BUTTON,
  1680. X              PANEL_NOTIFY_PROC, sv_quit_event_proc,
  1681. X              PANEL_LABEL_IMAGE, panel_button_image (panel,
  1682. X                                 "Quit", 0, 0),
  1683. X              PANEL_ITEM_X,       ATTR_COL (0),
  1684. X              PANEL_ITEM_Y,       ATTR_ROW (0),
  1685. X              0);
  1686. X
  1687. X   panel_create_item (panel, PANEL_BUTTON,
  1688. X              PANEL_NOTIFY_PROC, sv_tofirst_event_proc,
  1689. X              PANEL_LABEL_IMAGE, panel_button_image (panel,
  1690. X                                 "To First", 0, 0),
  1691. X              0);
  1692. X
  1693. X   panel_create_item (panel, PANEL_BUTTON,
  1694. X              PANEL_NOTIFY_PROC, sv_tolast_event_proc,
  1695. X              PANEL_LABEL_IMAGE, panel_button_image (panel,
  1696. X                                 "To Last", 0, 0),
  1697. X              0);
  1698. X
  1699. X   panel_create_item (panel, PANEL_CYCLE,
  1700. X              PANEL_LABEL_STRING,   "Brief:",
  1701. X              PANEL_CHOICE_STRINGS, "NO", "YES", 0,
  1702. X              PANEL_NOTIFY_PROC,    sv_brief_event_proc,
  1703. X              PANEL_VALUE,         brief_mode,
  1704. X              0);        
  1705. X
  1706. X   panel_create_item (panel, PANEL_SLIDER,
  1707. X              PANEL_LABEL_STRING, "Scale:",
  1708. X              PANEL_VALUE,        scale,
  1709. X              PANEL_MIN_VALUE,        5,
  1710. X              PANEL_MAX_VALUE,        400,
  1711. X              PANEL_SLIDER_WIDTH,  200,
  1712. X              PANEL_NOTIFY_PROC,   sv_scale_event_proc,
  1713. X              0);        
  1714. X
  1715. X   window_fit_height (panel);
  1716. X
  1717. X   horiz_scroll = scrollbar_create(0);
  1718. X   vert_scroll = scrollbar_create(0);
  1719. X
  1720. X   canvas = window_create (frame, CANVAS,
  1721. X               CANVAS_AUTO_SHRINK, FALSE,
  1722. X               WIN_VERTICAL_SCROLLBAR, vert_scroll,
  1723. X               WIN_HORIZONTAL_SCROLLBAR, horiz_scroll,
  1724. X               CANVAS_WIDTH, 1,
  1725. X               CANVAS_HEIGHT, 1,
  1726. X               0);
  1727. X   scrollbar_set (horiz_scroll, SCROLL_ADVANCED_MODE, 1, 0);
  1728. X   scrollbar_set (vert_scroll, SCROLL_ADVANCED_MODE, 1, 0);
  1729. X
  1730. X   first_time = TRUE;
  1731. X   sv_redraw ();
  1732. X   window_main_loop (frame);
  1733. X}
  1734. X
  1735. X#endif /* GFX_SUNVIEW */
  1736. END_OF_FILE
  1737.   if test 8895 -ne `wc -c <'sv_draw.c'`; then
  1738.     echo shar: \"'sv_draw.c'\" unpacked with wrong size!
  1739.   fi
  1740.   # end of 'sv_draw.c'
  1741. fi
  1742. echo shar: End of archive 1 \(of 4\).
  1743. cp /dev/null ark1isdone
  1744. MISSING=""
  1745. for I in 1 2 3 4 ; do
  1746.     if test ! -f ark${I}isdone ; then
  1747.     MISSING="${MISSING} ${I}"
  1748.     fi
  1749. done
  1750. if test "${MISSING}" = "" ; then
  1751.     echo You have unpacked all 4 archives.
  1752.     rm -f ark[1-9]isdone
  1753. else
  1754.     echo You still must unpack the following archives:
  1755.     echo "        " ${MISSING}
  1756. fi
  1757. exit 0
  1758. exit 0 # Just in case...
  1759.