Thanks to Doug and Kerry, who both posted interesting examples.
In the meantime, I had a shot at it myself and found that my specification
of the problem was inaccurate (and inadequate).
It would be very good to have a general hex function for COBOL but for the
specific reason I noted (dealing with color attributes), there needs to be
more.
I said that "sign is irrelevant" but I have since found out that I was
wrong.
(Experience is always the best teacher, but her fees are sometimes very
high...)
For the specifc requirement I have (which is about obtaining "color"
attributes from PowerCOBOL controls, by means of the COM/OLE interface), the
specs are as follows:
==================== start of description ===============================
OLE_COLOR
A four byte number defining a color.
COBOL equivalent: S9(9) COMP-5
The hexadecimal value of the four bytes (in the COMP-5 reverse order) is:
X"rrggbbss"
When ss (the most significant byte) is X"00", "rr" is Red, "gg" is Green,
"bb" is Blue.
When ss is X"80", "rr" contains a value indicating the system color value
(listed below),
and "gg" and "bb" should be zero.
Therefore, PowerCOBOL supports:
X"rrggbb00" (rr: Red, gg: Green, bb: Blue)
or
X"rr000080" (rr: as listed below)
00: Scroll bars
01: Desktop
02: Active title bar
03: Inactive title bar
04: Menu bar
05: Window background
06: Window frame
07: Menu text
08: Window Text
09: Active title bar text
0A: Active window border
0B: Inactive window border
0C: Application workspace
0D: Highlight
0E: Highlight text
0F: Button surface
10: Button shadow
11: Disabled text
12: Button text
13: Inactive title bar text
14: Button highlight
15: Button dark shadow
16: Button light shadow
17: Tool Tip text
18: Tool Tip background
You can set colors by using the color constants defined in PowerCOBOL (see
Color Constants for details) or by coding the following in COBOL:
01 COLOR-VALUE PIC S9(9) COMP-5.
01 COLOR REDEFINES COLOR-VALUE PIC X(4).
*> Make the text color blue.
MOVE X"0000FF00" TO COLOR.
MOVE COLOR-VALUE TO "ForeColor" OF StaticText1.
*> Make the character background color red.
MOVE 255 TO "HighlightColor" OF StaticText1.
*> Make the background color the button surface color.
MOVE X"0F000080" TO COLOR.
MOVE COLOR-VALUE TO "BackColor" OF StaticText1.
Notes:
1. The byte order is reversed on Intel 80x86 processors - hence the hex
values in the above examples.
2. You cannot store system color values in PIC S9(9) COMP-5 item because of
decimal truncation.
X"80xxxxxx" is equivalent to a 10 digit decimal number. Therefore, if you
want to store a system
color in a COBOL data item (e.g. in WORKING-STORAGE) you need to define it
as PIC S9(10) COMP-5.
This is not an issue if you move hex values to PowerCOBOL properties such as
the ForeColor property.
============================ end of description
=================================
Just before I get into the implications of the code I used and how it
evolved, here is some useful background for people who might want some...
USEFUL LINKS THAT HELP:
This one describes the process from the basics...
https://www.wisc-online.com/learn/formal-science/mathematics/tmh5406/an-algorithm-for-converting-a-decimal-number
This one gives a load of stuff about colours and is good for examples...(Bet
you didn't know there was Visual RPG... :-))
http://devnet.asna.com/documentation/Help110/AVR/_HTML/avrlrfSettingColors.htm
Now, MY CODE....
This is the first cut....
WORKING-STORAGE:
...
01 color pic s9(10) comp-5.
01 hex-color pic x(9).
01 quotient pic s9(10) comp.
01 rem pic s99 comp.
01 HV pic x(16) value "0123456789ABCDEF".
...
PROCEDURE DIVISION:
...
*----------------------------------------------------------
doColours section.
dsc000.
invoke objItem "GET-ForeColor"
returning color
end-invoke
move color to quotient
move zero to rem
move spaces to hex-color
move 1 to J
perform until quotient = 0
divide 16 into quotient
giving quotient
remainder rem
move HV (rem + 1: 1) to hex-color (J:1)
add 1 to J
end-perform
move hex-color to <a PIC X(9) field in a memory table, for subsequent
processing>
...
Guess what happened?
The refmodded reference threw an exception.
(The logic would indicate that it CAN'T, but it did... don't you love it
when that happens? :-))
Some investigation showed that the reason was because the passed color was
NEGATIVE and the rem was also negative.
(If the color is POSITIVE, the code works as intended)
Obviously, using the remainder as a direct base for the refmod when it is
negative, does not produce an index acceptable to COBOL...
The obvious solution was to make the remainder unsigned, possibly make the
color unsigned too. But if I do that, I probably WON'T get the value I need
as a base for the conversion to Hex...
I could check for negative color and divide by -16... but it all gets a bit
unwieldy.
(I messed around with it for an hour or so trying various ideas, but in the
end I just didn't like it so I'll look for another (better) solution.)
Currently, I'm looking at getting colours translated to hex as a separate
problem from just taking an integer and making its hex value.
I COULD pass the original signed integer returned as the attribute, to the
downstream C# code (which has all kinds of really cool functions to deal
with hex), but I'd like to solve this in COBOL and pass the HEX string to
the C# code...
I think a solution looking at the bytes and applying bitwise operations
might get me what I want. (Fujitsu provide the same COBOL subroutines that
Micro Focus do, so bitwise operations are possible.)
Meantime, if anyone manges to devise a hex routine that handles both signed
and unsigned integers in COMP-5 format correctly, I'd be very interested to
see it.
Cheers,