Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C/C++

C Programming


MAY96: C PROGRAMMING

Several years ago, I worked on a government project developing what can best be described as a "document processor" application. The project was based on a master text database of construction-engineering specifications. The database constituted a comprehensive document boilerplate from which sections were extracted to build custom specifications for the construction of buildings. The project resulted in a software application that runs on PCs and supports several agencies. The version that I worked on was a DOS text-mode application running on AT-class machines.

We integrated a word processor into the application, selecting one with an all-ASCII format for the document database so that our software could readily extract and renumber selected paragraphs, reconcile references, and so on. The project took some criticism because of the commercial word processor we used. Contractors who wanted to bid on government construction projects had to use our system, which meant that they had to buy the commercial word processor. That was viewed as an undue burden to assess on contractors who were struggling to make ends meet and still remain competitive. However, short of writing a custom word processor, we had no alternative. No one in the government wanted to fund the development of a word processor when perfectly good commercial ones existed.

Eventually, when Microsoft and WordPerfect took all the DOS word-processor business away from the little guys, the vendor of our word processor dropped the product. The government bought rights to the software so that the project could continue to support it. The burden of paying for the word processor was thus lifted from subsequent users of the system.

Several years ago, the project team began converting the system to Windows 3.1. At about the same time, they modified the database to support the Standard Generalized Markup Language (SGML) because that format is a Department of Defense standard for text databases. SGML is an all-ASCII text format that uses embedded tags to associate parts of a document with the document's unique Data Type Dictionary (DTD), which defines the document's structure and rules. The structure depends on the hierarchical format that most documents adhere to. The SGML format defines only a document's structure, whereas the proprietary formats of word processors define a document's appearance. An SGML document is therefore portable to any platform that supports SGML and can be rendered on that platform's printers, CD-ROMs, Web pages, and so on. The Hypertext Markup Language (HTML) is itself implemented as a DTD within SGML.

No SGML Windows word processor existed three years ago when the project team elected to support SGML. Consequently, they undertook the development of a Windows-hosted text editor that looks like a typical Windows word processor, supports SGML, and incorporates some of the application-specific functions. Funding was made available because there was no other choice. This approach had the added advantage that, once again, users would not be required to purchase a commercial product in order to use the application.

Freeze frame at this point. Design decisions were made based on what was known to be available at that time. Crystal balls were not--and still are not--standard government issue.

Now, fast forward three years to the present. The Web reigns. Electronic publishing is ubiquitous. CD-ROM authoring systems abound. SGML is a hot item. Microsoft introduces "Author," a two-way filter that converts between SGML and Word formats. Novell introduces WordPerfect 6.1 SGML Edition, a native SGML word processor. There are many commercial, freeware, and shareware SGML parsers and editors. The world is about to embrace SGML.

Back home, the project's custom SGML editor is less than an overwhelming success. It runs slowly on low-end machines and was released too soon, giving users early exposure to the dreaded Windows GPF. What's more, by the time the editor was released, users had become accustomed to, and spoiled by, feature-laden commercial Windows word processors. They didn't like the application's slow, unreliable, feature-poor, custom SGML editor.

Quite recently, and with the perfect wisdom of 20/20 hindsight, someone in the user community wrote a letter to his senator suggesting an investigation into why the government is wasting money developing an SGML editor when commercial Windows word processors with SGML capabilities are available. The senator's staff, not knowing anything whatsoever about the issue, sent an inquiry under the good senator's signature to the agency, probably just to satisfy the would-be whistle-blower. The matter should have died there, but letters of inquiry from U.S. senators cannot be ignored. This one resulted in many hours of effort and piles of paperwork at all levels from the agency's top management down to the project team, as everyone scrambled to explain what they were doing and why. Your tax dollars at work.

Which brings me to the point. Software technology shifts are constantly and rapidly stimulated by market pressures and advances in hardware bandwidth. No one can predict with any certainty or accuracy how things are going to change. When you launch a development project that has much more than a few months on its schedule, by necessity you must base it on technology that can be obsolete, dramatically changed, or even unavailable by the time of your first scheduled release.

The earlier experience with the soon-to-be-obsolete DOS text-mode word processor is a case in point. At the time, that product was the only one available that suited the project's needs. The fallout from that decision could have been costly. If, in the course of going belly-up, the vendor had shredded the source code, a major government project would have been seriously impacted.

Programmers today are faced with those kinds of decisions all too often. I get criticized for endorsing the Microsoft Foundation Classes when there are many other fine framework class libraries available. But I am above all a pragmatist. A tool's potential and propensity for endurance are as important as its momentary usefulness. Any development project of any consequence will span years. Our selection of a tool must consider the likelihood that the tool's life span will equal that of the project that uses it. Don't sweat the small stuff. You can change editors in midstream. You can switch to a better debugger if one comes along. But if you base your product on the proprietary architecture of someone else's software, you'd better be sure that support will continue and that the software will grow and evolve along with the other parts of the system.

CD-ROMs and Long Filenames

Take a look at the CD-ROMs that Microsoft ships with Windows 95 development products on them. Visual C++. Windows 95 itself. Do you see long filenames? Not many. Wonder why? I think I just found out. While developing a companion CD-ROM for a Windows 95 C++ programming book, I built a prototype of the CD-ROM on 100-MB Zip disks, which I sent to the publisher to get mastered onto a CD-ROM. When the CD-ROM master was written, my publisher called in a panic to say that she could not read some of the subdirectories and files on her Windows 95 computer. She sent the CD-ROM to my coauthor who had no problem with it. He sent it to me, and I tried it out on three different machines. It worked fine on all but one of my computers, the one with the Teac SuperQuad. That drive has abominably slow Windows 95 drivers, so I'm using the DOS 16-bit drivers instead. The penalty is that I cannot share the drive on the network. With that as a clue, I went to one of the other machines, one that worked okay with the CD-ROM, removed the Windows 95 drivers, and installed the DOS 16-bit drivers into CONFIG.SYS and AUTOEXEC.BAT. With that configuration, long filenames are unseen by Windows 95; their 8.3-format counterparts are unseen, too. I verified this conclusion by trying to read some of the files on the Microsoft Office CD-ROM. It uses long filenames, and the same problems occurred.

So beware. If you are using Windows 95 to construct a CD-ROM, either alert your users that they must have Windows 95 CD-ROM drivers or truncate all the filenames to the 8.3 format. This can be a problem if you are distributing source code on CD-ROMs. A typical Visual C++ Developer Studio session generates header and CPP files with long filenames to represent the classes they implement. If you distribute a GNU derivative program, you must also distribute all the GNU source code. The GNU compiler suite includes many files with long filenames.

To Singapore and Back

I spent the first week in February in Singapore teaching the concepts of C++ frameworks in game development to a small class of college freshman at Ngee Ann (pronounced "neon") Polytechnic. This trip, made at the invitation of the Center for Computer Studies, was one of the perks that comes with the notoriety that this column and my books afford me.

The staff at Ngee Ann Polytechnic was using game development as a vehicle to inspire the students' interest in computer programming. The 15 students who signed up needed no inspiration. They were bright, attentive, polite, and extremely well versed in the C language. I used the occasion to reveal some of the behavior of C++ classes, and to a man they soaked the knowledge up like so many sponges.

Singapore is a beautiful, tropical island country about 85 miles north of the equator. It's small enough that there are no telephone area codes. Unemployment and crime are not a problem. It was in Singapore that a young American lad was caned for spraying graffiti on a car. To be caned is to be swatted several strokes across the backside with a big stick. The incident got a lot of publicity when President Clinton displayed his diplomatic skill by negotiating a sentence reduction--four strokes instead of six. Where was he when I got caught pilfering Dad's Camels? Drug dealing is not tolerated in Singapore, being a capital offense with swift execution of the sentence. Chewing gum is forbidden, too. You cannot import or sell chewing gum. The law was passed to prevent kids from leaving gum stuck on public places as kids will do. Rather than pass a law that they cannot enforce--don't stick gum where it does not belong--they passed a law they could enforce--don't import or sell chewing gum. Effective. We read about that after we arrived in the country. As a consequence, Judy is now an undetected but guilty, nonetheless, international smuggler of a controlled substance. I offered her several strokes of the cane, but she firmly declined.

The Road Ahead

On the plane to Singapore I read Bill Gates' new book, The Road Ahead, (Penguin Books, 1995). I was skeptical about how much of this book Gates actually wrote. He mentions two collaborators inside, but not on the cover. Most likely, he wrote the foreword without help. I say that because it's not as well written as the rest of the book. Odd that he would write his own foreword. Forewords are traditionally written by someone else. Authors persuade some luminary in their field to write a foreword to add credibility to the work. Gates, having written forewords for other authors, knows that but seemingly decided to write his own foreword anyway. I guess when you are Bill Gates, there is no brighter luminary.

The book relates Bill's vision of the information superhighway, what it is and what it will become. Clearly, he intends for Microsoft to be a major player in that arena, and this book introduces that intention to the rest of us--as if we hadn't already guessed. The Web explosion happened while Windows 95 was in beta, and Microsoft was caught short. Gates means to catch up, and this book, apparently, is the launch. A few days ago, Microsoft announced a major reorganization toward that goal.

For example, Microsoft recently made its new Web browser and server programs available for free download, an obvious assault on Netscape's success. An acquaintance of mine downloaded and installed the Web server program under the NT server operating system. Then he used both Netscape's Navigator and the Microsoft Web browser to access his own pages. He noticed a significant performance lag with Netscape and speculates that the Microsoft server could be intentionally sensing its own browser and running better with it than with competing browsers. I chided him that such shenanigans are clearly beneath Microsoft, a company that would never resort to dirty tricks to make the competition look bad. Oh, yeah? This sounds like a job for Andrew Schulman.

The Road Ahead does a good job of explaining what Gates calls simply "the highway," its origins and its current state. Then the book lays out what Gates sees as the future of the technology and its impact on society, business, industry, and the international community. It's an easy read, covers the subject comprehensively at the lay level, and its prophesies are probably reasonable.

But The Road Ahead is not without some speed bumps. In a discussion of a society where your every move is recorded and documented by the government with concealed cameras, Gates calls the practice "unremarkable," citing it as being welcome by citizens concerned about crime. He says, "Almost everyone is willing to accept some restrictions in exchange for a sense of security."

Chilling. I am reminded of the words of another of our wealthy and famous leaders from the past who said, "Those who desire to give up Freedom in order to gain Security, will not have, nor do they deserve, either one." Those words, spoken by Thomas Jefferson, come to mind whenever someone suggests to me that society is best served by citizens being asked or forced to sacrifice yet one more freedom for the common good. On balance, I should point out that one of the freedoms that Jefferson himself was not willing to give up was the freedom he enjoyed to own slaves. His philosophy, however, outlived his contradictory practices, but I'm afraid we learned little from it. We are allowed to chew gum, however.

Quincy 96 and DDE

I suppose some of this column ought to be dedicated to C/C++. I'm wrapping up the development of Quincy 96, the Windows 95-hosted IDE that acts as a front end for the gnu-win32 port of the GNU C/C++ compilers. Since Quincy 96 is meant to be used from inside an interactive tutorial, it needs to be launched and controlled from another program, in this case, an Asymetrix Toolbook script. I chose DDE as the protocol for the commands that the script sends to Quincy 96 for two reasons: First, Toolbook's OpenScript language supports launching and sending DDE commands to other programs. Second, I can test the commands in the absence of the script by setting up dummy files with the names of the commands and associating them with Quincy 96 through the Windows 95 File Type mechanism.

I thought I had everything working prior to integrating the two parts of the system. I had allowed the Visual C++ Developer Studio to install DDE protocols into Quincy 96, and I had put the necessary program-launching and command-sending code into the Toolbook script. I had installed the command functions into Quincy 96 and tested them by double-clicking the dummy files that simulate the commands. But, when I put the two parts--the Toolbook application and Quincy 96--together, the command exchange did not work. As a test, I substituted a launch and command from Toolbook to Microsoft Word to see if the mechanism worked from the script. It did. Then I tried using Notepad as the target application. That did not work. The return value from the script's command said that no DDE server was running to accept the command, which was the same thing that I was getting from Quincy 96. This did not make sense. You can drag and drop files and double-click registered files to open them into Notepad, Word, and Quincy 96. The calls to DragAcceptFiles, EnableShellOpen, RegisterShellFileTypes, ParseCommandLine, and ProcessShellCommand that Developer Studio puts into the derived CWinApp class are supposed to take care of that. Why did the command mechanism work only for Word and not for the others?

In desperation, I did what we all hate to do. I went to the documentation. It turns out that in order to be a DDE command server, an application must register itself as such and provide a callback function to process the DDE commands. Listing One shows the code that I added to Quincy 96 to do that. None of the functions are members of any of the MFC classes. The overloaded CWinApp::InitInstance function calls the RegisterDDE function to register the protocol. The DdeCallback function calls the overloaded CWin|App::OnDDECommand function to process the command. I took this code from the examples in the Win32 SDK documentation and whittled away at it until it fit into the MFC design. Some of it might not be necessary, particularly some of the cases in the switch statement in the callback function. The code works, however, and I am reluctant to mess with it. Anyone more familiar with this architecture is encouraged to send me a message and set me straight. By the way, this exercise involved a lot of operating system crashes before I finally got everything working.

Source Code

The source code files for the Quincy 96 project are free. You can download them from the DDJ forum on CompuServe and on the Internet by anonymous ftp; see "Availability," page 3. To run Quincy, you'll need the GNU Win32 executables from the Cygnus port. They can be found on ftp.cygnus.com/ in the /pub/sac directory. Get Quincy 96 first and check its README file to see which version of gnu-win32 you need. Every time they release a new beta, I have to make significant changes to Quincy 96. As I write this, the latest beta is Version 13 and Quincy 96 works with Version 10.

If you cannot get to one of the online sources, send a 3.5-inch high-density diskette and a self-addressed, stamped mailer to me at Dr. Dobb's Journal, 411 Borel Avenue, San Mateo, CA 94402, and I'll send you the Quincy source code (not the GNU stuff, however--it's too big). Make sure that you include a note that says which project you want. The code is free, but if you care to support my Careware charity, include a dollar for the Brevard County Food Bank.

Listing One

TCHAR szApp[] = TEXT("Quincy");   // DDE service name
DWORD idInst = 0;                 // our DDEML instance object
HSZ   hszAppName = 0;             // the generic hsz for everything
UINT  OurFormat;                  // our custom registered format
HDDEDATA CALLBACK DdeCallback(WORD wType, WORD wFmt, 
     HCONV hConv, HSZ hszTopic,HSZ hszItem, HDDEDATA hData, 
     DWORD lData1, DWORD lData2);
void RegisterDDE()
{
    DdeInitialize(&idInst,
       (PFNCALLBACK)MakeProcInstance((FARPROC)DdeCallback, hInstance),
       APPCMD_FILTERINITS |
       CBF_SKIP_CONNECT_CONFIRMS |
       CBF_FAIL_SELFCONNECTIONS |
       CBF_FAIL_POKES,
       0);
    hszAppName = DdeCreateStringHandle(idInst, szApp, 0);
    OurFormat = RegisterClipboardFormat(szApp);
    DdeNameService(idInst, hszAppName, 0, DNS_REGISTER);
}
HDDEDATA CALLBACK DdeCallback(
WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hszTopic,
HSZ hszItem,
HDDEDATA hData,
DWORD lData1,
DWORD lData2)
{
    LPTSTR pszExec;
    switch (wType) {
    case XTYP_CONNECT:
        return((HDDEDATA)TRUE);
    case XTYP_ADVREQ:
        return(DdeCreateDataHandle(idInst, (PBYTE)&count, 
               sizeof(count), 0, hszAppName, OurFormat, 0));
    case XTYP_ADVSTART:
        return(HDDEDATA)
           ((UINT)wFmt == OurFormat && hszItem == hszAppName);
    case XTYP_EXECUTE:
        pszExec = (LPTSTR)DdeAccessData(hData, NULL);
        if (pszExec)
            theApp.OnDDECommand(pszExec);
        DdeUnaccessData(hData);
        return (HDDEDATA)DDE_FACK;
    case XTYP_REGISTER:
        return((HDDEDATA)TRUE);
    }
    return(0);
}


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.