_EXAMINING THE POWERBASIC DEVELOPER KIT_ by Raymond J. Schneider Listing One $ERROR ALL InputFileName$=COMMAND$ CALL Mergea(InputFileName$) END 'Program to read files and isolate and count occurances of words ' file should have the extension .TXT however the program will ' attempt to read any file so long as the user insists. 'OUTLINE ' 1. READ A LINE -- Drop if it is a comment line (i.e preceeded with ') ' 2. PARSE INTO WORDS ' 3. ADD WORDS TO AN ARRAY ' 4. WHEN LAST LINE, GO BACK AND... ' 5. ANALYZE ARRAY FOR REPEATED OCCURANCES OF WORDS ' 6. INITIALLY BY SORTING THE CONTENTS OF THE ARRAY AND ' 7. THEN GOING THROUGH THE ARRAY AND ACCUMULATING REPEATED WORDS. ' 8. WHEN FINISHED PRINT OUT TOTAL WORDS AND DISTINCT WORDS TO SCREEN. ' 9. WRITE THE ALPHA FILE ,<# OCCURANCES> IN SORTED ALPHA ORDER '10. BUT THIS IS NOT AN ASSUMPTION ABOUT ALPHA FILES, THEY CAN BE IN ANY ' ORDER Alpha File line::= , '****************************************** '6/5/94 Added LinkBack: to drop comment lines so that input files could 'contain embedded comments without affecting the word counts '6/7/94 Dropping word print outs and adding a stats line at end of run '****************************************** SUB Mergea (InputFileName$) 'OPEN FILE $DYNAMIC MaxWords%=20000 MaxWordsOnLine%=500 DIM Word$(MaxWordsOnLine%) 'Assumes no more than MaxWordsOnLine% DIM AllWord$(MaxWords%), Vocab$(MaxWords%), VFreq%(MaxWords%) 'String Constants Required UpperCase$="ABCDEFGHIJKLMNOPQRSTUVWXYZ" LowerCase$="abcdefghijklmnopqrstuvwxyz" Punctuation$=",.:;?" Brackets$="<>{}[]()" Digits$="0123456789" 'Now create OutputFileName$ by parsing COMMAND$ FileRootName$=EXTRACT$(InputFileName$,".") '********* Note that this Output FileName creation may be Error Prone OutputFileName$=FileRootName$+".CNT" 'Ready to Open input file ON ERROR GOTO ErrorHandler OPEN InputFileName$ for input as #1 WordCount=0 'This is the overall wordcount for the Input File WHILE NOT EOF(1) '*******************Get a Line$ and Parse it into words ************ 'Read Line In LinkBack: LINE INPUT #1, Lin$ 'Parse Line Into Words 'First check line for apostrophe ... and skip lines with apostrophes IF LEFT$(Lin$,1)="'" THEN Goto LinkBack 'this drops comment lines 'Then Eliminate non-alpha characters replacing them with spaces REPLACE ANY ",.:;?<>{}[]()0123456789" WITH " " IN Lin$ Again: L=VERIFY(Lin$,UpperCase$+LowerCase$+" "+"'"+"-") 'note apostrophe so as to ' capture contractions 'Note this process will accept hyphens as a word and we want only 'internal hyphens -- see below at EXTRACT$ IF L=0 THEN Goto Success 'Otherwise L points to a non alpha non space character 'replace it with a space and continue MID$(Lin$,L)=" " Goto Again Success: Lin$=LTRIM$(Lin$) Lin$=RTRIM$(Lin$) 'Now spaces are stripped from front and back of string i=0 'Word Counter for # for Word(s) in Line$ KeepGoing: IF Len(Lin$)=0 THEN Goto Done Word$(i)=EXTRACT$(Lin$," ") 'Finds ith word but it may just be hypens Lin$=LTRIM$(Lin$,Word$(i)) 'Strips found word from string Lin$=LTRIM$(Lin$) 'Strips leading blacks Word$(i)=LTRIM$(Word$(i),ANY "-'") Word$(i)=RTRIM$(Word$(i),ANY "-'") IF Len(Word$(i))=0 THEN Goto KeepGoing i=i+1 'Increment counter Goto KeepGoing 'this will loop collecting the words in Lin$ Done: '****************** End of Line$ Parse ************************* 'i enters Done as the # of words collected indexed from 0 to n-1 'Note that this is done with a line not the whole file so now we have 'to add the words to the AllWord$() array 'Now we must put the indicated # of words in an array which is ' large enough to hold all the words in the file. '************** Assemble the Line$ words into the AllWord$ Array ******* For j=0+WordCount to i-1+WordCount AllWord$(j)= Word$(j-WordCount) Next j WordCount=WordCount + i 'Increments after assigning all Word$(s) from line WEND CLOSE #1 '*********************************Word Collection Complete ************ ' **** SORT the AllWord$(0 to WordCount-1) Array ********************** ARRAY SORT AllWord$(0) FOR WordCount,COLLATE UCASE IF WordCount>0 THEN GOTO Proceed Print "No Words Found" END Proceed: 'Variables are NumWords which counts the Vocabulary Additions AllWordPointer ' which indexes through the AllWord$() array WordCount which holds the number ' of words in the AllWord$() array indexed from 0 to WordCount-1 'Vocab$() the Vocabulary Array and VFreq%() the frequency array NumWords=0 AllWordPointer=0 'Initialize NumWords and AllWordPointer Vocab$(NumWords)=AllWord$(AllWordPointer) 'Initializes 1st word VFreq%(NumWords)=1 'One occurrance of the 1st word VocabAgain: AllWordPointer=AllWordPointer+1 'Now has # of words scanned IF UCASE$(AllWord$(AllWordPointer))=UCASE$(AllWord$(AllWordPointer-1)) THEN 'Word is repeated so VFreq%(NumWords)=VFreq%(NumWords)+1 IF AllWordPointer=WordCount-1 THEN Goto VDone Goto VocabAgain ELSE NumWords=NumWords+1 Vocab$(NumWords)=AllWord$(AllWordPointer) VFreq%(NumWords)=1 IF AllWordPointer=WordCount-1 THEN Goto VDone Goto VocabAgain END IF VDone: OPEN OutputFileName$ for output as #1 For j=0 to NumWords PRINT #1,UCASE$(Vocab$(j));",";STR$(VFreq%(j)) next j CLOSE #1 Print "Total Number of Words= ";WordCount Print "Number of Different Words is= ";NumWords+1 END SUB '******************************************************** ' SUBROUTINES '******************************************************** ErrorHandler: E=ERRTEST IF E=53 then Print "Input File Not Found":END Print "Error";E;" Occurred" Listing Two $ERROR ALL 'Fun With Words -- an example of the conversion of DOS BASIC programs to ' Windows using the PowerBASIC Development Kit -- Copyright R.Schneider 1994 $INCLUDE "PB3DV.PB3" CALL InitExecution( "FWW", RESETAPP% ) CALL ReadErrorNumber( DVError% ) IF DVError% > 0 THEN END '***** 'Creation of a Session, required to use Menus. '***** Txt$ = "Fun With Words" CALL OpenSession( Txt$, 0, 0, 639, 479, hSession% ) 'Open Menu Resource MenuResName$="WFMENU.RC" CALL LoadResources(MenuResName$,hMenuRes%) MenuName$="MainMenu" CALL OpenMenuRes(hMenuRes%,0,MenuName$,hMenu%) ' Setting the new Menu in the current Session. The Menu is now ' displayed, and it starts emitting messages. CALL SetMenu(hMenu%) 'Load MainDialog Box ResName$="wfmndlg.rc" CALL LoadResources(ResName$,hDlg%) DlgName$="MAINDLG" CALL OpenDlgRes(hDlg%,DlgName$,hWnd%) CALL SetWindowModal(hWnd%,NOTMODAL%) 'Open Resources in Main Dialog Box hEditBox%=101 CALL GetDlgItem(hWnd%,hEditBox%,hEdit%) 'hEdit% set by Windows hListBox%=103 CALL GetDlgItem(hWnd%,hListBox%,hList%) hGOButton%=107 CALL GetDlgItem(hWnd%,hGOButton%,hGO%) hEndMergeButton%=110 CALL GetDlgItem(hWnd%,hEndMergeButton%,hEndMerge%) hMergeFileEdit%=108 CALL GetDlgItem(hWnd%,hMergeFileEdit%,hMergeEdit%) hMergeListBox%=109 CALL GetDlgItem(hWnd%,hMergeListBox%,hMergeList%) hOKButton%=111 CALL GetDlgItem(hWnd%,hOKButton%,hOK%) ' Event Loop DIM XParam%(4) GetMsg% = 1 WHILE GetMsg% <> 0 CALL GetMessage( hMsgWnd%, Msg%, wP%, XCursor%,_YCursor%, XParam%(1), Cmd$) ' When no message is available, GetMessage returns a Msg=0 Message. IF Msg% <> 0 THEN ' The Msg%=WMCOMMAND% messages come from the Menu. ' wP% contains the ID of the clicked Item. IF Msg% = WMCOMMAND% THEN IF wP%= 100 THEN 'Menu Count was selected Flags&=0 Filter$="Filter 1 $.TXT $.BAK |*.TXT *.BAK | Filter 2 $.C $.DOC $.BAK|*.C *.DOC *.BAK" CustomFilter$="CFilter 1 $.TXT $.BAK |*.TXT *.BAK" FileTitle$="" Title$="Get ASCII Test File to Count" FileName$=SPACE$(32) Directory$="C\" DExt$="" CALL GetOpenFileName(0,Filter$,CustomFilter$,0,_ FileName$,64,_ FileTitle$,Directory$,Title$,Flags&,_ FileOffset%,FileExt%,DExt$,xError&) CALL ReadErrorNumber(ErrNum%) IF ErrNum%=0 THEN 'Load Edit Box and Read .CNT file into ListBox DistinctWords%=0 CALL Count(FileName$,hEdit%,OutFileName$,DistinctWords%) 'Now load ListBox CALL ResetListBox(hList%) Open OutFileName$ for input as #1 lnum%=0 for num%=1 to DistinctWords% Line Input #1, WordF$ CALL AddStringListBox(hList%,WordF$,lnum%) next num% close #1 END IF IF ErrNum%=3 THEN END IF 'do nothing END IF 'menu 100 COUNT IF wP%=200 THEN ' Sort File Program Calls etc. Need to check for sort ' variable /F or /A and check that edit box has a file in it. IF OutFileName$<>"" THEN Path$=OutFileName$ CALL SetSelEdit(hEdit%,0,32)'Don-t like absolute #s CALL ReplaceSelEdit(hEdit%,Path$) CALL SortIt(OutFileName$,DWords%) CALL ResetListBox(hList%) Open OutFileName$ for input as #1 lnum%=0 FOR num%=1 to DWords% Line Input #1, WordF$ CALL AddStringListBox(hList%,WordF$,lnum%) NEXT num% CLOSE #1 END IF 'OutFileName END IF 'menu 200 SORT IF wP%=300 THEN 'Statistics Program Print OutFileName$ 'Note should check EditBox for contents and use that! IF OutFileName$="" THEN ELSE CALL Statistics(OutFileName$) END IF 'OutFileName END IF 'menu 300 STATISTICS IF wP%=400 THEN 'Merge Code CALL SetWindowModal(hWnd%,TASKMODAL%) CALL ResetListBox(hList%) CALL ResetListBox(hMergeList%) CALL SetSelEdit(hMergeEdit%,0,32) 'Set Edit Box to Default Value, *.CNT Path$="*.CNT" CALL SetSelEdit(hEdit%,0,32) CALL ReplaceSelEdit(hEdit%,Path$) 'Get directory based on DefaultValue CALL AddDirListBox(hList%,Path$,DDLREADWRITE%) 'Setup Local Event Loop Cmd$=SPACE$(32) DIM Xp%(4) GetLocalMsg%=1 WHILE GetLocalMsg%<>0 Call GetMessage(hLMsgWnd%, LMsg%, LwP%, Xc%, Yc%, Xp%(1), Cmd$) IF LMsg%=0 THEN CALL ReleaseTimeSlice ELSE 'LMsg% is not equal to zero IF LMsg%=WMCOMMAND% THEN IF LwP%=hEndMergeButton% THEN GetLocalMsg%=0 END IF 'hEndMergeButton IF LwP%=hListBox% THEN Notification%=Xp%(2) IF Notification%=LBNDBLCLK% THEN 'Get the selected item from ListBox 'first get # lines in list box CALL StatusListBox(hList%,l%,top%,w%,height%, _MaxWidth%,Index0%,NbLines%, _SelectedLine%,selcnt%) 'SelectedLine% is the index of the selected ' line or it is negative ThisLine$=SPACE$(32) CALL GetTextListBox(hList%,SelectedLine%, ThisLine$,32) Print ThisLine$ 'then look for selected line. put selected line 'in merge listbox. get # of items in listbox CALL StatusListBox(hMergeList%,l%,top%,w%, height%,_MaxWidth%,Index0%, NbLines%,_SelectedLine%,selcnt%) IF NbLines%<5 THEN CALL AddStringListBox(hMergeList%, ThisLine$,Rank%) Print "Got to NbLine%<5 IF Statement" ELSE 'List Box has 5 items in it now! No more 'will be accepted. Put up a message box. Txt$ = "Only 5 files can be merged at a time!" Caption$ = "Informative Message" CALL MessageBox( 0, Txt$, Caption$, MBOK% OR MBTASKMODAL%, Code%) END IF 'NbLines<5 END IF 'Notification END IF 'hListBox IF LwP%=hGOButton% THEN 'Enter a Merge File Name Size%=MAXSTR% MergeFileName$=SPACE$(MAXSTR%) CALL GetCTLText(hMergeEdit%, MergeFileName$,Size%) MergeFileName$=RTRIM$(MergeFileName$) MergeFileName$=LTRIM$(MergeFileName$) IF MergeFileName$="" THEN GOTO NoGood CALL StatusListBox(hMergeList%,l%,top%,w%, height%,_MaxWidth%,Index0%, NbLines%,_SelectedLine%,selcnt%) CtlString$="" for i%=Index0% to Index0%+NbLines%-1 Size%=MAXSTR% Text$=SPACE$(MAXSTR%) CALL GetTextListBox(hMergeList%,i%,Text$,Size%) Text$=RTRIM$(Text$) CtlString$=CtlString$+" "+Text$ next i% CtlString$=CtlString$+" /"+MergeFileName$ CALL Merge(CtlString$) Print CtlString$ NoGood: END IF 'hGOButton% IF LwP%=hMergeListBox% THEN 'if doubleclick on filename. then delete filename 'if no filename, then do nothing Notification%=Xp%(2) IF Notification%=LBNDBLCLK% THEN 'Get the selected item from ListBox 'first get # lines in list box CALL StatusListBox(hMergeList%,l%,top%,w%, height%,_MaxWidth%,Index0%, NbLines%,_SelectedLine%,selcnt%) 'SelectedLine% is the index of the selected 'line or it is negative ThisLine$=SPACE$(32) CALL GetTextListBox(hMergeList%,SelectedLine%, ThisLine$,32) Print ThisLine$ 'then look for selected line 'delete the selected line in merge list box IF ThisLine$ <> "" THEN CALL DeleteStringListBox(hMergeList%, SelectedLine%) END IF 'ThisLIne END IF 'Notification END IF 'hMergeListBox -- to delete entries IF LwP%=hOKButton% THEN 'a file name has been entered ' in the edit box with wildcards Size%=MAXSTR% EditFileName$=SPACE$(MAXSTR%) CALL GetCTLText(hEdit%,EditFileName$,Size%) PRINT EditFileName$ 'reset the edit box and then CALL ResetListBox(hList%) 'add the directory or file name CALL AddDirListBox(hList%,EditFileName$, DDLREADWRITE%) END IF 'hOKButtion% END IF 'WMCOMMAND END IF 'LMsg%=0 WEND 'Local Event Loop 'Clear Everything CALL SetWindowModal(hWnd%,NOTMODAL%) CALL SetFocus(hSession%) CALL ResetListBox(hList%) CALL ResetListBox(hMergeList%) CALL SetCTLText(hEdit%,SPACE$(32)) CALL SetCTLText(hMergeEdit%,SPACE$(32)) END IF 'Merge Menu Item #400 IF wP%=500 THEN Msg%=WMSYSCOMMAND%:wP%=SCCLOSE% IF wP%=600 THEN 'Get an alphafile name and display the file in listbox-- ' use same strategy as with the Count menu item without ' calling the count function Flags&=0 Filter$="Filter 1 $.CNT $.BNT |*.CNT *.BNT" CustomFilter$="CFilter 1 $.CNT $.BNT |*.CNT *.BNT" FileTitle$="" Title$="Get Alpha File" FileName$=SPACE$(32) Directory$="C\" DExt$="" CALL GetOpenFileName(0,Filter$,CustomFilter$,0,_ FileName$,64,_ FileTitle$,Directory$,Title$,Flags&,_ FileOffset%,FileExt%,DExt$,xError&) CALL ReadErrorNumber(ErrNum%) IF ErrNum%=0 THEN 'Load Edit Box and Read .CNT file into ListBox Path$=FileName$ CALL SetSelEdit(hEdit%,0,32)'Don-t like absolute #s CALL ReplaceSelEdit(hEdit%,Path$) OPEN FileName$ for INPUT as #1 LinCount%=0 CALL ResetListBox(hList%) WHILE NOT EOF(1) LINE INPUT #1, Lin$ CALL AddStringListBox(hList%,Lin$,lnum%) LinCount%=LinCount% + 1 WEND CLOSE #1 OutFileName$=FileName$ CALL Statistics(OutFileName$) END IF IF ErrNum%=3 THEN END IF 'do nothing END IF 'Menu 600 GET END IF 'Msg WMCOMMAND ' The Msg=WMSYSCOMMAND messages come from the System Menu of ' the current Session. wP contains the ID of the clicked Item. ' Event Loop ends when System Menu CLOSE Item is activated. IF Msg% = WMSYSCOMMAND% THEN IF wP% = SCCLOSE% THEN ' Opening a Message Box to ask the user if he really ' wants to end the program. Txt$ = "Do you really want to end Fun With Words?" Caption$ = "Goodbye Message" CALL MessageBox( 0, Txt$, Caption$, MBYESNO% OR MBTASKMODAL%, Code%) ' Code receives a value related to the user answer: ' IDYES%, or IDNO% in this case. IF Code% = IDYES% THEN GetMsg% = 0 END IF 'SCCLOSE END IF 'WMSYSCOMMAND ELSE ' If no message is available, the application releases its Time ' Slice to let other applications run. CALL ReleaseTimeSlice END IF WEND 'Main Event Loop CALL EndExecution END '******************* EXTERNAL SUBROUTINES *************** '***** Slightly Modified Original DOS Code ************** $INCLUDE "merge.bas" $INCLUDE "cnt.bas" $INCLUDE "sortwin.bas" $INCLUDE "statist.bas" '******************************************************** ' SUBROUTINES '******************************************************** ErrorHandler: E=ERRTEST 'IF E=53 then Print "Input File Not Found":END Print "Error";E;" Occurred" Txt$ = "Error="+STR$(E)+" Occurred at Line "+STR$(ERL) Caption$ = "Error Box" CALL MessageBox( 0, Txt$, Caption$,MBYESNO% OR MBTASKMODAL%, Code%) ' Code receives a value related to the user answer: ' IDYES%, or IDNO% in this case. IF Code% = IDYES% THEN END END