home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CMAGIC.ZIP / TUTOR.DOC < prev   
Text File  |  1992-09-06  |  61KB  |  1,256 lines

  1.  
  2.                                     C MAGIC
  3.                                   Version 1.5
  4.  
  5.                (c) Copyright 1992, Jeff Napier & Another Company
  6.  
  7.  
  8.                                  Tutorial File
  9.  
  10.          What C Magic can do for you:
  11.  
  12.             This   disk  consists  of  three  main  parts,  MAGIC.LIB,
  13.          MAGIC.TXT  and  TUTOR.DOC.   MAGIC.LIB  is  an   add-in   for
  14.          Borland's Turbo C and BORLAND C products.  It  will  work  on
  15.          versions  from  Turbo  C 1.5 through Borland C++ version 3.1,
  16.          and probably work on future versions as well.
  17.  
  18.              C  MAGIC  which  will  make your job as a programmer much
  19.          easier and your results much more polished.  MAGIC.TXT  is  a
  20.          text  file  which  explains  how  to  use all the features of
  21.          MAGIC.LIB, and TUTOR.DOC, the file you are now reading, is  a
  22.          tutorial  which starts at a very beginning level and quickly,
  23.          but effortlessly moves into advanced programming techniques.
  24.  
  25.          Specifically, MAGIC.LIB offers the following:
  26.  
  27.          *  Automatic  pop-up  text  boxes, dialog boxes and light-bar
  28.          menus.
  29.  
  30.          * Automatic handling of text files.
  31.  
  32.          *  Built-in  mouse  and  cursor  support for the programs you
  33.          create.
  34.  
  35.          * Support for graphics programs to make them as easy to write
  36.          as text-based programs.   This  includes  a  universal  mouse
  37.          cursor  which  will operate from the keyboard as well as from
  38.          mouse movement whether or not a mouse is available.
  39.  
  40.          * Incorporation of .BGI and .CHR files directly into finished
  41.          .EXE files.
  42.  
  43.          * Built-in 256-color VGA support. (Except with older versions
  44.          of Turbo C.)
  45.  
  46.          * Sound effects for your programs.
  47.  
  48.          * Simplification of many standard C operations.
  49.  
  50.          * Complete color control in text and graphics modes.
  51.  
  52.          *   Full,   documented,  easy-to-understand  source  code  is
  53.          available  so  you  can  learn  from  and customize the Magic
  54.          framework to your own applications.
  55.  
  56.          * OOP supported but not required.
  57.  
  58.                                      NOTE:
  59.  
  60.             This is a shareware product.  You have our  permission  to
  61.          copy  and distribute this package as long as all files remain
  62.          intact and unchanged.
  63.             If  you  benefit  from  this  tutorial,  or if you use the
  64.          MAGIC.LIB unit in your programs you are expected to register.
  65.          To register, send $39.95 to:
  66.  
  67.                                 Another Company
  68.                                  P.O. Box 298
  69.                               Applegate, OR 97530
  70.                                       USA
  71.  
  72.             Please  add  $3  per  order for postage in the USA, $5 for
  73.          postage to Canada, or $7 for postage to all other  countries.
  74.          Please add $1 if you require 3.5" disk size.
  75.  
  76.          If you would  like  the  full  source  code  sent  with  your
  77.          registration, send $79.90 plus postage.  Please add $2 if you
  78.          require 3.5" disk size.
  79.  
  80.                                   QUESTIONS:
  81.  
  82.          If you have questions: 503-846-7884, 9-5 Weekdays, West Coast
  83.          time.   (We  are not always available during those hours, but
  84.          you can try.)
  85.  
  86.                       THE BEST WAY TO USE THIS TUTORIAL:
  87.  
  88.          Copy MAGIC.LIB to the directory  where  you  keep  your  .LIB
  89.          files,  copy  MAGIC.H  to  the  directory which contains your
  90.          include (*.H) files, and  copy  TUTOR.DOC  to  the  directory
  91.          which  contains your source code files.  Start your BC.EXE or
  92.          TC.EXE and load in this file  (type: BC TUTOR.DOC). Since the
  93.          IDE* (Integrated Development Environment) allows you to  work
  94.          on  several  files at once, you can read this tutorial in one
  95.          window and work on practice programs in another  window.   If
  96.          you  don't  know  how  yet,  I'll  show  you.   If you are an
  97.          experienced programmer, you might want to skim  through  this
  98.          tutorial  and  concentrate  only on the areas that are new to
  99.          you.
  100.  
  101.          * Some of the older  versions  of  Turbo  C  do  not  have  a
  102.          multi-window  IDE.   With  these versions, simply switch from
  103.          one file to another as required.
  104.  
  105.                            A COUPLE OF OTHER NOTES:
  106.  
  107.          1.  It is assumed that you have legally purchased a Borland C
  108.          compiler and therefore have the valuable printed manuals that
  109.          come with the kit.  If not, you are advised to spend a little
  110.          money and get what you need, because there are places  within
  111.          this tutorial which will refer you to those books to complete
  112.          your knowledge.
  113.  
  114.          2.  This  is  not  the  last  word  on  C.   It doesn't teach
  115.          everything about programming - probably not even  10  percent
  116.          of  what you will eventually learn, but between this tutorial
  117.          and  the  Borland  manuals,  you'll  get   pretty   good   at
  118.          programming,  and  fairly  quickly.  One  of the best ways to
  119.          learn this is to  experiment  frequently.  Tear  the  example
  120.          programs apart and try to interject your own ideas into them.
  121.          See what you can change or improve, then run the programs you
  122.          have  modified  and  see  what happens. As you well know, you
  123.          can't hurt your computer by typing an incorrect line of code.
  124.  
  125.          3.   C is sensitive to capitalization. You must be careful to
  126.          use capital letters and  lower  case  letters  in  the  right
  127.          places. The exact placement of indentations is not important,
  128.          however,  and  every programmer develops a slightly different
  129.          style.
  130.  
  131.          4.  This  is version 1.5 of what I believe is a good product,
  132.          but then, I wrote it.  Let me know what you think. I'm pretty
  133.          sure I caught all the major bugs, but there may be some minor
  134.          ones. Most likely the registered and/or subsequent  shareware
  135.          versions will be even better!  Registered  users  always  get
  136.          the  very latest version with whatever improvements have been
  137.          added since the shareware release.
  138.  
  139.  
  140.                                   HERE WE GO:
  141.  
  142.          Here is the simplest program you can write:
  143.  
  144.               main() {}
  145.  
  146.          Let's  try  it  out.  Press [F3].  (First finish reading this
  147.          paragraph so you know how to get  back.)  A  window  pops  up
  148.          asking  for  a  file  name.   Call  it Prog1 (or any name you
  149.          choose) and type the preceding one-line program.  Press  [F2]
  150.          to save your valuable work against power failure, etc.  While
  151.          holding  the [Ctrl] key, press [F9] and the program will run.
  152.          (With older versions of Turbo C, hold [Alt] and  press  [r].)
  153.          Did  you  blink?   Since,  the  program  doesn't  actually do
  154.          anything, it runs very quickly, then returns to the IDE.
  155.  
  156.              IDE stands for Integrated Development  Environment,  what
  157.          Borland calls their compiler.  We'll use the same name rather
  158.          than trying to say Borland C, or something equally confusing.
  159.  
  160.              Let's look at the program you just ran in detail.  Main()
  161.          is a function. Every C program must have one main() function.
  162.          This  program  was  a  very  simple  one, and so there are no
  163.          additional details needed between the parentheses.  They  are
  164.          there  simply to tell the computer that "main" is a function,
  165.          not a number or an instruction  of  some  sort.   The  main()
  166.          function starts after the curly bracket.  It is there to tell
  167.          the computer that this is where the function will begin.  The
  168.          closing curly bracket tells the computer that the function is
  169.          done.  Since there is nothing between the curly brackets, the
  170.          program does nothing.
  171.  
  172.             If you are sharp, you may have noticed that the IDE issued
  173.          a  warning message.  If you don't see it at the bottom of the
  174.          screen,  press  [F6].   Technically,  all  functions  give  a
  175.          response  when they are run unless they are provided with the
  176.          special word "void."
  177.  
  178.          So  in  the  next  program,  we'll  precede main() with void.
  179.          Next, we'll add something to the program so it will  actually
  180.          have a purpose:
  181.  
  182.               void main(){
  183.                  printf("Hello, World!");
  184.               }
  185.  
  186.          Go  back  to  your program (hold [Alt] and press [1] or [2]),
  187.          and modify it to imitate the above example. Hold  [Ctrl]  and
  188.          press [F9] (or [Alt] + [r]) to run it.
  189.              What happened?  Well, it worked alright, but if you  have
  190.          a  recent  compiler,  you  did  not  see anything, because it
  191.          happened very quickly and returned to the  IDE  when  it  was
  192.          done.   Let's  add another function to slow it down.  Getch()
  193.          waits patiently for the  user  to  press  a  key  before  the
  194.          program continues, thereby giving you a chance to see "Hello,
  195.          World!" written on the screen. Test this one out:
  196.  
  197.               void main(){
  198.                  printf("Hello, World!");
  199.                  getch();
  200.               }
  201.  
  202.             If  you  have  a  recent  Borland  compiler, it issued two
  203.          warnings! You see, the IDE doesn't trust you to use  printf()
  204.          or  getch()  properly.  And that's a good thing, because when
  205.          you start writing complicated programs, you'll need  all  the
  206.          help  you  can get from the IDE. Any function that you try to
  207.          use  is  checked  to  see  that  you  are  feeding  it  right
  208.          information.   In  this  case,  printf()  is a function which
  209.          writes text onto the screen.  You want printf()  to  write  a
  210.          literal string, "Hello, World!", but what if you accidentally
  211.          told  it  to  write  14  cucumbers.   It  wouldn't  know what
  212.          cucumbers are, or what to do with 14 of them.  So C restricts
  213.          you to passing information to functions that they can handle.
  214.          To do this, you must list the functions that you are going to
  215.          use and what kind of information they can handle, before  you
  216.          use  them.   A  typical  C  program  has  a  list of function
  217.          "prototypes" and their acceptable "parameters" at the top  of
  218.          the program.
  219.  
  220.              Printf()  and  getch()  are  two of hundreds of functions
  221.          provided with C in a separate disk  file  called  a  library.
  222.          There  are several such libraries available so you don't have
  223.          to reinvent the wheel when you make your own programs.  There
  224.          are functions for dividing numbers, drawing circles,  writing
  225.          disk files, and so on.
  226.  
  227.              As a program grows in  size,  you  may  end  up  using  a
  228.          hundred  or so of these functions.  Rather than list them all
  229.          at the top of your source code, you can  "include"  a  header
  230.          file.    Borland   provides  several  header  files  for  the
  231.          functions in their library files.  The one which contains the
  232.          prototypes for printf()  and  getch()  is  STDIO.H  in  older
  233.          versions of Turbo C, or CONIO.H in new versions.  Look at the
  234.          following program listing to see how it is included:
  235.  
  236.               #include <stdio.h>
  237.               void main(){
  238.                  printf("Hello, World!");
  239.                  getch();
  240.               }
  241.  
  242.              While you are at it,  look at STDIO.H or CONIO.H and look
  243.          at the prototypes in the header file.
  244.  
  245.              Again,  you  can  type  in  the  changes  and  test  this
  246.          program.  Or,  you  could save yourself a bit of work. If you
  247.          have a mouse and a new version compiler:
  248.  
  249.              Move  the  cursor to the top of the program in this file.
  250.          (Move it to the  #  in  "#include."  Then  select  the  whole
  251.          program  by holding down the left mouse button and moving the
  252.          mouse until the whole four lines change  color.  Then  select
  253.          Edit  from  the  top  menu  and Copy.  Then open a new window
  254.          (press [F3]) and then select Paste from the Edit menu.
  255.  
  256.              Or  from  the keyboard: Move the cursor to the top of the
  257.          program and hold [Ctrl] and press [k]  then  [b].   (This  is
  258.          referred  to  as ^kb.) Then, using the arrow keys move to the
  259.          bottom of the program listing and press ^kk.   Then  [Alt]  +
  260.          [e],[c].   Open  a  new  window  (press [F3]) and then select
  261.          [Alt] + [e] + [p].
  262.  
  263.             The  program  will  be pasted in the new window.  Save the
  264.          program with a press of the [F2] key,  then  run  it.   (Hold
  265.          [Ctrl] and press [F9])
  266.  
  267.              With the older compilers, you use ^kb and ^kk to  mark  a
  268.          block,  and then press ^kw to write a block.  You'll be asked
  269.          to  name  a  file for the block so choose a name like "TEMP".
  270.          A file called TEMP.C appears on your disk.   Then  move  into
  271.          another  file,  such  as  TEST.C, and press ^kr to "read" the
  272.          block, TEMP.C into the file.
  273.  
  274.              If  you  haven't  changed  the  layout of directories and
  275.          files, the program will run just  fine.   If  it  can't  find
  276.          STDIO.H,  select Options from the top menu, then Directories,
  277.          then tell the IDE where it should look for "INCLUDE" files.
  278.  
  279.              Our little program works, but it doesn't look like  much,
  280.          does  it?   Here's a wonderful opportunity for me to show you
  281.          how much better C Magic is.  Let's try a  variation  of  that
  282.          program.  But  first,  you'll  need to do a couple of things,
  283.          Copy MAGIC.LIB  into  the  directory  containing  your  *.LIB
  284.          files,  and  MAGIC.H into the directory containing your other
  285.          *.H files (general called the INCLUDE directory).
  286.  
  287.              In  order  to  incorporate  MAGIC.LIB into your programs,
  288.          you'll need to start a "project".  This  is  easier  than  it
  289.          sounds.  Simply choose Project from the top menu, then choose
  290.          Open.  Give it any DOS-legal name (up  to  8  letters)  which
  291.          will end with .PRJ.  Then Choose  Include  from  the  Project
  292.          menu  and  type  your  program name, then MAGIC.LIB, and also
  293.          GRAPHICS.LIB.  Now all the functions within MAGIC.LIB will be
  294.          available to your program.
  295.  
  296.             If  you  have  an  older version compiler, you make a .PRJ
  297.          file by simply pressing [F3] to edit a new file, and name  it
  298.          something  specifically  ending with .PRJ.  In this file, you
  299.          type your program name (for instance, TEST.C), and  then,  on
  300.          the next line, MAGIC.LIB, and on a third line, GRAPHICS.LIB.
  301.  
  302.                                 IMPORTANT NOTE:
  303.  
  304.              GRAPHICS.LIB is a library of graphics routines,  some  of
  305.          which  are used by MAGIC.LIB, even for non-graphics programs.
  306.          Therefore, GRAPHICS.LIB must always be  included  along  with
  307.          MAGIC.LIB in your "projects."
  308.  
  309.              And now type or paste this into a file of it's own:
  310.  
  311.             #include <magic.h>
  312.             void main(){
  313.               xclear();
  314.               pile("Hello, World!");
  315.               getanykey(10,10);
  316.             }
  317.  
  318.              This  program  should  run,  and  look  quite  impressive
  319.          compared  to  the  earlier  version.
  320.  
  321.                              If You Have Problems:
  322.  
  323.              Select  OPTIONS  from  the  top menu, then COMPILER, then
  324.          CODE GENERATION.  The memory model MUST be LARGE.  Magic will
  325.          not work with smaller memory models.
  326.  
  327.              When  you  start  a  .PRJ file, the settings you may have
  328.          selected from the OPTIONS menu may change.  Especially  check
  329.          the Options | Directories menu.
  330.  
  331.              Another potential problem is that you can forget  to  use
  332.          the graphics library, which must be linked with MAGIC even if
  333.          you  aren't  using  any  graphics.   This is because MAGIC is
  334.          always READY for graphics.  With Borland C++ version  3.0  or
  335.          3.1,  select  OPTIONS,  then LINKER, then LIBRARIES, and make
  336.          sure the box for GRAPHICS.LIB is checked. You  can  leave  it
  337.          checked for all programs you write, because it is only linked
  338.          into  programs  which  use  it.   The only difference is your
  339.          programs will compile a bit slower.  With the older versions,
  340.          simply include the line GRAPHICS.LIB in your .PRJ files.
  341.  
  342.              While  the above program is similar to the previous ones,
  343.          you'll see some different functions.
  344.  
  345.              Since  the  above  program  uses  functions  from  within
  346.          MAGIC.LIB,  we  use  the MAGIC.H header file to prototype the
  347.          functions.
  348.  
  349.              The first one, xclear(), simply clears the previous  junk
  350.          off  the screen. Then pile() gets the "Hello, World!" string.
  351.          We'll talk more about  pile()  later.   Finally,  getanykey()
  352.          places  the  "Hello,  World!"  string on the screen, but in a
  353.          fancy box!
  354.  
  355.               Getanykey()  gets  two numbers, the coordinates at which
  356.          the upper left corner of the pop-up box is  to  appear.   The
  357.          first number is the horizontal position.  1  is  the  extreme
  358.          left  edge  of  the screen and 80 is the right-most edge. The
  359.          second number is the vertical position which can range from 1
  360.          to almost 25. If you use a negative integer for one  or  both
  361.          numbers,  the  box  is  automatically centered on the screen,
  362.          horizontally, vertically, or both. Like getch(),  getanykey()
  363.          waits for the user to press any key.  Unlike getch(), it then
  364.          erases  the  text box from the screen.  Also, it will respond
  365.          to  a  mouse  button.   If  the  left  button   is   clicked,
  366.          getanykey()  acts  as  if  [Enter]  was pressed and the right
  367.          mouse button is equivalent to [Esc].
  368.  
  369.             Lets add a few things to the previous program:
  370.  
  371.             /* program #6 */
  372.             #include <magic.h>
  373.             void main(){
  374.               magic_setup();
  375.               xclear();
  376.               pile("Do you want to quit? (Y/N)");
  377.               pile("");
  378.               pile("This is just an example.  Actually, the");
  379.               pile("program will quit whether you type Y or N");
  380.               getyn(-1,-1);
  381.             }
  382.  
  383.             The very top line, starting with /* and ending with */  is
  384.          a  comment.   Comments have no effect on the program, and are
  385.          available just for making notes.  You  can  include  comments
  386.          just  about  anywhere,  but  there are two restrictions:  You
  387.          must have the /* marker at the beginning and the  */  at  the
  388.          end; and you cannot usually include comments within comments.
  389.          (Compilers which support C++ also accept // as the start of a
  390.          comment and the end of a line as the end.)
  391.  
  392.             Using  lots  of  comments  is a good idea because they can
  393.          help you think out a program that is giving you trouble.   By
  394.          adding  comments,  you  can  sometimes  understand  your code
  395.          better.  Also, they help you remember what you did last  week
  396.          or last year.  They do not change the size of  or  slow  down
  397.          the finished .EXE file.
  398.  
  399.             We  added  a  new  function  from the MAGIC library,  this
  400.          one, magic_setup(), seemingly does nothing.  In fact, it does
  401.          lots of stuff in the background, ranging  from  fixing  up  a
  402.          sound  effects  error in older compilers to getting ready for
  403.          graphics screens should you decide to use  graphics.   It  is
  404.          advisable,   in   fact  necessary  in  most  cases,  to  call
  405.          magic_setup() once at the beginning of  most  programs  which
  406.          use the MAGIC library.
  407.  
  408.             You can see now that pile() builds a pile  of  strings  of
  409.          text  for  display.  You can call pile() over and over again.
  410.          Each  time  you  do, another line is added to the "pile." The
  411.          pile is actually a global array of 46 strings, called sent[],
  412.          each up to 80 characters long.
  413.  
  414.             In  this  program,  getanykey()  has  been  replaced  with
  415.          getyn(), which waits until the user types [Y], [y], [N], [n],
  416.          or  clicks  the left or right mouse button.  (NOTE: The mouse
  417.          is optional. It does not have to be hooked up.) When  getyn()
  418.          is done, it sets a global char variable called "u" to  either
  419.          capital "Y" or "N".
  420.  
  421.              Also, the coordinates have changed.  Getyn() now uses two
  422.          negative  integers,  and  will therefore center itself on the
  423.          screen.
  424.  
  425.             C mostly isn't sensitive to white space.  You can organize
  426.          the actual layout of your program differently.  It is usually
  427.          done  with indentations similar to the examples you have been
  428.          looking at.  This makes the programs much easier to read  and
  429.          understand.   To  illustrate this point, look at program #6a,
  430.          below, which compiles and runs just like program #6.   You'll
  431.          notice,  however,  that  the  "#include"  is on its own line.
  432.          Directives starting with # must be on their own line and  the
  433.          line must start with the #.
  434.  
  435.             /* program #6a */
  436.             #include <magic.h>
  437.             magic_setup();  void main(){xclear();
  438.             pile("Do you want to  quit?  (Y/N)");  pile("");
  439.             pile("This  is  just  an example. Actually,  the");
  440.             pile("program  will quit whether you type Y or N");
  441.             getyn(-1,-1);}
  442.  
  443.              In  the  next  program,  I'll show how you'd actually use
  444.          getyn().
  445.  
  446.            /* program #7 */
  447.             #include <magic.h>
  448.             void main(){
  449.               magic_setup();
  450.               xclear();
  451.               do {
  452.                  pile("Do you want to quit? (Y/N)");
  453.                  pile("");
  454.                  pile("This version works like it should.");
  455.                  getyn(-1,-1);
  456.                  }
  457.               while (u != 'Y');
  458.             }
  459.  
  460.             Most  of  the  program is the same.  But look at  the  "do
  461.          {"  line.   This  starts  a loop which executes over and over
  462.          again until the condition following the  "while"  allows  the
  463.          program  to  "fall  through"  or continue past the loop.  The
  464.          curly bracket following the "do" and on the line  before  the
  465.          "while"  contain  the statements which are allowed to repeat.
  466.          "!=" is C talk for "not  equal  to."  Remember  that  getyn()
  467.          allows  only  [y],  [Y],  [n], or [N], or a mouse button, and
  468.          returns the variable "u" only as (capital) [Y] or  [N].   So,
  469.          until  the  user  answers  "yes"  with [Y] or [y] or the left
  470.          mouse button, the computer is gonna keep asking "Do you  want
  471.          to quit," etc.
  472.  
  473.             You'll notice that the pile()s are repeated as well.  This
  474.          is  because  as  soon  as  getyn() is done, it resets all the
  475.          strings in the pile to blanks, in  preparation  for  whatever
  476.          the programmer might want next.  For this loop to work right,
  477.          you  have  to  keep  forcing the pile back to the strings you
  478.          want displayed.
  479.  
  480.             In  this  next  variation,  there are two small changes to
  481.          pretty it up:
  482.  
  483.  
  484.            /* program #8 */
  485.             #include <magic.h>
  486.             void main(){
  487.               magic_setup();
  488.               xclear();
  489.               centerjustify = 1;
  490.               musicon = 0;
  491.               do {
  492.                  pile("Do you want to quit? (Y/N)");
  493.                  pile("");
  494.                  pile("This version works like it should.");
  495.                  getyn(-1,-1);
  496.                  }
  497.               while (u != 'Y');
  498.             }
  499.  
  500.              First we have set a global variable called  centerjustify
  501.          to 1.  When this is set,  all the MAGIC functions which print
  502.          the  pile  to  the screen automatically center the strings of
  503.          text within the pop-up box. If centerjustify were set  to  0,
  504.          the default condition, the strings are not centered.
  505.  
  506.              Then,  another  variable  called  musicon,  which is 1 by
  507.          default, has been set to 0, and now sound  effects  will  not
  508.          play when pop-up boxes appear and disappear. Using 1 and 0 is
  509.          common  practice  in C programs.  1 is used to represent TRUE
  510.          or ON or YES and 0 equals NO or OFF or FALSE.
  511.  
  512.              Compile and run program 8 and see if you like it better.
  513.  
  514.              Now,  here's a little project: See if you can add another
  515.          loop to program #8 which asks the user "Are you  sure?"  when
  516.          "Do you want to quit?" is answered affirmatively.
  517.  
  518.              You might want to experiment a  bit  with  this  program,
  519.          entering  different  messages, and different numbers of lines
  520.          of text,  and  even  lines  of  text  of  differing  lengths.
  521.  
  522.                                 IMPORTANT NOTE:
  523.  
  524.          NOTE: There is a limit to the  size  of  pop-up  boxes.  This
  525.          limit  depends  on  which  graphics  mode you are using.  For
  526.          instance, in VGA high-resolution, if you try to pop up a  box
  527.          containing more than about 20 lines of text, with the longest
  528.          line  being  perhaps  40 characters long, you'll probably run
  529.          out of RAM space.  The result of this is a crash.
  530.  
  531.             This  next  program  introduces  another  Magic  function,
  532.          dialog(), which also pops a text box  onto  the  screen,  but
  533.          this  box  has  a  blank line at the bottom in which the user
  534.          types a response. The answer is returned in a global variable
  535.          called "answer."
  536.  
  537.            /* program #9 */
  538.             #include <magic.h>
  539.             void main(){
  540.               magic_setup();
  541.               xclear();
  542.               pile("How would you answer this question?");
  543.               dialog(-1,4);
  544.               pile("User typed:");
  545.               pile(answer);
  546.               getanykey(-1,12);
  547.             }
  548.  
  549.              Again, a good way to study this little program is to copy
  550.          it into it's own window, try to guess what it does, then  run
  551.          it and see if it did what you expected.
  552.  
  553.              Notice the two lines "pile()ed" up for getanykey().   The
  554.          first  has  a  literal  string surrounded by quotation marks.
  555.          Nothing new about that.  But the next call to  pile()  passes
  556.          the  variable, answer, not in quotation marks.  If it were in
  557.          quotation marks, the program would say:
  558.  
  559.              User typed:
  560.              answer
  561.  
  562.              What  you  want  instead  is the value answer represents,
  563.          which in this case is the string returned by dialog(). Answer
  564.          is  a global variable that always represents a string of zero
  565.          or more characters.
  566.  
  567.  
  568.              In program #9, you could make the  whole  operation  more
  569.          evident if you used some color control. Try program #10.
  570.  
  571.             /* program #10 */
  572.             #include <magic.h>
  573.             #include <conio.h>
  574.             void main(){
  575.               magic_setup();
  576.               xclear();
  577.               pile("How would you answer this question?");
  578.               dialog(-1,4);
  579.               boxback = WHITE;
  580.               border = LIGHTBLUE;
  581.               boxtext = BLACK;
  582.               shadow = MAGENTA;
  583.               mainback = RED;
  584.               xclear();
  585.               pile("User typed:");
  586.               pile(answer);
  587.               getanykey(-1,12);
  588.             }
  589.  
  590.  
  591.              Program 10 is ugly, but it shows you how  to  change  the
  592.          colors  within  the text box. The colors seem to be used here
  593.          as some sort of variables and they are.  They are defined  in
  594.          the CONIO.H file.  (Use GRAPHICS.H if using older versions of
  595.          Turbo  C.) Boxback, boxtext, shadow, border, and mainback are
  596.          global variables from Magic.  These variables accept a number
  597.          between 0 and 15.  CONIO.H assigns BLACK to 0, BLUE to 1, and
  598.          so on.
  599.  
  600.              If the program didn't work for you,  make sure  that  you
  601.          have "#include"d CONIO.H or  GRAPHICS.H  and  that  you  have
  602.          capitalized the color  names,  and  used  small  letters  for
  603.          mainback, boxtext, etc..
  604.  
  605.              Mainback is the  main  background  color,  and  will  not
  606.          change unless you call xclear() first to clear the screen and
  607.          change  the  background  color.  There  is  another  variable
  608.          called maintext, for use when writing directly to the screen.
  609.          Also  available are bartext and barback for the highlight bar
  610.          in menu().  (more about menu later)
  611.  
  612.               The colors could just as easily have been represented by
  613.          numbers, as in the following example:
  614.  
  615.             /* program #11 */
  616.             #include <magic.h>
  617.             void main(){
  618.               magic_setup();
  619.               xclear();
  620.               pile("How would you answer this question?");
  621.               dialog(-1,4);
  622.               boxback = 15;
  623.               border = 9;
  624.               boxtext = 0;
  625.               shadow = 5;
  626.               mainback = 4;
  627.               xclear();
  628.               pile("User typed:");
  629.               pile(answer);
  630.               getanykey(-1,12);
  631.             }
  632.  
  633.             Notice  that  CONIO.H is not used in this program #11.  It
  634.          was only used to provide the defined colors which  have  been
  635.          replaced with their normal numbers.
  636.  
  637.              With  a  bit  of  experimentation, you will soon discover
  638.          that not all 16 colors are available in all situations.  Only
  639.          the first 8 are available for backgrounds, with the  brighter
  640.          colors reserved for text components.  (In graphics modes, all
  641.          16 are available in all situations.)
  642.  
  643.          Let's  find  out  what all the colors are: Here is a slightly
  644.          more complex program than any we have made so far:
  645.  
  646.               /* program #12 */
  647.               #include <magic.h>
  648.               #include <conio.h>
  649.               #include <stdlib.h>
  650.               void main(){
  651.                  magic_setup();
  652.                  mainback = BLACK;
  653.                  xclear();
  654.                  border = WHITE;
  655.                  boxback = BLACK;
  656.                  centerjustify = 1;
  657.                  pile("Type a number from 0 to 15.");
  658.                  dialog(-1,-1);
  659.                  do {
  660.                     boxtext = atoi(answer);
  661.                     if ((boxtext  < 1) || (boxtext > 15)) boxtext = 15;
  662.                     pile("The current color is");
  663.                     pile(answer);
  664.                     pile("Type a number from 0 to 15");
  665.                     pile("or press [Esc] to exit.");
  666.                     dialog(-1,-1);
  667.                  }
  668.                  while (u != 27);
  669.               }
  670.  
  671.          Program  12  does this: First, the mainback, border color and
  672.          the boxback color are changed  and  the  screen  is  cleared.
  673.          Because  centerjustify  is set to 1, it will cause text to be
  674.          centered in the pop up boxes.
  675.  
  676.             Then a one-line dialog box appears. As soon  as  the  user
  677.          answers  the question in this dialog box, a loop starts.  The
  678.          repeat loop changes the boxtext color to the corresponding to
  679.          what the user typed in the dialog box. Since answer  contains
  680.          the  ASCII  (text)  representation of what the user typed, it
  681.          must be converted to the actual integer.  This is  done  with
  682.          atoi().   Atoi  is  prototyped  in STDLIB.H, and this file is
  683.          included at the top of the program.
  684.  
  685.               Since the only 'seeable' colors range from 1 to  15  (#0
  686.          is  BLACK),  the  line starting with 'if' repairs the boxtext
  687.          number if it not suitable.  Notice that it is a compound  if.
  688.          The  || means "or."  First, the whole expression evaluated by
  689.          if is in parentheses, then each the expression on either side
  690.          of the || is also in parentheses.  At first, writing sensible
  691.          statements containing  ||  (or  &&,  meaning  "and")  can  be
  692.          difficult  or  confusing,  but  with  practice,  it all makes
  693.          sense.
  694.  
  695.             Within the loop a new box pops up containing  three  lines
  696.          of  text written in the color corresponding to the number the
  697.          user typed in the dialog box.
  698.  
  699.             This all repeats until the user presses [Esc],  which,  as
  700.          you  probably  know  is ASCII 27.  You see, dialog() builds a
  701.          string called answer.  It  uses  the  global  variable  u,  a
  702.          single  character  variable,  to  pick  up  each key the user
  703.          presses, and this is why u is checked for the value of #27.
  704.  
  705.          Program 13 will be our  first  program  that  does  something
  706.          useful  in  the real world.  It will produce the square of an
  707.          integer. I know that's not much.  You paid around  $1000  for
  708.          your  computer, but your $5 calculator can do squares, and it
  709.          can even do  it  with  floating  point  numbers,  which  this
  710.          example  can't.  The important thing is, once you learn this,
  711.          you can build on this program.
  712.  
  713.               /* program #13 */
  714.               #include <magic.h>
  715.               #include <stdlib.h>
  716.               #include <stdio.h>
  717.               #include <string.h>
  718.               void main(){
  719.                  int thing;
  720.                  char tempstr[80];
  721.                  magic_setup();
  722.                  xclear();
  723.                  do {
  724.                     pile("Type a number to be squared");
  725.                     pile("or press [Esc] to end program");
  726.                     dialog(-1,-1);
  727.                     if (u != 27) {
  728.                        thing = atoi(answer);
  729.                        thing *= thing;
  730.                        sprintf(answer,"%d",thing);
  731.                        strcpy(tempstr,"The square is ");
  732.                        strcat(tempstr,answer);
  733.                        pile(tempstr);
  734.                        getanykey(-1,-1);
  735.                     }
  736.                  }
  737.                  while (u != 27);
  738.               }
  739.  
  740.              First, you'll notice we've included  four  header  files.
  741.          Each  one  contains prototypes for something in this program.
  742.          Look at the line below main().  It merely declares "thing"  a
  743.          variable  in  which  we can store an integer.  Because  thing
  744.          is  declared  at the start of the main() function, it will be
  745.          accessible throughout the program.  Variables declared at the
  746.          start of the main program are called "global." An  "int"  can
  747.          hold a number between -32,768 and +32,767.  If you are sharp,
  748.          you can see a flaw in this program already. If the user types
  749.          a number greater than 181, resulting in a square greater than
  750.          32,767,  the  program  will  not work properly. C offers many
  751.          ways around this problem.  For instance, instead of "int"  we
  752.          could use "long," a much bigger variable.
  753.  
  754.              The line below that declares "tempstr." This  one  is  an
  755.          array variable which can hold up to 80 characters - otherwise
  756.          known  as  a  "string."  Allowing tempstr to be 80 characters
  757.          long is overdoing it a bit, we could have used  maybe  20  or
  758.          so.   In  a  very large program, you always want to keep your
  759.          global variables small, but in a small program, it  does  not
  760.          matter much.
  761.  
  762.              Then we have a typical do - while loop  which  repeatedly
  763.          asks  a  question until the user presses [Esc] (ASCII 27). If
  764.          the  user  does press [Esc] the block following the "if" does
  765.          not execute.  Otherwise, the string, answer, is converted  to
  766.          the  integer,  thing.   Thing  is squared, and the function()
  767.          sprintf changes the new value of thing back into a string and
  768.          the answer is displayed on the screen.
  769.  
  770.              Look carefully at the line: thing *= thing; If it doesn't
  771.          make sense to you, that's because it is C shorthand. The same
  772.          thing could be expressed as: thing  =  thing  *  thing.  This
  773.          shorthand  can  also  be used with addition (thing += thing),
  774.          subtraction and some other mathematical operations.
  775.              There  are  a  couple  of  new string handling techniques
  776.          here.  Sprintf() is a neat gadget which makes numbers of  all
  777.          sorts  into  strings, but requires some reading to understand
  778.          fully. (look  up  sprintf()  and  printf()  in  your  Borland
  779.          manuals.) Strcat() combines two strings into one.
  780.              Strcpy  might  come  as  a  surprise  to BASIC and PASCAL
  781.          programmers.  In C, because a string is not  a  special  data
  782.          type,  but  simply  an  array  of characters, some things you
  783.          might take for granted will  not  work.   For  instance,  you
  784.          cannot  assign  an  variable number of characters to an array
  785.          which might be a different size simply with an = sign. C does
  786.          provide the library function strcpy() for that however.
  787.  
  788.              Here's another useful program:
  789.  
  790.               /* program #14 */
  791.               #include <magic.h>
  792.               #include <stdlib.h>
  793.               #include <stdio.h>
  794.               #include <string.h>
  795.               void main(){
  796.                  float millimeters;
  797.                  char tempstr[80];
  798.                  magic_setup();
  799.                  xclear();
  800.                  do {
  801.                     pile("Enter a number of inches");
  802.                     pile("or press [Esc] when done");
  803.                     dialog(-1,3);
  804.                     if (u != 27) {
  805.                        millimeters = atoi(answer) * 25.4;
  806.                        sprintf(answer,"%f",millimeters);
  807.                        strcpy(tempstr,"That would be ");
  808.                        strcat(tempstr,answer);
  809.                        strcat(tempstr," millimeters.");
  810.                        pile(tempstr);
  811.                        getanykey(-1,16);
  812.                     }  /* end of if block */
  813.                  }  /* end of do block */
  814.                  while (u != 27);
  815.               }
  816.  
  817.  
  818.              You'll notice in the seventh line that were are declaring
  819.          a  variable  of  type  "float." This means floating point and
  820.          must be used because the result of multiplication by 25.4  is
  821.          not usually going to be an integer.  But this program looks a
  822.          bit messy.  What are all those digits doing  in  the  answer?
  823.          Lets fix it to truncate the answer to an integer:
  824.  
  825.               /* program #15 */
  826.               #include <magic.h>
  827.               #include <stdlib.h>
  828.               #include <stdio.h>
  829.               #include <string.h>
  830.               void main(){
  831.                  float millimeters;
  832.                  char tempstr[80];
  833.                  magic_setup();
  834.                  xclear();
  835.                  do {
  836.                     pile("Enter a number of inches");
  837.                     pile("or press [Esc] when done");
  838.                     dialog(-1,3);
  839.                     if (u != 27) {
  840.                        millimeters = atof(answer) * 25.4;
  841.                        sprintf(answer,"%0.0f",millimeters);
  842.                        strcpy(tempstr,"That would be ");
  843.                        strcat(tempstr,answer);
  844.                        strcat(tempstr," millimeters.");
  845.                        pile(tempstr);
  846.                        getanykey(-1,16);
  847.                     }  /* end of if block */
  848.                  }  /* end of do block*/
  849.                  while (u != 27);
  850.               }
  851.  
  852.              The trick is in the sprintf() line.  This now has a width
  853.          and  precision  specifier,  and the program now truncates the
  854.          answer  to  show  an  integer  answer.   There  are   several
  855.          variations   available  in  outputting  strings  representing
  856.          numbers ranging from scientific notation to specific  numbers
  857.          of  leading  and  trailing zeroes or significant digits.  For
  858.          more information, see your Borland  Library  Reference  book.
  859.          Look up printf() and sprintf().
  860.  
  861.               Program  16  converts  Dupers from the imaginary country
  862.          Xanopieland to United States Dollars.
  863.  
  864.               /* program #16 */
  865.               #include <magic.h>
  866.               #include <string.h>
  867.               #include <stdlib.h>
  868.               #include <stdio.h>
  869.               #define CONVERSION 0.7143
  870.               void main(){
  871.                  float dollars;
  872.                  char tempstr[20];
  873.                  magic_setup();
  874.                  xclear();
  875.                  centerjustify = 1;
  876.                  strcpy(sent[1],"How many Dupers?");
  877.                  dialog(-1,-1);
  878.                  dollars = atof(answer) * CONVERSION;
  879.                  sprintf(tempstr,"%0.2f",dollars);
  880.                  strcat(sent[3],"$");
  881.                  strcat(sent[3],tempstr);
  882.                  strcpy(sent[1],"You own this much Xanopieland money:");
  883.                    /* notice that sent[3] is assigned above sent[1] */
  884.                  strcpy(sent[5],"Press any key to end program...");
  885.                  getanykey(-1,-1);
  886.               }
  887.  
  888.              This program shows several new  features.  In  the  sixth
  889.          line  is "#define" which simply allows the programmer to type
  890.          the CONVERSION anywhere in the program and the compiler  will
  891.          take  it  to  mean  0.7143.  This  is  very  useful  in large
  892.          programs.  Instead of trying to remember  0.7143  every  time
  893.          you need it, you can simply type CONVERSION  in  your  source
  894.          code.   Also, let's say you revise the program next year when
  895.          the conversion ratio advances to 0.7224.  You  simply  change
  896.          your  code  in  one  place,  but the proper conversion occurs
  897.          throughout your program.  And, of course, it can be easier to
  898.          understand complicated code when you have used clear meanings
  899.          in your #defines.
  900.  
  901.             Look  at the "How many Dupers?" line.  Notice that instead
  902.          of pile(), we used strcpy() and the  variable  "sent[1]."  As
  903.          you  may remember, "sent" is a two dimensional array which is
  904.          declared in the file MAGIC.H as "sent[46][81]".  This  allows
  905.          you  to  make a pile() of up to 46 separate sent(ences) up to
  906.          80 characters long each.  (C assigns an ASCII #0 to  the  end
  907.          of  character  arrays,  meaning  you need room for one extra,
  908.          hence the [81].)
  909.  
  910.              Pile() is nice because you don't have to  keep  track  of
  911.          which  sent[]  you are using, but sometimes manual control is
  912.          useful.
  913.  
  914.              The sprintf() line uses a precision  specifier  to  cause
  915.          the  output of the dollar amount to show two positions to the
  916.          right of the decimal point.  Nothing else would look sensible
  917.          when converting to dollars  and  cents.  Who  ever  heard  of
  918.          $12.3, or $12.3700000?
  919.  
  920.              And finally, you will see that the sent[]s are  built  up
  921.          out   of  order.  And why not?  This could be easier for you,
  922.          the programmer, but the final  result  will  look  the  same.
  923.          This  is  something  you  could  not  do  if you used pile().
  924.          Also, you'll  notice  that  sent[2]  and  sent[4]  are  never
  925.          affected.   They  started  out  as  blank  lines, and in this
  926.          program we'll leave them that way.
  927.  
  928.              Let's make one more improvement.  In program  #17,  we'll
  929.          straighten  out  the way Dupers can be entered.  The standard
  930.          dialog box is as wide as the widest sent[] and therefore  the
  931.          answer  can  be that long. What if you want to limit the user
  932.          to a 4-digit answer, for instance?  The  following  technique
  933.          also works well for use with filling in database forms:
  934.  
  935.               /* program #17 */
  936.               #include <magic.h>
  937.               #include <string.h>
  938.               #include <stdlib.h>
  939.               #include <stdio.h>
  940.               #include <conio.h>
  941.               #define CONVERSION 0.7143
  942.               void main(){
  943.                  float dollars;
  944.                  char tempstr[20];
  945.                  magic_setup();
  946.                  xclear();
  947.                  centerjustify = 1;
  948.                  strcpy(sent[1],"How many Dupers?");
  949.                  strcpy(sent[2]," ");
  950.                  pop(-1,-1);
  951.                  textcolor(boxtext);
  952.                  textbackground(boxback);
  953.                  xreadln(38,12,4);
  954.                  restore();
  955.                  dollars = atof(answer) * CONVERSION;
  956.                  sprintf(tempstr,"%0.2f",dollars);
  957.                  strcat(sent[3],"$");
  958.                  strcat(sent[3],tempstr);
  959.                  strcpy(sent[1],"You own this much Xanopieland money:");
  960.                  strcpy(sent[5],"Press any key to end program...");
  961.                  getanykey(-1,-1);
  962.               }
  963.  
  964.  
  965.              Can  you  spot  the  differences?   This program does not
  966.          depend on dialog().  Instead, we pop up a box  with  "pop(),"
  967.          which  is  a  simple  function  that  remembers what's on the
  968.          screen,  then puts a box on the screen.  Since pop() will use
  969.          only as many sent[]s as have text, sent[2] is  "  ",  or  one
  970.          blank, so it will be included in pop()'s box.  This will give
  971.          the user a line within the box on which to type the answer.
  972.  
  973.             Then the current text color and background color  are  set
  974.          to  the same as the colors within the box, so that xreadln(),
  975.          will work in the proper colors. Xreadln() is like the  gets()
  976.          function,  or  the  Turbo  Pascal  readln procedure, but with
  977.          three differences.  Xreadln()  accepts  mouse  control  (left
  978.          mouse  button  is  like  pressing [Enter] and right button is
  979.          like [Esc]), Xreadln() requires two integers to designate the
  980.          screen coordinates at which it will echo the  text  typed  by
  981.          the  user, and a third integer which limits how long a string
  982.          the user is allowed to type.
  983.  
  984.              Dialog()  knows  when  the user is done, and restores the
  985.          screen and disappears, but pop() doesn't know what is wanted,
  986.          so stays on the screen until a specific  call  to  restore(),
  987.          which wipes it out and replaces the previous screen image.
  988.  
  989.              Near the top of the program you may also note we've added
  990.          "#include  <conio.h>,  the header file where names for colors
  991.          are defined.  (With older Turbo C compilers, replace  CONIO.H
  992.          with GRAPHICS.H.)
  993.  
  994.              Program   #18  shows  many  new  techniques.  It  is  the
  995.          Universal Money Converter.  For simplicity,  only  the  first
  996.          menu  entry  has  a a function installed. Run this program to
  997.          see what it does, then study the source code to  see  how  it
  998.          does  it.   From  a practical point of view, you can see that
  999.          with modifications, this could be used for  real  money  from
  1000.          real  countries.   For that matter, the same program could be
  1001.          modified for many purposes.  How  about  a  universal  metric
  1002.          converter that converts lengths, weights, temperatures, etc?
  1003.  
  1004.             (NOTE:  When  I  first roughed out this tutorial, I got to
  1005.          thinking about the previous sentence, and an idea  was  born.
  1006.          It  is  now  complete  and  being  distributed  as shareware.
  1007.          Perhaps you've seen it, THE  UNIVERSAL  CONVERTER.  This  new
  1008.          program  performs  over  600 useful calculations and it makes
  1009.          extensive use of the Magic library!)
  1010.  
  1011.               /* program #18 */
  1012.               #include <magic.h>
  1013.               #include <string.h>
  1014.               #include <stdlib.h>
  1015.               #include <stdio.h>
  1016.               #include <conio.h>
  1017.               #define CONVERSION 0.7143
  1018.               void xano(void);              /*** 1 ***/
  1019.               float dollars;
  1020.               char tempstr[20];
  1021.               void main(){
  1022.                  magic_setup();
  1023.                  xclear();
  1024.                  centerjustify = 1;
  1025.                  pile("Universal Money Converter");
  1026.                  pop(-1,2);
  1027.                  clearsents();         /*** 2 ***/
  1028.                  mc = 1;               /*** 3 ***/
  1029.                  do {
  1030.                     pile("Xanopieland");
  1031.                     pile("Braze Island");
  1032.                     pile("Nomania");
  1033.                     pile("Grazille");
  1034.                     pile("Exit to Dos");
  1035.                     menu(-1,-1);       /*** 4 ***/
  1036.                     if (u == 13) {
  1037.                        if (mc == 1) xano();   /*** 5 ***/
  1038.                    /*  if (mc == 2) braze();
  1039.                        if (mc == 3) nomania();
  1040.                        if (mc == 4) Grazille();   *** 6 *** */
  1041.                     }
  1042.                  }
  1043.                  while (!((u == 13) && (mc == 5))); /*** 7 ***/
  1044.                  cleanup();   /*** 8 ***/
  1045.               }
  1046.  
  1047.               void xano(void){          /*** 9 ***/
  1048.                  pile("How many Xanopieland Dupers?");
  1049.                  pile(" "); //must be at least one char  *** 10 ***
  1050.                  pop(-1,-1);
  1051.                  textcolor(boxtext);
  1052.                  textbackground(boxback);
  1053.                  xreadln(38,12,4);
  1054.                  restore();
  1055.                  dollars = atof(answer) * CONVERSION;
  1056.                  sprintf(tempstr,"%0.2f",dollars);
  1057.                  strcat(sent[3],"$");
  1058.                  strcat(sent[3],tempstr);
  1059.                  strcpy(sent[1],"You own this much Xanopieland money:");
  1060.                  getanykey(-1,-1);
  1061.               } // end of xano function
  1062.  
  1063.              Well,  I've  got  some  explaining to do this time.  I've
  1064.          marked the 10 changes in this program with  comments  so  you
  1065.          can follow all this:
  1066.  
  1067.              The most noticeable change is the use of  a  sub-routine.
  1068.          For  the  first time you define your own function (other than
  1069.          main()).  At Note One,  we  have  the  "declaration"  of  the
  1070.          xano()  function.   This  prototype merely tells the compiler
  1071.          to expect the function and to know what information might  be
  1072.          passed to/from it.  In this case, nothing is passed to it, so
  1073.          the parentheses contain the word "void".  Also, nothing  will
  1074.          come from it, so it is also preceded by the word  "void."  By
  1075.          now,  you've probably looked at a couple of header (.H) files
  1076.          and recognize function declarations.   This  one  could  also
  1077.          have been put in a header file, but there is no need, because
  1078.          there  are  no other parts of the program in other files that
  1079.          are going to use it.
  1080.  
  1081.              Later,  in the body of the program the xano() function is
  1082.          "defined."  So, to review,  first we  "declare"  a  function,
  1083.          later we "define" it.
  1084.  
  1085.              At  Note 2, we've popped a box onto the screen. Remember,
  1086.          that pop() is less sophisticated than other functions such as
  1087.          getanykey() or dialog()  which  use  it.   These  also  clean
  1088.          themselves  off  the  screen  when they are done.  Pop() does
  1089.          not. It leaves itself on the screen and  leaves  the  sent[]s
  1090.          that  were  used,  full  of  text.  Clearsents()  is  a Magic
  1091.          function which restores all the sent[]s to empty  strings  so
  1092.          you can use them again without having old text pop up in your
  1093.          new boxes.
  1094.  
  1095.              We're  about to use a lightbar menu. But before we do, at
  1096.          Note  3,  we  ought  to  decide  which  menu  item  will   be
  1097.          highlighted when the menu first appears.
  1098.  
  1099.              At  Note  4,  we  actually  call the menu() function.  It
  1100.          starts like pop(), but lights up the sent[] corresponding  to
  1101.          the  number "mc." Using the mouse or arrow keys, the user can
  1102.          select an item  then  press  [Enter]  or  [Esc].   When  that
  1103.          happens, the menu is done, and erases itself from the screen,
  1104.          leaving behind a value in "mc" related to the menu item which
  1105.          was highlighted when the user was done.
  1106.  
  1107.              And  at Note 5, we have a series of "if"s.  In this case,
  1108.          most of them are commented out, because we  haven't  actually
  1109.          built  the  whole program.  But, if the user quits the menu()
  1110.          with 1 highlighted, then we do have function - xano().
  1111.  
  1112.             Notice  that  we  use  two  equal  signs when checking for
  1113.          equality. This is different  than  assigning  a  value  to  a
  1114.          variable with one equal sign.  If we were to do this:
  1115.  
  1116.              if (mc = 2)
  1117.  
  1118.          mc would become 2, but with == we harmlessly check it.
  1119.  
  1120.              As  I said, the other options are commented out (Note 6),
  1121.          but if the user selects menu item  1,  then  control  of  the
  1122.          program is given to the function xano().
  1123.  
  1124.              Skipping  ahead  to  Note #9:  It doesn't matter where in
  1125.          the source code xano() is defined, as long  as  it  has  been
  1126.          declared   in   advance.   Some  programmers  will  put  some
  1127.          functions ahead of the main() function, and others  will  put
  1128.          it  below.  This seems unusual to Pascal programmers who must
  1129.          always list sub-routines above routines which call them.
  1130.  
  1131.              At  Note  9,  you'll  see a new kind of comment.  This is
  1132.          unique to C++, and will not work in standard C  source  code.
  1133.          If  you  have an older C compiler, change these to the normal
  1134.          kind of comments with /* and */. When the  marker  //  occurs
  1135.          on  a  line,  everything  to the right of that marker will be
  1136.          ignored by the compiler.
  1137.  
  1138.              Now,  back  up  to Note 7.  What a weird statement!  What
  1139.          we're doing here is repeating the whole menu  sequence  until
  1140.          the  user  has  highlighted  menu  item 5 ("Exit to Dos") AND
  1141.          pressed [Enter].  C programmers do things like  this  -  with
  1142.          cryptic uses of the !  (not) operator and nested parentheses.
  1143.          The  best  way  to unravel a thing like this is to read it in
  1144.          the same  sequence  as  the  compiler.   Expressions  in  the
  1145.          innermost parentheses are evaluated first.  If you still find
  1146.          it  hard  to  read, sometimes you can put extra spaces on the
  1147.          line to break the expression into bite-size groups,  or  even
  1148.          cut it up into several lines.
  1149.  
  1150.              And  finally,  at  Note  8,  we  have  a  new   function,
  1151.          cleanup(),  which, much like it sounds, cleans everything up,
  1152.          freeing memory, clearing the screen and a few  other  chores.
  1153.          When  cleanup() is done, it stops the program and returns the
  1154.          user to DOS.
  1155.  
  1156.          Program   #19  adds  a  switch  statement. This cleans up the
  1157.          multiple "if" statements, but has little  overall  effect  on
  1158.          the  program, other  than  simplicity  in  the  source  code.
  1159.          Notice  the  use of "break" after all but the last comparison
  1160.          in  the  switch.  This  allows  us  to exit the switch once a
  1161.          match has been found.
  1162.              Then  we've  added another switch statement, allowing the
  1163.          end user to press any key corresponding to the  first  letter
  1164.          of  a  menu  item,  thereby  executing the menu choice with a
  1165.          single keystroke.
  1166.  
  1167.               /* program #19 */
  1168.               #include <magic.h>
  1169.               #include <string.h>
  1170.               #include <stdlib.h>
  1171.               #include <stdio.h>
  1172.               #include <conio.h>
  1173.               #include <ctype.h>
  1174.               #define CONVERSION 0.7143
  1175.               void xano(void);
  1176.               float dollars;
  1177.               char tempstr[20];
  1178.               void main(){
  1179.                  magic_setup();
  1180.                  xclear();
  1181.                  centerjustify = 1;
  1182.                  pile("Universal Money Converter");
  1183.                  pop(25,2);
  1184.                  clearsents();
  1185.                  mc = 1;
  1186.                  do {
  1187.                     pile("Xanopieland");
  1188.                     pile("Braze Island");
  1189.                     pile("Nomania");
  1190.                     pile("Grazille");
  1191.                     pile("Exit to Dos");
  1192.                     menu(-1,-1);
  1193.                     switch (toupper(u)) {
  1194.                        case 'X' : xano(); u = 126; break;
  1195.                        // case 'B' : braze(); u = 126; break;
  1196.                        // case 'N' : nomania(); u = 126; break;
  1197.                        // case 'G' : Grazille(); u = 126; break;
  1198.                        case 'E' : mc = 5; u = 13;
  1199.                     }
  1200.                     if (u == 13) switch (mc) {
  1201.                        case 1 : xano(); break;
  1202.                        //  case 2 : braze(); break;
  1203.                        //    case 3 : nomania(); break;
  1204.                        //    case 4 : Grazille();
  1205.                     }
  1206.                  }
  1207.                  while (!((u == 13) && (mc == 5)));
  1208.                  cleanup();
  1209.               }
  1210.  
  1211.               void xano(void){
  1212.                  pile("How many Xanopieland Dupers?");
  1213.                  pile(" "); //must be at least one char
  1214.                  pop(-1,-1);
  1215.                  textcolor(boxtext);
  1216.                  textbackground(boxback);
  1217.                  xreadln(38,12,4);
  1218.                  restore();
  1219.                  dollars = atof(answer) * CONVERSION;
  1220.                  sprintf(tempstr,"%0.2f",dollars);
  1221.                  strcat(sent[3],"$");
  1222.                  strcat(sent[3],tempstr);
  1223.                  strcpy(sent[1],"You own this much Xanopieland money:");
  1224.                  getanykey(-1,-1);
  1225.               } // end of xano function
  1226.  
  1227.              You see, the  whole  block  which  calls  pile()  several
  1228.          times, then menu(), then asseses the user input, is repeated,
  1229.          because  if the user presses any key except an arrow key, the
  1230.          menu considers itself done and  disappears.  As  the  program
  1231.          falls  through,  if  the  key  the  user  pressed  is not one
  1232.          examined by the switch statement, or [Enter], then  the  menu
  1233.          simply reappears, over and over again, until the user presses
  1234.          [Enter] or the first letter of something on the menu.
  1235.  
  1236.             Notice the new way  of  commenting  out  the  non-existent
  1237.          functions.
  1238.  
  1239.              There are opportunities for bugs here. You want  to  make
  1240.          sure  u  ==  13  (the  [Enter] key) before allowing the first
  1241.          "switch" to execute, because otherwise, a  function  may  run
  1242.          twice  in  a  row  if the user presses a character key, first
  1243.          when mc = whatever, then then when u = 'whatever'. Also  make
  1244.          sure to put the second case characters in single quote marks.
  1245.          And  last,  notice  the  "toupper(u)."  Without this the user
  1246.          would have to press the shift key to get the desired  result.
  1247.          Toupper()  converts  whatever  is  in  the  variable u into a
  1248.          capital letter.
  1249.  
  1250.                 THIS TUTORIAL IS CONTINUED IN THE FILE: TUTOR.2
  1251.  
  1252.          (This  file  is split into two parts in case you are using an
  1253.          older Turbo C compiler, which does not support  files  larger
  1254.          than 64k.)
  1255.  
  1256.