×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

Comments

top

Al Franken Calls for Tight Rules on Facial Recognition Software

codefool More likely... (158 comments)

Al Franken wants controls because his facial scan identifies as "asshole."

about 2 years ago
top

What's To Love About C?

codefool Re:Shorthand for Assembler (793 comments)

I agree with your comments. When I started with the Lifeboat compiler "back in the day" I could visualize the assembly that would be generated with the C code being written. Reading from K&R, it's clear that constructs such as switch(), prefix/postfix increments and the like, the register modifer, etc. were all there to make it easier to generate straight-line assembly in a friendlier syntax (I seem to recall that it would, in fact, generate an assembly source listing if requested.). Even the #asm shows the intimacy between the two. To your points, modern compilers "interpreting" C source into something that is much smaller/faster may get a Good Thing in the long run, but I miss the days when I could just code and know exactly what the compiler would produce. I also remember those times I had to write subroutines in assembler because the compiler refused to produce what I wanted. Sometimes the optimizer is wrong.

about 2 years ago
top

What's To Love About C?

codefool Shorthand for Assembler (793 comments)

The power of C is - and always has been - that it is a shorthand for assembly. It compiles very small and runs very fast, making it ideal for embedded systems.

about 2 years ago
top

Why 'Nigerian Scammers' Say They're From Nigeria

codefool Re:please ignore (209 comments)

I highly recommend that you go to 419eater.com and read the stories - it's the best way to lose an afternoon, besides being highly entertaining, informative, and horrifying all at the same time. And, yes, the way these "baiters" operate is not unlike masked vigilantism.

about 2 years ago
top

Microsoft Brings Back DRM

codefool Amazing! (414 comments)

Yet another Microsoft product that is meticulously planned, engineered, and executed such that no one will want to pay for it. Except Mr. Bill, that is.

MS: "Here's our version of an established service, but ours has more restrictions and costs more!"
Mr. Bill: "Sign me up!"
Everyone else: "Pound sand!"

more than 5 years ago
top

Bill Gates Chews Out Microsoft

codefool My favorite quote (836 comments)

So they told me that using the download page to download something was not something they anticipated.
Yes, M$ can certainly advise me on how to build my applications. Now, aren't you glad you bet the farm on CLR?

more than 5 years ago

Submissions

codefool hasn't submitted any stories.

Journals

top

codefool codefool writes  |  more than 8 years ago few simple lines of PHP (or equiv in any other language) can pull the real IP from a non-anonymising proxy:

    <?php

    if ($_SERVER['HTTP_X_FORWARDED_FOR'] == NULL) $ip = $_SERVER['REMOTE_ADDR'];
    else {
    $source = $_SERVER['HTTP_X_FORWARDED_FOR'];
    $pattern = "/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/";
    preg_match($pattern, $source, $matches);
    $ip = $matches[0];
    echo "Proxy detected (" . $_SERVER['REMOTE_ADDR'] . ")<br />";
    }

    echo $ip;

    ?>

top

codefool codefool writes  |  more than 9 years ago 2005.05.15 ==============
Oil and Filter Information

Oil Filter OEM: #16097-1054, #16097-1056

2005.04.13 ==============
Kawasaki Dealer 10 miles from work:

WILD WEST KAWASAKI
22515 KATY FWY
KATY, TX 77450-1535
(281) 392-8850 Phone
(281) 392-6162 Fax
(281) 392-8940 Service

2005.02.01 ==============
Ordered MOM from

Houston Kawasaki
(713) 783-3844
5802 Southwest Fwy
Houston, TX 77057

$16 or so. Charged to AMEX.

Price New: $4900

Price Now: $1524

top

Time-Sliced Procedures in Javascript

codefool codefool writes  |  more than 9 years ago /////////////////////////////////////////////////////////////////////////////////////////
//
//  clsTimeSlice
//
//  The atomic time slice object. Represents either a function call or a method call
//  to an object. The evoked function/method must answer false to continue processing, or
//  true to terminate it.
//
function clsTimeSlice( fnSlice, objObj, name, latency )
{
    this.fnSlice = fnSlice;
    this.obj     = objObj;
    this.name    = name;
    this.latency = ( null == latency || latency < 1 ) ? clsTimeSlicedProc.SLICE_LATENCY : latency;
}

clsTimeSlice.prototype.exec =
    function()
    {
        var bRet;
        if( null != this.obj )
            bRet = this.fnSlice.call( this.obj );
        else
            bRet = this.fnSlice();
        return bRet;
    }

/////////////////////////////////////////////////////////////////////////////////////////
//
//  clsTimeSlicedProc
//
//  Container for a time-sliced procedure.
//
function clsTimeSlicedProc( sObjectName )
{
    this.init( sObjectName );
}
clsTimeSlicedProc.CHAIN_INDEX            = -1;
clsTimeSlicedProc.SLICE_LATENCY          = 2;   // #ms between slices

clsTimeSlicedProc.prototype.init =
    function( sObjectName )
    {
        this.name       = sObjectName;
        this.slices     = new Array();
        this.sliceChain = null;
        this.latch      = false;
        this.next       = 0;
        this.error      = 0;
        this.run        = false;
    }

clsTimeSlicedProc.prototype.reset        = function()          { this.init( this.name ); }
clsTimeSlicedProc.prototype.sliceCnt     = function()          { return this.slices.length; }
clsTimeSlicedProc.prototype.slice        =
    function( idx )
    {
        if( idx < this.sliceCnt() )
            return this.slices[ idx ];
        return null;
    }

clsTimeSlicedProc.prototype.latched      = function()             { return this.latch; };
clsTimeSlicedProc.prototype.addSlice     = function( s )          { this.slices[ this.slices.length ] = s; return s; }
clsTimeSlicedProc.prototype.createSlice  = function( f, o, n, l ) { this.addSlice( new clsTimeSlice( f, o, n, l ) ); return this; }
clsTimeSlicedProc.prototype.addFunction  = function( f, n, l )    { this.addSlice( new clsTimeSlice( f, null, n, l ) )._f = true; return this; }
clsTimeSlicedProc.prototype.chain        = function( f, o, n, l ) { this.sliceChain = new clsTimeSlice( f, o, n, l ); return this; }
clsTimeSlicedProc.prototype.setErrorCode = function( c )          { this.error = c; }
clsTimeSlicedProc.prototype.hasError     = function()             { return !!( this.error != 0 ); }
clsTimeSlicedProc.prototype.finish       = function()             { this.next = clsTimeSlicedProc.CHAIN_INDEX; }

clsTimeSlicedProc.prototype.begin        =
    function()
    {
        if( this.latch )
            return false;

        this.latch = true;
        this._doSlice( this.next );
        return true;
    }

clsTimeSlicedProc.prototype.setNextSlice =
    function( indexOrName )
    {
        if( typeof indexOrName == "string" )
        {
            // search for a slice by name
            for( var idx = 0; idx < this.slices.length; idx++ )
            {
                if( this.slice( idx ).name == indexOrName )
                {
                    this.next = idx;
                    break;
                }
            }
            if( idx >= this.slices.length )
                alert( this.name + ": Not able to find slice with tag '" + indexOrName + "'" );
        }
        // must allow index to exceed slice count in order for loop to ever terminate!
        else if( indexOrName <= this.sliceCnt() )
            this.next = indexOrName;
    }

clsTimeSlicedProc.prototype._doSlice =
    function( iIndex )
    {
        var l = ( iIndex in this.slices ) ? this.slices[ iIndex ].latency : clsTimeSlicedProc.SLICE_LATENCY;
        setTimeout( this.name + ".exec( " + iIndex + ")", l );
    }

clsTimeSlicedProc.prototype.exec =
    function( iIndex )
    {
        if( clsTimeSlicedProc.CHAIN_INDEX == iIndex )
        {
            if( null != this.sliceChain )
                this.sliceChain.exec();
            this.sliceChain = null;            // chain is a one-shot deal
            this.latch = false;
        }
        else
        {
            if( !this.hasError() && iIndex < this.sliceCnt() )
            {
                this.setNextSlice( iIndex + 1 );
                if( this.slices[ iIndex ].exec() || this.slices[ iIndex ]._f )
                    iIndex = this.next;
                this._doSlice( iIndex );
            }
            else
            {
                this._doSlice( clsTimeSlicedProc.CHAIN_INDEX );
            }
        }
    }

top

codefool codefool writes  |  more than 9 years ago

[This is so good - I'm archiving it here until I get my *other* repository up]

I will be presenting a session at TechEd in Amsterdam next week on the subject of software development - "21 Rules of Thumb - How Microsoft develops its Software". As someone who has been involved with software development for over two decades, the whole area of how you actually bring together a team and get them to successfully deliver a project on time, is one worthy of a lot of attention, if only because it is so hard to do. Even before I joined Microsoft, ten years ago, I was interested in this topic, having been involved myself in a couple of projects that, I shall politely say, were somewhat "less than successful".

So, just how do you get teams to work together successfully? I've written a few articles on it, interviewed people at Microsoft about it, and witnessed it first hand with teams inside and outside Microsoft. Jim McCarthy, who I have met and heard present, whilst at Microsoft, in the C++ team, wrote an article entitles "21 Rules of Thumb for Shipping Great Software on Time" (which I have enclosed at the end of my blog in its original form) and followed it up with a book "Dynamics of Software Development". My session at TechEd is largely based on this article, and so if you are inspired by this session, then the best thing you can do is buy the book (and no, I don't get any commission!) and start using it. (He also has a newer book "Software for Your Head: Core Protocols for Creating and Maintaining Shared Vision" which you may want to look at as well)

The other topic I cover in my session is the Microsoft Solutions Framework (MSF). If Jim's contribution is the anecdotes and rules of thumb, then this is the more formal documentation from Microsoft. MSF has been an ongoing initiative within Microsoft since 1994 to document the best practices that the Microsoft product groups, customers and partners, have used in the software development process. I was one of the first MSF trainers in the UK back then, and have delivered MSF training courses and seminars to customers many times over the years.

All the information you need on MSF can be found at http://www.microsoft.com/msf , including an MSF 3.0 overview white paper, and details of the team and process model, which are at the core of MSF. There is also an update on how Visual Studio 2005 Team System, which we recently unveiled at TechEd in San Diego, works with MSF.

Here is Jim's original article:

21 Rules of Thumb for Shipping Great Software on Time

Jim McCarthy, Microsoft Corporation

Shipping great software on time is a difficult but not impossible task. Elements you think would count the most count for very little. Development methodology, process, technical prowess, excellence of tools and depth of project management skills all influence the outcome of a software development project; but nothing indicates success as much as the manager's ability to focus on a few critical and conceptually simple things. These things can be expressed as rules of thumb.

I enumerate twenty-one of these rules of thumb. Pick a handful (or so), apply them, and your project will be more likely to succeed. I lump them into three groups: "Shipping," "Great Software," "On Time". Duh. I cover them in a different order, because the concepts build a bit.

On Time

1. Don't know what you don't know.

It is essential not to profess to know, or seem to know, or accept that someone else knows, that which is unknown. Almost without exception, the things that end up coming back to haunt you are things you pretended to understand but didn't early on. At virtually every stage of even the most successful software projects, there are large numbers of very important things that are unknown. It is acceptable, even mandatory, to clearly articulate your ignorance, so that no one misunderstands the corporate state of unknowingness. If you do not disseminate this "lucid ignorance," disaster will surely befall you.

Human nature is such that we dislike not knowing things that are important to our well being. Since there is so much we don't know in a software project, the nearly universal tendency among developers and their managers is to gloss over or even deny altogether the extent of their ignorance. You should reward and treasure those who consistently make themselves aware of the list of relevant things that are currently unknown. It requires mental and psychological strength to resist the normal human cravings for certainty and order. It especially difficult to believe in uncertainty when things have a veneer of orderliness, which is often the case. Pseudo-order is a maladapted defense against uncertainty.

The organization surrounding you will undoubtedly abhor uncertainty, would infinitely prefer pseudo-order and will make countless attempts to magically convert your ignorance to knowledge. Your job is to make uncertainty an unshakable fact, and to coerce the reshaping of the surrounding organization to cope with the uncertain situation. The organization must learn to thrive in an uncertain environment for its own well being.

You should expend a great deal of effort making sure that all the people on the project are aware of their ignorance rather than naively converting it to falsehoods. Bear down on them until they realize they haven't comprehensively assessed the unknowns. In the successful project, this is much easier in the early stages, or during times of change. This is no time for niceties. People ultimately prefer success even if disillusionment is a prerequisite.

2. Get to a known state and stay there.

The function of QA is to know (and articulate) the quality of the product at all times in the development cycle. This should be achieved by abbreviated, repeatable tests conducted daily, and full product sweeps conducted weekly or biweekly.

It is not properly the job of QA to determine when a product is ready to ship; rather, the moment of shipworthiness in a product development cycle is evident to everyone involved, and is non controversial. This is because shipping has been the goal of the entire effort. Crossing the finish line, while it has intangible emotional and definite financial rewards, is no surprise when you've observed every single painful step toward it.

The only reason you've been able to make these micro-observations is because you got to a known state and stayed there, and your QA is how you did it.

Achieving a relatively accurate view into product status is a very challenging goal, requiring a highly motivated and competent QA team. It is also a pre-requisite for success. Many software development organizations have rudimentary or no real QA assets, and there is little that can be done for them until they make the appropriate investments in creating a modern development organization.

A known state consists of all components having accurate status information at a given point in time. You know that it's accurate because the status has been tested by QA.

A developer articulating the status of his/her component is an exercise that does produce information, but if it happens to communicate the component's status, it is only coincidental. This is someone else's job.

Status should consist of a comprehensive listing of tested and missing functionality, bug count sorted by severity, bug arrival rate, bug fix rate, projected total bug count, and other vital metrics.

3. Remember the triangle.

There are only three things that you are working with as a development manager: resources (people and money), features and the schedule. Changing one has an impact on at least one other axis, usually two. It is a simple enough matter to mentally run through the sides of the triangle, or force others to do so, when discussing any part of it. Since the people, the product or the schedule is almost always what you're discussing, this means that you must constantly envision the triangle. This leads to the most fruitful line of thought.

4. Don't go dark.

Some features have long development lead times, months or even years. Yet slips usually happen a little bit every day, and must be compensated for a little every day. This means that the granularity of development tasks must be such that deliverables are achieved at intervals sufficiently small that slips can be compensated for. A week is a long time to go without knowing what is happening. While micromanaging is always a danger, and will certainly be an accusation leveled against you from time to time, if the goal of the project is to ship great software on time, and if everybody accepts that goal as uppermost, they generally enjoy the chase. Team interdependency is also a powerful motivational force.

5. Use zero defect (ZD) milestones.

Organize the project around the concept a reaching milestones with zero defects. Zero defects does not mean that the product does not have bugs, or missing functionality; it means that the product achieves the quality level that had been set for that milestone. The product is tested to that effect. The essential point of ZD milestones is that nobody makes the milestone until everybody does, and nobody leaves it until everybody does. This enables the team to discover what aspects of the project are in trouble. Load balancing can occur. Awareness of unknowns rises.

At a milestone, the team and its leadership also have the opportunity to perceive the whole project status simultaneously, to draw conclusions about erroneous practices, to remedy bad design decisions and to reorganize for peak performance. Shipping is just the final milestone. Though the external organization cares most about shipping, which adds special pressure to that milestone, the team develops extraordinary focus and introspection about each and every milestone.

6. Beware of a guy in a room.

This is really just a special case of "Don't go dark." Specialist developers who lock themselves away in a room, going dark for long stretches, are anathema to shipping great software on time. Without regard to their individual brilliance, before investing a developer with a significant assignment, it is essential that they understand and agree with the type of development program you intend to run. They must be capable of performing on a team, making their work visible in modest increments and subjecting it to scrutiny as it matures. Some people find this intolerable, and though there is a role for people of this disposition in the software world, it is not as part of a team devoted to shipping great software on time.

There are many pathologies at play here as well as certain healthy patterns of creative behavior. One pathology is a type of savior complex that cannot be satisfied without blowing every single deadline but the last, and then emerging victoriously with a brilliant piece of work five minutes late. A more healthy pattern is that of the true innovator who is truly designing something great, but who has no personal resources left over for anything but the work at hand. Every ounce of psychological, emotional and intellectual energy is being consumed in the work itself. Teamwork, in this case, is an insignificant factor to a person immersed in this sort of creative experience.

But whether or not the cause is healthy or bogus, the results are uniformly fatal to the professional development organization. Beware. Extricating yourself from this trap is nearly impossible.

7. Never trade a bad date for an equally bad date

Generally, you know you're going to be late before you know when you're going to be done. Further, everybody on the team and everybody they come in contact with knows you're not going to hit the schedule. The pressure to reset the end-date (or the milestone date) is enormous. Even though your information is obviously better now than when you originally set your goal, it is probably insufficient to make a new schedule. This is because with each slip, you and your team are spending your credibility. It is essential that after a slip, the next milestone be hit. This is so the team believes in their ability to manage the project, and so that the reserves of credibility are rebuilt for later consumption.

It is difficult to say precisely and in all cases when you should "officially" slip. A good general rule is that the schedule should be reset when the total extent of the slip is known for each component, the causes of the slip are understood, and remedies are in place. Usually, this takes the effort of the entire team and its leadership, and must be an explicit, focused activity. After this level of work is achieved, create a new, closer and more conservative milestone which the team is very likely to hit, and promulgate that. Avoid just sliding the schedule out. Your near-in milestone should be extremely realistic, and uncertainties about later milestones will remain and should be highlighted.

8. When slipping, don't fall.

Slipping is what happens when information that was unknown becomes less unknown. Though slipping is widely perceived to be a "bad" thing, it is the symptom of a good thing, as a fever is the sign of the body's immune system at work. Although it is undesirable to have so many unknowns that slippage occurs, it is not an unusual situation, and may even be the norm. This is because much of contemporary software development is essentially experimental, i.e., new platforms, new operating systems, new programming technologies often coalesce on new programming projects to create a high degree of uncertainty.

In order to avoid calamity, certain measures should be undertaken in connection with a slip. Ideally, one or more of the pre-identified unknowns caused the slip. It is important that everybody involved understand that the risk to the schedule had been known previously. Alternatively, it is essential to understand how the unknown/s had come to be overlooked. How this gap occurred should become part of the group knowledge for future success. Also, determine whether or not people are working on the correct things. Often, slips occur because members of the team become occupied with features of marginal consequence, or features that are not part of the core product message.

If the slip was a surprise, your communications system is broken, and dramatic communications efforts are required. Large amounts of detail must be brought to the surface for everybody on the team to see. Assess the reality of all current near-term estimates. Expose denial. Team defensiveness will have to be pushed back for the purposes of group learning. Slips reveal your team's weaknesses, presenting a good opportunity for insightful management and mentoring. Make sure that each individual who has a role in the slip receives the needed guidance and support.

Slips are also an opportunity to re-evaluate the feature content and resource loads, generally with an eye toward decreasing the features and shoring up weaker areas on the team.

A good slip should be a net positive.

9. Low tech is good.

A smaller effort is almost always more desirable than a larger one. Shipping great software on time requires that we value an understood solution much higher than one fraught with unknowns. Keep in mind that customers would almost always rather see progress than promises.

10. Design time at design time.

The product will ship when the design can be shown to be implemented. Developers and their managers often ignore the exigencies of time when creating a design. Instead, they should consider the implementation time as a critical design element. When evaluating alternative design decisions, the one that takes longer to implement is consuming more time and should therefore be disadvantaged in comparison to the alternative. This must always be weighed. Often, when appropriate design value is awarded to timeliness, implementation time can be substantially compressed.

11. If you build it, it will ship.

Conversely, if you don't, it won't. The product should be built every day, along with all setup scripts and on-line help, in a public place, where QA can conduct appropriate assessment of daily status, and the entire team can observe progress or its lack. This is the single biggest indicator that a team is functional and a product being developed.

12. Portability is for canoes.

And system software. Even discounting the added development burden, with the addition of each additional platform the job of QA increases substantially. While clever QA management can minimize the burden somewhat, the complexity of multi-platform support is beyond the reach of most development organizations. Place your bets. Demand multi-platform support from your system software vendor, then build your product on the absolute fewest number of platforms possible.

Great Software

13. Enrapture the customers.

Most software is a renewal business. Customers buy multiple releases over a relatively long period of time. As a consequence, the market has a deep understanding of your software and its flaws, and your organization and its flaws. Often, the market has grown uncomfortably dependent on software that doesn't meet its needs. In many software situations, customers spend hours per/day uncomfortably shoe-horning their lives into your product. As a consequence, they crave your understanding, and will respond enthusiastically to the least sign of it. Normal success, meeting customer expectations, means to improve the most outrageous and flagrant violations of their needs from version to version. They will likely stay with you if you are faithful about that, though they may well be sullen if not mutinous.

Great software, however, requires that you pivot your entire technology so that it flows in the direction of their deepest needs. You must innovate in ways that clearly affirm their inarticulate desires. Surprise them by articulating and resolving in your product concerns and fantasies that heretofore had been rumbling about only in their pre-conscious. The fantasies of the market are generally centered on issues of empowerment, control and security. The market wants to be able to do things with its computers that it currently can't. Customers often find they can't even publicly admit these needs for fear of computer illiteracy. They derive value and security from being able to apply your software. To admit that they can't do what they want to do requires a sense of security beyond most customers' reach.

Market understanding is the foundation of great software. To repeatedly demonstrate through a series of two or three releases that you genuinely understand the market will result in enormous customer loyalty and brand equity. You will be viewed as the source of the market's empowerment. They will be rapturous.

Gaining this understanding and embodying it in your software requires skill, tenacity and creativity. You must recognize the central market need and organize all your technology and communications efforts in the direction of satisfying that need. While good listening, careful observation and concept testing will be required for you to identify the correct need, addressing it in your product will have these effects:

1. It will appeal to the customer's sense of security.

2. It will extend the customer's control.

3. It will be such that if all else were dropped from your product, but the central need was met in unique ways, the product would be compelling.

4. It will clarify your product messages.

5. It will simplify your product's use.

14. Remember one thing: Unity.

Unity is the master principle of great software. Each element in the product is necessary to the value of the whole and all necessary elements are there. Since everything you need is there, you aren't tempted to go beyond the present experience, and since nothing is there that isn't required, your absorption into the world of the product will not be disturbed. Unity of purpose and unity in execution should be the hallmark of your team. Unity is achieved in a product by following certain creative principles (#15-#19, below), whether intuitively or consciously.

15. State your theme.

Theme is the dominant idea that constitutes the basis of the design. All of the values of the product must stem from the theme. In order for people to comprehend the theme, it must be rendered with surpassing clarity. Theme is analogous to purpose. The more specific the purpose, the greater the effect. Having a theme to the product will require that you eliminate or at least minimize orthogonal values. This is painful and involves risk.

16. Vary it.

Variation is the theme restated and elaborated in slightly altered and embroidered ways. Variation is the means by which we intensify the user's comprehension and appreciation of our theme, and leverage his/her growing consciousness in new ways.

17. Balance it.

Allocate appropriate emphasis among the various elements of the product. If a key component supporting the theme, encountered every time the thematic function is enacted, is weak, the theme is weakly stated and the product will be justly criticized.

18. Evolve it.

Evolution is when earlier parts determine later parts. Lessons learned in one part of the product apply to the others. Things progress in a way that is pleasing. Outcomes, if not predictable, are satisfying because the product foreshadows them in countless ways.

19. Your product should be a hierarchy.

Hierarchy is when the elements of the product gain attention in proportion to their importance. Closely related to the property of balance, hierarchy provides a means for establishing and evaluating balance. If the theme is the top of the hierarchy, elements at the next level have balanced value with respect to each other, all equally supporting the thematic function, and so on throughout the rest of the hierarchy.

20. Establish a shared vision.

It seems absurd to even have to state this, yet it is perhaps the most difficult thing of all to achieve. Everybody on the team must know what they are trying to achieve, what the finished product will look like, what the basis of the product strategy is, and when they must deliver it in order for it to have its intended effect. Contradictory visions must be resolved and unified. Harmonious purpose must be achieved, or greatness is out of the question and even shipping becomes infinitely more complicated.

Shipping

21. Get the team into ship mode.

There is a moment on every development project when it is ideal for a team to enter ship-mode. Ship mode is a high performance period characterized by efficiency and determination. It is a period of flow. Before a team can enter ship mode, several pre-requisites must be satisfied.

1. Shipment must be the next milestone.

2. Everybody (or nearly everybody) must believe that achieving the milestone is possible.

3. All members of the team must understand precisely what they must do prior to shipping. All unknowns are factored out.

4. Management must lead the team to ship mode by entering ship mode first. That is, superfluous management hoo-ha is eliminated, the manager's awareness of detail climbs, fire-drills and other de-prioritizing activities are eliminated entirely and tremendous focus is brought to bear.

5. The team must desire to ship. Generally, a complete awareness of the effect of shipping (or not shipping) will create desire.

The team becomes especially vigilant about thinking things through, and looking for traps. Check-ins are made with extra precaution. Stabilization of the product is the principle goal. All development is complete but for bug fixing.

The endgame, the last stage of shipmode, is different yet again. It is conceptually a very simple exercise. There is a list of activities. When every activity on the list is complete, you ship. Though the list might have hundreds or thousands of items, it is still just a list. There is no time for any effort that does not contribute toward completing the items on the list. Everybody is expected to complete their items as promised. As unanticipated items arise, after appropriate resistance, they are put on the list.

A daily meeting should be established, with final decision-makers in attendance. Agenda is ad hoc, assembled at the beginning of each meeting. No item is postponed that can be handled now. The team is aware that all issues can be brought to this meeting for expeditious remedy. Management is involved, leading the team toward their goal.

The goal is an acceptable quality level at ship time. Only showstopper bugs should be addressed at all. Showstoppers are bugs that will either effect more than a handful of users or will cause unacceptably serious errors. Cosmetic changes, performance enhancements, new functions are not appropriate changes. The purpose of beta feedback during this period is to prove there are no showstoppers, provide advance warning of unanticipated market reaction and provide input to the next release.

Understand the range of quality that is acceptable to your customers. How many low priority bugs did your product ship with last time? Was it a problem? Are the customers better off with this product including this bug? Since destabilizing the software is more of a problem than most bugs, be very careful about which bugs you fix. This is why we have "ReadMe's" and bug lists.

Shipmode is basically a succession of daily milestones climaxing with the product's shipment.

Many thanks to the staff and management of the Visual C++ Business Unit at Microsoft, from whom I learned and plagiarized these ideas.

 

top

codefool codefool writes  |  more than 9 years ago There really is a deep need for a sleep() function in javascript. That is, a function that suspends the current thread so that some other thread(s) can complete processing. Currently, however, Javascript does not have a sleep function, but one can be simulated using window.setTimeout, but its not as simple as an embedded sleep() call would be.

The short: there is no way to pause the current thread. It must run until it ends, returning control to the browser. It is possible, however, to simulate pausing by performing a juggling act with setTimeout(), as follows:

var thread2sleepLatch = false;

function thread_2()
{
...
thread2sleepLatch = false; // say thread 2 is done
} // end of function!!!

function thread_1()
{
...
thread2sleepLatch = true; // say thread 2 is busy
setTimeout( "thread_2()", 10 ); // fork thread 2
setTimeout( "wait_thread_2()", 10 ); // juggle until thread 2 is done
} // exit!

function wait_thread_2()
{
if( thread2sleepLatch )
{
setTimeout( "wait_thread_2()", 10 ); // wait some more
return; // terminate this thread!
}
// get here if thread2 is done
// perform post-thread2 processing
...
}

After each iteration, control is returned to the browser for 10ms, which allows the other threads to run. Note that we set thread2sleepLatch true before running the actual thread to avoid a race condition between the two threads. This is also a problem, since if thread2 never starts, then wait_thread_2 will never terminate. Hence, I reiterate my request for a sleep() function in javascript.

top

codefool codefool writes  |  more than 10 years ago Update: Mandrake 10.0 Installs clean on a VAIO without any modifications at all. Next project: build the kernel from scratch.

So I've decided that I've been out of the Linux game long enough. Sure, I earn my bread on Windows, but its time to break out of the box, as it were, and figure out what this Linux thing is all about. I mean, if half of the capatilst world is trying to destroy it, then there must be something to it.

I decided I wanted to put Linux on my laptop. But since I do a lot of Windoze contract work, I needed to keep my installation of Win2K. Getting this to work was quite a lot of fun, and here's the brunt of it.

First I googled to find the 2000 sources of how to do this, but as each Linux is 'special' in its own way, there was tons of information to go through. I decided upon Mandrake Linux 9.2 because I had toyed with it before, and it seems pretty simple to set up. On thing everyone agreed on was that Linux needs its bootloader to be within the first 1024 cyls of the disk, which usuallly isn't a problem, but its something to look out for.

I used BootIT NG to partition the disk because, well, I already owned it and it does the job. The VAIO had a 20G HDD, so I split it up into:

  • 16MB EMBR for BootIT NG
  • 6150MB FAT-32 for Windows 2000
  • 6150MB Linux Native for Mandrake
  • 64??MB to share between the two.

My plan is to have all my source, development, etc. on the shared partition, which means I need to mount /home to that drive when I get Linux installed. Since I forgot this step, I have cleanup to do. Later.

First I installed Windows 2000 on H(0)P(2) with no problem. Although the Win2K bootloader sees H(0)P(3) as an 'Unknown operating system on C:', which makes no real sense. I edited the boot.ini to remove the reference to the other partition, and now BootIT NG can boot straight into Win2K. That's done.

The largest challenge of all was getting Linux installed. This is because, and only because, the Z505LSK does not have an integrated CDROM, but can boot from one via a PCMCIA card (which is, btw, a dongle off the CDROM drive). It seems that when the CDROM is booted, it appears to Linux as an ATAPI device, but once it figures out that a PCMCIA card exists, it moves it to the PC Card bus, which FUBARS the install. So you have to do a little magic. Namely, press F1 to enter in boot options, and then type this little piece of magic:

linux ide2=0x180,0x386 noauto

Which, I assume, tells the installer where it can find the CDROM drive, and not to try and move it. Once this peice of arcane knowledge was finally discovered, the install went very smoothly. Funny, if I google 'ide2=0x180' I get tons of hits - the info is out there, people, you just need the right keywords.

So everything is just peachy at the moment. Except, I have to go and change the mounts to that /home is on the share partition. I thought it pretty cool that either Samba or Samba-like functionality is already in Mandrake - it seems my DOS drivers are mounted as /mnt/win-c and /mnt/win-d which makes my life very easy at this point.

So I'm off to learn the world of Linux. If I didn't make so much money off of the M$ monopoly, I would dump Windoze completeley and go with Linux full-time just because its so cool.

Thanks to all the Linux people out there for giving us such a tool to work with.

top

codefool codefool writes  |  more than 10 years ago I've made the decision that I'm going back to school for an entrepreneurship degree. Since I never graduated in the first place, this is prob. good for me. The bad is that I'm 43 and by the time I graduate I'll be 48.

The reason for all this is that I was laid off a couple of years back in the wake of the dot-bomb collapse. It took me a full 18 months to find another job, that pays much less than I was making 10 years prior. Its not that I'm unemployable - its just that there were no jobs. There still are no jobs. In fact, the IT market is continuing to tank. A labor report published a couple months back says that by 2010 we'll hava 250K fewer jobs than we have now - after the bust. That means that not only will most of the jobs lost during the bust not be coming back, but we'll lose an additional 250K besides. This means that the IT industry as a whole will not rebound for another 15 years. I can't wait that long to find a better job.

But, I have 22 years in this business - seems a shame to waste it. So rather than change careers alltogether, I'm going to change paradigm. I'm going to get a business degree, and use my IT knowledge to either start my own company or go run somebody else's.

exit ubergeek - enter CEO/CIO/CTO with ubergeek overtones.

And that's the plan.

top

codefool codefool writes  |  more than 10 years ago <!--
    Skeletal framework for implementing a multiple column list
    box with 'standard' windows selection behavior using
    javascript for dhtml.

    Comments are sadly lacking - more to come.

    Use as you see fit, check back here for updates as I have time.
-->
//
//  manage a DHTML scrollable list
//
function scrollList_Column( owner, colId, index )
{
    this._owner = owner;                                // the owning scrolllist
    this._index = index;
    this._id    = colId;                                // our 'unique' id
}

scrollList_Column.prototype.getId =
    function()
    {
        return this._id;
    };

scrollList_Column.prototype.setWidth    = function( sWidth ) { this._width     = sWidth; return this; }
scrollList_Column.prototype.setStyle    = function( sStyle ) { this._style     = sStyle; return this; }
scrollList_Column.prototype.setClass    = function( sClass ) { this._class     = sClass; return this; }
scrollList_Column.prototype.setPrec     = function( sPrec  ) { this._prec      = sPrec;  return this; }
scrollList_Column.prototype.setAlign    = function( sAlign ) { this._textAlign = sAlign; return this; }
scrollList_Column.prototype.setXmlTag   = function( sTag   ) { this._xmlTag    = sTag;   return this; }
scrollList_Column.prototype.setHeading  = function( sHead  ) { this._heading   = sHead;  return this; }

scrollList_Column.prototype.getHeading =
    function()
    {
        var sRet = "[Unnamed Column]";
        if( this.hasOwnProperty( "_heading" ) )
            sRet = this._heading;
        else if( this.hasOwnProperty( "_id" ) )
            sRet = this._id;
        return sRet;
    };

//
//  create a <TD> element with this column attributes and properties
//
scrollList_Column.prototype.createElement =
    function( sData )
    {
        var oColumn = document.createElement( "TD" );
        oColumn.id = this._id;
        if( this.hasOwnProperty( "_width" ) )       oColumn.style.width     = this._width;
        if( this.hasOwnProperty( "_class" ) )       oColumn.className       = this._class;
        if( this.hasOwnProperty( "_style" ) )       oColumn.styleString     = this._style;
        if( this.hasOwnProperty( "_textAlign" ) )   oColumn.style.textAlign = this._textAlign;
        if( null != sData )
        {
            var oTextNode = document.createTextNode( sData );
            oColumn.appendChild( oTextNode );
        }
        return oColumn;
    };

scrollList_Column.prototype.format =
    function( sVal )
    {
        if( this.hasOwnProperty( "_prec" ) )
            sVal = Number( sVal ).toFixed( this._prec );
        return sVal;
    };

////////////////////////////////////////////////////////////////////////////////
//
//  S T A T I C   F U N C T I O N S
//
////////////////////////////////////////////////////////////////////////////////
function scrollList_onRowClick()
{
    var e = window.event.srcElement;
    while( null != e && e.tagName != "TR" )
        e = e.parentNode;

    if( null != e && null != e._scrollList )
    {
        e._scrollList.hilite( e );
    }
}

function scrollList_onRowDblClick()
{
    //
    //  the only reason to go through this is if there is someone to send
    //  the info to, since we do nothing with double clicks.
    //
    var e = window.event.srcElement;
    while( null != e && e.tagName != "TR" )
        e = e.parentNode;

    if( null != e && null != e._scrollList && null != e._scrollList._extRowDblClickHandler )
    {
        e._scrollList._extRowDblClickHandler( e.rowIndex );
    }
}

//
//  onSelectStart
//
//  This function is used to negate select start events on our owning table. This is so mouse
//  navigation works without having the browswer block-select text for us.
//
//  This function answers false. That's all it does. Just walk away.
//
function scrollList_onSelectStart()
{
    return false;
}

function scrollList_onKeyDown()
{
    var bRet = false;
    var e    = window.event.srcElement;

    while( e != null && e.tagName != "TABLE" )
        e = e.parentElement;

    if( null != e && null != e._scrollList && null != e._scrollList._curRow )
    {
        var list = e._scrollList;
        var ek   = event.keyCode;
        if( !event.shiftKey )
        {
            list._hiliteAnchor = null;
        }

        bRet = true;
        switch( ek )
        {
            case 0x26:  // cursor up    (VK_UP)
                if( null != list._curRow.previousSibling )
                    list.hilite( list._curRow.previousSibling );
                break;

            case 0x28:  // cursor down  (VK_DOWN)
                if( null != list._curRow.nextSibling )
                    list.hilite( list._curRow.nextSibling );
                break;

            case 0x20:  // space        (VK_SPACE)
                //  toggle the entry's selection status.
                {
                var bSelected          = !list._curRow._selected;
                list._curRow._selected = bSelected;
                list._curRow.className = list.getRowStyle( list._curRow );
                list._rowsSelected     = bSelected;
                }
                break;

            case 0x2d:    // insert       (VK_INSERT)
                if( null != list._extInsertRowHandler )
                    list._extInsertRowHandler();
                break;

            case 0x2e:  // delete       (VK_DELETE)
                list.removeSelectedRows();
                break;

            case 0x21:  // page up      (VK_PRIOR)
            case 0x22:  // page down    (VK_NEXT)
                if( list._viewDepth != -1 )
                {
                    var scrollValue = list._viewDepth - 1;
                    if( ek == 0x21 )
                        scrollValue = -scrollValue;

                    var rowIdx = list._curRow.rowIndex + scrollValue;

                    if( rowIdx >= list.rowCount() )
                        rowIdx = list.rowCount() - 1;

                    else if( rowIdx < 0 )
                        rowIdx = 0;

                    list.hilite( list.getRow( rowIdx ) );
                }
                else
                    bRet = false;
                break;

            case 0x24:  // home         (VK_HOME)
                list.hilite( list.getRow( 0 ) );
                break;

            case 0x23:  // end          (VK_END)
                list.hilite( list.getRow( list.rowCount() - 1 ) );
                break;

            default:
                bRet = false;
                break;
        }
        //
        //  if we usurped our table's onKeyDown proc, then call it here
        //
        if( null != list._tableOnKeyDown )
            bRet = list._tableOnKeyDown();
    }

    return bRet;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//  class scrollList
//
//  The actual row data is stored in the HTML document itself - the scroll
//  list only contains information necessary to manage that piece of the
//  document which must be totally eveloped by a single element, such as
//  a <div> or <tbody>.
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
function scrollList( elemId )
{
    this._elem                  = elemId;           // the DHTML element where we live
    this._styleClass            = new Object();     // container for css style classes
    this._cols                  = new Object();     // container for column descriptions
    this._colCnt                = 0;
    this._curRow                = null;             // there is no current row
    this._hiliteAnchor          = null;
    this._rowsSelected          = null;
    this._viewTop               = 0;                // first visible row in the view
    this._viewDepth             = -1;               // show everything
    this._emptyMessage          = "[List is empty]";
    this._extRemoveRowHandler   = null;
    this._extEndRemoveHandler   = null;
    this._extRowSelectHandler   = null;
    this._extRowDblClickHandler = null;

    //
    //  locate our containing <TABLE> element and setup some magic
    //
    var e = elemId;
    while( null != e && e.tagName != "TABLE" )
        e = e.parentElement;
    if( null != e )
    {
        this._table          = e;                           // save our table reference
        this._tableOnKeyDown = e.onkeydown;                 // save our table's onKeyDown handler
        e._scrollList        = this;                        // point our table to us
        e.onkeydown          = scrollList_onKeyDown;      // substitute our own handler
          e.onselectstart      = scrollList_onSelectStart;  // nullify mouse select events
    }
}
scrollList.prototype.DEFAULT_CLASS_STYLE_ID = "__default__";
scrollList.prototype.EMPTY_ROW_ID           = "__emptyrow__";

//
//  Associate an external handler for the insert row event.
//
//  This handler is called whenever a the user presses the 'insert' key on the scoll list.
//  The list itself does nothing, but will evoke this handler if it is defined. The handler
//  is expected to manipulate the to physically insert and populate the row where desired.
//
//  The handler accepts no arguments, and answers nothing.
//
scrollList.prototype.setInsertRowHandler =
    function( h )
    {
        this._extInsertRowHandler  = h;
    };

//
//  Associate an external handler for the end remove event.
//
//  This handler is called whenever a remove operation is completed (and something was
//  actually removed). This gives the owning document an opportunity to adjust from
//  the rows removed.
//
//  The handler accepts no arguments, and answers nothing.
//
scrollList.prototype.setEndRemoveHandler =
    function( h )
    {
        this._extEndRemoveHandler  = h;
    };

//
//  associate an external handler for the remove row event.
//
//  The handler accepts a single argument which is the row index of the row being
//  removed. The handler can get additional information about the targetted row
//  by supplying this index to scrollList.getRow().
//
//  The handler MUST answer true if the row may be removed, false otherwise.
//
scrollList.prototype.setRemoveRowHandler =
    function( h )
    {
        this._extRemoveRowHandler = h;
    };

//
//  Associate an external handler for when a row is selected. This handler is
//  called whenever a new row is selected either by the keyboard or mouse.
//
//  The handler accepts a single argument which is the row index of the row
//  selected. The handler can get additional information about the target row
//  by supplying this index to scrollList.getRow();
//
scrollList.prototype.setRowSelectHandler =
    function( h )
    {
        this._extRowSelectHandler = h;
    };

//
//  associate an external handler for when a user double-clicks a row.
//
//  The handler accepts a single argument which is the row index of the row being
//  double-clicked. The handler can get additional information about the target row
//  by supplying this index to scrollList.getRow();
//
scrollList.prototype.setRowDblClickHandler =
    function( h )
    {
        this._extRowDblClickHandler = h;
    };

scrollList.prototype.setViewDepth =
    function( iSize )
    {
        iSize += 0;
        if( 0 < iSize )
            ; // throw - BAD PARAMETER
        this._viewDepth = iSize;
        return this;
    };

scrollList.prototype.getViewDepth =
    function()
    {
        return this._viewDepth;
    };

//
//  for scrollable lists, scroll the named index into view. Optionaly specify
//  whether it should be scrolled to the center of the view. Otherwise, the
//  row is scrolled to either the first or last item, depending on whether
//  the target row is above or below the view.
//
scrollList.prototype.scrollIntoView =
    function( row, bCenter )
    {
        bCenter = !!bCenter;        // assure boolean

        row = this.getRow( row );

        if( null != row  )
        {
            var trueViewDepth = this._viewDepth - 1;
            var viewBottom    = this._viewTop + trueViewDepth;
            var newTopRow     = -1;
            if( bCenter )
            {
                var centerOffset = trueViewDepth / 2;

                if( row.rowIndex >= centerOffset )
                    newTopRow = row.rowIndex - centerOffset;
                //  else, the row can't be centered cuz there's not enough rows to
                //  fill the view.
            }
            // if the row is below the bottom of the view
            else if( viewBottom < row.rowIndex )
            {
                newTopRow = row.rowIndex - trueViewDepth;
            }
            // if the row is above the top of the view
            else if( row.rowIndex < this._viewTop )
            {
                newTopRow = row.rowIndex;
            }
            //  else the row is already visible

            if( newTopRow != -1 )
            {
                this._viewTop = newTopRow;
                this.paint();
            }
        }
        //else
        //  throw - index out of range
    };

scrollList.prototype.hilite =
    function( e, force )
    {
        force = !!force;
        //
        //  determine if its the row element, or a child TD element that originated
        //  the event
        //
        while( null != e && "TR" != e.tagName.toUpperCase() )
            e = e.parentElement;

        if( null != e && ( e != this._curRow || force ) )
        {
            //
            //  handle keyboard augments
            //
            if( null != event )
            {
                if( !event.shiftKey )
                {
                    this._hiliteAnchor = null;
                    if( !event.ctrlKey )
                        this.unselectAll();
                }
                else if( event.shiftKey && null == this._hiliteAnchor )
                    this._hiliteAnchor = this._curRow;
            }

            //
            //  first, un-hilite the currently hilited row, if there is one
            //
            var priorRow = this._curRow;
            this._curRow = e;
            if( null != priorRow )
                priorRow.className = this.getRowStyle( priorRow );

            //
            //  see if we have an anchor set by a prev shift operation
            //
            if( null != this._hiliteAnchor )
            {
                //
                //  we need to  hilite every node from hiliteAnchor to the current node
                //
                this.unselectAll();

                var lo = ( this._hiliteAnchor.rowIndex < this._curRow.rowIndex )
                       ? this._hiliteAnchor
                       : this._curRow;

                var hi = ( lo == this._hiliteAnchor )
                       ? this._curRow
                       : this._hiliteAnchor;

                for( e = lo; e != hi.nextSibling; e = e.nextSibling )
                {
                    e._selected        = true;
                    e.className        = this.getRowStyle( e );
                    this._rowsSelected = true;
                }
            }
            this._curRow.className = this.getRowStyle( this._curRow );

            //  now make sure the current row is visible
            this.scrollIntoView( this._curRow, false );

            if( null != this._extRowSelectHandler )
                this._extRowSelectHandler( this._curRow.rowIndex );
        }
    };

scrollList.prototype.unselectAll =
    function()
    {
        for( var e = this._elem.firstChild; e != null; e = e.nextSibling )
        {
            e._selected = false;
            e.className = this.getRowStyle( e );
        }
        this._rowsSelected = false;
    };

scrollList.prototype.rowCount =
    function()
    {
        var iRet = 0;
        if( !this.isEmpty() )
            iRet = this._elem.rows.length;
        return iRet;
    };

scrollList.prototype.columnCount =
    function()
    {
        return this._colCnt;
    };

//
//  remove selected rows
//
scrollList.prototype.removeSelectedRows =
    function()
    {
        //
        //  if there are no selected rows, then the current row
        //  is dead meat ...
        //
        if( !this._rowsSelected )
        {
            if( null == this._curRow )
                this._curRow = this._elem.rows[ 0 ];
            this._curRow._selected = true;
        }

        var e                 = this._elem.rows[ this._elem.rows.length - 1 ];
        var bSomethingRemoved = false;
        while( e != null )
        {
            var ePrev = e.previousSibling;
            if( e._selected )
            {
                var bRemove = true;
                //
                //  see if our owner wants to be notified that
                //  we're about to remove a row...
                //
                if( null != this._extRemoveRowHandler )
                    bRemove = this._extRemoveRowHandler( e.rowIndex );

                if( bRemove )
                {
                    this.removeRow( e );
                    bSomethingRemoved = true;
                }
            }
            e = ePrev;
        }

        //
        //  see if our owner wants to know that we're done removing stuff
        //
        if( bSomethingRemoved && null != this._extEndRemoveHandler )
            this._extEndRemoveHandler();

        this.paint();
    };

scrollList.prototype.removeRow =
    function( oRow )
    {
        if( oRow === this._curRow )
        {
            this._curRow = ( this._curRow.nextSibling != null )
                         ? this._curRow.nextSibling
                         : this._curRow.previousSibling;
        }
        this._elem.removeChild( oRow );
        this.createEmptyRow();
    };

//
//  addColumn
//
//  Creates a new column object with the given id (provided it doesn't already exist),
//  and sets its parent and index.
//
//  Answer the column created, or null if something goes wrong.
//
scrollList.prototype.addColumn =
    function( colId )
    {
        var newCol = this._cols[ colId ];
        if( null == newCol )
        {
            newCol = new scrollList_Column( this, colId, this._colCnt++ );
            this._cols[ colId ] = newCol;
        }
        return newCol;
    };

scrollList.prototype.createColumnDataObject =
    function()
    {
        var oRet = new Array();
        for( var idx = 0; idx < this._colCnt; idx++ )
            oRet[ idx ] = "";
        return oRet;
    };

//
//  creates a state-oriented style. Essentially, there are four basic styles:
//  'normal'   - row is not the current row, and is not selected
//  'hilite'   - row is the current row, but is not selected
//  'select'   - row is selected, but not the current row
//  'selecthi' - row is selected and is the current row
//
//  This breaks down into a 2x2 matrix like so:
//
//              | not selected | selected |
//  ------------+--------------+----------+
//  not current |  normal      | select   |
//  ------------+--------------+----------+
//  current row |  hilite      | selecthi |
//  ------------+--------------+----------+
//
//  So the style strings are stored as an array of [false,true]
//
//
scrollList.prototype.setStyleClass =
    function( sState, sNormal, sNormalHilite, sSelect, sSelectHilite )
    {
        //
        //  first, make sure we have four styles to choose from.
        //  sNormal is required, but the others are not
        //
        if( null != sNormal && sNormal != "" )
        {
            this._styleClass[ sState ]                   = new Array();
            this._styleClass[ sState ][ false ]          = new Array();
            this._styleClass[ sState ][ false ][ false ] = sNormal;
            this._styleClass[ sState ][ false ][ true  ] = sNormalHilite;
            this._styleClass[ sState ][ true  ]          = new Array();
            this._styleClass[ sState ][ true  ][ false ] = sSelect;
            this._styleClass[ sState ][ true  ][ true  ] = sSelectHilite;
        }
    };

//  provide a shorthand for setting the default style class
scrollList.prototype.setDefaultClassStyle =
    function( sNormal, sNormalHilite, sSelect, sSelectHilite )
    {
        this.setStyleClass( this.DEFAULT_CLASS_STYLE_ID, sNormal, sNormalHilite, sSelect, sSelectHilite );
    };

scrollList.prototype.getStateClassStyle =
    function( sState, isCurrentRow, isSelected )
    {
        var sRet   = null;
        var oStyle = this._styleClass[ sState ];
        if( null != oStyle )
            sRet = oStyle[ !!isSelected ][ !!isCurrentRow ];

        //
        //  if the style isn't provided, try to use a 'default' style
        //
        if( null == sRet )
            sRet = this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, !!isCurrentRow, !!isSelected );

        //  if there still isn't any style, use the basic 'default' style
        if( null == sRet )
            sRet = this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, false, false );

        return sRet;
    };

scrollList.prototype.getDefaultNormalStyle       = function() { return this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, false, false ); };
scrollList.prototype.getDefaultNormalHiliteStyle = function() { return this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, false, true  ); };
scrollList.prototype.getDefaultSelectStyle       = function() { return this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, true,  false ); };
scrollList.prototype.getDefaultSelectHiliteStyle = function() { return this.getStateClassStyle( this.DEFAULT_CLASS_STYLE_ID, true , true  ); };

scrollList.prototype.getRowStyle =
    function( oRow )
    {
        var sRet = this.getDefaultNormalStyle();
        oRow = this.getRow( oRow );
        if( null != oRow )
            sRet = this.getStateClassStyle( this.getRowState( oRow ), (this._curRow == oRow ),  oRow._selected );
        return sRet;
    };

scrollList.prototype.paint =
    function()
    {
        //
        //  make only the rows between _viewTop and _viewTop + _viewDepth - 1 visible
        //
        var viewBottom;
        if( -1 == this._viewDepth )
            viewBottom = this.rowCount() - 1;
        else
        {
            viewBottom = this._viewTop + this._viewDepth;
            if( viewBottom > this.rowCount() )
                viewBottom = this.rowCount();
        }

        for( var idx = 0; idx < this.rowCount(); idx++ )
        {
            var thisRow = this._elem.rows[ idx ];
            thisRow.style.display = ( this._viewTop <= idx && idx < viewBottom )
                                  ? "inline"
                                  : "none";
        }

        this.hilite( this.getCurrentRow(), true );
    };

scrollList.prototype.setHeaderRow =
    function( tableElem )
    {
        var oTableRow = document.createElement( "TR" );
        for( var colName in this._cols )
        {
            var col = this._cols[ colName ];
            var oTableCol = document.createElement( "TD" );
            var oTextElem = document.createTextNode( col.getHeading() );
            oTableCol.appendChild( oTextElem );
            oTableRow.appendChild( oTableCol );
        }
        tableElem.appendChild( oTableRow );
    };

scrollList.prototype.addRow =
    function()
    {
        this.removeEmptyRow();

        var oTableRow = document.createElement( "TR" );
        oTableRow.style.display = "none";                       // create invisible
          oTableRow.onclick       = scrollList_onRowClick;
          oTableRow.ondblclick    = scrollList_onRowDblClick;
        oTableRow._scrollList   = this;
        oTableRow.csRowState    = this.DEFAULT_CLASS_STYLE_ID;

        this._elem.appendChild( oTableRow );
        return oTableRow;
    };

scrollList.prototype.createColumn =
    function( colIndex )
    {
        var oCol      = this.getColumn( colIndex );
        var oTableCol = oCol.createElement();
        oTableCol.setAttribute( "cellId", colIndex );
        return oTableCol;
    };

//
//  answer the TR element for the given row index.
//
//  rowIndex can be either the TR element or an index to the TR element.
//
scrollList.prototype.getRow =
    function( rowIndex )
    {
        var oRow = null;

        //
        //  first see if we were passed a reference to an Element
        //  object that happens to be a TR object.
        //
        if( typeof rowIndex == "object" && rowIndex.tagName == "TR" )
            oRow = rowIndex;

        //
        //  If rowIndex is -1, then answer the "current row". If there is no
        //  current row, answer the first row.
        //
        else if( -1 == rowIndex )
        {
            if( null == this._curRow )
                this._curRow = this._elem.rows[ 0 ];
            oRow = this._curRow;
        }

        //
        //  else, if the index is sane, answer the row object for that index
        //
        else if( 0 <= rowIndex && rowIndex < this.rowCount() )
            oRow = this._elem.rows[ rowIndex ];
        return oRow;
    };

scrollList.prototype.getRowColumn =
    function( oRow, colIndex )
    {
        var oCol = null;
        if( null != this._cols[ colIndex ] )            // in case colIndex is a column name
            colIndex = this._cols[ colIndex ]._index;

        if( 0 <= colIndex && colIndex < this._colCnt )
        {
            oRow = this.getRow( oRow );

            var thisCol = null;
            if( null != oRow )
            {
                // this is not as simple as just getting the element from the row's cell collection
                // because its possible that the cells are being created out of order. So we have to
                // loop through the cell entries, looking for a cellid property of the desired index.
                // if the index is not found, it is created and inserted into the appropriate spot
                //
                //  however, to possibly save us some work, just peek to see if the cell we want
                //  is in the right place already...
                //
                if( colIndex < oRow.cells.length && oRow.cells[ colIndex ].getAttribute( "cellId" ) == colIndex )
                    oCol = oRow.cells[ colIndex ];

                else
                {
                    for( var iColIdx = 0; iColIdx < oRow.cells.length; iColIdx++ )
                    {
                        thisCol = oRow.cells[ iColIdx ];
                        var cellId = thisCol.getAttribute( "cellId" );
                        if( cellId == colIndex )
                        {
                            oCol = thisCol;
                            break;
                        }
                        else if( cellId > colIndex )
                            // this is our insertion point
                            break;
                        thisCol = null;
                    }

                    if( null == oCol )
                    {
                        //  didn't find the column - so create it
                        oCol = this.createColumn( colIndex );
                        if( null == thisCol )
                            //  this is the first cell in the row
                            oRow.appendChild( oCol );
                        else
                            oRow.insertBefore( oCol, thisCol );
                    }
                }
            }
        }
        return oCol;
    };

scrollList.prototype.setColData =
    function( row, colIndex, vColData )
    {
        var oCol    = this.getColumn( colIndex );
        var oNewCol = this.getRowColumn( row, colIndex );
        if( null != oNewCol )
            oNewCol.innerHTML = oCol.format( vColData );
    };

scrollList.prototype.getColumnData =
    function( row, colIndex )
    {
        var oCol = this.getRowColumn( row, colIndex );
        return oCol.innerHTML;
    };

scrollList.prototype.clear =
    function()
    {
        while( this._elem.hasChildNodes() )
            this._elem.removeChild( this._elem.firstChild );
        this._curRow = null;
        this.createEmptyRow();
    };

//
//  creates a new row from the supplied XML documnt fragment. For this to work,
//  the xmlTag properties of each row must have been supplied prior to calling
//  this method.
//
//  answers the row created
//
scrollList.prototype.createRowFromXML =
    function( oXmlDoc )
    {
        var oRow = this.addRow();
        if( null != oRow )
        {
            for( var colIdx = 0; colIdx < this.columnCount(); colIdx++ )
            {
                var oCol    = this.getColumn( colIdx );
                var sColVal = "";
                if( null != oCol._xmlTag )
                {
                    var oNode = oXmlDoc.selectSingleNode( ".//" + oCol._xmlTag );
                    if( null != oNode )
                        sColVal = oNode.text;
                }
                this.setColData( oRow, colIdx, sColVal );
            }
        }
        return oRow;
    };

scrollList.prototype.getColumn =
    function( colIndex )
    {
        var oRet = this._cols[ colIndex ];
        if( null == oRet )
        {
            for( var colName in this._cols )
            {
                if( this._cols[ colName ]._index == colIndex )
                {
                    oRet = this._cols[ colName ];
                    break;
                }
            }
        }
        return oRet;
    };

scrollList.prototype.swapRows =
    function( row1, row2 )
    {
        if( typeof row1 == "number" )
            row1 = this.getRow( row1 );

        if( typeof row2 == "number" )
            row2 = this.getRow( row2 );

        if( null != row1 && null != row2 )
        {
            row1.swapNode( row2 );
        }
    };

scrollList.prototype.moveRowUp =
    function( row )
    {
        if( typeof row == "number" )
            row = this.getRow( row );
        if( null != row )
            this.swapRows( row, row.previousSibling );
    };

scrollList.prototype.moveRowDown =
    function( row )
    {
        if( typeof row == "number" )
            row = this.getRow( row );
        if( null != row )
            this.swapRows( row, row.previousSibling );
    };

//
//  answers the row element for the currently hilited row
//
scrollList.prototype.getCurrentRow =
    function()
    {
        return this.getRow( -1 );
    }

scrollList.prototype.setCurrentRow =
    function( row )
    {
        row = this.getRow( row );
        if( row != null )
        {
            this.hilite( row );
        }
    };

//
//  sets the state value of a row. This is set as an attribute to the
//  row element as csRowState
//
scrollList.prototype.setRowState =
    function( row, state )
    {
        row = this.getRow( row );
        if( null != row )
            row.csRowState = state;
    };

//
//  answers the state value of a rows, or empty string if none exist
//
scrollList.prototype.getRowState =
    function( row )
    {
        var sRet = "";
        row = this.getRow( row );
        if( null != row && null != row.csRowState )
            sRet = row.csRowState;
        return sRet;
    };

//
//  answers the selected state for a given row
//
scrollList.prototype.isSelected =
    function( row )
    {
        var bRet = false;
        row = this.getRow( row );
        if( null != row )
            bRet = row._selected;
        return bRet;
    };

//
//  answers the CSS class for the given row based on its
//  csRowState and _selected values.
//
scrollList.prototype.getRowStateClass =
    function( row )
    {
        var sClass = "";
        row = this.getRow( row );
        if( null != row )
        {
            var sState = this.getRowState( row );
        }
        return sClass;
    };

//
//  specifies the string to display when the list is empty
//
scrollList.prototype.setEmptyMessage =
    function( sMessage )
    {
        this._emptyMessage = sMessage;
    };

//
//  answer true if the list is currently empty. The list is
//  empty if the only item in the list is the 'special' empty item
//  (which contains the mesage that the list is empty ;-)
//
scrollList.prototype.isEmpty =
    function()
    {
        return ( null != this._elem && this._elem.rows.length == 1 && this._elem.rows[ 0 ].id == this.EMPTY_ROW_ID );
    };

scrollList.prototype.createEmptyRow =
    function()
    {
        if( this._elem.rows.length == 0 )
        {
            var oText      = document.createTextNode( this._emptyMessage );
            var oCol       = document.createElement( "TD" );
            var oRow       = document.createElement( "TR" );
            oCol.colSpan   = this._colCnt;
            oRow.id        = this.EMPTY_ROW_ID;
            oRow.className = this.getDefaultNormalStyle();

            oCol.appendChild( oText );
            oRow.appendChild( oCol );
            this._elem.appendChild( oRow );
        }
    };

scrollList.prototype.removeEmptyRow =
    function()
    {
        if( this.isEmpty() )
        {
            this._elem.removeChild( this._elem.firstChild );
        }
    };   

top

codefool codefool writes  |  more than 10 years ago A Clean, Well-Lighted Place
© by Ernest Hemingway

It was very late and everyone had left the cafe except an old man who sat in the shadow the leaves of the tree made against the electric light. In the day time the street was dusty, but at night the dew settled the dust and the old man liked to sit late because he was deaf and now at night it was quiet and he felt the difference. The two waiters inside the cafe knew that the old man was a little drunk, and while he was a good client they knew that if he became too drunk he would leave without paying, so they kept watch on him.

"Last week he tried to commit suicide," one waiter said.

"Why?"

"He was in despair."

"What about?"

"Nothing."

"How do you know it was nothing?"

"He has plenty of money."

They sat together at a table that was close against the wall near the door of the cafe and looked at the terrace where the tables were all empty except where the old man sat in the shadow of the leaves of the tree that moved slightly in the wind. A girl and a soldier went by in the street. The street light shone on the brass number on his collar. The girl wore no head covering and hurried beside him.

"The guard will pick him up," one waiter said.

"What does it matter if he gets what he's after?"

"He had better get off the street now. The guard will get him. They went by five minutes ago."

The old man sitting in the shadow rapped on his saucer with his glass. The younger waiter went over to him.

"What do you want?"

The old man looked at him. "Another brandy," he said.

"You'll be drunk," the waiter said. The old man looked at him. The waiter went away.

"He'll stay all night," he said to his colleague. "I'm sleepy now. I never get into bed before three o'clock. He should have killed himself last week."

The waiter took the brandy bottle and another saucer from the counter inside the cafe and marched out to the old man's table. He put down the saucer and poured the glass full of brandy.

"You should have killed yourself last week," he said to the deaf man. The old man motioned with his finger. "A little more," he said. The waiter poured on into the glass so that the brandy slopped over and ran down the stem into the top saucer of the pile. "Thank you," the old man said. The waiter took the bottle back inside the cafe. He sat down at the table with his colleague again.

"He's drunk now," he said.

"He's drunk every night."

"What did he want to kill himself for?"

"How should I know."

"How did he do it?"

"He hung himself with a rope."

"Who cut him down?"

"His niece."

"Why did they do it?"

"Fear for his soul."

"How much money has he got?"

"He's got plenty."

"He must be eighty years old."

"Anyway I should say he was eighty."

"I wish he would go home. I never get to bed before three o'clock. What kind of hour is that to go to bed?"

"He stays up because he likes it."

"He's lonely. I'm not lonely. I have a wife waiting in bed for me."

"He had a wife once too."

"A wife would be no good to him now."

"You can't tell. He might be better with a wife."

"His niece looks after him. You said she cut him down."

"I know." "I wouldn't want to be that old. An old man is a nasty thing."

"Not always. This old man is clean. He drinks without spilling. Even now, drunk. Look at him."

"I don't want to look at him. I wish he would go home. He has no regard for those who must work."

The old man looked from his glass across the square, then over at the waiters.

"Another brandy," he said, pointing to his glass. The waiter who was in a hurry came over.

"Finished," he said, speaking with that omission of syntax stupid people employ when talking to drunken people or foreigners. "No more tonight. Close now."

"Another," said the old man.

"No. Finished." The waiter wiped the edge of the table with a towel and shook his head.

The old man stood up, slowly counted the saucers, took a leather coin purse from his pocket and paid for the drinks, leaving half a peseta tip. The waiter watched him go down the street, a very old man walking unsteadily but with dignity.

"Why didn't you let him stay and drink?" the unhurried waiter asked. They were putting up the shutters. "It is not half-past two."

"I want to go home to bed."

"What is an hour?"

"More to me than to him."

"An hour is the same."

"You talk like an old man yourself. He can buy a bottle and drink at home."

"It's not the same."

"No, it is not," agreed the waiter with a wife. He did not wish to be unjust. He was only in a hurry.

"And you? You have no fear of going home before your usual hour?"

"Are you trying to insult me?"

"No, hombre, only to make a joke."

"No," the waiter who was in a hurry said, rising from pulling down the metal shutters. "I have confidence. I am all confidence."

"You have youth, confidence, and a job," the older waiter said. "You have everything."

"And what do you lack?"

"Everything but work."

"You have everything I have."

"No. I have never had confidence and I am not young."

"Come on. Stop talking nonsense and lock up."

"I am of those who like to stay late at the cafe," the older waiter said.

"With all those who do not want to go to bed. With all those who need a light for the night."

"I want to go home and into bed."

"We are of two different kinds," the older waiter said. He was now dressed to go home. "It is not only a question of youth and confidence although those things are very beautiful. Each night I am reluctant to close up because there may be some one who needs the cafe."

"Hombre, there are bodegas open all night long."

"You do not understand. This is a clean and pleasant cafe. It is well lighted. The light is very good and also, now, there are shadows of the leaves."

"Good night," said the younger waiter.

"Good night," the other said. Turning off the electric light he continued the conversation with himself, It was the light of course but it is necessary that the place be clean and pleasant. You do not want music. Certainly you do not want music. Nor can you stand before a bar with dignity although that is all that is provided for these hours. What did he fear? It was not a fear or dread, It was a nothing that he knew too well. It was all a nothing and a man was a nothing too. It was only that and light was all it needed and a certain cleanness and order. Some lived in it and never felt it but he knew it all was nada y pues nada y nada y pues nada. Our nada who art in nada, nada be thy name thy kingdom nada thy will be nada in nada as it is in nada. Give us this nada our daily nada and nada us our nada as we nada our nadas and nada us not into nada but deliver us from nada; pues nada. Hail nothing full of nothing, nothing is with thee. He smiled and stood before a bar with a shining steam pressure coffee machine.

"What's yours?" asked the barman.

"Nada."

"Otro loco mas," said the barman and turned away.

"A little cup," said the waiter.

The barman poured it for him.

"The light is very bright and pleasant but the bar is unpolished," the waiter said.

The barman looked at him but did not answer. It was too late at night for conversation.

"You want another copita?" the barman asked.

"No, thank you," said the waiter and went out. He disliked bars and bodegas. A clean, well-lighted cafe was a very different thing. Now, without thinking further, he would go home to his room. He would lie in the bed and finally, with daylight, he would go to sleep. After all, he said to himself, it's probably only insomnia. Many must have it.

top

codefool codefool writes  |  more than 10 years ago They're Made Out Of Meat

by Terry Bisson

From "Bears Discover Fire and Other Stories," Copyright (C) 1994, Tor Books

"They're made out of meat."

"Meat?"

"Meat. They're made out of meat."

"Meat?"

"There's no doubt about it. We picked several from different parts of the planet, took them aboard our recon vessels, probed them all the way through. They're completely meat."

"That's impossible. What about the radio signals? The messages to the stars."

"They use the radio waves to talk, but the signals don't come from them. The signals come from machines."

"So who made the machines? That's who we want to contact."

"They made the machines. That's what I'm trying to tell you. Meat made the machines."

"That's ridiculous. How can meat make a machine? You're asking me to believe in sentient meat."

"I'm not asking you, I'm telling you. These creatures are the only sentient race in the sector and they're made out of meat."

"Maybe they're like the Orfolei. You know, a carbon-based intelligence that goes through a meat stage."

"Nope. They're born meat and they die meat. We studied them for several of their life spans, which didn't take too long. Do you have any idea the life span of meat?"

"Spare me. Okay, maybe they're only part meat. You know, like the Weddilei. A meat head with an electron plasma brain inside."

"Nope. We thought of that, since they do have meat heads like the Weddilei. But I told you, we probed them. They're meat all the way through."

"No brain?"

"Oh, there is a brain all right. It's just that the brain is made out of meat!"

"So... what does the thinking?"

"You're not understanding, are you? The brain does the thinking. The meat."

"Thinking meat! You're asking me to believe in thinking meat!"

"Yes, thinking meat! Conscious meat! Loving meat. Dreaming meat. The meat is the whole deal! Are you getting the picture?"

"Omigod. You're serious then. They're made out of meat."

"Finally, Yes. They are indeed made out meat. And they've been trying to get in touch with us for almost a hundred of their years."

"So what does the meat have in mind?"

"First it wants to talk to us. Then I imagine it wants to explore the universe, contact other sentients, swap ideas and information. The usual."

"We're supposed to talk to meat?"

"That's the idea. That's the message they're sending out by radio. 'Hello. Anyone out there? Anyone home?' That sort of thing."

"They actually do talk, then. They use words, ideas, concepts?"

"Oh, yes. Except they do it with meat."

"I thought you just told me they used radio."

"They do, but what do you think is on the radio? Meat sounds. You know how when you slap or flap meat it makes a noise? They talk by flapping their meat at each other. They can even sing by squirting air through their meat."

"Omigod. Singing meat. This is altogether too much. So what do you advise?"

"Officially or unofficially?"

"Both."

"Officially, we are required to contact, welcome, and log in any and all sentient races or multi-beings in the quadrant, without prejudice, fear, or favor. Unofficially, I advise that we erase the records and forget the whole thing."

"I was hoping you would say that."

"It seems harsh, but there is a limit. Do we really want to make contact with meat?"

"I agree one hundred percent. What's there to say?" `Hello, meat. How's it going?' But will this work? How many planets are we dealing with here?"

"Just one. They can travel to other planets in special meat containers, but they can't live on them. And being meat, they only travel through C space. Which limits them to the speed of light and makes the possibility of their ever making contact pretty slim. Infinitesimal, in fact."

"So we just pretend there's no one home in the universe."

"That's it."

"Cruel. But you said it yourself, who wants to meet meat? And the ones who have been aboard our vessels, the ones you have probed? You're sure they won't remember?"

"They'll be considered crackpots if they do. We went into their heads and smoothed out their meat so that we're just a dream to them."

"A dream to meat! How strangely appropriate, that we should be meat's dream."

"And we can mark this sector unoccupied."

"Good. Agreed, officially and unofficially. Case closed. Any others? Anyone interesting on that side of the galaxy?"

"Yes, a rather shy but sweet hydrogen core cluster intelligence in a class nine star in G445 zone. Was in contact two galactic rotations ago, wants to be friendly again."

"They always come around."

"And why not? Imagine how unbearably, how unutterably cold the universe would be if one were all alone."

top

codefool codefool writes  |  more than 10 years ago The Ransom of Red Chief

by O. Henry

It looked like a good thing: but wait till I tell you. We were down South, in Alabama--Bill Driscoll and myself-when this kidnapping idea struck us. It was, as Bill afterward expressed it, 'during a moment of temporary mental apparition'; but we didn't find that out till later.

There was a town down there, as flat as a flannel-cake, and called Summit, of course. It contained inhabitants of as undeleterious and self-satisfied a class of peasantry as ever clustered around a Maypole.

Bill and me had a joint capital of about six hundred dollars, and we needed just two thousand dollars more to pull off a fraudulent town-lot scheme in Western Illinois with. We talked it over on the front steps of the hotel. Philoprogenitiveness, says we, is strong in semi-rural communities therefore, and for other reasons, a kidnapping project ought to do better there than in the radius of newspapers that send reporters out in plain clothes to stir up talk about such things. We knew that Summit couldn't get after us with anything stronger than constables and, maybe, some lackadaisical bloodhounds and a diatribe or two in the Weekly Farmers' Budget. So, it looked good.

We selected for our victim the only child of a prominent citizen named Ebenezer Dorset. The father was respectable and tight, a mortgage fancier and a stern, upright collection-plate passer and forecloser. The kid was a boy of ten, with bas-relief freckles, and hair the colour of the cover of the magazine you buy at the news-stand when you want to catch a train. Bill and me figured that Ebenezer would melt down for a ransom of two thousand dollars to a cent. But wait till I tell you.

About two miles from Summit was a little mountain, covered with a dense cedar brake. On the rear elevation of this mountain was a cave. There we stored provisions.

One evening after sundown, we drove in a buggy past old Dorset's house. The kid was in the street, throwing rocks at a kitten on the opposite fence.

'Hey, little boy!' says Bill, 'would you like to have a bag of candy and a nice ride?'

The boy catches Bill neatly in the eye with a piece of brick.

'That will cost the old man an extra five hundred dollars,' says Bill, climbing over the wheel.

That boy put up a fight like a welter-weight cinnamon bear; but, at last, we got him down in the bottom of the buggy and drove away. We took him up to the cave, and I hitched the horse in the cedar brake. After dark I drove the buggy to the little village, three miles away, where we had hired it, and walked back to the mountain.

Bill was pasting court-plaster over the scratches and bruises on his features. There was a fire burning behind the big rock at the entrance of the cave, and the boy was watching a pot of boiling coffee, with two buzzard tailfeathers stuck in his red hair. He points a stick at me when I come up, and says:

'Ha! cursed paleface, do you dare to enter the camp of Red Chief, the terror of the plains?'

'He's all right now,' says Bill, rolling up his trousers and examining some bruises on his shins. 'We're playing Indian. We're making Buffalo Bill's show look like magic-lantern views of Palestine in the town hall. I'm Old Hank, the Trapper, Red Chief's captive, and I'm to be scalped at daybreak. By Geronimo! that kid can kick hard.'

Yes, sir, that boy seemed to be having the time of his life. The fun of camping out in a cave had made him forget that he was a captive himself. He immediately christened me Snake-eye, the Spy, and announced that, when his braves returned from the warpath, I was to be broiled at the stake at the rising of the sun.

Then we had supper; and he filled his mouth full of bacon and bread and gravy, and began to talk. He made a during-dinner speech something like this:

'I like this fine. I never camped out before; but I had a pet 'possum once, and I was nine last birthday. I hate to go to school. Rats ate up sixteen of Jimmy Talbot's aunt's speckled hen's eggs. Are there any real Indians in these woods? I want some more gravy. Does the trees moving make the wind blow? We had five puppies. What makes your nose so red, Hank? My father has lots of money. Are the stars hot? I whipped Ed Walker twice, Saturday. I don't like girls. You dassent catch toads unless with a string. Do oxen make any noise? Why are oranges round? Have you got beds to sleep on in this cave? Amos Murray has got six toes. A parrot can talk, but a monkey or a fish can't. How many does it take to make twelve?'

Every few minutes he would remember that he was a pesky redskin, and pick up his stick rifle and tiptoe to the mouth of the cave to rubber for the scouts of the hated paleface. Now and then he would let out a warwhoop that made Old Hank the Trapper, shiver. That boy had Bill terrorized from the start.

'Red Chief,' says I to the kid, 'would you like to go home?'

'Aw, what for?' says he. 'I don't have any fun at home. I hate to go to school. I like to camp out. You won't take me back home again, Snake-eye, will you?'

'Not right away,' says I. 'We'll stay here in the cave a while.'

'All right!' says he. 'That'll be fine. I never had such fun in all my life.'

We went to bed about eleven o'clock. We spread down some wide blankets and quilts and put Red Chief between us. We weren't afraid he'd run away. He kept us awake for three hours, jumping up and reaching for his rifle and screeching: 'Hist! pard,' in mine and Bill's ears, as the fancied crackle of a twig or the rustle of a leaf revealed to his young imagination the stealthy approach of the outlaw band. At last, I fell into a troubled sleep, and dreamed that I had been kidnapped and chained to a tree by a ferocious pirate with red hair.

Just at daybreak, I was awakened by a series of awful screams from Bill. They weren't yells, or howls, or shouts, or whoops, or yawps, such as you'd expect from a manly set of vocal organs--they were simply indecent, terrifying, humiliating screams, such as women emit when they see ghosts or caterpillars. It's an awful thing to hear a strong, desperate, fat man scream incontinently in a cave at daybreak.

I jumped up to see what the matter was. Red Chief was sitting on Bill's chest, with one hand twined in Bill's hair. In the other he had the sharp case-knife we used for slicing bacon; and he was industriously and realistically trying to take Bill's scalp, according to the sentence that had been pronounced upon him the evening before.

I got the knife away from the kid and made him lie down again. But, from that moment, Bill's spirit was broken. He laid down on his side of the bed, but he never closed an eye again in sleep as long as that boy was with us. I dozed off for a while, but along toward sun-up I remembered that Red Chief had said I was to be burned at the stake at the rising of the sun. I wasn't nervous or afraid; but I sat up and lit my pipe and leaned against a rock.

'What you getting up so soon for, Sam?' asked Bill.

'Me?' says I. 'Oh, I got a kind of a pain in my shoulder. I thought sitting up would rest it.'

'You're a liar!' says Bill. 'You're afraid. You was to be burned at sunrise, and you was afraid he'd do it. And he would, too, if he could find a match. Ain't it awful, Sam? Do you think anybody will pay out money to get a little imp like that back home?'

'Sure,' said I. 'A rowdy kid like that is just the kind that parents dote on. Now, you and the Chief get up and cook breakfast, while I go up on the top of this mountain and reconnoitre.'

I went up on the peak of the little mountain and ran my eye over the contiguous vicinity. Over toward Summit I expected to see the sturdy yeomanry of the village armed with scythes and pitchforks beating the countryside for the dastardly kidnappers. But what I saw was a peaceful landscape dotted with one man ploughing with a dun mule. Nobody was dragging the creek; no couriers dashed hither and yon, bringing tidings of no news to the distracted parents. There was a sylvan attitude of somnolent sleepiness pervading that section of the external outward surface of Alabama that lay exposed to my view. 'Perhaps,' says I to myself, 'it has not yet been discovered that the wolves have borne away the tender lambkin from the fold. Heaven help the wolves!' says I, and I went down the mountain to breakfast.

When I got to the cave I found Bill backed up against the side of it, breathing hard, and the boy threatening to smash him with a rock half as big as a cocoanut.

'He put a red-hot boiled potato down my back,' explained Bill, 'and then mashed it with his foot; and I boxed his ears. Have you got a gun about you, Sam?'

I took the rock away from the boy and kind of patched up the argument. 'I'll fix you,' says the kid to Bill. 'No man ever yet struck the Red Chief but what he got paid for it. You better beware!'

After breakfast the kid takes a piece of leather with strings wrapped around it out of his pocket and goes outside the cave unwinding it.

'What's he up to now?' says Bill, anxiously. 'You don't think he'll run away, do you, Sam?'

'No fear of it,' says I. 'He don't seem to be much of a home body. But we've got to fix up some plan about the ransom. There don't seem to be much excitement around Summit on account of his disappearance; but maybe they haven't realized yet that he's gone. His folks may think he's spending the night with Aunt Jane or one of the neighbours. Anyhow, he'll be missed to-day. To-night we must get a message to his father demanding the two thousand dollars for his return.'

Just then we heard a kind of war-whoop, such as David might have emitted when he knocked out the champion Goliath. It was a sling that Red Chief had pulled out of his pocket, and he was whirling it around his head.

I dodged, and heard a heavy thud and a kind of a sigh from Bill, like a horse gives out when you take his saddle off. A niggerhead rock the size of an egg had caught Bill just behind his left ear. He loosened himself all over and fell in the fire across the frying pan of hot water for washing the dishes. I dragged him out and poured cold water on his head for half an hour.

By and by, Bill sits up and feels behind his ear and says: 'Sam, do you know who my favourite Biblical character is?'

'Take it easy,' says I. 'You'll come to your senses presently.'

'King Herod,' says he. 'You won't go away and leave me here alone, will you, Sam?'

I went out and caught that boy and shook him until his freckles rattled.

'If you don't behave,' says I, 'I'll take you straight home. Now, are you going to be good, or not?'

'I was only funning,' says he sullenly. 'I didn't mean to hurt Old Hank. But what did he hit me for? I'll behave, Snake-eye, if you won't send me home, and if you'll let me play the Black Scout to-day.'

'I don't know the game,' says I. 'That's for you and Mr. Bill to decide. He's your playmate for the day. I'm going away for a while, on business. Now, you come in and make friends with him and say you are sorry for hurting him, or home you go, at once.'

I made him and Bill shake hands, and then I took Bill aside and told him I was going to Poplar Cove, a little village three miles from the cave, and find out what I could about how the kidnapping had been regarded in Summit. Also, I thought it best to send a peremptory letter to old man Dorset that day, demanding the ransom and dictating how it should be paid.

'You know, Sam,' says Bill, 'I've stood by you without batting an eye in earthquakes, fire and flood--in poker games, dynamite outrages, police raids, train robberies and cyclones. I never lost my nerve yet till we kidnapped that two-legged skyrocket of a kid. He's got me going. You won't leave me long with him, will you, Sam?'

'I'll be back some time this afternoon,' says I. 'You must keep the boy amused and quiet till I return. And now we'll write the letter to old Dorset.'

Bill and I got paper and pencil and worked on the letter while Red Chief, with a blanket wrapped around him, strutted up and down, guarding the mouth of the cave. Bill begged me tearfully to make the ransom fifteen hundred dollars instead of two thousand. 'I ain't attempting,' says he, 'to decry the celebrated moral aspect of parental affection, but we're dealing with humans, and it ain't human for anybody to give up two thousand dollars for that forty-pound chunk of freckled wildcat. I'm willing to take a chance at fifteen hundred dollars. You can charge the difference up to me.'

So, to relieve Bill, I acceded, and we collaborated a letter that ran this way:

Ebenezer Dorset, Esq.:

We have your boy concealed in a place far from Summit. It is useless for you or the most skilful detectives to attempt to find him. Absolutely, the only terms on which you can have him restored to you are these: We demand fifteen hundred dollars in large bills for his return; the money to be left at midnight to-night at the same spot and in the same box as your reply--as hereinafter described. If you agree to these terms, send your answer in writing by a solitary messenger to-night at half-past eight o'clock. After crossing Owl Creek, on the road to Poplar Cove, there are three large trees about a hundred yards apart, close to the fence of the wheat field on the right-hand side. At the bottom of the fence-post, opposite the third tree, will be found a small pasteboard box.

The messenger will place the answer in this box and return immediately to Summit.

If you attempt any treachery or fail to comply with our demand as stated, you will never see your boy again.

If you pay the money as demanded, he will be returned to you safe and well within three hours. These terms are final, and if you do not accede to them no further communication will be attempted.

TWO DESPERATE MEN.

I addressed this letter to Dorset, and put it in my pocket. As I was about to start, the kid comes up to me and says:

'Aw, Snake-eye, you said I could play the Black Scout while you was gone.'

'Play it, of course,' says I. 'Mr. Bill will play with you. What kind of a game is it?'

'I'm the Black Scout,' says Red Chief, 'and I have to ride to the stockade to warn the settlers that the Indians are coming. I 'm tired of playing Indian myself. I want to be the Black Scout.'

'All right,' says I. 'It sounds harmless to me. I guess Mr. Bill will help you foil the pesky savages.'

'What am I to do?' asks Bill, looking at the kid suspiciously.

'You are the hoss,' says Black Scout. 'Get down on your hands and knees. How can I ride to the stockade without a hoss?'

'You'd better keep him interested,' said I, 'till we get the scheme going. Loosen up.'

Bill gets down on his all fours, and a look comes in his eye like a rabbit's when you catch it in a trap.

' How far is it to the stockade, kid? ' he asks, in a husky manner of voice.

'Ninety miles,' says the Black Scout. 'And you have to hump yourself to get there on time. Whoa, now!'

The Black Scout jumps on Bill's back and digs his heels in his side.

'For Heaven's sake,' says Bill, 'hurry back, Sam, as soon as you can. I wish we hadn't made the ransom more than a thousand. Say, you quit kicking me or I '11 get up and warm you good.'

I walked over to Poplar Cove and sat around the postoffice and store, talking with the chawbacons that came in to trade. One whiskerand says that he hears Summit is all upset on account of Elder Ebenezer Dorset's boy having been lost or stolen. That was all I wanted to know. I bought some smoking tobacco, referred casually to the price of black-eyed peas, posted my letter surreptitiously and came away. The postmaster said the mail-carrier would come by in an hour to take the mail on to Summit.

When I got back to the cave Bill and the boy were not to be found. I explored the vicinity of the cave, and risked a yodel or two, but there was no response.

So I lighted my pipe and sat down on a mossy bank to await developments.

In about half an hour I heard the bushes rustle, and Bill wabbled out into the little glade in front of the cave. Behind him was the kid, stepping softly like a scout, with a broad grin on his face. Bill stopped, took off his hat and wiped his face with a red handkerchief. The kid stopped about eight feet behind him.

'Sam,' says Bill, 'I suppose you'll think I'm a renegade, but I couldn't help it. I'm a grown person with masculine proclivities and habits of self-defence, but there is a time when all systems of egotism and predominance fail. The boy is gone. I have sent him home. All is off. There was martyrs in old times,' goes on Bill, 'that suffered death rather than give up the particular graft they enjoyed. None of 'em ever was subjugated to such supernatural tortures as I have been. I tried to be faithful to our articles of depredation; but there came a limit.'

'What's the trouble, Bill?' I asks him.

'I was rode,' says Bill, 'the ninety miles to the stockade, not barring an inch. Then, when the settlers was rescued, I was given oats. Sand ain't a palatable substitute. And then, for an hour I had to try to explain to him why there was nothin' in holes, how a road can run both ways and what makes the grass green. I tell you, Sam, a human can only stand so much. I takes him by the neck of his clothes and drags him down the mountain. On the way he kicks my legs black-and-blue from the knees down; and I've got two or three bites on my thumb and hand cauterized.

'But he's gone'--continues Bill--'gone home. I showed him the road to Summit and kicked him about eight feet nearer there at one kick. I'm sorry we lose the ransom; but it was either that or Bill Driscoll to the madhouse.'

Bill is puffing and blowing, but there is a look of ineffable peace and growing content on his rose-pink features.

'Bill,' says I, 'there isn't any heart disease in your family, is there?'

'No,' says Bill, 'nothing chronic except malaria and accidents. Why?'

'Then you might turn around,' says I, 'and have a look behind you.'

Bill turns and sees the boy, and loses his complexion and sits down plump on the ground and begins to pluck aimlessly at grass and little sticks. For an hour I was afraid for his mind. And then I told him that my scheme was to put the whole job through immediately and that we would get the ransom and be off with it by midnight if old Dorset fell in with our proposition. So Bill braced up enough to give the kid a weak sort of a smile and a promise to play the Russian in a Japanese war with him as soon as he felt a little better.

I had a scheme for collecting that ransom without danger of being caught by counterplots that ought to commend itself to professional kidnappers. The tree under which the answer was to be left--and the money later on--was close to the road fence with big, bare fields on all sides. If a gang of constables should be watching for any one to come for the note they could see him a long way off crossing the fields or in the road. But no, sirree! At half-past eight I was up in that tree as well hidden as a tree toad, waiting for the messenger to arrive.

Exactly on time, a half-grown boy rides up the road on a bicycle, locates the pasteboard box at the foot of the fencepost, slips a folded piece of paper into it and pedals away again back toward Summit.

I waited an hour and then concluded the thing was square. I slid down the tree, got the note, slipped along the fence till I struck the woods, and was back at the cave in another half an hour. I opened the note, got near the lantern and read it to Bill. It was written with a pen in a crabbed hand, and the sum and substance of it was this:

Two Desperate Men.

Gentlemen: I received your letter to-day by post, in regard to the ransom you ask for the return of my son. I think you are a little high in your demands, and I hereby make you a counter-proposition, which I am inclined to believe you will accept. You bring Johnny home and pay me two hundred and fifty dollars in cash, and I agree to take him off your hands. You had better come at night, for the neighbours believe he is lost, and I couldn't be responsible for what they would do to anybody they saw bringing him back.

Very respectfully,
EBENEZER DORSET.

'Great pirates of Penzance!' says I; 'of all the impudent--'

But I glanced at Bill, and hesitated. He had the most appealing look in his eyes I ever saw on the face of a dumb or a talking brute.

'Sam,' says he, 'what's two hundred and fifty dollars, after all? We've got the money. One more night of this kid will send me to a bed in Bedlam. Besides being a thorough gentleman, I think Mr. Dorset is a spendthrift for making us such a liberal offer. You ain't going to let the chance go, are you?'

'Tell you the truth, Bill,' says I, 'this little he ewe lamb has somewhat got on my nerves too. We'll take him home, pay the ransom and make our get-away.'

We took him home that night. We got him to go by telling him that his father had bought a silver-mounted rifle and a pair of moccasins for him, and we were going to hunt bears the next day.

It was just twelve o'clock when we knocked at Ebenezer's front door. Just at the moment when I should have been abstracting the fifteen hundred dollars from the box under the tree, according to the original proposition, Bill was counting out two hundred and fifty dollars into Dorset's hand.

When the kid found out we were going to leave him at home he started up a howl like a calliope and fastened himself as tight as a leech to Bill's leg. His father peeled him away gradually, like a porous plaster.

'How long can you hold him?' asks Bill.

'I'm not as strong as I used to be,' says old Dorset, 'but I think I can promise you ten minutes.'

'Enough,' says Bill. 'In ten minutes I shall cross the Central, Southern and Middle Western States, and be legging it trippingly for the Canadian border.'

And, as dark as it was, and as fat as Bill was, and as good a runner as I am, he was a good mile and a half out of summit before I could catch up with him.

top

codefool codefool writes  |  more than 10 years ago The Night the Bed Fell

by James Thurber

I suppose that the high-water mark of my youth in Columbus, Ohio, was the night the bed fell on my father. It makes a better recitation (unless, as some friends of mine have said, one has heard it five or six times) than it does a piece of writing, for it is almost necessary to throw furniture around, shake doors, and bark like a dog, to lend the proper atmosphere and verisimilitude to what is admittedly a somewhat incredible tale. Still, it did take place.

It happened, then, that my father had decided to sleep in the attic one night, to be away where he could think. My mother opposed the notion strongly because, she said, the old wooden bed up there was unsafe- it was wobbly and the heavy headboard would crash down on father's head in case the bed fell, and kill him. There was no dissuading him, however, and at a quarter past ten he closed the attic door behind him and went up the narrow twisting stairs. We later heard ominous creakings as he crawled into bed. Grandfather, who usually slept in the attic bed when he was with us, had disappeared some days before. (On these occasions he was usually gone six or seven days and returned growling and out of temper, with the news that the federal Union was run by a passel of blockheads and that the Army of the Potomac didn't have any more chance than a fiddler's bitch.)

We had visiting us at this time a nervous first cousin of mine named Briggs Beall, who believed that he was likely to cease breathing when he was asleep. It was his feeling that if he were not awakened every hour during the night, he might die of suffocation. He had been accustomed to setting an alarm clock to ring at intervals until morning, but I persuaded him to abandon this. He slept in my room and I told him that I was such a light sleeper that if anybody quit breathing in the same room with me, I would wake Instantly. He tested me the first night-which I had suspected he would by holding his breath after my regular breathing had convinced him I was asleep. I was not asleep, however, and called to him. This seemed to allay his fears a little, but he took the precaution of putting a class of spirits of camphor on a little table at the head of his bed. In case I didn't arouse him until he was almost gone, he said, he would sniff the camphor, a powerful reviver.

Briggs was not the only member of his family who had his crotchets. Old Aunt Alelissa Beall (who could whistle like a man, with two fingers in her mouth) suffered under the premonition that she was destined to die on South High Street, because she had been born on South High Street and married on South High Street. Then there was Aunt Sarah Shoaf, who never went to bed at night without the fear that a burglar was going to get in and blow chloroform under her door through a tube. To avert this calamity -for she was in greater dread of anesthetics than of losing her household goods-she always piled her money, silverware, and other valuables in a neat stack just outside her bedroom, with a note reading,: "This is all I have. Please take it and do not use your chloroform, as this is all I have." Aunt Gracie Shoaf also had a burglar phobia, but she met it with more fortitude. She was confident that burglars had been getting into her house every night for four years. The fact that she never missed anything was to her no proof to the contrary. She always claimed that she scared them off before they could take anything, by throwing shoes down the hallway. When she went to bed she piled, where she could get at them handily, all the shoes there were about her house. Five minutes after she had turned off the light, she would sit up in bed and say "Hark!" Her husband, who had learned to ignore the whole situation as long ago as 1903, would either be sound asleep or pretend to be sound asleep. In either case he would not respond to her tugging and pulling, so that presently she would arise, tiptoe to the door, open it slightly and heave a shoe down the hall in one direction, and its mate down the hall in the other direction. Some nights she threw them all, some nights only a couple of pair.

But I am straying from the remarkable incidents that took place during the night that the bed fell on father. By midnight we were all in bed. The layout of the rooms and the disposition of their occupants is important to an understanding of what later occurred. In the front room upstairs (just under father's attic bedroom) were my mother and my brother Terry, who sometimes sang in his sleep, usually "Marching Through Georgia" or "Onward, Christian Soldiers." Briggs Beall and myself were in a room adjoining this one. My brother Roy was in a room across the hall from ours. Our bull terrier, Rex, slept in the hall.

My bed was an army cot, one of those affairs which are made wide enough to sleep on comfortably only by putting up, flat with the middle section, the two sides which ordinarily hang down like the sideboards of a drop-leaf table. When these sides are up, it is perilous to roll too far toward the edge, for then the cot is likely to tip completely over, bringing the whole bed down on top of one, with a tremendous banging crash. This, in fact, is precisely what happened, about two o'clock in the morning. (It was my mother who, in recalling the scene later, first referred to it as "the night the bed fell on your father.")

Always a deep sleeper, slow to arouse (I had lied to Briggs), I was at first unconscious of what had happened when the iron cot rolled me onto the floor and toppled over on me. It left me still warmly bundled up and unhurt, for the bed rested above me like a canopy. Hence I did not wake up, only reached-the edge of consciousness and went back. The racket, however, instantly awakened my mother, in the next room, who came to the immediate conclusion that her worst dread was realized: the big wooden bed upstairs had fallen on father. She therefore screamed, "Let's go to your poor father!" It was this shout, rather, than the noise of my cot falling, that awakened Herman, in the same room with her. He thought that mother had become, for no apparent reason, hysterical. "You're all right, Mamma!" He shouted, trying, to calm her. They exchanged shout for shout for perhaps ten seconds: "Let's go to your poor father!" and "You're all right! " That woke up Briggs. By this time I was conscious of what was going on, in a vague way, but did not yet realize that I was under my bed instead of on it. Briggs, awakening in the midst of loud shouts of fear and apprehension, came to the quick conclusion that he was suffocating and that we were all trying to "bring him out." With a low moan, he grasped the glass of camphor at the head of his bed and instead of sniffing it poured it over himself. The room reeked of camphor. "Ugh, ugh," choked Briggs, like a drowning man, for he had almost succeeded in stopping his breathing under the deluge of pungent spirits. He leaped out of bed and groped toward the open window, but he came up against one that was closed. With his hand, he beat out the glass, and I could hear it crash and tinkle on the alleyway below. It was at this juncture that I, in trying to get up, had the uncanny sensation of feeling my bed above me. Foggy with sleep, I now suspected, in my turn, that the whole uproar was being made in a frantic endeavor to extricate me from what must be an unheard-of and perilous situation. "Get me out of this!" I bawled. "Get me out!" I think I had the nightmarish belief that I was entombed in a mine. "Ugh," gasped Briggs, floundering in his camphor.

By this time my mother, still shouting, pursued by Herman, still shouting, was trying to open the door to the attic, in order to' go up and get my father's body out of the wreckage. The door was stuck, however, and wouldn't yield. Her frantic pulls on it only added to the general banging and confusion. Roy and the dog were now up, the one shouting questions, the other barking.

Father, farthest away and soundest sleeper of all, had by this time been awakened by the battering on the attic door. He decided that the house was on fire. "I'm coming, I'm coming,!" he wailed in a slow, sleepy voice-it took him many minutes to regain full consciousness. My mother, still believing he was caught under the bed, detected in his "I'm coming!" the mournful, resigned note of one who is preparing to meet his Maker. "He's dying!" she shouted.

"I'm all right!" Briggs yelled to reassure her. "I'm all right!" He still believed that it was his own closeness to death that was worrying mother. I found at last the light switch in my room, unlocked the door, and Briggs and I joined the others at the attic door. The dog, who never did like Briggs, jumped for him assuming that he was the culprit in whatever was going on and Roy had to throw Rex and hold him. We could hear father crawling out of bed upstairs. Roy pulled the attic door open, with a mighty jerk, and father came down the stairs, sleepy and irritable but safe and sound. My mother began to weep when she saw him. Rex began to-howl. "What in the name of God "s going on here?" asked father.

The situation was finally put together like a gigantic jig-saw puzzle. Father caught a cold from prowling around in his bare feet but there were no other bad results. "I'm glad," said mother, who always looked on the bright side of things, "that your grandfather wasn't here."

top

codefool codefool writes  |  more than 10 years ago This is perhaps one of the finest stories I have ever read. I read it for the first time in my eighth grade english class, and have never come across it since. So, you can tell that it's really stuck with me. As this story is not published in any non-text book and is not commercially avialable that I can discover, I'll publish it here for my own use and without permission of the Shulman estate. If you you have the time, its worth the read.

[Update 2003.06.06] I stand corrected. The story is from the book The Many Loves Of Dobbie Gillis (c) 1945 by Max Shulman. This book appears to be out of print (the last edition being from Amereon Limited in 1983). I secured a much older copy from eBay, so hopefully this will cover any fair use issues. Still, enjoy!

========================

Love Is a Fallacy

by Max Shulman (1919-1988)

Cool was I and logical. Keen, calculating, perspicacious, acute --- I was all of these. My brain was as powerful as a dynamo, as a chemist's scales, as penetrating as a scalpel. And - think of it! - I was only eighteen.

It is not often that one so young has such a giant intellect. Take, for example, Petey Burch my roommate at the University of Minnesota. Same age, same background, but dumb as an ox. A nice enough fellow, you understand, but nothing upstairs. Emotional type. Unstable. Impressionable. Worst of all, a faddist. Fads, I submit, are the very negation of reason. To be swept up in every new craze that comes along, to surrender oneself to idiocy just because everybody else is doing it - this to me, is the acme of mindlessness. Not, however, to Petey.

One afternoon I found Petey lying on his bed with an expression of such distress on his face that I immediately diagnosed appendicitis. "Don't move," I said, "Don't take a laxative. I'll get a doctor."

"Raccoon," he mumbled thickly.

"Raccoon?" I said, pausing in my flight.

"I want a raccon coat," he wailed.

I perceived that his trouble was not physical but mental. "Why do you want a raccoon coat?"

"I should have known it," he cried, pounding hie temples.

"I should have known it they'd come back when the Charleston came back. Like a fool I spent all my money for textbook, and now I can't get a raccoon coat."

"Can you mean," I said incredulously," that people are actually wearing raccoon coats again?"

"All the Big Men on Campus are wearing them. Where've you been?"

"In the library," I said, naming a place not frequented by Big Men on Campus.

He leaped from the bed and paced the room. "I've got to have a raccoon coat," he said passionately. "I've got to!"

"Petey, why? Look at it rationally. Raccoon coats are unsanitary. They shed. They smell bad. They weigh too much. They're unsightly. They..."

"You don't understand," he interrupted, impatiently. "It's the thing to do. Don't you want to be in the swim?"

"No," I said truthfully "Well, I do," he declared. "I'd give anything for a raccoon coat. Anything!"

My brain, that precision instrument, slipped into high gear. "Anything?" I asked, looking at him narrowly.

"Anything," he affirmed in ringing tones.

I stroked my chin thoughtfully. It so happened that I knew where to get my hands on a raccoon coat. My father had had one in his undergraduate days; it lay now in a trunk in the attic back home. It also happened that Petey had something I wanted. He didn't have it exactly, but at least he had first rights on it. I refer to his girl, Polly Espy.

I had long coveted Polly Espy. Let me emphasize that my desire for this young woman was not emotional in nature. She was, to be sure, a girl who excited the emotions, but I was not one to let my heart rule my head. I wanted Polly for a shrewdly calculated, entirely cerebral reason.

I was a freshman in law school. In a few years I would be out in practice. I was well aware of the importance of the right kind of wife in furthering a lawyer's career. The successful lawyers I had observed were, almost without exception, married to beautiful, gracious, intelligent women. With one omission, Polly fitted these specifications perfectly.

Beautiful she was. She was not yet of pin-up proportions, but I felt that time would supply the lack. She already had the makings.

Gracious she was. By gracious I mean full of graces. She had an erectness of carriage, an ease of bearing, a poise that clearly indicated the best of breeding. At table her manners were exquisite. I had seen her at the Kozy Kampus Korner eating the specialty of the house - a sandwich that contained scraps of pot roast, gravy, chopped nuts, and a dipper of sauerkraut - without even getting her fingers moist.

Intelligent she was not. In fact, she veered in the opposite direction. But I believed that under my guidance she would smarten up. At any rate, it was worth a try. It is, after all, easier to make a beautiful dumb girl smart than to make an ugly smart girl beautiful.

"Petey," I said, "are you in love with Polly Espy?"

"I think she's a keen kid," he replied, "but I don't know if you call it love. Why?"

"Do you," I asked, "have any kind of formal arrangement with her? I mean are you going steady or anything like that?"

"No. We see each other quite a bit, but we both have other dates. Why?"

"Is there," I asked, "any other man for whom she has a particular fondness?"

"Not that I know of. Why?"

I nodded with satisfaction. "In other words, if you were out of the picture, the field would be open. Is that right?"

"I guess so. What are you getting at?"

"Nothing , nothing," I said innocently, and took my suitcase out the closet.

"Where are you going?" asked Petey.

"Home for weekend." I threw a few things into the bag.

"Listen," he said, clutching my arm eagerly, "while you're home, you couldn't get some money from your old man, could you , and lend it to me so I can buy a raccoon coat?"

"I may do better than that," I said with a mysterious wink and closed my bag and left.

"Look," I said to Petey when I got back Monday morning. I threw open the suitcase and revealed the huge, hairy, gamy object that my father had worn in his Stutz Bearcat in 1925.

"Holy Toledo!" said Petey reverently. He plunged his hands into the raccoon coat and then his face. "Holy Toledo!" he repeated fifteen or twenty times.

"Would you like it?" I asked.

"Oh yes!" he cried, clutching the greasy pelt to him. Then a canny look came into his eyes. "What do you want for it?"

"Your girl" I said, mincing no words.

"Polly?" he said in a horrified whisper. "You want Polly?"

"That's right."

He shook his head.

I shrugged. "Okay. If you don't want to be in the swim, I guess it's your business.

I sat down in a chair and pretended to read a book, but out of the corner of my eye I kept watching Petey. He was a torn man. First he looked at the coat with the expression of waif at a bakery window. Then he turned away and set his jaw resolutely. Then he looked back at the coat, with even more longing in his face. Then he turned away, but with not so much resolution this time. Back and forth his head swiveled, desire waxing, resolution waning. Finally he didn't turn away at all; he just stood and stared with mad lust at the coat.

"It isn't as though I was in love with Polly," he said thickly. "Or going steady or anything like that."

"That's right," I murmured.

"What's Polly to me, or me to Polly?"

"Not a thing," said I.

"It's just been a casual kick - just a few laughs, that's all."

"Try on the coat," said I.

He compiled. The coat bunched high over his ears and dropped all the way down to his shoe tops. He looked like a mound of dead raccoons. "Fits fine," he said happily.

I rose from my chair. "Is it a deal?" I asked, extending my hand. He swallowed. "It's a deal," he said and shook my hand.

I had my first date with Polly the following evening. This was in the nature of a survey. I wanted to find out just how much work I had to get her mind up to the standard I required. I took her first to dinner.

"Gee, that was a delish dinner," she said as we left the restaurant.

And then I took her home. "Gee, I had a sensaysh time," she said as she bade me good night.

I went back to my room with a heavy heart. I had gravely underestimated the size of my task. This girl's lack of information was terrifying. Nor would it be enough merely to supply her with information. First she had to be taught to "think". This loomed as a project of no small dimensions, and at first I was tempted to give her back to Petey.

But then I got to thinking about her abundant physical charms and about the way she entered a room and the way she handled a knife and fork, and I decided to make an effort.

I went about it, as in all things, systematically. I gave her a course in logic. It happened that I, as a law student, was taking a course in logic myself, so I had all the facts at my fingertips. "Polly,: I said in to Her when I picked her up on our next date, tonight we are going over to the Knoll and talk.

"Oo, terrif," she replied. One thing I will say for this girl: you would go far to find another so agreeable.

We went to the Knoll, the campus trysting place, and we sat down under an old oak, and she looked at me expectantly. "What are we going to talk about?" she asked.

"Logic."

She thought this over for a minute and decided she liked it. "Magnif," she said.

Logic," I said, clearing my throat, "is the science of thinking. Before we can think correctly, we must first learn to recognize the common fallacies of logic. These we will take up tonight."

"Wow-dow!" she cried, clapping her hands delightedly.

I winced, but went bravely on. "First let us examine the fallacy called Dicto Simpliciter."

"By all means," she urged, batting her lashes eagerly.

"Dicto Simpliciter means an argument based on an unqualified generalization. For example: Exercise is good. Therefore everybody should exercise."

"Polly," I said gently, "the argument is a fallacy. Exercise is good is an unqualified generalization. For instance, if you have heart disease, exercise is bad, not good. Therefore exercise is bad, not good. Many people are ordered by their doctors not to exercise. You must qualify the generalization. You must say exercise is usually good, or exercise is good for most people. Otherwise you have committed a Dicto Simpliciter. Do you see?"

"No," she confessed. "But this is marvy. Do more! Do more!"

"It will be better if you stop tugging at my sleeve," I told her, and when she desisted, I continued. "Next we take up a fallacy called Hasty Generalization. Listen carefully: You can't speak French. Petey Burch can't speak French. I must therefore conclude that nobody at the University of Minnesota can speak French."

"Really?" said Polly, amazed. "Nobody?"

I hid my exasperation. "Polly, it's a fallacy. The generalization is reached too hastily. There are too few instance to support such a conclusion."

Know any more fallacies?" she asked breathlessly. "This is more fun than dancing, even."

I fought off a wave of despair. I was getting no where with this girl, absolutely no where. Still, I am nothing, if not persistent. I continued. "Next comes Post Hoc. Listen to this: Let's not take Bill on our picnic. Every time we take it out with us, it rains."

"I know somebody just like that," she exclaimed. "A girl back home - Eula Becker, her name is. It never fails. Every single time we take her on a picnic..."

"Polly," I said sharply, "it's a fallacy. Eula Becker doesn't cause the rain. She has no connection with the rain. You are guilty of Post Hoc if you blame Eula Becker."

"I'll never do it again," she promised contritely. "Are you mad at me?"

I sighed deeply. "No, Polly, I'm not mad."

"Then tell me some more fallacies."

"All right. Let's try Contradictory Premises."

"Yes, let's," she chirped, blinking her eyes happily.

I frowned, but plunged ahead. "Here's an example of Contradictory Premises: If God can do anything, can He make a stone so heavy that He won't be able to lift it?"

"Of course," she replied promptly.

"But if He can do anything, He can lift the stone," I pointed out.

"Yeah," she said thoughtfully. "Well, then I guess He can't make the stone."

"But He can do anything," I reminded her.

She scratched her pretty, empty head. "I'm all confused," she admitted.

"Of course you are. Because when the premises of an argument contradict each other, there can be no argument. If there is an irresistible force, there can be no immovable object. If there is an immovable object, there can be no irresistible force. Get it?"

"Tell me more of this keen stuff," she said eagerly.

I consulted my watch. "I think we'd better call it a night. I'll take you home now, and you go over all the things you've learned. We'll have another session tomorrow night."

I deposited her at the girls' dormitory, where she assured me that she had had a "perfectly" evening, and I went glumly home to my room. Petey lay snoring in his bed, the raccoon coat huddled like a great hairy beast at his feet. For a moment I considered waking him and telling him that he could have his girl back. It seemed clear that my project was doomed to failure. The girl simply had a logic-proof head.

But then I reconsidered. I had wasted one evening; I might as well waste another. Who knew? Maybe somewhere in the extinct crater of her mind, a few members still smoldered. Maybe somehow I could fan them into flame. Admittedly it was not a prospect fraught with hope, but I decided to give it one more try.

Seated under the oak the next evening I said, "Our first fallacy tonight is called Ad Misericordiam."

She quivered with delight.

"Listen closely," I said. "A man applies for a job. When the boss asks him what his qualifications are, he has a wife and six children at home, the wife is a helpless cripple, the children have nothing to eat, no clothes to wear, no shoes on their feet, there are no beds in the house, no coal in the cellar, and winter is coming."

A tear rolled down each of Polly's pink cheeks. "Oh, this is awful, awful," she sobbed.

"Yes, it's awful," I agreed, "but it's no argument. The man never answered the boss's question about his qualifications. Instead he appealed to the boss's sympathy. He committed the fallacy of Ad Misericordiam. Do you understand?"

"Have you got a handkerchief?" she blubbered.

I handed her a handkerchief and tried to keep from screaming while she wiped her eyes. "Next," I said in a carefully controlled tone, "we will discuss False Analogy. Here is an example: Students should be allowed to look at their textbooks during examination. After all, surgeons have X rays to guide them during a trial, carpenters have blueprints to guide them when they are building a house. Why, then, shouldn't students be allowed to look at their textbooks during examination?"

"There now," she said enthusiastically, "is the most marvy idea I've heard in years."

"Polly," I said testily, "the argument is all wrong. Doctors, lawyers, and carpenters aren't taking a test to see how much they have learned, but students are. The situations are altogether different, and you can't make an analogy between them."

"I still think it's a good idea," said Polly.

"Nuts," I muttered. Doggedly I pressed on. "Next we'll try Hypothesis Contrary to Fact."

"Sounds yummy," was Polly's reaction.

"Listen: If Madame Curie had not happened to leave a photographic plate in a drawer with a chunk of pitchblende, the world today would not know about radium."

"True, true," said Polly, nodding her head "Did you see the movie? Oh, it just knocked me out. That Walter Pidgeon is so dreamy. I mean he fractures me."

"If you can forget Mr. Pidgeon for a moment," I said coldly, "I would like to point out that statement is a fallacy. Maybe Madame Curie would have discovered radium at some later date. Maybe somebody else would have discovered it. Maybe any number of things would have happened. You can't start with a hypothesis that is not true and then draw any supportable conclusions from it."

"They ought to put Walter Pidgeon in more pictures," said Polly, "I hardly ever see him any more."

One more chance, I decided. But just one more. There is a limit to what flesh and blood can bear. "The next fallacy is called Poisioning the Well."

"How cute!" she gurgled.

"Two men are having a debate. The first one gets up and says, 'My opponent is a notorious liar. You can't believe a word that he is going to say.' ... Now, Polly, think hard. What's wrong?"

I watched her closely as she knit her creamy brow in concentration. Suddenly a glimmer of intelligence -- the first I had seen -- came into her eyes. "It's not fair," she said with indignation. "It's not a bit fair. What chance has the second man got if the first man calls him a liar before he even begins talking?"

"Right!" I cried exultantly. "One hundred per cent right. It's not fair. The first man has poisoned the well before anybody could drink from it. He has hamstrung his opponent before he could even start ... Polly, I'm proud of you."

"Pshaws," she murmured, blushing with pleasure.

"You see, my dear, these things aren't so hard. All you have to do is concentrate. Think-examine-evaluate. Come now, let's review everything we have learned."

"Fire away," she said with an airy wave of her hand.

Heartened by the knowledge that Polly was not altogether a cretin, began a long, patient review of all I had told her. Over and over and over again I cited instances, pointed out flaws, kept hammering away without letup. It was like digging a tunnel. At first, everything was work, sweat, and darkness. I had no idea when I would reach the light, or even if I would. But I persisted. I pounded and clawed and scraped, and finally I was rewarded. I saw a chink of light. And then the chink got bigger and the sun came pouring in and all was bright.

Five grueling nights with this book was worth it. I had made a logician out of Polly; I had taught her to think. My job was done. She was worthy of me, at last. She was a fit wife for me, a proper hostess for many mansions, a suitable mother for my well-heeled children.

It must not be thought that I was without love for this girl. Quite the contrary. Just as Pygmalion loved mine. I determined to acquaint her with feelings at our very next meeting. The time had come to change our relationship from academic to romantic.

"Polly," I said when next we sat beneath our oak, "tonight we will not discuss fallacies."

"Aw, gee," she said, disappointed.

"My dear," I said, favoring her with a smile, "we have now spent five evenings together. We have gotten along splendidly. It is clear that we are well matched."

"Hasty Generalization," said Polly brightly.

"I beg your pardon," said I.

"Hasty Generalization," she repeated. "How can you say that we are well matched on the basis of only five dates?"

I chuckled with amusement. The dear child had learned her lessons well. "My dear," I said, patting her hand in a tolerant manner, "five dates is plenty. After all, you don't have to eat a whole cake to know that it's good."

"False Analogy," said Polly promptly. "I'm not a cake. I'm a girl."

I chuckled with somewhat less amusement. The dear child had learned her lessons perhaps too well. I decided to change tactics. Obviously the best approach was a simple, strong, direct declaration of love. I paused for a moment while my massive brain chose the proper word. Then I began:

"Polly, I love you. You are the whole world to me, and the moon and the stars and the constellations of outer space. Please, my darling, say that you will go steady with me, for if you will not, life will be meaningless. I will languish. I will refuse my meals. I will wander the face of the earth, a shambling, hollow-eyed hulk."

There, I thought, folding my arms, that ought to do it.

"Ad Misericordiam," said Polly.

I ground my teeth. I was not Pygmalion; I was Frankenstein, and my monster had me by the throat. Frantically I fought back the tide of panic surging through me,. at all costs I had to keep cool.

"Well, Polly," I said, forcing a smile, "you certainly have learned your fallacies."

"You're darn right," she said with a vigorous nod.

"And who taught them to you, Polly?"

"You did."

"That's right. So you do owe me something, don't you, my dear? If I hadn't come along you never would have learned about fallacies."

"Hypothesis Contrary to Fact," she said instantly.

I dashed perspiration from my brow. "Polly," I croaked, "you mustn't take all these things so literally. I mean this is just classroom stuff. You know that the things you learn in school don't have anything to do with life."

"Dicto Simpliciter," she said, wagging her finger at me playfully.

That did it. I leaped to my feet, bellowing like a bull. "Will you or will you not go steady with me?"

"I will not," she replied.

"Why not?" I demanded.

"Because this afternoon I promised Petey Burch that I would go steady with him."

I reeled back, overcome with the infamy of it. After he promised, after he made a deal, after he shook my hand! "The rat!" I shrieked, kicking up great chunks of turf. "You can't go with him, Polly. He's a liar. He's a cheat. He's a rat."

"Poisoning the Well ," said Polly, "and stop shouting. I think shouting must be a fallacy too."

With an immense effort of will, I modulated my voice. "All right," I said. "You're a logician. Let's look at this thing logically. How could you choose Petey Burch over me? Look at me --- a brilliant student, a tremendous intellectual, a man with an assured future. Look at Petey -- a knothead, a jitterbug, a guy who'll never know where his next meal is coming from. Can you give me one logical reason why you should go steady with Petey Burch?"

"I certainly can," declared Polly. "He's got a raccoon coat."

top

codefool codefool writes  |  more than 10 years ago First stab at a base64 encoder class:
====== b64codec.h ======
// b64codec.h: interface for the b64codec class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_B64CODEC_H__E281B1B6_D880_4F90_A308_BD44E726E146__INCLUDED_)
#define AFX_B64CODEC_H__E281B1B6_D880_4F90_A308_BD44E726E146__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <ctype.h>
#include <list>
using namespace std;

#if !defined( byte )
typedef unsigned char byte;
#endif

#define E_B64CODEC_ENCODE_BUFFER_EMPTY  100
#define E_B64CODEC_ENCODE_INVALID_STATE 101

#define E_B64CODEC_DECODE_BUFFER_EMPTY  200
#define E_B64CODEC_DECODE_INVALID_STATE 201

class b64codec
{
    private:
        static const char codes[];

    public:
        enum { B64_ENC_IDLE = 0, B64_ENC_WAIT2, B64_ENC_WAIT3 };
        enum { B64_DEC_IDLE = 0, B64_DEC_WAIT2, B64_DEC_WAIT3, B64_DEC_WAIT4, B64_DEC_EOF };

    private:
      byte          m_byEncodeState;
      list<byte>    m_lstEncodeBuff;
      byte          m_byEncRem;             // encoding remainder "register"

      byte          m_byDecodeState;
      list<byte>    m_lstDecodeBuff;
      byte          m_byDecRem;             // decoding remainder "register"

    public:
        b64codec();
        virtual ~b64codec();

        byte encIndex( byte byIndex );      // given an index, answer the base64 char
        byte decChar( byte byChar );        // given a base64 char, answer its index
        byte *encodeBuffer( unsigned int *puiBuffSize, bool bClear = true );
        byte *decodeBuffer( unsigned int *puiBuffSize, bool bClear = true );
        bool encReady() { return (bool)( m_lstEncodeBuff.size() > 0 ); };
        bool decReady() { return (bool)( m_lstDecodeBuff.size() > 0 ); };

        void encReset();
        byte encPush( byte byVal );
        void encEnd();
        byte encPop();

        void decReset();
        byte decPush( byte byVal );
        void decEnd();
        byte decPop();

    private:
        byte *getBuffer( list<byte> *plist, unsigned int *puiBuffSize, bool bClear );

};

#endif // !defined(AFX_B64CODEC_H__E281B1B6_D880_4F90_A308_BD44E726E146__INCLUDED_)

====== b64codec.cpp ======
// b64codec.cpp: implementation of the b64codec class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "b64codec.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

                            //  0....:....1....:....2....:....3....:....4....:....5....:....6...6
                            //  0    5    0    5    0    5    0    5    0    5    0    5    0   4
const char b64codec::codes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
                            //  0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0
                            //  0               1               2               3               4

b64codec::b64codec()
{
    encReset();
    decReset();
}

b64codec::~b64codec()
{
    encReset();
    decReset();
}

byte b64codec::encIndex( byte byIndex )
{
    if( 0 <= byIndex && byIndex <= 63 )
        return codes[ byIndex ];
    return 0xff;
}

byte b64codec::decChar( byte byChar )      // given a base64 char, answer its index
{
    byte byRet;

    //
    //  rather than use a reverse lookup, this is much more
    //  efficient in terms of computer cycles.
    //
    if( 'A' <= byChar && byChar <= 'Z' )
        byRet = byChar - 'A';
    else if( 'a' <= byChar && byChar <= 'z' )
        byRet = byChar - 71;
    else if( '0' <= byChar && byChar <= '9' )
        byRet = byChar + 4;
    else if( byChar == '/' )
        byRet = 63;
    else if( byChar == '+' )
        byRet = 64;
    else
        byRet = 0xff;

    //fprintf( stderr, "Got byte '%c' which decoded to %02x, and is '%c'\n", byVal, byRet, c_b64_codes[ byRet ] );

    return byRet;
}

void b64codec::encReset()
{
    m_lstEncodeBuff.empty();
    m_byEncodeState = B64_ENC_IDLE;
}

byte b64codec::encPush( byte byVal )
{
    byte byAcc;      // accumulator "register"

    switch( m_byEncodeState )
    {
        case B64_ENC_IDLE:
            //
            //          mov acc, byVal      ;   copy byVal
            //          and acc, 0xfc       ;   mask upper three taystes
            //          shr acc, 2          ;   shift to lower three taystes
            //          sto acc             ;   store acc
            //          mov rem, byVal      ;   copy byVal
            //          and rem, 0x03       ;   mask lower three tasytes
            //          shl rem, 4          ;   put in hilo tayste
            //          inc state           ;   transition to state 1
            //          ret                 ;   done
            byAcc       = ( ( byVal & 0xfc ) >> 2 );
            m_byEncRem  = ( ( byVal & 0x03 ) << 4 );
            m_byEncodeState++;
            break;

        case B64_ENC_WAIT2:
            //          mov acc, byVal      ; copy byVal
            //          and acc, 0xf0       ; mask upper nibble
            //          shr acc, 4          ; put in lower nibble
            //          or  acc, rem        ; or in upper nibble
            //          sto acc             ; store acc
            //          mov rem, byVal      ; copy byVal
            //          and rem, 0x0f       ; mask lower nibble
            //          shl rem, 2          ; shift to middle taystes
            //          inc state           ; transistion to state 2
            //          ret                 ; done
            byAcc       = ( ( byVal & 0xf0 ) >> 4 ) | m_byEncRem;
            m_byEncRem  = ( ( byVal & 0x0f ) << 2 );
            m_byEncodeState++;
            break;

        case B64_ENC_WAIT3:
            //
            //          mov acc, byVal      ; copy byVal
            //          and acc, 0xc0       ; mask hi tayste
            //          shr acc, 6          ; shift to lo tayste
            //          or  acc, rem        ; or in middle taystes
            //          sto acc             ; store acc
            //          mov acc, byVal      ; copy byVal
            //          and acc, 0x3f       ; mask lower three taystes
            //          sto acc             ; store accumulator
            //          xor state,state     ; transition to state 0
            //          ret
            //
            byAcc   = ( ( byVal & 0xc0 ) >> 6 ) | m_byEncRem;
            m_lstEncodeBuff.push_back( encIndex( byAcc ) );
            byAcc   =   ( byVal & 0x3f );
            m_byEncodeState = 0;
            break;
    }
    m_lstEncodeBuff.push_back( encIndex( byAcc ) );
    return m_byEncodeState;
}

byte b64codec::encPop()
{
    if( !encReady() )
        throw E_B64CODEC_ENCODE_BUFFER_EMPTY;

    byte byRet = m_lstEncodeBuff.front();
    m_lstEncodeBuff.pop_front();
    return byRet;
}

void b64codec::encEnd()
{
    if( B64_ENC_IDLE != m_byEncodeState )
    {
        m_lstEncodeBuff.push_back( encIndex( m_byEncRem ) );     // push what we have
        switch( m_byEncodeState )
        {
            case B64_ENC_WAIT2: m_lstEncodeBuff.push_back( '=' );
            case B64_ENC_WAIT3: m_lstEncodeBuff.push_back( '=' );
                break;
            default:
                throw E_B64CODEC_ENCODE_INVALID_STATE;
        }
    }
}

void b64codec::decReset()
{
    m_lstDecodeBuff.empty();
    m_byDecodeState = B64_ENC_IDLE;
}

//
//  take four octets of input, one at a time, and decode into three octets
//
byte b64codec::decPush( byte byVal )
{
    byte byAcc;      // accumulator "register"

    //
    //  check for special chars that effect the machine
    //
    if( '=' == byVal )
        m_byDecodeState = B64_DEC_EOF;

    else if( !isspace( byVal ) )        // ignore whitespace
    {
        byVal = decChar( byVal );           // convert char to index

        switch( m_byDecodeState )
        {
            case B64_DEC_IDLE:
                //  mov rem, byVal  ; copy byVal
                //  shl rem, 2      ; clear lower tayste
                //  inc state       ; transition to state 1
                //  ret             ; done
                m_byDecRem = ( byVal << 2 );
                m_byDecodeState++;
                break;

            case B64_DEC_WAIT2:
                //  mov acc, byVal  ; copy byVal
                //  and acc, 0x30   ; mask hilo tayste
                //  shr acc, 4      ; put in lower tayste
                //  or  acc, rem    ; or in upper three tasytes
                //  sto acc         ; store the accumulator
                //  mov rem, byVal  ; copy byVal
                //  and rem, 0x0f   ; mask lower nibble
                //  shl rem, 4      ; shift to upper nibble
                //  inc state       ; transition to state 2
                //  ret             ; done
                byAcc      = ( ( byVal & 0x30 ) >> 4 ) | m_byDecRem;
                m_lstDecodeBuff.push_back( byAcc );
                m_byDecRem = ( ( byVal & 0x0f ) << 4 );
                m_byDecodeState++;
                break;

            case B64_DEC_WAIT3:
                //  mov acc, byVal  ; copy byVal
                //  and acc, 0x3c   ; mask middle taystes
                //  shr acc, 2      ; shift to lower nibble
                //  or  acc, rem    ; or in upper nible
                //  sto acc         ; store the accumulator
                //  mov rem, byVal  ; copy byVal
                //  and rem, 0x03   ; mask lower tayste
                //  shl rem, 6      ; shift to upper tayste
                //  inc state       ; transition to state 3
                //  ret             ; done
                byAcc      = ( ( byVal & 0x3c ) >> 2 ) | m_byDecRem;
                m_lstDecodeBuff.push_back( byAcc );
                m_byDecRem = ( ( byVal & 0x03 ) << 6 );
                m_byDecodeState++;
                break;

            case B64_DEC_WAIT4:
                //  mov acc, byVal  ; copy byVal
                //  or  acc, rem    ; or in upper tastye
                //  sto acc         ; store the accumulator
                //  xor state,state ; transition to state 0
                //  done
                byAcc= ( byVal | m_byDecRem );
                m_lstDecodeBuff.push_back( byAcc );
                m_byDecodeState = 0;
                break;
        }
    }
    return m_byDecodeState;
}

void b64codec::decEnd()
{
    if( B64_DEC_IDLE != m_byDecodeState && B64_DEC_EOF != m_byDecodeState )
    {
        m_lstDecodeBuff.push_back( m_byDecRem );
    }
}

byte b64codec::decPop()
{
    if( !decReady() )
        throw E_B64CODEC_DECODE_BUFFER_EMPTY;

    byte byRet = m_lstDecodeBuff.front();
    m_lstDecodeBuff.pop_front();
    return byRet;
}

byte *b64codec::getBuffer( list<byte> *plist, unsigned int *puiBuffSize, bool bClear )
{
    byte *pRet = NULL;

    *puiBuffSize = 0;
    if( plist->size() )
    {
        pRet = new byte[ plist->size() ];

        byte *p = pRet;

        list<byte>::iterator iter;
        for( iter = plist->begin(); iter != plist->end(); iter++ )
            *p++ = *iter;

        *puiBuffSize = plist->size();
        if( bClear )
        {
            plist->empty();
        }
    }
    return pRet;
}

byte *b64codec::encodeBuffer( unsigned int *puiBuffSize, bool bClear /*= true*/ )
{
    byte *pRet = getBuffer( &m_lstEncodeBuff, puiBuffSize, bClear );

    if( bClear )
    {
        m_byEncodeState = B64_ENC_IDLE;
    }
    return pRet;
}

byte *b64codec::decodeBuffer( unsigned int *puiBuffSize, bool bClear /*= true*/ )
{
    byte *pRet = getBuffer( &m_lstDecodeBuff, puiBuffSize, bClear );

    if( bClear )
    {
        m_byDecodeState = B64_ENC_IDLE;
    }
    return pRet;
}

Slashdot Account

Need an Account?

Forgot your password?

Don't worry, we never post anything without your permission.

Submission Text Formatting Tips

We support a small subset of HTML, namely these tags:

  • b
  • i
  • p
  • br
  • a
  • ol
  • ul
  • li
  • dl
  • dt
  • dd
  • em
  • strong
  • tt
  • blockquote
  • div
  • quote
  • ecode

"ecode" can be used for code snippets, for example:

<ecode>    while(1) { do_something(); } </ecode>
Sign up for Slashdot Newsletters
Create a Slashdot Account

Loading...