///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//         This example code is from the book:
//
//           Object-Oriented Programming with C++ and OSF/Motif, 2nd Edition
//         by
//           Douglas Young
//           Prentice Hall, 1995
//           ISBN 0-13-20925507
//
//         Copyright 1995 by Prentice Hall
//         All Rights Reserved
//
//  Permission to use, copy, modify, and distribute this software for 
//  any purpose except publication and without fee is hereby granted, provided 
//  that the above copyright notice appear in all copies of the software.
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////
// WordCountWindow.C: Test the InterruptibleCmd class
/////////////////////////////////////////////////////////////
#include "Application.h"
#include "InfoDialogManager.h"
#include "WordCountWindow.h"
#include "CountWordsCmd.h"
#include "SelectFileCmd.h"
#include "QuitCmd.h"
#include "MenuBar.h"
#include "CmdList.h"
#include <Xm/List.h>
#include <X11/cursorfont.h>
#include <stdio.h>

WordCountWindow::WordCountWindow ( const char *name ) : 
MenuWindow ( name )
{
    // Empty
}
Widget WordCountWindow::createWorkArea ( Widget parent )
{
    _list = XmCreateScrolledList ( parent, "list", NULL, 0 );
    
    XtManageChild ( _list );
    
    return ( XtParent ( _list ) );
}
void WordCountWindow::createMenuPanes()
{
    // Create the command objects for this menu
    
    Cmd  *quit       = new QuitCmd ( "Quit" );
    Cmd  *selectFile = 
	new SelectFileCmd ( "selectFile", TRUE, 
			    &WordCountWindow::countWordsCallback,
			    (void *) this );
    
    // Create a list of commands and install it in a menu pane
    
    CmdList  *cmdList = new CmdList ( "Application" );
    cmdList->add ( selectFile );
    cmdList->add ( quit );
    _menuBar->addCommands ( cmdList );
}
void WordCountWindow::countWordsCallback ( void *clientData, 
					   char *filename )
{
    WordCountWindow *obj = ( WordCountWindow * ) clientData;
    
    obj->countWords ( filename );
}
void WordCountWindow::countWords ( char * filename)
{
    if ( !filename )  // Catch NULL filenames
	return;
    
    // Instantiate a Cmd object to count words in the given file
    
    CountWordsCmd *task = new CountWordsCmd ( "countWords",
					      TRUE, filename );
    setBusyCursor();  // Display a busy cursor
    
    XtVaSetValues ( _list,   // Remove any items currently in the list
		    XmNitems,     NULL,
		    XmNitemCount, 0,
		    NULL );
    
    // Execute the cmd, providing a function to be called when finished
    
    task->execute ( &WordCountWindow::taskFinishedCallback , 
		    ( void * ) this );
}
void WordCountWindow::taskFinishedCallback ( InterruptibleCmd *cmd, 
					     Boolean      interrupted,
					     void        *clientData)
{
    CountWordsCmd   *cwObj = ( CountWordsCmd * )   cmd;
    WordCountWindow *obj   = ( WordCountWindow * ) clientData;
    
    // If the user interrupted the task, just confirm the interrupt
    // Otherwise, call taskFinished() to process the results
    
    if ( interrupted )
	theInfoDialogManager->post ( "Interrupted!" );
    else
	obj->taskFinished ( cwObj );
    
    // Complete the operation by restoring a normal cursor and
    // freeing the InterruptibleCmd object
    
    obj->setNormalCursor();
    delete cwObj;
}
void WordCountWindow::taskFinished ( CountWordsCmd *cwObj )
{
    int       i;
    char      buf[100];
    XmString *xmstrList;
    
    // Report the number of unique words
    
    sprintf ( buf, "This file contains %d unique words.",
              cwObj->numWords());
    
    theInfoDialogManager->post ( buf );
    
    // Create an array of compound strings large
    // enough to hold the results
    
    xmstrList = new XmString[cwObj->numWords()];
    
    // Retrieve each word, format the results, and
    // add an entry to the compound string array 
    
    for ( i = 0; i < cwObj->numWords(); i++ )
    {
        char buf[BUFSIZ];
	
        sprintf ( buf, 
                  "%-5d %s",
                  cwObj->getCount ( i ), cwObj->getWord ( i ) );
        xmstrList[i] = XmStringCreateSimple ( buf );
    }
    
    // Display the array of compound strings in the list  
    XtVaSetValues ( _list,
		    XmNitems,     xmstrList,
		    XmNitemCount, cwObj->numWords(),
		    NULL );
    
    // The XmList widget makes its own copy of the compound strings
    // so free all local copies
    
    for ( i = 0; i < cwObj->numWords(); i++ )
	XmStringFree ( xmstrList[i] );
    
    delete []xmstrList;
}
void WordCountWindow::setBusyCursor()
{
    // Do nothing if the widget has not been realized
    
    if ( XtIsRealized ( _w ) )
    {
	// If this is the first time, create the busy cursor
	
	if ( !_busyCursor )
	    _busyCursor = XCreateFontCursor ( XtDisplay ( _w ),
					      XC_watch );
 	
	// Install the busy cursor for this windowÕs top-level shell
	
	XDefineCursor ( XtDisplay ( _w ), XtWindow ( _w ),
                        _busyCursor );
    }	
}
void WordCountWindow::setNormalCursor()
{
    // Do nothing if the widget has not been realized
    if ( XtIsRealized ( _w ) )
    {
	// If this is the first time, create the normal cursor
	
	if ( !_normalCursor )
	    _normalCursor = XCreateFontCursor ( XtDisplay ( _w ),
                                                XC_left_ptr );
	
	// Install the left pointer cursor as the normal
	// cursor for this windowÕs top-level shell
	
	XDefineCursor ( XtDisplay ( _w ),
			XtWindow ( _w ),
			_normalCursor );
	
    }
}



























































