/* Original code (c)2002 Paul Kershaw. All rights reserved. Code 
   is offered in the spirit of open source, and should not be modified or resold 
   for commercial purposes without the explicit prior consent of the author.
   Contact the author via brighn@yahoo.com */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class wordcount extends Applet 
implements ItemListener, TextListener {

    Checkbox chkNumber = new Checkbox("Count Numbers", true);
    Checkbox chkApo = new Checkbox("Ignore Apostrophes (can't is one word)", true);
    Checkbox chkHyphen = new Checkbox("Ignore Hyphens (two-way is one word)", true);
    Checkbox chkTags = new Checkbox(
    "Count HTML tags (<div align=center> is 3 words, not 0)");
    Checkbox chkAlt = new Checkbox("Ignore chars > 127", true);
    TextArea txtWords = new TextArea("", 10, 10, TextArea.SCROLLBARS_VERTICAL_ONLY);
    TextField txtCount = new TextField(30);
    Label lblCount = new Label("Word count: ");
    Label lblTitle = new Label("100words");
    GridBagLayout gridbag = new GridBagLayout();
    GridBagConstraints gridcons = new GridBagConstraints();
    Color cGreen = new Color(16, 128, 16);
    Color cYellow = new Color(128, 128, 16);

    public wordcount() {

        txtCount.setForeground(cGreen);
        setLayout(gridbag);
        buildConstraints(gridcons, 0, 0, 1, 1, 50, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.NORTHWEST;
        gridbag.setConstraints(lblTitle, gridcons);
        add(lblTitle);
        buildConstraints(gridcons, 1, 0, 1, 1, 40, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.EAST;
        gridbag.setConstraints(lblCount, gridcons);
        add(lblCount);
        buildConstraints(gridcons, 2, 0, 1, 1, 10, 15);
	gridcons.fill = GridBagConstraints.HORIZONTAL;
        gridcons.anchor = GridBagConstraints.CENTER;
        gridbag.setConstraints(txtCount, gridcons);
        add(txtCount);
        buildConstraints(gridcons, 0, 1, 3, 1, 50, 40);
	gridcons.fill = GridBagConstraints.BOTH;
        gridcons.anchor = GridBagConstraints.CENTER;
        gridbag.setConstraints(txtWords, gridcons);
        add(txtWords);
        buildConstraints(gridcons, 0, 2, 1, 1, 50, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(chkNumber, gridcons);
        add(chkNumber);
        buildConstraints(gridcons, 1, 2, 2, 1, 50, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(chkApo, gridcons);
        add(chkApo);
        buildConstraints(gridcons, 0, 3, 1, 1, 50, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(chkAlt, gridcons);
        add(chkAlt);
        buildConstraints(gridcons, 1, 3, 2, 1, 50, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(chkHyphen, gridcons);
        add(chkHyphen);
        buildConstraints(gridcons, 0, 4, 3, 1, 100, 15);
	gridcons.fill = GridBagConstraints.NONE;
        gridcons.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(chkTags, gridcons);
        add(chkTags);
        chkNumber.addItemListener(this);
	chkApo.addItemListener(this);
	chkHyphen.addItemListener(this);
        chkAlt.addItemListener(this);
        chkTags.addItemListener(this);
	txtWords.addTextListener(this); 
    }

    public void itemStateChanged(ItemEvent evt) {
        CountWords();
    }

    public void textValueChanged(TextEvent evt) {
        CountWords();
    }

    void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw,
    int gh, int wx, int wy) {
        gbc.gridx = gx;
        gbc.gridy = gy;
        gbc.gridwidth = gw;
        gbc.gridheight = gh;
        gbc.weightx = wx;
        gbc.weighty = wy;
    }

    public boolean IsAlphaNumeric(char InputString, boolean bAlpha, boolean 
    bNumber, boolean bApos, boolean bAlt) {
        int ascii;
        ascii = (int)InputString;
        if ((ascii >= 65 & ascii <= 90) || (ascii >= 97 & ascii <= 122))
            return bAlpha;
        else if (ascii >= 48 & ascii <= 57)
            return bNumber;
        else if (ascii == 39 || ascii == 96 || ascii == 145 || ascii == 146 ||
        ascii == 8216 || ascii == 8217)
            return bApos;
        else if (ascii > 127 & !(ascii == 8212 || ascii == 150 ||
        ascii == 8220 || ascii == 8221 || ascii == 147 || ascii == 148))
            return bAlt;
        else
            return false;
    }
    
    public void CountWords() {
        int iWordCount = 0;
        int asc;
        String sTextString;
        boolean bInTag = false;
        boolean bInWord = false;
        int I;
        sTextString = txtWords.getText();
        char sInQuest;
        for (I = 1; I <= sTextString.length(); I++) {
            sInQuest = sTextString.charAt(I - 1);
            asc = (int)sInQuest;
            if (bInTag == true) 
                if (asc == 62) 
                    bInTag = false;
                else {}
            else {
                if (IsAlphaNumeric(sInQuest, true, chkNumber.getState(), 	    
                false, chkAlt.getState())) {
                    if (bInWord == false) {
                        bInWord = true;
                        iWordCount++;
                    }
                }
                else if ((asc == 45 || asc == 150 || asc == 8211) 
                & chkHyphen.getState()) {
                    if (I < sTextString.length()) 
                        if ((int)sTextString.charAt(I) == 45) 
                            bInWord = false;
                }
                else if ((asc == 44 || asc == 46 || asc == 47) 
                & chkNumber.getState()) {
                    if ((I > 1) & (I < sTextString.length())) 
                        if (!(IsAlphaNumeric(sTextString.charAt(I - 2), false, 
	                true, false, false) & IsAlphaNumeric(sTextString.charAt(I),
                        false, true, false, false))) 
                            bInWord = false;
                }
                else if (IsAlphaNumeric(sInQuest, false, false, true, false) &
                chkApo.getState()) {
                    if (I < sTextString.length())  
                        if (!IsAlphaNumeric(sTextString.charAt(I), true,                                    chkNumber.getState(), false, chkAlt.getState())) 
                            bInWord = false;
                }
                else if (asc == 60 & !chkTags.getState()) {
                    bInTag = true;
                }
                else {
                    bInWord = false;
                }
            }
        }
        if (iWordCount < 80)
            txtCount.setForeground(cGreen);
        else if (iWordCount < 100)
            txtCount.setForeground(cYellow);
        else if (iWordCount > 100)
            txtCount.setForeground(Color.red);
        else
            txtCount.setForeground(Color.black);
        txtCount.setText(String.valueOf(iWordCount));            
        repaint();
    } 
}
