home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / msj / msj1.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  205.1 KB  |  4,748 lines

  1.  Microsoft Systems Journal Volume 1
  2.  
  3.  ────────────────────────────────────────────────────────────────────────────
  4.  
  5.  Vol. 1 No. 1 Table of Contents
  6.  
  7.  ────────────────────────────────────────────────────────────────────────────
  8.  
  9.  Advanced Reuter Terminal Gives Traders Windows on Financial World
  10.  
  11.  The Advanced Reuter Terminal (ART), a dedicated hardware and software system
  12.  that runs under Microsoft(R) Windows, enables currency traders to view and
  13.  analyze up-to-the-minute financial data. An exclusive interview reveals the
  14.  developing team's experiences.
  15.  
  16.  
  17.  DDE: A Public Protocol for Advanced Application Linkages
  18.  
  19.  An extension of Microsoft Windows data exchange facilities, the Dynamic
  20.  Data Exchange (DDE) protocol allows developers to establish sophisticated
  21.  application linkages, ranging from automatic updating of documents to
  22.  processing of real-time data.
  23.  
  24.  
  25.  New Intel Graphics Coprocessor Makes Windows Sparkle
  26.  
  27.  Intel has a new way to boost the display speed of Windows and other
  28.  graphics applications: the 82786, a high-powered coprocessor that
  29.  improves workstation performance, moving graphics functions from
  30.  software to high-speed hardware.
  31.  
  32.  
  33.  TI's Programmable Graphics Processor Perks Up PC Pixels
  34.  
  35.  The first true graphics microprocessor, Texas Instruments' 32-bit TMS34010
  36.  executes at 6 MIPS, addresses up to 4 gigabytes of memory, supports displays
  37.  of up to 64K by 64K pixels, and includes high-speed pixel-processing
  38.  instructions.
  39.  
  40.  
  41.  Latest Dialog Editor Speeds Windows Application Development
  42.  
  43.  An improved version of the Microsoft Windows Dialog Editor (supplied with
  44.  the software development kit) simplifies designing and testing a dialog
  45.  box──one of the key elements of a Windows application. Here's how to use it
  46.  and what to watch out for.
  47.  
  48.  
  49.  Ask Dr. Bob
  50.  
  51.  
  52.  EDITOR'S NOTE
  53.  
  54.  This first issue of the Microsoft Systems Journal is devoted in its entirety
  55.  to Microsoft Windows operating environment, Microsoft's most important
  56.  system software product since MS-DOS(R).
  57.  
  58.  Windows has encountered remarkable success both as a retail product and as
  59.  a development environment since its release last November. While much of
  60.  the product's initial popularity can be attributed to its flexibility as
  61.  a "switcher" for traditional applications and the included sample
  62.  applications, its ultimate success will depend on the acceptance of native
  63.  Widows applications.
  64.  
  65.  Reuters' ART. As a definitive example of the capabilities of Microsoft
  66.  Windows and its flexibility to serve particular user interface designs,
  67.  we examine the Advanced Reuter Terminal (ART), the most sophisticated
  68.  Windows application to date. A superb example of design and coding
  69.  craftsmanship, the ART would be worth featuring even if it were not based
  70.  on Windows.
  71.  
  72.  We also present profiles of two graphics processors that will have a
  73.  significant impact on future graphics systems: the Intel 82786 and the
  74.  Texas Instruments TMS34010. And we take a look at DDE, a new standard
  75.  for interprogram data exchange, as well as examine the improved Dialog
  76.  editor. In addition, Dr. Bob tackles some questions about Windows from
  77.  developers. In sum, we hope to present a developer's view of Microsoft
  78.  Windows.
  79.  
  80.  Future Issues. In future issues we will focus on other areas of interest to
  81.  developers, including C programming, device drivers, extended and expanded
  82.  memory, debuggers, code portability, and the inside view of MS-DOS and
  83.  Microsoft XENIX(R). We will tackle the subjects that interest serious
  84.  developers most──from user interface design to guidelines for writing
  85.  ternimate-and-stay-resident programs. Our aim is to confront the real
  86.  issues confronting serious developers.
  87.  
  88.  Write to Us. We invite you to write to us, to subscribe, and equally
  89.  important, to tell us what you think we should include in the Journal.
  90.  Beginning in January 1987, our issues will expand to full size, more than
  91.  twice the length of this special issue.
  92.  
  93.  We hope the Journal will become one of the most important publications you
  94.  receive.──Ed.
  95.  
  96.  JONATHAN D. LAZARUS
  97.  Editor
  98.  
  99.  MICHAEL LONGACRE
  100.  Design
  101.  
  102.  Copyright(C) 1986 Microsoft Corporation. All rights reserved; reproduction
  103.  in part or in whole without permission is prohibited.
  104.  
  105.  Microsoft Systems Journal is published every other month by Microsoft
  106.  Corporation, 16011 NE 36th Way, Box 97017, Redmond, WA 98073-9717. Officers:
  107.  William H. Gates, III, Chairman of the Board and Chief Executive Officer;
  108.  Jon Shirley, President and Chief Operating Officer; Francis J. Gaudette,
  109.  Treasurer; William Neukom, Secretary.
  110.  
  111.  Microsoft Corporation assumes no liability for any damages resulting from
  112.  the use of the information contained herein.
  113.  
  114.  Microsoft, the Microsoft logo, MS-DOS, and XENIS are registered trademarks
  115.  of Microsoft Corporation. Intel is a registered trademark of Intel
  116.  Corporation. IBM is a registered trademark of International Business
  117.  Machines Corporation. Lotus is a registered trademark of Lotus
  118.  Development Corporation. Texas Instruments is a registered trademark of
  119.  Texas Instruments, Inc.
  120.  
  121.  ────────────────────────────────────────────────────────────────────────────
  122.  
  123.  ART Showcases Microsoft Windows
  124.  
  125.  MSJ Interview
  126.  
  127.  One of the finest examples to date of software running under Microsoft
  128.  Windows is a product called the ART, the Advanced Reuter Terminal. When you
  129.  think of Reuters, you think of news, but to currency traders who buy and
  130.  sell millions of dollars each day, Reuters means finance. Its financial
  131.  information service is the lifeblood of their trade, providing the timely
  132.  and accurate information on which their success depends. The ART is a
  133.  complete hardware and software solution that supplies a high-resolution
  134.  color monitor and features multiple windows showing text and graphics
  135.  displays of up-to-the-minute financial information. It has the equivalent
  136.  display capacity of ten of the previous Reuter Monitor terminals, which
  137.  limited users to viewing information on a monochrome text display. What's
  138.  more, ART users can perform data analyses by choosing options from pull-down
  139.  menus.
  140.  
  141.  
  142.  ART's Configuration
  143.  
  144.  ART hardware consists of an 80286-based (PC-AT compatible) NCR computer with
  145.  1.5 megabytes of RAM, a 20-megabyte hard disk, high-resolution (EGA)
  146.  display, 1200-baud modem, Reuters proprietary communications board, a
  147.  Reuters programmable keyboard, and, of course, a mouse.
  148.  
  149.  But the heart of the system is the Windows-based software. Developed by the
  150.  Reuters office in London, it offers such capabilities as real-time graphics,
  151.  user-defined montage pages, limit and news watching, and graphics analysis.
  152.  Real-time graphics are made possible by calling up a graphics window and
  153.  linking it to a particular currency value displayed on the screen. Each time
  154.  the value of the currency changes, a new tick is added to the graph.
  155.  
  156.  The ART provides automatic limit watching, using dialogs in which users
  157.  enter upper and lower limits for any currency displayed on a stored page.
  158.  When limits are broken, the ART gives audible and visible signals allowing a
  159.  dealer to react instantly. News watching works the same way; the ART
  160.  immediately alerts the user when the preselected word or phrase appears in a
  161.  headline. In sum, the ART system allows the user to determine the screen's
  162.  content and layout, an asset to active traders.
  163.  
  164.  To find out about some of the background development of the ART, we spoke
  165.  with Paul Lucke, manager of the Reuters micro section in London, and asked
  166.  him some questions about developing a product under Microsoft Windows.
  167.  
  168.  To find out about some of the background and development of the ART, we
  169.  spoke with Paul Lucke, manager of the Reuters micro section in London, and
  170.  asked him some questions about developing a product under Microsoft Windows
  171.  operating environment.
  172.  
  173.  
  174.  Why Windows?
  175.  
  176.  MSJ: Why did you choose Microsoft Windows rather than some of the other
  177.  graphics environments such as GEM?
  178.  
  179.  REUTERS: Clearly we wanted a bit-mapped graphics display because a major
  180.  component of the system is drawing graphs and performing analytical studies.
  181.  That cut out the non-bit-mapped graphics systems, which brings you down to
  182.  Windows and GEM.
  183.  
  184.  We started out by buying a Laser (computer) as soon as they arrived on the
  185.  scene. At the time it looked as if that was the way user interfaces were
  186.  going. After we did some development work on the Laser, we saw the IBM PC
  187.  running Microsoft Windows and figured that this particular combination was
  188.  the way to go. We felt that Microsoft had the makings of a market leader, so
  189.  we took Windows on as an alpha test site and put up some experimental demos
  190.  using Reuters data. Our objective was to turn data into information, and we
  191.  believed that Microsoft Windows was the right vehicle for doing so.
  192.  
  193.  Clearly, when GEM came out, we had to consider it as well, particularly
  194.  because an alpha release of any product has its fair share of bugs. But we
  195.  found GEM's method of window interfacing, at least at the time we reviewed
  196.  it, to be inferior to Microsoft's tiled windows concept.
  197.  
  198.  Think of it as two kinds of desks: the untidy desk and the tidy desk. Tidy
  199.  is the way we wanted to go. When information changes, traders need to see it
  200.  as it happens. They can't afford to have it obscured underneath another
  201.  window. So any kind of obscuring device must be something temporary, like
  202.  pull-down menus, which disappear once you select an item.
  203.  
  204.  Also, some of the simple things were better implemented in Windows──like the
  205.  accuracy of the pointing. We just found it easier to use than GEM.
  206.  
  207.  
  208.  Microsoft Support
  209.  
  210.  MSJ: How did you find Microsoft's support?
  211.  
  212.  REUTERS: We took care only to go to our contact at Microsoft when we were
  213.  dealing with a problem that was clearly a fault of the product. That way we
  214.  were able to encourage him to listen to us. And he offered good support on a
  215.  one-to-one basis.
  216.  
  217.  Clearly, something like the DIAL system would have been useful, had it been
  218.  available. We have a North American operation that has a DIAL account, and
  219.  users report that it has recently improved considerably. One of the things
  220.  that's been particularly useful is watching the bulletin board as other
  221.  people's problems are discussed.
  222.  
  223.  MSJ: You depend on having information updated instantly. Did you run into
  224.  any problems when you were working with your implementation?
  225.  
  226.  REUTERS: We have to go through a lot of tricks to design the system in such
  227.  a way that the time-critical aspects of the application are catered to.
  228.  There must be an easier way.
  229.  
  230.  What's also a major problem is 640K restrictions. It's imperative that we're
  231.  able to access lots of memory. For large data areas you can do something
  232.  with RAM disks, but we really need MS-DOS 5.0. It seems to be receding into
  233.  the far distance; every quarter it seems to slip a quarter. The whole point
  234.  of a windows environment is to have multiple simultaneous applications
  235.  running, and if memory limitations prevent loading more than two
  236.  applications, that's really bad news.
  237.  
  238.  If Microsoft is going to keep faith with the developers of Windows
  239.  applications, it has to come out with MS-DOS 5.0──or at least a
  240.  mechanism for making large chunks of executable memory available.
  241.  
  242.  
  243.  Cautious Interest
  244.  
  245.  MSJ: You mentioned that in the course of developing your product you had to
  246.  come up with some tricks to perform cerain tasks. Do you ever share this
  247.  information with other developers? Would, for instance, a user group benefit
  248.  from your experiences, or would you rather keep that kind of information to
  249.  yourself?
  250.  
  251.  REUTERS: I'd characterize our attitude as "cautious interest." You must
  252.  understand that the major users of Microsoft Windows in the U.K. are either
  253.  our customers or competitors. And so, while we will certainly chat about our
  254.  experiences and exchange information on bugs and so on, we would not be
  255.  quite as forthcoming as perhaps a company that was trying to advertise
  256.  itself.
  257.  
  258.  MSJ: The keyboard used with ART is quite different from the normal PC-style
  259.  keyboard. Tell us something about it.
  260.  
  261.  REUTERS: The keyboard uses an 80186, which gives it more processing power
  262.  than a PC. It is completely programmable, which we need since we have many
  263.  different installations, which drive different kinds of terminal keyboards.
  264.  The keyboard we use lets us emulate any of these.
  265.  
  266.  MSJ: What is the function of your proprietary communications board?
  267.  
  268.  REUTERS: The board has its own processor and handles the communications
  269.  link, which is a multi-drop line protocol. The board also de-couples
  270.  communications processing from Windows processing and does page-caching.
  271.  Information pages are put into cache memory so that dealers will get a
  272.  quicker response when changing pages.
  273.  
  274.  MSJ: Are you looking at any of the new graphics chips like the Intel 82786
  275.  and TI34010 to enhance the system?
  276.  
  277.  REUTERS: Yes. We've developed a super-high-resolution graphics board that
  278.  uses the Intel chip, and we are waiting for Intel to release the final
  279.  version. We were also impressed with the TI chip, and we're looking at it
  280.  seriously. We'll use the one that's up and running at board production
  281.  time.
  282.  
  283.  MSJ: Your windows work a little differently from the typical Microsoft
  284.  windows. Why did you choose to have a common menu bar?
  285.  
  286.  REUTERS: We eliminated the menus because we didn't want to waste any
  287.  precious screen space, and found that it simplified usage.
  288.  
  289.  
  290.  Mouse-o-phobia?
  291.  
  292.  MSJ: What has been the reaction of dealers to the mouse?
  293.  
  294.  REUTERS: We've had a positive response at demonstrations we've given. No one
  295.  who has used it has ever let it go. We have found, however, that some people
  296.  take time to adjust to pointing with it──as long as two to three hours.
  297.  
  298.  MSJ: Now that you've had considerable experience with it, what is your
  299.  overall impression of the Microsoft Windows environment?
  300.  
  301.  REUTERS: Windows is an extremely powerful set of tools. We could not have
  302.  brought to market a product of the quality of the ART in such a relatively
  303.  short time frame without it. The learning curve is reasonably short, too. An
  304.  experienced C programmer will take only a matter of days to get a simple
  305.  application running. And in perhaps four to five weeks he'll become fully
  306.  productive, partly as a result of support within the team.
  307.  
  308.  A large number of people on the team now know how to use Microsoft Windows.
  309.  Also, the examples of working systems make the learning curve easier. From
  310.  that point of view, I'm convinced Windows is the right choice for Reuters.
  311.  As an environment for running third-party applications, Windows might not be
  312.  the ideal choice, but we're using it for specialized applications within the
  313.  financial marketplace.
  314.  
  315.  The thing that makes it so useful is its ability to adapt quickly to
  316.  different high-resolution screens. For example, we pulled in a Wyse PC with
  317.  a 1280 by 786 monochrome screen. In a couple of hours we got the whole
  318.  system running in a totally different resolution, different character sets,
  319.  different fonts and looking nice. If you've got a Windows driver for your
  320.  display, you can port your application onto it and make use of the
  321.  facilities provided by that display. It's that flexible.
  322.  
  323.  MSJ: Is there anything else?
  324.  
  325.  REUTERS: One of the most imaginative ideas I've seen yet is that Microsoft
  326.  has been advertising in a specialist magazine, called DOT.EXE. It's targeted
  327.  at ISVs and offers, for four hundred pounds, a one-day course in Microsoft
  328.  Windows, which includes an ISV tool kit and a Microsoft Mouse. We'll
  329.  probably be plugging our new people into it.
  330.  
  331.  The credit for developing ART should go to a team of high-powered
  332.  programmers led by Chris Oswald. They are the ones who deserve the credit
  333.  for doing an incredible job.
  334.  
  335.  ────────────────────────────────────────────────────────────────────────────
  336.  
  337.  Dynamic Data Exchange Enhances Application Connectivity
  338.  
  339.  Harvey Berger
  340.  
  341.  One of the most valuable benefits of Microsoft Windows is that enables you
  342.  to use a number of application programs in combination to solve a problem.
  343.  With Windows you can transfer text, numbers, or pictures from one
  344.  application to another. A classic example is the ability of Windows to take
  345.  a table or a graph from a spreadsheet program and insert it into a word
  346.  processing document.
  347.  
  348.  The Windows Clipboard is what serves as the intermediate repository for such
  349.  information exchanges among applications. At your direction, information is
  350.  placed on the Clipboard by a CUT or COPY operation in one application and
  351.  then inserted into the context of a second application with a PASTE
  352.  operation.
  353.  
  354.  On the surface the process seems straightforward──a selection, a CUT or
  355.  COPY, and then a PASTE──and manual. But behind the scenes the two
  356.  applications and Windows combine to effect the actual transfer. The donating
  357.  application takes control of the Clipboard and places the selected
  358.  information on it in one or a series of formats. The receiving application
  359.  then selects a format and requests the data from the Clipboard.
  360.  
  361.  In many cases, to save memory and reduce processing overhead, the donating
  362.  applications may defer actually rendering the selected data until another
  363.  applications requests it.
  364.  
  365.  
  366.  A Step Forward
  367.  
  368.  The Clipboard's facilities are quite flexible, but they require manual
  369.  intervention for each transfer, and the Clipboard can hold only one "item"
  370.  at a time. In a multitasking environment like Windows, the need rapidly
  371.  develops for more sophisticated data exchange facilities. Windows Dynamic
  372.  Data Exchange (DDE) is intended to facilitate implementation of more complex
  373.  information transfers than are possible with a single or even multiple
  374.  clipboards.
  375.  
  376.  DDE is a formal, public protocol for data exchange built on Windows
  377.  messaging, and the shared memory facility. DDE is much more an agreement
  378.  among cooperating applications than it is a particular body of code or
  379.  executable routine. It's a special usage of Windows messages.
  380.  
  381.  Windows applications routinely receive messages corresponding to user- and
  382.  system-initiated actions ranging from keystrokes to request to repaint the
  383.  screen. DDE uses a set of formerly reserved message numbers to implement the
  384.  protocol. In the Windows environment any application may send a message to
  385.  any other application, without explicit knowledge of the nature of the other
  386.  application.
  387.  
  388.  DDE is designed to facilitate implementation of a wide variety of data
  389.  exchanges, ranging from simple one-time transfers of selected data to
  390.  automatic parallel transfers of real-time data. Since many DDE relationships
  391.  are likely to be more complicated than those of the Clipboard, DDE is
  392.  described in terms of a server and client applications rather than in terms
  393.  of a donor and a receiver, where a single server may be supplying data to
  394.  many clients and a single client application may be communicating with many
  395.  servers simultaneously.
  396.  
  397.  
  398.  Data Formats
  399.  
  400.  DDE and the Clipboard share a number of common facilities, most notably an
  401.  extensible set of data exchange formats. Initially Microsoft Windows
  402.  recognized a limited set of public formats for data exchange (TEXT, BIT MAP,
  403.  META-FILE, SYLK, DIF, and so forth) and custom formats. Concurrent with the
  404.  announcement of DDE, Microsoft has announced five additional clipboard data
  405.  formats (Rich Text, Table, Sub-Table, WKS, and DBF).
  406.  
  407.  Windows also allows cooperating applications to register custom formats for
  408.  private usage. The new formats allow the economical transfer of data with
  409.  its formatting information.
  410.  
  411.  
  412.  Object Orientation
  413.  
  414.  A key distinction between Clipboard and DDE exchanges is DDE's object
  415.  orientation. The Clipboard is used to transfer a user selection from one
  416.  application to another. Each Clipboard transfer is independent; the sequence
  417.  of transfers corresponds to the sequence of user operations. With DDE each
  418.  transfer consists of an item associated with a "name."
  419.  
  420.  
  421.  Names and Topics
  422.  
  423.  When requesting or supplying data, the names are provided to allow the
  424.  communicating task to identify the source or disposition of the data item.
  425.  Names describe either the location or the contents of a data item. In a
  426.  spreadsheet, each cell has an address (for example, R2C3 for the cell in the
  427.  second row and third column). Some spreadsheets also have named cell ranges
  428.  (R1:4C5, for example, might be named TOTALS). In either case, a natural
  429.  relationship exists between names and data items. With other kinds of
  430.  applications, like word processors, names are likely be to more positionally
  431.  oriented. The DDE protocol requires a name or a positional reference for
  432.  each item to be transferred.
  433.  
  434.  By definition, each name, as recognized by the server, refers uniquely to a
  435.  specific data item. The choice of names and topics are the private concern
  436.  of a server and its clients. Some servers will associate names relevant to a
  437.  given subject with a topic. Client applications typically ask potential
  438.  servers if they recognize (and can supply data about) the topic. Where the
  439.  server's names are in themselves very complete descriptions of data items, a
  440.  sample name may be used as the topic. Servers that define topics should be
  441.  worded carefully to avoid accidental duplication.
  442.  
  443.  
  444.  Applications
  445.  
  446.  In the first example the Clipboard is used to paste a chart into a word
  447.  processing document. With DDE it is possible to construct more complex
  448.  scenarios. In addition to saving the pasted chart, the word processor might
  449.  store the name of the chart, the file name worksheet it was associated with,
  450.  and the file name of the application program. Given that information, the
  451.  word processor could ensure that it had the latest version of the chart.
  452.  
  453.  First the word processor could, after verifying existence of the worksheet
  454.  file, start executing the spreadsheet application, specifying the worksheet
  455.  file name and a DDE startup parameter. Then, using DDE, the word processor
  456.  could request retransfer of the graph. The exact procedures to be used are
  457.  left up to the developers of the respective applications. Microsoft will
  458.  most likely issue guidelines soon for future application development.
  459.  
  460.  
  461.  Chain Reaction
  462.  
  463.  A scenario in which the chart is the result of calculations in a spreadsheet
  464.  is also reasonable to envision. When printing the document, the word
  465.  processor might request the chart from the graphics application, which in
  466.  turn might extract the applicable data from the spreadsheet. The integration
  467.  becomes involved, but the burden moves from the user repeating manual steps
  468.  (which he might forget) to the PC using DDE.
  469.  
  470.  
  471.  DDE Sequences
  472.  
  473.  A sequence of DDE exchanges between a client and a server are referred to as
  474.  sessions.(Figures 2, 3, 4, 5, 7, 8, and 9 show portions of sample
  475.  client and server applications.) A session typically begins with an INQUIRE
  476.  message. A client application sends a WM_DDE_ INQUIRE to every other active
  477.  application (potential server) in the system. The INQUIRE message includes a
  478.  topic or a sample name. If an active server is willing to exchange data
  479.  related to the topic, it in turn responds with a WM_DDE_ ACK message.
  480.  
  481.  After establishing a session, the client and the server exchange messages
  482.  according to the operating rules of the server. Servers may have
  483.  implementation restrictions on the number of clients or the types of
  484.  transfers it will honor. DDE provides eight message types that establish
  485.  transfer protocols.
  486.  
  487.  The terms client and server are largely semantic, since either application
  488.  can send (or receive) any message type. In practice, a given application may
  489.  be functioning as a server to one application and as a client to the same or
  490.  another application.
  491.  
  492.  A simple example of a DDE transfer would consist of the following sequence:
  493.  
  494.    1.  Application One broadcasts an INQUIRE message to those windows in
  495.        search of a server that will discuss CHEMICAL FORMULAS.
  496.  
  497.    2.  APP2, with a database of chemical formulas, responds to APP1 with an
  498.        ACK (acknowledgement) message.
  499.  
  500.    3.  APP1 then sends a REQUEST message specifying WATER as the desired item
  501.        name.
  502.  
  503.    4.  APP2 responds with a text string UPDATE message pointing to WATER=H2O.
  504.  
  505.    5.  APP1 then sends a REQUEST message for SALT.
  506.  
  507.    6.  APP2 responds with an UPDATE message specifying SALT=NaCl.
  508.  
  509.  
  510.  Real-Time Data
  511.  
  512.  DDE was developed in response to the users' need for the coupling of data
  513.  from separate applications. The stock market is another classic example of
  514.  the need for DDE. During trading hours there's a constant flow of data as
  515.  each transaction is processed by the exchanges. Market watchers need to
  516.  filter the data stream and isolate the transactions of interest to them. The
  517.  selected data is then analyzed to determine the required action. One of the
  518.  first demonstrations of DDE modeled this process.
  519.  
  520.  A SignalTM receiver (supplied by Lotus Information Network Corporation)
  521.  offered a continuous feed of stock prices (for up to 600 selected stocks).
  522.  Normally the Signal receiver (connected to a serial port) supplies data to
  523.  special Lotus(R) software. For this demonstration Windows Terminal was
  524.  modified to detect price changes and respond to DDE messages. A simple bar-
  525.  charting program was then written to receive the DDE UPDATE messages.
  526.  
  527.  Interestingly the SIGNAL monitor program was written in New York City by
  528.  consultant Louis Cutrona, and the Charting program was written by Mark
  529.  Taylor of Microsoft. When brought together, the two programs were able to
  530.  communicate through DDE after being developed 3,000 miles apart.
  531.  
  532.  
  533.  ADVISE-DATA
  534.  
  535.  In the first example above, the transfers are relatively simple. For each
  536.  REQUEST message there's a corresponding UPDATE. The ADVISE message allows
  537.  for more complex transfers. In the following example it accommodates the
  538.  automatic transfer of real-time data as it changes.
  539.  
  540.    1.  APP3 broadcasts an INQUIRE message to those windows, looking for a
  541.        server with NY STOCK PRICES.
  542.  
  543.    2.  The Signal Monitor Application Four (APP4) responds with an ACK.
  544.  
  545.    3.  APP3 sends APP4 an ADVISE message that specifies IBM.(R)
  546.  
  547.    4.  APP4 responds with an ACK indicating that it recognizes IBM and can
  548.        supply data about it.
  549.  
  550.    6.  APP4 then sends the current price data for IBM.
  551.  
  552.    7.  Steps 3 to 5 are repeated for each stock of interest.
  553.  
  554.    8.  Each time APP4 learns of a new price for stock about which it has
  555.        received an ADVISE, it sends an UPDATE message with the new price.
  556.  
  557.  
  558.  Atom Management
  559.  
  560.  To speed processing and simplify the development of DDE Servers, DDE
  561.  applications exchange "atoms" rather than strings. A central atom manager
  562.  allows all applications in the system to register strings in exchange for a
  563.  16-bit atom. The atom manager (a shared executable library) will also
  564.  translate the atom to its corresponding string. A single atom pool is
  565.  maintained for all DDE applications in the system.
  566.  
  567.  In anticipation of sophisticated client/server relationships, DDE offers
  568.  optional specification of the Clipboard format for data exchange,
  569.  acknowledgement of messages, and shared memory controls. Private
  570.  client/server priority schemes are also accommodated.
  571.  
  572.  Developers interested in the details of DDE, the central atom manager, or
  573.  the new Clipboard formats can download the specifications documents and
  574.  sample programs from either DIAL or GENIE.
  575.  
  576.  On the basis of early response to the DDE design specification, a
  577.  significant number of the new Microsoft Windows applications now being
  578.  developed will incorporate DDE provisions. The nature of the implementation
  579.  depends on the type of application and its particular features.
  580.  
  581.  
  582.  Macros
  583.  
  584.  Many applications, including spreadsheets, databases, and charting programs,
  585.  include user-definable macros or other programming capabilities. The DDE
  586.  design anticipates the combination of these applications based entirely on
  587.  user programming. If the application implements a substantive part of DDE
  588.  capabilities, the user can supply the topics and item names, constructing
  589.  data relationships not contemplated by the application developer.
  590.  Generalized applications can thus be combined into tightly coupled
  591.  customized applications suites.
  592.  
  593.  This process is not as complex as it might sound. In the bar chart example
  594.  described above, the user can specify, via a dialog box, the particular
  595.  stocks to be tracked. In a more generalized implementation, the user might
  596.  also have been allowed to specify the topic, directing the DDE message to a
  597.  different server. If, hypothetically, another server existed in the PC, it
  598.  could supply the data to be plotted. Thus one instance of the bar chart
  599.  program might display stock market data, while another instance displays
  600.  temperature, pulse, and blood pressure from a server connected to
  601.  appropriate sensors.
  602.  
  603.  This example may be far-fetched in the choice of data to be displayed side
  604.  by side, but it's reasonable to imagine the development of common analytical
  605.  software that can be applied to disparate tasks. Microsoft Windows and DDE
  606.  expand the potential market for analytical software by providing a protocol
  607.  that is truly application independent.
  608.  
  609.  
  610.  Outside Influence
  611.  
  612.  
  613.  So far this discussion has been limited to communications among
  614.  applications running on the same PC. The principles of DDE are, however,
  615.  applicable to transfers of data across machines, even computers of different
  616.  types.
  617.  
  618.  The DDE protocol assumes that (if possible) a request for data exchange will
  619.  be satisfied by "broadcasting" a request to all other tasks in the PC and
  620.  that one of those contacted will supply the desired data. If the data
  621.  desired is not available locally, DDE provides for the use of "agents."
  622.  
  623.  An agent is an application that serves as the importer/exporter of data.
  624.  When an agent application receives an INQUIRE request for data about a
  625.  given topic, it determines whether it can satisfy the request by in turn
  626.  sending the message to its "correspondents" in other machines, which may be
  627.  able to satisfy the request.
  628.  
  629.  A given agent might use a local area network, micro-mainframe link, or
  630.  other communications facility to reach its correspondents. The correspondent
  631.  agent may then issue a DDE INQUIRE (if it is located in a PC) to locate the
  632.  ultimate server. The exchange of data then proceeds without either the
  633.  client or the server being aware of the agents.
  634.  
  635.  
  636.  Access Control
  637.  
  638.  While DDE does not explicitly provide for access control or data security, a
  639.  server application has a number of alternatives at its disposal to validate
  640.  the authority of a given client before exchanging data with it. The server
  641.  could require a password or other access parameter to be sent along with the
  642.  plete communication faciT message back to the client for the password, or
  643.  using the window handle provided, access a lot of information (from Windows)
  644.  about the client.
  645.  
  646.  The DDE protocol is a framework on which software developers can construct
  647.  private or public exchange mechanisms. When exchanging data with private
  648.  (well-known) clients, servers can supplement DDE with message priority, data
  649.  queueing, and private message protocols. In addition to Microsoft Windows'
  650.  built-in facilities for inter-application communication, very complete
  651.  communication facilities designs can be implemented.
  652.  
  653.  
  654.  The Future
  655.  
  656.  The fact that Microsoft Windows is independent of any physical device
  657.  permits applications to take full advantage of the capabilities of a wide
  658.  variety of current and future displays, printers, and pointing devices.
  659.  Application developers are freed from having to be concerned in their
  660.  programs with the peculiarities of particular devices. DDE extends the same
  661.  concept to data exchange. If an application honors DDE requests, it's then
  662.  able to communicate with all other applications that do so, without having
  663.  to consider their peculiarities.
  664.  
  665.  DDE is an important step forward in inter-application communication, since
  666.  it provides a public protocol that applications can subscribe to rather
  667.  than requiring each application developer to have to consider all the
  668.  possible applications that users might want to exchange data with. The user
  669.  can then combine programs and achieve results that no single application can
  670.  offer.
  671.  
  672.  
  673.  Figure 1:  DDE Messages
  674.  
  675. ╓┌─────────────────┌───────────────────┌──────────────────┌──────────────────╖
  676.  DDE Messages      Purpose             Argument 1         Argument 2
  677.  
  678.  WM_DDE_INITIATE   Ask if a window     Atom ─ Topic
  679.                    will exchange
  680.                    items related
  681.                    to a topic
  682.  WM_DDE_TERMINATE  End the exchange    Atom ─ Topic
  683.                    of items related
  684.                    to the topic
  685.  WM_DDE_ACK        Response to a       Atom               Acknowledgement
  686.                    DDE message                            code
  687.  WM_DDE_REQUEST    Request a given     Atom ─ Item name  Desired data
  688.                    item                                   format
  689.  WM_DDE_DATA       Contains a          Atom ─ Item name  Handle to
  690.                    requested data                         data object
  691.                    item
  692.  WM_DDE_ADVISE     Request a given     Atom ─ Item name  Desired data
  693.                    item and automatic                     format
  694.                    updating
  695.  DDE Messages      Purpose             Argument 1         Argument 2
  696.                   updating
  697.  WM_DDE_UNADVISE   Request end of      Atom ─ Item name  Desired data
  698.                    automatic updating                     format
  699.                    for a given time
  700.  WM_DDE_POKE       Contains an         Atom ─ Item name  Handle to
  701.                    unsolicited data                       data object
  702.                    item
  703.  WM_DDE_EXECUTE    Request execution                      Handle to data
  704.                    of indicated                           object containing
  705.                    command                                command
  706.  
  707.  
  708.  Figure 2:  Client's Window Procedure
  709.  
  710.  typedef struct {
  711.      WORD wDDEMODE;
  712.      WORD wFormat;
  713.  }  DDEADVISEBLOCK;
  714.  typedef struct {
  715.      WORD wClientRelease;
  716.      WORD wFormat;
  717.      WORD hServerWnd;
  718.      WORD ClipData;
  719.  }  UPDATEINFO;
  720.  ATOM aCompare;
  721.  BOOL bAccepted;
  722.  
  723.  long FAR PASCAL SampleRcvrWndProc(hWnd, message, wParam, lParam)
  724.       switch (message)
  725.  {
  726.                                      ∙
  727.                                      ∙
  728.                                      ∙
  729.        case WM_DDE_ACK:
  730.            aCompare  = HIWORD(lParam);
  731.            bAccepted = LOWORD(lParam);
  732.                 /* Is this acknowledgement of first inquire message? */
  733.             if ((aCompare == aStockInfo) && bAccepted)
  734.                 hwndServer = wParam;
  735.             else {
  736.                 /* is this the acknowledgement of an advise message? */
  737.                 for (i = 0; i<NUMSTOCKS; i++) {
  738.                     if (aCompare == stockinfo[i].Atom) {
  739.                          /* Record Server's response to Stock Symbol */
  740.                                      ∙
  741.                                      ∙
  742.                                      ∙
  743.                     }
  744.                 }
  745.             }
  746.  
  747.             break;
  748.          case WM_DDE_DATA:
  749.             ProcessNewData(wParam, lParam);
  750.             break;
  751.          default:
  752.             return((long)DefWindowProc(hWnd, message, wParam, lParam));
  753.             break;
  754.          }
  755.          return(0L);
  756.      }
  757.  
  758.  
  759.  Figure 3:  Client's Window Creation Procedure
  760.  
  761.  SampleRcvrCreate(hwnd)
  762.  HWND hwnd;
  763.  {
  764.  HMENU hMenu;
  765.  DDEADVISEBLOCK far *lpmem;
  766.  int i;
  767.           /* DDEAddAtom is part of the global atom manager
  768.            * in the dynamically linked library -- DDE.EXE */
  769.  aStockInfo = DDEAddAtom((LPSTR)"NYSE.COM.STK");
  770.           /* For the first message, broadcast it to everyone;
  771.            * When we return from this call, hwndServer will be valid
  772.            * if a server exists. NULL as loword of lParam means server
  773.            * can be any application. */
  774.  SendMessage((HWND) -1, WM_DDE_INITIATE, hwnd, MAKELONG(NULL, aStockInfo));
  775.  DDEDeleteAtom(aStockInfo);
  776.          /* If Server isn't available, return. hwndServer
  777.           *         can't be null in a call to PostMessage */
  778.  if (hwndServer == NULL) return;
  779.        /* Some Dummy Stocks for this example */
  780.  stockinfo[0].Atom = DDEAddAtom((LPSTR)"T");
  781.  stockinfo[1].Atom = DDEAddAtom((LPSTR)"GM");
  782.  stockinfo[2].Atom = DDEAddAtom((LPSTR)"IBM");
  783.  stockinfo[3].Atom = DDEAddAtom((LPSTR)"INDU");
  784.                                      ∙
  785.                                      ∙
  786.                                      ∙
  787.     for (i = 0; i< NUMSTOCKS; i++) {
  788.         hmem[i] = GlobalAlloc(GHND, (DWORD)4);
  789.         lpmem = (DDEADVISEBLOCK far *)GlobalLock(hmem[i]);
  790.         lpmem->wDDEMODE = 0;    /* I'm not going to ACK his updates */
  791.         lpmem->wFormat = CF_TEXT;
  792.         GlobalUnlock(hmem[i]);
  793.         PostMessage( (HWND) hwndServer, WM_DDE_ADVISE, hwnd,
  794.            MAKELONG(hmem[i],stockinfo[i].Atom)  );
  795.          }
  796.  
  797.  
  798.  Figure 4:  Client's Data Update Procedure
  799.  
  800.  ProcessNewData(hwnd, lStuff)
  801.  HWND hwnd;
  802.  DWORD lStuff;
  803.  {
  804.      ATOM     aData    = HIWORD(lStuff);
  805.      HANDLE   hDDEData = LOWORD(lStuff);
  806.      UPDATEINFO far *lpDataBlock;
  807.      LPSTR lpData;
  808.      HDC hdc;
  809.      int i,c;
  810.           /* Make sure we're getting info only from our server */
  811.           /* Note: hwndServer is a  global variable */
  812.      if (hwnd != hwndServer)
  813.          return;
  814.      lpDataBlock = (UPDATEINFO far *)GlobalLock(hDDEData);
  815.      for (i = 0; i<NUMSTOCKS; i++) {
  816.          if (aData == stockinfo[i].Atom) {
  817.                                      ∙
  818.                                      ∙
  819.                                      ∙
  820.               }
  821.          }
  822.          GlobalUnlock(hDDEData);
  823.          GlobalFree(hDDEData);
  824.      }
  825.  
  826.  
  827.  Figure 5:  Server's Window Procedure
  828.  
  829.  /* Procedures which make up the window class. */
  830.  
  831.  long FAR PASCAL TermWndProc(hwnd, message, wParam, lParam)
  832.                                  ∙
  833.                                  ∙
  834.                                  ∙
  835.      switch (message)
  836.  
  837.          {
  838.                                  ∙
  839.                                  ∙
  840.                                  ∙
  841.           case WM_DDE_INITIATE:
  842.                  dde_initiate( hwnd, wParam, lParam );
  843.                  break;
  844.           case WM_DDE_ADVISE:
  845.                  dde_advise( hwnd, wParam, lParam );
  846.                  break;
  847.           case WM_DDE_UNADVISE:
  848.                  dde_unadvise( hwnd, wParam, lParam );
  849.                  break;
  850.           case WM_DDE_CLOSE:
  851.                  dde_cancel  ( hwnd, wParam, lParam );
  852.                  break;
  853.           case WM_DDE_REQUEST:
  854.                  dde_request( hwnd, wParam, lParam );
  855.                  break;
  856.           case WM_DDE_EXECUTE:
  857.                  dde_execute( hwnd, wParam, lParam );
  858.                  break;
  859.                                ∙
  860.                                ∙
  861.                                ∙
  862.          default:
  863.              return(DefWindowProc(hwnd, message, wParam,lParam));
  864.              break;
  865.      }
  866.      return(0L);
  867.    }
  868.  
  869.  
  870.  Figure 6:  Foreign Intrigue
  871.  
  872.  ╔══════════════════════════════════════╗
  873.  ║ ┌──────────┐             ┌─────────┐ ║
  874.  ║ │          │             │         │ ║
  875.  ║ │  APP  5  │DDE REQUEST│  LOCAL  │ ║
  876.  ║ │          │             │         │ ║
  877.  ║ │  CLIENT  │DDE ACK│  AGENT  │ ║
  878.  ║ │          │             │         │ ║
  879.  ║ └──────────┘             └─────────┘ ║
  880.  ╚══════════════════════┌────────────────┐
  881.                            LOCAL AREA NETWORK   
  882.                         └────────────────┘═══════════════════════╗
  883.                                   ║  ┌─────────┐             ┌──────────┐║
  884.                                   ║  │         │             │          │║
  885.                                   ║  │ FOREIGN │DDE REQUEST│  APP  6  │║
  886.                                   ║  │         │             │          │║
  887.                                   ║  │  AGENT  │DDE ACK│  CLIENT  │║
  888.                                   ║  │         │             │          │║
  889.                                   ║  └─────────┘             └──────────┘║
  890.                                   ╚══════════════════════════════════════╝
  891.  
  892.  
  893.  Figure 7:  Server's Initialization Procedure
  894.  
  895.  typedef struct
  896.  
  897.  {
  898.          WORD    wHandshake;
  899.          WORD    wFormat;
  900.          HWND    hServerWnd;
  901.          char    szData[ MAXDATACHARS ];
  902.  } DDEUPDATEBLOCK;
  903.  
  904.  typedef struct
  905.  
  906.  {
  907.          WORD    DDEMode;
  908.          WORD    wFormat;
  909.  } DDEADVISEBLOCK;
  910.  
  911.  typedef struct
  912.  
  913.  {
  914.         int     cActive;                  /* Number of active clients */
  915.         ATOM    aSymbol;                  /* Atom identifies symbol */
  916.         char    szSymbol[ MAXSYMCHARS ];  /* Text of the symbol name */
  917.         HWND    hwndClient[ MAXCLIENTS ]; /* Handles of active clients */
  918.  } HOTITEMS;
  919.  
  920.  static  HOTITEMS        DDE[ MAXHOTITEMS ];
  921.  static  DDEUPDATEBLOCK  DDEUpdateBlock;
  922.  static  ATOM            aStockInfo;
  923.                  /* This atom means DDE_INITIATE is for us */
  924.  void     dde_init()
  925.  {
  926.           /* Atoms for WM_DDE_INITIATE */
  927.           aStockInfo = DDEAddAtom( (LPSTR) "NYSE.COM.STK" );
  928.                                      ∙
  929.                                      ∙
  930.                                      ∙
  931.  {
  932.  
  933.  
  934.  Figure 8:  Server's INITIATE Response Procedure
  935.  
  936.  void    dde_initiate( hwnd, hwndClient, lData )
  937.      HWND    hwnd;
  938.      WORD    hwndClient; /* Contains client's window handle */
  939.      DWORD   lData;
  940.      {
  941.          ATOM    atom;
  942.          atom = (ATOM) HIWORD( lData );
  943.          if( atom == aStockInfo )  {
  944.              if( IsWindow( (HWND) hwndClient ) )
  945.                  SendMessage( (HWND) hwndClient,WM_DDE_ACK,
  946.                         hwnd, MAKELONG( TRUE, atom )  ): )
  947.      }
  948.  
  949.  
  950.  Figure 9:  Server's Response to Advise Request
  951.  
  952.  void    dde_initiate( hwnd, hwndClient, lData )
  953.  HWND    hwnd;
  954.  WORD    hwndClient; /* Contains client's window handle */
  955.  DWORD   lData;
  956.  {
  957.       ATOM                    atom;
  958.       BOOL                    b;
  959.       GLOBALHANDLE            gh;
  960.       DDEADVISEBLOCK FAR *    lpDDEAdviseBlock;
  961.       int                     i, j, k;
  962.       LPSTR                   lps;
  963.       char *                  p;
  964.       char                    sz[ 20 ];
  965.       b = FALSE;
  966.       atom = (ATOM) HIWORD( lData );
  967.                 /* Lookup Symbol in Table */
  968.       if( SymbolIsAvailable( atom ) )  {
  969.           gh = (HANDLE) LOWORD( lData );
  970.           lpDDEAdviseBlock = (DDEADVISEBLOCK FAR *) GlobalLock( gh );
  971.  
  972.              if( lpDDEAdviseBlock->wFormat == CF_TEXT ) {
  973.                  for( i = 0; i < MAXHOTITEMS; i++ ) {
  974.                      if( DDE[i].aSymbol == atom ) {
  975.                          for( j = 0; j < MAXCLIENTS; j++ )  {
  976.                             if(
  977.                                DDE[i].hwndClient[j]==(HWND)hwndClient){
  978.                                   b = TRUE; /* Already there */
  979.                                   break;
  980.                            }  }
  981.                       if( !b )   /* if atom is there but client isn't */
  982.                        {   for( j = 0; j < MAXCLIENTS;j++ )
  983.                            {        /* Look for an empty slot */
  984.                               if( DDE[i].hwndClient[j]==(HWND)NULL )
  985.                                 { DDE[i].hwndClient[j]= (HWND)hwndClient;
  986.                                   DDE[i].cActive++;
  987.                                   b = TRUE;
  988.                                   break;
  989.                    }   }   }  }
  990.                    if( b ) break;
  991.            }
  992.            if( !b )        /* If atom is not already in the table */
  993.            {  for( i = 0; i < MAXHOTITEMS; i++ )
  994.               {  if( DDE[i].cActive <= 0 )
  995.                  {   DDE[i].aSymbol = atom;
  996.                      DDEGetAtomName( atom, (LPSTR) DDE[i].szSymbol,
  997.                                      MAXSYMCHARS - 1 );
  998.                      DDE[i].szSymbol[MAXSYMCHARS - 1 ] = '\0';
  999.                      DDE[i].hwndClient[ 0 ] =(HWND) hwndClient;
  1000.                      DDE[i].cActive = 1;
  1001.                      b = TRUE;
  1002.                      break;
  1003.            }  }  }
  1004.                  GlobalUnlock( gh );
  1005.          }
  1006.           /* Acknowledge one way or the other */
  1007.          if( IsWindow( (HWND) hwndClient ) )
  1008.              SendMessage( (HWND) hwndClient,
  1009.                  WM_DDE_ACK, hwnd, MAKELONG( b, atom ) );
  1010.          if( b )
  1011.          {
  1012.              /* Transmit latest data we received */
  1013.              if(  ( gh = GlobalAlloc( GMEM_MOVEABLE, (DWORD)
  1014.                      sizeof(DDEUPDATEBLOCK)))
  1015.                    && ( lps = (LPSTR) GlobalLock( gh ) ) )
  1016.                  {   for( p = (char *) &DDEUpdateBlock, k = 0;
  1017.                           k < sizeof( DDEUPDATEBLOCK );
  1018.                           *lps++ = *p++, k++ );
  1019.                      GlobalUnlock( gh );
  1020.                      PostMessage( (HWND) hwndClient, WM_DDE_DATA, hwnd,
  1021.                           MAKELONG( gh, atom ) );
  1022.          }       }
  1023.             return;
  1024.     }
  1025.  
  1026.  ────────────────────────────────────────────────────────────────────────────
  1027.  
  1028.  New Intel Graphics Coprocessor Makes Windows Sparkle
  1029.  
  1030.  ───────────────────────────────────────────────────────────────────────────
  1031.  Also see related tables:
  1032.    82786 Features
  1033.    82786 Graphics Instruction
  1034.  ───────────────────────────────────────────────────────────────────────────
  1035.  
  1036.  The new graphics coprocessor from Intel, the 82786, is expected to
  1037.  substantially enhance the performance of Microsoft Windows and other
  1038.  graphics applications on the IBM PC, XT, AT, and compatibles. The chip
  1039.  performs near-instantaneous screen updates, draws graphic primitives such
  1040.  as lines and circles at more than 2 million pixels per second, and creates
  1041.  text at a rate of 25,000 characters per second. It also supports
  1042.  multitasking and ultra-high-resolution displays.
  1043.  
  1044.  The 82786 has four major components: a graphics processor, display
  1045.  processor, bus interface unit, and dynamic RAM controller. These parts
  1046.  of the chip communicate over a built-in asynchronous bus.
  1047.  
  1048.  The graphics processor accepts commands from applications programs to draw
  1049.  bit maps, which create objects in memory. The processor contains a set of
  1050.  on-chip graphics commands that draw points, lines, rectangles, circles,
  1051.  polygons, and other primitives, to relieve the host CPU of the task of
  1052.  creating these figures from scratch. To display any of these figures on the
  1053.  screen, the CPU sends a single 16-bit request to the 82786 graphics
  1054.  coprocessor.
  1055.  
  1056.  To handle specialized drawing functions, the 82786 includes commands such as
  1057.  BitBLT (bit block transfer), ChaBLT (character-block transfer), Incremental
  1058.  Point, and Fill. BitBLTs are performed upon request from the CPU at a rate
  1059.  of 24 megabits per second. ChaBLTs occur at the rate of 25,000 characters
  1060.  per second. The Incremental Point command is used to draw more complex
  1061.  figures. An incremental point list describes the figure's shape, and, once
  1062.  the CPU sends the list to the 82786, the graphics processor draws the shape
  1063.  at a rate of 2 million pixels per second. The Fill command instructs the
  1064.  graphics processor to fill in any shape with horizontal lines.
  1065.  
  1066.  The coprocessor also has non-drawing instructions. For example, the Link
  1067.  command executes an unconditional jump to another command, and Enter Macro
  1068.  and Exit Macro are used to call and return, respectively, from a
  1069.  subroutine.
  1070.  
  1071.  The 82786 can receive a block of commands at one time from the CPU, and do
  1072.  it while executing other commands.
  1073.  
  1074.  Many of the graphics processor's functions are implemented in hardware
  1075.  rather than software. These include clipping, mouse support, character-set
  1076.  support, logical operations, and bit-plane masking.
  1077.  
  1078.  The amount of display memory is the only limitation on the number of
  1079.  character sets that the 82786 can support. Any one can be activated by a
  1080.  single command. All character sets can have proportional spacing or kerning.
  1081.  
  1082.  The next major functional block of the 82786 is the display processor. This
  1083.  part of the 82786 is independent of the graphics processor. Microsoft
  1084.  Windows would use the display processor to control display contents.
  1085.  
  1086.  The display processor transfers multiple bit maps from memory to window
  1087.  areas on the screen. It also provides a hardware cursor and colored borders
  1088.  around the windows. An almost unlimited number of windows can be displayed
  1089.  on the screen.
  1090.  
  1091.  To create windows, the display processor divides the screen into strips and
  1092.  tiles. A strip is one or more horizontal scan lines, and a tile is a section
  1093.  of a strip. A collection of tiles forms a window.
  1094.  
  1095.  Unlike the graphics and display processors, the bus-interface unit and
  1096.  dynamic RAM controller are invisible to the CPU software. The bus interface
  1097.  unit maintains the integrity of a display by arbitrating requests for
  1098.  graphics memory. The dynamic RAM controller handles up to 4 megabytes of
  1099.  graphics memory and screen rereshing.
  1100.  
  1101.  
  1102.  82786 and Windows
  1103.  
  1104.  What will the 82786 do for a product like Microsoft Windows? According to
  1105.  Richard Bader of Intel, "The 82786 will make Windows so responsive that a
  1106.  computer like the IBM PC will no longer stand in the way of what the user
  1107.  wants to do. Operations that took seconds to execute previously will now
  1108.  happen instantaneously. The 82786 enhances the intimacy between user and
  1109.  machine, and thus enhances productivity."
  1110.  
  1111.  Will Windows developers need to understand the intricacies of the 82876 in
  1112.  order to achieve this high performance? Says Bader, "When an 82786 board-
  1113.  level product comes to market, it will have a Windows driver, which would
  1114.  then make the 82786 virtually transparent to the applications programmer──as
  1115.  transparent as the Microsoft Graphics Device Interface allows. When an
  1116.  applications programmer uses any graphics board, he needs to interrogate the
  1117.  GDI interface to find out specific characteristics of the board such as the
  1118.  resolution it supports and whether or not it supports color. The application
  1119.  is then adapted to those physical characteristics. But for the most part
  1120.  there is a great deal of transparency provided by GDI, and this will be
  1121.  applicable to new 82786 graphics boards."
  1122.  
  1123.  
  1124.  An Ideal Application
  1125.  
  1126.  One application that stands to gain significantly from the appearance of
  1127.  82786 boards is desktop publishing. Intel's Bader points out, "As Windows
  1128.  evolves, we expect that it will be ideally suited for desktop publishing.
  1129.  And since the 82786 is so well suited as a GDI device, we believe that the
  1130.  82786 is also applicable to that market." Many of the desktop publishing
  1131.  packages currently on the market take quite a long time to reformat
  1132.  information on the screen. And displaying a variety of fonts on the screen
  1133.  is time consuming and awkward. Continues Bader, "The speed of the 82786 will
  1134.  change all that. Microsoft Windows in conjunction with the 82786 will give a
  1135.  good performance."
  1136.  
  1137.  The 82786 supports a wide range of monitors, which is also a plus for
  1138.  desktop publishing. It easily supports systems that are 640 by 480 with 64
  1139.  colors. Additionally, Bader points out, "We can also support large-format
  1140.  screens, full-page displays, with a resolution in the order of 1200 by 800,
  1141.  1400 by 1400, or 1000 by 800 with gray scales. What we've found in a number
  1142.  of instances is that people are looking for that 17-inch high-resolution
  1143.  monochrome monior. They're looking for extremely crisp, stable, high-
  1144.  performance text displays, and that's exactly what the 82786 is capable of
  1145.  providing."
  1146.  
  1147.  Intel and Microsoft have entered a cooperative program to provide Microsoft
  1148.  Windows software driver technology for systems designs using the Intel
  1149.  82786.
  1150.  
  1151.  ───────────────────────────────────────────────────────────────────────────
  1152.  82786 Features
  1153.  ───────────────────────────────────────────────────────────────────────────
  1154.  
  1155.    ■  High-performance graphics
  1156.  
  1157.    ■  Fast polygon and line drawing
  1158.  
  1159.    ■  High-speed character drawing
  1160.  
  1161.    ■  Advance DRAM controller for graphics memory up to 4 megabytes
  1162.  
  1163.    ■  Supports up to 200-MHz CRTs
  1164.       ──up to 640 by 480 by 8 bits (1K∙1K∙8) or
  1165.       1400 by 1400 by 1 bit (2K∙2K∙2)
  1166.  
  1167.    ■  Up to 1,024 simultaneous colors
  1168.  
  1169.    ■  Integral DRAM controller, shift registers, and DMA Channel
  1170.  
  1171.    ■  IBM PC Computer Graphics Adaptor compatbility
  1172.  
  1173.    ■  Hardware windows
  1174.  
  1175.    ■  Fast bit-block copies between system and bit-map memories
  1176.  
  1177.    ■  Integral video DRAM support──up to 1900 by 1900 by 8
  1178.  
  1179.    ■  Multitasking support
  1180.  
  1181.    ■  International character support
  1182.  
  1183.    ■  Provides support for rapid filling with patterns
  1184.  
  1185.    ■  88- pin grid array leadless chip carrier
  1186.  
  1187.    ■  Advanced CHMOS technology
  1188.  
  1189.  
  1190.  ───────────────────────────────────────────────────────────────────────────
  1191.  Graphics Instructions
  1192.  ───────────────────────────────────────────────────────────────────────────
  1193.  
  1194.    64 Bit Block Transfer within bit-map
  1195.    AE Bit Block Transfer across bit-maps
  1196.    06 Define Texture: Opaque
  1197.    0A Define Character Set: Word
  1198.    64 Bit-Block Transfer Within Bit-Map
  1199.    AE Bit-lock Transfer Across Bit-Maps
  1200.    06 Define Texture: Opaque
  1201.    07 Define Texture: Transparent
  1202.    0A Define Character Set: Word
  1203.    0B Define Character Set: Byte
  1204.    1A Define Bit-Map
  1205.    3D Define Colors
  1206.    41 Define Logical Combination
  1207.    46 Define Clip Rectangle
  1208.    4D Define Inter character Space
  1209.    4E Define Character Orientation
  1210.    68 Draw Arc: Exclusion
  1211.    69 Draw Arc: Inclusion
  1212.    53 Draw Point
  1213.    B4 Draw Incremental Points
  1214.    BA Draw Series of Horizontal Lines
  1215.    54 Draw Line
  1216.    58 Draw Rectangle
  1217.    73 Draw Polygon
  1218.    74 Draw Polyline
  1219.    8E Draw Circle
  1220.    A6 Draw Character String: Opaque
  1221.    A7 Draw Character String: Transparent
  1222.    44 Enter Pick Mode
  1223.    45 Exit Pick Mode
  1224.    4F Move to Absolute Position
  1225.    52 Move to Relative Position
  1226.  
  1227.  ────────────────────────────────────────────────────────────────────────────
  1228.  
  1229.  Programmable Graphics processor from TI Perks up PC Pixels
  1230.  
  1231.  ───────────────────────────────────────────────────────────────────────────
  1232.  Also see the related TMS34010 tables:
  1233.    TMS34010 Features
  1234.    TMS34010 Graphics Instruction
  1235.  ───────────────────────────────────────────────────────────────────────────
  1236.  
  1237.  Joe Desposito
  1238.  
  1239.  Texas Instruments(R) has developed the first graphics microprocessor, the
  1240.  TMS34010. This is a significant development in the world of graphics chips,
  1241.  which to date has been populated with less powerful graphics coprocessors
  1242.  and controllers. The TMS34010 is a 32-bit processor that executes 6-million
  1243.  instructions per seconds (MIPS), addresses up to 4-gigabytes of memory, and i
  1244.  a general-purpose instruction set.
  1245.  
  1246.  The chip, which will enhance all graphics applications, is of particular
  1247.  interest to developers using Microsoft Windows on the IBM PC and
  1248.  compatibles, where up until now performance has been less than spectacular.
  1249.  The TMS34010 will be contained in an add-on board that will handle all the
  1250.  graphics processing, replacing the monohrome color graphics or enhanced
  1251.  graphics display adaptor.
  1252.  
  1253.  
  1254.  Inside the TMS34010
  1255.  
  1256.  Like most microprocessors, the TMS34010 has an ALU, general registers, stack
  1257.  pointer, program counter, instruction decoder, and control unit. However, it
  1258.  also contains components that optimize the chip for graphics processing.
  1259.  
  1260.  It has a far greater number of general registers contained in the
  1261.  microprocessor than that found in general-purpose processors. Thirty 32-bit
  1262.  registers are divided into an A file and a B file. This large number
  1263.  prevents the shifting of bits between registers that often occurs with
  1264.  graphics processing. It uses a barrel shifter for high-speed bit rotations
  1265.  and can rotate a field of up to 32-bits in a single instruction cycle.
  1266.  
  1267.  The microprocessor uses a four-segment instruction cache for loading
  1268.  instructions from memory before they are executed. Each segment has eight
  1269.  subsegments, each holding eight bytes of code. This 256-byte instruction
  1270.  cache speeds up the execution of graphics algorithms by capturing loops of
  1271.  instructions. Once a loop is captured, "fetch" memory cycles in the loop
  1272.  halt. Loop execution is fast because the chip can access instruction cache,
  1273.  internal register files, and external memory simultaneously instead of
  1274.  sequentially.
  1275.  
  1276.  The chip's input/output registers include interrupt registers, host
  1277.  interface registers (for communicating with a host processor), video timing
  1278.  registers (to drive a CRT), and local memory control registers.
  1279.  
  1280.  To further increase speed, the TMS34010 employs some of the principles of
  1281.  reduced-instruction-set computer (RISC) chips; for example, it executes most
  1282.  of its instructions in a single 160-ns cycle.
  1283.  
  1284.  
  1285.  Pixel Processing
  1286.  
  1287.  In addition to approximately 100 general-purpose instructions, the TMS34010
  1288.  uses special high-speed instructions called PixBLTs (pixel block transfers)
  1289.  to handle character display and bit-mapped graphics. These instructions are
  1290.  an extension of BitBLTs (bit-block transfers) found in some graphics
  1291.  controllers. Transfers are made between source and destination arrays using
  1292.  linear addressing or X-Y coordinates.
  1293.  
  1294.  PixBLT instructions include Boolean and arithmetic operations, expansion of
  1295.  a single bit to one of two colors, transparency detection, and plane-
  1296.  masking. These types of instructions can also be combined to perform a much
  1297.  larger set of operations.
  1298.  
  1299.  The TMS34010 operates on single-bit pixels, which are usually associated
  1300.  with monochrome graphics, by using its Boolean operations on source and
  1301.  destination arrays. The common combining operations are Replace, OR, NOT-
  1302.  AND, AND, and XOR.
  1303.  
  1304.  For multiple-bit pixels, which are usually associated with color and gray-
  1305.  scale graphics, the processor uses arithmetic operations such as Maximum,
  1306.  Minimum, Add, Add with Saturate, Subtract, and Subtract with Saturate. The
  1307.  Maximum and Minimum functions are used to create a sense of depth and to
  1308.  smooth jagged lines, a technique called antialiasing. Add with Saturate and
  1309.  Subtract with Saturate are useful for dedicating multiple color planes to
  1310.  each of the three primary colors.
  1311.  
  1312.  A PixBLT instruction can expand a bit to one of two colors by taking one bit
  1313.  per pixel data from memory, expanding it to multiple-bit color data, and
  1314.  placing it anywhere in the frame buffer. PixBLT instructions also handle
  1315.  windowing, allowing the placement of windows of variable size and content
  1316.  anywhere on the display, and clipping, which prevents drawing outside the
  1317.  boundaries of a window.
  1318.  
  1319.  The way the TMS34010 handles text generation is quite different from other
  1320.  processors. First, a display list, which defines what is to be displayed,
  1321.  appears. For normal block text, the list is simple; say, a list of ASCII
  1322.  character codes. As text becomes more complex, requiring, for example,
  1323.  proportional spacing and kerning, the display list becomes more complicated.
  1324.  The TMS34010 general-purpose instructions typically break down the display
  1325.  list, and then a PixBLT is used to move this image from off-screen memory
  1326.  onto the screen.
  1327.  
  1328.  Texas Instruments is supporting the TMS34010 with a line of software
  1329.  development and support products, including low-level assembly language
  1330.  tools, a C compiler with a run-time support package, a function library,
  1331.  and support of the CGI (computer graphics interface) standard. Hardware
  1332.  and software development systems are also available.
  1333.  
  1334.  
  1335.  Building Applications
  1336.  
  1337.  Since the TMS34010 is a microprocessor, a software developer has a great
  1338.  deal of flexibility in determining what runs on the graphics processor and
  1339.  what runs on the host processor. Since the chip will also support a number
  1340.  of graphics standards such as CGI and Microsoft's GDI (graphics device
  1341.  interface), many applications can be ported by using these standards.
  1342.  
  1343.  One way that developers can tap the potential of the chip is to port a
  1344.  graphics environment like Microsoft Windows to it at GDI levels. Thus any
  1345.  software application running through Windows could be accelerated by a 32-
  1346.  bit graphics processor.
  1347.  
  1348.  However, many of the graphics cards being developed are relatively "soft"
  1349.  cards, in that they are RAM based. In effect, the command set for the board
  1350.  will be downloaded to it. As Kevin McDonough of Texas Instruments points
  1351.  out, "This will give the cards tremendous flexibility and tremendous
  1352.  performance advantages. For example, a program such as AutoCAD running under
  1353.  Microsoft Windows will run much faster in the Windows environment. You can
  1354.  probably gain another performance factor of 10 by doing specific algorithms
  1355.  and downloading them to the graphics processor for specific applications."
  1356.  
  1357.  According to McDonough, graphics boards incorporating the TMS34010 processor
  1358.  are currently under development at Video 7, Number 9, and other vendors.
  1359.  
  1360.  The distinguishing feature of the TMS34010 is that the processor is not
  1361.  limited to a few algorithms. Rather, any algorithm, be it a line, ellipse,
  1362.  circle, or whatever, can be programmed. And similarly, for text, the chip
  1363.  can be programmed for any format.
  1364.  
  1365.  Karl Guttag, also of Texas Instruments, points out that the chip is also
  1366.  excellent at performing data compression algorithms. "You know that when you
  1367.  draw images, they have to be stored on disk. And since the images take up a
  1368.  lot of disk space, it makes sense to compress them. Data compression mostly
  1369.  involves bit manipulation, which the TMS34010 excels at, so it turns out
  1370.  that this chip is better than any general-purpose processor for doing image
  1371.  compression."
  1372.  
  1373.  Texas Instruments and Microsoft have entered a cooperative program to
  1374.  provide Microsoft Windows software driver technology for systems designs
  1375.  using the TMS34010.
  1376.  
  1377.  With graphics boards that incorporate the TMS34010 processor now under
  1378.  development, a new world of graphics will soon open up to personal computer
  1379.  users.
  1380.  
  1381.  ───────────────────────────────────────────────────────────────────────────
  1382.  TMS34010 Features
  1383.  ───────────────────────────────────────────────────────────────────────────
  1384.  
  1385.    ■  160-ns instruction cycle time
  1386.  
  1387.    ■  Fully programmable 32-bit general-purpose processor with 128-megabyte
  1388.       address range
  1389.  
  1390.    ■  Pixel processing, X-Y addressing, and window clip/pick built into the
  1391.       instruction set
  1392.  
  1393.    ■  Programmable 1,2,4,8, or 16-bit pixel size with 16 Boolean and 6
  1394.       arithmetic pixel processing options (Raster-Ops)
  1395.  
  1396.    ■  31 general purpose 32-bit registers
  1397.  
  1398.    ■  256-byte LRU on-chip instruction cache
  1399.  
  1400.    ■  Direct interfacing to both conventional DRAM and multiport video RAM
  1401.  
  1402.    ■  Dedicated 8/16-bit host processor interface and HOLD/HLDA interface
  1403.  
  1404.    ■  Programmable CRT control (HSYNC,VSYNC,BLANK)
  1405.  
  1406.    ■  High-level language support
  1407.  
  1408.    ■  Full line of hardware and software development tools including a C
  1409.       compiler
  1410.  
  1411.    ■  68-leaded packaging (PLCC)
  1412.  
  1413.    ■  5-volt CMOS technology Graphics Instruction
  1414.  
  1415.  
  1416.  ───────────────────────────────────────────────────────────────────────────
  1417.  TMS34010 Graphics Instruction
  1418.  ───────────────────────────────────────────────────────────────────────────
  1419.  
  1420.  ADDXY     RS,RD           Add Registers in XY Mode
  1421.  CMPXY     RS,RD           Compare X and Y Halves of Registers
  1422.  CPW       RS,RD           Compare Point to Window
  1423.  CVXYL     RS,RD           Convert XY Address to Linear Address
  1424.  DRAV      RS,RD           Draw and Advance
  1425.  FILL      L               Fill Array with Processed Pixels: Linear
  1426.  FILL      XY              Fill Array with Processed Pixels: XY
  1427.  MOVX      RS,RD           Move X Half of Register
  1428.  MOVY      RS,RD           Move Y Half of Register
  1429.  PIXBLT    B,L             Pixel Block Transfer: Binary to Linear
  1430.  PIXBLT    B,XY            Pixel Block Transfer: Binary to XY
  1431.  PIXBLT    L,L             Pixel Block Transfer: Linear to Linear
  1432.  PIXBLT    L,XY            Pixel Block Transfer: Linear to XY
  1433.  PIXBLT    XY,L            Pixel Block Transfer: XY to Linear
  1434.  PIXBLT    XY,XY           Pixel Block Transfer: XY to XY
  1435.  PIXT      RS,*RD          Pixel Transfer: Register to Indirect
  1436.  PIXT      RS,*RD.XY       Pixel Transfer: Register to Indirect XY
  1437.  PIXT      *RS,RD          Pixel Transfer: Indirect to Register
  1438.  PIXT      *RS,*RD         Pixel Transfer: Indirect to Register
  1439.  PIXT      *RS.XY,RD       Pixel Transfer: Indirect XY to Register
  1440.  PIXT      *RS.XY,*RD.XT   Pixel Transfer: Indirect XY to Indirect Y
  1441.  SUBXY     RS,RD           Subtract Registers in XY Mode
  1442.  LINE      Z               Line Draw
  1443.  
  1444.  Key to abbreviations: S (source register), D (destination register),
  1445.  R (register file select), K (constant), Z (draw option)
  1446.  
  1447.  ────────────────────────────────────────────────────────────────────────────
  1448.  
  1449.  Developers' Aid: Dialog Editor
  1450.  
  1451.  Charles Petzold
  1452.  
  1453.  The Microsoft Windows dialog box is both one of the most important elements
  1454.  of a Windows application and the most difficult element to design. Since
  1455.  dialog boxes allow the user to select or enter information too complex for
  1456.  an application's menu, they must be clearly and logically organized. Yet
  1457.  the graphical image of the dialog box is normally derived from a template
  1458.  in a Resource Script (.RC) file, where all the coordinates and sizes are
  1459.  specified as numbers. For the programmer, editing the .RC file to get these
  1460.  coordinates and sizes right (both in terms of clarity and aesthetics) is
  1461.  mostly a matter of trial and error.
  1462.  
  1463.  
  1464.  New Dialog Editor
  1465.  
  1466.  The only help the original Microsoft Windows Software Development Kit
  1467.  offered in designing dialog boxes was the barely adequate DLGEDIT.EXE. If
  1468.  you've tried DLGEDIT and rejected it, don't overlook version 2 of the dialog
  1469.  editor, now called DIALOG.EXE. It's a complete rewrite and a major
  1470.  improvement. A beta test version of the new dialog editor is distributed at
  1471.  Windows Development Seminars and can also be downloaded from the Microsoft
  1472.  SIG on CompuServe.
  1473.  
  1474.  Aside from it's practical value in helping you create attractive dialog
  1475.  boxes for Windows applications, DIALOG is also an excellent tool to learn
  1476.  about the various styles, controls, and options of dialog boxes. The only
  1477.  problem is that it is distributed without documentation. But like most
  1478.  Windows applications, some creative playtime unlocks most of it's
  1479.  treasures.
  1480.  
  1481.  DIALOG saves files in two different formats: a .RES format (the compiled
  1482.  format that it uses for later editing) and a human-readable ASCII format
  1483.  with the extension DLG. The .DLG file contains the complete dialog template
  1484.  as it would normally appear in a .RC file, with style parameters expressed
  1485.  in terms of the macro definitions from WINDOWS.H (such as BS_PUSHBUTTON) and
  1486.  IDs identifying each control as specified in a header file for the
  1487.  application.
  1488.  
  1489.  One .RES file created by DIALOG can contain many different dialog templates
  1490.  for the application. You can begin a new file within DIALOG by selecting New
  1491.  from the File menu. To start a new dialog template, select New Dialog from
  1492.  the Edit menu and switch between dialog templates by using the View Dialog
  1493.  option of the File menu.
  1494.  
  1495.  To fill up the dialog box with various controls, use the Control menu, which
  1496.  lists 12 basic types of controls (such as Check Box, Radio Button, Push
  1497.  Button). If the control uses text, it will simply show the word TEXT. You
  1498.  can select the control for editing simply by clicking on it. By hooking the
  1499.  sides or corners you can stretch and size it, and by hooking the center you
  1500.  can move it around.
  1501.  
  1502.  
  1503.  A Matter of Style
  1504.  
  1505.  The Control menu lets you select from the basic types of controls. The
  1506.  Styles menu allows you to further refine them, replace the word TEXT with
  1507.  something else, and assign an ID to each control. These IDs are usually
  1508.  macro definitions from the application's header (.H) file. Your source
  1509.  program can then reference each control by these names.
  1510.  
  1511.  Although DIALOG can read a header file and let you use the name (rather than
  1512.  the number), it asks for the header file only when reading an existing RES
  1513.  file. So, before you get too far, you'll want to save a new file using the
  1514.  Save As option from the Files menu, create a header file with define
  1515.  statements for the IDs, read the file back into DIALOG with File Open, and
  1516.  enter the name of the header file when DIALOG asks for it.
  1517.  
  1518.  From the Styles menu you have a choice of Class Styles and Standard Styles.
  1519.  The options here let you refine the way the control appears on the screen
  1520.  and how it works.
  1521.  
  1522.  For instance, you might select Push Button from the Control menu, which will
  1523.  display text in a rounded rectangle and is often used for things like OK and
  1524.  CANCEL If you want a default setting for the push button (which has a bold
  1525.  outline), you first select the push button control for editing, bring down
  1526.  the Class Styles option of the Styles menu, and select Def Push Button.
  1527.  Another example: The dialog box itself is initially shown with a simple
  1528.  frame. You can add a caption bar and a system menu box by selecting those
  1529.  options from Standard Styles.
  1530.  
  1531.  Controls in a Windows dialog box are generally organized by "groups" and
  1532.  "tab stops." Controls marked as tab stops can be navigated using the tab
  1533.  key. Within a group, however, you can use the arrow keys. You can mark
  1534.  controls as groups and tab stops from the Standard Styles option of the
  1535.  Styles menu. However, if you've been designing your dialog box in a free-
  1536.  form manner, you'll find that the tab stops will bounce around from item to
  1537.  item in the order that you've created them rather than a visually logical
  1538.  order.
  1539.  
  1540.  Fortunately, you can both re-order the controls and select groups and tab
  1541.  stops through the Order Groups option of the Options menu. This shows a list
  1542.  of all the controls you've created. Selecting a control with the mouse and
  1543.  placing the horizontal black bar cursor in a different location moves the
  1544.  control. To define a group, you have to mark only the first and last control
  1545.  of the group. You would usually flag the first control of the group as a tab
  1546.  stop also, but you can pick another control as the tab stop if you'd like
  1547.  the cursor to jump to the middle of a group.
  1548.  
  1549.  
  1550.  Make Sure It Works
  1551.  
  1552.  Of course, now you'll have to recompile to see if the thing works right.
  1553.  Well, not quite yet. You can now pick Test Mode from the Options menu and
  1554.  test the tab stops and groups from within DIALOG. This test mode is one of
  1555.  the nicest features of the program.
  1556.  
  1557.  DIALOG is not perfect. You should watch out for a few things: If you want to
  1558.  delete a specific control from the dialog box, first select it and then pick
  1559.  Clear Control from the Edit menu. The Cut Dialog option of the Edit menu
  1560.  deletes the whole dialog box and everything in it. You can get it back by
  1561.  selecting Paste Dialog from the Edit menu, but it's a little disconcerting
  1562.  to see the whole thing disappear.
  1563.  
  1564.  Icons do not work right. You should be able to identify an icon by typing
  1565.  the name in the Text field of the Class Styles box. However, DIALOG will
  1566.  ignore this name. You can either avoid using icons in dialog boxes or enter
  1567.  in the name later using a text editor.
  1568.  
  1569.  The worst problem does not lie with DIALOG. Preferably, you should be able
  1570.  to include the .DLG file created by DIALOG in the application's Resource
  1571.  Script (.RC) file, as:
  1572.  
  1573.    #include "myprog.dlg"
  1574.  
  1575.  However, the RC.EXE resource compiler version 1.00 will not correctly
  1576.  process an include file in the resource script unless the include file
  1577.  contains only define statements. Until this problem has been fixed, you'll
  1578.  probably have to copy the .DLG file into your .RC file manually. You'll also
  1579.  want to use a different name for the .RES file that is created by DIALOG and
  1580.  used for future editing. Otherwise, DIALOG's .RES file will be overwritten
  1581.  when you run the RC resource compiler. Although DIALOG can read and properly
  1582.  modify a RES file that it did not create and which contains information
  1583.  other than the dialog boxes, it would probably be safer to let DIALOG work
  1584.  with its own .RES file.
  1585.  
  1586.  
  1587.  Required Reading
  1588.  
  1589.  Chapter 7 (pages 147 to 174 of the Microsoft Windows Software Development
  1590.  Kit Programming Guide (for a general discussion of controls and dialog boxes
  1591.  of controls and dialog boxes).
  1592.  
  1593.  Section 6.2.6 (pages 292 to 307 of the Programmer's Reference (for the
  1594.  format of the DIALOG template).
  1595.  
  1596.  
  1597.  Figure 1:
  1598.  
  1599.  TRYOUT DIALOG 11, 18, 208, 165
  1600.   CAPTION "Mythical Windows Spreadsheet"
  1601.   STYLE WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SYSMENU | WS_POPUP
  1602.   BEGIN
  1603.    CONTROL "Number Format"  11,"button", BS_GROUPBOX    | WS_CHILD, 12, 4, 64,
  1604.    CONTROL "General"    ID_GEN, "button",BS_RADIOBUTTON | WS_GROUP | WS_TABSTO
  1605.    CONTROL "Fixed"      ID_FIX, "button", BS_RADIOBUTTON | WS_CHILD, 16, 28, 4
  1606.    CONTROL "Scientific" ID_SCI, "button", BS_RADIOBUTTON | WS_CHILD, 16, 40, 5
  1607.    CONTROL "Currency"   ID_CUR, "button", BS_RADIOBUTTON | WS_CHILD, 16, 52, 4
  1608.    CONTROL "Comma"      ID_COM, "button", BS_RADIOBUTTON | WS_CHILD, 15, 65, 4
  1609.    CONTROL "Default Column Width:" 8, "static", SS_LEFT | WS_GROUP | WS_CHILD,
  1610.    CONTROL " 9" ID_DCW, "edit", ES_LEFT | ES_RIGHT | WS_BORDER | WS_TABSTOP |
  1611.    CONTROL "Decimal Places:" 17, "static", SS_LEFT | WS_CHILD, 88, 28, 66, 10
  1612.    CONTROL " 2" ID_DPL, "edit", ES_LEFT | ES_RIGHT | WS_BORDER | WS_TABSTOP |
  1613.    CONTROL "Fast Entry Mode" ID_FEM, "button", BS_AUTOCHECKBOX | WS_TABSTOP |
  1614.    CONTROL "Flag Circular Calcs" ID_FCC, "button", BS_CHECKBOX | WS_TABSTOP |
  1615.    CONTROL "Text Format"   19,  "button", BS_GROUPBOX | WS_CHILD, 12, 84, 64,
  1616.    CONTROL "Left"       ID_LEF, "button", BS_RADIOBUTTON | WS_GROUP | WS_TABST
  1617.    CONTROL "Right"      ID_RIT, "button", BS_RADIOBUTTON | WS_CHILD, 16, 108,
  1618.    CONTROL "Centered"   ID_CEN, "button", BS_RADIOBUTTON | WS_CHILD, 16, 120,
  1619.    CONTROL "Recalculation" 3, "button", BS_GROUPBOX | WS_GROUP | WS_CHILD, 88,
  1620.    CONTROL "Auto"       ID_AUT, "button", BS_RADIOBUTTON | WS_GROUP | WS_TABST
  1621.    CONTROL "Manual"     ID_MAN, "button", BS_RADIOBUTTON | WS_CHILD, 96, 108,
  1622.    CONTROL "Row-Wise"   ID_ROW, "button", BS_RADIOBUTTON | WS_CHILD, 148, 96,
  1623.    CONTROL "Col-Wise"   ID_COL, "button", BS_RADIOBUTTON | WS_CHILD, 148, 108,
  1624.    CONTROL "Natural"    ID_NAT, "button", BS_RADIOBUTTON | WS_CHILD, 148, 119,
  1625.    CONTROL "OK" 0,     "button", BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP | WS
  1626.    CONTROL "Cancel" 0, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 120, 1
  1627.   END
  1628.  
  1629.  
  1630.  
  1631.  NULL
  1632.                  );
  1633.              }
  1634.          }
  1635.  
  1636.          return 0L;
  1637.  
  1638.        case WM_CREATE:
  1639.  
  1640.  ────────────────────────────────────────────────────────────────────────────
  1641.  
  1642.  Ask Dr. Bob!
  1643.  
  1644.  Multitasking?
  1645.  
  1646.  Dear Dr. Bob,
  1647.  
  1648.  I'm confused: Is Microsoft Windows a multitasking environment or not?
  1649.  Sometimes it seems like it is, and sometimes it seems like it isn't. What's
  1650.  the story, Dr. Bob?──Confused
  1651.  
  1652.  Dear Confused,
  1653.  
  1654.  Most people think of multitasking as a process requiring time-slicing. In a
  1655.  traditional multitasking environment, the operating system switches between
  1656.  different tasks by allocating short periods of time to each. Microsoft
  1657.  Windows does not yet time-slice between applications. Windows will probably
  1658.  use time-slicing for multitasking only when MS-DOS also does so.
  1659.  
  1660.  Instead, Windows has a nonpreemptive multitasking scheduler for running
  1661.  Windows applications (programs written specifically for Microsoft Windows).
  1662.  A Windows application will not be interrupted if it does not want to be
  1663.  interrupted; only when it specifically relinquishes control do other
  1664.  applications get a chance to run.
  1665.  
  1666.  A Windows application normally sits in a loop waiting to receive messages,
  1667.  usually executing a GetMessage call. The messages it receives cover all the
  1668.  events (keystrokes, mouse movements, window resizing, and so forth) that
  1669.  affect the application. When it gets a message, the Windows application
  1670.  dispatches it to the appropriate procedure in the program. This procedure
  1671.  can either act on the message or ignore it.
  1672.  
  1673.  Microsoft Windows switches between applications when an application polls
  1674.  for a message by using the GetMessage call or the similar WaitMessage call.
  1675.  Once it has the message, the application can take as long as it wants,
  1676.  without interruption. In the interim other applications (for instance, the
  1677.  CLOCK) will stop working.
  1678.  
  1679.  Polite Windows applications check frequently for messages while performing
  1680.  lengthy chores. This way they can yield control to other applications and
  1681.  give them an opportunity to run.
  1682.  
  1683.  However, if a Windows application needs an unbroken chunk of time (say, for
  1684.  high-speed real-time data acquisition), it can take it. The application can
  1685.  interrogate the mouse and the keyboard, write to the screen, and do
  1686.  everything it needs to do──all without interruption. It just has to avoid
  1687.  looking for more messages.
  1688.  
  1689.  So Microsoft Windows is multitasking, but it's up to the individual Windows
  1690.  applications when to allow multitasking with other applications and when not
  1691.  to.
  1692.  
  1693.  For "good old applications" (MS-DOS applications that don't write directly
  1694.  to the display and that can run in a window), Windows yields control to
  1695.  other applications during keyboard input and screen output. But for old
  1696.  applications that do write directly to the display, Microsoft Windows
  1697.  suspends all multitasking but still allows the user (in most cases) to
  1698.  switch among applications.
  1699.  
  1700.  
  1701.  Compilers
  1702.  
  1703.  Dear Dr. Bob,
  1704.  
  1705.  Why do I need to use Microsoft compilers for developing Windows
  1706.  applications?──Puzzled
  1707.  
  1708.  Dear Puzzled,
  1709.  
  1710.  Right now the only compilers that support Microsoft Windows are the
  1711.  Microsoft C and Pascal compilers. You can also program Windows applications
  1712.  in assembler, but the most convenient way to do that would be to use
  1713.  assembler routines called from a C program. Microsoft has made public the
  1714.  relatively minor support for Windows that a C compiler requires, and so
  1715.  other compilers may also support Microsoft Windows.
  1716.  
  1717.  A C compiler for Windows requires procedures to be "Pascal" (arguments are
  1718.  pushed on the stack from left to right and that the procedure itself adjusts
  1719.  the stack). Normally, C pushes arguments right to left and adusts the stack
  1720.  after returning from the procedure. The C compiler must also allow mixed-
  1721.  model programming with the "near" and "far" key words. Procedures called
  1722.  from Microsoft Windows must have a small prolog and epilog so that Windows
  1723.  can adjust data segment references after moving data.
  1724.  
  1725.  
  1726.  No Software Interrupt
  1727.  
  1728.  Dear Dr. Bob,
  1729.  
  1730.  Is there some kind of software interrupt or other hook I can use to access
  1731.  Microsoft Windows procedures from within a program I write in another
  1732.  language, such as BASIC or Turbo Pascal? Can I get at Windows graphics
  1733.  functions any other way?──Frustrated
  1734.  
  1735.  Dear Frustrated,
  1736.  
  1737.  No. Windows functions are not accessed through a software interrupt. The
  1738.  Windows loader resolves all function references in the new format executable
  1739.  at load time. This means that only programs in the new EXE format can access
  1740.  Microsoft Windows functions.
  1741.  
  1742.  It might be possible to write a shell program as a Windows application that
  1743.  would provide a path for other programs that are not Windows applications to
  1744.  call Windows procedures. But this task would be very difficult. Moveover,
  1745.  these programs would almost certainly have to be fixed in memory and could
  1746.  not be moved.
  1747.  
  1748.  The WINOLDAP module allows some old applications to run in a window, by
  1749.  providing one type of shell that intercepts DOS and BIOS calls and
  1750.  translates these calls into Windows functions. This shell is one of Windows'
  1751.  more complex features, since it must deal with many of the nasty things that
  1752.  old applications do. A more extensive shell──even one that included only
  1753.  graphics support──would have to be more complex.
  1754.  
  1755.  
  1756.  Executive
  1757.  
  1758.  Dear Dr. Bob:
  1759.  
  1760.  Can I execute a Windows application from within another Windows
  1761.  application?──Stumped
  1762.  
  1763.  Dear Stumped,
  1764.  
  1765.  Sure. That's what the MS-DOS Executive does. The recommended method for
  1766.  executing a program from a Windows application is with an assembly language
  1767.  subroutine using the EXEC function call 0x4B. Windows intercepts this MS-DOS
  1768.  call and can correctly load the new format executable.
  1769.  
  1770.  The EXEC function call returns to the calling program right after the child
  1771.  process has been loaded. Under MS-DOS, the calling program doesn't get
  1772.  control back until the child process has terminated.
  1773.  
  1774.  You can even execute an old application from a Windows application or vice
  1775.  versa. You can get a little sense of what happens in this latter case by
  1776.  running COMMAND.COM from Microsoft Windows. If you lie in the PIF file and
  1777.  say that COMMAND.COM writes directly to the screen, you'll find that
  1778.  executing a Windows application from the MS-DOS command level results in the
  1779.  "This program requires Microsoft Windows" message.
  1780.  
  1781.  If you run COMMAND.COM in a window and enter the name of a Windows
  1782.  application, however, it will load correctly and take over the area of the
  1783.  screen occupied by COMMAND.COM. When you bring up COMMAND.COM again, you'll
  1784.  see the cursor sitting at the MS-DOS prompt. The Windows application has
  1785.  been loaded, and Windows has returned control back to COMMAND.COM.
  1786.  
  1787.  
  1788.  Expanded RAM
  1789.  
  1790.  Dear Dr. Bob,
  1791.  
  1792.  Can Microsoft Windows use an expanded memory board?──Fuzzy
  1793.  
  1794.  Dear Fuzzy,
  1795.  
  1796.  Yes and no. Microsoft Windows can take advantage of a RAM-Disk on an
  1797.  expanded memory board but not of expanded memory itself. However, Windows
  1798.  supports the use of expanded memory by old applications by preserving and
  1799.  restoring the state of the Expanded Memory Manager.
  1800.  
  1801.  Let's look at these two topics separately.
  1802.  
  1803.  The presence of any high-speed disk storage will improve Windows'
  1804.  performance. Windows uses the disk for storing temporary files from Windows
  1805.  applications and for swapping old applications in and out of memory. The
  1806.  disk used for these purposes can be any real or virtual disk on your system,
  1807.  including any type of RAM-Disk. A RAM-Disk installed in expanded memory is
  1808.  ideal.
  1809.  
  1810.  If your RAM-Disk is installed as drive D: (for instance), put the following
  1811.  statement in your AUTOEXEC.BAT:
  1812.  
  1813.    SET TEMP=D:
  1814.  
  1815.  This statement directs Microsoft Windows applications to store temporary
  1816.  files (for instance, those created by WRITE) on the RAM-Disk. These
  1817.  temporary files begin with a tilde (~) and have the extension TMP.
  1818.  
  1819.  If you do Windows program development, you should also include the following
  1820.  statement in your AUTOEXEC.BAT:
  1821.  
  1822.    SET TMP=D:
  1823.  
  1824.  This statement directs the Microsoft C Compiler to use the RAM-Disk for its
  1825.  temporary files.
  1826.  
  1827.  To use drive D: as a swapping disk for old applications, replace the line in
  1828.  your WIN.INI file that reads
  1829.  
  1830.  Beyond using a RAM-Disk in expanded memory, neither Microsoft Windows nor
  1831.  Windows applications use expanded memory directly. (A future version of
  1832.  Windows may have more support for expanded memory.)
  1833.  
  1834.  However, Microsoft Windows can detect the presence of an expanded memory
  1835.  board. If it finds one, Windows can let old applications use expanded memory
  1836.  in the multitasking environment without memory conflicts. Windows will save
  1837.  the contents of the expanded memory board registers and restore them when
  1838.  switching among applications.
  1839.  
  1840.  Some early Expanded Memory Managers did not include full support of the
  1841.  "Get/Set Page Map" (function 15) of the Expanded Memory Specification
  1842.  Release 3.20. This call is the one Microsoft Windows uses to save the
  1843.  contents of the expanded memory board registers. For this reason, Release
  1844.  3.20 versions of the Expanded Memory Manager are included with Windows.
  1845.  These drivers are called EMM.PC and EMM.AT; they work only with the Intel
  1846.  Above Boards. You can also use any Expanded Memory Manager, Release 3.20 or
  1847.  later, supplied with an Intel Above Board. Before using any other expanded
  1848.  memory board, check with the manufacturer to determine if the Expanded
  1849.  Memory Manager provides Release 3.20 support of the "Get/Set Page Map"
  1850.  call.
  1851.  
  1852.  
  1853.  Math Coprocessor
  1854.  
  1855.  Dear Dr. Bob,
  1856.  
  1857.  Can Windows applications use an 8087 or 80287 math coprocessor?
  1858.  ──Perplexed
  1859.  
  1860.  Dear Perplexed,
  1861.  
  1862.  Yes. Microsoft Windows provides full support for saving the state of the
  1863.  math coprocessor and restoring it when switching among applications. That's
  1864.  the good news. However, Windows applications cannot yet use the 8087
  1865.  floating point libraries provided with the Microsoft C Compiler (version 3
  1866.  or 4). This problem lies with the libraries themselves rather than with
  1867.  Windows support of the 8087.
  1868.  
  1869.  If you want to use floating point in a Windows application written in C, you
  1870.  must currently use the /FPa compiler switch and link with the SLIBFA.LIB,
  1871.  MLIBFA.LIB, or LLIBFA.LIB──depending on your memory model──alternate math
  1872.  library. The alternate math library, which uses a subset of the IEEE
  1873.  standard, is faster and smaller (but less accurate) than the 8087-emulation
  1874.  code of the other floating point math libraries. The alternate math library
  1875.  does not use an 8087 even if one is present.
  1876.  
  1877.  When the 8087 floating point libraries are eventually modified for Windows,
  1878.  upgrading the program should only require relinking it with LINK4.
  1879.  
  1880.  In the interim, you could define your own floating point routines that use
  1881.  either the regular C library routines or the assembly language subroutines
  1882.  using the 8087, depending on the presence of the math coprocessor.
  1883.  
  1884.  
  1885.  Printf
  1886.  
  1887.  Dear Dr. Bob,
  1888.  
  1889.  What happens ins a Windows application if I try to write to the Display in
  1890.  the conventional way using the C function printf?──Stymied
  1891.  
  1892.  Dear Stymied,
  1893.  
  1894.  Nothing. Microsoft Windows intercepts all DOS and BIOS output headed for the
  1895.  display and dumps it into the bit bucket, where it is never seen again.
  1896.  
  1897.  If you need to write formatted text output to the screen, you can use
  1898.  sprintf and display the resultant string with Windows TextOut procedure.
  1899.  
  1900.  
  1901.  Instances
  1902.  
  1903.  Dear Dr. Bob, What happens when I run the same program simultaneously in
  1904.  Microsoft Windows? Are the two versions entirely distinct or do they share
  1905.  code and data?──Unclear
  1906.  
  1907.  Dear Unclear,
  1908.  
  1909.  When an application is loaded more than once, the loadings of the
  1910.  application are referred to as different "instances." Generally, multiple
  1911.  instances of the same application share the same code segment but have
  1912.  different data segements. Windows applications also share resources such as
  1913.  menus, icons, cursors, and bitmaps, since such resources are read-only
  1914.  data.
  1915.  
  1916.  During initialization, an application can determine whether or not it is the
  1917.  first instance of that application. If it is not the first instance, it can
  1918.  retrieve some data that must be shared from the previous instance.
  1919.  
  1920.  
  1921.  ════════════════════════════════════════════════════════════════════════════
  1922.  
  1923.  
  1924.  Vol. 1 No. 2 Table of Contents
  1925.  
  1926.  Aldus: Preparing PageMaker for the Move to Windows
  1927.  
  1928.  The success of Aldus Corporation's PageMaker(TM) has made this program
  1929.  practically synonymous with desktop publishing. Now, Aldus is moving
  1930.  PageMaker to Microsoft(R) Windows and rewriting the program in C for both
  1931.  the PC and the Macintosh.
  1932.  
  1933.  
  1934.  Moving Toward an Industry Standard for Developing TSRs
  1935.  
  1936.  Terminate-and-stay-resident programs such as Borland International's
  1937.  SideKick(TM) have become popular tools for many PC users. A report from the
  1938.  May gathering of software developers attempting to formulate guidelines for
  1939.  peaceful coexistence among TSRs.
  1940.  
  1941.  
  1942.  A Step-by-Step Guide to Building Your First Windows Application
  1943.  
  1944.  
  1945.  At first, creating a Microsoft Windows-based application seems to be a
  1946.  complex process involving an oddly structured C program that uses Windows
  1947.  functions and macros. This simple program, WSZ, provides a model for
  1948.  building a Windows application.
  1949.  
  1950.  
  1951.  New XENIX Version Will Be First to Run On the Intel 80386
  1952.  
  1953.  In early 1987, Microsoft will release XENIX(R) System V/386, the first
  1954.  version of XENIX to make full use of Intel's new 32-bit 80386
  1955.  microprocessor. In this exclusive interview, XENIX Development Manager
  1956.  Martin Dunsmuir tells what to expect.
  1957.  
  1958.  
  1959.  A New Generation of Debugging Arrives with CodeView
  1960.  
  1961.  The CodeView(TM) debugger included with the Microsoft(R) C Compiler 4.00,
  1962.  the latest debugging tool to become available, marks improvement over
  1963.  SYMDEB by including symbolic local variable and subroutine names with
  1964.  additional debugging capabilities.
  1965.  
  1966.  
  1967.  Ask Dr. Bob
  1968.  
  1969.  
  1970.  EDITOR'S NOTE
  1971.  
  1972.  Welcome to Issue 2 of Microsoft Systems Journal, up in size from the last
  1973.  issue of MSJ, but already too small to accommodate the problem-solving
  1974.  and problem-avoiding technical articles that many of you have already come
  1975.  to expect──judging from the first subscription mailing response. We are,
  1976.  of course, delighted by your interest and approval.
  1977.  
  1978.  There's still time to become a charter subscriber to Microsoft Sytems
  1979.  Journal and avoid missing the solutions, insights, and inspirations we're
  1980.  dedicated to bringing you. Consider what's coming up: a closeup of the IRMA
  1981.  3270 board (from a developer's point of view, of course), a comparison of
  1982.  page description languages, details of the MS-DOS CD ROM extensions, and a
  1983.  step-by-step debugging session using CodeView. Down the road: authoritative
  1984.  examinations of operating systems developments and language enhancements.
  1985.  
  1986.  Wish List. How many times have you said to yourself, "How could they have
  1987.  gone to all the trouble to design such a useful product and left out _____?"
  1988.  MSJ is so committed to the principle of product improvement that we'll pay
  1989.  you a $100 for your idea if we publish it, and you can be sure that the
  1990.  manufacturer will hear of its sins of omission directly from the editors
  1991.  of Microsoft Systems Journal.
  1992.  
  1993.  Write to Us. Our aim at Microsoft Systems Journal is to tackle the issues
  1994.  confronting serious developers, but we need your help. Write us, or send us
  1995.  a message on MCI Mail (MSJ). Tell us what you want to see in the Journal.
  1996.  Or let us pass on your most recent programming snafu to Dr. Bob. And, of
  1997.  course, we'd like your feedback on these first two issues. Whether you've
  1998.  got a question, comment, or complaint, we'd like to hear from you.──Ed.
  1999.  
  2000.  
  2001.  Masthead
  2002.  
  2003.  JONATHAN D. LAZARUS
  2004.  Editor
  2005.  
  2006.  BARRY OWEN
  2007.  Managing Editor
  2008.  
  2009.  CHRISTINA G. DYAR
  2010.  Assistant Editor
  2011.  
  2012.  MICHAEL LONGACRE
  2013.  Art Director
  2014.  
  2015.  VALERIE MYERS
  2016.  Associate Art Director
  2017.  
  2018.  WILLIAM B. GRANBERG
  2019.  Circulation Manager
  2020.  
  2021.  L. PERRIN TOMICH
  2022.  Office Manager
  2023.  
  2024.  Copyright(C) 1986 Microsoft Corporation. All rights reserved; reproduction
  2025.  in part or in whole without permission is prohibited.
  2026.  
  2027.  Microsoft Systems Journal is a publication of Microsoft Corporation, 16011
  2028.  NE 36th Way, Box 97017, Redmond, WA 98073-9717. Officers: William H.
  2029.  Gates, III, Chairman of the Board and Chief Executive Officer; Jon Shirley,
  2030.  President and Chief Operating Officer; Francis J. Gaudette, Treasurer;
  2031.  William Neukom, Secretary.
  2032.  
  2033.  Microsoft Corporation assumes no liabilty for any damages resulting from the
  2034.  use of the information contained herein.
  2035.  
  2036.  Microsoft, the Microsoft logo, MS-DOS, and XENIX are registered trademarks
  2037.  and CodeView is a trademark of Microsoft Corporation. Apple is a registered
  2038.  trademark and Macintosh is a trademark of Apple Computer, Inc. IBM is a
  2039.  registered trademark of International Business Machines Corporation.
  2040.  PageMaker is a registered trademark of Aldus Corporation. Lotus and 1-2-3
  2041.  are registered trademarks of Lotus Development Corporation. UNIX is a
  2042.  registered trademark of AT&T. Compaq is a registered trademark of Compaq
  2043.  Computer Corporation. Intel is a registered trademark of Intel Corporation.
  2044.  
  2045.  ────────────────────────────────────────────────────────────────────────────
  2046.  
  2047.  Aldus: Preparing Pagemaker(TM) for the Move to Windows
  2048.  
  2049.  Kevin Strehlo
  2050.  
  2051.  Several years after the end of Ethel Merman's heyday as the queen of musical
  2052.  comedy on Broadway, a reporter said to her, "Broadway has been very good to
  2053.  you." Merman was quick to retort, "Yes, and I have been very good for
  2054.  Broadway."
  2055.  
  2056.  Such is the mutually advantageous relationship between the Apple
  2057.  Macintosh(TM) and Aldus Corporation's PageMaker, the leading desktop
  2058.  publishing software. While the Macintosh has certainly been very good for
  2059.  PageMaker, PageMaker has been very good for the Mac.
  2060.  
  2061.  Pagemaker's featured position in Apple advertising has helped push it to the
  2062.  top ten in the bestseller charts, while it returned the favor by selling
  2063.  lots of Macs (Aldus research shows that one out of three of Macintosh users
  2064.  bought their computers primarily to use PageMaker). Indeed, the PageMaker
  2065.  program has been such a success that the Mac and desktop publishing have
  2066.  become practically synonymous.
  2067.  
  2068.  It comes as little surprise that Aldus is attempting to repeat its success
  2069.  by making a move to Microsoft Windows(R), the logical vehicle for cracking
  2070.  the lucrative PC marketplace. What may be surprising, however, is the
  2071.  Seattle-based company's decision to throw away the code of its original
  2072.  Pascal-based version of PageMaker in favor of a complete rewrite in C that
  2073.  will run on both the PC and the Macintosh.
  2074.  
  2075.  From the start, Aldus Corporation had planned to merge the Macintosh version
  2076.  of the PageMaker page layout program with the version it was developing
  2077.  under Microsoft Windows. Rather than release the Macintosh version first,
  2078.  Aldus decided to wait until the PC version of PageMaker was out the door.
  2079.  
  2080.  
  2081.  A Rare Problem
  2082.  
  2083.  In Aldus's effort to share source code between the Mac and the PC, however,
  2084.  the decision to wait was reversed by a problem in one of the environments.
  2085.  It was a rare case where the problem was located in the Mac.
  2086.  
  2087.  "We had made all the data structures in the original Mac version of
  2088.  PageMaker 'resources' and saved them out to files using the Mac's Resource
  2089.  Manager," says Jeremy Jaech, programming manager for Aldus. "That turned out
  2090.  to be a mistake."
  2091.  
  2092.  The Resource Manager was designed to read small, indexed data structures
  2093.  (such as fonts and dialog boxes) into memory. It wasn't intended to
  2094.  continually write large pieces of data back to disk. Aldus found itself
  2095.  plagued with less-than-optimum performance and occasional file corruption
  2096.  caused by persistent bugs in the Resource Manager's garbage collection
  2097.  routines.
  2098.  
  2099.  Fortunately the PC team was already working on the solution. "There is no
  2100.  equivalent to the Resource Manager under Windows, so we spent a lot of time
  2101.  up front designing and implementing a file system that did exactly what we
  2102.  wanted to do on the PC," says Jaech.
  2103.  
  2104.  But because they had not cleanly separated the file system layer from the
  2105.  rest of the Mac code, sliding that file system underneath the Mac code would
  2106.  necessitate a major rewrite. They decided to bite the bullet and merge the
  2107.  Mac and Windows versions right away.
  2108.  
  2109.  
  2110.  The Edge
  2111.  
  2112.  The project was organized into three teams: the core code team and──because
  2113.  of the significant differences between the two environments──two teams that
  2114.  would each write the unavoidable environment-specific modules, dubbed the
  2115.  Macintosh edge code and the Windows edge code.
  2116.  
  2117.  One of the first choices was fundamental. Building for the lowest common
  2118.  denominator of the Macintosh and Windows would result in failure to take
  2119.  advantage of the most appealing features of both. Instead, the Aldus team
  2120.  decided to write for the union of the two environments' capabilities.
  2121.  
  2122.  That often meant that the edge code for one environment had to emulate a
  2123.  capability that was missing from the other. For example, the Mac provided
  2124.  continually scalable fonts and Windows did not.
  2125.  
  2126.  "Microsoft went for the concept of readability," explains Dave Walter, the
  2127.  lead programmer for the core code group. "But a lot of things PageMaker does
  2128.  involve showing the form rather than the content. We need to be able to get
  2129.  a piece of type up on the screen the actual size it's going to be. We don't
  2130.  really care if it's readable."
  2131.  
  2132.  Thus, given a request from the core code drawing routine for a particular
  2133.  size and face of type, the Windows edge code read the character metrics of
  2134.  the printer font and returned the appropriate bit map for screen display.
  2135.  
  2136.  Fortunately, Windows did make provisions for handling fractional character
  2137.  values──a feature missing from the Mac Toolbox until the 128K ROM
  2138.  upgrade──so the PC version of PageMaker was able to portray line lengths
  2139.  accurately on-screen despite a screen resolution that is much lower than
  2140.  (and not necessarily an even divisor of) the final 300 DPI printer output.
  2141.  
  2142.  When possible, the environments were equalized in the core code rather than
  2143.  in the edge code. When the user drags a guide on PageMaker's page layout
  2144.  board, for example, Aldus's Walter wanted the code that actually moved it to
  2145.  be part of the core. That meant accommodating the differences between the
  2146.  way the two environments handled the pattern used to represent that guide.
  2147.  
  2148.  The Windows GDI (graphics device interface) drawing routines automatically
  2149.  align a pattern so that it begins and ends at the same point, ensuring it is
  2150.  "in phase." The Mac Quickdraw routines do not align patterns for you; the
  2151.  application must rotate patterns into proper phase for drawing. To deal with
  2152.  the discrepancy, Walter says, "We just used an 'if def Mac' or 'if def
  2153.  Windows' clause."
  2154.  
  2155.  
  2156.  Complex Code
  2157.  
  2158.  Sometimes, however, the environments' differing approaches made the patch
  2159.  code so complex that it was forced out of the core and into the edges,
  2160.  Walter says.
  2161.  
  2162.  For example, under Windows, scrolling involved handling a series of messages
  2163.  that described the user clicking on the cursor keys or clicking the thumb, a
  2164.  simple procedure. But tracking a scroll bar on the Mac required calling the
  2165.  Mac Toolbox's TrackControl function. Unfortunately, the arguments
  2166.  TrackControl passed were different depending on whether the user was
  2167.  clicking on the thumb or a cursor key.
  2168.  
  2169.  "You actually have to have two different scrolling procedures on the Mac,"
  2170.  Walter explains.
  2171.  
  2172.  In other ways, Windows is less orthogonal and therefore more complex to work
  2173.  with than the Mac environment.
  2174.  
  2175.  For example, under Windows the function GetMessagePos fetched the position
  2176.  of the mouse, while GetCurrentPos fetched the cursor position. "But the
  2177.  first returns the value to you as a Long (pointer), while the other gives
  2178.  you a pointer to a pointer," says Walter.
  2179.  
  2180.  Clyde McQueen, who wrote the shared memory management and file handling code
  2181.  for the two environments, had to deal with a number of similarly
  2182.  disconcerting choices as he strove to keep as much of the code in core as
  2183.  possible.
  2184.  
  2185.  "On the Mac it's neat and clean to dereference from your handle to get a
  2186.  pointer," says McQueen. Doing a dereference once outside a loop would be far
  2187.  more efficient than doing it inside a thousand times, of course, and it
  2188.  would be perfectly safe as long as he knew the object pointed to would not
  2189.  be moved. Since times of memory movement are pretty well defined on the Mac,
  2190.  he wouldn't have to lock the object down.
  2191.  
  2192.  Under Windows, however, an object is automatically locked whenever you
  2193.  dereference its handle to get a pointer. (This will allow Microsoft to flesh
  2194.  out Windows in the future with preemptive scheduling of tasks.)
  2195.  
  2196.  McQueen had a choice: he could add overhead by locking memory "needlessly"
  2197.  on the Mac or move that central part of the memory management system out of
  2198.  the core code. He decided that the lesser of these evils was locking memory
  2199.  on the Mac.
  2200.  
  2201.  
  2202.  Low Memory
  2203.  
  2204.  In another case, the problem was the lack of an early warning under Windows
  2205.  that you were about to run out of memory. "I can get a ballpark," says
  2206.  McQueen, "but it's not reliable." A clause in the core code lets the program
  2207.  know it's operating in the Windows environment and thus has to be careful
  2208.  about running out of memory.
  2209.  
  2210.  "That's why a lot of user operations under the Windows version of PageMaker
  2211.  result in a little disk hit," McQueen says. Such behavior is less acceptable
  2212.  for PageMaker on the Mac, where the program is much more likely to be
  2213.  running on floppy disk drives. Thus, if the clause senses it is on the Mac,
  2214.  writing data out to disk or purging code segments is deferred until a global
  2215.  memory warning is received.
  2216.  
  2217.  
  2218.  Fixing the Bugs
  2219.  
  2220.  To work out the early kinks in his memory management and file handling
  2221.  routines, McQueen used Heapwalker, the Windows utility designed to track
  2222.  objects in the global heap. Since he knew the number and approximate sizes
  2223.  of objects he was dealing with, Heapwalker let him see instantly when
  2224.  something had gone awry.
  2225.  
  2226.  But discovering a bug was not the same as fixing it. For bug hunting,
  2227.  McQueen turned to home-brewed tools he called "scopes" (see Figure 1).
  2228.  
  2229.  "The scopes were a way to quickly examine the memory structures I was
  2230.  using," McQueen says. The scopes were modeless dialog boxes, written as an
  2231.  excuse to learn the structure of a Windows application. They proved
  2232.  exceedingly useful.
  2233.  
  2234.  Although they could alter as well as display memory, viewing turned out to
  2235.  be far more valuable than altering. McQueen could often tell what had gone
  2236.  wrong simply by examining his memory structures. Clicking on the "next"
  2237.  button he had built into the scope would display the next record, allowing
  2238.  him to follow whatever errant trail he had blazed through memory.
  2239.  
  2240.  "It sure beat trying to figure out what was going on from SYMDEB's
  2241.  hexadecimal dump," he says.
  2242.  
  2243.  
  2244.  Working Environments
  2245.  
  2246.  Once the Mac and Windows projects merged, however, the development of the
  2247.  core code could be done in either environment. For Windows, the Microsoft C
  2248.  Compiler and the Make program were used; on the Mac, Lightspeed C and
  2249.  Polytron's Polymake were used.
  2250.  
  2251.  "Some of the problems we've got when we're dealing with an Intel processor
  2252.  are the segmentation of memory and the existence of two different pointers,
  2253.  near and far," says Walter. To avoid such processor-specific dependencies,
  2254.  he says, "We found that using warning level 2 on the Microsoft C Compiler
  2255.  was crucially important for our development."
  2256.  
  2257.  The Aldus team found the Microsoft debugger for Windows helpful. "But what
  2258.  we're really looking forward to is a future version of CodeView(TM) that
  2259.  works with Windows applications──it's certainly a big help with DOS apps,"
  2260.  says Ted Johnson, lead programmer on the Windows edge code.
  2261.  
  2262.  To an outsider, it might seem Aldus had something to lose by going with the
  2263.  common code approach. The marketplace for PC page layout programs was wide
  2264.  open, after all, and an early presence in the market would be a great
  2265.  advantage. So why waste time making sure that the Windows code already under
  2266.  development would also work on the Mac?
  2267.  
  2268.  One reason was to get the PC product out sooner. It was simply too hard to
  2269.  find good Windows programmers at such an early stage in the game. "The PC
  2270.  project was definitely resource starved," Johnson explains, "until the Mac
  2271.  team's talents were brought to bear."
  2272.  
  2273.  
  2274.  Common Benefits
  2275.  
  2276.  The benefits to Aldus of a common code approach, says Jaech, are several.
  2277.  "Since 80 percent of the code is shared, you usually implement a feature
  2278.  just once, not twice. Also you only have to fix a bug once, unless it's
  2279.  environment specific. And from a maintenance point of view, people over in
  2280.  customer service trying to deal with phone calls won't have to remember two
  2281.  sets of technical issues and problems."
  2282.  
  2283.  Finally there's the advantage of file compatibility. PageMaker files will be
  2284.  interchangeable between the Mac and the PC, as will import filters for key
  2285.  word processing products.
  2286.  
  2287.  "We didn't plan it that way," says Jaech. But, as with most of the spinoffs
  2288.  of the decision to write common source code, it seems to have worked out for
  2289.  the best.
  2290.  
  2291.  ────────────────────────────────────────────────────────────────────────────
  2292.  
  2293.  Moving Toward an Industry Standard for Developing TSRs
  2294.  
  2295.  Nancy Andrews
  2296.  
  2297.  Terminate-and-stay-resident programs──"pop ups"──are like people: they can't
  2298.  live together but they can't live alone either. If you are running Microsoft
  2299.  Word, for example, you cannot check spelling interactively with Turbo
  2300.  Lightning. If you interrupt Lotus(R) 1-2-3(R) with SideKick, strange things
  2301.  can happen when you return. If you run XyWrite you can't use any TSRs. And
  2302.  if you run two or more TSRs, there's no knowing how they will interact.
  2303.  
  2304.  Currently all software developers program their TSRs a little differently.
  2305.  There is no established set of programming rules to ensure smooth
  2306.  interaction with other TSRs and with the operating system itself. To make a
  2307.  TSR work with everyone else's requires an enormous programming
  2308.  commitment──it must be tested against everything in the marketplace. This
  2309.  includes not only other TSRs but normal applications as well.
  2310.  
  2311.  Some normal applications make life difficult for TSRs. XyWrite, for example,
  2312.  steals the hardware keyboard interrupt, thus locking out any TSR that also
  2313.  requires INT 9. Are there "offenders," TSRs that purposely try to be
  2314.  exclusive, taking the system resources they need without regard for others?
  2315.  
  2316.  John Socha, chief programmer at Peter Norton Computing, says no. Different
  2317.  software vendors have depended upon different approaches to solving problems
  2318.  in a world where there are no rules.
  2319.  
  2320.  Others who are not so kind cite Borland as an offender; Borland's SideKick
  2321.  takes the keyboard interrupt, for example, and then at each timer tick
  2322.  checks to see if anyone else has taken it. If another program has it, then
  2323.  SideKick will steal it back. These factors complicate writing a TSR, making
  2324.  it a tough job to deliver a good and flexible product.
  2325.  
  2326.  One of the reasons all TSRs work differently is that TSR controls are not
  2327.  built into MS-DOS(R). There was no such thing as a TSR in the UNIX(R) world.
  2328.  
  2329.  "It was a radically new idea," says Socha, "to be able to change the
  2330.  behavior of an existing program──a dynamic rather than a background
  2331.  process──and to add new features without having the source code."
  2332.  
  2333.  Later operating systems like the Apple(R) Macintosh did incorporate TSR
  2334.  controls into the operating system. The Mac makes its desk accessories
  2335.  constantly available on the Apple menu and handles their interactions for
  2336.  you.
  2337.  
  2338.  Because current versions of MS-DOS do not provide similar capabilities,
  2339.  Microsoft is part of the team working toward developing standards or
  2340.  guidelines. According to Adrian King, Microsoft's Director of Operating
  2341.  Systems, future versions of MS-DOS will address this at the outset. King,
  2342.  however, declined to comment about which versions, when, and how.
  2343.  
  2344.  
  2345.  The Solution
  2346.  
  2347.  A group of software developers co-chaired by Adrian King of Microsoft and
  2348.  Tony Middleton of Softronics, and hosted by Softronics, met in Colorado in
  2349.  May. King said that his goal was to put together standards "of maximum
  2350.  benefit to the software community that could be wholeheartedly endorsed by
  2351.  as many organizations as possible." Lynn Stricklan from Softronics said
  2352.  that what he wanted was standards that would make TSRs "clean and
  2353.  nonviolent."
  2354.  
  2355.  Participants at the conference agreed to agree that they were not able to
  2356.  issue a standard──a formal definition of rules. Instead, they aimed for the
  2357.  creation of a set of programming guidelines, and they called their efforts
  2358.  "Programming Guidelines for MS-DOS Co-Resident Software."
  2359.  
  2360.  
  2361.  The Guidelines
  2362.  
  2363.  Microsoft produced a draft of these guidelines. The original draft included
  2364.  the following: a set of operational rules for TSRs, specifications for their
  2365.  order of loading, a set of data records that describe operational
  2366.  characteristics, and a program interface to allow other applications to
  2367.  avail themselves of a TSR's functions.
  2368.  
  2369.  Two parts included in the original draft but recognized as unfeasible were a
  2370.  mechanism for TSRs to uninstall and a procedure for loading TSRs into
  2371.  extended memory, leaving memory below 640K available for normal
  2372.  applications.
  2373.  
  2374.  Operational rules include two major areas: interrupts and maintaining
  2375.  software variables for changes that are made directly to the hardware. Major
  2376.  problems have occurred with the keyboard interrupts INT 9 and INT 16h. Some
  2377.  applications hook INT 9 and bypass INT 16h, thus preventing others from
  2378.  seeing the keyboard request.
  2379.  
  2380.  Other applications take complete control over the keyboard with INT 9,
  2381.  presumably to trap keystrokes that the BIOS does not generate, such as Ctrl-
  2382.  Up Arrow. The proposed way to handle interrupt conflicts is to always use
  2383.  INT 16h to get a keystroke and to chain the interrupts. Essentially,
  2384.  chaining stores the old interrupt vector inside the program before replacing
  2385.  it with its own vector.
  2386.  
  2387.  The code sample in Figure 1 illustrates how to chain into INT 9. This
  2388.  routine doesn't do anything useful now──you can insert your own code for
  2389.  that. It simply passes control back to the old INT 9 routine, which can be
  2390.  either the ROM BIOS routine or some other memory-resident program like
  2391.  Prokey. But as long as everyone does, in fact, chain interrupts, all should
  2392.  function properly and it shouldn't matter who gets control next.
  2393.  
  2394.  Other proposed interrupt operational rules prohibit setting a timer to
  2395.  retrieve an interrupt vector and using a stack only when interrupts are off
  2396.  or in a protected or non-reentrant area.
  2397.  
  2398.  The remaining operational rules require that the BIOS data area be updated
  2399.  in order to reflect any of the following alterations: changing video modes,
  2400.  setting the high-order attribute bit for background intensity, using a
  2401.  software cursor, or changing the EGA palette directly.
  2402.  
  2403.  If your program is interrupted by another TSR, it ought to know what to
  2404.  restore when it relinquishes control.
  2405.  
  2406.  The proposed data records to describe operational characteristics of TSRs
  2407.  include a Program Identification Record and an Interrupt Information Record
  2408.  (see Figure 2). Each TSR will have only one Program Information Record but
  2409.  will have an Interrupt Information Record for each interrupt vector it
  2410.  intercepts. The record includes a pointer to the old routine. This allows
  2411.  any program to trace through the chain of installed programs. The
  2412.  Interrupt_Priority value in the Interrupt Information Record will be
  2413.  assigned based on the type of program, and it can be used to control the
  2414.  order of loading TSRs. Keyboard macro processors such as SuperKey and
  2415.  Prokey need to be last in the chain and will be given high priority
  2416.  numbers.
  2417.  
  2418.  The guidelines also propose a TSR program interface. Such an interface would
  2419.  permit users to write programs that call functions provided by a TSR. This
  2420.  way a Turbo Pascal program could, for example, run a SuperKey macro.
  2421.  Proposed functions include Get Program Information By Name or Number
  2422.  functions, Activate and Deactivate functions, and Enable and Disable
  2423.  functions. This interface would be implemented by a set of subfunctions to
  2424.  function 52h on INT 15h, the cassette interrupt. INT 15h was chosen because
  2425.  it's used infrequently and has a lot of unused function numbers.
  2426.  
  2427.  
  2428.  More Details To Come
  2429.  
  2430.  The participants generally concurred with the proposed guidelines and
  2431.  determined that more detailed work was needed in four areas. These include:
  2432.  
  2433.  
  2434.    1. A revised set of rules for interaction with DOS. Currently TSRs depend
  2435.       on several undocumented MS-DOS features such as the IN_DOS flag (see
  2436.       Figure 3), the critical error flag, and some undocumented system calls.
  2437.       Microsoft's Adrian King has agreed to provide this information. Both
  2438.       Borland and Lotus say that this information is critical for TSRs to
  2439.       work consistently.
  2440.  
  2441.    2. A standard model for keyboard handling. This will most likely include
  2442.       scan codes for keys (such as Ctrl-Cursor Up) that don't currently
  2443.       exist. David Rose of Rosesoft and Roger Schlafley of Borland have been
  2444.       put in charge of this area.
  2445.  
  2446.    3. More extensive work on data structures. This will refine and expand the
  2447.       data structures section in the original guidelines. Norton's John Socha
  2448.       is in charge of data structures.
  2449.  
  2450.    4. A kernel to be added to DOS to take charge of RAM-resident programs.
  2451.       This kernel will tell the operating system what programs to install and
  2452.       where to install them, and it will allocate resources based on the
  2453.       priority of the requester. Lynn Stricklan of Softronics is
  2454.       investigating the feasibility of the kernel approach. Softronics
  2455.       currently uses a kernel to manage its RAM-resident programs.
  2456.  
  2457.  Participants agreed to have work completed in 90 days and to publish results
  2458.  on the CompuServe Microsoft SIG. Unfortunately, the 90 days have elapsed,
  2459.  and the work has not yet been completed. But King reports that the
  2460.  guidelines are "not dead." He expects to finish his part, and he encourages
  2461.  others to do the same. He says he hopes that we'll see a new draft on the
  2462.  SIG in early November.
  2463.  
  2464.  
  2465.  But Will They Work?
  2466.  
  2467.  Participants in the drafting of the TSR guidelines qualify their work. They
  2468.  want it to be understood that guidelines are "evolving," that right now they
  2469.  are a "moving target" and "will definitely change," that this is not a "be
  2470.  all and end all" solution, and that "enforcement is not possible." They
  2471.  caution against unmitigated optimism, pointing out that even if the
  2472.  guidelines are completed and generally accepted, developers will still have
  2473.  to deal with users who choose not to upgrade.
  2474.  
  2475.  But even with these qualifications, the possibility that both software
  2476.  developers and end users will benefit looks good. Writing a TSR will still
  2477.  be a difficult and complex task, but once the TSR is written, if it plays by
  2478.  the rules, software developers will know that it will work with any other
  2479.  TSR or application that also plays by the rules. If the big players──Lotus,
  2480.  Microsoft, Borland──agree to support the guidelines, others will as well,
  2481.  and the guidelines can do the job they're intended to do. So far this looks
  2482.  like a real possibility.
  2483.  
  2484.  David Reed from Lotus acknowledged that there are some incompatibilities
  2485.  between 1-2-3 and the guidelines, and said that once a consensus document
  2486.  has been produced, Lotus will make 1-2-3 and Spotlight, its TSR, conform. He
  2487.  points out that it is to their advantage to have their applications work
  2488.  with everyone else's and that this will directly reduce their support
  2489.  costs.
  2490.  
  2491.  Microsoft has taken an active role in this. It co-chaired the conference and
  2492.  agreed to provide the necessary information about DOS. Beyond that the
  2493.  company has also made some changes to its standard applications so that they
  2494.  will work better with TSRs.
  2495.  
  2496.  David Intersimone at Borland says that when everyone else writes well-
  2497.  behaved applications──that is, when the guidelines have been agreed to and
  2498.  implemented──Borland will too. He claims that SideKick programmers had no
  2499.  choice but to grab INT 9 back because some of the applications SideKick was
  2500.  expected to work with were ill-behaved and users expected SideKick to appear
  2501.  when they pressed Ctrl-****. And he says that Borland has gone out of its
  2502.  way to help developers work around the idiosyncrasies of SideKick.
  2503.  
  2504.  Phillipe Kahn says, "The whole issue of standardization should not be driven
  2505.  by the software publishers or the press but by the users." And when
  2506.  standardization actually happens, end users can't help but be the ultimate
  2507.  beneficiaries. They'll be able to choose from the full range of available
  2508.  software──to work with any combination of TSRs and applications without
  2509.  conflict.
  2510.  
  2511.  
  2512.  Figure 1:  Code Sample for Chaining Interrupts
  2513.  
  2514.  This code sample illustrates how to chain into INT 9. This routine won't
  2515.  be useful until you insert your own code; it just passes control back to the
  2516.  old INT 9 routine.
  2517.  
  2518.  CODE_SEG        SEGMENT
  2519.          ASSUME  CS:CODE_SEG
  2520.          ORG     100h
  2521.  
  2522.  BEGIN:          JMP     INIT_VECTORS   ;Initialize vectors and attach
  2523.                                         ;to DOS
  2524.  OLD_KEYBOARD_INT        DD      ?      ;Address for ROM routine
  2525.  
  2526.  ;-----------------------------------------------------------------;
  2527.  ; This procedure intercepts the INT 9 keyboard vector. Right now it
  2528.  ;  just calls the old INT 9 routine.
  2529.  ;
  2530.  ;-----------------------------------------------------------------;
  2531.  INTERCEPT_KEYBOARD_INT  PROC NEAR
  2532.  
  2533.          ###                             ;Put your code here
  2534.          CLI                             ;Disable interrupts
  2535.          JMP     OLD_KEYBOARD_INT        ;Chain back to the old Int 9
  2536.  INTERCEPT_KEYBOARD_INT  ENDP
  2537.  
  2538.  ;-----------------------------------------------------------------;
  2539.  ;  This procedure initializes the interrupt vectors and installs this
  2540.  ;  program. This routine also throws itself away after the install.
  2541.  ;
  2542.  ;-----------------------------------------------------------------;
  2543.  INIT_VECTORS    PROC NEAR
  2544.  MOV     AH,35h                     ;Get the old keyboard interrupt vector
  2545.  MOV     AL,9                            ;This is INT 9
  2546.  INT     21h                             ;Old vector now in ES:BX
  2547.  MOV     Word Ptr OLD_KEYBOARD_INT,BX
  2548.  MOV     AX,ES
  2549.  MOV     Word Ptr OLD_KEYBOARD_INT[2],AX
  2550.  
  2551.  MOV     AH,25h                  ;Set the new KEYBOARD_INT vector
  2552.  MOV     AL,9                            ;This is INT 9
  2553.  LEA     DX,INTERCEPT_KEYBOARD_INT
  2554.  INT     21h
  2555.  
  2556.  MOV     AX,3100h                        ;Terminate but stay resident
  2557.                                          ;with
  2558.                                          ;return code of
  2559.  0
  2560.  LEA     DX,INIT_VECTORS         ;End of resident portion
  2561.  ADD     DX,15                           ;Round up paragraph number
  2562.  MOV     CL,4                            ;Convert from bytes to
  2563.                                          ;paragraphs
  2564.  SHR     DX,CL                           ;Divide by 16
  2565.  INT     21h                             ;Terminate but stay resident
  2566.  INIT_VECTORS    ENDP
  2567.  
  2568.  CODE_SEG        ENDS
  2569.  
  2570.          END     BEGIN
  2571.  
  2572.  
  2573.  Figure 2:  Proposed Data Structures for TSRs
  2574.  
  2575.  These are the proposed data records to describe operational characteristics
  2576.  of TSRs. Each TSR will have one Program Information Record but will have an
  2577.  Interrupt Information Record for each interrupt record it intercepts.
  2578.  
  2579.  Program Identification Record -- PIDR
  2580.  
  2581.  Program_Record_ID       DB      "PIDR"
  2582.  Version_Number          DW      BCD version number
  2583.  Interrupt_List          DW      Near Pointer to list of interrupts
  2584.  Startup_Shift_Keys      DW      Near Pointer to shift-pairs
  2585.  Startup_Key_Codes       DW      Near Pointer to startup codes
  2586.  Options_Area            DW      Near Pointer to local data area
  2587.  Program_ID_String       DB      ASCIIZ string
  2588.  
  2589.  Interrupt Information Record -- IINR
  2590.  
  2591.  Down_Pointer            DD      Far pointer to old interrupt routine
  2592.  Program_ID                      DW      Near Pointer to PIDR
  2593.  Interrupt_priority              DB      Between 0 and 255 giving priority
  2594.  Function_Numbers                DB      Null-terminated function list
  2595.  
  2596.  To correlate interrupts with the associated IINR, each interrupt
  2597.  procedure must be preceded by a 6-byte record. The first four bytes
  2598.  identify it as a valid interrupt record, and the last two bytes point
  2599.  to the IINR for more information.
  2600.  
  2601.          DB      "SRID"
  2602.          DW      Offset Interrupt_Record
  2603.  
  2604.  Intercept_Interrupt     Proc Far
  2605.  ###
  2606.  ###
  2607.  Intercept_Interrupt     Endp
  2608.  -----------------------------------------------------------------
  2609.  
  2610.  
  2611.  Figure 3:  The IN_DOS Flag
  2612.  
  2613.  The IN_DOS flag is an undocumented MS-DOS feature that TSRs depend on.
  2614.  
  2615.  IN_DOS_FLAG     DD      ?       ;Address of IN_DOS flag
  2616.  
  2617.  MOV     AH,34h
  2618.  INT     21h                     ;Get pointer to IN_DOS flag
  2619.  MOV     Word Ptr IN_DOS_FLAG,BX
  2620.  MOV     Word Ptr IN_DOS_FLAG[2],ES
  2621.                                  ;Above four lines are init code -- they
  2622.                                  ;are done once to get address of flag
  2623.  
  2624.                                  ;Following 7 lines done each time to
  2625.                                  ;check if IN DOS
  2626.  PUSH    BX                      ;See if you can popup
  2627.  PUSH    DS
  2628.  LDS     BX,IN_DOS_FLAG  ;Set DS:BX to point to IN_DOS flag
  2629.  CMP     Byte Ptr [BX],0 ;Are we inside DOS?
  2630.  POP     DS
  2631.  POP     BX
  2632.  JNZ     DO_NOT_POPUP_NOW
  2633.  
  2634.  *This routine is not foolproof. For example, your program would never popup
  2635.  if you were at the DOS prompt. Information to make it usable in all
  2636.  situations will be provided with the revised guidelines (on CompuServe in
  2637.  the Microsoft SIG).
  2638.  
  2639.  ────────────────────────────────────────────────────────────────────────────
  2640.  
  2641.  A Step-by-Step Guide to Building Your First Windows Application
  2642.  
  2643.  Charles Petzold
  2644.  
  2645.  The notion of "building" a Windows application rather than simply "writing"
  2646.  one implies that the job involves more than just cranking out hot C code.
  2647.  This is true. While the core of most Microsoft Windows applications
  2648.  certainly is a C program, it is a C program that is oddly structured and
  2649.  makes heavy use of Windows functions, macros, and type definitions.
  2650.  
  2651.  A typical Windows application also requires several other files besides the
  2652.  C program. Much of the difficulty for programmers first approaching
  2653.  Microsoft Windows is the large amount of overhead and the new concepts
  2654.  needed just to get a small program off the ground.
  2655.  
  2656.  To clear away some of the mystery that surrounds building a Windows
  2657.  application, we'll put together a fairly simple program called Whatsize, or
  2658.  WSZ. WSZ displays the dimensions of its own window in units of pixels,
  2659.  millimeters, or inches. The program also allows you to switch this display
  2660.  between black text on a white background and white text on a black
  2661.  background.
  2662.  
  2663.  Despite its limited functionality, WSZ illustrates some basic Microsoft
  2664.  Windows concepts; demonstrates the use of such familiar Windows accessories
  2665.  as menus, icons, and dialog boxes; and offers some insight into the nature
  2666.  of device-independent applications.
  2667.  
  2668.  
  2669.  Getting Set Up
  2670.  
  2671.  I will assume that you have a Microsoft Windows Software Development Kit,
  2672.  the Microsoft C Compiler 4.00, a hard disk, and a mouse. Some of the
  2673.  procedures in building the Windows application are slightly different from
  2674.  the earlier C compiler included with the Software Development Kit.
  2675.  
  2676.  The files you'll need for this project are shown below in one possible
  2677.  subdirectory organization. Notations in parentheses indicates whether a file
  2678.  comes from the C Compiler 4.00 (C4) or the Software Development Kit (SDK).
  2679.  
  2680.    \MSC
  2681.      CL.EXE      (C4)
  2682.      P1.EXE      (C4)
  2683.      P2.EXE      (C4)
  2684.      P3.EXE      (C4)
  2685.      MAKE.EXE    (C4)
  2686.      RC.EXE      (SDK)
  2687.      RCPP.EXE    (SDK)
  2688.      LINK4.EXE   (C4)
  2689.      WINSTUB.EXE (SDK)
  2690.      MAPSYM.EXE  (SDK)
  2691.      SYMDEB.EXE  (SDK)
  2692.  
  2693.    \MSC\INC
  2694.      WINDOWS.H   (SDK)
  2695.  
  2696.            (and regular C header files from C4 if needed)
  2697.  
  2698.    \MSC\LIB
  2699.      SLIBC.LIB   (C4)
  2700.      SLIBW.LIB   (C4)
  2701.      SLIBFA.LIB  (C4)
  2702.      LIBH.LIB    (C4)
  2703.      (and other memory models from C4 if needed)
  2704.  
  2705.    \WINDOWS
  2706.      Installed version of Windows (SDK)
  2707.      ICONEDIT.EXE (SDK)
  2708.      DIALOG.EXE (optional)
  2709.  
  2710.    \WINDOWS\WSZ
  2711.      All WSZ files
  2712.  
  2713.  The environment variables necessary for the C compiler to get at the
  2714.  libraries and the include files are
  2715.  
  2716.    SET PATH=\MSC
  2717.    SET LIB=\MSC\LIB
  2718.    SET INCLUDE=\MSC\INC
  2719.  
  2720.  Microsoft Windows programmers generally do most of their development work
  2721.  (particularly editing source code and compiling) outside of Windows in
  2722.  regular old MS-DOS. This is due partly to the inadequacy of current Windows
  2723.  text editors and the problems that occur when running the C compiler in a
  2724.  limited memory environment.
  2725.  
  2726.  
  2727.  Creating an Icon
  2728.  
  2729.  We'll begin with one exception to this rule. Let's get into Microsoft
  2730.  Windows and start with a part of WSZ where you can ignore what I've done and
  2731.  exercise your own creativity.
  2732.  
  2733.  Most Windows applications have an icon that Windows displays when the
  2734.  program is parked downstairs at the bottom of the screen. You can create an
  2735.  icon for WSZ by using ICONEDIT (see Figure 1). Choose Icon from the mode
  2736.  menu, pick a pen color, a pen size, and then use the mouse to draw. For the
  2737.  icon I created for WSZ, I painted the surface white and then drew a question
  2738.  mark in black.
  2739.  
  2740.  The resolution of the bit-mapped icon you created in ICONEDIT will be
  2741.  considerably reduced when Windows displays the icon when your program runs.
  2742.  This is why ICONEDIT shows the icon in a reduced size at the left of the
  2743.  screen. If you use thin lines (three or fewer pixels wide) in your icon,
  2744.  they could possibly disappear when the icon is displayed. You'll eventually
  2745.  want to see how the icon looks on both a low-resolution (IBM CGA or
  2746.  equivalent) and medium-resolution (EGA or Hercules) display.
  2747.  
  2748.  When you finish creating your miniature masterpiece, save the icon as
  2749.  WSZ.ICO in the subdirectory WSZ.
  2750.  
  2751.  
  2752.  Resources
  2753.  
  2754.  That icon you just created is called a "resource." It will eventually become
  2755.  part of the WSZ.EXE executable file, but it is neither part of your
  2756.  program's code nor part of your program's data. Icons are not the only type
  2757.  of resource you can have in your .EXE file. Resources also include dialog
  2758.  boxes, menus, and (most preferably) all displayable text.
  2759.  
  2760.  Think of a resource as read-only data that is conveniently stored right in
  2761.  the application's .EXE file. In most cases, resources are not loaded from
  2762.  the disk into memory until they are needed. (This is why you'll often see a
  2763.  disk access when you pop up a dialog box.) Simple Microsoft Windows calls
  2764.  retrieve these resources from the disk so your program can use them. Because
  2765.  resources are read-only, Windows may discard them from memory when they are
  2766.  no longer needed and then reload them later if necessary. In an operating
  2767.  system that implements virtual memory, a resource currently in memory would
  2768.  not have to be saved to the disk because it would still be available in the
  2769.  same form from the .EXE file.
  2770.  
  2771.  Resources are defined in a resource script (.RC) file, which is an ASCII
  2772.  file you create in a normal text editor. The resource script for WSZ is
  2773.  called WSZ.RC and is shown in Figure 2. This file includes definitions for
  2774.  the icon, all of the displayable text strings used in the C program, a menu,
  2775.  and two dialog boxes.
  2776.  
  2777.  The dialog boxes are usually the most complex part of the resource script
  2778.  file. You can either work out the dialog box coordinates manually (as I've
  2779.  done here) or by using DIALOG.EXE (see Figure 3; also see "Latest Dialog
  2780.  Editor Speeds Windows Application Development," MSJ Vol. 1, Issue 1).
  2781.  
  2782.  The resource script file also contains all the displayable text strings that
  2783.  the C program will use. You are not required to put them in the resource
  2784.  script. In fact, defining text strings in the C program usually makes both
  2785.  the source file and the .EXE file somewhat smaller. The program will run
  2786.  faster (since it doesn't have to retrieve strings from disk) but will
  2787.  require more memory space because the strings have to remain in memory
  2788.  rather than reside on the disk. However, if you want to adapt Windows
  2789.  applications for foreign-language markets, collecting all displayable text
  2790.  into one relatively small file will be enormously helpful.
  2791.  
  2792.  The STRINGTABLE option in the resource script file can handle only single
  2793.  lines. If you need to include larger text strings in your program (for
  2794.  instance, for a "Help" window like PIFEDIT's), put this text into separate
  2795.  files and use the "user-defined" resources in the resource script file. You
  2796.  can then use the FindResource, LoadResource, and LockResource functions
  2797.  within your program to get pointers to those resources. The user-defined
  2798.  resource is a general-purpose facility that allows you to imbed any read-
  2799.  only data into the .EXE file and access it very easily with just three
  2800.  simple Microsoft Windows calls.
  2801.  
  2802.  
  2803.  Avoid Header Loss
  2804.  
  2805.  The names in the WSZ.RC file that begin with the letters "ID" are really
  2806.  just numbers that are defined as macros in the WSZ.H header file shown in
  2807.  Figure 4. It's possible to use macro names here in a resource script because
  2808.  the RC.EXE resource compiler has its own C-like preprocessor. Using names
  2809.  instead of numbers makes both the resource script and your C program easier
  2810.  to understand and maintain.
  2811.  
  2812.  The WSZ.RC file also has an include statement for WINDOWS.H, which comes
  2813.  with the Windows Software Development Kit. WINDOWS.H is a massive 80K header
  2814.  file that is much more important for compiling Windows C programs than
  2815.  resource scripts. Here it is used only to define the macro names beginning
  2816.  with "WS" (window style).
  2817.  
  2818.  
  2819.  The C Program
  2820.  
  2821.  Now that we've gotten some of the preliminaries out of the way, we're ready
  2822.  to start looking at some C code.
  2823.  
  2824.  The complete WSZ.C file is shown in Figures 5, 6, 7, 8 and 9. This file
  2825.  functions: WinMain, Initialization, MainWndProc, AboutWndProc, and
  2826.  UnitsWndProc.
  2827.  
  2828.  WSZ.H and WINDOWS.H are specified as include files at the top of the
  2829.  program. You will often find that it is helpful when you are programming
  2830.  Windows applications to consult the WINDOWS.H header file. It contains
  2831.  declarations for every Windows function and loads of #define and typedef
  2832.  definitions that ought to be used within Windows applications.
  2833.  
  2834.  Every Windows application requires a WinMain procedure. This is the entry
  2835.  point to the application. The WinMain procedure for WSZ is shown in Figure
  2836.  5.
  2837.  
  2838.  The input parameters to WinMain include two "handles," one to the current
  2839.  instance and another to the previous instance. When you load a Windows
  2840.  application, that's the first "instance" of the program, and there is no
  2841.  previous instance. If you load the same application without terminating the
  2842.  first, the previous instance handle will refer to the copy loaded
  2843.  previously.
  2844.  
  2845.  You'll run across handles a lot in Windows programming. Almost everything in
  2846.  Microsoft Windows (menus, windows, memory) is represented by a handle. If
  2847.  you look at the WINDOWS.H file you'll discover that the various handle data
  2848.  types are just plain old integers. Handles are just numbers that Windows
  2849.  uses to refer to things.
  2850.  
  2851.  WinMain also receives a command line parameter string. If the user of your
  2852.  application entered a parameter in the File Run box, this is where your
  2853.  application will get the parameter. The fourth parameter to WinMain
  2854.  ("nCmdShow") indicates the initial state of the application. It could be a
  2855.  window (if the application was invoked by File Run) or an icon (if File Load
  2856.  was used).
  2857.  
  2858.  After WinMain calls the Initialization routine, it sits in a small loop
  2859.  polling for messages from Microsoft Windows. When it gets a message, WinMain
  2860.  dispatches it off to somewhere else. Right now, this looks a little
  2861.  mysterious. Let's leave WinMain in this loop while we take a look at the
  2862.  Initialization function.
  2863.  
  2864.  
  2865.  Initialization
  2866.  
  2867.  The Initialization function (see Figure 6) does several chores necessary to
  2868.  get the application moving. The two most important chores are defining a
  2869.  "window class" and a "window." More than one window may use the same class.
  2870.  The window class defines such things as the standard cursor, the icon, and
  2871.  the window procedure. Creating the window defines the style and title of the
  2872.  window.
  2873.  
  2874.  If you run more than one copy of WSZ in Windows, different instances of the
  2875.  application will use the same code segment, but different data segments.
  2876.  This reduces memory use considerably. Different instances of the same
  2877.  application will have different windows, but the windows will use the same
  2878.  window class. This is the reason we define the window class only if this is
  2879.  the first instance of the program.
  2880.  
  2881.  Although each instance of a Windows application will generally have its own
  2882.  data segment, the instances are able to share some data. This is illustrated
  2883.  by the two GetInstanceData calls.
  2884.  
  2885.  
  2886.  Window Procedure
  2887.  
  2888.  When we last left WinMain, it was sitting in a loop getting messages from
  2889.  Microsoft Windows and dispatching them somewhere. Where these messages
  2890.  ultimately go is the MainWndProc procedure shown in Figure 7. This is a
  2891.  window procedure. It receives messages from Windows regarding everything
  2892.  that affects the WSZ window. Every keystroke, every mouse click, even every
  2893.  movement of the mouse is a message. Within a window procedure, you can
  2894.  ignore many of these messages by passing them on to the Windows function
  2895.  DefWindowProc.
  2896.  
  2897.  The message handling in window procedures makes Windows programming seem
  2898.  very strange to programmers who have previously worked in more traditional
  2899.  environments. Usually a program makes a call to the operating system to find
  2900.  out what's going on. Microsoft Windows is different. From the viewpoint of
  2901.  the window procedures, it seems like Windows is calling your program to tell
  2902.  you what's going on. If you feel comfortable with that concept, stick with
  2903.  it. Otherwise, you can think of DispatchMessage as initiating the call to
  2904.  the window procedure.
  2905.  
  2906.  MainWndProc handles only a few of the messages that are sent to it by
  2907.  Windows. The WM_CREATE message is sent by Windows as a result of the
  2908.  CreateWindow call in Initialization. WSZ takes this opportunity to retrieve
  2909.  some of the information that will not be changing during the Windows
  2910.  session. This information includes the size (in both millimeters and pixels)
  2911.  of the entire display surface and the dimensions of a character that is in
  2912.  the default system font.
  2913.  
  2914.  Microsoft Windows sends a WM_SIZE message to the window procedure when the
  2915.  window is first displayed and whenever the window is resized. The new
  2916.  dimensions of the window are encoded in the lParam variable. The dimensions
  2917.  refer only to the "client area," which excludes the caption bar, menu, and
  2918.  scroll bars. This is the area that a Windows application is free to write
  2919.  in.
  2920.  
  2921.  A window procedure will receive a WM_ERASEBKG any time Windows wants it to
  2922.  erase the background of the window client area. The color of the background
  2923.  is defined as part of the window class. Since WSZ will be coloring the
  2924.  background itself, all we need to do is tell Windows not to erase the
  2925.  background.
  2926.  
  2927.  Windows sends window procedures a WM_PAINT message whenever the client area
  2928.  needs repainting. This can happen after the window has been resized (in
  2929.  which case it has been preceded by a WM_SIZE message) or after a pop-up menu
  2930.  has been removed. This is where WSZ will do most of its work. It calculates
  2931.  values to write the display, colors the whole client area with PatBlt, loads
  2932.  strings from the resource table with LoadString, and then writes text to the
  2933.  screen with a combination of DrawText and the regular C sprintf function.
  2934.  
  2935.  Generally, Windows applications use TextOut rather than DrawText for simple
  2936.  text strings. However, DrawText provides such amenities as centering and
  2937.  word-wrap options. The text is drawn in a rectangle indicated by the rect
  2938.  structure. The rectangle is defined to allow a top and bottom border equal
  2939.  to the height of a character and a left and right border equal to the width
  2940.  of a character.
  2941.  
  2942.  Creating a device-independent application requires that you not make any
  2943.  assumptions about the size of the display or the client area or the
  2944.  character sizes. You will probably find that it works best to dynamically
  2945.  design window displays within your program based around the size of a
  2946.  default character rather than around hard-coded constants.
  2947.  
  2948.  
  2949.  Dialog Boxes
  2950.  
  2951.  The WM_SYSCOMMAND message means that the user of the application has
  2952.  selected something from the system menu. Normally we wouldn't care, except
  2953.  that we've added "About..." to the system menu. If About... has been
  2954.  selected, then WSZ calls DialogBox to indicate that control should now
  2955.  transfer to the procedure called AboutWndProc (see Figure 8).
  2956.  
  2957.  Because the About dialog box is fairly simple (just some text and an "Ok"
  2958.  button), AboutWndProc is also simple. Microsoft Windows is responsible for
  2959.  actually displaying the dialog box and passing messages back to
  2960.  AboutWndProc. The only message that we really care about is a WM_COMMAND
  2961.  message, which means that the Ok button has been hit.
  2962.  
  2963.  When the MainWndProc receives a WM_COMMAND message, it knows that the user
  2964.  has selected something from the window menu (rather than from the system
  2965.  menu). The two choices from the Color menu option (ID_BLACK and ID_WHITE)
  2966.  simply require changing a checkmark and then saving the CurrentColor. The
  2967.  Units menu selection then passes control to UnitsWndProc (see Figure 9),
  2968.  another dialog box.
  2969.  
  2970.  Note that both the menus and dialog boxes make full use of the same mouse
  2971.  and keyboard interface as in other Windows applications. Yet nowhere does
  2972.  WSZ make any explicit keyboard or mouse calls.
  2973.  
  2974.  
  2975.  Definitions
  2976.  
  2977.  Finally (well, almost finally), a Windows application requires a Definition
  2978.  (.DEF) file. The Definition file contains information about the program
  2979.  segments and procedures that LINK4 (the Windows linker) needs in order to
  2980.  construct the .EXE file. WSZ.DEF is shown in Figure 10v1n2a3fa.
  2981.  
  2982.  The code and data segments are both defined as MOVEABLE, which means that
  2983.  Microsoft Windows can move them around in memory in order to make room for
  2984.  other programs. The idea that Windows may be moving your program around in
  2985.  memory may give you the willies, and it should. Many Windows bugs result
  2986.  from doing such things as saving far pointers (where they become invalid) or
  2987.  not properly locking and unlocking allocated memory.
  2988.  
  2989.  The MainWndProc, AboutWndProc, and UnitsWndProc routines are very special
  2990.  because they are called by Windows. These routines must be specified as
  2991.  EXPORTS in the WSZ.DEF file. The STUB called WINSTUB.EXE is a small program
  2992.  that LINK4 embeds in the .EXE file. Try running WINSTUB.EXE on the DOS
  2993.  command level to see what it does.
  2994.  
  2995.  
  2996.  Putting It All Together
  2997.  
  2998.  So far we've created five different source files with the extensions .ICO,
  2999.  .RC, .H, .C, and .DEF──all for just one application. Now we have to run
  3000.  these files through the RC.EXE resource compiler, the CL.EXE C compiler, and
  3001.  the LINK4 linker.
  3002.  
  3003.  You may be wondering how you're going to keep this mess straight. If you
  3004.  decide to change the icon file, what do you have to do to bring everything
  3005.  up to date? It's a problem, and that's why all good Windows programmers use
  3006.  MAKE.
  3007.  
  3008.  MAKE.EXE is a program maintainer. The "make-file" for an application
  3009.  contains sections that look like this:
  3010.  
  3011.    target: dependent
  3012.            command
  3013.  
  3014.  If the file change date of any "dependent" file is later than the file
  3015.  change date of the "target" file, then the "command" is run. Otherwise, it
  3016.  is not run.
  3017.  
  3018.  The make-file for WSZ is shown in Figure 11. By convention, make-files have
  3019.  no extension, so the file is just called WSZ. By executing
  3020.  
  3021.    MAKE WSZ
  3022.  
  3023.  after making changes to your source files, you can bring the whole thing up
  3024.  to date.
  3025.  
  3026.  The make-file also serves as a form of documentation of the different pieces
  3027.  that contribute to the application and indicates how to recreate the program
  3028.  from the source files.
  3029.  
  3030.  
  3031.  From Source to .EXE
  3032.  
  3033.  Figure 12 shows a system flowchart of the various WSZ files and how they
  3034.  eventually get into the WSZ.EXE executable file.
  3035.  
  3036.  Some of this should look normal. The CL.EXE C Compiler uses the WSZ.C source
  3037.  code, and two header files to create a WSZ.OBJ object file. The command line
  3038.  options may look excessive, but they are all there for a reason. The -Gw
  3039.  option, for instance, adds some special Windows Prolog code to far
  3040.  procedures.
  3041.  
  3042.  LINK4.EXE is much like the normal LINK program. It uses the WSZ.OBJ file and
  3043.  C .LIB library files and creates an executable WSZ.EXE file. But this .EXE
  3044.  file is not the same format as the .EXE files we've been using for 5 years
  3045.  with MS-DOS. These .EXE files have expanded header information, and some of
  3046.  this information will come from the WSZ.DEF definition file.
  3047.  
  3048.  One apparent oddity in this flowchart is that the resource compiler (RC.EXE)
  3049.  must be run twice, once at the beginning and again at the end. This is
  3050.  because the resource compiler has to do two things: First, it must compile
  3051.  your ASCII .RC file into a binary .RES file, and second, it must append data
  3052.  from the .RES file to your .EXE file and set up pointers in the .EXE file
  3053.  header to reference each resource.
  3054.  
  3055.  To do both these steps at once (assuming LINK4 has already created an .EXE
  3056.  file), you would execute
  3057.  
  3058.    RC FILENAME [.RC]
  3059.  
  3060.  This creates the compiled .RES file from your .RC file and copies the
  3061.  contents of the .RES file to the .EXE file. However, this approach creates
  3062.  problems with program maintenance. If you need to relink following a C
  3063.  source code change, you don't need to recompile the resource script. All you
  3064.  need to do is add the existing .RES data to the new .EXE file.
  3065.  
  3066.  For this reason it's better to use RC.EXE in two separate steps:
  3067.  
  3068.    RC -r FILENAME [.RC]
  3069.  
  3070.  creates the compiled .RES file from the .RC file, and
  3071.  
  3072.    -RC FILENAME.RES
  3073.  
  3074.  copies the data from the .RES file to the .EXE file.
  3075.  
  3076.  If you change the .RC file now, you'll have to recompile it with RC.EXE,
  3077.  relink, then use RC.EXE to add the new compiled resources to the .EXE file.
  3078.  But if you change something that affects only the C compilations (which is
  3079.  more often the case), then you need only relink and add the .RES file to the
  3080.  .EXE file. You don't have to recompile the resource script.
  3081.  
  3082.  
  3083.  The Rewards
  3084.  
  3085.  Building a Windows application up from the beginning is no picnic. Yet
  3086.  neither is writing your own graphics routines, menu logic, and dialog
  3087.  boxes──and Microsoft Windows does all that for you.
  3088.  
  3089.  
  3090.  Figure 2:  WSZ.RC
  3091.  
  3092.  Th resource script for WSZ, called WSZ.RC. This file includes definitions
  3093.  for the icon, all of the displayable text strings used in the C program, a
  3094.  menu, and two dialog boxes.
  3095.  
  3096.  #include <windows.h>
  3097.  #include "WSZ.h"
  3098.  
  3099.  WhatSize ICON WSZ.ico
  3100.  
  3101.  STRINGTABLE
  3102.      BEGIN
  3103.          IDS_NAME,   "WhatSize"
  3104.          IDS_ABOUT,  "About..."
  3105.          IDS_TITLE,  "What Size is the Window?"
  3106.          IDS_FORMAT, "%.3G %s by %.3G %s"
  3107.          ID_MILLIM,  "millimeters"
  3108.          ID_INCHES,  "inches"
  3109.          ID_PIXELS,  "pixels"
  3110.      END
  3111.  
  3112.  WhatSize MENU
  3113.      BEGIN
  3114.          POPUP "Colors"
  3115.              BEGIN
  3116.                  MENUITEM "Black on White", ID_BLACK
  3117.                  MENUITEM "White on Black", ID_WHITE
  3118.              END
  3119.          MENUITEM "Units", IDM_UNITS
  3120.      END
  3121.  
  3122.  AboutBox DIALOG 20, 20, 144, 75
  3123.      STYLE WS_POPUP | WS_DLGFRAME
  3124.      BEGIN
  3125.          CTEXT "What Size?",             -1, 37,  5,  68,  8
  3126.          ICON  "WhatSize",               -1,  9, 23,   0,  0
  3127.          CTEXT "A Windows Application",  -1,  0, 14, 144,  8
  3128.          CTEXT "Version 1.00",           -1, 38, 34,  64,  8
  3129.          DEFPUSHBUTTON "Ok",           IDOK, 53, 59,  32, 14, WS_GROUP
  3130.      END
  3131.  
  3132.  UnitsBox DIALOG 20, 20, 100, 90
  3133.      STYLE WS_POPUP | WS_BORDER
  3134.      CAPTION "What Size Units"
  3135.      BEGIN
  3136.          RADIOBUTTON "Pixels",ID_PIXELS,20,5,60,15,WS_GROUP | WS_TABSTOP
  3137.          RADIOBUTTON "Millimeters", ID_MILLIM, 20, 25, 60, 15
  3138.          RADIOBUTTON "Inches",      ID_INCHES, 20, 45, 60, 15
  3139.          DEFPUSHBUTTON "Ok",        IDOK,      10, 70, 32, 15, WS_GROUP
  3140.          PUSHBUTTON "Cancel",       IDCANCEL,  58, 70, 32, 15
  3141.      END
  3142.  
  3143.  
  3144.  Figure 4:  WSZ.H Header File
  3145.  
  3146.  The WSZ.H header file contains numbers that are defined as macros, which
  3147.  become the names in the WSZ.RC file that begin with the letters "ID".
  3148.  
  3149.  #define IDS_NAME        101
  3150.  #define IDS_ABOUT       102
  3151.  #define IDS_TITLE       103
  3152.  #define IDS_FORMAT      104
  3153.  
  3154.  #define ID_PIXELS       105
  3155.  #define ID_MILLIM       106
  3156.  #define ID_INCHES       107
  3157.  #define ID_BLACK        108
  3158.  #define ID_WHITE        109
  3159.  
  3160.  #define IDM_ABOUT       110
  3161.  #define IDM_UNITS       111
  3162.  
  3163.  
  3164.  Figure 5:  WinMain Function for WSZ
  3165.  
  3166.  The WinMain procedure for WSZ. Every Windows application requires such a
  3167.  procedure, which is the entry point to the application.
  3168.  
  3169.  /*  whatsize -- Windows application in C */
  3170.  
  3171.  #include <windows.h>
  3172.  #include "wsz.h"
  3173.  
  3174.  long FAR PASCAL MainWndProc (HWND, unsigned, WORD, LONG) ;
  3175.  BOOL FAR PASCAL AboutWndProc (HWND, unsigned, WORD, LONG) ;
  3176.  BOOL FAR PASCAL UnitsWndProc (HWND, unsigned, WORD, LONG) ;
  3177.  
  3178.  FARPROC lpAbout ;
  3179.  FARPROC lpUnits ;
  3180.  HANDLE  hInst;
  3181.  int     CurrentUnits = ID_PIXELS ;
  3182.  int     CurrentColor = ID_BLACK ;
  3183.  
  3184.  int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
  3185.      HANDLE hInstance, hPrevInstance;
  3186.      LPSTR  lpszCmdLine;
  3187.      int    nCmdShow;
  3188.      {
  3189.      MSG    msg;
  3190.  
  3191.      if (!Initialize (hInstance, hPrevInstance, lpszCmdLine, nCmdShow))
  3192.          return FALSE ;
  3193.  
  3194.      while (GetMessage ((LPMSG)&msg, NULL, 0, 0))
  3195.          {
  3196.          TranslateMessage ((LPMSG)&msg) ;
  3197.          DispatchMessage ((LPMSG)&msg) ;
  3198.          }
  3199.      return (msg.wParam) ;
  3200.      }
  3201.  
  3202.  
  3203.  Figure 6:  Initialization Function for WSZ
  3204.  
  3205.  The Initialization function performs several of the chores necessary to get
  3206.  the application moving. The two most important chores are deining a "window
  3207.  class" and a "window."
  3208.  
  3209.  BOOL Initialize (hInstance, hPrevInst, lpszCmdLine, nCmdShow)
  3210.      HANDLE   hInstance, hPrevInst ;
  3211.      LPSTR    lpszCmdLine ;
  3212.      int      nCmdShow ;
  3213.      {
  3214.      char     *szAppName [10] ;
  3215.      char     *szAbout [10] ;
  3216.      char     *szTitle [30] ;
  3217.      WNDCLASS wndclass ;
  3218.      HWND     hWnd;
  3219.      HMENU    hMenu;
  3220.  
  3221.      LoadString (hInstance, IDS_NAME, (LPSTR) szAppName, 10) ;
  3222.      LoadString (hInstance, IDS_ABOUT, (LPSTR) szAbout, 10) ;
  3223.      LoadString (hInstance, IDS_TITLE, (LPSTR) szTitle, 30 ) ;
  3224.  
  3225.      if (!hPrevInst)
  3226.          {
  3227.          wndclass.style        = CS_HREDRAW | CS_VREDRAW;
  3228.          wndclass.lpfnWndProc  = MainWndProc;
  3229.          wndclass.cbClsExtra   = 0;
  3230.          wndclass.cbWndExtra   = 0;
  3231.          wndclass.hInstance    = hInstance ;
  3232.          wndclass.hIcon        = LoadIcon (hInstance, (LPSTR) szAppName);
  3233.          wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW);
  3234.          wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH);
  3235.          wndclass.lpszMenuName = (LPSTR) szAppName;
  3236.          wndclass.lpszClassName= (LPSTR) szAppName;
  3237.  
  3238.          if (!RegisterClass ((LPWNDCLASS) &wndclass))
  3239.              return FALSE;
  3240.          }
  3241.      else
  3242.          {
  3243.          GetInstanceData(hPrevInst,(NPSTR)&CurrentUnits,sizeof(int));
  3244.          GetInstanceData(hPrevInst,(NPSTR)&CurrentColor,sizeof(int));
  3245.          }
  3246.  
  3247.      hWnd = CreateWindow (
  3248.              (LPSTR) szAppName,  /* class name       */
  3249.              (LPSTR) szTitle,    /* caption title    */
  3250.              WS_TILEDWINDOW,     /* windows style    */
  3251.              0,                  /* x (ignored)      */
  3252.              0,                  /* y (ignored)      */
  3253.              0,                  /* width (ignored)  */
  3254.              0,                  /* height (ignored) */
  3255.              (HWND) NULL,        /* parent (none)    */
  3256.              (HMENU) NULL,       /* menu (use class) */
  3257.              (HANDLE) hInstance, /* instance handle  */
  3258.              (LPSTR) NULL) ;     /* parameters       */
  3259.  
  3260.      hInst = hInstance ;
  3261.  
  3262.      lpAbout = MakeProcInstance ((FARPROC) AboutWndProc, hInstance) ;
  3263.      lpUnits = MakeProcInstance ((FARPROC) UnitsWndProc, hInstance) ;
  3264.  
  3265.      hMenu = GetSystemMenu (hWnd, FALSE) ;
  3266.      ChangeMenu (hMenu, 0, NULL, 999, MF_APPEND | MF_SEPARATOR) ;
  3267.      ChangeMenu (hMenu, 0, (LPSTR) szAbout, IDM_ABOUT,
  3268.        MF_APPEND | MF_STRING) ;
  3269.  
  3270.  
  3271.      hMenu = GetMenu (hWnd) ;
  3272.      CheckMenuItem (hMenu, CurrentColor, MF_CHECKED) ;
  3273.  
  3274.      ShowWindow (hWnd, nCmdShow) ;
  3275.      UpdateWindow (hWnd) ;
  3276.  
  3277.      return TRUE ;
  3278.      }
  3279.  
  3280.  
  3281.  Figure 7:  MainWndProc Procedure for WSZ
  3282.  
  3283.  MainWndProc is a window procedure that receives messages from windows on
  3284.  everything that affects the WSZ window.
  3285.  
  3286.  long FAR PASCAL MainWndProc (hWnd, message, wParam, lParam)
  3287.      HWND       hWnd;
  3288.      unsigned   message;
  3289.      WORD       wParam;
  3290.      LONG       lParam;
  3291.      {
  3292.      HMENU      hMenu ;
  3293.      static int CharHorzPix, CharVertPix ;
  3294.      static int ScrnHorzPix, ScrnVertPix ;
  3295.      static int ScrnHorzMil, ScrnVertMil ;
  3296.      static int WindHorzPix, WindVertPix ;
  3297.  
  3298.      switch (message)
  3299.          {
  3300.          case WM_CREATE:
  3301.              {
  3302.              TEXTMETRIC tm ;
  3303.              HDC        hDC = GetDC (hWnd) ;
  3304.  
  3305.              GetTextMetrics (hDC, (LPTEXTMETRIC) &tm) ;
  3306.              CharHorzPix = tm.tmAveCharWidth ;
  3307.              CharVertPix = tm.tmHeight ;
  3308.  
  3309.              ScrnHorzPix = GetDeviceCaps (hDC, HORZRES) ;
  3310.              ScrnVertPix = GetDeviceCaps (hDC, VERTRES) ;
  3311.              ScrnHorzMil = GetDeviceCaps (hDC, HORZSIZE) ;
  3312.              ScrnVertMil = GetDeviceCaps (hDC, VERTSIZE) ;
  3313.  
  3314.              ReleaseDC (hWnd, hDC) ;
  3315.              }
  3316.              break ;
  3317.  
  3318.          case WM_SIZE:
  3319.              WindHorzPix = LOWORD (lParam) ;
  3320.              WindVertPix = HIWORD (lParam) ;
  3321.              break ;
  3322.  
  3323.          case WM_ERASEBKGND:
  3324.              return TRUE ;
  3325.  
  3326.          case WM_PAINT:
  3327.              {
  3328.              PAINTSTRUCT ps ;
  3329.              char        szFormat [20] ;
  3330.              char        szUnits [20] ;
  3331.              char        szBuffer [60] ;
  3332.              float       nHorz = (float) WindHorzPix ;
  3333.              float       nVert = (float) WindVertPix ;
  3334.              RECT        rect ;
  3335.  
  3336.              if (CurrentUnits != ID_PIXELS)
  3337.                  {
  3338.                  nHorz *= (float) ScrnHorzMil / ScrnHorzPix ;
  3339.                  nVert *= (float) ScrnVertMil / ScrnVertPix ;
  3340.                  }
  3341.              if (CurrentUnits == ID_INCHES)
  3342.                  {
  3343.                  nHorz /= 25.4 ;
  3344.                  nVert /= 25.4 ;
  3345.                  }
  3346.  
  3347.              BeginPaint (hWnd, (LPPAINTSTRUCT) &ps) ;
  3348.  
  3349.    PatBlt (ps.hdc, 0, 0, WindHorzPix, WindVertPix,
  3350.                 (CurrentColor == ID_WHITE) ? BLACKNESS : WHITENESS) ;
  3351.  
  3352.              if (CurrentColor == ID_WHITE)
  3353.                  {
  3354.                  SetTextColor (ps.hdc, RGB (255, 255, 255)) ;
  3355.                  SetBkColor (ps.hdc, RGB (0, 0, 0)) ;
  3356.                  }
  3357.              LoadString (hInst, IDS_FORMAT, (LPSTR) szFormat, 20) ;
  3358.              LoadString (hInst, CurrentUnits, (LPSTR) szUnits, 20) ;
  3359.  
  3360.              rect.bottom = WindVertPix - (rect.top  = CharVertPix) ;
  3361.              rect.right  = WindHorzPix - (rect.left = CharHorzPix) ;
  3362.  
  3363.              DrawText (ps.hdc, (LPSTR) szBuffer,
  3364.                  sprintf(szBuffer,szFormat,nHorz,szUnits,nVert,szUnits),
  3365.                  (LPRECT) &rect, DT_CENTER | DT_WORDBREAK) ;
  3366.  
  3367.              EndPaint (hWnd, (LPPAINTSTRUCT) &ps) ;
  3368.              }
  3369.              break;
  3370.  
  3371.          case WM_SYSCOMMAND:
  3372.              switch (wParam)
  3373.                  {
  3374.                  case IDM_ABOUT:
  3375.                      DialogBox(hInst,(LPSTR)"AboutBox",hWnd,lpAbout);
  3376.                      break;
  3377.  
  3378.                  default:
  3379.                      return DefWindowProc(hWnd,message,wParam,lParam);
  3380.                  }
  3381.              break;
  3382.  
  3383.          case WM_COMMAND :
  3384.              switch (wParam)
  3385.                  {
  3386.                  case ID_BLACK:
  3387.                  case ID_WHITE:
  3388.                      hMenu = GetMenu (hWnd) ;
  3389.                      CheckMenuItem(hMenu,CurrentColor,MF_UNCHECKED);
  3390.                      CheckMenuItem (hMenu, CurrentColor = wParam,
  3391.                           MF_CHECKED) ;
  3392.                      InvalidateRect (hWnd, (LPRECT) NULL, TRUE) ;
  3393.                      break ;
  3394.  
  3395.                  case IDM_UNITS:
  3396.                      if (DialogBox (hInst, (LPSTR) "UnitsBox", hWnd,
  3397.                                lpUnits))
  3398.                           InvalidateRect (hWnd, (LPRECT) NULL, TRUE) ;
  3399.                      break ;
  3400.  
  3401.                  default :
  3402.                      return DefWindowProc (hWnd, message, wParam, lParam) ;
  3403.                  }
  3404.              break ;
  3405.  
  3406.          case WM_DESTROY:
  3407.              PostQuitMessage (0) ;
  3408.              break;
  3409.  
  3410.          default:
  3411.              return DefWindowProc (hWnd, message, wParam, lParam) ;
  3412.              break;
  3413.          }
  3414.      return (0L) ;
  3415.      }
  3416.  
  3417.  
  3418.  Figure 8:  AboutWndProc Procedure for WSZ
  3419.  
  3420.  AboutWndProc is the window procedure for the dialog box called up by
  3421.  selecting the About option from the menu.
  3422.  
  3423.  BOOL FAR PASCAL AboutWndProc (hDlg, message, wParam, lParam)
  3424.      HWND     hDlg ;
  3425.      unsigned message ;
  3426.      WORD     wParam ;
  3427.      LONG     lParam ;
  3428.      {
  3429.      switch (message)
  3430.          {
  3431.          case WM_INITDIALOG :
  3432.              return TRUE ;
  3433.  
  3434.          case WM_COMMAND :
  3435.              EndDialog (hDlg, TRUE) ;
  3436.              return TRUE ;
  3437.  
  3438.          default:
  3439.              return FALSE ;
  3440.          }
  3441.      }
  3442.  
  3443.  
  3444.  Figure 9:  UnitsWndProc Procedure for WSZ
  3445.  
  3446.  UnitsWndProc is the window procedure for the dialog box called up by
  3447.  selecting the Units option from the menu.
  3448.  
  3449.  BOOL FAR PASCAL UnitsWndProc (hDlg, message, wParam, lParam)
  3450.      HWND       hDlg ;
  3451.      unsigned   message ;
  3452.      WORD       wParam ;
  3453.      LONG       lParam ;
  3454.      {
  3455.      static int NewUnits ;
  3456.  
  3457.      switch (message)
  3458.          {
  3459.          case WM_INITDIALOG :
  3460.              CheckRadioButton (hDlg,ID_PIXELS,ID_INCHES,CurrentUnits);
  3461.              SetFocus (GetDlgItem (hDlg, NewUnits = CurrentUnits)) ;
  3462.              return FALSE ;
  3463.  
  3464.          case WM_COMMAND :
  3465.              switch (wParam)
  3466.                  {
  3467.                  case ID_MILLIM:
  3468.                  case ID_INCHES:
  3469.                  case ID_PIXELS:
  3470.                      NewUnits = wParam ;
  3471.                      CheckRadioButton (hDlg,ID_PIXELS,ID_INCHES,NewUnits);
  3472.                      break ;
  3473.  
  3474.                  case IDOK:
  3475.                      CurrentUnits = NewUnits ;
  3476.                      EndDialog (hDlg, TRUE) ;
  3477.                      break ;
  3478.  
  3479.                  case IDCANCEL:
  3480.                      EndDialog (hDlg, FALSE) ;
  3481.                      break ;
  3482.  
  3483.                  default:
  3484.                      return FALSE ;
  3485.                  }
  3486.              break ;
  3487.  
  3488.          default:
  3489.              return FALSE ;
  3490.          }
  3491.      return TRUE ;
  3492.      }
  3493.  
  3494.  
  3495.  Figure 10:  WSZ.DEF Definition File
  3496.  
  3497.  The Definition file for WSZ, called WSZ.DEF contains information about the
  3498.  program segments and procedures that LINK4, the Windows linker, requires for
  3499.  constructing the .EXE file.
  3500.  
  3501.  NAME    WhatSize
  3502.  
  3503.  DESCRIPTION 'A Windows Application'
  3504.  
  3505.  STUB    'WINSTUB.EXE'
  3506.  
  3507.  CODE    MOVEABLE
  3508.  DATA    MOVEABLE MULTIPLE
  3509.  
  3510.  HEAPSIZE  1024
  3511.  STACKSIZE 4096
  3512.  
  3513.  EXPORTS
  3514.          MainWndProc     @1
  3515.          AboutWndProc    @2
  3516.          UnitsWndProc    @3
  3517.  
  3518.  
  3519.  Figure 11:  Make-File for WSZ
  3520.  
  3521.  The make-file for WSZ is a program maintainer that keeps everything up to
  3522.  date. It serves as a record of the different pieces that contribute to the
  3523.  application and indicates how to recreate the program from the source files.
  3524.  
  3525.  wsz.res: wsz.rc wsz.ico wsz.h
  3526.      rc -r wsz.rc
  3527.  
  3528.  wsz.obj: wsz.c wsz.h
  3529.      cl -d -c -W2 -AS -Gs -Gw -Oas -Zpd -FPa wsz.c
  3530.  
  3531.  wsz.exe: wsz.obj wsz.res wsz.def
  3532.      link4 wsz, wsz/align:16, wsz/map, slibw, wsz.def
  3533.      mapsym wsz
  3534.      rc wsz.res
  3535.  
  3536.  
  3537.  Figure 12:  This system flowchart of the various WSZ files shows how the
  3538.              files eventually get into the WSZ.EXE executable file.
  3539.  
  3540.  ┌──────────┐   ┌───────────┐   ┌─────────────┐   ┌─────────┐
  3541.  │  WSZ.RC  │   │  WSZ.ICO  │   │  WINDOWS.H  │   │  WSZ.C  │
  3542.  └─────┬────┘   └─────┬─────┘   │    WSZ.RC   │   └─┬───────┘
  3543.        └──────────┐   │         └─┬────┬──────┘     │  ╔════════════╗
  3544.                   │   │       ┌───┘    │        ┌───┘  ║   P1.EXE   ║
  3545.  ╔════════════╗  ╔═══════════╗  ╔════════════╗  ┌─   P2.EXE   ║
  3546.  ║  RCPP.EXE  ──╢  RC.EXE(-r)  ║  ║    CL.EXE    ╟──┘ ║   P3.EXE   ║
  3547.  ╚════════════╝  ╚═══════╤══════╝  ╚══════╤═══════╝    ╚════════════╝
  3548.                    ┌──────────┐    ┌──────────┐      ┌───────────┐
  3549.                    │  WSZ.RES  │    │  WSZ.OBJ  │┌─────┤  WSZ.DEF  │
  3550.                    └─────┬─────┘    └─────┬─────┘│     └───────────┘
  3551.                          │   ╔══════════════╗   │ ┌───────────────┐
  3552.                          └───               ───┘┌┤  WINSTUB.EXE  │
  3553.                              ║     LINK4     ────┘└───────────────┘
  3554.                              ║               ───────────┐
  3555.                              ╚═╤═══════════╤═╝        ┌──┴─────────┐
  3556.                       ┌──────────┐  ┌──────────┐    │ SLIBC.LIB  │
  3557.              ┌────────┤  WSZ.EXE  │  │  WSZ.MAP  │    │ SLIBW.LIB  │
  3558.        ╔═════════╗   └───────────┘  └─────┬─────┘    │ SLIBFA.LIB │
  3559.        ║  RC.EXE  ║                  ╔═════════╗     │ LIBH.LIB   │
  3560.        ╚═════╤════╝                  ║  MAPSYM  ║     └────────────┘
  3561.        ┌──────────┐                 ╚═════╤════╝
  3562.        │  WSZ.EXE  │                 ┌──────────┐
  3563.        └───────────┘                 │  WSZ.SUM  │
  3564.                                      └───────────┘
  3565.  
  3566.  ────────────────────────────────────────────────────────────────────────────
  3567.  
  3568.  New XENIX Version Will Be First to Run On the Intel 80386
  3569.  
  3570.  Joe Desposito
  3571.  
  3572.  Microsoft's XENIX(R) System V/386 is expected to be released during the
  3573.  first quarter of 1987. This version of the product is especially
  3574.  significant, as it is the first version of XENIX to take full advantage of a
  3575.  32-bit microprocessor──namely, Intel's 80386. To learn more about XENIX 386
  3576.  we went straight to the source: Martin Dunsmuir, Microsoft's XENIX
  3577.  Development Manager.
  3578.  
  3579.  MSJ: We're here to talk about Microsoft XENIX System V/386. But could you
  3580.  first give us a brief background on the other versions of XENIX?
  3581.  
  3582.  MARTIN DUNSMUIR: The product out there at the moment is XENIX 286, for which
  3583.  there is a number of large OEMs (original equipment manufacturers),
  3584.  particularly IBM(R), Compaq(R), Altos, Tandy, and Intel(R). There have been
  3585.  two releases of XENIX 286: System 3, which went out in the '84 time frame,
  3586.  and System V, which came out in '85. The first release, System 3, was really
  3587.  targeted at the Intel 310 Machine. With the exception of IBM──we made a
  3588.  version available on the AT──most other versions of XENIX System 3 were on
  3589.  proprietary architectures. Then, when we went to System V, the emphasis
  3590.  moved to the AT architecture and its clones.
  3591.  
  3592.  Except for the Altos, which has its own architecture and is intended to be
  3593.  used in a turnkey environment, all of the XENIX 286 versions are on the IBM
  3594.  AT or clones──for example, IBM, Compaq, the TI Business Pro, and the Sperry
  3595.  IT.
  3596.  
  3597.  In the last year, the Intel 80386 microprocessor has appeared. And the
  3598.  machines that are currently being manufactured or are on the verge of being
  3599.  shipped──which use the 80386──are AT clones that replace the 80286 with the
  3600.  80386. So what we're aiming at is a release of XENIX 386 that will run on
  3601.  these machines. Now that's not to say that somebody like Altos, for example,
  3602.  can't take the source of what we produce and make it work on their own
  3603.  proprietary architecture. In fact, Altos is planning to do that──they've
  3604.  already started.
  3605.  
  3606.  MSJ: You mentioned 80386 machines. One that has already hit the marketplace
  3607.  is the Compaq 386. What's your opinion of it?
  3608.  
  3609.  DUNSMUIR: That's the machine that we've been using for development. We
  3610.  actually had some of the earliest prototypes and now we have some real
  3611.  models of it. It's really very good. It's very fast──about three times the
  3612.  speed of the AT. The only slow part of it is the disk, which, of course,
  3613.  operates at the same speed as it does on the AT. When you speed up the
  3614.  processor and you don't speed up the disk in proportion, the effective speed
  3615.  of the whole system obviously doesn't increase as much as that of the
  3616.  processor.
  3617.  
  3618.  
  3619.  The 386 Explosion
  3620.  
  3621.  MSJ: At the fall Comdex, there is expected to be an explosion of 386
  3622.  accelerator cards for the IBM AT and other 286 machines. Have you worked
  3623.  with any of them?
  3624.  
  3625.  DUNSMUIR: Well, the question really is: What machines will XENIX run on, or
  3626.  rather, what does it run on so far? It runs on any machines containing an
  3627.  80386 that have an AT compatible architecture. This includes the Compaq
  3628.  Deskpro 386, of course, but also machines running the Intel motherboard and
  3629.  386 turbo cards plugged into ATs.
  3630.  
  3631.  MSJ: In terms of the microprocessor itself, the 80386──what are some of the
  3632.  advantages that it has over the 80286, and how do these advantages relate to
  3633.  XENIX?
  3634.  
  3635.  DUNSMUIR: One advantage the 80386 has over the 80286 is that it is much
  3636.  faster──about three times the speed in terms of raw CPU power. And it also
  3637.  has this large address space. On the 286 your program can be very large, but
  3638.  basically it is composed of 64K segments.
  3639.  
  3640.  The problem with this is that people who have written applications for
  3641.  UNIX(R) in general find it difficult to bring those applications down onto
  3642.  XENIX 286. In other words, the applications are bigger than the 64K limit
  3643.  that you can get with one segment. Originally we hoped to put a real UNIX
  3644.  machine on everybody's desktop──or a small multiuser UNIX machine──but the
  3645.  number of ISVs (independent software vendors) who actually have gone to
  3646.  XENIX 286 has been somewhat less than we had hoped. That's not to say that
  3647.  the volumes aren't very good. XENIX 286 is probably the single most-
  3648.  installed derivative of UNIX ever. But the number of applications that have
  3649.  been written specifically for XENIX 286 is smaller than we had hoped at the
  3650.  outset.
  3651.  
  3652.  With the 386, you can easily bring your application down from, say, a VAX or
  3653.  a Sun or whatever, because you don't have this problem with these segments
  3654.  getting in the way of your large programs.
  3655.  
  3656.  
  3657.  Possible Problems
  3658.  
  3659.  MSJ: That sounds good in theory, but in practice, won't there be some snags
  3660.  when you try to port a UNIX program running on a VAX to a microcomputer like
  3661.  the Compaq 386 running XENIX?
  3662.  
  3663.  DUNSMUIR: On the VAX, the pointers and the integers in your program are all
  3664.  32 bits. Now, that means that if you simply compile your program on the 286,
  3665.  then it breaks because the integers on the 286 are 16 bits and the addresses
  3666.  are, too──unless you use multiple segments. So you're forced to use multiple
  3667.  segments.
  3668.  
  3669.  Now, when you use multiple segments, you've got a choice: You can go to
  3670.  what's called the large model, which means that the compiler automatically
  3671.  generates the instructions that change the segments when it needs to. This
  3672.  simulates the large address space in the 286 but reduces performance by
  3673.  about 20 percent. The alternative is to rewrite your application to optimize
  3674.  the use of the segments.
  3675.  
  3676.  On the 80386, however, segments are so large that there are essentially no
  3677.  segments. As a result, all you need to do is recompile, and the thing will
  3678.  run. And XENIX provides the right set of subroutines for the application to
  3679.  call, because it's a standard UNIX programming interface.
  3680.  
  3681.  A caveat to this arises, for example, if the program does graphics through
  3682.  some known standard interface. For instance, on the Sun they may be driving
  3683.  the graphics interface directly. Then the programmer is going to have to
  3684.  emulate that or provide support. But in terms of some straightforward
  3685.  application like a compiler or anything that's terminal-based, the program
  3686.  will just recompile and run.
  3687.  
  3688.  
  3689.  A Big Change
  3690.  
  3691.  MSJ: All the recent Intel processors like the 8088, 8086, and 80286 use 64K
  3692.  segments. The 80386 processor represents a radical change, doesn't it?
  3693.  
  3694.  DUNSMUIR: It certainly does. On the 286 you have these segments, and each
  3695.  segment has a number that you load into the segment register. The segments
  3696.  themselves can be up to 64K. So to actually address a piece of memory you
  3697.  specify the segment and the offset, which is a 16-bit number. On the 386,
  3698.  segments exist, too──except that the offsets are 32-bit numbers. This means
  3699.  that once you've loaded the segment register, you can address 4 gigabytes of
  3700.  memory, rather than 64K, without reloading the segment register.
  3701.  
  3702.  On the 386 you can emulate 286 programs. You can actually make a segment
  3703.  look like a 16-bit segment or a 32-bit segment. Basically, the operating
  3704.  system sets up the segment descriptor table as appropriate, depending on
  3705.  whether you're running a 286 or a 386 program.
  3706.  
  3707.  MSJ: Are there other characteristics that distinguish the 80386 from its
  3708.  predecessors?
  3709.  
  3710.  DUNSMUIR: Underneath the segmentation of the 386 is also paging, which
  3711.  doesn't exist on the 286. Underneath the 4-gigabyte segment are page tables,
  3712.  which map each 4K piece of that address space onto some piece of physical
  3713.  memory──or not, as the case may be. You don't have to actually have all of
  3714.  the physical paging present in that 4-gigabyte segment. Typically, you have
  3715.  only a few. A big program might have 4 megabytes, say, of actual paging
  3716.  mapped. But the advantage of having the very large address space is that you
  3717.  can actually put different parts of the program at completely weird,
  3718.  enormous addresses. So you can say: Okay, shared memory regions, for
  3719.  example, start at 2 gigabytes. But then you must make sure that the
  3720.  operating system maps the shared memory regions up to the 2-gigabyte virtual
  3721.  address used in the program.
  3722.  
  3723.  This is very similar to the way it works, for example, on the VAX or a 68020
  3724.  machine like the Sun. Any of these 32-bit minicomputers really do it the
  3725.  same sort of way. And that's what the 386 brings you on a chip. It brings
  3726.  you the minicomputer architecture. Microsoft hopes that the people who write
  3727.  UNIX applications for 32-bit minicomputers like the VAX will bring their
  3728.  application, which is presumably written in C, down onto XENIX 386 and then
  3729.  make a low-end version available. That's one of the main thrusts.
  3730.  
  3731.  MSJ: Where does that leave users with XENIX 286 applications?
  3732.  
  3733.  DUNSMUIR: There are, of course, applications that have been written
  3734.  specifically for XENIX 286. These will be available on XENIX 386 simply
  3735.  because it runs all the 286 software. One of the advantages of the 386 is
  3736.  its downward compatibility. If somebody wants a higher-performance multiuser
  3737.  solution, he can just use his old XENIX-286-based programs on the 386
  3738.  machine, and they'll run just fine.
  3739.  
  3740.  MSJ: XENIX 286 was primarily aimed at the multiuser market. Will the same
  3741.  hold true for XENIX 386?
  3742.  
  3743.  DUNSMUIR: The market position of XENIX 386 will be the small, multiuser
  3744.  marketplace. That's the main thrust. And that's where XENIX 286 has been
  3745.  successful. However, we now have the ability to create, if you like, a
  3746.  workstation with the 386, which we didn't have on the 286. So we will also
  3747.  be trying to address the workstation marketplace. I know that OEMs are
  3748.  planning to compete with the low-end VAX and Sun stations, and they'll offer
  3749.  a very cost-effective solution if, for example, you want to do CAD/CAM or
  3750.  desktop publishing, or anything like that.
  3751.  
  3752.  
  3753.  DOS Overlap
  3754.  
  3755.  MSJ: Doesn't this overlap with the potential market for MS-DOS 5.0?
  3756.  
  3757.  DUNSMUIR: Yes. When it becomes available, MS-DOS 5.0 will offer a very good,
  3758.  single-user workstation environment that will be very similar to a UNIX
  3759.  workstation in many ways. The main difference between an MS-DOS 5.0 and a
  3760.  XENIX 386 workstation is the existence of a UNIX market that is distinct
  3761.  from any other single-user market. UNIX allows you to have an application
  3762.  that will run on anything from a mainframe to a micro. In contrast,
  3763.  applications designed to run under MS-DOS 5.0 won't run under any other
  3764.  version. Hence, there will probably always be a UNIX workstation market
  3765.  unless UNIX disappears completely. This single-user workstation group is a
  3766.  separate group that we'll address with XENIX.
  3767.  
  3768.  MSJ: Will XENIX 386 have any brand-new features?
  3769.  
  3770.  DUNSMUIR: For the single-user workstation group, we've got to provide new
  3771.  features with XENIX. The features that make a good multiuser operating
  3772.  system──for example, supporting terminals──are not the sort of features. . .
  3773.  well, they're a subset, but they're not really the features that you need
  3774.  for a good, single-user workstation. The features that spring to mind for a
  3775.  single-user workstation are windowing, some sort of graphics capability, the
  3776.  ability to run 32-bit applications (which is what you get with the 386), and
  3777.  a networking facility so that you can connect your workstation to a larger
  3778.  machine, whatever that might be. What we're trying to do is to put together
  3779.  all of these various pieces in XENIX 386.
  3780.  
  3781.  MSJ: So XENIX System V/386 is slated to appear in the first quarter of
  3782.  1987?
  3783.  
  3784.  DUNSMUIR: Right. The beta version will be shipped to OEMs in late November.
  3785.  We plan to ship them the final product in early January. Now, the time delay
  3786.  for any of those OEMs to get a product out in the field is about 2 months at
  3787.  least. So you probably won't see any XENIX 386 operating systems appearing
  3788.  from our OEMs until something like April. But in the meantime, the Santa
  3789.  Cruz Operation (SCO) will be making available a retail version of the same
  3790.  software. I don't know exactly what their plans are, but I imagine that they
  3791.  will make it available very early in January close to the same time that we
  3792.  ship the product to the OEMs.
  3793.  
  3794.  MSJ: But isn't SCO one of your OEMs?
  3795.  
  3796.  DUNSMUIR: We have what's called a second-source agreement with SCO. What
  3797.  that actually means is that we work together to create XENIX. They have
  3798.  access on a daily basis to the code, and therefore they are in a much better
  3799.  position to put together a product. In fact, in the case of XENIX 386,
  3800.  they're actually doing a bit of device driver work, and so forth.
  3801.  
  3802.  One other thing needs to be said about SCO. At the present time, if you buy
  3803.  XENIX directly from SCO, you can get certain added features that we don't
  3804.  provide. This added value is being incorporated into XENIX 386, and we are
  3805.  committed to having functionally identical products from now on. This should
  3806.  silence some criticism in the press that SCO and MS XENIX versions are not
  3807.  compatible. We are very concerned about providing ISVs and end-users with a
  3808.  compatible platform for their XENIX applications whether they choose to buy
  3809.  XENIX from SCO or one of our other OEMs.
  3810.  
  3811.  
  3812.  V/386 Toolkit
  3813.  
  3814.  MSJ: Although XENIX 386 isn't available right now, a XENIX System V/386
  3815.  Toolkit is. Can you tell us something about it?
  3816.  
  3817.  DUNSMUIR: The XENIX System V/386 Toolkit is a special upgrade package for
  3818.  Microsoft XENIX System V/286. It's for independent software developers who
  3819.  want to write XENIX 386 applications now.
  3820.  
  3821.  The Toolkit includes both the program development tools needed to create
  3822.  XENIX 386 applications and the execution environment needed to run them.
  3823.  Virtually all of the 386 applications developed under the Toolkit will
  3824.  execute without recompilation under XENIX 386.
  3825.  
  3826.  Program development tools include a Microsoft C compiler for the 386; a new
  3827.  version of the Microsoft Macro Assembler, extended to support the 386
  3828.  instruction set and addressing modes; and a debugger for 386 programs.
  3829.  
  3830.  These tools can be installed on any computer running XENIX 286. But the
  3831.  execution environment portion of the Toolkit requires not only XENIX 286,
  3832.  but also a system with a 386 processor.
  3833.  
  3834.  ────────────────────────────────────────────────────────────────────────────
  3835.  
  3836.  A New Generation of Debugging Arrives with CodeView
  3837.  
  3838.  ───────────────────────────────────────────────────────────────────────────
  3839.  Also see the related articles:
  3840.    A Look at DEBUG and SYMDEB
  3841.    Codeview Command Summary
  3842.  ───────────────────────────────────────────────────────────────────────────
  3843.  
  3844.  Charles Petzold
  3845.  
  3846.  Debugging is such an awful, dirty, unglamorous, time-consuming job that
  3847.  nobody likes to think much about it. Perhaps for this reason, good debugging
  3848.  tools have always lagged behind other advances in language technology. It
  3849.  wasn't until the introduction of SYMDEB (SYMbolic DEBugger, first included
  3850.  with the Macro Assembler 3.0) that Microsoft offered programmers an
  3851.  alternative to the inadequate DEBUG.
  3852.  
  3853.  The CodeView(TM) debugger included with Microsoft's C Compiler Version 4.00,
  3854.  however, represents a new generation. Just as SYMDEB added to DEBUG's
  3855.  features by reading in source code and displaying symbolic references to
  3856.  global variables and subroutines, CodeView advances over SYMDEB by including
  3857.  symbolic local variable and subroutine names, new data display and enter
  3858.  types, an 8087 math coprocessor dump, and some additional debugging
  3859.  techniques.
  3860.  
  3861.  CodeView uses a full-screen windowed display and includes a mouse, menu, and
  3862.  command line interface. It can do C expression evaluation and UNIX-like
  3863.  regular expression evaluation. For now, CodeView is limited to Microsoft C
  3864.  4.00 and cannot yet be used for debugging Microsoft Windows applications,
  3865.  but it will eventually be adapted for other languages.
  3866.  
  3867.  
  3868.  Prepararation
  3869.  
  3870.  The mechanics of preparing a program for CodeView are simple. When compiling
  3871.  a program, use the /Zi switch
  3872.  
  3873.    MSC PROGRAM /Zi;
  3874.  
  3875.  This option directs the compiler to include in the .OBJ file the names,
  3876.  addresses, and types of all global and local variables; the names,
  3877.  addresses, and return values of all global and static functions; and source
  3878.  code line number references.
  3879.  
  3880.  If you don't need all this information (perhaps for a module that's already
  3881.  in good shape), you can specify that only global functions and variables and
  3882.  line number information be included in the .OBJ file by using the /Zd
  3883.  switch
  3884.  
  3885.    MSC MODULE /Zd;
  3886.  
  3887.  This is the same switch used for preparing programs for SYMDEB.
  3888.  
  3889.  In either case, you might also want to disable optimization with the /Od
  3890.  switch. This will make it easier to correlate source code and the compiled
  3891.  assembly language.
  3892.  
  3893.  When you link, use the /CO (CodeView) switch
  3894.  
  3895.    LINK PROGRAM /CO;
  3896.  
  3897.  The /CO switch directs LINK to include the debugging information from each
  3898.  .OBJ file in the .EXE file together with directory paths of the .OBJ files.
  3899.  CodeView uses these directory paths to search for the C source code file.
  3900.  You will want to help CodeView out by keeping source code and object files
  3901.  in the same subdirectory.
  3902.  
  3903.  Both CodeView and SYMDEB are easier to use if you follow certain programming
  3904.  rules. For instance, since SYMDEB can handle only global functions and
  3905.  variables, you might be less inclined to use local variables or functions
  3906.  defined as static. With CodeView, however, you don't have to accommodate the
  3907.  debugger in this way.
  3908.  
  3909.  The rules for programming for CodeView are generally the same as those for
  3910.  writing structured readable C. You should use small modular functions. You
  3911.  should keep source code statements to one line each since multiple-line
  3912.  source code statements do not show up well in CodeView's combined source and
  3913.  assembly display. You can get a better feel for the relationship between
  3914.  source and compiled code by avoiding long, complex C statements.
  3915.  
  3916.  On the other hand, CodeView does not show source from include files and
  3917.  macros. Also, since LIB strips out the debugging information, CodeView
  3918.  cannot show source code for functions retrieved from libraries, even if the
  3919.  modules were compiled with the /Zi switch. For this reason you will want to
  3920.  wait until certain modules have been debugged before putting them in
  3921.  libraries.
  3922.  
  3923.  
  3924.  Letting MAKE Help Out
  3925.  
  3926.  The symbolic information that LINK embeds into an .EXE file for use by
  3927.  CodeView can make the .EXE much larger than normal. You will not want to
  3928.  distribute an .EXE file with this information because anybody looking at the
  3929.  program in CodeView can learn a great deal about its inner workings from the
  3930.  variable and procedure names that CodeView displays.
  3931.  
  3932.  You can use MAKE to help out with the chore of compiling a program with or
  3933.  without CodeView information. At the top of the make-file for a particular
  3934.  program, define several macros
  3935.  
  3936.    CVC  = /Zi /Od
  3937.    CVL  = /CO
  3938.    COMP = msc $* $(CVC) ;
  3939.    LINK  = link $** $(CVL) ;
  3940.  
  3941.  where CVC and CVL are the CodeView switches for the compile and link steps,
  3942.  respectively. After the definition of these macros, you can set up the make-
  3943.  file like this:
  3944.  
  3945.    prog.obj : prog.c
  3946.           $(COMP)
  3947.    module1.obj : module1.c
  3948.           $(COMP)
  3949.    module2.obj : module2.c
  3950.           $(COMP)
  3951.    prog.exe : prog.obj\module1.obj\module2.obj
  3952.           $(LINK)
  3953.  
  3954.  When it is time to prepare the final .EXE file without embedded debugging
  3955.  information, just undefine the macros on the MAKE command line
  3956.  
  3957.    MAKE prog /DCVC= /DCVL=
  3958.  
  3959.  Alternatively, you can use the EXEPACK utility to strip debugging
  3960.  information from the .EXE file.
  3961.  
  3962.  
  3963.  Starting It Up
  3964.  
  3965.  In many cases you can bring up CodeView for debugging your program with the
  3966.  command line
  3967.  
  3968.    CV PROGRAM
  3969.  
  3970.  However, certain situations (such as using a PC compatible or a black-and-
  3971.  white monitor on a color adapter) will warrant CodeView command line
  3972.  switches. These switches must be placed before the name of the program that
  3973.  you're debugging.
  3974.  
  3975.  The most important command line switches relate to how CodeView uses the
  3976.  display. Because CodeView is a full-screen debugger, it must share the
  3977.  display with the out-put from the program you are debugging. Depending on
  3978.  the hardware installed on your system, you have several options for handling
  3979.  this problem.
  3980.  
  3981.  For systems with one video adapter, CodeView will use either video
  3982.  "swapping" or video "flipping" to keep the CodeView and program output
  3983.  separate.
  3984.  
  3985.  If you have only a monochrome adapter on your system, CodeView will use the
  3986.  "swapping" method. CodeView allocates some memory to save the contents of
  3987.  the display. It swaps screen displays between this memory and the video
  3988.  adapter memory when switching back and forth between CodeView and your
  3989.  program.
  3990.  
  3991.  If you have only a Color Graphics Adapter (CGA) or Enhanced Graphics Adapter
  3992.  (EGA) on your system, CodeView will, by default, use the "flipping" option.
  3993.  CodeView will use different video pages for its own display and the display
  3994.  of the program being debugged. Flipping between these video pages is faster
  3995.  than swapping video contents in and out of memory.
  3996.  
  3997.  You cannot use screen flipping with a monochrome adapter because it has only
  3998.  4K of memory and one video page. You also cannot use flipping on a CGA or
  3999.  EGA if you are debugging a program that uses multiple video pages or
  4000.  graphics. In this case, you must override the default and specify screen
  4001.  swapping with the /S parameter.
  4002.  
  4003.  Both screen flipping and screen swapping have some problems. Every time you
  4004.  trace a statement, CodeView switches the display to program output and back
  4005.  again. You're likely to find your head aching before you find the bug. If
  4006.  you are debugging a program that directly accesses output ports on the video
  4007.  adapter, CodeView may not be able to restore the exact video state when it
  4008.  returns to your program output display. But there is really no alternative
  4009.  to this when debugging programs using a single monitor.
  4010.  
  4011.  These problems can be alleviated with a second display adapter. If you have
  4012.  two adapters on your system, you can specify the /2 option when you bring up
  4013.  CodeView, and CodeView will use the second adapter. (This option is not in
  4014.  the manual, but it's mentioned in the C 4.00 README.DOC file.) Unfortunately
  4015.  (as also mentioned in this README file), the /2 option does not allow the
  4016.  mouse to work on the debugging display.
  4017.  
  4018.  As with SYMDEB, you can redirect CodeView input and output through a serial
  4019.  port and use a separate debugging terminal. However, you lose many of the
  4020.  advantages of working with CodeView in a full-screen mode.
  4021.  
  4022.  
  4023.  Menus and the Mouse
  4024.  
  4025.  Although the pull-down menu interface and mouse support in CodeView make it
  4026.  easier to use than most debuggers, early encounters with CodeView can be
  4027.  quite confusing. There are actually several user interfaces──a SYMDEB-like
  4028.  command line, a Windows-like menu, the PC function keys, and the mouse. Each
  4029.  of these different interfaces has some distinct features and also some
  4030.  overlap. You can usually do things in several different ways, and it is
  4031.  precisely this flexibility that makes CodeView a bit awkward at first.
  4032.  
  4033.  On entry to CodeView, the screen is divided into two windows called Display
  4034.  and Dialog. The Display window shows either your source code, or source code
  4035.  combined with the compiled assembly language code.
  4036.  
  4037.  The Dialog window at first appears to be SYMDEB running in a window.
  4038.  However, you'll find that CodeView is missing a few DEBUG and SYMDEB
  4039.  commands (Fill, Move, Compare) and adds other valuable functions, such as
  4040.  expression evaluation, symbol examination, a file browser with a search
  4041.  capability, and additional methods to set breakpoints.
  4042.  
  4043.  Everything you can do in CodeView is done by entering commands in the Dialog
  4044.  window. This allows you to use CodeView in a SYMDEB-like teletype mode and
  4045.  still retain full functionality. Some commands (Dump, Enter, Assemble) must
  4046.  be entered in the Dialog window and cannot be done any other way.
  4047.  
  4048.  The menu, mouse, and function key interfaces duplicate many of the more
  4049.  common commands. They do not add functionality but they do provide ease of
  4050.  use.
  4051.  
  4052.  Let's explore some of the ways you can use CodeView by examining the guts of
  4053.  debugging──tracing through code.
  4054.  
  4055.  
  4056.  Trace, Go, and Break
  4057.  
  4058.  Users of DEBUG and SYMDEB are familiar with the Trace and Go commands. DEBUG
  4059.  3.x and SYMDEB also include a Proceed command. CodeView implements all three
  4060.  of these methods to trace code.
  4061.  
  4062.  The Trace command uses the Intel microprocessors' single-step trap to
  4063.  single-step through instructions. Just as in DEBUG and SYMDEB, you can do a
  4064.  one-instruction trace in CodeView by entering T in the Dialog window. If
  4065.  you're in assembly mode, you'll step through assembly language instructions.
  4066.  In source code mode, you'll step through source code instructions. You can
  4067.  also do a one-instruction trace by pressing the F8 function key or clicking
  4068.  Trace! on the menu with the left mouse button. A multiple-instruction trace
  4069.  is possible only through the Dialog window by including a value after the T.
  4070.  
  4071.  The Program Step command (which was called the Proceed command when
  4072.  introduced in DEBUG 3.0) is similar to the Trace command except that it will
  4073.  not trace through subroutine calls or software interrupts. This is good for
  4074.  skipping through BIOS calls or subroutines that you know work. You can
  4075.  Program Step by entering P in the Dialog window, pressing F10, or clicking
  4076.  Trace! on the menu with the right mouse button.
  4077.  
  4078.  Note that Program Step works by setting a breakpoint following the call or
  4079.  interrupt that it skips through. This breakpoint will not work in ROM or
  4080.  with calls and interrupts to routines that adjust the return address.
  4081.  
  4082.  The Go command just executes code until it hits a breakpoint. You can set a
  4083.  breakpoint at the same time you do a Go by entering G in the Dialog window
  4084.  with a breakpoint expressed as an address, line number, or symbolic label.
  4085.  Alternatively, you can position the cursor in the Display window at the
  4086.  break line and press F7. For a Go command with no break, press F5. With the
  4087.  mouse, you can Go to a particular line by clicking the line with the right
  4088.  mouse button. For a no-break Go, click Go! on the menu.
  4089.  
  4090.  Users of SYMDEB are also familiar with setting explicit breakpoints. The
  4091.  advantage of this method over specifying a breakpoint in the Go command is
  4092.  that you can set more than one of them, and they are sticky──the breakpoint
  4093.  will remain in effect until you disable it or clear it.
  4094.  
  4095.  The breakpoint command in CodeView works like the one in SYMDEB. Twenty
  4096.  breakpoints are available. Setting a breakpoint with the mouse is very
  4097.  easy──you just click on the line with the left mouse button. You can also
  4098.  use the keyboard to move the cursor to the break line and press F9.
  4099.  
  4100.  
  4101.  Beyond SYMDEB
  4102.  
  4103.  Now let's look at some of the ways that CodeView goes beyond the
  4104.  functionality of SYMDEB. We have watches, watchpoints, and tracepoints. They
  4105.  all appear on the same menu, they are listed in the same window, and they
  4106.  have confusingly similar names. They are not the same.
  4107.  
  4108.  A "watch" is a C expression using any global or currently available local
  4109.  variable. The expression is displayed in the Watch window along with the
  4110.  calculated value. For instance, if you have a routine that writes directly
  4111.  to the video display memory using two variables called row and col, you
  4112.  might want to keep a watch on the implied display address referenced by
  4113.  these two variables. Your watch would look like this:
  4114.  
  4115.    2 * (row + 80 * col)
  4116.  
  4117.  The C expression evaluator can even handle calls to your program's C
  4118.  functions. This lets you test individual functions by passing experimental
  4119.  values to them.
  4120.  
  4121.  A "watchpoint" is generally a Boolean expression, again expressed using C
  4122.  syntax with global and currently available local variable names. When the
  4123.  watchpoint becomes true (i.e., is nonzero), CodeView will break and return
  4124.  control to you.
  4125.  
  4126.  For both watches and watchpoints, CodeView must repeatedly evaluate the
  4127.  expression while single-stepping through code. For watches, it just displays
  4128.  the new value. For watchpoints, it breaks if the expression evaluates to a
  4129.  nonzero value.
  4130.  
  4131.  A "tracepoint" is similar to a watchpoint in that it can cause a break in
  4132.  program execution. But while a watchpoint depends on the evaluation of an
  4133.  expression, a tracepoint will break when an area of memory changes. This is
  4134.  much easier and faster for CodeView to do, but is not quite as flexible for
  4135.  the user.
  4136.  
  4137.  For instance, suppose you had a for loop that increments the variable i,
  4138.  such as
  4139.  
  4140.    for (i = 0; i < 100; i++)
  4141.  
  4142.  If you wanted to break every time that i changed value, you could set a
  4143.  tracepoint that is simply the expression
  4144.  
  4145.    i
  4146.  
  4147.  But if i is a registered variable, the tracepoint would not work, because i
  4148.  does not refer to an area of memory.
  4149.  
  4150.  Also, if you wanted to break every ten cycles through, you could not set a
  4151.  tracepoint that looks like
  4152.  
  4153.    i % 10
  4154.  
  4155.  because "i % 10" does not refer to a memory location. What you really need
  4156.  is a watchpoint that looks like this:
  4157.  
  4158.    i % 10 == 0
  4159.  
  4160.  
  4161.  Watching Tracepoints
  4162.  
  4163.  In debugging any program it is advisable to try to localize your problem
  4164.  before setting either watchpoints or tracepoints. Watchpoints take longer to
  4165.  evaluate than tracepoints, but they do not need to refer to memory
  4166.  locations. Here's a simple rule: When you think you need to set a watchpoint
  4167.  or tracepoint, try to do it as a tracepoint first. If you can't, use a
  4168.  watchpoint.
  4169.  
  4170.  Watchpoints and tracepoints both require some time at every program step.
  4171.  For real-time applications, you may need a hardware debugger.
  4172.  
  4173.  
  4174.  Null Pointers
  4175.  
  4176.  The ability to test the contents of any variable or any region of memory
  4177.  continually is a very powerful debugging tool. For instance, you may be
  4178.  familiar with the run-time message
  4179.  
  4180.    error 2001: Null pointer assignment
  4181.  
  4182.  At the very beginning of your program's data segment is a small area of
  4183.  memory containing some zeros and the Microsoft copyright notice. The clean-
  4184.  up exit code calculates a checksum on this memory. If the memory has been
  4185.  changed, the "Null pointer assignment" message is displayed.
  4186.  
  4187.  In C, a null pointer is an invalid pointer. If the beginning of the data
  4188.  segment has been changed, then it may very well be the result of using a
  4189.  null pointer. The message you get doesn't mean you've just assigned 0 to a
  4190.  pointer. It means that you've actually used that pointer to write something
  4191.  into memory.
  4192.  
  4193.  You can find the buggy code that does this by setting a tracepoint on this
  4194.  memory. From the command line of the Dialog window, you can enter
  4195.  
  4196.    TPB 0 L 8
  4197.  
  4198.  This means "Set a Tracepoint of type Byte, starting at address 0 for a
  4199.  Length of 8." CodeView displays the current values in a Dump-like format.
  4200.  
  4201.  Or you can do essentially the same thing as an expression from the
  4202.  Tracepoint option of the Watch menu
  4203.  
  4204.    *((double *) 0)
  4205.  
  4206.  The contents of this double pointer to zero are the eight bytes starting at
  4207.  address 0. When this memory is changed, CodeView will break and show you
  4208.  where it happened.
  4209.  
  4210.  If you have a particular character string getting chewed up or an array
  4211.  picking up some strange values or even code that gets destroyed, you can set
  4212.  a tracepoint at the variable or the explicit address, and CodeView will
  4213.  break when the damage happens.
  4214.  
  4215.  
  4216.  The Panic Button
  4217.  
  4218.  CodeView also supports dynamic breaking using the SysReq key on the PC-AT.
  4219.  The SysReq key usually works to regain control when your program seems to
  4220.  avoid the breakpoints you set for it. The Calls option on the menu (or the K
  4221.  command in the Dialog window) displays a stack trace. The stack trace is
  4222.  good for answering the question "Where am I and how did I get here?" It
  4223.  displays a list of nested subroutines, the parameters passed to them, and
  4224.  (when the command is entered in the Dialog window) the line numbers where
  4225.  these routines were called.
  4226.  
  4227.  
  4228.  The Caveats
  4229.  
  4230.  Some warnings about CodeView:
  4231.  
  4232.  First, if you've been using DEBUG or SYMDEB, you should be aware that all
  4233.  the CodeView commands use a civilian form of notation called base-10 or
  4234.  decimal. If you enter D 197F, you'll get an error message. You should have
  4235.  typed D 6527 or D 0x197F instead. You can change the radix to hexadecimal if
  4236.  you can't get accustomed to this. (Dumps, assembly language listings, and
  4237.  register contents are displayed in hexadecimal regardless.)
  4238.  
  4239.  However, be aware that watch, watchpoint, and tracepoint expressions also
  4240.  use the radix. If you set the radix to 16, the numbers you type in the
  4241.  expressions will also be interpreted as hexadecimal. For instance, this is
  4242.  the watch I showed earlier:
  4243.  
  4244.    2 * (row + 80 * col)
  4245.  
  4246.  After radix is set to 16, the 80 is interpreted as hexadecimal and would
  4247.  actually be the decimal value 128. If you'll be changing the radix, write
  4248.  expressions with explicit hexadecimal or decimal prefixes, such as
  4249.  
  4250.    2 * (row + 0x50 * col)
  4251.  or
  4252.    2 * (row + 0n80 * col)
  4253.  
  4254.  Second, CodeView 1.00 has at least one bug in its assembly and disassembly
  4255.  logic regarding the DWORD data type (typically used in floating point
  4256.  arithmetic). It treats DWORDs as WORDs.
  4257.  
  4258.  Finally, don't get rid of SYMDEB. CodeView itself uses 160K of memory, and
  4259.  .EXEs prepared for CodeView are larger than normal to include the symbol
  4260.  information, so you may have problems with large programs. Go back to SYMDEB
  4261.  for those.
  4262.  
  4263.  SYMDEB is also easier to use for some chores, such as taking a quick look at
  4264.  some disassembled ROM code, printing a disassembly, or creating short
  4265.  assembly language .COM files. For exploration and experimentation, you'll
  4266.  still think SYMDEB. For serious debugging, you'll definitely want to use Code
  4267.  
  4268.  ───────────────────────────────────────────────────────────────────────────
  4269.  A Look at DEBUG and SYMDEB
  4270.  ───────────────────────────────────────────────────────────────────────────
  4271.  
  4272.  Remember the "good" old days? you'd start off with and innocent looking
  4273.  peice of C code:
  4274.  
  4275.  mainmenu ()
  4276.          {
  4277.          int i, code, good, donw = 0 ;
  4278.  
  4279.          do
  4280.                  {
  4281.                  topline (atl) ;
  4282.                  menutype ("MAIN MENU", at3) ;
  4283.  
  4284.                  clrwin (6, 10, 24, 69, at2) ;
  4285.                  clrwin (6, 0, 24, 9, at3) ;
  4286.                  clrwin (6, 70, 24, 79, at3) ;
  4287.  
  4288.                  writestr ( 7, 21, "Press:", at2) ;
  4289.  
  4290.  But when it came time to do a little debugging in DEBUG, all you saw is
  4291.  something that just doesn't look the same:
  4292.  
  4293.  -u 24a
  4294.  1434:024A 55           PUSH      BP
  4295.  1434:024B 8BEC         MOV       BP,SP
  4296.  1434:024D V80800       MOV       AX,0008
  4297.  1434:0250 E8881C       CALL      1EDB
  4298.  1434:0253 57           PUSH      DI
  4299.  1434:0254 56           PUSH      SI
  4300.  1434:0255 C746FE0000   MOV       WORD PTR [BP-02],0000
  4301.  1434:025A FF36A241     PUSH      [41A2]
  4302.  1434:025E E8B304       CALL      0714
  4303.  1434:0261 83C402       ADD       SP,+02
  4304.  1434:0264 FF36A641     PUSH      [41A6]
  4305.  1434:0268 B86E01       MOV       AX,016E
  4306.  1434:026B 50           PUSH      AX
  4307.  1434:026C E8E004       CALL      074F
  4308.  1434:026F 83C404       ADD       AP,+04
  4309.  1434:0272 FF36A441     PUSH      [41A4]
  4310.  
  4311.  Are we really sure it's the same program? Fortunately, SYMDEB took some of
  4312.  the guesswork out of debugging (below). Today, the CodeView debugger
  4313.  included with the Microsoft C Compiler 4.00 makes debugging even less
  4314.  painful.
  4315.  
  4316.  -u _mainmenu
  4317.  12:             {
  4318.  _TEXT:_mainmenu:
  4319.  1AA4:024A 55           PUSH      BP
  4320.  1AA4:024B 8BEC         MOV       BP,SP
  4321.  1AA4:024D B80800       MOV       AX,0008
  4322.  1AA4:0250 E8881C       CALL      _chkstk
  4323.  1AA4:0253 57           PUSH      DI
  4324.  1AA4:0254 56           PUSH      SI
  4325.  20:            int i, code, good, done = 0 ;
  4326.  1AA4:0255 C746FE0000   MOV       Word Ptr [BP-02],0000
  4327.  24:                   topline (atl) ;
  4328.  1AA4:025A FF36A241     PUSH      [41A2]
  4329.  1AA4:025E E8B304       CALL      _topline
  4330.  1AA4:0261 83C402       ADD       SP,+02
  4331.  
  4332.  ───────────────────────────────────────────────────────────────────────────
  4333.  Codeview Command Summary
  4334.  ───────────────────────────────────────────────────────────────────────────
  4335.  
  4336. ╓┌─────────────┌────────────────────┌────────────┌────────────┌──────────────╖
  4337.  Command       Dialog Window        Menu         Mouse        Function Key
  4338.  
  4339.  Assemble      A (address)
  4340.  
  4341.  Breakpoint    BC list:*            Run/Clear    Left click   F9 (cursor on
  4342.  Clear                              Breakpoints               break line)
  4343.  
  4344.  Breakpoint    BD list:*
  4345.  Disable
  4346.  
  4347.  Breakpoint    BE list:*
  4348.  Enable
  4349.  Command       Dialog Window        Menu         Mouse        Function Key
  4350. Enable
  4351.  
  4352.  Breakpoint    BL
  4353.  List
  4354.  
  4355.  Breakpoint    BP (address)                      Left click   F9 (cursor on
  4356.                (passcount)                       break line   break line)
  4357.                (commands)
  4358.  
  4359.  Dump Data     D (type) (range)
  4360.  
  4361.  Enter Data    E (type) address
  4362.                (list)
  4363.  
  4364.  Execute       E                    Run/Execute
  4365.  
  4366.  Go            G                    Go!          Click Go!    F3
  4367.  
  4368.  Goto          G (break                          Right click  F7 (cursor on
  4369.                address)                          break line   break line)
  4370.  Command       Dialog Window        Menu         Mouse        Function Key
  4371.               address)                          break line   break line)
  4372.  
  4373.  Help          H                    View/Help                 F1
  4374.  
  4375.  Stack Trace   K                    Calls
  4376.  
  4377.  Restart       L                    Run/Restart
  4378.                (arguments)
  4379.  
  4380.  Restart & Go                       Run/Start
  4381.  
  4382.  Radix         N (radix)
  4383.  
  4384.  Program step  P (count)                         Right click  F10
  4385.                                                  Trace !
  4386.  
  4387.  Quit          Q                    File/Quit
  4388.  
  4389.  Register      R                    Options/                  F2
  4390.  Display                            Registers
  4391.  Command       Dialog Window        Menu         Mouse        Function Key
  4392. Display                            Registers
  4393.  
  4394.  Register      R (register)                      Click on
  4395.  Change        ((=)                              Flag
  4396.                expression))                      Mnemonic
  4397.  
  4398.  Set Mode -    S +                  View/Source               F3
  4399.  Source
  4400.  
  4401.  Set Mode -    S -                  View/                     F3
  4402.                                     Assemble
  4403.  
  4404.  Trace         T (count)            Trace!       Left click   F8
  4405.                                                  Trace!
  4406.  
  4407.  Tracepoint    TP? expression       Watch/
  4408.                (,format)            Tracepoint
  4409.                TP (type) range
  4410.  
  4411.  Unassemble    U (range)
  4412.  Command       Dialog Window        Menu         Mouse        Function Key
  4413. Unassemble    U (range)
  4414.  
  4415.  View File     V (. (filename:)     File/Load
  4416.                line)
  4417.                V (expression)
  4418.  
  4419.  Watch         W? expression        Watch/Add
  4420.                (,format)            Watch
  4421.                W(type) range
  4422.  
  4423.  Watch List    W
  4424.  
  4425.  Watchpoint    WP? expression       Watch/
  4426.                                     Watchpoint
  4427.  
  4428.  Examine       X? (module!)
  4429.  Symbol        (function.)
  4430.                (symbol) (*)
  4431.  
  4432.  Examine       X*
  4433.  Command       Dialog Window        Menu         Mouse        Function Key
  4434. Examine       X*
  4435.  Module Names
  4436.  
  4437.  Delete Watch  Y number             Watch/Delete
  4438.                                     Watch
  4439.  
  4440.  8087 Dump     7
  4441.  
  4442.  Display       ?expression          View/
  4443.                                     Evaluate
  4444.  
  4445.  Expression    (,format)
  4446.  Display       .
  4447.  Location
  4448.  
  4449.  Redraw        .@
  4450.  Screen
  4451.  
  4452.  Screen        \                    View/Output
  4453.  Exchange
  4454.  Command       Dialog Window        Menu         Mouse        Function Key
  4455. Exchange
  4456.  
  4457.  Search        /(expression)        Search/Find
  4458.  
  4459.  Search Next   /                    Search/Next
  4460.  Search                             Search/
  4461.  Previous                           Previous
  4462.  
  4463.  Search Label  V (expression)       Search/Label
  4464.  
  4465.  Shell to DOS  !                    File/Shell
  4466.  
  4467.  Tab Size      # number
  4468.  
  4469.  
  4470.  ────────────────────────────────────────────────────────────────────────────
  4471.  
  4472.  Ask Dr. Bob!
  4473.  
  4474.  Peeks and Pokes
  4475.  
  4476.  Dear Dr. Bob,
  4477.  
  4478.  In my programs I often have to get at memory outside my program segment, say
  4479.  to retrieve values from the BIOS data area or to write directly to the
  4480.  display. In BASIC I can use PEEK and POKE. How can I do PEEKs and POKEs in
  4481.  C?──"C"urious
  4482.  
  4483.  Dear "C"urious,
  4484.  
  4485.  Very easily. The flexibility you have using pointers in C makes this job
  4486.  almost trivial. For instance, if you need to retrieve the current video mode
  4487.  (located at address 0040:0049 in the BIOS data area), you can use the
  4488.  statement in Figure 1. The 0x400049L is a long integer containing the
  4489.  segment and offset address of the value you want to access. The (char far *)
  4490.  casts this number into a far pointer to a character. The indirection
  4491.  operator * retrieves the 1-byte value stored at this pointer.
  4492.  
  4493.  You can also use a similar construction to store values, as shown in
  4494.  Figure 2. Obviously, in this example, you would not do this unless your
  4495.  program has manually changed the video mode and you want the BIOS data area
  4496.  to agree with what you have done.
  4497.  
  4498.  If you have to reference data outside your program frequently, you might
  4499.  want to set up a couple of macros, as shown in Figure 3, where s and o are
  4500.  the segment and offset parts of the far address. You would use MEMC for 1-
  4501.  byte characters and MEMI for integers. The examples in Figure 3 would then
  4502.  look like Figure 4.
  4503.  
  4504.  If you need a far pointer that accesses the IBM Color Graphics Adapter, you
  4505.  could define it as shown in Figure 5.
  4506.  
  4507.  
  4508.  Interrupts
  4509.  
  4510.  Dear Dr. Bob,
  4511.  
  4512.  I've been using the intdos and int86 functions included with the Microsoft C
  4513.  3.0 compiler to call DOS and BIOS routines directly. I haven't experienced
  4514.  many problems. However, I recently tried to use int86 for the DOS Interrupts
  4515.  0x25 and 0x26 (which read and write absolute sectors on a disk) and I can't
  4516.  get it to work. For instance, this program should read the first sector of a
  4517.  drive A: disk into the array called buffer:
  4518.  
  4519.    #include <dos.h>
  4520.    main ()
  4521.    {
  4522.    char    buffer [512];
  4523.    union   REGS regs;
  4524.    regs.h.al=0;
  4525.    regs.x.bx=(int)buffer;
  4526.    regs.x.cx=1;
  4527.    regs.x.dx=0;
  4528.    int86 (0x25, ®s, ®s);
  4529.    }
  4530.  
  4531.  But this program crashes. What's the problem?──Puzzled
  4532.  
  4533.  Dear Puzzled,
  4534.  
  4535.  Interrupts 0x25 and 0x26 are a little different from the other DOS and BIOS
  4536.  interrupts because they leave the original flags on the stack. The stack
  4537.  must be adjusted after returning from the interrupt. The int86 function
  4538.  included with C 3.0 did not make this adjustment.
  4539.  
  4540.  The solution to your problem is as simple as an upgrade. The int86 function
  4541.  in Microsoft C 4.0 specifically checks for Interrupts 0x25 and 0x26 and
  4542.  adjusts the stack after the interrupt function returns control.
  4543.  
  4544.  
  4545.  Arrays and Pointers
  4546.  
  4547.  Dear Dr. Bob,
  4548.  
  4549.  I've been programming in C for a while now, but I still get confused about
  4550.  the relationship between arrays and pointers. For instance, I can define two
  4551.  variables like this:
  4552.  
  4553.    char str1[] = "This is a string" ;
  4554.    char *str2 = "This is a string" ;
  4555.  
  4556.  For some purposes, str1 and str2 appear to work the same. Other times,
  4557.  however, it's obvious that they are not the same. What is the difference
  4558.  between a character array and a pointer to a character string, and when
  4559.  should I use one instead of the other.──Unsure
  4560.  
  4561.  Dear Unsure,
  4562.  
  4563.  Both str1 and str2 may be used as pointers that address the first element of
  4564.  the string. Both
  4565.  
  4566.    puts (str1) ;
  4567.  
  4568.  and
  4569.  
  4570.    puts (str2) ;
  4571.  
  4572.  print the string on the display. It may help to think of str2 as a pointer
  4573.  to the string and str1 as shorthand notation for &str1[0], which is a
  4574.  pointer to the first element of the array.
  4575.  
  4576.  You can see what the compiler does with these two definitions by compiling
  4577.  with the /Fc switch. The compiler creates a combined source code and
  4578.  assembly code listing created as a file with the .COD extension.
  4579.  
  4580.  If both str1 and str2 are defined at the external level (outside of any
  4581.  function), then str1 is compiled into the assembly language statement shown
  4582.  in Figure 6, while str2 is compiled in the manner shown in Figure 7.
  4583.  The pointer definition takes up 2 additional bytes of memory.
  4584.  
  4585.  When you define and initialize str1, you are allocating 17 bytes to hold the
  4586.  string and the terminating zero. When you define str2, however, you are
  4587.  really only allocating 2 bytes for the pointer. The initialization directs
  4588.  the compiler to store in str2 the address of the string. In theory, this
  4589.  string should be treated as "read-only" (but nothing bad will happen if you
  4590.  try to write into it). For str1, you've defined the whole string, so you can
  4591.  read from it and write to it.
  4592.  
  4593.  Again in theory, if you also define
  4594.  
  4595.    char str3[] = "This is a string" ;
  4596.  
  4597.  and
  4598.  
  4599.    char *str4 = "This is a string" ;
  4600.  
  4601.  then str1 and str3 must define two separate strings. However, it would be
  4602.  legitimate for a compiler to initialize str2 and str4 as pointers to the
  4603.  same string. (The Microsoft C Compiler will not do this.)
  4604.  
  4605.  For both str1 and str2, you can reference characters in the strings using
  4606.  either array notation or indirection. All of these statements will then put
  4607.  the character 's' into the character variable ch:
  4608.  
  4609.    ch = *(str1 + 3) ;
  4610.    ch = str1[3] ;
  4611.    ch = *(str2 + 3) ;
  4612.    ch = str2[3] ;
  4613.  
  4614.  The assignment statements using str1 are compiled into assembly language
  4615.  statements that look something like this:
  4616.  
  4617.    mov al,[_str1 + 3]
  4618.    mov [_ch],al
  4619.  
  4620.  However, an extra assembly language step is required for the assignments
  4621.  using str2 because the address of the string must be retrieved from str2
  4622.  before the string can be referenced:
  4623.  
  4624.    mov bx,[_str2]
  4625.    mov al,[bx + 3]
  4626.    mov [_ch],al
  4627.  
  4628.  If str1 and str2 are defined inside a function, then str1 must be defined as
  4629.  static:
  4630.  
  4631.    static char str1[] = "This is a string" ;
  4632.  
  4633.  because arrays can't be initialized inside functions. However, you can
  4634.  define str2 either way:
  4635.  
  4636.    char *str2 = "This is a string" ;
  4637.  
  4638.  or
  4639.  
  4640.    static char *str2 = "This is a string" ;
  4641.  
  4642.  In the first case, 2 bytes will be allocated on the function's stack frame
  4643.  for str2, and the function will store the address of the string in that
  4644.  location. In the second case, the str2 pointer variable is stored in static
  4645.  memory just as if it were defined outside the function.
  4646.  
  4647.  So far it looks like the array definition is preferable to the pointer
  4648.  definition, but this is not always the case. One important distinction is
  4649.  that str2 is an lvalue, but str1 is not; that is, you can assign another
  4650.  pointer to str2. You can say
  4651.  
  4652.    str2 = str1 ;
  4653.  
  4654.  but you cannot say
  4655.  
  4656.    str1 = str2 ;
  4657.  
  4658.  If you go back and look at the assembly language code for the str1
  4659.  definition, you will see that this second statement makes no sense.
  4660.  
  4661.  Initialized strings are more efficient when defined as an array. However,
  4662.  if you need to use the variable name as a pointer to other strings, then
  4663.  you must use a pointer definition.
  4664.  
  4665.  
  4666.  Recognizing Windows
  4667.  
  4668.  Dear Dr. Bob,
  4669.  
  4670.  When I try to execute a Windows application on the DOS command level, I get
  4671.  the message "This program requires Microsoft Windows." How does a Windows
  4672.  application determine whether it's running under Windows or running under
  4673.  plain MS-DOS?──Wondering
  4674.  
  4675.  Dear Wondering,
  4676.  
  4677.  It doesn't. Although Windows programs have an .EXE extension, the format of
  4678.  the .EXE file is different from the DOS .EXE format. This "new format
  4679.  executable" is created by LINK4, the Microsoft Windows linker. Only the
  4680.  Windows loader knows about the new format of the .EXE file; MS-DOS does not.
  4681.  But the new format executable is constructed in such a way that it appears
  4682.  to MS-DOS to be an old format executable.
  4683.  
  4684.  The program that runs when Microsoft Windows loads the .EXE file is the
  4685.  Windows application. The program that runs when MS-DOS loads the .EXE file
  4686.  is a small piece of code that prints the message "This program requires
  4687.  Microsoft Windows."
  4688.  
  4689.  The new format executable is required to give Microsoft Windows more
  4690.  information about the program. Windows must know which segments of the
  4691.  program are code and which are data, which segments it can move around
  4692.  in memory and
  4693.  
  4694.  which segments must be fixed, whether a segment can be loaded immediately or
  4695.  only when it is needed, and so forth.
  4696.  
  4697.  The new format executable also contains support for resources (menus, icons,
  4698.  cursors, bitmaps, dialog boxes, etc.) that Windows loads from the disk as
  4699.  the application requires them. All calls to Windows functions from the
  4700.  application appear in the new format executable as dummied-out far calls.
  4701.  The Microsoft Windows loader resolves these calls based on a table that is
  4702.  also within the .EXE file.
  4703.  
  4704.  The program that runs when MS-DOS attempts to execute the Windows
  4705.  application can be any .EXE file and not necessarily the standard one. You
  4706.  could even use a non-Windows version of your application for that file.
  4707.  
  4708.  
  4709.  Figure 1:
  4710.  
  4711.  videomode = *(char far *)0x400049L ;
  4712.  
  4713.  
  4714.  Figure 2:
  4715.  
  4716.  *(char far *)0x400049L = videomode ;
  4717.  
  4718.  
  4719.  Figure 3:
  4720.  
  4721.  #define MEMC(s,o) (*(char far *)((long)(s)<<16|(o)))
  4722.  #define MEMI(s,o) (*(int far *)((long)(s)<<16|(o)))
  4723.  
  4724.  
  4725.  Figure 4:
  4726.  
  4727.  videomode = MEMC (0x40, 0x49) ;
  4728.  MEMC (0x40, 0x49) = videomode ;
  4729.  
  4730.  
  4731.  Figure 5:
  4732.  
  4733.  int far *colorscreen = 0xB8000000L ;
  4734.  
  4735.  
  4736.  Figure 6:
  4737.  
  4738.  _str1    db "This is a string", 0
  4739.  
  4740.  
  4741.  Figure 7:
  4742.  
  4743.  label    db "This is a string", 0
  4744.  _str2    dw label
  4745.  
  4746.  
  4747.  
  4748.