Home Contact Site Map Privacy Policy Rev Search
Volume 2 Issue 7
 

Up
Volume 1 Issue 1
Volume 1 Issue 2
Volume 1 Issue 3
Volume 1 Issue 4
Volume 1 Issue 5
Volume 1 Issue 6
Volume 1 Issue 7
Volume 1 Issue 8
Volume 1 Issue 9
Volume 1 Issue 10
Volume 2 Issue 1
Volume 2 Issue 2
Volume 2 Issue 3
Volume 2 Issue 4
Volume 2 Issue 5
Volume 2 Issue 6
Volume 2 Issue 7
Volume 3 Issue 1
Volume 3 Issue 2
Volume 3 Issue 3
Volume 4 Issue 1
Volume 4 Issue 2
Volume 4 Issue 3
Volume 4 Issue 4


 

 

 S/ENL - The Sprezzatura Electronic Newsletter

(All the RevSoft News That's Fit To Print (And bits that probably aren't as well...))

Contents

Welcome

Feedback

MYKL'S JOKE SECTION (He's back, and this time it's terrible…)

Technical Briefing # 2 – Compiled OIWin Structures

Relational Indexing – A Beginner’s Guide – Aaron Kaplan

Adding Index Transactions Programmatically – Andrew McAuley

PB Computers – A Reader Writes

OIPI – A tip

What is sub-classing? – Carl Pates

S/QBF – A replacement for QBF

ERIC THE EMU'S AREV TIPS - # 1

Celebrity Interview – Andrew McAuley

ERIC THE EMU'S AREV TIPS - # 2

Peripheral Trivia

2nd August 1999

S/ENL Volume 2 Issue 7

Welcome

WELCOME - to this issue of S/ENL, the Sprezzatura Electronic Newsletter. A special "BUMPER" issue to make up for the lost time!

Gosh is that the time already? Whoops. Well, where’ve we been? Australian Developer’s Conference, Rev U and now JavaOne, all interesting events for the Rev community.

We’ve been terribly busy lately, with more and more AREV to Web conversions – it seems that several clients are choosing to skip the OpenInsight conversion and go straight to the Web where their AREV data is only a browser click away.

Revelation Software have been so impressed with the quality of the Web work we’ve been doing that they’ve asked Carl Pates along to demonstrate some of the products at recent seminars in Milton Keynes. We hope to shortly be able to do live demos of product on our Sprezzatura-Group web site that is still under construction – we’ll post you as soon as it is live.

We’ve not got a review of the Australian Developer conference but we hear it was a lively affair. Rev U however was a success and all attendees were excited by what they saw. Checkout www.revelation.com or www.livewater.com for details.

The Sprezzatura Group have been busy and in this issue we have a couple of new product announcements, the long awaited Tech Bulletin No 2 on compiled OiWin structures and a replacement QBF for OpenInsight.

Congratulations to Joe Toledo of Toledo Inc. In California! Joe organised a golf tournament to raise money for cancer research and education. If you’re located on the West Coast of the US why not register for next year’s event? Details of this year’s event can be found at http://www.lusogolf.org.

We’ve resolved to keep editorial down to the minimum so on this note I’ll close! Thanks for your patience and your continued support – we do appreciate the chance to be part of this community. Thank you.

Andrew P McAuley

Publisher

 

Feedback

An S/List user from the US writes

"I don't know if it is possible to pass S/LIST a variable equal to the record in the SYSREPOSREPORTS table. This would allow us to call S/List programmatically and do some manipulation - particular on the heading command to update it for user company name, selection dates, etc - then print the report. Also, developer users could change the basic report layouts that we ship canned to them using the SLIST_97."

What you have to bear in mind is that S/List was written as an R/LIST replacement. We had an AREV app with hundreds of RLIST reports that we needed to bring to Windows. Unfortunately the client took one look at the report output and, as we quaint Brits say "had a duck egg" ("Had a cow" for our American friends <g>). We needed a way of making them look good. Thus was born S/LIST. The idea was that instead of calling R/LIST passing it a sentence, you would call S/LIST passing it the SAME sentence but add the words FONT ARIAL (or similar) onto the end.

This is what we did and so S/LIST came into being. A year or two later we decided to add a sexy front end and market it as an end user tool. So, in answer to your question, you don’t need to pass S/LIST an SYSREPORTS row, just pass it the equivalent of what is stored on line 50 of the row – an R/LIST statement with S/LIST additional keywords!

After our recent mailing warning you of the forthcoming release of S/ENL and suggesting that you notify us of any changes in Email address, Tim Sneller of Miles 33 replied

But if my email address had changed, I wouldn't have received your reminder to resubscribe!!!! 8-)

Well Tim, it’s a fair cop – we used the mailer to plug our internet enabling of AREV apps as well! We find that quite a few people are using OI to move straight from AREV to the Web without performing an intermediate Windows conversion! This move makes great sense and is frequently much more cost effective than going completely over to OI if the application suits it! In fact we know of one site where they’ve written their own custom CGI program and have users all over the world querying and updating live AREV data! Mind you they did this before OICGI was introduced – but it works well for them!

In fairness though several people did make use of the mailer to update us with their preferred mailing address!

Steve Smith shared an interesting AREV related link with us recently at http://www.regione.piemonte.it/arev a link I’m sure we all appreciate! <g>

Our sincere thanks to Stephen J. Witt-Thompson, Manager of Development at SPECTRUM Human Resource Systems Corporation who wrote to us about the issue of Y2K compliance and Revelation G. He writes as follows

The corrected version of RTP26 deals with a G2b bug in RTP26 (ICONV) where the 2-digit years 00-09 are incorrectly interpreted as the years 0-9 AD rather than as 2000-2009. i.e., the internal date is some number between -718796 (01/01/00) and -715144 (12/31/09) rather than the correct interpretation of 11689 (01/01/00) through 15341 (12/31/09).

The fix doesn't change Revelation's reliance on interpretation of dates between 00-29 or 30-99. That logic remains intact.

RTI's original source was changed by myself and then system compiled by RTI. We and our clients (over 500 systems currently, although we are converting them to our graphical products on a regular basis) have been running with this version since late 93, early 94.

Our webmaster has added the file (same file) to our website. Go to:

http://www.spectrumhr.com/revelation/iconv

and click on the 'download now' link. I've tested the download using both Netscape 4.5 and IE 4.01 and it downloads correctly.

I’m sure we don’t need to tell you how generous of Stephen this is, but all the same a big vote of thanks from all the existing Rev G users out there!

Bob Silverstein writes

I attended the recent road show in Chicago and received one of your fountain pens. Really enjoyed using it but cannot find refills.

Well after extensive research our American R&D team have determined that replacement cartridges can be purchased for a nominal amount from your local Staples – just look for A&W Stratos – part number 51213. And by the way – those of you who were asking about the spring in the barrel – we’re indebted to another subscriber who tells us that it is designed to ensure that longer cartridges do not become stuck in the barrel.

Finally Steve Bush in Nicosia writes

Why do computer people insist on abbreviating "year 2000" to "Y2K"!? It is this kind of thinking that got us into the trouble in the first place!

 

MYKL'S JOKE SECTION (He's back, and this time it's terrible…)

The American businessman was at the pier of a small coastal Mexican Village when a small boat with just one fisherman docked. Inside the small Boat were several large yellowfin tuna. The American complimented the Mexican on the quality of his fish and asked how long it took to catch them.

The Mexican replied only a little while.

The American then asked why didn't he stay out longer and catch more fish?

The Mexican said he had enough to support his family's immediate needs.

The American then asked, but what do you do with the rest of your time?

The Mexican fisherman said, "I sleep late, fish a little, play with my children, take siesta with my wife, Maria, stroll into the village each evening where I sip wine and play guitar with my amigos, I have a full and busy life, senor."

The American scoffed, "I am a Harvard MBA and could help you. You Should spend more time fishing and with the proceeds buy a bigger boat, with the proceeds from the bigger boat you could buy several boats, eventually you would have a fleet of fishing boats. Instead of selling your catch to a middleman you would sell directly to the processor, eventually opening your own cannery. You would control the product, processing and distribution.

You would need to leave this small coastal fishing village and move to Mexico City, then LA and eventually NYC where you will run your expanding enterprise."

The Mexican fisherman asked, "But senor, how long will this all take?"

To which the American replied, "15-20 years."

But what then, senor?

The American laughed and said that's the best part. When the time is right you would announce an IPO and sell your company stock to the public and become very rich, you would make millions.

Millions, senor? Then what?

The American said, "Then you would retire. Move to a small coastal Fishing village where you would sleep late, fish a little, play with your kids, take siesta with your wife, stroll to the village in the evenings where you could sip wine and play your guitar with your amigos."

 

Technical Briefing # 2 – Compiled OIWin Structures

As threatened many moons ago, Sprezzatura are at last in a position to offer the second in our (very) occasional series of additional technical documentation for OpenInsight developers. The second in this series is "REVMEDIA Technical Briefings # 2 - OI Compiled Window Structures.". This 125+ page document details all aspects of OIWINEXE structures permitting the developer to add new compiled windows programmatically.

It details Compiled Window Control Structure, Control Structure and Menu Structure as well as explaining how to use REPOSITORY to add new windows. It also includes a comprehensive guide to Windows SDK Styles and Presentation Server PS Styles.

Below we attach the first chapter for your perusal! The price is only 50GBP or 80USD. Order by fax or Email in the usual way! The contents list is reprinted below as a taster!

CHAPTER 1 INTRODUCTION 7

CHAPTER 2 OPENINSIGHT WINDOW STRUCTURE - AN OVERVIEW 9

LOCATION OF WINDOWS 10

CHAPTER 3 CONTROL LISTS 14

WINDOW FRAME INFORMATION 15

EDITBOX INFORMATION 19

EDITFIELD INFORMATION 23

EDITTABLE INFORMATION 27

CHECKBOX INFORMATION 31

COMBOBOX INFORMATION 34

LISTBOX INFORMATION 38

PUSHBUTTON INFORMATION 42

RADIOBUTTON INFORMATION 46

RADIOGROUP INFORMATION 50

HSCROLLBAR INFORMATION 54

VSCROLLBAR INFORMATION 57

ICON INFORMATION 60

BITMAP INFORMATION 63

GROUPBOX INFORMATION 66

STATIC INFORMATION 70

PUSHBMP INFORMATION 73

RADIOBMP INFORMATION 77

CHECKBMP INFORMATION 81

RTFBOX INFORMATION 85

MDI FRAME INFORMATION 88

MENU INFORMATION 92

CHAPTER 4 JOIN MAPS 95

CHAPTER 5 ROW MAPS 97

CHAPTER 6 MASTER ROW MAPS 98

CHAPTER 7 CONTROL MAPS 99

CHAPTER 8 KEY MAPS 100

CHAPTER 9 CONTROL SEMANTICS 101

CHAPTER 10 SYSTEM INFORMATION 106

APPENDIX A - VALID CONTROL TYPES 107

APPENDIX B - OPENINSIGHT EVENT TYPES 109

APPENDIX C - JOIN TABLE DELETE INFORMATION 110

APPENDIX D - WINDOWS™ SDK STYLES 112

APPENDIX E - PS STYLES 114

APPENDIX F - FONT STRUCTURE 117

APPENDIX G - EDIT CONTROL STYLE SETTINGS 119

APPENDIX H - BUTTON CONTROL STYLE SETTINGS 123

APPENDIX I - COMBOBOX CONTROL STYLE SETTINGS 125

APPENDIX J - LISTBOX CONTROL STYLE SETTINGS 127

APPENDIX K - NOTES COLUMN LINK STRUCTURE 131

APPENDIX L - EDITTABLE CONTROL STYLE SETTINGS 133

APPENDIX M - SCROLLBAR CONTROL STYLE SETTINGS 135

APPENDIX N - MENU STYLES 137

APPENDIX O - VIRTUAL KEY CODES 138

APPENDIX P - COLOR DEFINITIONS 142

 

 

Relational Indexing – A Beginner’s Guide – Aaron Kaplan

A large Revelation Software house recently asked me to document how Relational Indexes work in OpenInsight. At first the request seemed strange, but then people can go for years and never use aspects of the product. So for our more neophyte users we present an introduction to relational indexing.

Relational indexing is a method of storing row keys of detail tables in a column of the master table row. Since OpenInsight’s native filing format, Linear Hash, is a non-relational database structure, Relational indexing is used to emulate standard Codd/Date relational structures.

One example (the example used in the accompanying screens) is the relations between contacts and companies. In the application outlined below, the system required a separate file for company information and contact information. One reason for this is that the company headquarters might be in one location, but individual contacts for that company scattered about in many offices around the country.

To help promote the linkage, we have created files in the following structure:

TABLE COMPANIES

FIELD NAME

TYPE

FMC

PART

SM..

GENERIC TYPE...

JST

COMPANY_ID

F

0

0

S

VARCHAR(65531)

L

COMPANY_NAME

F

1

 

S

VARCHAR

L

ADDRESS

F

2

 

M

VARCHAR

T

CITY

F

3

 

S

VARCHAR

L

STATE

F

4

 

S

VARCHAR

L

ZIP

F

5

 

S

VARCHAR

L

CONTACT_CODES

F

6

 

M

VARCHAR

L

PHONE_NBRS

F

7

 

M

VARCHAR

R

PHONE_TYPES

F

8

 

M

VARCHAR

L

CONTACT_NAME

S

 

 

M

VARCHAR(65531)

L

TABLE CONTACTS

FIELD NAME

TYPE

FMC

PART

SM..

GENERIC TYPE...

JST

COMPANY_ID

F

0

1

S

VARCHAR

L

CONTACT_NBR

F

0

2

S

VARCHAR

L

FIRST_NAME

F

1

 

S

VARCHAR

L

MI

F

2

 

S

VARCHAR

L

LAST_NAME

F

3

 

S

VARCHAR

L

ADDRESS

F

4

 

M

VARCHAR

L

CITY

F

5

 

S

VARCHAR

L

STATE

F

6

 

S

VARCHAR

L

ZIP

F

7

 

S

VARCHAR

L

PHONE_NBRS

F

8

 

M

VARCHAR

R

PHONE_TYPES

F

9

 

M

VARCHAR

L

COMPANY_NAME

S

 

 

S

VARCHAR(65531)

L

FULL_NAME

S

 

 

S

VARCHAR(65531)

L

As you can see, the COMPANIES file contains a contact code field, while the CONTACTS file has a multi-part key consisting of company code and a contact number. This creates a series of pointers. We now have a link from the contact row telling us which company this contact belongs to. We also have a link from the company row so we can easily find all the contacts.

The question them becomes, how can we set this all up without requiring any programming to update the links?

The links from the COMPANY table into the CONTACT table is simple. The company ID is part of the key. It must be there. The company ID must also be unique, so a contact can never be part of more than one company.

The link from the CONTACT table into the COMPANY table is not so easy. You can easily have more than one contact for a company. There’s also not a unique identifying mark in the COMPANY table to save for lookup. We do have the CONTACT_CODE field, but that can contain any information.

We could write a program such that each time a contact is created or deleted, we go into the appropriate company record and modify the CONTACT_CODE field. Essentially what has to happen is each time we create or destroy a key in the CONTACT table, we need to update a field in the COMPANY table. Depending on how your particular application handles writes and deletes, this could happen in hundreds of places.

Normally in situations like this, we would recommend writing a custom MFS. However, in this case, we find that OpenInsight has provided us with a handy tool to do just we require. This is the Relational Index.

A Relational index takes the key of one table and writes it into a datafield of a second table. In our case, it will take the key of the CONTACT table and write it into the CONTACT_CODE field of the COMPANY table. OpenInsight can do this because somewhere in the CONTACT row, exists the key to the COMPANY table.

The dictionary field of the CONTACT table is called the SOURCE field. This would be the COMPANY_ID field. The real data dictionary field in the COMPANY table is called the DESTINATION field. This would be CONTACT_CODES.

Note: In this case the company code happens to be a part of key field. This is not a requirement. Any dictionary field can be used as the source field; key parts, real fields, even symbolics (though I wouldn’t recommend them with relational indexing).

The Relational index window allow you to specify a source table and column and a destination table and column. Once this is created, OpenInsight will automatically update the destination column with keys from the source table.

This window is used to create a relational index. All you need to do is fill in the prompts, decided how you wan the information stored in the destination row, and click Add.

Here is what this screen would look like filled out

The Sort Mode options are used to determine how the keys will be written into the destination file.

Sort Mode

Description and Basic+ Code executed for action

Append End

Inserts a new update at the end of the existing list.

DestField< -1 > = SourceKey

Insert Beginning

Inserts a new update at the start of an existing list

DestField = Insert( DestField, 1, 0, 0, SourceKey)

Ascend Right Justify

Keeps the destination field sorted in ascending right justified format.

Locate SourceKey in DestField by ‘AR’ using @VM setting Pos Else

DestField = Insert( DestField, Pos, 0, 0, SourceKey)

End

Ascend Left Justify

Keeps the destination field sorted in ascending left justified format.

Locate SourceKey in DestField by ‘AL’ using @VM setting Pos Else

DestField = Insert( DestField, Pos, 0, 0, SourceKey)

End

Descend Right Justify

Keeps the destination field sorted in descending right justified format.

Locate SourceKey in DestField by ‘DR’ using @VM setting Pos Else

DestField = Insert( DestField, Pos, 0, 0, SourceKey)

End

Descend Left Justify

Keeps the destination field sorted in descending left justified format.

Locate SourceKey in DestField by ‘DL’ using @VM setting Pos Else

DestField = Insert( DestField, Pos, 0, 0, SourceKey)

End

Other examples of relational indexes would be

Storing all invoice keys for a sales order in the sales order

A municipality will track all real property through unique lot numbers. They could track tax payer’s address by lot numbers instead of entering in the full street address. They could then use relational indexing to store the tax payer in the lot number record.

Store all support incident numbers for a customer in the customers record, this way when the customer calls, you have an instant access of what types of questions the customer has asked before.

Suppose you had a film database, handling all your home movies. You have one table for MOVIES, another for DIRECTORS another for WORDSMITH and another for THESPIANS. In each MOVIE record, you could enter in the directors, writers and performers. Relational indexing could kick in and update the credit listing of each table

Any parent- child relationship

After relational indexes have been added to a field, the system needs to ensure it’s continued integrity. To do that, the system protects the data field from any modifications. You cannot make changes to a field that is the destination of a relational index. In the example above, if you tried to modify the value of a CONTACT_CODES column, you will find that the system will restore all changes you made.

 

Adding Index Transactions Programmatically – Andrew McAuley

At a client’s site recently we had an interesting index requirement. Essentially the system is currently being converted to OI and thence to the Web – it tracks hundreds of thousands of documents and their lenders for a governmental department. As a document can be out on loan for months people can put their name down to reserve it on return. The controlling department needed a way to be notified when a loan request could be fulfilled because a document had been returned.

For various technical reasons what this actually meant was an index was required on a symbolic which would evaluate to true if the document was available for loan and false otherwise. To calculate this value, the symbolic had to look at the previous loan and see if it had been returned. The symbolic worked well BUT when the status of the previous loan changed an index transaction was not generated for the next request and so the index never became updated!

The way round this seemed obvious – we would just generate the appropriate index transaction ourselves and update the bang file. If we had to do this we might as well make it generic and if we had to make it generic we might as well publish it in SENL!

So without further ado… AddIndexTransaction

Function AddIndexTransaction(Table, Column, OldRow, NewRow, RowId)

TransactionRow = ""

SaveRec = @Record

SaveDict = @Dict

SaveId = @Id

Open "DICT." : Table To @Dict Then

@Id = RowId

@Record = OldRow

If Num(Column) Then

OldValue = @Record<Column>

End Else

OldValue = Calculate(Column)

End

@Record = NewRow

If Num(Column) Then

NewValue = @Record<Column>

End Else

NewValue = Calculate(Column)

End

TransactionRow := Column : @Fm : RowId : @fm : OldValue

TransactionRow := @Fm : @Fm

Open "!" : Table To vTable Then

Lock vTable, 0 Then

Read Update From vTable, 0 Else Update = @Fm

Update := TransactionRow

Write Update On vTable, 0 Then

Status = 1

End Else

Status = 0

End

Unlock vTable, 0 Else Call FsMsg()

End Else

Status = 0

End

End Else

Status = 0

End

End Else

Status = 0

End

@Id = SaveId

@Dict = SaveDict

@Record = SaveRecord

Return Status

And before you point it out, yes we know there’s no FsMsg in OI – unless you’ve written your own that is. In case you haven’t yet…. Thanks Carl!

function FsMsg(Charstr Dummy)

/*

Author Mr C

Date 22/05/95

Purpose OI version of Arev's FsMsg() Subroutine.

*/

Declare Subroutine Msg

Equ Cr$ To Char(13)

MsgRec = ""

if assigned( dummy) else

dummy = ''

end

If @File.Error Then

FileError = @File.Error

Code = "FS" : FileError<1>

OsRead ErrorFile From "REVERROR.DAT" Then

Pos = Index(ErrorFile,Code,1)

If Pos Then

DosError = ErrorFile[Pos,Cr$]

ErrorText = DosError[11,200]

MsgVars = FileError<2>

if len( dummy) then

msgVars := @FM : dummy

end

If MsgVars Then

RemPos = 0

Mark = 1

Counter = 1

Loop

While Mark

Remove NextVal From msgVars At RemPos Setting Mark

SwapStr = '"%' : Counter : '%"'

if len( nextVal ) else

nextVal = ' <<NULL or Unassigned>> '

end

Swap SwapStr With NextVal In ErrorText

Counter += 1

Repeat

End

MsgRec<1> = ErrorText

MsgRec<2> = "BO"

MsgRec<3> = "S"

MsgRec<4> = "!"

MsgRec<9> = "192":@Vm:"192":@Vm:"192"

MsgRec<12> = Code

Msg("",MsgRec)

End Else

Msg("","Undefined FS Error!!")

End

End Else

Msg("","Can't Open REVERROR.DAT")

End

End Else

Msg("","Nothing in @File.Error!!")

End

Return ''

 

PB Computers – A Reader Writes

Following your comments about PB Computers in your newsletter (volume 2 issue 6, Feb 20th '99) I thought as an ex-employee of the company I would enlighten your readers about the situation with the company in the time I worked there and perhaps comment on the state of matters. It would be a pity if no lessons were learnt from this fiasco.

It is not my usual practice to comment publicly about my ex-employers but I will make an exception in this case because the obvious implications merit such comments.

I was employed by PB Computers for nearly two years after a previous career spanning nearly ten years in various multi-value development environments. At the end of my time with the company I had seen not just software piracy but also cynical exploitation of the workforce and clients by the company management.

The employees of the company were generally honest and hardworking. You would find several of us each day either working late into the night or clocking up huge mileages in client site visits. Indeed, many of us still keep in contact with each other to this day because of the camaraderie we felt and the pride we had in our work.

The issue of questionable software licensing was raised by myself and other programming staff on many occasions both directly to the MD and to other management but we were assured time and again that there was '... no problem, Revelation are quite aware of the licensing situation' (sic.). This was a downright lie. The company was releasing pirated copies of software that was worth tens of thousands of pounds and not paying any revenue to the licensers.

So as employees what could we do about it? Nothing. We had been assured that the licences were legal. We had our suspicions but no positive information to prove otherwise and if we thought our MD was lying to us then there was little point in continued employment with the company.

Secondly, our jobs were at stake. It was not uncommon in the company for staff to be informed of their redundancy by letter in their absence. On one particular occasion we suffered management moving from one department to another pulling one member of staff from each and making them redundant on the spot. The unfortunate individuals were then forced to pack their belongings and were marched off the premises by the management in front of their fellow workers.

Money problems became too much for the company and eventually it fell into the hands of the liquidator. Clients were left owing thousands of pounds for software licences they thought they already owned and with no support. Employees were left exhausted, disillusioned and in debt. Revelation faced a huge revenue loss as did the Inland Revenue and H.M. Customs and Excise. Although some money was undoubtedly made from the sale of the company assets the debts of the company were not cleared entirely by any measure. (well we’re still owed everything they went down owing us – Ed)

So what is the situation now? Most of the employees have moved on to other companies. Revelation managed to claw back some of the money they were owed. To their credit they negotiated very fair deals with the clients because it's not their business to put the squeeze on victims of fraud.

And PB Computers? The MD acquired the assets of the company and most of the unsupported client base. It turns out that a new company, CQ Technology, had been started before PB Computers had gone to the wall. The primary asset of the new company was a software package that was developed using PB staff, money and expertise.

The package had taken nearly two years to develop while PB was still trading and funding was even raised through advances from PB Computers clients on the promise of cheaper licensing when the new product was completed. In effect the major asset of PB Computers was transferred stealthily to a separate business entity without the knowledge of it's staff. Even the programmers working on the project still received PB Computers wage-slips.

Clients were urged to pay large sums of money to transfer to the new product as the company was dropping Revelation support after the end of March 1999. Clients who wished to transfer to other systems were quoted huge amounts in conversion fees and were tied by product knowledge to the company to undertake them.

Nearly two years later to all intents and purposes CQ Technology is still going. I don't know what sort of car Mr. Paul Bentley, the MD and founder of PB Computers, is driving but I bet it's not a mini.

So what can we learn from this case study? Always check the legal status of a licensed software product you purchase from a supplier. Ensure you receive written proof or a certificate and check the licence number with the software originators or other users. It may cost you the price of a phone call but it could save you thousands of pounds in the future.

Read your licence agreement very carefully and consider all reasonable implications and get references for the company where possible. Check with their suppliers to ensure your contacts are value added resellers. If there's a user group attend a meeting or write to other members. Check your licence number against theirs for extra security as legal copies will always be licensed separately between individual clients and suppliers.

Never, under any circumstances, pay in advance for promised software modifications without establishing targets. Ensure these targets are met before parting with any money and then only pay enough to cover the work undertaken. If a software house cannot even fund it's own development project then it is highly unlikely to be stable enough to support your (modified) product for the next five years.

Above all, remember that software piracy is still theft and should not be condoned under any circumstances.

CQ Technology can be contacted at cqtechnology.com

 

OIPI – A tip

Those of you who’ve worked personally with us will know that we are big fans of Tony Splaver’s OpenInsight Printer Interface (OIPI). We wouldn’t consider undertaking an OpenInsight development project without it. In fact we were so impressed with it that we built our flagship S/List product using it. If you haven’t licensed OIPI (and S/List <g>) already then do so!

Anyhow, it does, naturally, have it’s failings but they are very few and far between. . Just recently we ran into one such failing, the fact that the TEXTBOX Set-Printer call does not always work. What this essentially does is print a string of text in a box of a nominated size, truncating if needed. This is documented as not always working, and the printer I was using proved to be one such exception!

Fortunately in the best traditions of RevSoft products, Splaver Software made it possible to roll our own routines. So we present below our own answer to this problem.

Firstly we needed a routine to format text to a specific width. The following is a routine we wrote to return a field-mark delimited array of text of a specific width – the width is specified in the units you are currently using.

Function FormatText(Text, Width)

Declare Function Set_Printer, Get_Printer

String = ''

Ptr = 1

Ctr = 1

NewString = ''

Loop

Ctr += 1

PreviousString = String

String := Text[Ptr, " "] : ' '

PreviousPtr = Ptr

Ptr = Col2() + 1

Call Set_Printer("CALCTEXT", String)

CurrentWidth = Get_Printer("CALCTEXT")<1>

If CurrentWidth > Width Then

NewString<-1> = PreviousString

Ptr = PreviousPtr

String = ''

End

While Len(Text[Ptr, 9999])

Until Ctr = 100

Repeat

If Len(String) Then NewString<-1> = String

Return NewString

(The Ctr check is to avoid going into a continuous loop and is probably superfluous now!).

Now that we have a mechanism whereby we can text a text string and split it horizontally as it where, we can now combine this with a routine to split it vertically, thus giving us our capability to print text in a box!

Function TextBox(Text, x1, y1, Width, Depth)

Declare Function FormatText, Set_Printer, Get_Printer

NewText = FormatText(Text, Width)

TotalDepth = 0 ; Ptr = 1 ; Newy = y1

Loop

NextLine = NewText[Ptr, @Fm]

While NextLine

Ptr = Col2() + 1

Error = Set_Printer("CALCTEXT", NextLine)

Dimensions = Get_Printer("CALCTEXT")

TotalDepth += Dimensions<2>

While TotalDepth < Depth

Error = Set_Printer("TEXTXY", NextLine, x1 : @Fm : Newy)

Newy += Dimensions<2>

Repeat

Return Error

 

What is sub-classing? – Carl Pates

On Andrew and Aaron’s recent forays to the States during the Revelation Roadshow, they demonstrated several sample applications to show that using a 16 bit tool doesn’t mean developing applications that look 16 bit! One of the more technically accomplished showings was the SysKnowledge Window, which amongst other things showed tool-tips on list-boxes, transparent Statics, thunking calls to 32 bit apps! However the pièce de resistance was the slider bar which enabled the user to resize edit boxes by dragging on a slider tool. Andrew always just explained this away with the throwaway comment that it was created by "sub-classing an OI control".

Needless to say after the road-show was over, Sprezz support started getting emails asking "What is sub-classing and how do I do it?". So here to sate a wider need is a brief explanation!

Whenever a control/window is created it also supplies the Windows OS with the address of a function which Windows should call ( aka 'send messages to' ) whenever an event occurs. This function address is know as a 'Window Procedure' or 'WndProc'.

When you sub-class a window/control what you are doing is to replace the WndProc with a function of your own ( ie tell Windows to use a new function address instead of the original one ) and Windows then sends then messages to your function. Therefore you get them first and can act on them, passing on the ones you don't want to deal with to the original WndProc.

As all this is done by function addresses and playing with memory locations you need to use a tool that can deal with these, ie C++, Delphi etc, as all the functions in OI are compiled Opcodes and not x86 executable at all.

Of course thunking to 32 bit apps gets a bit hairier – but that’s sub-classing in layman’s terms!

 

S/QBF – A replacement for QBF

At Sprezzatura we have a number of clients who have moved from AREV to OI but miss some of the features they’d come to rely on in AREV – frequently simple things like Alt-C to copy forward a row – and of course F5 for TCL! One of the most sorely missed features however has to be Query By Form. When this was moved to OpenInsight the syntax was changed and several key features were omitted. Naturally our users complained, and naturally we responded!

We now have available a complete replacement for OI’s QBF called (surprisingly) S/QBF. This has