home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / sources / misc / 4131 < prev    next >
Encoding:
Text File  |  1992-11-23  |  55.1 KB  |  1,708 lines

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