Click! 2.03 Source Code Reformatter
Release 2.03
Cleaned up documentation.
---
Added five directives:
// options are YES, NO
// deflate mode removes spaces
// following ({[ and preceding ]})
DEFLATE_(=NO
DEFLATE_{=NO
DEFLATE_[=NO
// following , (comma)
DEFLATE_,=NO
// both sides of +
DEFLATE_+=NO
Many people have asked for this. If you turn any of these on, there is
a slight speed impact.
Release 2.02
It was brought to my attention that Click! broke this line of code.
cBlock := { || if( !aX[dict->(recno())][1]==NIL, {4,5}, {1,2} ) }
I found two problems.
You could not turn off the ][ conversion feature because of a typo in
the code. This is fixed.
Click! thinks that the second array reference, [1], is a string
delimited with [ and ]. This caused it to be treated as a single literal
instead of 3 parts of the line.
To fix this bad behaviour, I modified the ][ conversion routine to copy
the remainder of the 'bracketed text' to the same cell as the ,.
Release 2.01
Mods 1 and 2 were by Douglas Woodrow <doug@acuity-ltd.demon.co.uk>
1) the "LIKEINFILE" setting does not work for commands (it uses > UPPER
instead)
This was caused by the c version of function no_ast(): it works
directly on the contents of the variable passed (i.e. by
reference), and hence always leaves the aCommands array with upper
case copies of the commands. I have fixed this by simply
re-instating your original no_ast() function in cmd_list.prg, so
no_ast.obj no longer needs to be linked in. This has very
negligible impact on speed of operation when dealing with lots of
source code, as no_ast() is only called when processing the .ini
file at startup. I have not included my version of the build
files, as I had to change them for my development environment (and
dbfcdx driver instead of six etc.)
2) the setting specified for functions is always ignored (it uses
the setting specified for commands instead, and this time
LIKEINFILE *does* work).
This one was simply caused by using variable cComCase instead of
cFunCase in the relevant sections of click.prg.
Mod 3 was by "Peter Townsend" <cephas@tpgi.com.au>
3) Phil, thanks for the Click! source. I was looking at
FILNPATH.PRG when I found a UDF (UnDocumented
Feature). As written, fileinpath will only find a
file in the nominated path if the file is in the
directory specified in the last portion of the path.
So if:
path == "c:\windows;c:\windows\command"
? fileinpath( "win.com" ) => "win.com"
but if:
path == "c:\windows\command;c:\windows"
? fileinpath( "win.com" ) => "c:\windows\win.com"
I've attached a modified version so you can see what I
mean.
Release 2.00
The general release version of Click! for OO code.
Release 1.13b4
Modified the screen writing code to move the divider bar between the top
and bottom windows to the center, regardless of the screen resolution.
Now, Click looks great in larger screen resolutions.
---
Linked with Blinker 5. Click! is now compressed with Blinker file
compression instead of WWPACK.EXE, allowing me to link Click! in
protected mode.
---
Version 1.13b3 formatted classes with an extra empty line, like:
Class Foo
Method init
EndClass
The extra empty line is now removed.
Class Foo
Method init
EndClass
---
Click! previously formatted a method in a class without any scope
modifier like:
Class Foo
Method init
EndClass
It is now only indented a single level.
Class Foo
Method init
EndClass
Release 1.13b3
Click! did not know how to deal with something like...
@:bar()
...and incorrectly formatted it as...
@ :bar()
This is fixed.
---
Renamed MY_TABLE_OPENING_FUNCTION to MY_TABLE_FUNCTION in CLICK.INI.
--
Added a new Click! entry similar to MY_TABLE_FUNCTION, except for index
functions.
The new entry is named MY_INDEX_FUNCTION, and can contain several
functions delimited by |, just like the table group.
---
Previously, Click! compared MY_TABLE_FUNCTION, the customizable table
function list to the first word on each line. Now, Click! compares the
customizable list to every word on the line.
Using delimited settings like these... (use | to add more functions)
MY_TABLE_FUNCTION=D_OPEN|D_CLOSE|D_ZAP
MY_INDEX_FUNCTION=D_INDEX|D_ORDER
...and code like this...
if d_close( 'myarea' )
endif
if dbusearea( 'another' )
index on ( temp ) to stuff tag more
endif
d_zap( 'myfile' )
do while d_open( cSomeFile )
enddo
if dbcreateind()
endif
if d_order( csomealias ) == 12
endif
if d_index( cSomeFile )
endif
...Click! will detect correctly, and add to the Files or Indexes list...
*+ Tables: if d_close( 'myarea' )
*+ if dbusearea( 'another' )
*+ d_zap( 'myfile' )
*+ do while d_open( cSomeFile )
*+
*+ Indexes: index on ( temp ) to stuff tag more
*+ if dbcreateind()
*+ if d_order( csomealias ) == 12
*+ if d_index( cSomeFile )
---
Previously, if you set INDENT_FUNCTION=YES, Click! would leave the final
return dangling indented, instead of deindented.
This is fixed. The last return is identified by a read ahead scheme. If
you use this feature, and find a 'last return' which is dangling, I need
to see the code following that return.
---
Added a new CLICK.INI directive, INDENT_LOCALS=NO, which overrides
indenting of any line starting with LOCA PRIV MEMV STAT PUBL FIEL if
INDENT_FUNCTION=YES.
---
if() reported as an <unresolved function> in the function table.
Fixed.
---
a[ 1 ][ 1 ][ 1 ]
used to come out as:
a[ 1 ] [ 1 ] [ 1 ]
Fixed. Spaces are no longer inserted.
A new option is added in CLICK.INI to convert it to the other style:
CONVERT_][_TO_,=YES
Converts:
a[ 1 ][ 1 ][ 1 ]
to
a[ 1, 1, 1 ]
---
CREATE CLASS was not recognized as CLASS.
Fixed.
---
END CLASS was not always found, but ENDCLASS always worked.
Fixed.
Release 1.13b2
Modified MY_TABLE_OPENING_FUNCTION to handle multiple functions.
Now, you can declare as many file opening, closing and modifying
functions as you need, simply by delimiting each one with the pipe |.
MY_TABLE_OPENING_FUNCTION=D_OPEN|D_CLOSE|D_ZAP
---
Fixed CONVERT_*_TO_// so it would leave a space after the //
Otherwise:
*********
converted to
//*******
and the second and third characters looked like /*, turning on block
commenting.
Now, it converts to
// *******
---
Modified Click! so that it understands END CLASS as well as ENDCLASS, for
Class(y) support.
---
Added END CLASS to Click.ini
---
Added CLEAN_UP_INCLUDES=YES to CLICK.INI.
This Determines if #includes will be beautified. Beautification consists
of lower case #define, converting the delimiters to "" and upper case
file name.
#INCLUDE 'somefile.CH'
#include "nextFILE.CH"
becomes
#include "SOMEFILE.CH"
#include "NEXTFILE.CH"
Prior to this version, you had no control over this clean up and it
defaulted to YES.
Release 1.13b1
Click! begins it's ascent into object oriented awareness!
----
Not that it makes any difference, but I added:
SET EPOCH TO YEAR( DATE() ) - 50
Better safe than sorry.
----
Added ALIGN_CLASS_IN_THE_ALIGNER to CLICK.INI.
---
Added METHOD to the declaration buster
---
Added METHOD and CLASS METHOD to Click.ini, and modified Click! to treat
them like FUNCTION and PROCEDURE, including header creation.
---
Added METHOD, CLASS, VAR, ENDCLASS, INIT, EXIT to Click.ini
---
Click! now removes spaces before : when it's appropriate. OO stuff now
looks like:
::windowStack[1]:setFrameState( XBPDLG_FRAMESTAT_NORMALIZED )
oSubMenu := XbpMenu():new( oMenu )
instead of:
::windowStack[1] :setFrameState( XBPDLG_FRAMESTAT_NORMALIZED )
oSubMenu := XbpMenu() :new( oMenu )
---
Click! had a problem converting this:
store chr( toets ) to x
This is fixed. It now converts to:
x := chr( toets )
---
Fixed the identification and headers on INIT PROCEDURE and EXIT PROCEDURE.
---
There was a problem with the declaration buster when avoiding
declaration lines with the key words ALL, NEXT, WHILE and FOR which
would avoid the breaking up the line even if any of those words were
subparts of variables.
Now, Click! scans the parsed array for exact matches. This allows lines
like:
local INSCREEN,XWIDTH,XLENGTH,XSHALLOW,XDEEP,XGALLONS,AVEDEPTH,mult
to be broken up instead of avoided. (XGALLONS contains ALL)
Release 1.12
( From CLICK.INI )
// Convert * to // when && is starting a line
CONVERT_*_TO_//=YES
This will convert * comments to // comments
* this is a comment
becomes
// this is a comment
---
Fixed problem with # directives being manipulated.
Now, # directives are not processed at all.
---
Fixed problem with macro expansion while using a 'restore from' command.
Now, any RESTORE FROM command receives simple spacing. The list of
Clipper commands which obey simple spacing are as follows:
USE
COPY
SAVE
ERASE
CREATE
COPY TO
RESTORE
SET COLO
SET ORDE
COPY FILE
DELETE FILE
Release 1.11
REPLACE ALL/NEXT/WHILE/FOR lines with multiple changes were being
converted to broken code.
The problem was in the Declaration Buster. The Declaration Buster is now
able to distinguish a compound command, and entirely avoid it. It now
avoids converting any REPLACE containing ALL, NEXT, WHILE or FOR.
What was happening was:
replace all x with y, w with z
was processed by Pass 1 into:
replace all x with y
replace w with z
and then in pass 2:
replace all x with y
field->w := z
Fixed by avoidance.
---
There was a problem with alignment and recognition of @ SAY GET lines
when the command was followed by a value in parenthesis, such as:
@ 7, 25 get rdbf1 picture "@!" color (cCGetColor)
@ 9, 25 get rprefunc picture "@!" valid ChkPreFunc() color (cCGetColor)
@ 10, 25 get rpostfunc picture "@!" valid MakeStru() color (cCGetColor)
@ 11, 25 get reptype picture "@!" valid REP->reptype$"RP" color (cCGetColor)
@ 12, 25 get custom picture "@!" valid REP->custom$"YN" color (cCGetColor)
Click! failed to recognize the COLOR clause because it appeared to be a
function. Click! now uses 'SAY |GET |PICT|COLO|WHEN|RANG|VALI' to detect
@ SAY GET clauses.
This also caused type 3 @ SAY GET output to fail compile due to a missing ;
This is repaired.
---
Due to a problem with IF FUNCTION/COMMAND detection combined with a
problem with the line continue flag, the following code would cause a
control underflow because Click! was not breaking the line up correctly.
if empty(detail);delete;result:=1;endif
This was fixed but not documented in 1.10
Release 1.10
IF lPrint := MESSYN( 'DESTINO', 'IMPRESORA', 'PANTALLA' )
The IF was being treated wrong, and was being combined with the lPrint.
( the part of Click! that aligns := was fooled )
This is fixed.
---
Breaking of multipart lines with continue (;) into individual lines was
broken. This is fixed.
---
I fixed some code in Click! that locked the Declaration Buster into a
continuous loop under certain conditions. This is fixed.
---
DBCREATE() alignment was broken. It is fixed.
Release 1.09
1.09 makes a change to the way that the conversion of old style function
calls are done. After creating 1.08, I was informed that conversion of
DO/WITH function calls to formal function/parameters changes the way the
variables are passed. DO/WITH passes all variables by reference, but
function calls do not. Now, the conversion places an @ in front of each
parameter. Sometimes this will break the code because the @ sign is an
illegal operator. See below for what to do if you get C2009 errors..
This now defaults to NO
CONVERT_OLD_STYLE_FUNCTIONS=NO
With this set to YES, ...
do test
do test // a comment
do test with a, c, somevar
do test with a, c, somevar // and a comment
... becomes ...
test()
test() // a comment
test( @a, @c, @somevar )
test( @a, @c, @somevar ) // and a comment
... and a blazing warning screen appears when Click! is set to run with
this option turned on, because of the potential of compiler error C2009
occuring because of the pass by reference on all parameters.
If you get C2009 compiler errors after using this option, remove the
offending @ in the parameter list and recompile.
Release 1.08
Click! now does a few things with # directives.
1. If a # is followed by a space, the space is removed
... and only for #include ...
2. The word INCLUDE is converted to lower case
3. The filename is converted to upper case
4. The delimiters on the filename are changed to " if they are '
So...
# INCLUDE 'filename.ch'
... becomes ...
#include "FILENAME.CH"
---
The conversion of line elements for alignment of := was too aggressive.
I changed it so that it only tries to align := on lines that start with
variables. This works much better.
---
Optimized a few more places in the code in an attempt to squeeze every
ounce of speed out of Click!. Found a couple of pretty good speed
improvements.
---
The Declaration Buster can now convert older style code to use the
incremental operators ++, --, +=, -=, /=, *= and ^=
CONVERT_TO_INCREMENTOR=YES
Code style like:
s = s + 1
s := s - 1
x := x + ( anyvar + anyfunc() )
test=test-1// with a comment
q = q * 14
... now converts to ...
s ++
s --
x += ( anyvar + anyfunc() )
test -- // with a comment
q *= 14
It will not convert more complex forms, like:
x[ 2 ] = x[ 2 ] + 1
---
The Declaration Buster can now convert the old style function calls to
the new style. The CLICK.INI directive which controls this is:
CONVERT_OLD_STYLE_FUNCTIONS=YES (defaults to NO)
With this set to YES, ...
do test
do test // a comment
do test with a, c, somevar
do test with a, c, somevar // and a comment
... becomes ...
test()
test() // a comment
test( a, c, somevar )
test( a, c, somevar ) // and a comment
Release 1.07
There is a new option in The Aligner which will eliminate duplicate
empty lines. This allows me to do nicer formatting around function and
source headers and footers, and removes extra empty lines from your
source.
REMOVE_DUPLICATE_EMPTY_LINES=YES
---
The Aligner was previously only able to align := when it was the third
element on a line. Now, it can handle more complex alignments, so ...
y[ 2,MANIFEST ]='Hello'
x := 11
z[function(),variable]='somevalue'
...becomes...
y[ 2, MANIFEST ] := 'Hello'
x := 11
z[ function(), variable ] := 'somevalue'
---
On the second line, the first = sign was being converted to :=, but that
was improper, since it is a continued line. This is fixed.
if CFIRSTCHAR = chr( 10 ) .or. CFIRSTCHAR = chr( 12 ) .or. ;
CFIRSTCHAR = chr( 13 ) .or. CFIRSTCHAR = chr( 26 )
CLINE := substr( CLINE, 2 )
endif
---
Someone was complaining that comments were lost on variable declarations.
I can't find anything wrong. This...
local x := 1 // this is a comment
local y // this is also a comment
local z, w // two variables on a single line
... comes out looking like ...
local x := 1 // this is a comment
local y // this is also a comment
local z // two variables on a single line
local w // two variables on a single line
If anyone can provide a specific example which breaks, please do.
---
The declaration buster was ltrim()ing all lines between the text and
endtext commands.
This is corrected.
The declaration buster was making #include into # include
This is corrected.
(I don't think that either of these were a problem outside of creating 1.07)
---
Because of the while on the continued line, this used to make a mess.
if mfilter == TRUE
copy to ( cTempFile ) for eval( miofield2 ) .and. ;
eval( mfiltfield ) ;
while eval( use_dates )
else
copy to ( cTempFile ) for eval( miofield2 ) ;
while eval( use_dates )
endif
Now, control structure identifiers are ignored if they are on a
continued line.
---
The part of Click! which broke the .not. from comp_elem was broken.
if line_disp = SUBSTR(linesrch[i],2,19) .and. .not.comp_elem
endif
This parses correctly now. This was particularly bad, since it sent
Click! to the error exit.
---
Click! now correctly removes the space between ! and = when it is the
first element of a continued line.
do while x == 1 .and. y ;
!= 7
no longer creates
do while x == 1 .and. y ;
! = 7
which caused a compiler error.
Release 1.06
Removed from CLICK.INI...
TABS2SPACES=3
SMART_ALIGN_ASSIGN=14
SMART_ALIGN_DECLARE=20
The Aligner makes these unnecessary, so I removed the older code to
speed up the process a little.
---
There was a problem with Click! removing comments on declarations with
no assignment. (only in declaration buster) It is fixed.
---
Click! was case sensitive on TABLE and INDEX references. Now it is not.
---
Click! will allow you to designate a function name which you use to open
your files, so the Table tracking routine can work on highly customized
code.
// Use this if you have a dictionary function that opens files
// This will allow Click! to track table openings via your function
MY_TABLE_OPENING_FUNCTION=D_OPEN
Release 1.05
Added some C code to speed up the array sort during startup.
---
Click! can now incorporate a Table and Index cross reference into each
source module header, and can create the list of all modules using files
and indexes.
The following CLICK.INI entries control this behaviour.
TABLE_XREF_FILE=TBL_CROS.TXT
// options are YES, NO
// please note that you must set ADD_CLICK_HEADERS=YES
TABLE_XREF_INTO_SOURCE=YES
// options are YES, NO
// please note that you must set ADD_CLICK_HEADERS=YES
INDEX_XREF_INTO_SOURCE=YES
---
Click! now recognizes when a Clipper FUNCTION or COMMAND is being used
as something other than a function or command.
New rules are:
If a Clipper function is not followed by a (, then it not evaluated as a
Clipper function.
/*
I suppose that means I should convert:
DO SOMEFUNC with a, b, c
...to...
SOMEFUNC( a, b, c )
...in PASS 1
*/
If a Clipper command is found within () or {} or [], then it not
evaluated as a Clipper command.
This will allow code like ...
#define TOP a[1]
#define LEFT a[2]
#define BOTTOM a[3]
#define RIGHT a[4]
aadd(envSTAck_, { row(), col(), setcursor(curs_size), setcolor(newcolor), ;
if(valtype(coords) == "A", { TOP, LEFT, BOTTOM, RIGHT, ;
savescreen(TOP, LEFT, BOTTOM, RIGHT) }, NIL) } )
... to continue to work, even though I find using reserved words as
variables or manifest constants an undesirable style ...
Also, prequalifying what can't be a function or a command has led to a
significant reduction in processing time!
---
The Aligner now recognize and align arrays destined for DBCREATE(),
so that code like...
somevar := {{ 'XXX', 'C', 123, 0 },;
{ 'YYYYY', 'C', 99, 0 },;
{'Z','D',8,0},;
{ 'AFIELD', 'C', 2, 0 } }
... ends up looking like ...
somevar := { { 'XXX' , 'C', 123, 0 }, ;
{ 'YYYYY' , 'C', 99, 0 }, ;
{ 'Z' , 'D', 8, 0 }, ;
{ 'AFIELD', 'C', 2, 0 } }
---
Click! now understands when [ and ] are being used as string delimiters.
So...
x := [asdfasdf'"asdf]
? [this works'"]
x := somefunc( [this works, too] )
...will all be recognized as a string being delimited by [].
---
Click! can now convert && to // when found as a comment marker.
( in CLICK.INI )
CONVERT_&&_TO_//=YES
So...
if x && test
...becomes...
if x // test
...but...
if x &&&&&&&& test
...becomes...
if x //&&&&&& test
---
STORE conversion modified to eliminate this...
for L_count = 1 to 5
store " " to Em_Benefit[L_count,1]
store 0.00 to Em_Benefit[L_count,2]
next
from becoming ...
for L_count = 1 to 5
Em_Benefit[ L_count := 1 ] := " "
Em_Benefit[ L_count := 2 ] := 0.00
next
Now, it correctly identifies internal commas and processes like:
for L_count = 1 to 5
Em_Benefit[ L_count, 1 ] := " "
Em_Benefit[ L_count, 2 ] := 0.00
next
---
Click! has an option to end it's run by returning to DOS with the
original screen and color setting, pausing for a keystroke to end the
run.
RESTORE_SCREEN_ON_EXIT=YES
Release 1.04
Commands with a length of 4 or less were not being recognized correctly.
This is fixed.
index on DEPARTMENT to( TEMPRECP )
now processes into:
index on DEPARTMENT to ( TEMPRECP )
---
Added the ability to force recreation of the CLICK.DBF and CLICK.NSX
files. Any of the following methods...
CLICK /REBUILD <Enter>
CLICK /UPDATE <Enter>
CLICK CLICK.DBF <Enter>
...will rebuild these two files ( according to the master CLICK.INI )
and quit.
---
Added more options for scanning libraries for function cross reference.
1: You specify that you want to use the LIB= environment path. (this is
the way it worked before.)
2: You specify a path or set of paths, just like the environment, except
in CLICK.INI.
3: You specify that you want CLICK.EXE to search your hard drive for
every library in every directory, even including multiple drives and
network drives. This one might take longer, but creates the ultimate
cross reference.
// options are ENVIRONMENT, (specified path), DRIVES
//MAKE_CLICK_DBF_FROM=ENVIRONMENT
//MAKE_CLICK_DBF_FROM=C:\CLIPPER5\LIB;E:\GRUMP52\LIB;F:\FUNCKY\LIB
MAKE_CLICK_DBF_FROM=DRIVES
---
If you select DRIVES in the above step, you can limit how deep the
recursion level will go with...
RECURSION_LIMIT=N
... means that it will only recurse the first N-1 levels and will skip
all N level directories and below.
---
If you created a custom CLICK.INI file and placed it in a local
directory, CLICK.EXE wanted to build another copy of CLICK.DBF and
CLICK.NSX. This is corrected, so no matter how many copies of CLICK.INI
you have, there is only one master function to library cross reference.
---
Added ability to turn off the DBCREATE( aligner and leave other sections
of The Aligner working. From CLICK.INI...
ALIGN_DBCREATE_IN_THE_ALIGNER=YES
---
Tightened up the code which decides if a DBCREATE follows a prescribed
pattern, and avoids alignment if this pattern is not found.
The Aligner will now only align DBCREATE() arrays if they follow the
format shown here.
So, this:
dbcreate( 'filename.dbf', { { 'xxxxx', 'C', 23, 0 }, ;
{ 'yyy', 'D', 8, 0 }, ;
{ 'yy', 'C', 8, 0 }, ;
{ 'yuu', 'D', 8, 0 }, ;
{ 'yijiiiyy', 'N', 9, 2 }, ;
{ 'yhhfyy', 'D', 8, 0 } } )
ends up looking like this:
dbcreate( 'FILENAME.DBF', { { 'XXXXX' , 'C', 23, 0 }, ;
{ 'YYY' , 'D', 8, 0 }, ;
{ 'YY' , 'C', 8, 0 }, ;
{ 'YUU' , 'D', 8, 0 }, ;
{ 'YIJIIIYY', 'N', 9, 2 }, ;
{ 'YHHFYY' , 'D', 8, 0 } } )
Any DBCREATE() which does not follow the above format is not changed,
code such as...
local temp := {}
aadd( temp, { 'xxxxx', 'C', 23, 0 } )
aadd( temp, { 'yyy', 'D', 8, 0 } )
aadd( temp, { 'yy', 'C', 8, 0 } )
aadd( temp, { 'yuu', 'D', 8, 0 } )
aadd( temp, { 'yijiiiyy', 'N', 9, 2 } )
aadd( temp, { 'yhhfyy', 'D', 8, 0 } )
dbcreate( filename, temp )
...is ignored.
Release 1.03
1.02 was broken.
The Aligner had array errors due to bad coding on my part.
1.03 is everything that 1.02 was, except it actually works!
Release 1.02
A minor fix of The Aligner on some object oriented code.
This had problems in prior versions because of the := on the continued
line... (line 3)
o:goBottomBlock := { || i := len( a ) }
o:SkipBlock := { | n, ntemp | ntemp := i, ;
i := iif( x, min( i + n, len( a ) ), max( 1, i + n ) ), ;
i - ntemp }
---
The Aligner is now able to align DBCREATE() arrays.
So, this:
dbcreate( 'filename.dbf', { { 'xxxxx', 'C', 23, 0 }, ;
{ 'yyy', 'D', 8, 0 }, ;
{ 'yy', 'C', 8, 0 }, ;
{ 'yuu', 'D', 8, 0 }, ;
{ 'yijiiiyy', 'N', 9, 2 }, ;
{ 'yhhfyy', 'D', 8, 0 } } )
ends up looking like this:
dbcreate( 'FILENAME.DBF', { { 'XXXXX' , 'C', 23, 0 }, ;
{ 'YYY' , 'D', 8, 0 }, ;
{ 'YY' , 'C', 8, 0 }, ;
{ 'YUU' , 'D', 8, 0 }, ;
{ 'YIJIIIYY', 'N', 9, 2 }, ;
{ 'YHHFYY' , 'D', 8, 0 } } )
Release 1.01
Click! now has a S87 mode. From CLICK.INI:
// options are S87, 5.X
// selecting S87:
// Stops the = to := conversion
// Turns off the Declaration Buster
// Stops the STORE to := converter
// The Aligner uses = != instead of := += -= *= /= ^= !=
RUNMODE=5.X
---
The CLICK.LOG file is now created in the output directory, instead of
needing to specify the entire path.
---
There was some problems with The Aligner which caused loss of code.
(Gasp!) This is fixed now, plus The Aligner works even better, and
comments are realigned after The Aligner aligns := sections. The Aligner
aligns object oriented code much better now.
---
Also, I received a question concerning whether we can turn off the
source output to make it faster to get cross reference files only. The
answer is no, you can't turn off the output, but it wouldn't make much
difference anyway. 95% of the time is spent parsing the input files.
However, there is an opportunity to speed up Click! if you only want the
cross reference files.
Turn off the Declaration Buster (Pass 1) and The Aligner (Pass 3).
Pass 2 and 4 create the function cross references and source references.
Eliminating passes 1 and 3 will not effect the creation of the cross
references, but will eliminate two thirds of the parsing work.
In fact, after you have used Click! on your files with the Declaration
Buster turned on, you can turn it off until the next time you need it. A
good clue is that you never see the progress meter on pass one turn red,
which means it found something. If the first pass is yellow all the
time, the Declaration Buster is wasting time.
Release 1.00
Click! scans all of your libraries available via the LIB= path
statement, however, if you have libraries which are not included in your
LIB= statement, you should create a temporary environment which includes
pointers to ALL libraries.
If you have already created CLICK.DBF, and it doesn't contain ALL of
your library references, Delete CLICK.DBF and CLICK.NSX, correct your
LIB= path to include ALL directories where you have libraries, and run
CLICK so it can rebuild the CLICK.DBF table and index.
When you pass a link script as a file list, Click! will use your current
environment to resolve exactly which library would be used when more than
one is found to match the function.
This means that you can scan all of your libraries into CLICK.DBF one
time, and Click! is 'current environment sensitive' at runtime.
This only works when you use a .LNK file as the file list. If run Click!
with no parameters, or *.PRG, then Click! will list every library that
any function may have come from, in no particular order.
If you pass the name of a .LNK file into Click!, it uses the library
references inside the .LNK file(s) to resolve the function names in
FNC_CROS.TXT when they could have come from more than one library.
References to other .LNK files are also scanned for input, so if you
have one or more references (@<filename>) to other .LNK files in the
main .LNK file, they will be included if found. The LIB= environment
variable will be used for the .LNK search.
---
There is a new file named CLICKFNC.INI which is used to augment the
CLICK.DBF creation process. It belongs in the same directory as
CLICK.EXE. Since functions can come from many places other than
libraries, you need a method of permanently informing Click! as to what
their name is and where they reside.
If you have functions which do not come from libraries, and you want
Click! to understand where they come from and include them in CLICK.DBF,
then add the file references to CLICKFNC.INI file following the example
of:
<function> = <LOCATION>
like:
swpruncmd=BLINKER.EXE
Everything in CLICKFNC.INI is included any time CLICK.DBF is created.
Case is not sensitive and are corrected when the .INI file is read in.
Improperly formatted lines are omitted.
---
If you used the first word of a two word command as a function, then it
was treated wrong, like:
MENU()
was coming out like:
MENU ()
because of the MENU TO command. This is fixed now.
Also fixed are:
SAVE ALL LIKE A????X TO TEMP
SAVE ALL EXCEPT A* TO TEMP
SET COLOR TO G*
COPY TO STKSUPP$
.999 beta
Click! can now accept .LNK files as file lists. Each line starting with
the letters FI will be parsed and if the file(s) referred to on that
line exist in the current directory, they are included in the processing
list. This is handy when you keep the source for more than one
executable in a single directory, and don't want to process them all at
once.
---
In the output directory, Click! now creates two files named SRC_CROS.TXT
and FNC_CROS.TXT.
(from CLICK.INI...)
SOURCE_XREF_FILE=SRC_CROS.TXT
FUNCTION_XREF_FILE=FNC_CROS.TXT
// options are YES, NO
// please note that you must set ADD_CLICK_HEADER=YES
FUNCTION_REF_INTO_SOURCE=YES
// options are YES, NO
// please note that you must set ADD_FUNCTION_HEADERS=YES
FUNCTION_XREF_INTO_SOURCE=YES
SRC_CROS.TXT contains a module to function reference for all modules
included in the processing pass. If you set FUNCTION_REF_INTO_SOURCE to
YES, then a final pass is made which incorporates the function
information into the source file header.
FNC_CROS.TXT contains a function called by function reference for the
functions in all modules included in the processing pass. If you set
FUNCTION_XREF_INTO_SOURCE to YES, then then a final pass is made which
incorporates the function information into the source file function
headers.
This can be used as a complete function cross reference when all .PRG
source files in a system are included in the processing pass.
---
In addition to the above internal function tracking ability, Click! also
scans the LIB= environment variable, gathers a list of all available
libraries, and extracts the function names out of every library
available via the environment settings.
The function names gathered in this process are placed into an indexed
master function table, which is used to identify unresolved functions
including which library they might belong to.
---
Files are now processed in alpha order.
---
Rewrite of PROFILE.PRG to be a buffered system for faster program
startup.
---
If the output directory did not exist when the run was started, the
initialization of the log file left off the starting time. Click! now
checks for the output directory first.
---
In .997, I added the ability to convert STORE commands to assignments.
Continued lines were messed up in the process, so Click! now skips
conversion on lines which continue, and a message is logged to the error
file as to the module and line number. Hand corrected code can then be
converted safely.
ie:
Current File => E:\CLICK\TEST.PRG
No Conversion of STORE due to ; at end of line 1
---
In .998, I made any word followed by a ( into a function, however, it
caused control structures to fail when followed by a parenthesis. So,
these work OK now.
do while ( x := somefunc() )
enddo ( oGet:ExitState == GE_NOEXIT )
This more robust way of handling things is controlled by the CLICK.INI
file [CMD_LIST] section.
(from CLICK.INI...)
// Commands beginning with * never make sense when used as a function, so
// when they are followed by a (, they are NOT considered to be functions.
// THIS ALLOWS YOU TO DEFINE WHICH COMMANDS WILL NOT BE CONSIDERED TO BE
// FUNCTIONS. If you prefer for Click! to treat all commands as if they
// cannot be functions, then place a * before each command.
// Good programming practices never allow key words to be used as
// functions.
ACCEPT
ADDITIVE
*ALL
*APPEND BLANK
*APPEND FROM
etc...
---
Added many more functions and commands to the CLICK.INI file
.998 beta
Click! now has buffered line output for data writing.
---
Fixed the buffered line reader function to deal correctly with source
files that are not delimited with CHR( 13 ) + CHR( 10 ). It will now
function correctly with either of them alone, and automatically detect
which one(s) it needs to use.
Detection order is:
CHR( 13 ) + CHR( 10 )
CHR( 13 )
CHR( 10 )
Output will always use CHR( 13 ) + CHR( 10 ) as the line delimiter,
regardless of this change in the input parsing mechanism.
---
Click! assumes that any word followed by a parenthesis is a function,
and reversed the logic on detecting IF () the command.
---
Which fixed Click! so that it knows the difference between
FUNCTION
and
function() // Legal in Clipper, but bad practice in my opinion.
// Either way, it no longer causes an indent level.
---
Added FUNCTION to the [Command] list in CLICK.INI
.997 beta
STORE statements are converted to := assignments, like:
STORE 'Hello' + " World" to y, z, x
STORE x to y
becomes:
y := z := x := 'Hello' + " World"
y := x
---
Updated CLICKINI.DOC
---
Added BEGIN SEQUENCE to the command list in CLICK.INI, and modified
Click! so it understands it as a two word command.
---
Using the MrDebug profiler, ( great debugger! ) I found a couple of
places where I could speed up Click!
Rewrote the List Reader and changed the binary seek routines for seeking
into the arrays of commands, functions and operaters. Bypassed the line
parser when the line is obviously a comment.
---
Well, I thought I fixed the REPLACE ALL problem, but I didn't.
Once Again.... (sigh)
I originally looked in the .NG, and not STD.CH.
This is now according to STD.CH
So:
replace x with y
replace all x with y
replace x with y all
replace x with y for z
replace x with y while z
replace x with y record n
replace x with y next n
replace x with y rest
becomes:
field->x := y
replace all x with y
replace x with y all
replace x with y for z
replace x with y while z
replace x with y record n
replace x with y next n
replace x with y rest
Any REPLACE commands with ALL, FOR, WHILE, RECORD, REST and NEXT are not
modified. (note 2 previous inadequate corrections in .995 and .996)
.996 beta
Well, I thought I fixed the REPLACE ALL problem, but I didn't. Now, it
is fixed. So:
replace x with y
replace all x with y
replace x with y all
replace x with y for z
replace x with y while z
becomes:
field->x := y
replace all x with y
replace x with y all
replace x with y for z
replace x with y while z
Any REPLACE commands with ALL, FOR or WHILE are not modified.
.995 beta
This is the first wide public beta.
---
Fixed the REPLACE ALL to not be changed, no matter where the ALL is on
the line
.994 beta
On an assignment, when the aligner was fixing the spaces before the :=,
it would not correct the following lines if the := was followed by a ;
It started like:
somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
.993 version looked like:
somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
.994 version looks like:
somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
---
On a similar note:
On a declaration, when the aligner was fixing the spaces before the :=,
it would not correct the following lines if the := was followed by a ;
It started like:
LOCAL somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
.993 version looked like:
LOCAL somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
.994 version looks like:
LOCAL somevar := { 'asdfasdf', ;
'asdfasdf', ;
'asdfasdf' }
---
REPLACE ALL
is ignored when
CHANGE_REPLACE_WITH_TO_ASSIGNMENT=YES
---
replace x with y
now becomes
field->x := y
instead of
x := y
however
replace inv->x with y
becomes
inv->x := y
and not
field->inv->x := y // which works, by the way!
.993 beta
You can now include your own text in the header block. Just put some
text in a file named CLICK.HDR, and it will be placed in the title block
of each file processed.
You can have a CLICK.HDR in with your CLICK.INI and CLICK.EXE, and if
you place a CLICK.HDR in the local directory, it will override the
master file.
You don't need to comment or indent it. Plain text is all you need.
---
Click! had some problems ignoring comment lines. This is improved.
---
If the word SET is the first element of a line, and is followed by a (,
it is now understood to be a function, not a command.
---
If a source file ends with the comment block still turned on, Click! now
ends gracefully.
So, you can have a source module like:
function stuff
xfunc( x, y )
/*
This should have a comment end block, but it doesn't
---
If the output file in the output directory has the same or later
date/time than the source file, you can use:
SKIP_FILES_WITH_NO_CHANGES=YES
to not process them again.
---
The Aligner now removes the extra spaces in assignment blocks, so:
nIndIf := 0
nIndFor := 0
nIndCase := 0
nIndFunc := 0
nIndBegin := 0
nIndWhile := 0
becomes:
nIndIf := 0
nIndFor := 0
nIndCase := 0
nIndFunc := 0
nIndBegin := 0
nIndWhile := 0
---
The Aligner now removes extra spaces in declarations, so:
local CRLF := chr( 13 ) + chr( 10 )
local cContSpace := ''
local cFullPath := if( file( 'CLICK.INI' ), 'CLICK', rootname( ft_origin() ) )
becomes:
local CRLF := chr( 13 ) + chr( 10 )
local cContSpace := ''
local cFullPath := if( file( 'CLICK.INI' ), 'CLICK', rootname( ft_origin() ) )
.992 beta
// options are OFF, ON
VERBOSE=ON
Stops data from scrolling in the two windows when set to OFF
---
// options are YES, NO
RETAIN_ORIGINAL_TIME_DATE_ON_OUTPUT_FILES=YES
When set to YES, the output file(s) will have the same time and date as
the input file.
.991 beta
If you are using
INDENT_FUNCTIONS=YES
then return statements do not de-indent the code, and only the beginning
of the next function will signify the zero indentation.
FUNCTION TEST1( y )
local x := 1
if y == x
return .f.
endif
return .t.
FUNCTION blork( y )
blah( y )
return blap( y )
---
Anything between
TEXT
ENDTEXT
is passed straight through to the output.
( this works identically to *+CLICKOFF and *+CLICKON )
---
if x=1.or.y=3.and..not.z=17
endif
correctly parses to:
if x = 1 .or. y = 3 .and. .not. z = 17
endif
---
The Declaration Buster was not able to ignore comments, which is fixed,
and also did not identify commands correctly. This is fixed, but it
costs quite a bit of time during the processing phase of the Declaration
Buster.
It was an unavoidable loss of processing speed.
---
I thought I had fixed the keyword being used as a variable and still
being dealt with as if it was a structural command. I believe this is
really fixed now, so you can do things like:
do while .t.
while = 7
for = 8
do = 15
if while + for == do
exit
endif
enddo
Try that with any other reindenter!
.99 beta
If you selected:
CASE_OF_COMMANDS=LIKEINFILE
IF and FOR didn't get indented.
This is fixed.
---
Previously, the Declaration Buster was adding comments together when
comments were on consecutive continued lines which were not parts of
declarations.
This is fixed.
---
INIT FUNCTION
EXIT FUNCTION
are now recognized as functions.
---
Previously, the macro character &, was being broken out of words in
lines. Now, the & character is interpreted to be part of a word unless it
is found in pairs, &&, which is interpreted as a comment.
---
Previously, the backslash character \, was being broken out of words in
lines. Now, the \ character is always interpreted to be part of a word.
Currently, the word characters are:
'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._\' and sometimes '&'
---
Declaration Buster now also busts up multiparameter REPLACE statements.
So, if you have the Declaration Buster turned on, this:
REPLACE foo with x, bar with y, baz with z
becomes:
REPLACE foo with x
REPLACE bar with y
REPLACE baz with z
(which sets us up for the next change)
---
Continuing on with that thought, there is a new parameter in CLICK.INI,
CHANGE_REPLACE_WITH_TO_ASSIGNMENT, which when set to YES, results in:
REPLACE foo with x
REPLACE bar with y
REPLACE baz with z
being processed into:
foo := x
bar := y
baz := z
This doesn't work unless the Declaration Buster is turned on.
.98 beta
Instead of INDENT=3, you now have an indent level for each type of
structure
INDENT_IF=3
INDENT_FOR=3
INDENT_CASE=3
INDENT_FUNC=3
INDENT_BEGIN=3
INDENT_WHILE=3
---
The Aligner on @ SAY GET's now has four options for alignment.
options are 0, no alignment
1, each element type in it's own aligned column
2, Columns aligned, but not by type
3, Each element in it's own row.
If you use option 3, there is no reverse process.
Review the output before you commit to method 3.
I suspect that option 2 will fit the best.
@_SAY_GET_ALIGNMENT_METHOD=2
---
You can turn on and off Click! processing with:
*+CLICKOFF
lines between these commands will not be processed.
*+CLICKON
Now, if you find something in your code that Click! handles very badly,
you can turn off Click! processing around that area, and you won't have
to deal with Click's bad behaviour in that area of your code.
.97 beta
There is a new CLICK.INI parameter named:
POSTPROCESS_WITH_THE_ALIGNER=YES
Which, when set to YES, will align @ SAY GET's (valids, etc.)
---
This compiles correctly in Clipper, even though it's nasty form to use a
key word as a variable.
Click! accepts this and does not count a key word which has been used as
a variable as a part of the structural code in a program.
( Even against my better judgement )
if x
end := 9
endif
---
for i=1 to 2
nMezo:=if(nHonap=0,;
if(i=1,_FFNYTART,_FFNYKOV),; // Nyito adatok
if(i=1,nHonap*2+_FF1T-2,nHonap*2+_FF1K-2)) // Havi adatok
next
There are some tab characters after the ; and before the // which were
messing up the end of the line continue flag detection.
Tabs are now converted to spaces everywhere except inside strings.
---
Function Main()
? if( seconds() < 5000, Wibble(), Wobble() )
? iif( seconds() < 5000, Wibble(), Wobble() )
Return( NIL )
Is fixed.
Any IF that does not start the line is a function, and the space after
the IF is removed.
.96 beta
If Multimsgyn( ;
"This is a test" ;
" " ;
"Test Line 3")
endif
No longer blows Click! out of the water.
---
CLICKINI.DOC file documents the CLICK.INI file parameters.
---
INDENT_DO_CASE=YES
is now working.
---
PREPROCESS_WITH_DECLARATION_BUSTER=YES
is now working, and the declaration buster is improved over the one
I have on my www site.
---
A lot more := will be smart aligned. Also, += -= *= /= and ^=
---
You can now feed Click! with a file list like the old compiler response
files.
ie, you can create a text file containing:
(temp.txt)
prog1.prg
prog2.prg
prog3.prg
and pass it into Click! like:
CLICK @TEMP.TXT <enter>
If you pass bad file names, they are ignored with no error message.
---
If you have a file named CLICK.INI in the current directory, it will
override the one stored with CLICK.EXE. This will allow you to have a
generic CLICK.INI in the main directory and copy it to the local
directory so that you can change certain parameters for the local
directory only.
---
Two word commands were not being recognized, such as:
do while
do case
set scoreboard
This is fixed.
---
If you type:
CLICK MYPROG <enter>
Click! will assume it is a .PRG and treat it like:
CLICK MYPROG.PRG <enter>
.95 beta
I changed the characters I use to create headers and function dividers
to *+ instead of *, since many of you use a windows editor which was
messed up by the earlier one.
When the * are encountered in your programs, those lines are removed
unconditionally.
---
#defines that continue onto more than one line are kept intact
---
do ;
while
do ;
case
Both are reassembled onto one line
---
CLICK.INI has new parameters. Documented in CLICKINI.DOC
---
Function Main(); Return( NIL )
Fixed remaining output when remainder is last line of program.
---
// Reworked inline comments. These work now.
Function Main()
Local n
For n := /* A number the romans didn't have */ 0 To /* The Answer */ 42
? n
Next n
Return( NIL )
Function Main()
Local n
For n := 1 To 42
? n
/* Hello, World */ Next
Return( NIL )
---
If you turn on function indenting, and your function does not end with a
return, Click! starts the next function correctly and without an error
message.
---
@2,17 get LASTNAME color GETCLR WHEN activeBox(1);
picture"@!" valid filled(LASTNAME,"Last Name")
got indented stupidly. Added SMART_ALIGN_MAX_ELEMENTS to fix this.
Without limitation, it aligned like:
@ 2, 17 get LASTNAME color GETCLR WHEN activeBox( 1 );
picture"@!" valid filled(LASTNAME,"Last Name")
because it tried to align to the second element after the ( which was
the 21st element of the line. I have defaulted SMART_ALIGN_MAX_ELEMENTS
to 11 but you might like it even lower.
now it aligns like:
@ 2, 17 get LASTNAME color GETCLR WHEN activeBox( 1 ) ;
picture "@!" valid filled( LASTNAME, "Last Name" )
( DEFAULT_INDENT=8 )