home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / mbase / part03 < prev    next >
Encoding:
Text File  |  1992-11-23  |  54.9 KB  |  1,702 lines

  1. Newsgroups: comp.sources.misc
  2. From: richid@owlnet.rice.edu (Richard Parvin Jernigan)
  3. Subject:  v33i121:  mbase - MetalBase 5.0, Portable database engine, Part03/08
  4. Message-ID: <1992Nov23.232430.7223@sparky.imd.sterling.com>
  5. X-Md4-Signature: f81c89ae5f27e6945586775c564c7210
  6. Date: Mon, 23 Nov 1992 23:24:30 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: richid@owlnet.rice.edu (Richard Parvin Jernigan)
  10. Posting-number: Volume 33, Issue 121
  11. Archive-name: mbase/part03
  12. Environment: AMIGA, MS-DOS, HP-UX, XENIX, UNIX, ULTRIX, SGI, SU, Curses
  13. Supersedes: mbase: Volume 28, Issue 40-44
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  dox/vr.dox sample/sample.c sample/sample.rpt src/input.c
  20. #   src/vr.c
  21. # Wrapped by kent@sparky on Mon Nov 23 16:33:12 1992
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 3 (of 8)."'
  25. if test -f 'dox/vr.dox' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'dox/vr.dox'\"
  27. else
  28.   echo shar: Extracting \"'dox/vr.dox'\" \(5167 characters\)
  29.   sed "s/^X//" >'dox/vr.dox' <<'END_OF_FILE'
  30. XVR -- View Relation                                               MetalBase 5.0
  31. X-------------------------------------------------------------------------------
  32. X
  33. X                                   Curses
  34. X
  35. X     Take a look at curses.dox if you're using MS-DOS and don't have curses.
  36. X
  37. X                                  Functions
  38. X
  39. XVR is utility which allows visual querying and modification of the records
  40. Xin any relation.  I'll be honest here--I modeled it directly after Informix'
  41. Xenter2 command... not a bad port, if I do say so, seeing as I have no idea
  42. Xhow they did theirs.  So thanks for the idea, Informix; you know, imitation is
  43. Xthe sincerest form of flattery...
  44. X
  45. XThe command-line format is trivial:
  46. X    % vr [relationname[.rel]]
  47. XIf not compiled with -DNOENCRYPT, vr will ask for an encryption password after
  48. Xevery time a relation is specified; on the command line, or with the 'Rel'
  49. Xoption from the main menu.  This password is hashed using the standard
  50. Xstrtokey() function in MetalBase, and is used to open the relation.  If a
  51. Xrelation is specified on the command line which cannot be opened, vr will
  52. Xreturn to the command line after indicating the error.  Once at the main
  53. Xmenu, though, vr will not exit until you tell it to; errors instead appear on
  54. Xthe bottom line of the display, highlighted (nifty, eh?).
  55. X
  56. XThe various functions performed by vr are:
  57. X
  58. XFirst  -- Find the first record in the given relation, on the current index.
  59. X          When a relation is first opened, the current index is set to the
  60. X          first specified in the schema; afterwards, it may be selected using
  61. X          the 'Idx' option, described below.
  62. XLast   -- Find the last record in the relation, following the current index.
  63. XNext   -- Find the next record sequentially.  If no current record is selected
  64. X          (the fields shown will all be blank or 0), this function acts as if
  65. X          you had selected 'First'.
  66. XPrev   -- Find the previous record sequentially.  If no current record is
  67. X          selected, this function acts as if you had selected 'Last'.
  68. XGteq   -- Find the record which is greater than or equal to a specified record,
  69. X          alphabetically/numerically (whichever is appropriate for each field).
  70. X          When you select Gteq or Equ (described below), all fields will
  71. X          disappear from the display other than those used by the current
  72. X          index; these will appear in the order in which they are used by the
  73. X          index.  Enter as many as you like, starting with the first
  74. X          (naturally); when you hit accept the transaction (movement is
  75. X          described later), it will search for the appropriate record and, if
  76. X          found, display it.
  77. XEqu    -- Similar to Gteq, Equ will accept only a record which is exactly equal
  78. X          to that specified for the relevant fields; if one is not found, the
  79. X          query fails.
  80. XIdx    -- Selecting Idx will allow you to change which index is currently being
  81. X          used to search.  A list will appear for you of valid indices and
  82. X          their order; you may enter either their name or number.
  83. XScreen -- If a relation has more than 18 fields, they will not all fit on the
  84. X          display at once; selecting 'screen' will toggle which set of 18
  85. X          is displayed.
  86. XAdd    -- 'Add' allows you, obviously enough, to add a new record to the
  87. X          relation.
  88. XUpd    -- Similarly, 'Upd' allows you to update the current record.
  89. XDel    -- And, 'Del' deletes the current record.  After the record has been
  90. X          deleted, the record will disappear and you'll have to make another
  91. X          query.
  92. XRel    -- 'Rel' allows you to open a new relation.
  93. X
  94. X                               Standard Keys
  95. X
  96. XOther than movement keys, the following are accepted:
  97. X   Ctrl-A  : Accept data-entry--same as ":w" or ":x" if in vi-emulation mode.
  98. X   Ctrl-C  : Abort data-entry.
  99. X   Ctrl-Q  : Abort data-entry.
  100. X   Ctrl-U  : Undo any changes (to this field only)
  101. X   PgUp    : Works like an up-arrow
  102. X   PgDn    : Works like an down-arrow
  103. X   Del     : Works like a backspace
  104. X
  105. XThe arrow keys work just dandy in *nix, or if you're using the same curses
  106. Xpackage I am... don't know about any others.
  107. X
  108. X                                  Movement
  109. X
  110. XUsers who are not familiar with the editor vi will probably wish NOT to compile
  111. Xvr with -DVI_EMU; if this isn't present, it removes some of the input routine's
  112. Xediting and movement commands, but allows the user to enter text in a more
  113. Xintuitive manner.
  114. X
  115. XArrow keys operate as expected; vi'ers, you may ARROW _past_ the end of a line
  116. Xof text, whereas space and 'l' will not let you (in keeping with vi's
  117. Xconventions).  Others, you are in perpetual insert, with backspace and DEL
  118. Xalways destructive, and left-arrow not (unless in VI-emulation).
  119. X
  120. XVi'ers, there are some extra ways to exit a template entry: normally, you
  121. Xmay only accept a transaction, and then, only by hitting return on the last
  122. Xfield in the set.  Without VI you can abort a transaction by hitting ESC
  123. Xtwice; you may want to hit it 3 times, just to make it catch the second
  124. Xmore quickly; with vi, typing :q (no return) will abort a transaction, and :w
  125. Xor :x will accept it, from any point.
  126. X
  127. END_OF_FILE
  128.   if test 5167 -ne `wc -c <'dox/vr.dox'`; then
  129.     echo shar: \"'dox/vr.dox'\" unpacked with wrong size!
  130.   fi
  131.   # end of 'dox/vr.dox'
  132. fi
  133. if test -f 'sample/sample.c' -a "${1}" != "-c" ; then 
  134.   echo shar: Will not clobber existing file \"'sample/sample.c'\"
  135. else
  136.   echo shar: Extracting \"'sample/sample.c'\" \(15287 characters\)
  137.   sed "s/^X//" >'sample/sample.c' <<'END_OF_FILE'
  138. X/*
  139. X * METALBASE 5.0
  140. X *
  141. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  142. X *                                       [ t-richj@microsoft.com ]
  143. X */
  144. X
  145. X#undef MODULE
  146. X
  147. X/*
  148. X * Lemme explain the above line--it's not necessary 'cause MODULE isn't
  149. X * defined anywhere else, but I put it in so I could put in this comment.
  150. X * The headers created by "build" and "form" include actual data, that should
  151. X * be local to only one module of a multiple .c-program executable; all the
  152. X * others should have the headers' variables declared as external.  So the
  153. X * headers use #ifdefs and check for the definition of MODULE--if it's there,
  154. X * variables are declared external, if not, they're declared local.  That way,
  155. X * variables always go in this one piece of .c code; if you were to link this
  156. X * with any others, add "#define MODULE" to 'em and the headers will tell the
  157. X * program that the variables therein are actually local to another C program.
  158. X * Works rather well.
  159. X *
  160. X */
  161. X
  162. X#include <mbase.h>
  163. X
  164. X#include "sample.h"     /* Created during "% build sample.s"  */
  165. X#include "sampl_fm.h"  /* Created during "% form sample.frm" */
  166. X
  167. X#ifdef LONGARGS
  168. X   void  main      (void);
  169. X   void  add_cust  (void);
  170. X   int   validate  (de_form *);
  171. X   void  do_datent (void);
  172. X   void  do_error  (char *);
  173. X   int   verify    (char *);
  174. X#else
  175. X   void  main();
  176. X   void  add_cust();
  177. X   int   validate();
  178. X   void  do_datent();
  179. X   void  do_error();
  180. X   int   verify();
  181. X#endif
  182. X
  183. X#ifdef MSDOS
  184. X#define Standout()   /* For some reason, the MSDOS curses package I use   */
  185. X#define Standend()   /* craps out with standout and standend.  Try yours. */
  186. X#else
  187. X#define Standout() standout()
  188. X#define Standend() standend()
  189. X#endif
  190. X
  191. Xstatic sample_str arr[] =
  192. X { { "Johnson Bill", 0L, 123.4567, 0L, 0L, "N", (ushort)15, "494-0220" },
  193. X   { "Calvin John",  0L,  23.00,   0L, 0L, "N", (ushort)3,  "216-881-2624"  },
  194. X   { "Moore Bob",    0L, 456.1234, 0L, 0L, "Y", (ushort)45, "882-8080x14651" },
  195. X   { "",             0L,   0.0,    0L, 0L, "",  (ushort)0,  ""  } };
  196. X
  197. Xrelation   *samp;
  198. Xint         iserr;
  199. Xsample_str  rec;
  200. X
  201. Xvoid
  202. Xmain ()
  203. X{
  204. X   int       i;
  205. X   long      l;
  206. X   char      temp[80];
  207. X
  208. X/*
  209. X * First, if we need one, we've gotta get an encryption key for sample.rel:
  210. X *
  211. X */
  212. X
  213. X#ifdef NOENCRYPT
  214. X   temp[0] = 0;
  215. X#else
  216. X   printf ("%s%s%sMetalBase 5.0 Sample________________________________%s",
  217. X            SNGCR, CLS, SNGCR, SNGCR);
  218. X   printf ("%sEncryption password : ", DUBCR);
  219. X   gets   (temp);
  220. X   printf (SNGCR);
  221. X#endif
  222. X
  223. X   if ((samp = mb_inc ("sample", strtokey (temp))) == RNULL)
  224. X    { fprintf (stderr, "Database could not be opened (%s).%s", mb_error,SNGCR);
  225. X      mb_exit (1);
  226. X    }
  227. X
  228. X   for (;;)
  229. X    { if ((l = mb_num(samp)) == 1L)
  230. X         printf ("%s%sThere is currently 1 customer in the database.%s",
  231. X                      CLS, SNGCR, DUBCR);
  232. X      else
  233. X         printf ("%s%sThere are currently %ld customers in the database.%s",
  234. X                 CLS, SNGCR, l, DUBCR);
  235. X      printf ("It is currently %s %s%s",
  236. X                fmt_time(curtime(),0), fmt_date(curdate(),0), SNGCR);
  237. X
  238. X      printf (SNGCR);
  239. X      printf (" [D] - Add demonstration customers%s", SNGCR);
  240. X      printf (" [F] - Use data-entry form%s", SNGCR);
  241. X      printf (" [Q] - Quit%s", SNGCR);
  242. X      printf ("%sOption : ", SNGCR);
  243. X      gets (temp);  if ((i = tolower (temp[0])) == 'q')  break;
  244. X
  245. X      switch (i)
  246. X       { case 'd':  add_cust  ();      gets(temp);  break;
  247. X         case 'f':  do_datent ();                   break;
  248. X         default:                                   break;
  249. X       }
  250. X    }
  251. X
  252. X   printf ("%s%s%s", SNGCR, CLS, SNGCR);
  253. X   if (mb_rmv (samp))
  254. X    { fprintf (stderr, "Database could not be closed (%s).%s", mb_error,SNGCR);
  255. X      mb_exit (1);
  256. X    }
  257. X   mb_exit (0);
  258. X}
  259. X
  260. X/*
  261. X * Here, we add three customers to the relation.  Basically so you can have
  262. X * some test data to play with, without thinking of anyone's names or
  263. X * whatever; also helps demonstrate mb_add().
  264. X *
  265. X */
  266. X
  267. Xvoid
  268. Xadd_cust ()
  269. X{
  270. X   int  i, n;
  271. X
  272. X   printf (SNGCR);
  273. X   for (n=0; ; n++)
  274. X      if (arr[n].custname[0] == 0)  break;
  275. X   for (i=0; i<n; i++)
  276. X    { printf ("Adding customer #%d/%d...", i+1, n);
  277. X      arr[i].date_en = curdate();
  278. X      arr[i].time_en = curtime();
  279. X
  280. X/*
  281. X * Note that the serial number is not set by us--it's assigned automatically
  282. X * by the system.  We just send in 0L, or whatever happens to be there--
  283. X * its value when passed is discarded.
  284. X *
  285. X */
  286. X
  287. X      if (mb_add (samp, &arr[i]) == MB_OKAY)
  288. X         printf ("Successfully added%s", SNGCR);
  289. X      else
  290. X         printf ("%s%s", mb_error, SNGCR);
  291. X
  292. X/*
  293. X * Note that after a successful mb_add() call, the record's serial number
  294. X * has been filled in automatically; if you looked in arr[i].custnum, the
  295. X * number is now set.  Most engines require you to look up the record before
  296. X * you can find out what number it was assigned; likewise, money values have
  297. X * been truncated appropriately.  Nya nya nya, Informix.  :)
  298. X *
  299. X */
  300. X
  301. X    }
  302. X   printf ("%sPress RETURN :", SNGCR);
  303. X}
  304. X
  305. X/*
  306. X * Here's the code for the data-entry stuff.  I'm including my notes
  307. X * for when I first designed this, to press a point--data-entry is SIMPLE
  308. X * if you're positive of what exactly you want BEFORE you start to code.
  309. X * I suggest you do something exactly like what I've got here, and DE will
  310. X * completely cease to be a problem for you.  :)  Likely, anyway...
  311. X *
  312. X * We've got:
  313. X *
  314. X *       +--------------------------------------------+
  315. X *       |                                            |
  316. X *       |  Customer Number...[custnum  ]             |
  317. X *       |  Customer Name.....[custname  ]            |
  318. X *       |                                            |
  319. X *       |  Current Balance...${balance  }            |
  320. X *       |  Accept Credit.....[A]..[B  ]              |
  321. X *       |                                            |
  322. X *       |  Date Entered......[date_en  ][time_en  ]  |
  323. X *       |                                            |
  324. X *       +--------------------------------------------+
  325. X *
  326. X * We want a menu that sez:
  327. X *  Add  Find  Change  Delete
  328. X *
  329. X * Where
  330. X * Add     == Mode 1 (everything inout, save date/time and custnum--
  331. X *                 they're set by the system)
  332. X * Find    == Mode 2 (only number and name inout, everything else out)
  333. X * Change  == Mode 1 (same stuff as for Add, above)
  334. X * Delete  == No mode--just a yes/no question.
  335. X *
  336. X * On second thought, let's not make it a menu.  Let's put 'em in the data-
  337. X * entry form... since there's no data, we'll start with Find == mode 2.  When
  338. X * they've entered something valid, we'll go on to Mode 1/Change; if they enter
  339. X * something invalid, we'll go to Mode 1/Add.  If they're in Mode 1/Change..
  340. X * hell, let's make it a mode 3.. If they're in Mode 3, and they hit
  341. X * EOF==Ctrl-D, we'll delete the record if they want to--and they'll go back
  342. X * to Mode 2 with no data.
  343. X * Let's also let 'em move around.  Ctrl-N and Ctrl-P will select the Next
  344. X * and previous records if they're in custnum or custname fields... if they're
  345. X * not, print an error.  Those two keys will work in.. hummm.  If they're
  346. X * in find mode, -N will do a FIRST, and -P will do a LAST; after any -N/-P,
  347. X * it'll pull up the record & put 'em in change mode, same field.  From change
  348. X * mode, they'll do NEXT and PREVIOUS, respectively... if you've updated the
  349. X * data, it'll ask you if you wanna save it.
  350. X *
  351. X * So:
  352. X *      Set Mode 2
  353. X *      Set Field Custnum
  354. X *      Go
  355. X *       : If (selected Previous or Next)
  356. X *       :  : if (! in custnum or custname)
  357. X *       :  :  : error--can't search on any other fields (nya nya)
  358. X *       :  : if (in mode 1 ("Add"))
  359. X *       :  :  : error--can't search during add
  360. X *       :  : if (in mode 2 ("Find"))
  361. X *       :  :  : make 'em do FIRST and LAST
  362. X *       :  :  : pull up record go to mode 3 ("Change")
  363. X *       :  : if (in mode 3 ("Change"))
  364. X *       :  :  : if they've updated the record, don't ask to save it  :)
  365. X *       :  :  : pull up record
  366. X *       :  : don't change fields
  367. X *       :  : return 0 (okay)
  368. X *       : If (mode 2 ("Find"))
  369. X *       :  : If (Abort DE)
  370. X *       :  :  : return -1 --abort
  371. X *       :  : If (valid custnum or valid custname)
  372. X *       :  :  : load information
  373. X *       :  :  : change to mode 3 ("Change")
  374. X *       :  : If (invalid custnum or invalid custname)
  375. X *       :  :  : error--cannot find record (stay in field)
  376. X *       :  : If (custname == "new")
  377. X *       :  :  : clear the form and go to mode 1
  378. X *       : If (mode 1 ("Add"))
  379. X *       :  : If (EOF)
  380. X *       :  :  : clear data--change to mode 2
  381. X *       :  : If (Accept DE)
  382. X *       :  :  : add new record
  383. X *       :  :  : change to mode 3 ("Change")
  384. X *       :  : If (Abort DE)
  385. X *       :  :  : clear data--change to mode 2
  386. X *       : If (mode 3 ("Change"))
  387. X *       :  : If (EOF)
  388. X *       :  :  : ask to delete--if so, clear data and change to mode 2 ("Find")
  389. X *       :  : If (Accept DE)
  390. X *       :  :  : add new record
  391. X *       :  : If (Abort DE)
  392. X *       :  :  : clear data--change to mode 2
  393. X *      Done
  394. X *
  395. X */
  396. X
  397. Xvoid
  398. Xdo_datent ()
  399. X{
  400. X   de_form *form = &sample_fm; /* Shorthand, basically. */
  401. X
  402. X   sprintf (quit_chars, "%c%c%c", CTRL_D, CTRL_P, CTRL_N);
  403. X
  404. X   form->curmode  = 2;
  405. X   form->curfield = fm_fldnum (form, "custnum");
  406. X   form->valid_fn = validate;
  407. X
  408. X/*
  409. X * Oh yeah.  If we left looking at a record, let's pull it up and start in
  410. X * Change mode:
  411. X *
  412. X */
  413. X
  414. X/* (naw)
  415. X *
  416. X * if (mb_sel (samp, 0, &rec, CURRENT, NULL) == MB_OKAY)
  417. X *  { form->curmode = 3;
  418. X *    reltoform (samp, form, &rec);
  419. X *  }
  420. X *
  421. X */
  422. X
  423. X   do_form (form);
  424. X}
  425. X
  426. Xint
  427. Xvalidate (form)
  428. Xde_form  *form;
  429. X{
  430. X   int   idx, n;
  431. X
  432. X   if (iserr)  do_error("");  /* Get rid of any old message */
  433. X
  434. X   if (form->key == CTRL_P || form->key == CTRL_N)
  435. X    { idx = -1;
  436. X      if (form->curfield == fm_fldnum (form, "custnum"))
  437. X         idx = idxnum (samp, "ix_number");
  438. X      if (form->curfield == fm_fldnum (form, "custname"))
  439. X         idx = idxnum (samp, "ix_name");
  440. X      if (idx == -1)
  441. X       { do_error ("Ctrl-N and Ctrl-P only work on CustNum / CustName");
  442. X         form->nextfield = form->curfield;
  443. X         return 0;
  444. X       }
  445. X      if (form->curmode == 1)
  446. X       { do_error ("you may not search during an add operation");
  447. X         form->nextfield = form->curfield;
  448. X         return 0;
  449. X       }
  450. X      do_error ("wait...");
  451. X      if (form->curmode == 3)
  452. X       { if (mb_sel (samp, idx, &rec, (form->key==CTRL_P) ?PREV:NEXT, NULL))
  453. X          { do_error ("no more records in that direction");
  454. X            form->nextfield = form->curfield;
  455. X            return 0;
  456. X          }
  457. X       }
  458. X      if (form->curmode == 2)
  459. X       { if (mb_sel (samp, idx, &rec, (form->key==CTRL_P) ?LAST:FIRST, NULL))
  460. X          { do_error ("no more records in that direction");
  461. X            form->nextfield = form->curfield;
  462. X            return 0;
  463. X          }
  464. X         fm_mode (form, 3);
  465. X       }
  466. X      form->nextfield = form->curfield;
  467. X      reltoform  (samp, form, &rec);
  468. X      fm_refrall (form);
  469. X      do_error ("record found successfully");
  470. X      return 0;
  471. X    }
  472. X
  473. X   switch (form->curmode)
  474. X    {
  475. X      case 2:  formtorel (form, samp, &rec);
  476. X               if (form->key == -1)
  477. X                  return -1;
  478. X
  479. X               if (rec.custname[0] != 0)
  480. X                { idx = idxnum (samp, "ix_name");
  481. X
  482. X                  if (! strcmp (rec.custname, "new"))
  483. X                   { fm_mode (form, 1);
  484. X                     form->nextfield = form->curfield;  /* Don't move */
  485. X                     fm_zero (form);
  486. X                     if ((n = fm_fldnum (form, "custname")) >= 0)
  487. X                        fm_refrnum (form, n);
  488. X                     do_error ("enter new record");
  489. X                     break;
  490. X                   }
  491. X                }
  492. X               else
  493. X                  if (rec.custnum != 0L)
  494. X                     idx = idxnum (samp, "ix_number");
  495. X                  else
  496. X                     break;
  497. X
  498. X               do_error ("wait...");
  499. X               if (mb_sel (samp, idx, &rec, GTEQ, NULL) == MB_OKAY)
  500. X                { reltoform  (samp, form, &rec);
  501. X                  fm_refrall (form);
  502. X                  fm_mode (form, 3);
  503. X                  do_error ("record found successfully");
  504. X                  break;
  505. X                }
  506. X               do_error ("the specified record cannot be found.");
  507. X               form->nextfield = form->curfield;
  508. X              break;
  509. X
  510. X      case 1:  if (form->key == 4)
  511. X                { fm_zero    (form);
  512. X                  fm_refrall (form);
  513. X                  fm_mode (form, 2);
  514. X                  do_error ("add aborted");
  515. X                  break;
  516. X                }
  517. X               if (form->key == 1)
  518. X                { formtorel (form, samp, &rec);
  519. X                  do_error ("wait...");
  520. X                  rec.date_en = curdate();
  521. X                  rec.time_en = curtime();
  522. X                  if (mb_add (samp, &rec) != MB_OKAY)
  523. X                     do_error (mb_error);
  524. X                  else
  525. X                   { do_error   ("record added successfully");
  526. X                     fm_mode    (form, 3);
  527. X                     reltoform  (samp, form, &rec);
  528. X                     fm_refrall (form);
  529. X                   }
  530. X                  break;
  531. X                }
  532. X               if (form->key == -1)
  533. X                { do_error   ("add aborted");
  534. X                  fm_mode    (form, 2);
  535. X                  fm_zero    (form);
  536. X                  fm_refrall (form);
  537. X                  formtorel  (form, samp, &rec);
  538. X                  break;
  539. X                }
  540. X              break;
  541. X
  542. X      case 3:  if (form->key == 4)
  543. X                { if (! verify ("delete this record ? [yN] "))
  544. X                   { do_error ("delete aborted");
  545. X                     break;
  546. X                   }
  547. X                  do_error ("wait...");
  548. X                  if (mb_del (samp) != MB_OKAY)
  549. X                   { do_error (mb_error);
  550. X                     break;
  551. X                   }
  552. X                  fm_zero    (form);
  553. X                  formtorel  (form, samp, &rec);
  554. X                  fm_refrall (form);
  555. X                  do_error ("record deleted");
  556. X                  break;
  557. X                }
  558. X               if (form->key == 1)
  559. X                { formtorel (form, samp, &rec);
  560. X                  do_error ("wait...");
  561. X                  if (mb_upd (samp, &rec) != MB_OKAY)
  562. X                     do_error (mb_error);
  563. X                  else
  564. X                     do_error ("record updated successfully");
  565. X                  break;
  566. X                }
  567. X               if (form->key == -1)
  568. X                { do_error   ("change aborted");
  569. X                  fm_mode    (form, 2);
  570. X                  fm_zero    (form);
  571. X                  fm_refrall (form);
  572. X                  formtorel  (form, samp, &rec);
  573. X                  break;
  574. X                }
  575. X             break;
  576. X    }
  577. X
  578. X   return 0;
  579. X}
  580. X
  581. X/*
  582. X * Stuff copied from vr.c to make life a little easier and a little prettier:
  583. X *
  584. X */
  585. X
  586. Xvoid
  587. Xdo_error (line)
  588. Xchar     *line;
  589. X{
  590. X   move (23, 0);   clrtoeol();  iserr = 0;
  591. X   if (! *line)  { refresh(); return; }
  592. X   Standout();     addstr (line);
  593. X   Standend();     refresh();   iserr = 1;
  594. X}
  595. X
  596. Xint
  597. Xverify (str)
  598. Xchar   *str;
  599. X{
  600. X   char  c;
  601. X   do_error (str);
  602. X   for (;;)
  603. X    { c = getarr();
  604. X      switch (tolower(c))
  605. X       { case 'q': case 'n':  case ' ':   do_error (""); return 0; break;
  606. X         case  27: case '\r': case '\n':  do_error (""); return 0; break;
  607. X         case 'y':                        do_error (""); return 1; break;
  608. X       }
  609. X    }
  610. X}
  611. X
  612. END_OF_FILE
  613.   if test 15287 -ne `wc -c <'sample/sample.c'`; then
  614.     echo shar: \"'sample/sample.c'\" unpacked with wrong size!
  615.   fi
  616.   # end of 'sample/sample.c'
  617. fi
  618. if test -f 'sample/sample.rpt' -a "${1}" != "-c" ; then 
  619.   echo shar: Will not clobber existing file \"'sample/sample.rpt'\"
  620. else
  621.   echo shar: Extracting \"'sample/sample.rpt'\" \(1120 characters\)
  622.   sed "s/^X//" >'sample/sample.rpt' <<'END_OF_FILE'
  623. X#
  624. X# METALBASE 5.0
  625. X#
  626. X# Released October 1st, 1992 by Huan-Ti [ virtual!root@owlnet.rice.edu ]
  627. X#                                       [ t-richj@microsoft.com ]
  628. X#
  629. X
  630. XData sample;
  631. X
  632. XSize
  633. X   Rows       23;  # Make the report screen-size (default is page-size)
  634. X   Top Margin  0;  #
  635. X   Bottom      0;  # And get rid of most margins.  This _is_ going to a screen,
  636. X   Left        4;  # most likely.  :)
  637. X   Right       8;
  638. X
  639. XFooter Keep
  640. X   print centered  : "-continued-";
  641. XLast
  642. X   print centered  : "-end of report-";
  643. X
  644. XHeader
  645. X   print centered  : system;
  646. X   print continued : system!date, system!time format 1;
  647. X   print right     : "Page", system!page;
  648. X   skip 1 line;
  649. X   print continued : "Customer Name" to 23, "Number" to 30, "Balance";
  650. X   print           : column 40, "Date Entered", column 60, "Credit";
  651. X   print continued : "-------------" to 23, "------" to 30, "-------";
  652. X   print           : column 40, "------------", column 60, "------";
  653. X
  654. XOn ix_name
  655. X   print continued : custname to 25, custnum to 30, balance using "$%7.2f";
  656. X   print continued : column 40, date_en, time_en format 1, column 63, credit;
  657. X   print : phone;
  658. X
  659. END_OF_FILE
  660.   if test 1120 -ne `wc -c <'sample/sample.rpt'`; then
  661.     echo shar: \"'sample/sample.rpt'\" unpacked with wrong size!
  662.   fi
  663.   # end of 'sample/sample.rpt'
  664. fi
  665. if test -f 'src/input.c' -a "${1}" != "-c" ; then 
  666.   echo shar: Will not clobber existing file \"'src/input.c'\"
  667. else
  668.   echo shar: Extracting \"'src/input.c'\" \(13695 characters\)
  669.   sed "s/^X//" >'src/input.c' <<'END_OF_FILE'
  670. X/*
  671. X * METALBASE 5.0
  672. X *
  673. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  674. X *                                       [ t-richj@microsoft.com ]
  675. X */
  676. X
  677. X   /**********************************************************************/
  678. X   /* Compile with -DTROUBLE if you have usleep() and your arrows act up */
  679. X   /**//**************************************************************//**/
  680. X       /* Compile with -DVI_EMU if you really want some vi emulation */
  681. X       /**************************************************************/
  682. X
  683. X#define INPUT_C
  684. X#include "mbase.h"
  685. X
  686. X#ifndef MSDOS
  687. X#ifdef LONGARGS
  688. X   extern long   atol(char *);
  689. X   extern double atof(char *);
  690. X#else
  691. X   extern long   atol();
  692. X   extern double atof();
  693. X#endif
  694. X#endif
  695. X
  696. X#ifdef LONGARGS
  697. X   void display (dataptr, int, int);
  698. X   char getarr  (void);
  699. X   char input   (dataptr, int, int);
  700. X#else
  701. X   void display();
  702. X   char getarr();
  703. X   char input();
  704. X#endif
  705. X
  706. X/*
  707. X * An option at compile time:  if you want the field to be accepted (as with
  708. X * a down arrow) automatically when the user has filled it completely, define
  709. X * ADVANCE_AT_END as below.  This makes DE a bit more natural for Choice
  710. X * fields and the like.
  711. X *
  712. X */
  713. X
  714. X#define ADVANCE_AT_END
  715. X
  716. X#define DELAY_TIME 10
  717. X
  718. X#define movech(c,y,x)  move(y,x);refresh();c=getarr();
  719. X
  720. X#ifndef ESC
  721. X#define ESC (char)27
  722. X#endif
  723. X
  724. Xstatic int  ins = 1;
  725. X
  726. Xchar  str[150], org[150];
  727. Xint   pos,y,x,len,tgt,inslt,cln,esc;
  728. X
  729. X/*
  730. X * getarr() functions like getch(), but returns special codes for arrow
  731. X * keys as well.
  732. X *
  733. X */
  734. X
  735. X#ifdef USE_CURKEY
  736. X
  737. Xchar
  738. Xgetarr ()
  739. X{
  740. X   int   ch;
  741. X
  742. X   do  ch = (int)getch();
  743. X   while (ch == 0);
  744. X
  745. X   if (ch == KEY_UP)     return (char)AR_UP;
  746. X   if (ch == KEY_DOWN)   return (char)AR_DOWN;
  747. X   if (ch == KEY_LEFT)   return (char)AR_LEFT;
  748. X   if (ch == KEY_RIGHT)  return (char)AR_RIGHT;
  749. X   if (ch == KEY_IC)     return (char)AR_INS;
  750. X   if (ch == KEY_DC)     return (char)AR_DEL;
  751. X   if (ch == KEY_HOME)   return (char)AR_HOME;
  752. X   if (ch == KEY_LL)     return (char)AR_END;
  753. X   if (ch == KEY_PPAGE)  return (char)AR_PGUP;
  754. X   if (ch == KEY_NPAGE)  return (char)AR_PGDN;
  755. X
  756. X   return (char)ch;
  757. X}
  758. X
  759. X#else
  760. X
  761. Xchar
  762. Xgetarr ()
  763. X{
  764. X   register int   x;
  765. X   char          *a,*b,*c,*d,*e,*f,*g,*h,*i,*j,ch;
  766. X   static char   *up="\033[A";
  767. X   static char   *down="\033[B";
  768. X   static char   *left="\033[D";
  769. X   static char   *right="\033[C";
  770. X   static char   *ins="\033[@";
  771. X   static char   *del="\033[P";
  772. X   static char   *home="\033[H";
  773. X   static char   *end="\033[24H";
  774. X   static char   *pgup="\033[V";
  775. X   static char   *pgdn="\033[U";
  776. X
  777. X   do
  778. X    { ch = (char)getch();  if (ch < 0)  ch = 0;
  779. X
  780. X      if (ch != *(a= up))     a=NULL;  else a++;
  781. X      if (ch != *(b= down))   b=NULL;  else b++;
  782. X      if (ch != *(c= left))   c=NULL;  else c++;
  783. X      if (ch != *(d= right))  d=NULL;  else d++;
  784. X      if (ch != *(e= ins))    e=NULL;  else e++;
  785. X      if (ch != *(f= del))    f=NULL;  else f++;
  786. X      if (ch != *(g= home))   g=NULL;  else g++;
  787. X      if (ch != *(h= end))    h=NULL;  else h++;
  788. X      if (ch != *(i= pgup))   i=NULL;  else i++;
  789. X      if (ch != *(j= pgdn))   j=NULL;  else j++;
  790. X
  791. X      if (!a && !b && !c && !d && !e && !f && !g && !h && !i && !j)  break;
  792. X
  793. X#ifndef MSDOS
  794. X#ifndef AMIGA
  795. X      fcntl (0, F_SETFL, O_NDELAY);  /* Turn off waiting for keys */
  796. X#endif
  797. X#endif
  798. X
  799. X      for (;;)
  800. X       { if (a && !*a) { ch = AR_UP;     break; }
  801. X         if (b && !*b) { ch = AR_DOWN;   break; }
  802. X         if (c && !*c) { ch = AR_LEFT;   break; }
  803. X         if (d && !*d) { ch = AR_RIGHT;  break; }
  804. X         if (e && !*e) { ch = AR_INS;    break; }
  805. X         if (f && !*f) { ch = AR_DEL;    break; }
  806. X         if (g && !*g) { ch = AR_HOME;   break; }
  807. X         if (h && !*h) { ch = AR_END;    break; }
  808. X         if (i && !*i) { ch = AR_PGUP;   break; }
  809. X         if (j && !*j) { ch = AR_PGDN;   break; }
  810. X
  811. X         if (!a && !b && !c && !d && !e && !f && !g && !h && !i && !j)
  812. X          { ch=*(up);
  813. X            break;
  814. X          }
  815. X         for (x=0; x < DELAY_TIME; x++)       /* DELAY_TIME quick reads */
  816. X          {
  817. X            if ((ch = (char)getch()) > 0)  break;
  818. X#ifdef TROUBLE
  819. X            usleep (100);
  820. X#endif
  821. X          }
  822. X         if (x == DELAY_TIME)
  823. X          { ch=*(up);
  824. X            break;
  825. X          }
  826. X         a=(a==NULL || ch != *a) ? NULL : a+1;
  827. X         b=(b==NULL || ch != *b) ? NULL : b+1;
  828. X         c=(c==NULL || ch != *c) ? NULL : c+1;
  829. X         d=(d==NULL || ch != *d) ? NULL : d+1;
  830. X         e=(e==NULL || ch != *e) ? NULL : e+1;
  831. X         f=(f==NULL || ch != *f) ? NULL : f+1;
  832. X         g=(g==NULL || ch != *g) ? NULL : g+1;
  833. X         h=(h==NULL || ch != *h) ? NULL : h+1;
  834. X         i=(i==NULL || ch != *i) ? NULL : i+1;
  835. X         j=(j==NULL || ch != *j) ? NULL : j+1;
  836. X       }
  837. X
  838. X#ifndef MSDOS
  839. X#ifndef AMIGA
  840. X      fcntl (0, F_SETFL, 0);
  841. X#endif
  842. X#endif
  843. X    } while (! ch);
  844. X
  845. X   return ch;
  846. X}
  847. X
  848. X#endif
  849. X
  850. Xvoid
  851. Xdisplay (buf, typ, siz)
  852. Xdataptr  buf;
  853. Xftype         typ;
  854. Xint                siz;
  855. X{
  856. X   int   b, a;
  857. X   long  ac, num, pre, ext;
  858. X   long  tlong;
  859. X   char  temp[22];
  860. X
  861. X   getyx    (win,b,a);
  862. X   sprintf  (str, "%-132.132s", "");  str[siz] = 0;
  863. X   mvaddstr (b,a, str);
  864. X
  865. X   switch (typ)
  866. X      {
  867. X      case T_CHAR:    strzcpy (str, buf,   siz);                      break;
  868. X      case T_SHORT:   sprintf (str, "%d",  (int)*(short  *)buf);      break;
  869. X      case T_USHORT:  sprintf (str, "%u",  (int)*(ushort *)buf);      break;
  870. X      case T_LONG:    sprintf (str, "%ld", *(long   *)buf);           break;
  871. X      case T_ULONG:   sprintf (str, "%lu", *(ulong  *)buf);           break;
  872. X      case T_FLOAT:   sprintf (str, "%f",  *(float  *)buf);           break;
  873. X      case T_DOUBLE:  sprintf (str, "%lf", *(double *)buf);           break;
  874. X      case T_MONEY:   tlong = (long)(*(double *)buf * 100.0);
  875. X                      sprintf (str, "%-.2lf", (double)tlong / 100.0); break;
  876. X      case T_TIME:    strcpy (str, fmt_time (*(mb_time *)buf, 0));    break;
  877. X      case T_DATE:    strcpy (str, fmt_date (*(mb_date *)buf, 0));    break;
  878. X      case T_SERIAL:  sprintf (str, "%ld", *(long   *)buf);           break;
  879. X      case T_PHONE:   strzcpy (temp, buf, 20);
  880. X                      scn_phone (&ac, &pre, &num, &ext, temp);
  881. X                      strcpy (str, fmt_phone (ac,pre,num,ext, 0));    break;
  882. X      }
  883. X   str[siz] = 0;
  884. X   mvaddstr (b,a, str);
  885. X   move     (b,a);
  886. X   refresh  ();
  887. X}
  888. X
  889. X/*
  890. X * Returns:     0 -- Continue to next field
  891. X *              1 -- Finished with DE
  892. X *             -1 -- Abort DE
  893. X *          other -- Field control (-/+/j/k)
  894. X *
  895. X */
  896. X
  897. Xchar
  898. Xinput   (buf, typ, siz)
  899. Xdataptr  buf;
  900. Xftype         typ;
  901. Xint                siz;
  902. X{
  903. X   register int  i;
  904. X   char          c;
  905. X   int           y1,x1, start;
  906. X   long          tlong;
  907. X   long          ac, num, pre, ext;
  908. X   char          temp[22];
  909. X
  910. X   inslt=pos=tgt=cln=esc=start=0;  raw();noecho();getyx(win,y,x);
  911. X   display (buf, typ, siz);        len=strlen(str);  strcpy (org,str);
  912. X
  913. X   for (;;)
  914. X    { movech (c,y,x+pos);
  915. X      if (strchr (quit_chars, c))  break;
  916. X#ifdef VI_EMU
  917. X      if (c == ESC)
  918. X       { if (tgt)           tgt=0;
  919. X         else if (ins)      ins=0,pos--;
  920. X         else esc++;
  921. X         if (esc == 2)  { c = 'q'; break; }  /* Two ESC's aborts too */
  922. X         if (pos==-1)  pos=0;
  923. X         continue;
  924. X       }
  925. X#else
  926. X      if (c != ESC)  esc = 0;
  927. X      else
  928. X       { esc++;
  929. X         if (esc == 2)   { c = 'q';  break; }
  930. X       }
  931. X#endif
  932. X      if (c == CTRL_C)   { c = 'q';  break; }  /* Ctrl-C aborts */
  933. X      if (c == CTRL_Q)   { c = 'q';  break; }  /* Ctrl-Q aborts */
  934. X      if (c == AR_PGUP)  { c = 'k';  break; }
  935. X      if (c == AR_UP)    { c = 'k';  break; }
  936. X      if (c == AR_PGDN)  { c = 'j';  break; }
  937. X      if (c == AR_DOWN)  { c = 'j';  break; }
  938. X      if (c == CTRL_L)   { clearok (win, TRUE);  refresh();  continue; }
  939. X      if (c == AR_END)   { pos = len;  continue; }
  940. X      if (c == CTRL_U)   { strcpy  (str, org);
  941. X                           move (y, x); display (buf, typ, siz);
  942. X                           len=strlen(str); start = 0;
  943. X                           c = AR_HOME;  /* Pretend they hit HOME afterward. */
  944. X                         }
  945. X      if (c == AR_HOME)  { pos = 0;    continue; }
  946. X
  947. X      if (c == AR_RIGHT)
  948. X       { if (pos < len)  pos++;
  949. X         continue;
  950. X       }
  951. X#ifndef VI_EMU
  952. X      if (c == AR_LEFT)
  953. X       { if (pos > 0)  pos--;
  954. X         continue;
  955. X       }
  956. X#endif
  957. X      esc = 0;
  958. X      if (ins)
  959. X       { if (c == '\b' || c == 127 || c == AR_LEFT || c == AR_DEL)
  960. X            if (pos != inslt)
  961. X             { pos--,len--,mvdelch(y,x+pos),mvinsch(y,x+siz-1,' ');
  962. X               for (i=pos; i<len; i++)
  963. X                  str[i] = str[i+1];
  964. X               str[i] = 0;
  965. X             }
  966. X         if (c == '\r' || c == '\n' || c == CTRL_A)  break;
  967. X         if (c < ' ' || c > 'z')  continue;
  968. X#ifndef VI_EMU
  969. X         if (pos == 0 && ! start)
  970. X          {
  971. X            for (i=0; i<len; i++)
  972. X               mvdelch(y,x),mvinsch(y,x+siz-1,' ');
  973. X            str[0] = 0;  len = 0;  move(y,x);  refresh();
  974. X          }
  975. X         start = 1;
  976. X#endif
  977. X         if (len == siz)  continue;
  978. X         insch(c);  mvdelch(y,x+siz);
  979. X         for (i=len-1; i>=pos; i--)
  980. X            str[i+1] = str[i];
  981. X         len++;  str[len] = 0;
  982. X         str[pos] = c;  pos++;
  983. X#ifdef ADVANCE_AT_END
  984. X         if (len == siz) { c = 'j'; break; }
  985. X#endif
  986. X         continue;
  987. X       }
  988. X      if (tgt)
  989. X       { if (c < ' ' || c > 'z' || len <= 1) { tgt=0; continue; }
  990. X         if (tgt < 3)
  991. X            for (i=pos-1; i>=0; i--)
  992. X               if (str[i] == c)  break;
  993. X         if (tgt > 2)
  994. X            for (i=pos+1; i<len; i++)
  995. X               if (str[i] == c)  break;
  996. X         if (i < 0 || i == len) { tgt=0; continue; }
  997. X         pos=i;
  998. X         if (tgt == 2) pos++;
  999. X         if (tgt == 3) pos--;
  1000. X         tgt=0; continue;
  1001. X       }
  1002. X      if (cln==2) { move(23,0); clrtoeol(); cln=0; continue; }
  1003. X      if (cln==1)
  1004. X       { if (c > ' ' && c < 'z')
  1005. X          { mvaddch (23, 1, c);
  1006. X            c = (char)tolower (c);
  1007. X            if (c == 'w' || c == 'x') { c = 'x'; break; }
  1008. X            if (c == 'q')                        break;
  1009. X          }
  1010. X         cln=2; y=y1; x=x1;
  1011. X         continue;
  1012. X       }
  1013. X
  1014. X      if (c=='\r' || c=='j' || c=='k' || c=='z' || c=='q' || c == CTRL_A ||
  1015. X          c=='\n' || c=='+' || c=='-' || c=='Z' || c=='Q')  break;
  1016. X
  1017. X      switch (c)
  1018. X       { case 'F':  tgt = 1;  break;
  1019. X         case 'T':  tgt = 2;  break;
  1020. X         case 't':  tgt = 3;  break;
  1021. X         case 'f':  tgt = 4;  break;
  1022. X         case 'A':  pos=len;  ins=1;  break;
  1023. X         case 'a':  if (pos != len)
  1024. X                       pos++; ins=1;  break;
  1025. X         case 'i':            ins=1;  break;
  1026. X         case 'I':  pos=0;    ins=1;  break;
  1027. X         case 'x':  if (len != 0)
  1028. X                       len--,mvdelch(y,x+pos),mvinsch(y,x+siz-1,' ');
  1029. X                    for (i=pos; i<len; i++)
  1030. X                       str[i] = str[i+1];
  1031. X                    str[i] = 0;
  1032. X                    if (pos == len && pos != 0)  pos--;
  1033. X                   break;
  1034. X         case 'X':  if (pos != 0)
  1035. X                     { pos--,len--,mvdelch(y,x+pos),mvinsch(y,x+siz-1,' ');
  1036. X                       for (i=pos; i<len; i++)
  1037. X                          str[i] = str[i+1];
  1038. X                       str[i] = 0;
  1039. X                     }
  1040. X                   break;
  1041. X         case ':':  cln=1; y1=y; x1=x; y=23; x=1;
  1042. X                    move(23,0); clrtoeol(); mvaddch(23,0,':');  break;
  1043. X         case '^':  pos=0;     break;
  1044. X         case '_':  pos=0;     break;
  1045. X         case '0':  pos=0;     break;
  1046. X         case '$':  pos=len-1; if (pos==-1)  pos = 0;  break;
  1047. X         case AR_RIGHT:
  1048. X         case 'l':  if (pos < len-1)  pos++;  break;
  1049. X         case ' ':  if (pos < len-1)  pos++;  break;
  1050. X         case AR_LEFT:
  1051. X         case 'h':  if (pos > 0)      pos--;  break;
  1052. X         case 127:  if (pos > 0)      pos--;  break;
  1053. X         case '\b': if (pos > 0)      pos--;  break;
  1054. X         case 'D':  for (i=pos; i<len; i++)
  1055. X                       mvdelch(y,x+pos),mvinsch(y,x+siz-1,' ');
  1056. X                    len = pos;  pos--;  if (pos == -1)  pos = 0;
  1057. X                    str[len] = 0;
  1058. X                   break;
  1059. X         case 'U':
  1060. X         case 'u':  strcpy  (str, org);       move (y, x);
  1061. X                    display (buf, typ, siz);  len=strlen(str);
  1062. X                   break;
  1063. X       }
  1064. X      if (ins)  inslt=pos;
  1065. X    }
  1066. X   if (cln) { move(23,0);  clrtoeol();  }
  1067. X
  1068. X   switch (typ)
  1069. X      {
  1070. X      case T_CHAR:    strncpy (buf, str, siz);                 break;
  1071. X      case T_SHORT:   *(short  *)buf  = (short) atoi(str);     break;
  1072. X      case T_USHORT:  *(ushort *)buf  = (ushort)atoi(str);     break;
  1073. X      case T_LONG:    *(long   *)buf  = (long)  atol(str);     break;
  1074. X      case T_ULONG:   *(ulong  *)buf  = (ulong) atol(str);     break;
  1075. X      case T_FLOAT:   *(float  *)buf  = (float) atof(str);     break;
  1076. X      case T_DOUBLE:  *(double *)buf  = (double)atof(str);     break;
  1077. X      case T_MONEY:   tlong = (long)(atof(str) * 100.0);
  1078. X                      *(double  *)buf  = (double)tlong / 100.0; break;
  1079. X      case T_SERIAL:  *(long   *)buf  = (long)  atoi(str);     break;
  1080. X      case T_TIME:    *(mb_time *)buf = scn_time (str);        break;
  1081. X      case T_DATE:    *(mb_date *)buf = scn_date (str);        break;
  1082. X      case T_PHONE:   strzcpy (temp, str, 20);
  1083. X                      scn_phone (&ac, &pre, &num, &ext, temp);
  1084. X                      strcpy (buf, fmt_phone (ac,pre,num,ext, 0));  break;
  1085. X      }
  1086. X
  1087. X   move    (y, x);
  1088. X   display (buf, typ, siz);
  1089. X
  1090. X   return (char) ( (c=='\r') ? (char)0
  1091. X                 : (c=='x'||c=='Z'||c=='\n'||c==CTRL_A) ? (char)1
  1092. X                 : (c=='q'||c=='Q') ? (char)-1
  1093. X                 : tolower(c) );
  1094. X}
  1095. X
  1096. Xvoid
  1097. Xinit_curses ()
  1098. X{
  1099. X#ifdef MSDOS
  1100. X   initscr();
  1101. X   win = stdscr;
  1102. X#else
  1103. X#ifdef AMIGA
  1104. X   initscr();
  1105. X   win = stdscr;
  1106. X#else
  1107. X   win = initscr();
  1108. X#endif
  1109. X#endif
  1110. X#ifdef USE_CURKEY
  1111. X   keypad(win, TRUE);
  1112. X#endif
  1113. X}
  1114. X
  1115. END_OF_FILE
  1116.   if test 13695 -ne `wc -c <'src/input.c'`; then
  1117.     echo shar: \"'src/input.c'\" unpacked with wrong size!
  1118.   fi
  1119.   # end of 'src/input.c'
  1120. fi
  1121. if test -f 'src/vr.c' -a "${1}" != "-c" ; then 
  1122.   echo shar: Will not clobber existing file \"'src/vr.c'\"
  1123. else
  1124.   echo shar: Extracting \"'src/vr.c'\" \(15920 characters\)
  1125.   sed "s/^X//" >'src/vr.c' <<'END_OF_FILE'
  1126. X/*
  1127. X * METALBASE 5.0
  1128. X *
  1129. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  1130. X *                                       [ t-richj@microsoft.com ]
  1131. X */
  1132. X
  1133. X#include "mbase.h"
  1134. X
  1135. X#define movech(c,y,x)  move(y,x);refresh();c=getarr();
  1136. X#define doing(x,o)    (arr == x && opt == o && go == 1)
  1137. X
  1138. X#ifdef LONGARGS
  1139. X   void   main       (int, char **);
  1140. X   void   paint_scrn (int, int);
  1141. X   int    get_rel    (char *);
  1142. X   void   get_index    (void);
  1143. X   void   get_rel_name (void);
  1144. X   void   add_rec      (int);
  1145. X   void   del_rec      (void);
  1146. X   void   do_error   (char *);
  1147. X   void   sel_rec    (int);
  1148. X   void   fill_page  (void);
  1149. X   int    verify     (char *);
  1150. X   void   zero_rec   (void);
  1151. X   void   do_line    (int, int);
  1152. X#else
  1153. X   void   main();
  1154. X   void   paint_scrn();
  1155. X   int    get_rel();
  1156. X   void   get_index();
  1157. X   void   get_rel_name();
  1158. X   void   do_error();
  1159. X   void   add_rec();
  1160. X   void   del_rec();
  1161. X   void   sel_rec();
  1162. X   void   fill_page();
  1163. X   int    verify();
  1164. X   void   zero_rec();
  1165. X   void  do_line();
  1166. X#endif
  1167. X
  1168. Xstatic int num_[]     = { 13 };
  1169. Xstatic int opt_[][20] = {{ 0, 6, 11, 16, 21, 26, 30, 34, 41, 45, 49, 53, 57 }};
  1170. Xstatic char *line_[]  =
  1171. X { "First Last Next Prev Gteq Equ Idx Screen Add Upd Del Rel Quit" };
  1172. X
  1173. X#ifdef MSDOS
  1174. X#define Standout()
  1175. X#define Standend()
  1176. X#else
  1177. X#define Standout() standout()
  1178. X#define Standend() standend()
  1179. X#endif
  1180. X
  1181. Xrelation *rel = (relation *)0;
  1182. Xchar      name[20];
  1183. Xint       pg, pgmax, iserr=0, inw=0, pglst, idx;
  1184. Xdataptr   buf;
  1185. X
  1186. Xvoid
  1187. Xmain  (argc, argv)
  1188. Xint    argc;
  1189. Xchar **argv;
  1190. X{
  1191. X   int  c, opt = 0, arr = 0, go, esc=0;
  1192. X
  1193. X   if (argc > 2)
  1194. X    { fprintf (stderr, "vr: format: vr [relation]%s", SNGCR);
  1195. X      exit    (1);
  1196. X    }
  1197. X
  1198. X   if (argc == 2)
  1199. X      if (! get_rel (argv[1]))
  1200. X       { fprintf (stderr,"vr: invalid argument (%s)%s",mb_error,SNGCR);
  1201. X         exit    (1);
  1202. X       }
  1203. X
  1204. X   init_curses();
  1205. X
  1206. X   inw = 1; savetty();
  1207. X   raw(); noecho(); nl();
  1208. X   paint_scrn (0, 1);
  1209. X
  1210. X   if (rel)  fill_page();
  1211. X
  1212. X   for (;;)
  1213. X    { movech (c, 0,opt_[arr][opt]);  go = 0;  if (iserr)  do_error("");
  1214. X#ifdef VI_EMU
  1215. X      if (c != 27)  esc = 0;
  1216. X      else
  1217. X         if (esc == 1)  break;
  1218. X         else           esc = 1;
  1219. X#endif
  1220. X
  1221. X      switch (c)
  1222. X       { case    ' ':           case AR_RIGHT: opt++;   break;
  1223. X         case   '\b': case 127: case AR_LEFT:  opt--;   break;
  1224. X         case    '?': case '/':  paint_scrn(-1,0);      break;
  1225. X         case CTRL_L: clearok(win,TRUE); refresh();     break;
  1226. X       }
  1227. X      if (arr == 0)
  1228. X         switch (c=tolower(c))
  1229. X          { case '\n': case '\r': go = 1;  break;
  1230. X            case  'f':  opt = 0;  go = 1;  break;
  1231. X            case  'l':  opt = 1;  go = 1;  break;
  1232. X            case  'n':  opt = 2;  go = 1;  break;
  1233. X            case  'p':  opt = 3;  go = 1;  break;
  1234. X            case  'g':  opt = 4;  go = 1;  break;
  1235. X            case  'e':  opt = 5;  go = 1;  break;
  1236. X            case  'i':  opt = 6;  go = 1;  break;
  1237. X            case  's':  opt = 7;  go = 1;  break;
  1238. X            case  'a':  opt = 8;  go = 1;  break;
  1239. X            case  'u':  opt = 9;  go = 1;  break;
  1240. X            case  'd':  opt =10;  go = 1;  break;
  1241. X            case  'r':  opt =11;  go = 1;  break;
  1242. X            case  'q':  opt =-1;  go = 1;  break;
  1243. X          }
  1244. X      if (opt == -1)         opt = num_[arr]-1;
  1245. X      if (opt == num_[arr])  opt = 0;
  1246. X
  1247. X      if (arr==0 && go==1 && opt < 11 && rel==RNULL && opt >= 0)
  1248. X         do_error("specify new relation first"),go=0;
  1249. X      if (arr==0 && go==1 && (opt==9||opt==10) && rel->pos == 0L)
  1250. X         do_error("select a record first"),go=0;
  1251. X
  1252. X      if (doing (0, -1))  break;
  1253. X      if (doing (0, 12))  break;
  1254. X      if (doing (0,  0))  sel_rec (FIRST);
  1255. X      if (doing (0,  1))  sel_rec (LAST);
  1256. X      if (doing (0,  2))  sel_rec (NEXT);
  1257. X      if (doing (0,  3))  sel_rec (PREVIOUS);
  1258. X      if (doing (0,  4))  sel_rec (GTEQ);
  1259. X      if (doing (0,  5))  sel_rec (EQUAL);
  1260. X      if (doing (0,  6))  get_index();
  1261. X      if (doing (0,  7)) {pg++;if(pg>pgmax)pg=1;fill_page();paint_scrn(arr,0);}
  1262. X      if (doing (0,  8))  add_rec(1);
  1263. X      if (doing (0,  9))  add_rec(0);
  1264. X      if (doing (0, 10))  del_rec();
  1265. X      if (doing (0, 11))  get_rel_name();
  1266. X    }
  1267. X
  1268. X   if (buf)  free(buf),  buf=NULL;
  1269. X   clear   ();
  1270. X   refresh ();
  1271. X   endwin  ();
  1272. X   resetty ();
  1273. X   mb_exit (0);
  1274. X}
  1275. X
  1276. Xvoid
  1277. Xpaint_scrn (opt, init)
  1278. Xint         opt, init;
  1279. X{
  1280. X   char temp[128];
  1281. X
  1282. X   if (init)
  1283. X    { clear();
  1284. X      mvaddstr (0, 66, "MetalBase 5.0");
  1285. X      move     (1,  0);
  1286. X      addstr   ("-------------------------------------------------------------------------------");
  1287. X    }
  1288. X   if (opt != -1)
  1289. X      mvaddstr (0,  0, line_[opt]), refresh();
  1290. X   if (opt == -1 || init)
  1291. X    { if (rel == RNULL)
  1292. X         strcpy  (temp, "no relation given");
  1293. X      else
  1294. X         sprintf (temp, "%s.rel -- %ld records, %d indices -- Page %d of %d",
  1295. X                         name,     mb_num(rel), rel->num_i,        pg,pgmax);
  1296. X      move     (2, 0);  clrtoeol();
  1297. X      mvaddstr (2, (80-strlen(temp))/2, temp);
  1298. X    }
  1299. X   refresh();
  1300. X}
  1301. X
  1302. Xvoid
  1303. Xget_index ()
  1304. X{
  1305. X   register int  i;
  1306. X   char          ptr[128];
  1307. X
  1308. X   move (4, 0);  clrtobot();
  1309. X   for (i = 0; i < min (rel->num_i, 16); i++)
  1310. X      sprintf (ptr, "Index #%2d - %s", i+1, rel->iname[i]),
  1311. X      mvaddstr (6+i, 10, ptr);
  1312. X   sprintf (ptr, "%s", rel->iname[idx]);  do_error ("Select index");
  1313. X
  1314. X   mvaddstr (4, 10, "Index Name or Number : ");  refresh();
  1315. X   if ((input (ptr, 0, 20) < 0) || ptr[0] == 0)
  1316. X    { fill_page();  do_error("Index selection aborted"); return; }
  1317. X
  1318. X   if ((i = atoi (ptr)-1) < 0)  i = idxnum (rel, ptr);
  1319. X
  1320. X   if (i < 0 || i > 16 || i >= rel->num_i)
  1321. X    { fill_page ();
  1322. X      do_error  ("Invalid index -- selection aborted");
  1323. X      return;
  1324. X    }
  1325. X
  1326. X   idx = i;  sprintf (ptr, "New index: #%d (%s)", idx+1, rel->iname[idx]);
  1327. X   fill_page();  do_error(ptr);
  1328. X}
  1329. X
  1330. Xvoid
  1331. Xget_rel_name ()
  1332. X{
  1333. X   char   nm[128], *c;
  1334. X   mb_err d;
  1335. X
  1336. X   move (4, 0);  clrtobot();
  1337. X   addstr ("Relation Name      : ");  refresh();  nm[0] = 0;
  1338. X   input  (nm, 0, 60);
  1339. X   if ((! *nm) || (*nm && !get_rel(nm)))
  1340. X    { c=mb_error;d=mb_errno;
  1341. X      fill_page();  if (d)  do_error(c);
  1342. X      paint_scrn(-1,0);
  1343. X    }
  1344. X}
  1345. X
  1346. Xint
  1347. Xget_rel (file)
  1348. Xchar    *file;
  1349. X{
  1350. X   char          pw[80], t[80];
  1351. X   register int  i;
  1352. X
  1353. X   i = strlen(file);
  1354. X   if (! strcmp (&file[i-4], ".rel"))  file[i-4] = 0;
  1355. X   for (i = strlen(file); i >= 0; i--)
  1356. X      if (file[i] == '/' || file[i] == ':')  break;
  1357. X   strcpy (t, &file[i+1]);
  1358. X
  1359. X   if (mb_tst (file))  return 0;
  1360. X
  1361. X   if (rel)  mb_rmv(rel),rel=RNULL;
  1362. X   if (buf)  free(buf),  buf=NULL;
  1363. X   pg = pgmax = pglst = 0; strcpy (name, t);
  1364. X
  1365. X#ifdef NOENCRYPT
  1366. X   pw[0] = 0;
  1367. X#else
  1368. X   if (! inw)  printf ("Encryption password: "), fflush(stdout), gets(pw);
  1369. X   else
  1370. X    { move (5, 0);
  1371. X      addstr ("Encryption password: ");  refresh();
  1372. X      pw[0] = 0;
  1373. X      input (pw, 0, 60);
  1374. X      move (4, 0);  clrtobot();  refresh();
  1375. X    }
  1376. X#endif
  1377. X   if ((rel = mb_inc (file, strtokey (pw))) == RNULL)  return 0;
  1378. X   buf = (dataptr)malloc (rel->rec_len + 1);
  1379. X   pgmax=rel->num_f / 18 + 1;  idx=0;
  1380. X   pglst=rel->num_f % 18;  pg=1;  if (inw)  fill_page();
  1381. X   zero_rec();
  1382. X   return 1;
  1383. X}
  1384. X
  1385. Xvoid
  1386. Xdo_error (line)
  1387. Xchar     *line;
  1388. X{
  1389. X   move (23, 0);   clrtoeol();  iserr = 0;
  1390. X   if (! *line) { refresh(); return; }
  1391. X   Standout();     addstr (line);
  1392. X   Standend();     refresh();   iserr = 1;
  1393. X}
  1394. X
  1395. Xvoid
  1396. Xsel_rec (act)
  1397. Xint      act;
  1398. X{
  1399. X   char *a, c;
  1400. X   int   i, m, arr[40], n;
  1401. X
  1402. X   if (act == GTEQ || act == EQUAL)
  1403. X      {
  1404. X      move (4,0); clrtobot();
  1405. X      do_error("Enter comparison values (vi-style)");
  1406. X      a=rel->idxs[idx]; m=(a[0]-'0')*100 +(a[1]-'0')*10 +(a[2]-'0');
  1407. X      m=min(m,39);
  1408. X      for (i=0; i<m; i++)
  1409. X         {
  1410. X         arr[i]= (a[i*3+3]-'0')*100 +(a[i*3+4]-'0')*10 +(a[i*3+5]-'0');
  1411. X         do_line (4+i, arr[i]);
  1412. X         }
  1413. X      refresh();
  1414. X      for (i=0; ; )
  1415. X         {
  1416. X         move (4+i, 18);
  1417. X         switch (rel->type[arr[i]])
  1418. X            {
  1419. X            case T_CHAR:                  n=rel->siz[arr[i]]; break;
  1420. X            case T_SHORT:  case T_USHORT: n=6;                break;
  1421. X            case T_LONG:   case T_ULONG:  n=11;               break;
  1422. X            case T_FLOAT:  case T_SERIAL: n=11;               break;
  1423. X            case T_DOUBLE: case T_MONEY:  n=14;               break;
  1424. X            case T_TIME:                  n=8;                break;
  1425. X            case T_DATE:                  n=10;               break;
  1426. X            case T_PHONE:                 n=20;               break;
  1427. X            }
  1428. X         if ((c=input ((char*)buf+rel->start[arr[i]], rel->type[arr[i]], n))<0)
  1429. X            break;
  1430. X         if (c == 1)
  1431. X            break;
  1432. X         if (c == 0 && i == m-1)  break;
  1433. X         if (c == 0)  c='+';
  1434. X         switch (c)
  1435. X            {
  1436. X            case '-': case 'k': case AR_UP:   i--; break;
  1437. X            case '+': case 'j': case AR_DOWN: i++; break;
  1438. X            }
  1439. X         if (i == -1)  i = m-1;
  1440. X         if (i ==  m)  i = 0;
  1441. X         }
  1442. X      if (c < 0)
  1443. X         {
  1444. X         fill_page();  do_error("Search aborted");
  1445. X         return;
  1446. X         }
  1447. X      }
  1448. X
  1449. X   if (mb_sel (rel, idx, buf, act, buf) != MB_OKAY)
  1450. X    { a=mb_error;  fill_page();
  1451. X      do_error (a);
  1452. X      return;
  1453. X    }
  1454. X   fill_page();
  1455. X}
  1456. X
  1457. Xvoid
  1458. Xfill_page ()
  1459. X{
  1460. X   register int  i, n;
  1461. X
  1462. X   move (4, 0);  clrtobot();
  1463. X
  1464. X   if (rel)
  1465. X      for (i=0, n=(pg-1)*18; i < (pg == pgmax ? pglst : 18); i++,n++)
  1466. X         do_line(4+i, n);
  1467. X
  1468. X   paint_scrn (-1, 0);
  1469. X   refresh();
  1470. X}
  1471. X
  1472. X#define getdata(b,f,t) sprintf (b, f, *(t *)((char *)buf +rel->start[n]));
  1473. X
  1474. Xvoid
  1475. Xdo_line (y, n)
  1476. Xint      y, n;
  1477. X{
  1478. X   char    temp[80];
  1479. X   int     t;
  1480. X   long    ac,pre,num,ext;
  1481. X
  1482. X   move (y, 0);  clrtoeol();
  1483. X
  1484. X   strzcpy  (temp, rel->name[n], 13);
  1485. X   mvaddstr (y,  0, temp);
  1486. X   mvaddstr (y, 15, "-");
  1487. X
  1488. X   switch (rel->type[n])
  1489. X      {
  1490. X      case T_CHAR:    mvaddch (y, 17, '\"');
  1491. X                      mvaddch (y, 18 +min(rel->siz[n],60), '\"');
  1492. X                     break;
  1493. X      case T_SHORT:
  1494. X      case T_USHORT:  mvaddstr (y, 17, "[      ]");               break;
  1495. X      case T_LONG:
  1496. X      case T_ULONG:
  1497. X      case T_FLOAT:   mvaddstr (y, 17, "[           ]");          break;
  1498. X      case T_DOUBLE:  mvaddstr (y, 17, "[              ]");       break;
  1499. X      case T_MONEY:   mvaddstr (y, 17, "$              ");        break;
  1500. X      case T_TIME:    mvaddstr (y, 17, "(  :  :  )");             break;
  1501. X      case T_DATE:    mvaddstr (y, 17, "(  /  /    )");           break;
  1502. X      case T_SERIAL:  mvaddstr (y, 17, "(           )");          break;
  1503. X      case T_PHONE:   mvaddstr (y, 17, "(   -   -            )"); break;
  1504. X      }
  1505. X
  1506. X   if (rel->pos != 0L)
  1507. X      {
  1508. X      switch (rel->type[n])
  1509. X         {
  1510. X         case T_CHAR:  t = min (rel->siz[n], 60);
  1511. X                       strzcpy (temp, (char *)buf+rel->start[n], t);
  1512. X                      break;
  1513. X
  1514. X         case T_SHORT:   getdata (temp, "%d",     short);   break;
  1515. X         case T_USHORT:  getdata (temp, "%u",     ushort);  break;
  1516. X         case T_LONG:    getdata (temp, "%ld",    long);    break;
  1517. X         case T_ULONG:   getdata (temp, "%lu",    ulong);   break;
  1518. X         case T_FLOAT:   getdata (temp, "%f",     float);   break;
  1519. X         case T_DOUBLE:  getdata (temp, "%lf",    double);  break;
  1520. X         case T_MONEY:   getdata (temp, "%-.2lf", double);  break;
  1521. X
  1522. X         case T_SERIAL:  getdata (temp, "%ld", long);                    break;
  1523. X         case T_PHONE:   scn_phone (&ac,&pre,&num,&ext,
  1524. X                                      ((char *)buf + rel->start[n]));
  1525. X                         strcpy(temp, fmt_phone (ac, pre, num, ext, 0)); break;
  1526. X         case T_TIME:    strcpy(temp, fmt_time (*(mb_time *)
  1527. X                                      ((char *)buf +rel->start[n]), 0)); break;
  1528. X         case T_DATE:    strcpy(temp, fmt_date (*(mb_date *)
  1529. X                                      ((char *)buf +rel->start[n]), 0)); break;
  1530. X         }
  1531. X      mvaddstr (y, 18, temp);
  1532. X      }
  1533. X}
  1534. X
  1535. Xvoid
  1536. Xadd_rec (opt)
  1537. Xint      opt;
  1538. X{
  1539. X   register int  i;
  1540. X   int           _pg, n, m, o;  /* Handles up to 500 fields */
  1541. X   mb_err        e;
  1542. X   char          c,  *p;
  1543. X   long          tlong;
  1544. X
  1545. X   _pg=pg;
  1546. X
  1547. X   if (opt)  tlong=rel->pos, rel->pos=1L, zero_rec();  /* Add new rec */
  1548. X
  1549. X   for (pg = 1, i=0; ; )
  1550. X    {
  1551. X      fill_page ();
  1552. X      if (opt)  do_error ("enter data to add");
  1553. X      else      do_error ("enter new data for this record");
  1554. X
  1555. X      for (o=18*pg-18, m=o+(pg == pgmax ? pglst : 18); ; )
  1556. X       { move (4+i -((pg-1)*18), 18);
  1557. X         switch (rel->type[i])
  1558. X            {
  1559. X            case T_CHAR:                    n=rel->siz[i];  break;
  1560. X            case T_SHORT:   case T_USHORT:  n=6;            break;
  1561. X            case T_LONG:    case T_ULONG:   n=11;           break;
  1562. X            case T_FLOAT:   case T_SERIAL:  n=11;           break;
  1563. X            case T_DOUBLE:  case T_MONEY:   n=14;           break;
  1564. X            case T_TIME:                    n=8;            break;
  1565. X            case T_DATE:                    n=10;           break;
  1566. X            case T_PHONE:                   n=20;           break;
  1567. X            }
  1568. X         n = min (n, 60);
  1569. X         if (rel->type[i] == T_SERIAL)
  1570. X            {
  1571. X            if (rel->num_f == 1)  c = 1;    /* Nothing but serial#?  Done. */
  1572. X            else                  c = '+';  /* Don't let 'em enter serial# */
  1573. X            }
  1574. X         else
  1575. X            {
  1576. X            if ((c = input ((char *)buf + rel->start[i], rel->type[i], n)) < 0)
  1577. X               break;
  1578. X            }
  1579. X         if (c == 0 && i == m-1 && pg==pgmax)  c=1;
  1580. X         if (c == 0)  c='+';
  1581. X         if (c == 1)  break;
  1582. X         switch (c)
  1583. X          { case '-': case 'k': case AR_UP:   i--;  c='-';  break;
  1584. X            case '+': case 'j': case AR_DOWN: i++;  c='+';  break;
  1585. X          }
  1586. X         if (c == '-' && rel->type[i] == T_SERIAL)  i--;
  1587. X         if (i >=  m) { pg++;i=m;  c=0;if(pg>pgmax) pg=1, i=0;           break;}
  1588. X         if (i <   o) { pg--;i=o-1;c=0;if(pg==0) pg=pgmax,i=rel->num_f-1;break;}
  1589. X       }
  1590. X      if (c != 0)  break;
  1591. X    }
  1592. X   if (opt)  pg=_pg, rel->pos=tlong;
  1593. X
  1594. X   if (c < 0)
  1595. X    { mb_sel (rel, idx, buf, CURRENT, NULL);  if (! rel->pos)  zero_rec();
  1596. X      fill_page ();
  1597. X      do_error ("add aborted");
  1598. X      return;
  1599. X    }
  1600. X
  1601. X   fill_page();
  1602. X   do_error ("wait...");
  1603. X
  1604. X   if (opt)  e=mb_add (rel, buf), p=mb_error;
  1605. X   else      e=mb_upd (rel, buf), p=mb_error;
  1606. X
  1607. X   mb_sel (rel, idx, buf, CURRENT, NULL);  if (! rel->pos)  zero_rec();
  1608. X   fill_page ();
  1609. X
  1610. X   if (e != MB_OKAY)
  1611. X      do_error (p);
  1612. X   else
  1613. X    { if (opt)  do_error ("record successfully added");
  1614. X      else      do_error ("record successfully updated");
  1615. X      paint_scrn (-1, 0);
  1616. X    }
  1617. X}
  1618. X
  1619. Xvoid
  1620. Xdel_rec ()
  1621. X{
  1622. X   if (! verify ("delete this record ? "))
  1623. X    { do_error ("delete aborted");
  1624. X      return;
  1625. X    }
  1626. X   do_error ("wait...");
  1627. X   if (mb_del (rel) != MB_OKAY)
  1628. X    { do_error (mb_error);
  1629. X      return;
  1630. X    }
  1631. X   if (! rel->pos)  zero_rec();
  1632. X   fill_page();
  1633. X   do_error ("record deleted");
  1634. X}
  1635. X
  1636. Xint
  1637. Xverify (str)
  1638. Xchar   *str;
  1639. X{
  1640. X   char  c;
  1641. X   do_error (str);
  1642. X   for (;;)
  1643. X    { c = getarr();
  1644. X      switch (tolower(c))
  1645. X       { case 'q': case 'n':  case ' ':   do_error (""); return 0; break;
  1646. X         case  27: case '\r': case '\n':  do_error (""); return 0; break;
  1647. X         case 'y':                        do_error (""); return 1; break;
  1648. X       }
  1649. X    }
  1650. X}
  1651. X
  1652. Xvoid
  1653. Xzero_rec ()
  1654. X{
  1655. X   register int  i;
  1656. X   char         *a;
  1657. X
  1658. X   for (i=0; i<rel->num_f; i++)
  1659. X      {
  1660. X      a=(char *)buf +rel->start[i];
  1661. X      switch (rel->type[i])
  1662. X         {
  1663. X         case T_CHAR:    *a = 0;                      break;
  1664. X         case T_PHONE:   *a = 0;                      break;
  1665. X         case T_SHORT:   *(short  *)a = (short)0;     break;
  1666. X         case T_USHORT:  *(ushort *)a = (ushort)0;    break;
  1667. X         case T_LONG:    *(long   *)a = (long)0;      break;
  1668. X         case T_ULONG:   *(ulong  *)a = (ulong)0;     break;
  1669. X         case T_FLOAT:   *(float  *)a = (float)0.0;   break;
  1670. X         case T_DOUBLE:
  1671. X         case T_MONEY:   *(double *)a = (double)0.0;  break;
  1672. X         case T_TIME:    *(mb_time*)a = (mb_time)0;   break;
  1673. X         case T_DATE:    *(mb_date*)a = (mb_date)0;   break;
  1674. X         case T_SERIAL:  *(long   *)a = (long)0;      break;
  1675. X         }
  1676. X      }
  1677. X}
  1678. X
  1679. END_OF_FILE
  1680.   if test 15920 -ne `wc -c <'src/vr.c'`; then
  1681.     echo shar: \"'src/vr.c'\" unpacked with wrong size!
  1682.   fi
  1683.   # end of 'src/vr.c'
  1684. fi
  1685. echo shar: End of archive 3 \(of 8\).
  1686. cp /dev/null ark3isdone
  1687. MISSING=""
  1688. for I in 1 2 3 4 5 6 7 8 ; do
  1689.     if test ! -f ark${I}isdone ; then
  1690.     MISSING="${MISSING} ${I}"
  1691.     fi
  1692. done
  1693. if test "${MISSING}" = "" ; then
  1694.     echo You have unpacked all 8 archives.
  1695.     rm -f ark[1-9]isdone
  1696. else
  1697.     echo You still must unpack the following archives:
  1698.     echo "        " ${MISSING}
  1699. fi
  1700. exit 0
  1701. exit 0 # Just in case...
  1702.